frontend: Show group calendars

This commit is contained in:
Lennart
2025-04-12 13:13:16 +02:00
parent 30b0bf5b56
commit 63c16f411d
5 changed files with 22 additions and 35 deletions

27
Cargo.lock generated
View File

@@ -868,20 +868,6 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "dashmap"
version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
dependencies = [
"cfg-if",
"crossbeam-utils",
"hashbrown 0.14.5",
"lock_api",
"once_cell",
"parking_lot_core",
]
[[package]] [[package]]
name = "der" name = "der"
version = "0.7.9" version = "0.7.9"
@@ -1278,12 +1264,6 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.15.2" version = "0.15.2"
@@ -1301,7 +1281,7 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
dependencies = [ dependencies = [
"hashbrown 0.15.2", "hashbrown",
] ]
[[package]] [[package]]
@@ -1653,7 +1633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.15.2", "hashbrown",
] ]
[[package]] [[package]]
@@ -2742,7 +2722,6 @@ dependencies = [
"argon2", "argon2",
"async-trait", "async-trait",
"clap", "clap",
"dashmap",
"figment", "figment",
"opentelemetry", "opentelemetry",
"opentelemetry-otlp", "opentelemetry-otlp",
@@ -3215,7 +3194,7 @@ dependencies = [
"futures-intrusive", "futures-intrusive",
"futures-io", "futures-io",
"futures-util", "futures-util",
"hashbrown 0.15.2", "hashbrown",
"hashlink", "hashlink",
"indexmap", "indexmap",
"log", "log",

View File

@@ -110,7 +110,6 @@ reqwest = { version = "0.12", features = [
"charset", "charset",
"http2", "http2",
], default-features = false } ], default-features = false }
dashmap = "6.1"
[dependencies] [dependencies]
rustical_store = { workspace = true } rustical_store = { workspace = true }
@@ -129,7 +128,6 @@ sqlx = { workspace = true }
async-trait = { workspace = true } async-trait = { workspace = true }
tracing-actix-web = { workspace = true } tracing-actix-web = { workspace = true }
uuid.workspace = true uuid.workspace = true
dashmap.workspace = true
opentelemetry = { version = "0.29", optional = true } opentelemetry = { version = "0.29", optional = true }
opentelemetry-otlp = { version = "0.29", optional = true } opentelemetry-otlp = { version = "0.29", optional = true }

View File

