global is being global and i can select it and so on

This commit is contained in:
Priec
2026-08-13 22:51:57 +02:00
parent df145c14f7
commit 05f29b82f6
7 changed files with 368 additions and 130 deletions

View File

@@ -20,10 +20,11 @@ use crate::{
definitions::{
common::Empty,
table_definition::{
GetColumnAliasRenameHistoryRequest, GetProfileDetailsRequest, MoneyRounding,
table_definition_client::TableDefinitionClient,
GetColumnAliasRenameHistoryRequest, GetProfileDetailsRequest, GetTableCatalogRequest,
MoneyRounding, table_definition_client::TableDefinitionClient,
},
},
pages::table_scope,
schema::{ColumnCatalog, column_catalog},
services::authenticated_request,
};
@@ -98,50 +99,68 @@ pub(crate) async fn load_page(
.map(|profile| profile.name.as_str())
.collect::<Vec<_>>();
// A profile that no longer exists takes the table selection with it.
if inputs.selection.profile != GLOBAL_SCOPE
// A profile that no longer exists takes the table selection with it, and
// says so — the commonest way to get here with a stale one is having just
// deleted its last table, which is worth being told.
if inputs.selection.has_profile()
&& inputs.selection.profile != GLOBAL_SCOPE
&& !profiles.contains(&inputs.selection.profile.as_str())
{
inputs.selection.profile.clear();
let missing = std::mem::take(&mut inputs.selection.profile);
inputs.selection.table.clear();
inputs
.error
.get_or_insert(format!("Profile `{missing}` no longer exists."));
}
// The same two sources the admin panel browses by, so a table it offers is
// a table this page can act on. Reading the global scope out of the tree
// instead is what used to answer "No table chosen" for a table the panel
// had just listed.
let selected_tables = if inputs.selection.is_global() {
tree.profiles.first().map(|profile| profile.tables.as_slice())
table_scope::global_tables(
&definitions
.get_table_catalog(
authenticated_request(headers, GetTableCatalogRequest { profile_name: None })
.map_err(|_| LoadError::Unauthenticated)?,
)
.await
.map_err(|error| LoadError::Backend(error.message().to_string()))?
.into_inner()
.tables,
)
} else {
tree.profiles
.iter()
.find(|profile| profile.name == inputs.selection.profile)
.map(|profile| profile.tables.as_slice())
table_scope::profile_owned_tables(&tree.profiles, &inputs.selection.profile)
};
let tables = selected_tables
.map(|tables| {
tables
.iter()
.filter(|table| table.global == inputs.selection.is_global())
.map(|table| TableSummary {
name: table.name.clone(),
table_kind: table.table_kind.clone(),
global: table.global,
// One entry per link, named by the column carrying it, so a
// table pointing at one target twice reads as two links.
depends_on: table
.depends_on
.iter()
.map(|dependency| {
format!("{} ({})", dependency.table_name, dependency.column_name)
})
.collect(),
})
.collect::<Vec<_>>()
.into_iter()
.map(|table| TableSummary {
name: table.name,
table_kind: table.table_kind,
global: table.global,
// One entry per link, named by the column carrying it, so a table
// pointing at one target twice reads as two links.
depends_on: table
.depends_on
.into_iter()
.map(|dependency| format!("{} ({})", dependency.table_name, dependency.column_name))
.collect(),
})
.unwrap_or_default();
.collect::<Vec<_>>();
if !tables
.iter()
.any(|table| table.name == inputs.selection.table)
// A table the scope does not hold is dropped rather than acted on. It is
// said out loud, though: dropping it in silence is what left the panel
// telling someone who had just picked a table to go and pick one.
if inputs.selection.has_table()
&& !tables
.iter()
.any(|table| table.name == inputs.selection.table)
{
inputs.selection.table.clear();
let missing = std::mem::take(&mut inputs.selection.table);
let scope = inputs.selection.scope_label();
inputs
.error
.get_or_insert(format!("`{missing}` is not a table of {scope}."));
}
let detail = match inputs.selection.has_table() {