7 Commits
2.0 ... 2.1.1

Author SHA1 Message Date
Daniel J. Summers
6a6f7b35c7 Reverse notes ordering, make scrollable (#32) 2019-10-14 10:50:50 -05:00
715df08cbe Migrate API to .NET Core 3.0 (#31)
Migrate API to .NET Core 3.0 (fixes #30)
2019-09-28 08:42:58 -05:00
Daniel J. Summers
ac8b39fff9 Update version 2019-09-26 21:22:14 -05:00
Daniel J. Summers
2bf54136ca Fix journal ordering fix (#28 again) 2019-09-26 20:46:08 -05:00
Daniel J. Summers
0709cabea1 Fix journal ordering (#28) 2019-09-10 06:08:19 -05:00
Daniel J. Summers
cbd9114599 Update deps
fixes security for eslint-utils, which isn't part of the published package; no same-day point-plusone release required
2019-09-02 19:39:51 -05:00
Daniel J. Summers
097ee2deb4 Remove v2 migration program 2019-09-02 19:07:51 -05:00
10 changed files with 352 additions and 461 deletions

View File

@@ -85,6 +85,15 @@ module private Helpers =
/// Flip JSON result so we can pipe into it
let asJson<'T> next ctx (o : 'T) =
json o next ctx
/// Work-around to let the Json.NET serializer synchronously deserialize from the request stream
// TODO: Remove this once there is an async serializer
let allowSyncIO : HttpHandler =
fun next ctx ->
match ctx.Features.Get<Features.IHttpBodyControlFeature>() with
| null -> ()
| f -> f.AllowSynchronousIO <- true
next ctx
/// Strongly-typed models for post requests
@@ -156,6 +165,7 @@ module Request =
/// POST /api/request
let add : HttpHandler =
authorize
>=> allowSyncIO
>=> fun next ctx ->
task {
let! r = ctx.BindJsonAsync<Models.Request> ()
@@ -187,6 +197,7 @@ module Request =
/// POST /api/request/[req-id]/history
let addHistory requestId : HttpHandler =
authorize
>=> allowSyncIO
>=> fun next ctx ->
task {
use sess = session ctx
@@ -218,6 +229,7 @@ module Request =
/// POST /api/request/[req-id]/note
let addNote requestId : HttpHandler =
authorize
>=> allowSyncIO
>=> fun next ctx ->
task {
use sess = session ctx
@@ -297,6 +309,7 @@ module Request =
/// PATCH /api/request/[req-id]/snooze
let snooze requestId : HttpHandler =
authorize
>=> allowSyncIO
>=> fun next ctx ->
task {
use sess = session ctx
@@ -314,6 +327,7 @@ module Request =
/// PATCH /api/request/[req-id]/recurrence
let updateRecurrence requestId : HttpHandler =
authorize
>=> allowSyncIO
>=> fun next ctx ->
task {
use sess = session ctx

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<Version>2.0.0.0</Version>
<TargetFramework>netcoreapp3.0</TargetFramework>
<Version>2.1.1.0</Version>
</PropertyGroup>
<ItemGroup>
@@ -16,7 +16,7 @@
<PackageReference Include="FunctionalCuid" Version="1.0.0" />
<PackageReference Include="Giraffe" Version="3.6.0" />
<PackageReference Include="Giraffe.TokenRouter" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.0" />
<PackageReference Include="Microsoft.FSharpLu" Version="0.10.29" />
<PackageReference Include="Microsoft.FSharpLu.Json" Version="0.10.29" />
<PackageReference Include="RavenDb.Client" Version="4.2.1" />

View File

@@ -90,11 +90,12 @@ module Configure =
bldr.ConfigureServices svcs
open Microsoft.Extensions.Logging
open Microsoft.Extensions.Hosting
/// Configure logging
let logging (bldr : IWebHostBuilder) =
let logz (log : ILoggingBuilder) =
let env = log.Services.BuildServiceProvider().GetService<IHostingEnvironment> ()
let env = log.Services.BuildServiceProvider().GetService<IWebHostEnvironment> ()
match env.IsDevelopment () with
| true -> log
| false -> log.AddFilter(fun l -> l > LogLevel.Information)
@@ -109,7 +110,7 @@ module Configure =
let appConfig =
Action<IApplicationBuilder> (
fun (app : IApplicationBuilder) ->
let env = app.ApplicationServices.GetService<IHostingEnvironment> ()
let env = app.ApplicationServices.GetService<IWebHostEnvironment> ()
match env.IsDevelopment () with
| true -> app.UseDeveloperExceptionPage ()
| false -> app.UseGiraffeErrorHandler Handlers.Error.error

2
src/app/.gitignore vendored
View File

@@ -21,4 +21,4 @@ yarn-error.log*
*.sw*
# Auth0 settings
src/auth/auth0-variables.js
src/auth/auth0-variables.*

View File

@@ -1,6 +1,6 @@
{
"name": "my-prayer-journal",
"version": "2.0.0",
"version": "2.1.1",
"description": "myPrayerJournal - Front End",
"author": "Daniel J. Summers <daniel@bitbadger.solutions>",
"private": true,
@@ -10,7 +10,7 @@
"lint": "vue-cli-service lint",
"apistart": "cd ../MyPrayerJournal.Api && dotnet run",
"vue": "vue-cli-service build --modern && cd ../MyPrayerJournal.Api && dotnet run",
"publish": "vue-cli-service build --modern && cd ../MyPrayerJournal.Api && dotnet publish -c Release"
"publish": "vue-cli-service build --modern && cd ../MyPrayerJournal.Api && dotnet publish -c Release -r linux-x64 --self-contained false"
},
"dependencies": {
"auth0-js": "^9.7.3",

View File

@@ -10,7 +10,7 @@ md-dialog(:md-active.sync='notesVisible').mpj-note-dialog
md-dialog-actions
md-button(@click='saveNotes()').md-primary #[md-icon save] Save
md-button(@click='closeDialog()') #[md-icon undo] Cancel
.mpj-dialog-content
md-dialog-content(md-scrollbar='true').mpj-dialog-content
div(v-if='hasPriorNotes')
p.mpj-text-center: strong Prior Notes for This Request
.mpj-note-list
@@ -71,7 +71,7 @@ export default {
this.progress.$emit('show', 'indeterminate')
try {
const notes = await api.getNotes(this.form.requestId)
this.priorNotes = notes.data
this.priorNotes = notes.data.sort((a, b) => b.asOf - a.asOf)
this.progress.$emit('done')
} catch (e) {
console.error(e)

View File

@@ -50,11 +50,22 @@ const setBearer = async function () {
}
/* eslint-enable no-console */
/**
* Get the sort value for a prayer request
* @param x The prayer request
*/
const sortValue = x => x.showAfter === 0 ? x.asOf : x.showAfter
/**
* Sort journal requests either by asOf or showAfter
*/
const journalSort = (a, b) => sortValue(a) - sortValue(b)
export default new Vuex.Store({
state: {
user: auth.session.profile,
isAuthenticated: auth.isAuthenticated(),
journal: {},
journal: [],
isLoadingJournal: false
},
mutations: {
@@ -62,7 +73,7 @@ export default new Vuex.Store({
state.isLoadingJournal = flag
},
[mutations.LOADED_JOURNAL] (state, journal) {
state.journal = journal
state.journal = journal.sort(journalSort)
},
[mutations.REQUEST_ADDED] (state, newRequest) {
state.journal.push(newRequest)
@@ -107,7 +118,7 @@ export default new Vuex.Store({
}
},
async [actions.LOAD_JOURNAL] ({ commit }, progress) {
commit(mutations.LOADED_JOURNAL, {})
commit(mutations.LOADED_JOURNAL, [])
progress.$emit('show', 'query')
commit(mutations.LOADING_JOURNAL, true)
await setBearer()

File diff suppressed because it is too large Load Diff

View File

@@ -1,110 +0,0 @@

open Microsoft.FSharpLu.Json
open MyPrayerJournal
open Npgsql
open Raven.Client.Documents
type NpgsqlDataReader with
member this.getShort = this.GetOrdinal >> this.GetInt16
member this.getString = this.GetOrdinal >> this.GetString
member this.getTicks = this.GetOrdinal >> this.GetInt64 >> Ticks
member this.isNull = this.GetOrdinal >> this.IsDBNull
let pgConn connStr =
let c = new NpgsqlConnection (connStr)
c.Open ()
c
let isValidStatus stat =
try
(RequestAction.fromString >> ignore) stat
true
with _ -> false
let getHistory reqId connStr =
use conn = pgConn connStr
use cmd = conn.CreateCommand ()
cmd.CommandText <- """SELECT "asOf", status, text FROM mpj.history WHERE "requestId" = @reqId ORDER BY "asOf" """
(cmd.Parameters.Add >> ignore) (NpgsqlParameter ("@reqId", reqId :> obj))
use rdr = cmd.ExecuteReader ()
seq {
while rdr.Read () do
match (rdr.getString >> isValidStatus) "status" with
| true ->
yield
{ asOf = rdr.getTicks "asOf"
status = (rdr.getString >> RequestAction.fromString) "status"
text = match rdr.isNull "text" with true -> None | false -> (rdr.getString >> Some) "text"
}
| false ->
printf "Invalid status %s; skipped history entry %s/%i\n" (rdr.getString "status") reqId
((rdr.getTicks >> Ticks.toLong) "asOf")
}
|> List.ofSeq
let getNotes reqId connStr =
use conn = pgConn connStr
use cmd = conn.CreateCommand ()
cmd.CommandText <- """SELECT "asOf", notes FROM mpj.note WHERE "requestId" = @reqId"""
(cmd.Parameters.Add >> ignore) (NpgsqlParameter ("@reqId", reqId :> obj))
use rdr = cmd.ExecuteReader ()
seq {
while rdr.Read () do
yield
{ asOf = rdr.getTicks "asOf"
notes = rdr.getString "notes"
}
}
|> List.ofSeq
let migrateRequests (store : IDocumentStore) connStr =
use sess = store.OpenSession ()
use conn = pgConn connStr
use cmd = conn.CreateCommand ()
cmd.CommandText <-
"""SELECT "requestId", "enteredOn", "userId", "snoozedUntil", "showAfter", "recurType", "recurCount" FROM mpj.request"""
use rdr = cmd.ExecuteReader ()
while rdr.Read () do
let reqId = rdr.getString "requestId"
let recurrence =
match rdr.getString "recurType" with
| "immediate" -> Immediate
| "hours" -> Hours
| "days" -> Days
| "weeks" -> Weeks
| x -> invalidOp (sprintf "%s is not a valid recurrence" x)
sess.Store (
{ Id = (RequestId.fromIdString >> RequestId.toString) reqId
enteredOn = rdr.getTicks "enteredOn"
userId = (rdr.getString >> UserId) "userId"
snoozedUntil = rdr.getTicks "snoozedUntil"
showAfter = match recurrence with Immediate -> Ticks 0L | _ -> rdr.getTicks "showAfter"
recurType = recurrence
recurCount = rdr.getShort "recurCount"
history = getHistory reqId connStr
notes = getNotes reqId connStr
})
sess.SaveChanges ()
open Converters
open System
open System.Security.Cryptography.X509Certificates
[<EntryPoint>]
let main argv =
match argv.Length with
| 4 ->
let clientCert = new X509Certificate2 (argv.[1], argv.[2])
let raven = new DocumentStore (Urls = [| argv.[0] |], Database = "myPrayerJournal", Certificate = clientCert)
raven.Conventions.CustomizeJsonSerializer <-
fun x ->
x.Converters.Add (RequestIdJsonConverter ())
x.Converters.Add (TicksJsonConverter ())
x.Converters.Add (UserIdJsonConverter ())
x.Converters.Add (CompactUnionJsonConverter ())
let store = raven.Initialize ()
migrateRequests store argv.[3]
printfn "fin"
| _ ->
Console.WriteLine "Usage: dotnet migrate.dll [raven-url] [raven-cert-file] [raven-cert-pw] [postgres-conn-str]"
0

View File

@@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.FSharpLu.Json" Version="0.11.2" />
<PackageReference Include="Npgsql" Version="4.0.8" />
<PackageReference Include="RavenDb.Client" Version="4.2.2" />
<ProjectReference Include="../MyPrayerJournal.Api/MyPrayerJournal.Api.fsproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="FSharp.Core" Version="4.7.0" />
</ItemGroup>
</Project>