mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 21:42:34 +00:00
frontend: Add form to create addressbook
This commit is contained in:
@@ -108,48 +108,51 @@
|
|||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h3>Create calendar</h3>
|
<section>
|
||||||
<form action="/frontend/user/{{ user.id }}/calendar" method="POST">
|
<h3>Create calendar</h3>
|
||||||
<label>
|
<form action="/frontend/user/{{ user.id }}/calendar" method="POST">
|
||||||
href
|
<label>
|
||||||
<input type="text" name="id" />
|
href
|
||||||
</label>
|
<input type="text" name="id" />
|
||||||
<br>
|
</label>
|
||||||
<label>
|
<br>
|
||||||
Displayname
|
<label>
|
||||||
<input type="text" name="displayname" />
|
Displayname
|
||||||
</label>
|
<input type="text" name="displayname" />
|
||||||
<br>
|
</label>
|
||||||
<label>
|
<br>
|
||||||
Description
|
<label>
|
||||||
<input type="text" name="description" />
|
Description
|
||||||
</label>
|
<input type="text" name="description" />
|
||||||
<br>
|
</label>
|
||||||
<label>
|
<br>
|
||||||
Color
|
<label>
|
||||||
<input type="color" name="color" />
|
Color
|
||||||
</label>
|
<input type="color" name="color" />
|
||||||
<br>
|
</label>
|
||||||
<label>
|
<br>
|
||||||
Subscription URL
|
<label>
|
||||||
<input type="text" name="subscription_url" />
|
Subscription URL
|
||||||
</label>
|
<input type="text" name="subscription_url" />
|
||||||
<br>
|
</label>
|
||||||
<label>
|
<br>
|
||||||
Support VEVENT
|
<label>
|
||||||
<input type="checkbox" name="comp_event" checked />
|
Support VEVENT
|
||||||
</label>
|
<input type="checkbox" name="comp_event" checked />
|
||||||
<label>
|
</label>
|
||||||
Support VTODO
|
<label>
|
||||||
<input type="checkbox" name="comp_todo" checked />
|
Support VTODO
|
||||||
</label>
|
<input type="checkbox" name="comp_todo" checked />
|
||||||
<label>
|
</label>
|
||||||
Support VJOURNAL
|
<label>
|
||||||
<input type="checkbox" name="comp_journal" />
|
Support VJOURNAL
|
||||||
</label>
|
<input type="checkbox" name="comp_journal" />
|
||||||
<br>
|
</label>
|
||||||
<button type="submit">Create</button>
|
<br>
|
||||||
</form>
|
<button type="submit">Create</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
@@ -186,6 +189,29 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>Create addressbook</h3>
|
||||||
|
<form action="/frontend/user/{{ user.id }}/addressbook" method="POST">
|
||||||
|
<label>
|
||||||
|
href
|
||||||
|
<input type="text" name="id" />
|
||||||
|
</label>
|
||||||
|
<br>
|
||||||
|
<label>
|
||||||
|
Displayname
|
||||||
|
<input type="text" name="displayname" />
|
||||||
|
</label>
|
||||||
|
<br>
|
||||||
|
<label>
|
||||||
|
Description
|
||||||
|
<input type="text" name="description" />
|
||||||
|
</label>
|
||||||
|
<br>
|
||||||
|
<button type="submit">Create</button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ use oidc_user_store::OidcUserStore;
|
|||||||
use crate::{
|
use crate::{
|
||||||
assets::{Assets, EmbedService},
|
assets::{Assets, EmbedService},
|
||||||
routes::{
|
routes::{
|
||||||
addressbook::{route_addressbook, route_addressbook_restore},
|
addressbook::{route_addressbook, route_addressbook_restore, route_create_addressbook},
|
||||||
app_token::{route_delete_app_token, route_post_app_token},
|
app_token::{route_delete_app_token, route_post_app_token},
|
||||||
calendar::{route_calendar, route_calendar_restore, route_create_calendar},
|
calendar::{route_calendar, route_calendar_restore, route_create_calendar},
|
||||||
login::{route_get_login, route_post_login, route_post_logout},
|
login::{route_get_login, route_post_login, route_post_logout},
|
||||||
@@ -76,6 +76,10 @@ pub fn frontend_router<
|
|||||||
post(route_calendar_restore::<CS>),
|
post(route_calendar_restore::<CS>),
|
||||||
)
|
)
|
||||||
// Addressbook
|
// Addressbook
|
||||||
|
.route(
|
||||||
|
"/user/{user}/addressbook",
|
||||||
|
post(route_create_addressbook::<AS>),
|
||||||
|
)
|
||||||
.route(
|
.route(
|
||||||
"/user/{user}/addressbook/{addressbook}",
|
"/user/{user}/addressbook/{addressbook}",
|
||||||
get(route_addressbook::<AS>),
|
get(route_addressbook::<AS>),
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::sync::Arc;
|
|||||||
use askama::Template;
|
use askama::Template;
|
||||||
use askama_web::WebTemplate;
|
use askama_web::WebTemplate;
|
||||||
use axum::{
|
use axum::{
|
||||||
Extension,
|
Extension, Form,
|
||||||
extract::Path,
|
extract::Path,
|
||||||
response::{IntoResponse, Redirect, Response},
|
response::{IntoResponse, Redirect, Response},
|
||||||
};
|
};
|
||||||
@@ -11,6 +11,7 @@ use axum_extra::TypedHeader;
|
|||||||
use headers::Referer;
|
use headers::Referer;
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
use rustical_store::{Addressbook, AddressbookStore, auth::User};
|
use rustical_store::{Addressbook, AddressbookStore, auth::User};
|
||||||
|
use serde::{Deserialize, Deserializer};
|
||||||
|
|
||||||
#[derive(Template, WebTemplate)]
|
#[derive(Template, WebTemplate)]
|
||||||
#[template(path = "pages/addressbook.html")]
|
#[template(path = "pages/addressbook.html")]
|
||||||
@@ -32,6 +33,53 @@ pub async fn route_addressbook<AS: AddressbookStore>(
|
|||||||
.into_response())
|
.into_response())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn empty_to_none<'de, D>(deserializer: D) -> Result<Option<String>, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let val: Option<String> = Deserialize::deserialize(deserializer)?;
|
||||||
|
Ok(val.filter(|val| !val.is_empty()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Clone)]
|
||||||
|
pub struct PutAddressbookForm {
|
||||||
|
id: String,
|
||||||
|
#[serde(deserialize_with = "empty_to_none")]
|
||||||
|
displayname: Option<String>,
|
||||||
|
#[serde(deserialize_with = "empty_to_none")]
|
||||||
|
description: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn route_create_addressbook<AS: AddressbookStore>(
|
||||||
|
Path(owner): Path<String>,
|
||||||
|
Extension(store): Extension<Arc<AS>>,
|
||||||
|
user: User,
|
||||||
|
Form(PutAddressbookForm {
|
||||||
|
id,
|
||||||
|
displayname,
|
||||||
|
description,
|
||||||
|
}): Form<PutAddressbookForm>,
|
||||||
|
) -> Result<Response, rustical_store::Error> {
|
||||||
|
if !user.is_principal(&owner) {
|
||||||
|
return Ok(StatusCode::UNAUTHORIZED.into_response());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(!id.is_empty());
|
||||||
|
|
||||||
|
let addressbook = Addressbook {
|
||||||
|
id: id.to_owned(),
|
||||||
|
displayname,
|
||||||
|
description,
|
||||||
|
principal: user.id.to_owned(),
|
||||||
|
synctoken: 0,
|
||||||
|
deleted_at: None,
|
||||||
|
push_topic: uuid::Uuid::new_v4().to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
store.insert_addressbook(addressbook).await?;
|
||||||
|
Ok(Redirect::to(&format!("/frontend/user/{}/addressbook/{}", user.id, id)).into_response())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn route_addressbook_restore<AS: AddressbookStore>(
|
pub async fn route_addressbook_restore<AS: AddressbookStore>(
|
||||||
Path((owner, addressbook_id)): Path<(String, String)>,
|
Path((owner, addressbook_id)): Path<(String, String)>,
|
||||||
Extension(store): Extension<Arc<AS>>,
|
Extension(store): Extension<Arc<AS>>,
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ pub async fn route_create_calendar<C: CalendarStore>(
|
|||||||
description,
|
description,
|
||||||
color,
|
color,
|
||||||
subscription_url,
|
subscription_url,
|
||||||
principal: user.id,
|
principal: user.id.to_owned(),
|
||||||
components: comps,
|
components: comps,
|
||||||
order: 0,
|
order: 0,
|
||||||
timezone_id: None,
|
timezone_id: None,
|
||||||
@@ -107,7 +107,7 @@ pub async fn route_create_calendar<C: CalendarStore>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
store.insert_calendar(cal).await?;
|
store.insert_calendar(cal).await?;
|
||||||
Ok(Redirect::to(&id).into_response())
|
Ok(Redirect::to(&format!("/frontend/user/{}/calendar/{}", user.id, id)).into_response())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn route_calendar_restore<CS: CalendarStore>(
|
pub async fn route_calendar_restore<CS: CalendarStore>(
|
||||||
|
|||||||
Reference in New Issue
Block a user