Add the ability to delete tasks.
This commit is contained in:
parent
c07df0b094
commit
d87c2e8922
|
@ -44,7 +44,12 @@ type Status a
|
||||||
|
|
||||||
init : Nav.Key -> ( Model, Cmd Msg )
|
init : Nav.Key -> ( Model, Cmd Msg )
|
||||||
init navKey =
|
init navKey =
|
||||||
( Model navKey Loading True defaultCreateTask
|
reloadTasks (Model navKey Loading True defaultCreateTask)
|
||||||
|
|
||||||
|
|
||||||
|
reloadTasks : Model -> ( Model, Cmd Msg )
|
||||||
|
reloadTasks model =
|
||||||
|
( model
|
||||||
, Http.get
|
, Http.get
|
||||||
{ url = "http://localhost:3000/tasks"
|
{ url = "http://localhost:3000/tasks"
|
||||||
, expect = Http.expectJson GotTasks (list taskDecoder)
|
, expect = Http.expectJson GotTasks (list taskDecoder)
|
||||||
|
@ -55,10 +60,12 @@ init navKey =
|
||||||
type Msg
|
type Msg
|
||||||
= GotTasks (Result Http.Error (List Task))
|
= GotTasks (Result Http.Error (List Task))
|
||||||
| ToggleCreateTask
|
| ToggleCreateTask
|
||||||
| CreateTask
|
|
||||||
| GotTaskCreated (Result Http.Error Task)
|
|
||||||
| CreateTaskUpdateTitle String
|
| CreateTaskUpdateTitle String
|
||||||
| CreateTaskUpdateDescription String
|
| CreateTaskUpdateDescription String
|
||||||
|
| CreateTask
|
||||||
|
| GotTaskCreated (Result Http.Error Task)
|
||||||
|
| DeleteTask Int
|
||||||
|
| GotTaskDeleted (Result Http.Error ())
|
||||||
|
|
||||||
|
|
||||||
update : Msg -> Model -> ( Model, Cmd Msg )
|
update : Msg -> Model -> ( Model, Cmd Msg )
|
||||||
|
@ -113,6 +120,22 @@ update msg model =
|
||||||
in
|
in
|
||||||
( { model | createTask = { createTask | description = description } }, Cmd.none )
|
( { model | createTask = { createTask | description = description } }, Cmd.none )
|
||||||
|
|
||||||
|
DeleteTask id ->
|
||||||
|
( model
|
||||||
|
, Http.request
|
||||||
|
{ method = "DELETE"
|
||||||
|
, headers = []
|
||||||
|
, url = "http://localhost:3000/tasks/" ++ String.fromInt id
|
||||||
|
, body = Http.emptyBody
|
||||||
|
, expect = Http.expectWhatever GotTaskDeleted
|
||||||
|
, timeout = Nothing
|
||||||
|
, tracker = Nothing
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
GotTaskDeleted _ ->
|
||||||
|
reloadTasks model
|
||||||
|
|
||||||
|
|
||||||
taskDecoder : Decoder Task
|
taskDecoder : Decoder Task
|
||||||
taskDecoder =
|
taskDecoder =
|
||||||
|
@ -186,6 +209,7 @@ viewTaskListItem task =
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
, button [ onClick (DeleteTask task.id) ] [ text "Delete Task" ]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod routes;
|
||||||
|
|
||||||
use axum::http::{StatusCode, Uri};
|
use axum::http::{StatusCode, Uri};
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
use axum::routing::get;
|
use axum::routing::{delete, get};
|
||||||
use dotenvy::dotenv;
|
use dotenvy::dotenv;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
|
|
||||||
|
@ -28,6 +28,10 @@ async fn main() {
|
||||||
.post(routes::tasks::create)
|
.post(routes::tasks::create)
|
||||||
.options(routes::tasks::options),
|
.options(routes::tasks::options),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
"/tasks/:task_id",
|
||||||
|
delete(routes::tasks::delete).options(routes::tasks::options),
|
||||||
|
)
|
||||||
.with_state(state);
|
.with_state(state);
|
||||||
|
|
||||||
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{FromRow, SqlitePool};
|
use sqlx::{sqlite::SqliteQueryResult, FromRow, SqlitePool};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, FromRow)]
|
#[derive(Serialize, Deserialize, FromRow)]
|
||||||
pub struct Task {
|
pub struct Task {
|
||||||
|
@ -32,4 +32,10 @@ impl Task {
|
||||||
.fetch_one(pool)
|
.fetch_one(pool)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn delete(pool: &SqlitePool, id: i64) -> Result<SqliteQueryResult, sqlx::Error> {
|
||||||
|
sqlx::query!("DELETE FROM task WHERE id = ?1", id)
|
||||||
|
.execute(pool)
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
use std::collections::HashMap;
|
use axum::extract::{Json, Path, State};
|
||||||
|
|
||||||
use axum::extract::{Json, State};
|
|
||||||
use axum::http::header;
|
use axum::http::header;
|
||||||
use axum::http::StatusCode;
|
use axum::http::StatusCode;
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
|
@ -59,9 +57,22 @@ pub async fn options() -> impl IntoResponse {
|
||||||
StatusCode::OK,
|
StatusCode::OK,
|
||||||
[
|
[
|
||||||
(header::ACCESS_CONTROL_ALLOW_ORIGIN, "*"),
|
(header::ACCESS_CONTROL_ALLOW_ORIGIN, "*"),
|
||||||
(header::ACCESS_CONTROL_ALLOW_METHODS, "POST, GET, OPTIONS"),
|
(
|
||||||
|
header::ACCESS_CONTROL_ALLOW_METHODS,
|
||||||
|
"POST, GET, OPTIONS, DELETE",
|
||||||
|
),
|
||||||
(header::ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type"),
|
(header::ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type"),
|
||||||
(header::ACCESS_CONTROL_MAX_AGE, "86400"),
|
(header::ACCESS_CONTROL_MAX_AGE, "86400"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn delete(state: State<AppState>, Path(id): Path<i64>) -> impl IntoResponse {
|
||||||
|
Task::delete(&state.db_pool, id).await.unwrap();
|
||||||
|
|
||||||
|
(
|
||||||
|
StatusCode::OK,
|
||||||
|
[(header::ACCESS_CONTROL_ALLOW_ORIGIN, "*")],
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue