Update posts/new example.

This commit is contained in:
Dillon Kearns 2023-02-03 10:18:23 -08:00
parent 39db416e89
commit 51f7a8dbd7
2 changed files with 106 additions and 69 deletions

View File

@ -6,9 +6,10 @@ module Route.Posts.New exposing (ActionData, Data, route, RouteParams, Msg, Mode
-} -}
import BackendTask import BackendTask exposing (BackendTask)
import BackendTask.Custom
import Date import Date
import Debug import Dict
import Effect import Effect
import ErrorPage import ErrorPage
import FatalError import FatalError
@ -19,11 +20,13 @@ import Form.Validation
import Head import Head
import Html import Html
import Html.Attributes import Html.Attributes
import Json.Decode as Decode
import Json.Encode as Encode
import Pages.Msg import Pages.Msg
import Pages.PageUrl import Pages.PageUrl
import Pages.Script
import Path import Path
import Platform.Sub import Platform.Sub
import Route
import RouteBuilder import RouteBuilder
import Server.Request import Server.Request
import Server.Response import Server.Response
@ -92,7 +95,9 @@ type alias Data =
type alias ActionData = type alias ActionData =
{ errors : Form.Response String } { errors : Form.Response String
, errorMessage : Maybe String
}
data : data :
@ -117,6 +122,20 @@ view maybeUrl sharedModel model app =
{ title = "Posts.New" { title = "Posts.New"
, body = , body =
[ Html.h2 [] [ Html.text "Form" ] [ Html.h2 [] [ Html.text "Form" ]
, app.action
|> Maybe.andThen .errorMessage
|> Maybe.map
(\errorMessage ->
Html.p [ Html.Attributes.style "color" "red" ] [ Html.text errorMessage ]
)
|> Maybe.withDefault (Html.text "")
, app.pageFormState
--|> Debug.toString
|> Dict.get "form"
|> Maybe.andThen (.fields >> Dict.get "body")
|> Maybe.map .value
|> Maybe.withDefault ""
|> Html.text
, Form.renderHtml , Form.renderHtml
[] []
(\renderStyledHtmlUnpack -> Just renderStyledHtmlUnpack.errors) (\renderStyledHtmlUnpack -> Just renderStyledHtmlUnpack.errors)
@ -135,14 +154,34 @@ action routeParams =
(\formData -> (\formData ->
case formData of case formData of
( formResponse, parsedForm ) -> ( formResponse, parsedForm ) ->
BackendTask.map case parsedForm of
(\_ -> Ok okForm ->
Server.Response.render BackendTask.Custom.run "createPost"
{ errors = formResponse } (Encode.object
) [ ( "slug", Encode.string okForm.slug )
(Pages.Script.log , ( "title", Encode.string okForm.title )
(Debug.toString parsedForm) , ( "body", Encode.string okForm.body )
) ]
)
(Decode.oneOf
[ Decode.field "errorMessage" (Decode.string |> Decode.map Err)
, Decode.succeed (Ok ())
]
)
|> BackendTask.allowFatal
|> BackendTask.map
(\result ->
case result of
Ok () ->
Route.redirectTo Route.Index
Err errorMessage ->
Server.Response.render { errors = formResponse, errorMessage = Just errorMessage }
)
Err errors ->
Server.Response.render { errors = formResponse, errorMessage = Nothing }
|> BackendTask.succeed
) )
(Server.Request.formData (Form.initCombined Basics.identity form)) (Server.Request.formData (Form.initCombined Basics.identity form))
@ -155,7 +194,7 @@ form =
"Required" "Required"
(Form.Field.date { invalid = \_ -> "" }) (Form.Field.date { invalid = \_ -> "" })
) )
((\title slug markdown publish -> ((\title slug body publish ->
{ combine = { combine =
ParsedForm ParsedForm
|> Form.Validation.succeed |> Form.Validation.succeed
@ -173,7 +212,7 @@ form =
Form.Validation.mapWithNever identity slug Form.Validation.mapWithNever identity slug
) )
) )
|> Form.Validation.andMap markdown |> Form.Validation.andMap body
|> Form.Validation.andMap publish |> Form.Validation.andMap publish
, view = , view =
\formState -> \formState ->
@ -193,21 +232,33 @@ form =
in in
[ fieldView "title" title [ fieldView "title" title
, fieldView "slug" slug , fieldView "slug" slug
, fieldView "markdown" markdown , fieldView "body" body
, fieldView "publish" publish , fieldView "publish" publish
, Html.button [] [ Html.text "Submit" ] , if formState.isTransitioning then
Html.button [ Html.Attributes.disabled True ]
[ Html.text "Submitting..."
]
else
Html.button []
[ Html.text "Submit"
]
] ]
} }
) )
|> Form.init |> Form.init
|> Form.field "title" (Form.Field.required "Required" Form.Field.text) |> Form.field "title" (Form.Field.required "Required" Form.Field.text)
|> Form.field "slug" (Form.Field.required "Required" Form.Field.text) |> Form.field "slug" (Form.Field.required "Required" Form.Field.text)
|> Form.field "markdown" (Form.Field.required "Required" Form.Field.text |> Form.Field.textarea) |> Form.field "body"
(Form.Field.required "Required" Form.Field.text
|> Form.Field.textarea
{ rows = Just 30, cols = Just 80 }
)
) )
type alias ParsedForm = type alias ParsedForm =
{ title : String, slug : String, markdown : String, publish : Date.Date } { title : String, slug : String, body : String, publish : Date.Date }
errorsView : errorsView :

View File

@ -1,63 +1,49 @@
import kleur from "kleur"; import { PrismaClient } from "@prisma/client";
import fs from "node:fs"; import { PrismaClientKnownRequestError } from "@prisma/client/runtime/index.js";
import path from "node:path";
kleur.enabled = true; const prisma = new PrismaClient();
export async function environmentVariable(name: string) { export async function createPost({ slug, title, body }) {
const result = process.env[name]; try {
if (result) { await prisma.post.create({
return result; data: {
} else { slug,
throw `No environment variable called ${kleur title,
.yellow() body,
.underline(name)}\n\nAvailable:\n\n${Object.keys(process.env) },
.slice(0, 5) });
.join("\n")}`; } catch (e) {
if (e instanceof PrismaClientKnownRequestError) {
console.log("MESSAGE:", e.message, e.meta, e.code, e.name);
console.dir(e);
return { errorMessage: e.message };
// specific error
} else {
console.trace(e);
throw e;
}
} }
} }
export async function hello(name: string) { export async function posts() {
await waitFor(1000); return (await prisma.post.findMany()).map(transformDates);
return `147 ${name}!!`;
} }
function waitFor(ms: number) { function transformDates(item) {
return new Promise((resolve) => setTimeout(resolve, ms)); return Object.fromEntries(
} Object.entries(item).map(([key, value]) => [key, transformValue(value)])
export async function addItem(name: string) {
let timeToWait = 0;
try {
timeToWait = parseInt(name);
} catch (e) {}
console.log("Adding ", name);
await fs.promises.writeFile(path.join(folder, name), "");
await waitFor(timeToWait);
return await listFiles();
}
const folder = "./items-list";
async function listFiles(): Promise<string[]> {
return (await fs.promises.readdir(folder)).filter(
(file) => !file.startsWith(".")
); );
} }
export async function getItems() { function transformValue(value) {
return await listFiles(); // if (typeof value === "bigint") {
} // obj[key] = toNumber(value);
// }
export async function deleteAllItems(name: string) { if (value instanceof Date) {
for (const file of await listFiles()) { return value.getMilliseconds();
await fs.promises.unlink(path.join(folder, file)); } else {
return value;
} }
return await listFiles();
}
export async function log(message: string) {
console.log(message);
return null;
} }