feat: ability to delete a project (#37)
This commit is contained in:
commit
1c0b3a4196
@ -6,6 +6,6 @@ CREATE TABLE "tasks"(
|
|||||||
"deadline" DATE,
|
"deadline" DATE,
|
||||||
"category" JSONB NOT NULL,
|
"category" JSONB NOT NULL,
|
||||||
"project_id" INT4,
|
"project_id" INT4,
|
||||||
FOREIGN KEY ("project_id") REFERENCES "projects"("id")
|
FOREIGN KEY ("project_id") REFERENCES "projects"("id") ON DELETE SET NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::models::project::{NewProject, Project};
|
use crate::models::project::{NewProject, Project};
|
||||||
use crate::server::projects::{create_project, edit_project};
|
use crate::query::{QueryErrors, QueryKey, QueryValue};
|
||||||
|
use crate::server::projects::{create_project, delete_project, edit_project};
|
||||||
use dioxus::core_macro::{component, rsx};
|
use dioxus::core_macro::{component, rsx};
|
||||||
use dioxus::dioxus_core::Element;
|
use dioxus::dioxus_core::Element;
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
use dioxus_query::prelude::use_query_client;
|
use dioxus_query::prelude::use_query_client;
|
||||||
use crate::query::{QueryErrors, QueryKey, QueryValue};
|
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
pub(crate) fn ProjectForm(project: Option<Project>, on_successful_submit: EventHandler<()>)
|
pub(crate) fn ProjectForm(project: Option<Project>, on_successful_submit: EventHandler<()>)
|
||||||
@ -25,9 +25,7 @@ pub(crate) fn ProjectForm(project: Option<Project>, on_successful_submit: EventH
|
|||||||
} else {
|
} else {
|
||||||
let _ = create_project(new_project).await;
|
let _ = create_project(new_project).await;
|
||||||
}
|
}
|
||||||
query_client.invalidate_queries(&[
|
query_client.invalidate_queries(&[QueryKey::Projects]);
|
||||||
QueryKey::Projects
|
|
||||||
]);
|
|
||||||
on_successful_submit.call(());
|
on_successful_submit.call(());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -44,14 +42,31 @@ pub(crate) fn ProjectForm(project: Option<Project>, on_successful_submit: EventH
|
|||||||
input {
|
input {
|
||||||
name: "title",
|
name: "title",
|
||||||
required: true,
|
required: true,
|
||||||
initial_value: project.map(|project| project.title().to_owned()),
|
initial_value: project.as_ref().map(|project| project.title().to_owned()),
|
||||||
r#type: "text",
|
r#type: "text",
|
||||||
class: "py-2 px-3 grow bg-zinc-800/50 rounded-lg",
|
class: "py-2 px-3 grow bg-zinc-800/50 rounded-lg",
|
||||||
id: "input_title"
|
id: "input_title"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div {
|
div {
|
||||||
class: "flex flex-row justify-end mt-auto",
|
class: "flex flex-row justify-between mt-auto",
|
||||||
|
button {
|
||||||
|
r#type: "button",
|
||||||
|
class: "py-2 px-4 bg-zinc-300/50 rounded-lg",
|
||||||
|
onclick: move |_| {
|
||||||
|
let project = project.clone();
|
||||||
|
async move {
|
||||||
|
if let Some(project) = project {
|
||||||
|
let _ = delete_project(project.id()).await;
|
||||||
|
query_client.invalidate_queries(&[QueryKey::Projects]);
|
||||||
|
}
|
||||||
|
on_successful_submit.call(());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
i {
|
||||||
|
class: "fa-solid fa-trash-can"
|
||||||
|
}
|
||||||
|
}
|
||||||
button {
|
button {
|
||||||
r#type: "submit",
|
r#type: "submit",
|
||||||
class: "py-2 px-4 bg-zinc-300/50 rounded-lg",
|
class: "py-2 px-4 bg-zinc-300/50 rounded-lg",
|
||||||
|
@ -7,11 +7,17 @@ pub enum Error {
|
|||||||
ServerInternal,
|
ServerInternal,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<diesel::result::Error> for Error {
|
||||||
|
fn from(_: diesel::result::Error) -> Self {
|
||||||
|
Self::ServerInternal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// has to be implemented for Dioxus server functions
|
// has to be implemented for Dioxus server functions
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Error::ServerInternal => write!(f, "internal server error"),
|
Self::ServerInternal => write!(f, "internal server error"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -22,7 +28,7 @@ impl FromStr for Error {
|
|||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
Ok(match s {
|
Ok(match s {
|
||||||
"internal server error" => Error::ServerInternal,
|
"internal server error" => Self::ServerInternal,
|
||||||
_ => return Err(()),
|
_ => return Err(()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ impl From<ValidationErrors> for ErrorVec<ProjectError> {
|
|||||||
|
|
||||||
impl From<diesel::result::Error> for ProjectError {
|
impl From<diesel::result::Error> for ProjectError {
|
||||||
fn from(_: diesel::result::Error) -> Self {
|
fn from(_: diesel::result::Error) -> Self {
|
||||||
ProjectError::Error(Error::ServerInternal)
|
Self::Error(Error::ServerInternal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +52,6 @@ impl FromStr for ProjectError {
|
|||||||
type Err = ();
|
type Err = ();
|
||||||
|
|
||||||
fn from_str(_: &str) -> Result<Self, Self::Err> {
|
fn from_str(_: &str) -> Result<Self, Self::Err> {
|
||||||
Ok(ProjectError::Error(Error::ServerInternal))
|
Ok(Self::Error(Error::ServerInternal))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,12 +42,12 @@ impl From<diesel::result::Error> for TaskError {
|
|||||||
diesel::result::DatabaseErrorKind::ForeignKeyViolation, info
|
diesel::result::DatabaseErrorKind::ForeignKeyViolation, info
|
||||||
) => {
|
) => {
|
||||||
match info.constraint_name() {
|
match info.constraint_name() {
|
||||||
Some("tasks_project_id_fkey") => TaskError::ProjectNotFound,
|
Some("tasks_project_id_fkey") => Self::ProjectNotFound,
|
||||||
_ => TaskError::Error(Error::ServerInternal)
|
_ => Self::Error(Error::ServerInternal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
TaskError::Error(Error::ServerInternal)
|
Self::Error(Error::ServerInternal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,6 +65,6 @@ impl FromStr for TaskError {
|
|||||||
type Err = ();
|
type Err = ();
|
||||||
|
|
||||||
fn from_str(_: &str) -> Result<Self, Self::Err> {
|
fn from_str(_: &str) -> Result<Self, Self::Err> {
|
||||||
Ok(TaskError::Error(Error::ServerInternal))
|
Ok(Self::Error(Error::ServerInternal))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,3 +71,17 @@ pub(crate) async fn edit_project(project_id: i32, new_project: NewProject)
|
|||||||
|
|
||||||
Ok(updated_project)
|
Ok(updated_project)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[server]
|
||||||
|
pub(crate) async fn delete_project(project_id: i32)
|
||||||
|
-> Result<(), ServerFnError<ErrorVec<Error>>> {
|
||||||
|
use crate::schema::projects::dsl::*;
|
||||||
|
|
||||||
|
let mut connection = establish_database_connection()
|
||||||
|
.map_err::<ErrorVec<Error>, _>(|_| vec![Error::ServerInternal].into())?;
|
||||||
|
|
||||||
|
diesel::delete(projects.filter(id.eq(project_id))).execute(&mut connection)
|
||||||
|
.map_err::<ErrorVec<Error>, _>(|error| vec![error.into()].into())?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user