Env swap #21
							
								
								
									
										1
									
								
								src/JobsJobsJobs/Api/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/JobsJobsJobs/Api/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
wwwroot
 | 
			
		||||
@ -20,6 +20,7 @@
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="Giraffe" Version="5.0.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.FSharpLu.Json" Version="0.11.7" />
 | 
			
		||||
    <PackageReference Include="NodaTime.Serialization.JsonNet" Version="3.0.0" />
 | 
			
		||||
    <PackageReference Include="Polly" Version="7.2.2" />
 | 
			
		||||
    <PackageReference Include="RethinkDb.Driver" Version="2.3.150" />
 | 
			
		||||
    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.11.1" />
 | 
			
		||||
 | 
			
		||||
@ -12,9 +12,12 @@ open Giraffe.EndpointRouting
 | 
			
		||||
/// Configure the ASP.NET Core pipeline to use Giraffe
 | 
			
		||||
let configureApp (app : IApplicationBuilder) =
 | 
			
		||||
  app
 | 
			
		||||
    .UseCors(fun p -> p.AllowAnyOrigin() |> ignore)
 | 
			
		||||
    .UseCors(fun p -> p.AllowAnyOrigin().AllowAnyHeader() |> ignore)
 | 
			
		||||
    .UseStaticFiles()
 | 
			
		||||
    .UseRouting()
 | 
			
		||||
    .UseEndpoints(fun e -> e.MapGiraffeEndpoints Handlers.allEndpoints)
 | 
			
		||||
    .UseEndpoints(fun e ->
 | 
			
		||||
        e.MapGiraffeEndpoints Handlers.allEndpoints
 | 
			
		||||
        e.MapFallbackToFile "index.html" |> ignore)
 | 
			
		||||
  |> ignore
 | 
			
		||||
 | 
			
		||||
open NodaTime
 | 
			
		||||
 | 
			
		||||
@ -106,11 +106,14 @@ module Startup =
 | 
			
		||||
  
 | 
			
		||||
  open Microsoft.Extensions.Configuration
 | 
			
		||||
  open Microsoft.Extensions.Logging
 | 
			
		||||
  open NodaTime
 | 
			
		||||
  open NodaTime.Serialization.JsonNet
 | 
			
		||||
  
 | 
			
		||||
  /// Create a RethinkDB connection
 | 
			
		||||
  let createConnection (cfg : IConfigurationSection) (log : ILogger) =
 | 
			
		||||
    
 | 
			
		||||
    // Add all required JSON converters
 | 
			
		||||
    Converter.Serializer.ConfigureForNodaTime DateTimeZoneProviders.Tzdb |> ignore
 | 
			
		||||
    Converters.all ()
 | 
			
		||||
    |> List.iter Converter.Serializer.Converters.Add
 | 
			
		||||
    // Read the configuration and create a connection
 | 
			
		||||
@ -382,7 +385,7 @@ module Continent =
 | 
			
		||||
 | 
			
		||||
/// Job listing data access functions
 | 
			
		||||
[<RequireQualifiedAccess>]
 | 
			
		||||
module Listing =
 | 
			
		||||
module Listing =  
 | 
			
		||||
 | 
			
		||||
  /// Find all job listings posted by the given citizen
 | 
			
		||||
  let findByCitizen (citizenId : CitizenId) conn =
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ open JobsJobsJobs.Domain
 | 
			
		||||
open JobsJobsJobs.Domain.SharedTypes
 | 
			
		||||
open JobsJobsJobs.Domain.Types
 | 
			
		||||
open Microsoft.AspNetCore.Http
 | 
			
		||||
open Microsoft.Extensions.Logging
 | 
			
		||||
 | 
			
		||||
/// Handler to return the files required for the Vue client app
 | 
			
		||||
module Vue =
 | 
			
		||||
@ -19,15 +20,20 @@ module Vue =
 | 
			
		||||
