Show parent hierarchy in item list and details
This commit is contained in:
parent
9138865b48
commit
b736eba0a0
|
@ -27,6 +27,7 @@ struct ItemDetails {
|
|||
req: HttpRequest,
|
||||
item: Item,
|
||||
item_class: ItemClass,
|
||||
parents: Vec<Item>,
|
||||
}
|
||||
|
||||
#[get("/item/{id}")]
|
||||
|
@ -45,10 +46,15 @@ async fn show_item(
|
|||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
let parents = manage::item::get_parents_details(&mut pool.get().await.unwrap(), item.id)
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
Ok(ItemDetails {
|
||||
req,
|
||||
item,
|
||||
item_class,
|
||||
parents,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -56,8 +62,12 @@ async fn show_item(
|
|||
#[template(path = "item_list.html")]
|
||||
struct ItemList {
|
||||
req: HttpRequest,
|
||||
items: Vec<Item>,
|
||||
// Both a Vec and a HashMap are used to have both the natural order,
|
||||
// as well as arbitrary access capabilities.
|
||||
item_list: Vec<Item>,
|
||||
items: HashMap<Uuid, Item>,
|
||||
item_classes: HashMap<Uuid, ItemClass>,
|
||||
item_tree: HashMap<Uuid, Vec<Uuid>>,
|
||||
}
|
||||
|
||||
#[get("/items")]
|
||||
|
@ -65,7 +75,11 @@ async fn list_items(
|
|||
req: HttpRequest,
|
||||
pool: web::Data<DbPool>,
|
||||
) -> actix_web::Result<impl Responder> {
|
||||
let items = manage::item::get_all(&mut pool.get().await.unwrap())
|
||||
let item_list = manage::item::get_all(&mut pool.get().await.unwrap())
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
let items = manage::item::get_all_as_map(&mut pool.get().await.unwrap())
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
|
@ -73,10 +87,16 @@ async fn list_items(
|
|||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
let item_tree = manage::item::get_all_parents(&mut pool.get().await.unwrap())
|
||||
.await
|
||||
.map_err(error::ErrorInternalServerError)?;
|
||||
|
||||
Ok(ItemList {
|
||||
req,
|
||||
item_list,
|
||||
items,
|
||||
item_classes,
|
||||
item_tree,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use diesel::prelude::*;
|
||||
use diesel::sql_types;
|
||||
use diesel_async::pg::AsyncPgConnection;
|
||||
use diesel_async::RunQueryDsl;
|
||||
use uuid::Uuid;
|
||||
|
@ -37,6 +38,16 @@ pub async fn get_all(conn: &mut AsyncPgConnection) -> Result<Vec<Item>, diesel::
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn get_all_as_map(
|
||||
conn: &mut AsyncPgConnection,
|
||||
) -> Result<HashMap<Uuid, Item>, diesel::result::Error> {
|
||||
Ok(get_all(conn)
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|i| (i.id, i))
|
||||
.collect())
|
||||
}
|
||||
|
||||
pub async fn update(
|
||||
conn: &mut AsyncPgConnection,
|
||||
id: Uuid,
|
||||
|
@ -91,3 +102,23 @@ pub async fn get_all_parents(
|
|||
.collect::<HashMap<Uuid, Vec<Uuid>>>()
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn get_parents_details(
|
||||
conn: &mut AsyncPgConnection,
|
||||
id: Uuid,
|
||||
) -> Result<Vec<Item>, diesel::result::Error> {
|
||||
define_sql_function!(fn unnest(a: sql_types::Array<sql_types::Uuid>) -> sql_types::Uuid);
|
||||
|
||||
schema::items::table
|
||||
.filter(
|
||||
schema::items::id.eq_any(
|
||||
schema::item_tree::table
|
||||
.filter(schema::item_tree::id.eq(id))
|
||||
.select(unnest(schema::item_tree::parents))
|
||||
.into_boxed(),
|
||||
),
|
||||
)
|
||||
.select(Item::as_select())
|
||||
.load(conn)
|
||||
.await
|
||||
}
|
||||
|
|
|
@ -39,3 +39,4 @@ diesel::table! {
|
|||
diesel::joinable!(items -> item_classes (class));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(item_classes, items);
|
||||
diesel::allow_tables_to_appear_in_same_query!(items, item_tree);
|
||||
|
|
|
@ -36,10 +36,15 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
Parent
|
||||
Parents
|
||||
</th>
|
||||
<td>
|
||||
{% if let Some(parent) = item.parent %}{{ parent }}{% else %}-{% endif %}
|
||||
<ol class="breadcrumb mb-0">
|
||||
{%- for parent in parents %}
|
||||
<li class="breadcrumb-item"><a href="/item/{{ parent.id }}">{{ parent.name }}</a></li>
|
||||
{%- endfor %}
|
||||
<li class="breadcrumb-item active">{{ item.name }}</li>
|
||||
</ol>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -15,14 +15,28 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Class</th>
|
||||
<th>Parents</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for item in items -%}
|
||||
{% for item in item_list -%}
|
||||
{% let class = item_classes.get(item.class).unwrap() %}
|
||||
<tr>
|
||||
<td><a href="/item/{{ item.id }}">{{ item.name }}</a></td>
|
||||
<td><a href="/item-class/{{ class.id }}">{{ class.name }}</a></td>
|
||||
<td>
|
||||
<ol class="breadcrumb mb-0">
|
||||
{%- let parents = item_tree.get(item.id).unwrap() -%}
|
||||
{%- if parents.len() > 3 %}
|
||||
<li class="breadcrumb-item">…</li>
|
||||
{%- endif %}
|
||||
{%- for parent in parents.iter().rev().take(3).rev() %}
|
||||
{%- let parent = items.get(parent).unwrap() %}
|
||||
<li class="breadcrumb-item"><a href="/item/{{ parent.id }}">{{ parent.name }}</a></li>
|
||||
{%- endfor %}
|
||||
<li class="breadcrumb-item active">{{ item.name }}</li>
|
||||
</ol>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor -%}
|
||||
</tbody>
|
||||
|
|
Loading…
Reference in a new issue