frontend: Add basic information about collections

This commit is contained in:
Lennart K
2025-07-04 20:54:37 +02:00
parent 32f5c01716
commit 6bcc03d659
13 changed files with 219 additions and 22 deletions

View File

@@ -202,14 +202,16 @@ ul.collection-list {
background: color-mix(in srgb, var(--background-color), var(--dilute-color) 5%);
display: grid;
min-height: 80px;
height: fit-content;
grid-template-areas:
". . color-chip"
"title comps color-chip"
"description description color-chip"
"subscription-url subscription-url color-chip"
"metadata metadata color-chip"
"actions actions color-chip"
". . color-chip";
grid-template-rows: 12px auto auto auto auto 12px;
grid-template-rows: 12px auto auto auto auto auto 12px;
grid-template-columns: min-content auto 80px;
row-gap: 4px;
color: inherit;
@@ -251,6 +253,11 @@ ul.collection-list {
white-space: nowrap;
}
.metadata {
grid-area: metadata;
white-space: nowrap;
}
.subscription-url {
grid-area: subscription-url;
white-space: nowrap;

View File

@@ -1,6 +1,6 @@
<h2>{{user.id }}'s Addressbooks</h2>
<ul class="collection-list">
{% for addressbook in addressbooks %}
{% for (meta, addressbook) in addressbooks %}
<li class="collection-list-item">
<a href="/frontend/user/{{ addressbook.principal }}/addressbook/{{ addressbook.id}}">
<span class="title">
@@ -18,6 +18,9 @@
<delete-button trash
href="/carddav/principal/{{ addressbook.principal }}/{{ addressbook.id }}"></delete-button>
</div>
<div class="metadata">
{{ meta.len }} objects, {{ meta.deleted_len }} deleted objects
</div>
</a>
</li>
{% else %}
@@ -27,7 +30,7 @@
{%if !deleted_addressbooks.is_empty() %}
<h3>Deleted Addressbooks</h3>
<ul class="collection-list">
{% for addressbook in deleted_addressbooks %}
{% for (meta, addressbook) in deleted_addressbooks %}
<li class="collection-list-item">
<a href="/frontend/user/{{ addressbook.principal }}/addressbook/{{ addressbook.id}}">
<span class="title">
@@ -44,6 +47,9 @@
</form>
<delete-button href="/carddav/principal/{{ addressbook.principal }}/{{ addressbook.id }}"></delete-button>
</div>
<div class="metadata">
{{ meta.len }} objects, {{ meta.deleted_len }} deleted objects
</div>
</a>
</li>
{% endfor %}

View File

@@ -1,6 +1,6 @@
<h2>{{ user.id }}'s Calendars</h2>
<ul class="collection-list">
{% for calendar in calendars %}
{% for (meta, calendar) in calendars %}
{% let color = calendar.color.to_owned().unwrap_or("transparent".to_owned()) %}
<li class="collection-list-item" style="--color: {{ color }}">
<a href="/frontend/user/{{ calendar.principal }}/calendar/{{ calendar.id }}">
@@ -27,6 +27,9 @@
<delete-button trash href="/caldav/principal/{{ calendar.principal }}/{{ calendar.id }}"></delete-button>
{% endif %}
</div>
<div class="metadata">
{{ meta.len }} objects, {{ meta.deleted_len }} deleted objects
</div>
<div class="color-chip"></div>
</a>
</li>
@@ -37,7 +40,7 @@
{%if !deleted_calendars.is_empty() %}
<h3>Deleted Calendars</h3>
<ul class="collection-list">
{% for calendar in deleted_calendars %}
{% for (meta, calendar) in deleted_calendars %}
{% let color = calendar.color.to_owned().unwrap_or("transparent".to_owned()) %}
<li class="collection-list-item" style="--color: {{ color }}">
<a href="/frontend/user/{{ calendar.principal }}/calendar/{{ calendar.id}}">
@@ -60,6 +63,9 @@
</form>
<delete-button href="/caldav/principal/{{ calendar.principal }}/{{ calendar.id }}"></delete-button>
</div>
<div class="metadata">
{{ meta.len }} objects, {{ meta.deleted_len }} deleted objects
</div>
<div class="color-chip"></div>
</a>
</li>

View File

@@ -4,7 +4,7 @@ use askama::Template;
use askama_web::WebTemplate;
use axum::{Extension, extract::Path, response::IntoResponse};
use http::StatusCode;
use rustical_store::{Addressbook, AddressbookStore, auth::Principal};
use rustical_store::{Addressbook, AddressbookStore, CollectionMetadata, auth::Principal};
use crate::pages::user::{Section, UserPage};
@@ -18,8 +18,8 @@ impl Section for AddressbooksSection {
#[template(path = "components/sections/addressbooks_section.html")]
pub struct AddressbooksSection {
pub user: Principal,
pub addressbooks: Vec<Addressbook>,
pub deleted_addressbooks: Vec<Addressbook>,
pub addressbooks: Vec<(CollectionMetadata, Addressbook)>,
pub deleted_addressbooks: Vec<(CollectionMetadata, Addressbook)>,
}
pub async fn route_addressbooks<AS: AddressbookStore>(
@@ -41,11 +41,33 @@ pub async fn route_addressbooks<AS: AddressbookStore>(
deleted_addressbooks.extend(addr_store.get_deleted_addressbooks(group).await.unwrap());
}
let mut addressbook_infos = vec![];
for addressbook in addressbooks {
addressbook_infos.push((
addr_store
.addressbook_metadata(&addressbook.principal, &addressbook.id)
.await
.unwrap(),
addressbook,
));
}
let mut deleted_addressbook_infos = vec![];
for addressbook in deleted_addressbooks {
deleted_addressbook_infos.push((
addr_store
.addressbook_metadata(&addressbook.principal, &addressbook.id)
.await
.unwrap(),
addressbook,
));
}
UserPage {
section: AddressbooksSection {
user: user.clone(),
addressbooks,
deleted_addressbooks,
addressbooks: addressbook_infos,
deleted_addressbooks: deleted_addressbook_infos,
},
user,
}

View File

@@ -5,7 +5,7 @@ use askama::Template;
use askama_web::WebTemplate;
use axum::{Extension, extract::Path, response::IntoResponse};
use http::StatusCode;
use rustical_store::{Calendar, CalendarStore, auth::Principal};
use rustical_store::{Calendar, CalendarStore, CollectionMetadata, auth::Principal};
impl Section for CalendarsSection {
fn name() -> &'static str {
@@ -17,8 +17,8 @@ impl Section for CalendarsSection {
#[template(path = "components/sections/calendars_section.html")]
pub struct CalendarsSection {
pub user: Principal,
pub calendars: Vec<Calendar>,
pub deleted_calendars: Vec<Calendar>,
pub calendars: Vec<(CollectionMetadata, Calendar)>,
pub deleted_calendars: Vec<(CollectionMetadata, Calendar)>,
}
pub async fn route_calendars<CS: CalendarStore>(
@@ -35,16 +35,38 @@ pub async fn route_calendars<CS: CalendarStore>(
calendars.extend(cal_store.get_calendars(group).await.unwrap());
}
let mut calendar_infos = vec![];
for calendar in calendars {
calendar_infos.push((
cal_store
.calendar_metadata(&calendar.principal, &calendar.id)
.await
.unwrap(),
calendar,
));
}
let mut deleted_calendars = vec![];
for group in user.memberships() {
deleted_calendars.extend(cal_store.get_deleted_calendars(group).await.unwrap());
}
let mut deleted_calendar_infos = vec![];
for calendar in deleted_calendars {
deleted_calendar_infos.push((
cal_store
.calendar_metadata(&calendar.principal, &calendar.id)
.await
.unwrap(),
calendar,
));
}
UserPage {
section: CalendarsSection {
user: user.clone(),
calendars,
deleted_calendars,
calendars: calendar_infos,
deleted_calendars: deleted_calendar_infos,
},
user,
}