11 Commits
1.0.0 ... 1.2

Author SHA1 Message Date
Daniel J. Summers
42615dae82 Update recurrence before status (#25); version bump 2019-07-05 20:34:38 -05:00
Daniel J. Summers
68b650e31d Updated dependencies 2019-05-31 20:29:57 -05:00
Daniel J. Summers
d738321dc0 Use FSharpLu for JSON serialization (#24) 2019-02-23 13:59:32 -06:00
Daniel J. Summers
8995097d68 Updated to .NET Core 2.2 (#23)
Also updated API and app deps
2019-02-23 10:59:23 -06:00
Daniel J. Summers
4310fb91fa Updated deps 2019-01-29 20:52:38 -06:00
Daniel J. Summers
c0def7623f Updated docs link to new subdomain 2018-09-09 21:08:22 -05:00
Daniel J. Summers
ab8fab51c5 Create CNAME 2018-09-07 17:43:59 -05:00
Daniel J. Summers
96717ae7c4 Delete CNAME 2018-09-07 17:43:43 -05:00
Daniel J. Summers
b11ff0ff3d Create CNAME 2018-09-07 16:41:38 -05:00
Daniel J. Summers
6486763297 Delete CNAME 2018-09-07 16:41:23 -05:00
Daniel J. Summers
e94e28880b Create CNAME 2018-09-07 16:39:43 -05:00
11 changed files with 3923 additions and 2631 deletions

3
.gitignore vendored
View File

@@ -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
docs/CNAME Normal file
View File

@@ -0,0 +1 @@
docs.prayerjournal.me

View File

@@ -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

View File

@@ -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

View File

@@ -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.0.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>

View File

@@ -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

View File

@@ -1,19 +1,20 @@
{ {
"name": "my-prayer-journal", "name": "my-prayer-journal",
"version": "1.0.0", "version": "1.2.0",
"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"

View File

@@ -25,7 +25,7 @@ nav.mpj-top-nav.mpj-bg(role='menubar')
href='#' href='#'
role='menuitem' role='menuitem'
@click.stop='logOn()') Log On @click.stop='logOn()') Log On
a(href='https://bit-badger.github.io/myPrayerJournal/' a(href='https://docs.prayerjournal.me'
target='_blank' target='_blank'
role='menuitem' role='menuitem'
@click.stop='') Docs @click.stop='') Docs

View File

@@ -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) &nbsp; td(v-else) &nbsp;
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

View File

@@ -104,12 +104,12 @@ 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 !== 'Answered' && (oldReq.recurType !== recurType || oldReq.recurCount !== recurCount)) {
await api.updateRequest(requestId, status, updateText)
}
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()

File diff suppressed because it is too large Load Diff