module Error =
 | 
			
		||||
  
 | 
			
		||||
  open System.Threading.Tasks
 | 
			
		||||
  open Microsoft.Extensions.Logging
 | 
			
		||||
 | 
			
		||||
  /// Handler that will return a status code 404 and the text "Not Found"
 | 
			
		||||
  let notFound : HttpHandler =
 | 
			
		||||
    fun next ctx -> task {
 | 
			
		||||
      let fac = ctx.GetService<ILoggerFactory>()
 | 
			
		||||
      let log = fac.CreateLogger("Handler")
 | 
			
		||||
      match [ "GET"; "HEAD" ] |> List.contains ctx.Request.Method with
 | 
			
		||||
      | true ->
 | 
			
		||||
          log.LogInformation "Returning Vue app"
 | 
			
		||||
          // TODO: check for valid URL prefixes
 | 
			
		||||
          return! Vue.app next ctx
 | 
			
		||||
      | false ->
 | 
			
		||||
          log.LogInformation "Returning 404"
 | 
			
		||||
          return! RequestErrors.NOT_FOUND $"The URL {string ctx.Request.Path} was not recognized as a valid URL" next
 | 
			
		||||
                    ctx
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										392
									
								
								src/JobsJobsJobs/App/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										392
									
								
								src/JobsJobsJobs/App/package-lock.json
									
									
									
										generated
									
									
									
								
							@ -2015,6 +2015,122 @@
 | 
			
		||||
        "tslint": "^5.20.1",
 | 
			
		||||
        "webpack": "^4.0.0",
 | 
			
		||||
        "yorkie": "^2.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ansi-styles": {
 | 
			
		||||
          "version": "4.3.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
 | 
			
		||||
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-convert": "^2.0.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "chalk": {
 | 
			
		||||
          "version": "4.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
 | 
			
		||||
          "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ansi-styles": "^4.1.0",
 | 
			
		||||
            "supports-color": "^7.1.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "color-convert": {
 | 
			
		||||
          "version": "2.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
 | 
			
		||||
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-name": "~1.1.4"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "color-name": {
 | 
			
		||||
          "version": "1.1.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
 | 
			
		||||
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "fork-ts-checker-webpack-plugin-v5": {
 | 
			
		||||
          "version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.1.tgz",
 | 
			
		||||
          "integrity": "sha512-SVi+ZAQOGbtAsUWrZvGzz38ga2YqjWvca1pXQFUArIVXqli0lLoDQ8uS0wg0kSpcwpZmaW5jVCZXQebkyUQSsw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "@babel/code-frame": "^7.8.3",
 | 
			
		||||
            "@types/json-schema": "^7.0.5",
 | 
			
		||||
            "chalk": "^4.1.0",
 | 
			
		||||
            "cosmiconfig": "^6.0.0",
 | 
			
		||||
            "deepmerge": "^4.2.2",
 | 
			
		||||
            "fs-extra": "^9.0.0",
 | 
			
		||||
            "memfs": "^3.1.2",
 | 
			
		||||
            "minimatch": "^3.0.4",
 | 
			
		||||
            "schema-utils": "2.7.0",
 | 
			
		||||
            "semver": "^7.3.2",
 | 
			
		||||
            "tapable": "^1.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "has-flag": {
 | 
			
		||||
          "version": "4.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "lru-cache": {
 | 
			
		||||
          "version": "6.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "yallist": "^4.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "schema-utils": {
 | 
			
		||||
          "version": "2.7.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
 | 
			
		||||
          "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "@types/json-schema": "^7.0.4",
 | 
			
		||||
            "ajv": "^6.12.2",
 | 
			
		||||
            "ajv-keywords": "^3.4.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "semver": {
 | 
			
		||||
          "version": "7.3.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
 | 
			
		||||
          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "lru-cache": "^6.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "supports-color": {
 | 
			
		||||
          "version": "7.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
 | 
			
		||||
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "has-flag": "^4.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "yallist": {
 | 
			
		||||
          "version": "4.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "@vue/cli-plugin-vuex": {
 | 
			
		||||
@ -2093,6 +2209,44 @@
 | 
			
		||||
          "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "ansi-styles": {
 | 
			
		||||
          "version": "4.3.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
 | 
			
		||||
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-convert": "^2.0.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "chalk": {
 | 
			
		||||
          "version": "4.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
 | 
			
		||||
          "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ansi-styles": "^4.1.0",
 | 
			
		||||
            "supports-color": "^7.1.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "color-convert": {
 | 
			
		||||
          "version": "2.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
 | 
			
		||||
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-name": "~1.1.4"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "color-name": {
 | 
			
		||||
          "version": "1.1.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
 | 
			
		||||
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "fs-extra": {
 | 
			
		||||
          "version": "7.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
 | 
			
		||||
@ -2104,6 +2258,13 @@
 | 
			
		||||
            "universalify": "^0.1.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "has-flag": {
 | 
			
		||||
          "version": "4.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "jsonfile": {
 | 
			
		||||
          "version": "4.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
 | 
			
		||||
@ -2113,6 +2274,18 @@
 | 
			
		||||
            "graceful-fs": "^4.1.6"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "loader-utils": {
 | 
			
		||||
          "version": "2.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "big.js": "^5.2.2",
 | 
			
		||||
            "emojis-list": "^3.0.0",
 | 
			
		||||
            "json5": "^2.1.2"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "ssri": {
 | 
			
		||||
          "version": "8.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
 | 
			
		||||
@ -2122,11 +2295,33 @@
 | 
			
		||||
            "minipass": "^3.1.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "supports-color": {
 | 
			
		||||
          "version": "7.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
 | 
			
		||||
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "has-flag": "^4.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "universalify": {
 | 
			
		||||
          "version": "0.1.2",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
 | 
			
		||||
          "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
 | 
			
		||||
          "dev": true
 | 
			
		||||
        },
 | 
			
		||||
        "vue-loader-v16": {
 | 
			
		||||
          "version": "npm:vue-loader@16.3.3",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.3.3.tgz",
 | 
			
		||||
          "integrity": "sha512-/1GzCuQ6MRORbC+leKTKoTGtpQt60bYe0gDGEextSteA2OM+v201FPha5jzmjQzVhRcwieZeUvezAtG5a/e5cw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "chalk": "^4.1.0",
 | 
			
		||||
            "hash-sum": "^2.0.0",
 | 
			
		||||
            "loader-utils": "^2.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
@ -6490,122 +6685,6 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "fork-ts-checker-webpack-plugin-v5": {
 | 
			
		||||
      "version": "npm:fork-ts-checker-webpack-plugin@5.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-SVi+ZAQOGbtAsUWrZvGzz38ga2YqjWvca1pXQFUArIVXqli0lLoDQ8uS0wg0kSpcwpZmaW5jVCZXQebkyUQSsw==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "optional": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@babel/code-frame": "^7.8.3",
 | 
			
		||||
        "@types/json-schema": "^7.0.5",
 | 
			
		||||
        "chalk": "^4.1.0",
 | 
			
		||||
        "cosmiconfig": "^6.0.0",
 | 
			
		||||
        "deepmerge": "^4.2.2",
 | 
			
		||||
        "fs-extra": "^9.0.0",
 | 
			
		||||
        "memfs": "^3.1.2",
 | 
			
		||||
        "minimatch": "^3.0.4",
 | 
			
		||||
        "schema-utils": "2.7.0",
 | 
			
		||||
        "semver": "^7.3.2",
 | 
			
		||||
        "tapable": "^1.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ansi-styles": {
 | 
			
		||||
          "version": "4.3.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
 | 
			
		||||
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-convert": "^2.0.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "chalk": {
 | 
			
		||||
          "version": "4.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
 | 
			
		||||
          "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ansi-styles": "^4.1.0",
 | 
			
		||||
            "supports-color": "^7.1.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "color-convert": {
 | 
			
		||||
          "version": "2.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
 | 
			
		||||
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-name": "~1.1.4"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "color-name": {
 | 
			
		||||
          "version": "1.1.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
 | 
			
		||||
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "has-flag": {
 | 
			
		||||
          "version": "4.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "lru-cache": {
 | 
			
		||||
          "version": "6.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "yallist": "^4.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "schema-utils": {
 | 
			
		||||
          "version": "2.7.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
 | 
			
		||||
          "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "@types/json-schema": "^7.0.4",
 | 
			
		||||
            "ajv": "^6.12.2",
 | 
			
		||||
            "ajv-keywords": "^3.4.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "semver": {
 | 
			
		||||
          "version": "7.3.5",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
 | 
			
		||||
          "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "lru-cache": "^6.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "supports-color": {
 | 
			
		||||
          "version": "7.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
 | 
			
		||||
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "has-flag": "^4.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "yallist": {
 | 
			
		||||
          "version": "4.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "form-data": {
 | 
			
		||||
      "version": "2.3.3",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
 | 
			
		||||
@ -12862,87 +12941,6 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "vue-loader-v16": {
 | 
			
		||||
      "version": "npm:vue-loader@16.3.0",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.3.0.tgz",
 | 
			
		||||
      "integrity": "sha512-UDgni/tUVSdwHuQo+vuBmEgamWx88SuSlEb5fgdvHrlJSPB9qMBRF6W7bfPWSqDns425Gt1wxAUif+f+h/rWjg==",
 | 
			
		||||
      "dev": true,
 | 
			
		||||
      "optional": true,
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "chalk": "^4.1.0",
 | 
			
		||||
        "hash-sum": "^2.0.0",
 | 
			
		||||
        "loader-utils": "^2.0.0"
 | 
			
		||||
      },
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "ansi-styles": {
 | 
			
		||||
          "version": "4.3.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
 | 
			
		||||
          "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-convert": "^2.0.1"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "chalk": {
 | 
			
		||||
          "version": "4.1.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
 | 
			
		||||
          "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "ansi-styles": "^4.1.0",
 | 
			
		||||
            "supports-color": "^7.1.0"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "color-convert": {
 | 
			
		||||
          "version": "2.0.1",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
 | 
			
		||||
          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "color-name": "~1.1.4"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "color-name": {
 | 
			
		||||
          "version": "1.1.4",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
 | 
			
		||||
          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "has-flag": {
 | 
			
		||||
          "version": "4.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true
 | 
			
		||||
        },
 | 
			
		||||
        "loader-utils": {
 | 
			
		||||
          "version": "2.0.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
 | 
			
		||||
          "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "big.js": "^5.2.2",
 | 
			
		||||
            "emojis-list": "^3.0.0",
 | 
			
		||||
            "json5": "^2.1.2"
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        "supports-color": {
 | 
			
		||||
          "version": "7.2.0",
 | 
			
		||||
          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
 | 
			
		||||
          "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
 | 
			
		||||
          "dev": true,
 | 
			
		||||
          "optional": true,
 | 
			
		||||
          "requires": {
 | 
			
		||||
            "has-flag": "^4.0.0"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "vue-router": {
 | 
			
		||||
      "version": "4.0.10",
 | 
			
		||||
      "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.10.tgz",
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "serve": "vue-cli-service serve",
 | 
			
		||||
    "build": "vue-cli-service build",
 | 
			
		||||
    "build": "vue-cli-service build --mode development",
 | 
			
		||||
    "lint": "vue-cli-service lint"
 | 
			
		||||
  },
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
import { LogOnSuccess } from './types'
 | 
			
		||||
import { Count, LogOnSuccess, Profile } from './types'
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create a URL that will access the API
 | 
			
		||||
@ -7,17 +7,72 @@ import { LogOnSuccess } from './types'
 | 
			
		||||
 */
 | 
			
		||||
const apiUrl = (url : string) : string => `http://localhost:5000/api/${url}`
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Create request init parameters
 | 
			
		||||
 *
 | 
			
		||||
 * @param method The method by which the request should be executed
 | 
			
		||||
 * @param user The currently logged-on user
 | 
			
		||||
 * @returns RequestInit parameters
 | 
			
		||||
 */
 | 
			
		||||
const reqInit = (method : string, user : LogOnSuccess) : RequestInit => {
 | 
			
		||||
  const headers = new Headers()
 | 
			
		||||
  headers.append('Authorization', `Bearer ${user.jwt}`)
 | 
			
		||||
  return {
 | 
			
		||||
    headers,
 | 
			
		||||
    method
 | 
			
		||||
    // mode: 'cors'
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Log a citizen on
 | 
			
		||||
   * @param code The authorization code from No Agenda Social
 | 
			
		||||
   * @returns The user result, or an error
 | 
			
		||||
   */
 | 
			
		||||
  logOn: async (code : string) : Promise<LogOnSuccess | string> => {
 | 
			
		||||
    const resp = await fetch(apiUrl(`citizen/log-on/${code}`), { method: 'GET', mode: 'cors' })
 | 
			
		||||
    if (resp.status === 200) return await resp.json() as LogOnSuccess
 | 
			
		||||
    return `Error logging on - ${await resp.text()}`
 | 
			
		||||
  /** API functions for citizens */
 | 
			
		||||
  citizen: {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Log a citizen on
 | 
			
		||||
     *
 | 
			
		||||
     * @param code The authorization code from No Agenda Social
 | 
			
		||||
     * @returns The user result, or an error
 | 
			
		||||
     */
 | 
			
		||||
    logOn: async (code : string) : Promise<LogOnSuccess | string> => {
 | 
			
		||||
      const resp = await fetch(apiUrl(`citizen/log-on/${code}`), { method: 'GET', mode: 'cors' })
 | 
			
		||||
      if (resp.status === 200) return await resp.json() as LogOnSuccess
 | 
			
		||||
      return `Error logging on - ${await resp.text()}`
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  /** API functions for profiles */
 | 
			
		||||
  profile: {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieve a profile
 | 
			
		||||
     *
 | 
			
		||||
     * @param id The ID of the profile to retrieve (optional; if omitted, retrieve for the current citizen)
 | 
			
		||||
     * @param user The currently logged-on user
 | 
			
		||||
     * @returns The profile (if found), undefined (if not found), or an error string
 | 
			
		||||
     */
 | 
			
		||||
    retreive: async (id : string | undefined, user : LogOnSuccess) : Promise<Profile | undefined | string> => {
 | 
			
		||||
      const url = id ? `profile/get/${id}` : 'profile'
 | 
			
		||||
      const resp = await fetch(apiUrl(url), reqInit('GET', user))
 | 
			
		||||
      if (resp.status === 200) return await resp.json() as Profile
 | 
			
		||||
      if (resp.status !== 204) return `Error retrieving profile - ${await resp.text()}`
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Count profiles in the system
 | 
			
		||||
     *
 | 
			
		||||
     * @param user The currently logged-on user
 | 
			
		||||
     * @returns A count of profiles within the entire system
 | 
			
		||||
     */
 | 
			
		||||
    count: async (user : LogOnSuccess) : Promise<number | string> => {
 | 
			
		||||
      const resp = await fetch(apiUrl('profile/count'), reqInit('GET', user))
 | 
			
		||||
      if (resp.status === 200) {
 | 
			
		||||
        const result = await resp.json() as Count
 | 
			
		||||
        return result.count
 | 
			
		||||
      }
 | 
			
		||||
      return `Error counting profiles = ${await resp.text()}`
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -8,3 +8,45 @@ export interface LogOnSuccess {
 | 
			
		||||
  /** The name of the logged-in citizen */
 | 
			
		||||
  name : string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** A skill the job seeker possesses */
 | 
			
		||||
export interface Skill {
 | 
			
		||||
  /** The ID of the skill */
 | 
			
		||||
  id : string
 | 
			
		||||
  /** A description of the skill */
 | 
			
		||||
  description : string
 | 
			
		||||
  /** Notes regarding this skill (level, duration, etc.) */
 | 
			
		||||
  notes : string | undefined
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** A job seeker profile */
 | 
			
		||||
export interface Profile {
 | 
			
		||||
  /** The ID of the citizen to whom this profile belongs */
 | 
			
		||||
  id : string
 | 
			
		||||
  /** Whether this citizen is actively seeking employment */
 | 
			
		||||
  seekingEmployment : boolean
 | 
			
		||||
  /** Whether this citizen allows their profile to be a part of the publicly-viewable, anonymous data */
 | 
			
		||||
  isPublic : boolean
 | 
			
		||||
  /** The ID of the continent on which the citizen resides */
 | 
			
		||||
  continentId : string
 | 
			
		||||
  /** The region in which the citizen resides */
 | 
			
		||||
  region : string
 | 
			
		||||
  /** Whether the citizen is looking for remote work */
 | 
			
		||||
  remoteWork : boolean
 | 
			
		||||
  /** Whether the citizen is looking for full-time work */
 | 
			
		||||
  fullTime : boolean
 | 
			
		||||
  /** The citizen's professional biography */
 | 
			
		||||
  biography : string
 | 
			
		||||
  /** When the citizen last updated their profile */
 | 
			
		||||
  lastUpdatedOn : number
 | 
			
		||||
  /** The citizen's experience (topical / chronological) */
 | 
			
		||||
  experience : string | undefined
 | 
			
		||||
  /** Skills this citizen possesses */
 | 
			
		||||
  skills : Skill[]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** A count */
 | 
			
		||||
export interface Count {
 | 
			
		||||
  /** The count being returned */
 | 
			
		||||
  count : number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -3,27 +3,32 @@
 | 
			
		||||
    <p class="home-link"><router-link to="/">Jobs, Jobs, Jobs</router-link></p>
 | 
			
		||||
    <p> </p>
 | 
			
		||||
    <nav>
 | 
			
		||||
      <router-link to="/"><v-icon icon="mdi-home" /> Home</router-link>
 | 
			
		||||
      <!-- If not logged in -->
 | 
			
		||||
      <router-link to="/profile/seeking"><v-icon icon="mdi-view-list-outline" /> Job Seekers</router-link>
 | 
			
		||||
      <a :href="authUrl"><v-icon icon="mdi-login-variant" /> Log On</a>
 | 
			
		||||
      <!-- If logged in -->
 | 
			
		||||
      <router-link to="/citizen/profile"><v-icon icon="mdi-pencil" /> Edit Your Profile</router-link>
 | 
			
		||||
      <router-link to="/profile/search"><v-icon icon="mdi-view-list-outline" /> View Profiles</router-link>
 | 
			
		||||
      <router-link to="/success-story/list"><v-icon icon="mdi-thumb-up" /> Success Stories</router-link>
 | 
			
		||||
      <router-link to="/citizen/log-off"><v-icon icon="mdi-logout-variant" /> Log Off</router-link>
 | 
			
		||||
      <!-- everyone -->
 | 
			
		||||
      <template v-if="!isLoggedOn">
 | 
			
		||||
        <router-link to="/"><v-icon icon="mdi-home" /> Home</router-link>
 | 
			
		||||
        <router-link to="/profile/seeking"><v-icon icon="mdi-view-list-outline" /> Job Seekers</router-link>
 | 
			
		||||
        <a :href="authUrl"><v-icon icon="mdi-login-variant" /> Log On</a>
 | 
			
		||||
      </template>
 | 
			
		||||
      <template v-else>
 | 
			
		||||
        <router-link to="/citizen/dashboard"><v-icon icon="mdi-view-dashboard-variant" />Dashboard</router-link>
 | 
			
		||||
        <router-link to="/citizen/profile"><v-icon icon="mdi-pencil" /> Edit Your Profile</router-link>
 | 
			
		||||
        <router-link to="/profile/search"><v-icon icon="mdi-view-list-outline" /> View Profiles</router-link>
 | 
			
		||||
        <router-link to="/success-story/list"><v-icon icon="mdi-thumb-up" /> Success Stories</router-link>
 | 
			
		||||
        <router-link to="/citizen/log-off"><v-icon icon="mdi-logout-variant" /> Log Off</router-link>
 | 
			
		||||
      </template>
 | 
			
		||||
      <router-link to="/how-it-works"><v-icon icon="mdi-help-circle-outline" /> How It Works</router-link>
 | 
			
		||||
    </nav>
 | 
			
		||||
  </aside>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent } from 'vue'
 | 
			
		||||
import { computed, defineComponent } from 'vue'
 | 
			
		||||
import { useStore } from '../../store'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'AppNav',
 | 
			
		||||
  setup () {
 | 
			
		||||
    const store = useStore()
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      /** The authorization URL to which the user should be directed */
 | 
			
		||||
      authUrl: (() => {
 | 
			
		||||
@ -35,7 +40,10 @@ export default defineComponent({
 | 
			
		||||
        const respType = 'response_type=code'
 | 
			
		||||
        // TODO: move NAS base URL to config
 | 
			
		||||
        return `https://noagendasocial.com/oauth/authorize?${client}&${scope}&${redirect}&${respType}`
 | 
			
		||||
      })()
 | 
			
		||||
      })(),
 | 
			
		||||
 | 
			
		||||
      /** Whether a user is logged in or not */
 | 
			
		||||
      isLoggedOn: computed(() => store.state.user !== undefined)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
@ -49,7 +57,7 @@ aside
 | 
			
		||||
a:link, a:visited
 | 
			
		||||
  text-decoration: none
 | 
			
		||||
  color: white
 | 
			
		||||
  font-weight: bold
 | 
			
		||||
  font-weight: 500
 | 
			
		||||
.home-link
 | 
			
		||||
  font-size: 1.2rem
 | 
			
		||||
  text-align: center
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,10 @@ const routes: Array<RouteRecordRaw> = [
 | 
			
		||||
  {
 | 
			
		||||
    path: '/citizen/authorized',
 | 
			
		||||
    component: () => import(/* webpackChunkName: "logon" */ '../views/citizen/Authorized.vue')
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    path: '/citizen/dashboard',
 | 
			
		||||
    component: () => import(/* webpackChunkName: "logon" */ '../views/citizen/Dashboard.vue')
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ export default createStore({
 | 
			
		||||
  },
 | 
			
		||||
  actions: {
 | 
			
		||||
    async logOn ({ commit }, code: string) {
 | 
			
		||||
      const logOnResult = await api.logOn(code)
 | 
			
		||||
      const logOnResult = await api.citizen.logOn(code)
 | 
			
		||||
      if (typeof logOnResult === 'string') {
 | 
			
		||||
        commit('setLogOnState', logOnResult)
 | 
			
		||||
      } else {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										81
									
								
								src/JobsJobsJobs/App/src/views/citizen/Dashboard.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/JobsJobsJobs/App/src/views/citizen/Dashboard.vue
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <h3>Welcome, {{user.name}}</h3>
 | 
			
		||||
 | 
			
		||||
  <template v-if="profile">
 | 
			
		||||
    <p>
 | 
			
		||||
      Your employment profile was last updated {{profile.lastUpdatedOn}}. Your profile currently lists
 | 
			
		||||
      {{profile.skills.length}} skill<span v-if="profile.skills.length !== 1">s</span>.
 | 
			
		||||
    </p>
 | 
			
		||||
    <p><router-link :to="'/profile/view/' + user.citizenId">View Your Employment Profile</router-link></p>
 | 
			
		||||
    <p v-if="profile.seekingEmployment">
 | 
			
		||||
      Your profile indicates that you are seeking employment. Once you find it,
 | 
			
		||||
      <router-link to="/success-story/add">tell your fellow citizens about it!</router-link>
 | 
			
		||||
    </p>
 | 
			
		||||
  </template>
 | 
			
		||||
  <template v-else>
 | 
			
		||||
    <p>
 | 
			
		||||
      You do not have an employment profile established; click “Edit Profile” in the menu to get
 | 
			
		||||
      started!
 | 
			
		||||
    </p>
 | 
			
		||||
  </template>
 | 
			
		||||
  <hr>
 | 
			
		||||
  <p>
 | 
			
		||||
    There <span v-if="profileCount === 1">is</span><span v-else>are</span> <span v-if="profileCount === 0">no</span><span v-else>{{profileCount}}</span>
 | 
			
		||||
    employment profile<span v-if="profileCount !== 1">s</span> from citizens of Gitmo Nation.
 | 
			
		||||
    <span v-if="profileCount > 0">Take a look around and see if you can help them find work!</span>
 | 
			
		||||
  </p>
 | 
			
		||||
  <hr>
 | 
			
		||||
  <p>
 | 
			
		||||
    To see how this application works, check out “How It Works” in the sidebar (last updated June
 | 
			
		||||
    14<sup>th</sup>, 2021).
 | 
			
		||||
  </p>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent, onMounted, Ref, ref } from 'vue'
 | 
			
		||||
import api, { LogOnSuccess, Profile } from '../../api'
 | 
			
		||||
import { useStore } from '../../store'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'Dashboard',
 | 
			
		||||
  setup () {
 | 
			
		||||
    const store = useStore()
 | 
			
		||||
 | 
			
		||||
    /** The currently logged-in user */
 | 
			
		||||
    const user = store.state.user as LogOnSuccess
 | 
			
		||||
 | 
			
		||||
    /** Error messages from data retrieval */
 | 
			
		||||
    const errorMessage = ref('')
 | 
			
		||||
 | 
			
		||||
    /** The user's profile */
 | 
			
		||||
    const profile : Ref<Profile | undefined> = ref(undefined)
 | 
			
		||||
 | 
			
		||||
    /** A count of profiles in the system */
 | 
			
		||||
    const profileCount = ref(0)
 | 
			
		||||
 | 
			
		||||
    const retrieveData = async () => {
 | 
			
		||||
      const profileResult = await api.profile.retreive(undefined, user)
 | 
			
		||||
      if (typeof profileResult === 'string') {
 | 
			
		||||
        errorMessage.value = profileResult
 | 
			
		||||
      } else if (typeof profileResult !== 'undefined') {
 | 
			
		||||
        profile.value = profileResult
 | 
			
		||||
      }
 | 
			
		||||
      const count = await api.profile.count(user)
 | 
			
		||||
      if (typeof count === 'string') {
 | 
			
		||||
        errorMessage.value = `${errorMessage.value}\n${count}`
 | 
			
		||||
      } else {
 | 
			
		||||
        profileCount.value = count
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onMounted(retrieveData)
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      user,
 | 
			
		||||
      errorMessage,
 | 
			
		||||
      profile,
 | 
			
		||||
      profileCount
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
module.exports = {
 | 
			
		||||
  transpileDependencies: [
 | 
			
		||||
    'vuetify'
 | 
			
		||||
  ]
 | 
			
		||||
  ],
 | 
			
		||||
  outputDir: '../Api/wwwroot'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user