@@ -60,7 +60,7 @@ li.collection-list-item {
{% for calendar in calendars %} {% for calendar in calendars %}
{% let color = calendar.color.to_owned().unwrap_or("red".to_owned()) %} {% let color = calendar.color.to_owned().unwrap_or("red".to_owned()) %}
<li class="collection-list-item" style="--color: {{ color }}"> <li class="collection-list-item" style="--color: {{ color }}">
<a href="/frontend/user/{{ user_id }}/calendar/{{ calendar.id}}"> <a href="/frontend/user/{{ calendar.principal }}/calendar/{{ calendar.id}}">
<span class="title">{{ calendar.displayname.to_owned().unwrap_or(calendar.id.to_owned()) }}</span> <span class="title">{{ calendar.displayname.to_owned().unwrap_or(calendar.id.to_owned()) }}</span>
<span class="description"> <span class="description">
{% if let Some(description) = calendar.description %}{{ description }}{% endif %} {% if let Some(description) = calendar.description %}{{ description }}{% endif %}
@@ -71,6 +71,8 @@ li.collection-list-item {
<div class="color-chip"></div> <div class="color-chip"></div>
</a> </a>
</li> </li>
{% else %}
You do not have any calendars yet
{% endfor %} {% endfor %}
</ul> </ul>
{%if !deleted_calendars.is_empty() %} {%if !deleted_calendars.is_empty() %}
@@ -79,7 +81,7 @@ li.collection-list-item {
{% for calendar in deleted_calendars %} {% for calendar in deleted_calendars %}
{% let color = calendar.color.to_owned().unwrap_or("red".to_owned()) %} {% let color = calendar.color.to_owned().unwrap_or("red".to_owned()) %}
<li class="collection-list-item" style="--color: {{ color }}"> <li class="collection-list-item" style="--color: {{ color }}">
<a href="/frontend/user/{{ user_id }}/calendar/{{ calendar.id}}"> <a href="/frontend/user/{{ calendar.principal }}/calendar/{{ calendar.id}}">
<span class="title">{{ calendar.displayname.to_owned().unwrap_or(calendar.id.to_owned()) }}</span> <span class="title">{{ calendar.displayname.to_owned().unwrap_or(calendar.id.to_owned()) }}</span>
<span class="description"> <span class="description">
{% if let Some(description) = calendar.description %}{{ description }}{% endif %} {% if let Some(description) = calendar.description %}{{ description }}{% endif %}
@@ -98,13 +100,15 @@ li.collection-list-item {
<ul> <ul>
{% for addressbook in addressbooks %} {% for addressbook in addressbooks %}
<li class="collection-list-item"> <li class="collection-list-item">
<a href="/frontend/user/{{ user_id }}/addressbook/{{ addressbook.id}}"> <a href="/frontend/user/{{ addressbook.principal }}/addressbook/{{ addressbook.id}}">
<span class="title">{{ addressbook.displayname.to_owned().unwrap_or(addressbook.id.to_owned()) }}</span> <span class="title">{{ addressbook.displayname.to_owned().unwrap_or(addressbook.id.to_owned()) }}</span>
<span class="description"> <span class="description">
{% if let Some(description) = addressbook.description %}{{ description }}{% endif %} {% if let Some(description) = addressbook.description %}{{ description }}{% endif %}
</span> </span>
</a> </a>
</li> </li>
{% else %}
You do not have any addressbooks yet
{% endfor %} {% endfor %}
</ul> </ul>
{%if !deleted_addressbooks.is_empty() %} {%if !deleted_addressbooks.is_empty() %}
@@ -112,7 +116,7 @@ li.collection-list-item {
<ul> <ul>
{% for addressbook in deleted_addressbooks %} {% for addressbook in deleted_addressbooks %}
<li class="collection-list-item"> <li class="collection-list-item">
<a href="/frontend/user/{{ user_id }}/addressbook/{{ addressbook.id}}"> <a href="/frontend/user/{{ addressbook.principal }}/addressbook/{{ addressbook.id}}">
<span class="title">{{ addressbook.displayname.to_owned().unwrap_or(addressbook.id.to_owned()) }}</span> <span class="title">{{ addressbook.displayname.to_owned().unwrap_or(addressbook.id.to_owned()) }}</span>
<span class="description"> <span class="description">
{% if let Some(description) = addressbook.description %}{{ description }}{% endif %} {% if let Some(description) = addressbook.description %}{{ description }}{% endif %}

View File

@@ -51,9 +51,15 @@ async fn route_user<CS: CalendarStore, AS: AddressbookStore>(
if user_id != user.id { if user_id != user.id {
return actix_web::HttpResponse::Unauthorized().body("Unauthorized"); return actix_web::HttpResponse::Unauthorized().body("Unauthorized");
} }
dbg!(&user);
let mut calendars = vec![];
for group in user.memberships() {
calendars.extend(cal_store.get_calendars(group).await.unwrap());
}
UserPage { UserPage {
calendars: cal_store.get_calendars(&user.id).await.unwrap(), calendars,
deleted_calendars: cal_store.get_deleted_calendars(&user.id).await.unwrap(), deleted_calendars: cal_store.get_deleted_calendars(&user.id).await.unwrap(),
addressbooks: addr_store.get_addressbooks(&user.id).await.unwrap(), addressbooks: addr_store.get_addressbooks(&user.id).await.unwrap(),
deleted_addressbooks: addr_store.get_deleted_addressbooks(&user.id).await.unwrap(), deleted_addressbooks: addr_store.get_deleted_addressbooks(&user.id).await.unwrap(),

View File

@@ -1,13 +1,13 @@
use actix_web::{ use actix_web::{
body::BoxBody,
http::{header, StatusCode},
FromRequest, HttpMessage, HttpResponse, ResponseError, FromRequest, HttpMessage, HttpResponse, ResponseError,
body::BoxBody,
http::{StatusCode, header},
}; };
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use derive_more::Display; use derive_more::Display;
use rustical_xml::ValueSerialize; use rustical_xml::ValueSerialize;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::future::{ready, Ready}; use std::future::{Ready, ready};
/// https://datatracker.ietf.org/doc/html/rfc5545#section-3.2.3 /// https://datatracker.ietf.org/doc/html/rfc5545#section-3.2.3
#[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)] #[derive(Debug, Clone, Deserialize, Serialize, Default, PartialEq)]
@@ -54,7 +54,7 @@ pub struct User {
#[serde(default)] #[serde(default)]
pub app_tokens: Vec<AppToken>, pub app_tokens: Vec<AppToken>,
#[serde(default)] #[serde(default)]
pub memberships: Vec<String>, memberships: Vec<String>,
} }
impl User { impl User {