Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57cd17c734 | ||
|
|
42615dae82 | ||
|
|
68b650e31d | ||
|
|
d738321dc0 | ||
|
|
8995097d68 | ||
|
|
4310fb91fa |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -252,6 +252,9 @@ paket-files/
|
|||||||
.idea/
|
.idea/
|
||||||
*.sln.iml
|
*.sln.iml
|
||||||
|
|
||||||
|
# Ionide VSCode extension
|
||||||
|
.ionide
|
||||||
|
|
||||||
# Compiled files / application
|
# Compiled files / application
|
||||||
src/api/build
|
src/api/build
|
||||||
src/api/MyPrayerJournal.Api/wwwroot/favicon.ico
|
src/api/MyPrayerJournal.Api/wwwroot/favicon.ico
|
||||||
|
|||||||
@@ -1,15 +1,8 @@
|
|||||||
namespace MyPrayerJournal
|
namespace MyPrayerJournal
|
||||||
|
|
||||||
open FSharp.Control.Tasks.ContextInsensitive
|
open FSharp.Control.Tasks.V2.ContextInsensitive
|
||||||
open Microsoft.EntityFrameworkCore
|
open Microsoft.EntityFrameworkCore
|
||||||
|
open Microsoft.FSharpLu
|
||||||
/// Helpers for this file
|
|
||||||
[<AutoOpen>]
|
|
||||||
module private Helpers =
|
|
||||||
|
|
||||||
/// Convert any item to an option (Option.ofObj does not work for non-nullable types)
|
|
||||||
let toOption<'T> (x : 'T) = match box x with null -> None | _ -> Some x
|
|
||||||
|
|
||||||
|
|
||||||
/// Entities for use in the data model for myPrayerJournal
|
/// Entities for use in the data model for myPrayerJournal
|
||||||
[<AutoOpen>]
|
[<AutoOpen>]
|
||||||
@@ -183,7 +176,6 @@ module Entities =
|
|||||||
|
|
||||||
|
|
||||||
open System.Linq
|
open System.Linq
|
||||||
open System.Threading.Tasks
|
|
||||||
|
|
||||||
/// Data context
|
/// Data context
|
||||||
type AppDbContext (opts : DbContextOptions<AppDbContext>) =
|
type AppDbContext (opts : DbContextOptions<AppDbContext>) =
|
||||||
@@ -248,7 +240,7 @@ type AppDbContext (opts : DbContextOptions<AppDbContext>) =
|
|||||||
member this.TryRequestById reqId userId =
|
member this.TryRequestById reqId userId =
|
||||||
task {
|
task {
|
||||||
let! req = this.Requests.AsNoTracking().FirstOrDefaultAsync(fun r -> r.requestId = reqId && r.userId = userId)
|
let! req = this.Requests.AsNoTracking().FirstOrDefaultAsync(fun r -> r.requestId = reqId && r.userId = userId)
|
||||||
return toOption req
|
return Option.fromObject req
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve notes for a request by its ID and user ID
|
/// Retrieve notes for a request by its ID and user ID
|
||||||
@@ -263,7 +255,7 @@ type AppDbContext (opts : DbContextOptions<AppDbContext>) =
|
|||||||
member this.TryJournalById reqId userId =
|
member this.TryJournalById reqId userId =
|
||||||
task {
|
task {
|
||||||
let! req = this.Journal.FirstOrDefaultAsync(fun r -> r.requestId = reqId && r.userId = userId)
|
let! req = this.Journal.FirstOrDefaultAsync(fun r -> r.requestId = reqId && r.userId = userId)
|
||||||
return toOption req
|
return Option.fromObject req
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve a request, including its history and notes, by its ID and user ID
|
/// Retrieve a request, including its history and notes, by its ID and user ID
|
||||||
@@ -276,7 +268,7 @@ type AppDbContext (opts : DbContextOptions<AppDbContext>) =
|
|||||||
.Include(fun r -> r.history)
|
.Include(fun r -> r.history)
|
||||||
.Include(fun r -> r.notes)
|
.Include(fun r -> r.notes)
|
||||||
.FirstOrDefaultAsync(fun r -> r.requestId = requestId && r.userId = userId)
|
.FirstOrDefaultAsync(fun r -> r.requestId = requestId && r.userId = userId)
|
||||||
match toOption fullReq with
|
match Option.fromObject fullReq with
|
||||||
| Some _ -> return Some { req with history = List.ofSeq fullReq.history; notes = List.ofSeq fullReq.notes }
|
| Some _ -> return Some { req with history = List.ofSeq fullReq.history; notes = List.ofSeq fullReq.notes }
|
||||||
| None -> return None
|
| None -> return None
|
||||||
| None -> return None
|
| None -> return None
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module MyPrayerJournal.Api.Handlers
|
module MyPrayerJournal.Api.Handlers
|
||||||
|
|
||||||
|
open FSharp.Control.Tasks.V2.ContextInsensitive
|
||||||
open Giraffe
|
open Giraffe
|
||||||
open MyPrayerJournal
|
open MyPrayerJournal
|
||||||
open System
|
open System
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||||
|
<Version>1.2.1.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -12,15 +13,18 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FSharp.EFCore.OptionConverter" Version="1.0.0" />
|
<PackageReference Include="FSharp.EFCore.OptionConverter" Version="1.0.0" />
|
||||||
<PackageReference Include="Giraffe" Version="1.1.0" />
|
<PackageReference Include="Giraffe" Version="3.6.0" />
|
||||||
<PackageReference Include="Giraffe.TokenRouter" Version="0.1.0-beta-110" />
|
<PackageReference Include="Giraffe.TokenRouter" Version="1.0.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||||
|
<PackageReference Include="Microsoft.FSharpLu" Version="0.10.29" />
|
||||||
|
<PackageReference Include="Microsoft.FSharpLu.Json" Version="0.10.29" />
|
||||||
<PackageReference Include="NCuid.NetCore" Version="1.0.1" />
|
<PackageReference Include="NCuid.NetCore" Version="1.0.1" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.1.1.1" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.2.0" />
|
||||||
|
<PackageReference Include="TaskBuilder.fs" Version="2.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Update="FSharp.Core" Version="4.5.2" />
|
<PackageReference Update="FSharp.Core" Version="4.6.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ open Microsoft.AspNetCore.Builder
|
|||||||
open Microsoft.AspNetCore.Hosting
|
open Microsoft.AspNetCore.Hosting
|
||||||
open System
|
open System
|
||||||
|
|
||||||
|
|
||||||
/// Configuration functions for the application
|
/// Configuration functions for the application
|
||||||
module Configure =
|
module Configure =
|
||||||
|
|
||||||
open Giraffe
|
open Giraffe
|
||||||
|
open Giraffe.Serialization
|
||||||
open Giraffe.TokenRouter
|
open Giraffe.TokenRouter
|
||||||
open Microsoft.AspNetCore.Authentication.JwtBearer
|
open Microsoft.AspNetCore.Authentication.JwtBearer
|
||||||
open Microsoft.AspNetCore.Server.Kestrel.Core
|
open Microsoft.AspNetCore.Server.Kestrel.Core
|
||||||
@@ -16,7 +16,9 @@ module Configure =
|
|||||||
open Microsoft.Extensions.Configuration
|
open Microsoft.Extensions.Configuration
|
||||||
open Microsoft.Extensions.DependencyInjection
|
open Microsoft.Extensions.DependencyInjection
|
||||||
open Microsoft.Extensions.Logging
|
open Microsoft.Extensions.Logging
|
||||||
|
open Microsoft.FSharpLu.Json
|
||||||
open MyPrayerJournal
|
open MyPrayerJournal
|
||||||
|
open Newtonsoft.Json
|
||||||
|
|
||||||
/// Set up the configuration for the app
|
/// Set up the configuration for the app
|
||||||
let configuration (ctx : WebHostBuilderContext) (cfg : IConfigurationBuilder) =
|
let configuration (ctx : WebHostBuilderContext) (cfg : IConfigurationBuilder) =
|
||||||
@@ -30,6 +32,15 @@ module Configure =
|
|||||||
let kestrel (ctx : WebHostBuilderContext) (opts : KestrelServerOptions) =
|
let kestrel (ctx : WebHostBuilderContext) (opts : KestrelServerOptions) =
|
||||||
(ctx.Configuration.GetSection >> opts.Configure >> ignore) "Kestrel"
|
(ctx.Configuration.GetSection >> opts.Configure >> ignore) "Kestrel"
|
||||||
|
|
||||||
|
/// Custom settings for the JSON serializer (uses compact representation for options and DUs)
|
||||||
|
let jsonSettings =
|
||||||
|
let x = NewtonsoftJsonSerializer.DefaultSettings
|
||||||
|
x.Converters.Add (CompactUnionJsonConverter (true))
|
||||||
|
x.NullValueHandling <- NullValueHandling.Ignore
|
||||||
|
x.MissingMemberHandling <- MissingMemberHandling.Error
|
||||||
|
x.Formatting <- Formatting.Indented
|
||||||
|
x
|
||||||
|
|
||||||
/// Configure dependency injection
|
/// Configure dependency injection
|
||||||
let services (sc : IServiceCollection) =
|
let services (sc : IServiceCollection) =
|
||||||
use sp = sc.BuildServiceProvider()
|
use sp = sc.BuildServiceProvider()
|
||||||
@@ -48,6 +59,7 @@ module Configure =
|
|||||||
opts.Audience <- jwtCfg.["Id"])
|
opts.Audience <- jwtCfg.["Id"])
|
||||||
|> ignore
|
|> ignore
|
||||||
sc.AddDbContext<AppDbContext>(fun opts -> opts.UseNpgsql(cfg.GetConnectionString "mpj") |> ignore)
|
sc.AddDbContext<AppDbContext>(fun opts -> opts.UseNpgsql(cfg.GetConnectionString "mpj") |> ignore)
|
||||||
|
.AddSingleton<IJsonSerializer>(NewtonsoftJsonSerializer jsonSettings)
|
||||||
|> ignore
|
|> ignore
|
||||||
|
|
||||||
/// Routes for the available URLs within myPrayerJournal
|
/// Routes for the available URLs within myPrayerJournal
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
{
|
{
|
||||||
"name": "my-prayer-journal",
|
"name": "my-prayer-journal",
|
||||||
"version": "1.0.1",
|
"version": "1.2.1",
|
||||||
"description": "myPrayerJournal - Front End",
|
"description": "myPrayerJournal - Front End",
|
||||||
"author": "Daniel J. Summers <daniel@bitbadger.solutions>",
|
"author": "Daniel J. Summers <daniel@bitbadger.solutions>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build --modern",
|
||||||
"lint": "vue-cli-service lint",
|
"lint": "vue-cli-service lint",
|
||||||
"apistart": "cd ../api/MyPrayerJournal.Api && dotnet run",
|
"apistart": "cd ../api/MyPrayerJournal.Api && dotnet run",
|
||||||
"vue": "vue-cli-service build --modern && cd ../api/MyPrayerJournal.Api && dotnet run"
|
"vue": "vue-cli-service build --modern && cd ../api/MyPrayerJournal.Api && dotnet run",
|
||||||
|
"publish": "vue-cli-service build --modern && cd ../api/MyPrayerJournal.Api && dotnet publish -c Release"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"auth0-js": "^9.7.3",
|
"auth0-js": "^9.7.3",
|
||||||
"axios": "^0.18.0",
|
"axios": "^0.19.0",
|
||||||
"moment": "^2.18.1",
|
"moment": "^2.18.1",
|
||||||
"vue": "^2.5.15",
|
"vue": "^2.5.15",
|
||||||
"vue-progressbar": "^0.7.3",
|
"vue-progressbar": "^0.7.3",
|
||||||
@@ -25,7 +26,7 @@
|
|||||||
"@vue/cli-plugin-babel": "^3.0.0",
|
"@vue/cli-plugin-babel": "^3.0.0",
|
||||||
"@vue/cli-plugin-eslint": "^3.0.0",
|
"@vue/cli-plugin-eslint": "^3.0.0",
|
||||||
"@vue/cli-service": "^3.0.0",
|
"@vue/cli-service": "^3.0.0",
|
||||||
"@vue/eslint-config-standard": "^3.0.0",
|
"@vue/eslint-config-standard": "^4.0.0",
|
||||||
"pug": "^2.0.1",
|
"pug": "^2.0.1",
|
||||||
"pug-plain-loader": "^1.0.0",
|
"pug-plain-loader": "^1.0.0",
|
||||||
"vue-template-compiler": "^2.5.17"
|
"vue-template-compiler": "^2.5.17"
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ article.mpj-main-content(role='main')
|
|||||||
tbody
|
tbody
|
||||||
tr(v-for='item in log' :key='item.asOf')
|
tr(v-for='item in log' :key='item.asOf')
|
||||||
td {{ item.status }} on #[span.mpj-text-nowrap {{ formatDate(item.asOf) }}]
|
td {{ item.status }} on #[span.mpj-text-nowrap {{ formatDate(item.asOf) }}]
|
||||||
td(v-if='item.text').mpj-request-text {{ item.text.fields[0] }}
|
td(v-if='item.text').mpj-request-text {{ item.text }}
|
||||||
td(v-else)
|
td(v-else)
|
||||||
p(v-else) Loading request...
|
p(v-else) Loading request...
|
||||||
</template>
|
</template>
|
||||||
@@ -52,11 +52,11 @@ export default {
|
|||||||
lastText () {
|
lastText () {
|
||||||
return this.request.history
|
return this.request.history
|
||||||
.filter(hist => hist.text)
|
.filter(hist => hist.text)
|
||||||
.sort(asOfDesc)[0].text.fields[0]
|
.sort(asOfDesc)[0].text
|
||||||
},
|
},
|
||||||
log () {
|
log () {
|
||||||
const allHistory = (this.request.notes || [])
|
const allHistory = (this.request.notes || [])
|
||||||
.map(note => ({ asOf: note.asOf, text: { case: 'Some', fields: [ note.notes ] }, status: 'Notes' }))
|
.map(note => ({ asOf: note.asOf, text: note.notes, status: 'Notes' }))
|
||||||
.concat(this.request.history)
|
.concat(this.request.history)
|
||||||
.sort(asOfDesc)
|
.sort(asOfDesc)
|
||||||
// Skip the first entry for answered requests; that info is already displayed
|
// Skip the first entry for answered requests; that info is already displayed
|
||||||
|
|||||||
@@ -104,12 +104,14 @@ export default new Vuex.Store({
|
|||||||
progress.start()
|
progress.start()
|
||||||
try {
|
try {
|
||||||
let oldReq = (state.journal.filter(req => req.requestId === requestId) || [])[0] || {}
|
let oldReq = (state.journal.filter(req => req.requestId === requestId) || [])[0] || {}
|
||||||
if (status !== 'Updated' || oldReq.text !== updateText) {
|
if (!(status === 'Prayed' && updateText === '')) {
|
||||||
await api.updateRequest(requestId, status, updateText)
|
if (status !== 'Answered' && (oldReq.recurType !== recurType || oldReq.recurCount !== recurCount)) {
|
||||||
}
|
|
||||||
if (status === 'Updated' && (oldReq.recurType !== recurType || oldReq.recurCount !== recurCount)) {
|
|
||||||
await api.updateRecurrence(requestId, recurType, recurCount)
|
await api.updateRecurrence(requestId, recurType, recurCount)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (status !== 'Updated' || oldReq.text !== updateText) {
|
||||||
|
await api.updateRequest(requestId, status, oldReq.text !== updateText ? updateText : '')
|
||||||
|
}
|
||||||
const request = await api.getRequest(requestId)
|
const request = await api.getRequest(requestId)
|
||||||
commit(mutations.REQUEST_UPDATED, request.data)
|
commit(mutations.REQUEST_UPDATED, request.data)
|
||||||
progress.finish()
|
progress.finish()
|
||||||
|
|||||||
6476
src/app/yarn.lock
6476
src/app/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user