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 Debug
import Dict
import Effect
import ErrorPage
import FatalError
@ -19,11 +20,13 @@ import Form.Validation
import Head
import Html
import Html.Attributes
import Json.Decode as Decode
import Json.Encode as Encode
import Pages.Msg
import Pages.PageUrl
import Pages.Script
import Path
import Platform.Sub
import Route
import RouteBuilder
import Server.Request
import Server.Response
@ -92,7 +95,9 @@ type alias Data =
type alias ActionData =
{ errors : Form.Response String }
{ errors : Form.Response String
, errorMessage : Maybe String
}
data :
@ -117,6 +122,20 @@ view maybeUrl sharedModel model app =
{ title = "Posts.New"
, body =
[ 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
[]
(\renderStyledHtmlUnpack -> Just renderStyledHtmlUnpack.errors)
@ -135,14 +154,34 @@ action routeParams =
(\formData ->
case formData of
( formResponse, parsedForm ) ->
BackendTask.map
(\_ ->
Server.Response.render
{ errors = formResponse }
)
(Pages.Script.log
(Debug.toString parsedForm)
)
case parsedForm of
Ok okForm ->
BackendTask.Custom.run "createPost"
(Encode.object
[ ( "slug", Encode.string okForm.slug )
, ( "title", Encode.string okForm.title )
, ( "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))
@ -155,7 +194,7 @@ form =
"Required"
(Form.Field.date { invalid = \_ -> "" })
)
((\title slug markdown publish ->
((\title slug body publish ->
{ combine =
ParsedForm
|> Form.Validation.succeed
@ -173,7 +212,7 @@ form =
Form.Validation.mapWithNever identity slug
)
)
|> Form.Validation.andMap markdown
|> Form.Validation.andMap body
|> Form.Validation.andMap publish
, view =
\formState ->
@ -193,21 +232,33 @@ form =
in
[ fieldView "title" title
, fieldView "slug" slug
, fieldView "markdown" markdown
, fieldView "body" body
, 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.field "title" (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 =
{ title : String, slug : String, markdown : String, publish : Date.Date }
{ title : String, slug : String, body : String, publish : Date.Date }
errorsView :

View File

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