diff --git a/web/CHANGELOG.md b/web/CHANGELOG.md index b702e9fa..f65757e6 100644 --- a/web/CHANGELOG.md +++ b/web/CHANGELOG.md @@ -16,6 +16,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ### Changed +- **Editable empty-table definitions** — the table-definition column page now + calls `PutTableDefinition` to atomically remove selected columns and append + replacements, with stable column identities and optimistic revision checks. + Add-only changes continue to work for populated tables. - **The shared profile is named by the backend** — `ProfileTreeResponse` gained `shared_profile_name`, and every page that browses the shared tables now reads the name from there instead of spelling `__global` itself. Catalog diff --git a/web/locales/cs/main.ftl b/web/locales/cs/main.ftl index 9cf8073c..2320c00f 100644 --- a/web/locales/cs/main.ftl +++ b/web/locales/cs/main.ftl @@ -135,7 +135,7 @@ admin-no-profile-tables = Tento profil nemá vlastní tabulky. admin-no-dependencies = Bez závislostí admin-depends-on-prefix = Závisí na admin-row-display-prefix = zobrazení: -admin-add-columns = Přidat sloupce +admin-add-columns = Upravit sloupce admin-column-presentation = Aliasy sloupců admin-delete-table = Smazat tabulku admin-who-may-use-it = Kdo ji může používat @@ -161,9 +161,17 @@ admin-system-columns-label = Systémové sloupce · skryté před uživateli # --- Stránky definice tabulky (přidat sloupce / zobrazení / smazat / kopírovat / šablona / historie) td-add-columns-title = Přidat sloupce +td-adjust-columns-title = Upravit sloupce td-presentation-title = Zobrazení sloupců td-add-columns-to = Přidat sloupce do td-append-hint = Sloupce se přidávají na konec. Nic, co už existuje, se nemění a nové sloupce lze indexovat hned při přidání. +td-adjust-columns-of = Upravit sloupce tabulky +td-adjust-hint = Přidejte nové sloupce nebo označte existující k odebrání. Samotné přidání funguje i v tabulce s daty; odebrání nebo nahrazení vyžaduje prázdnou tabulku a uloží se atomicky. +td-existing-columns = Existující sloupce +td-new-columns = Nové sloupce k přidání +td-remove-column = Odebrat +td-remove-column-aria = Odebrat { $column } +td-save-definition = Uložit definici tabulky td-rename-column = Aliasy sloupců td-rename-hint = Přejmenovává se jen zobrazený název, ne fyzický sloupec pod ním, takže uložená data a skripty zůstávají nedotčené. td-column-label = Sloupec @@ -189,7 +197,7 @@ td-col-target-column = Cílový sloupec td-col-description = Popis td-source = zdroj -td-could-not-add-column = Sloupec se nepodařilo přidat +td-could-not-add-column = Sloupce se nepodařilo upravit td-staged = Připraveno td-link-alias = Alias odkazu td-column-name = Název sloupce @@ -250,6 +258,8 @@ td-global-label = Globální — všechny profily td-tab-aria = akce s tabulkou td-tab-add-columns = Přidat sloupce td-tab-add-columns-sub = Připojit nové sloupce +td-tab-adjust-columns = Upravit sloupce +td-tab-adjust-columns-sub = Přidat, odebrat nebo nahradit td-tab-presentation = Zobrazení td-tab-presentation-sub = Změnit aliasy a pořadí td-tab-delete = Smazat @@ -306,6 +316,7 @@ td-columns-added = { $count -> [few] { $count } sloupce přidány do `{ $table }`. *[other] { $count } sloupců přidáno do `{ $table }`. } +td-definition-adjusted = Tabulka `{ $table }` upravena: přidáno { $added }, odebráno { $removed }. td-profile-copied = { $message } — zkopírováno { $tables -> [one] { $tables } tabulka [few] { $tables } tabulky @@ -324,7 +335,9 @@ td-err-select-table-first = Nejprve vyberte tabulku. td-err-profile-gone = Profil `{ $missing }` už neexistuje. td-err-not-a-table = `{ $missing }` není tabulka rozsahu { $scope }. td-err-describe-column = Před přidáním popište alespoň jeden sloupec. +td-err-describe-change = Označte sloupec k odebrání nebo připravte alespoň jeden sloupec k přidání. td-err-backend-no-columns = Backend nepřidal sloupce. +td-err-backend-no-adjustment = Backend neupravil definici tabulky. td-err-choose-rename = Zadejte nový název sloupce. td-err-unknown-column = Tento sloupec už do této tabulky nepatří. Panel níže ukazuje tabulku, jaká je teď. td-err-backend-no-rename = Backend nepřejmenoval sloupec. diff --git a/web/locales/en/main.ftl b/web/locales/en/main.ftl index 0145edd9..249ddc62 100644 --- a/web/locales/en/main.ftl +++ b/web/locales/en/main.ftl @@ -139,7 +139,7 @@ admin-no-profile-tables = This profile has no tables of its own. admin-no-dependencies = No dependencies admin-depends-on-prefix = Depends on admin-row-display-prefix = display: -admin-add-columns = Add columns +admin-add-columns = Adjust columns admin-column-presentation = Column aliases admin-delete-table = Delete table admin-who-may-use-it = Who may use it @@ -163,9 +163,17 @@ admin-system-columns-label = System columns · hidden from users # --- Table definition pages (add columns / presentation / delete / copy / template / history) - td-add-columns-title = Add columns +td-adjust-columns-title = Adjust columns td-presentation-title = Column presentation td-add-columns-to = Add columns to td-append-hint = Columns are appended. Nothing that already exists is changed, and the new columns can be indexed as they are added. +td-adjust-columns-of = Adjust columns of +td-adjust-hint = Add new columns, or select existing columns to remove. Add-only changes also work on populated tables; removing or replacing columns requires an empty table and is saved atomically. +td-existing-columns = Existing columns +td-new-columns = New columns to add +td-remove-column = Remove +td-remove-column-aria = Remove { $column } +td-save-definition = Save table definition td-rename-column = Column aliases td-rename-hint = Renames what the column is called, not the physical column underneath, so stored data and scripts are untouched. td-column-label = Column @@ -191,7 +199,7 @@ td-col-target-column = Target column td-col-description = Description td-source = source -td-could-not-add-column = Could not add the column +td-could-not-add-column = Could not adjust the columns td-staged = Staged td-link-alias = Link alias td-column-name = Column name @@ -250,6 +258,8 @@ td-global-label = Global — all profiles td-tab-aria = table actions td-tab-add-columns = Add columns td-tab-add-columns-sub = Append new columns +td-tab-adjust-columns = Adjust columns +td-tab-adjust-columns-sub = Add, remove, or replace columns td-tab-presentation = Presentation td-tab-presentation-sub = Change aliases and order td-tab-delete = Delete @@ -305,6 +315,7 @@ td-columns-added = { $count -> [one] { $count } column added to `{ $table }`. *[other] { $count } columns added to `{ $table }`. } +td-definition-adjusted = `{ $table }` adjusted: { $added } added, { $removed } removed. td-profile-copied = { $message } — { $tables -> [one] { $tables } table *[other] { $tables } tables @@ -320,7 +331,9 @@ td-err-select-table-first = Select a table first. td-err-profile-gone = Profile `{ $missing }` no longer exists. td-err-not-a-table = `{ $missing }` is not a table of { $scope }. td-err-describe-column = Describe at least one column before adding. +td-err-describe-change = Select a column to remove or stage at least one column to add. td-err-backend-no-columns = The backend did not add the columns. +td-err-backend-no-adjustment = The backend did not adjust the table definition. td-err-choose-rename = Type a new name for the column. td-err-unknown-column = That column is not part of this table any more. The panel below is the table as it now is. td-err-backend-no-rename = The backend did not rename the column. diff --git a/web/locales/sk/main.ftl b/web/locales/sk/main.ftl index 480b1656..dbb48c89 100644 --- a/web/locales/sk/main.ftl +++ b/web/locales/sk/main.ftl @@ -135,7 +135,7 @@ admin-no-profile-tables = Tento profil nemá vlastné tabuľky. admin-no-dependencies = Bez závislostí admin-depends-on-prefix = Závisí od admin-row-display-prefix = zobrazenie: -admin-add-columns = Pridať stĺpce +admin-add-columns = Upraviť stĺpce admin-column-presentation = Aliasy stĺpcov admin-delete-table = Vymazať tabuľku admin-who-may-use-it = Kto ju môže používať @@ -161,9 +161,17 @@ admin-system-columns-label = Systémové stĺpce · skryté pred používateľmi # --- Stránky definície tabuľky (pridať stĺpce / zobrazenie / vymazať / kopírovať / šablóna / história) td-add-columns-title = Pridať stĺpce +td-adjust-columns-title = Upraviť stĺpce td-presentation-title = Zobrazenie stĺpcov td-add-columns-to = Pridať stĺpce do td-append-hint = Stĺpce sa pridávajú na koniec. Nič, čo už existuje, sa nemení a nové stĺpce možno indexovať hneď pri pridaní. +td-adjust-columns-of = Upraviť stĺpce tabuľky +td-adjust-hint = Pridajte nové stĺpce alebo označte existujúce na odstránenie. Samotné pridanie funguje aj v tabuľke s údajmi; odstránenie alebo nahradenie vyžaduje prázdnu tabuľku a uloží sa atómovo. +td-existing-columns = Existujúce stĺpce +td-new-columns = Nové stĺpce na pridanie +td-remove-column = Odstrániť +td-remove-column-aria = Odstrániť { $column } +td-save-definition = Uložiť definíciu tabuľky td-rename-column = Aliasy stĺpcov td-rename-hint = Premenúva sa len zobrazený názov, nie fyzický stĺpec pod ním, takže uložené údaje a skripty zostávajú nedotknuté. td-column-label = Stĺpec @@ -189,7 +197,7 @@ td-col-target-column = Cieľový stĺpec td-col-description = Popis td-source = zdroj -td-could-not-add-column = Stĺpec sa nepodarilo pridať +td-could-not-add-column = Stĺpce sa nepodarilo upraviť td-staged = Pripravené td-link-alias = Alias odkazu td-column-name = Názov stĺpca @@ -250,6 +258,8 @@ td-global-label = Globálne — všetky profily td-tab-aria = akcie s tabuľkou td-tab-add-columns = Pridať stĺpce td-tab-add-columns-sub = Pripojiť nové stĺpce +td-tab-adjust-columns = Upraviť stĺpce +td-tab-adjust-columns-sub = Pridať, odstrániť alebo nahradiť td-tab-presentation = Zobrazenie td-tab-presentation-sub = Zmeniť aliasy a poradie td-tab-delete = Vymazať @@ -306,6 +316,7 @@ td-columns-added = { $count -> [few] { $count } stĺpce pridané do `{ $table }`. *[other] { $count } stĺpcov pridaných do `{ $table }`. } +td-definition-adjusted = Tabuľka `{ $table }` upravená: pridané { $added }, odstránené { $removed }. td-profile-copied = { $message } — skopírované { $tables -> [one] { $tables } tabuľka [few] { $tables } tabuľky @@ -324,7 +335,9 @@ td-err-select-table-first = Najprv vyberte tabuľku. td-err-profile-gone = Profil `{ $missing }` už neexistuje. td-err-not-a-table = `{ $missing }` nie je tabuľka rozsahu { $scope }. td-err-describe-column = Pred pridaním popíšte aspoň jeden stĺpec. +td-err-describe-change = Označte stĺpec na odstránenie alebo pripravte aspoň jeden stĺpec na pridanie. td-err-backend-no-columns = Backend nepridal stĺpce. +td-err-backend-no-adjustment = Backend neupravil definíciu tabuľky. td-err-choose-rename = Zadajte nový názov stĺpca. td-err-unknown-column = Tento stĺpec už do tejto tabuľky nepatrí. Panel nižšie ukazuje tabuľku, aká je teraz. td-err-backend-no-rename = Backend nepremenoval stĺpec. diff --git a/web/src/pages/admin/table_definition/loader.rs b/web/src/pages/admin/table_definition/loader.rs index 1eac25c0..39951d6b 100644 --- a/web/src/pages/admin/table_definition/loader.rs +++ b/web/src/pages/admin/table_definition/loader.rs @@ -289,6 +289,7 @@ pub(crate) async fn load_page( history, selection: inputs.selection, columns: inputs.columns, + remove_column_ids: inputs.remove_column_ids, copy: inputs.copy, invoice: inputs.invoice, status: inputs.status, diff --git a/web/src/pages/admin/table_definition/logic.rs b/web/src/pages/admin/table_definition/logic.rs index b48002fa..0ef6f6d4 100644 --- a/web/src/pages/admin/table_definition/logic.rs +++ b/web/src/pages/admin/table_definition/logic.rs @@ -24,6 +24,7 @@ use crate::{ definitions::table_definition::{ AddTableColumnsRequest, CopyProfileRequest, CreateInvoiceTemplateTableRequest, ColumnPresentation, DeleteTableRequest, SetColumnPresentationRequest, + PutTableDefinitionRequest, }, {i18n::Locale, tr}, schema::{ColumnForm, proto_columns}, @@ -214,7 +215,8 @@ pub(crate) async fn update_columns( } } -/// POST /admin/tables/columns/add — AddTableColumns. +/// POST /admin/tables/columns/add — append columns, or atomically replace part +/// of an empty table through PutTableDefinition. pub(crate) async fn add_columns( State(state): State, headers: HeaderMap, @@ -235,6 +237,7 @@ pub(crate) async fn add_columns( let mut inputs = PageInputs::for_selection(selection); inputs.columns = form.to_draft(catalog.clone(), false); + inputs.remove_column_ids = form.remove_column_ids.clone(); if !inputs.selection.has_table() { let message = tr!( @@ -250,10 +253,10 @@ pub(crate) async fn add_columns( ) .await; } - if inputs.columns.is_empty() { + if inputs.columns.is_empty() && inputs.remove_column_ids.is_empty() { let message = tr!( Locale::from_headers(&headers), - "td-err-describe-column" + "td-err-describe-change" ); return refuse( state, @@ -266,10 +269,88 @@ pub(crate) async fn add_columns( } // The same checks the server runs, applied to a draft that may have been // rebuilt from a posted form rather than through the panel. - if let Err(message) = inputs.columns.validate(Locale::from_headers(&headers)) { + if !inputs.columns.is_empty() + && let Err(message) = inputs.columns.validate(Locale::from_headers(&headers)) + { return refuse(state, headers, inputs, Page::AddColumns, message).await; } + // Keep the old append capability for populated tables. Put is used only + // when a removal was requested, because that operation deliberately + // refuses every table which has ever stored a row. + if inputs.remove_column_ids.is_empty() { + return append_columns(state, headers, inputs, catalog, definitions).await; + } + + let current = match load_page(state.clone(), &headers, inputs.clone()).await { + Ok(page) => page.detail, + Err(error) => return load_error_response(&headers, error), + }; + let Some(current) = current else { + let message = tr!(Locale::from_headers(&headers), "td-err-select-table-first"); + return refuse(state, headers, inputs, Page::AddColumns, message).await; + }; + let remove_column_ids = match current.expanded_removal_ids(&inputs.remove_column_ids) { + Ok(ids) => ids, + Err(()) => { + let message = tr!(Locale::from_headers(&headers), "td-err-unknown-column"); + return refuse(state, headers, inputs, Page::AddColumns, message).await; + } + }; + + let request = PutTableDefinitionRequest { + profile_name: inputs.selection.profile.clone(), + table_name: inputs.selection.table.clone(), + remove_column_ids, + add_columns: proto_columns(&inputs.columns.added), + add_indexes: inputs.columns.selected_index_names(), + generated_aliases: Vec::new(), + expected_row_version: form.expected_row_version, + }; + let Ok(request) = authenticated_request(&headers, request) else { + return Redirect::to("/login").into_response(); + }; + + match definitions.put_table_definition(request).await { + Ok(response) if response.get_ref().success => { + let response = response.into_inner(); + let removed = response.removed_column_ids.len(); + let added = inputs.columns.added.len(); + inputs.sql = Some(response.sql); + inputs.status = Some(tr!( + Locale::from_headers(&headers), + "td-definition-adjusted", + "added" => added as i64, + "removed" => removed as i64, + "table" => inputs.selection.table.clone(), + )); + inputs.columns = crate::schema::ColumnDraft::for_append(catalog); + inputs.remove_column_ids.clear(); + respond(state, headers, inputs, Page::AddColumns, StatusCode::OK).await + } + Ok(response) => { + let message = response.into_inner().sql; + let message = if message.is_empty() { + tr!(Locale::from_headers(&headers), "td-err-backend-no-adjustment") + } else { + message + }; + refuse(state, headers, inputs, Page::AddColumns, message).await + } + Err(error) => { + refuse(state, headers, inputs, Page::AddColumns, error.message().to_string()).await + } + } +} + +async fn append_columns( + state: AppState, + headers: HeaderMap, + mut inputs: PageInputs, + catalog: crate::schema::ColumnCatalog, + mut definitions: crate::definitions::table_definition::table_definition_client::TableDefinitionClient, +) -> Response { + let request = AddTableColumnsRequest { profile_name: inputs.selection.profile.clone(), table_name: inputs.selection.table.clone(), diff --git a/web/src/pages/admin/table_definition/mod.rs b/web/src/pages/admin/table_definition/mod.rs index aaa7fe8a..118320e4 100644 --- a/web/src/pages/admin/table_definition/mod.rs +++ b/web/src/pages/admin/table_definition/mod.rs @@ -1,6 +1,6 @@ //! What can be done to a table once it exists, as one page per decision. //! -//! Adding columns, presenting columns, dropping the table, copying its profile, +//! Adjusting columns, presenting columns, dropping the table, copying its profile, //! generating tables from a template and reading the rename history are six //! different jobs, and they used to be panels stacked on one `/admin/table-definition` //! workspace — which meant that after creating a table you landed on a screen diff --git a/web/src/pages/admin/table_definition/state.rs b/web/src/pages/admin/table_definition/state.rs index 4e6a54b5..a9c38e5f 100644 --- a/web/src/pages/admin/table_definition/state.rs +++ b/web/src/pages/admin/table_definition/state.rs @@ -101,6 +101,46 @@ impl TableDetailView { .filter(|column| column.renameable) .collect() } + + /// Expands a top-level removal choice to the generated columns the backend + /// requires to travel with it. PHONE/IBAN companions name their source; + /// linked projections use `link.source`. + pub(crate) fn expanded_removal_ids(&self, selected: &[i64]) -> Result, ()> { + let selected = selected.iter().copied().collect::>(); + if selected + .iter() + .any(|id| !self.columns.iter().any(|column| column.column_id == *id)) + { + return Err(()); + } + + let mut roots = selected.clone(); + for column in self.columns.iter().filter(|column| selected.contains(&column.column_id)) { + if let Some(root_name) = column.generated_from.split('.').next() + && !root_name.is_empty() + && let Some(root) = self.columns.iter().find(|candidate| candidate.name == root_name) + { + roots.insert(root.column_id); + } + } + + Ok(self + .columns + .iter() + .filter(|column| { + roots.contains(&column.column_id) + || self.columns.iter().any(|root| { + roots.contains(&root.column_id) + && (column.generated_from == root.name + || column + .generated_from + .strip_prefix(&root.name) + .is_some_and(|suffix| suffix.starts_with('.'))) + }) + }) + .map(|column| column.column_id) + .collect()) + } } #[derive(Clone, Debug)] @@ -121,6 +161,12 @@ pub(crate) struct DetailColumn { } impl DetailColumn { + /// Generated/read-only rows are shown as part of their parent definition; + /// choosing the parent expands to them in `expanded_removal_ids`. + pub(crate) fn is_removal_choice(&self) -> bool { + self.column_id > 0 && !self.generated && !self.read_only + } + /// The badge list rendered under each column name. pub(crate) fn flags(&self, locale: &crate::i18n::Locale) -> Vec { let mut flags = Vec::new(); @@ -274,8 +320,10 @@ pub(crate) struct DeleteForm { #[derive(Clone, Debug, Default)] pub(crate) struct PageInputs { pub selection: Selection, - /// The columns staged for `AddTableColumns`. + /// The new columns staged for the structural edit. pub columns: ColumnDraft, + /// Existing column identities selected for removal. + pub remove_column_ids: Vec, pub copy: CopyForm, pub invoice: InvoiceTemplateForm, pub status: Option, @@ -316,6 +364,7 @@ pub(crate) struct TableDefinitionPageState { pub detail: Option, pub history: Vec, pub columns: ColumnDraft, + pub remove_column_ids: Vec, pub copy: CopyForm, pub invoice: InvoiceTemplateForm, pub status: Option, @@ -328,6 +377,10 @@ pub(crate) struct TableDefinitionPageState { } impl TableDefinitionPageState { + pub(crate) fn column_is_selected_for_removal(&self, column_id: &i64) -> bool { + self.remove_column_ids.contains(column_id) + } + /// Whether `name` is the page being rendered. Read by context.html. pub(crate) fn is(&self, name: &str) -> bool { self.active == name @@ -490,5 +543,11 @@ mod tests { detail.columns[2].flags(&crate::i18n::Locale::default()), vec!["EUR", "generated from accounting"] ); + + assert_eq!(detail.expanded_removal_ids(&[1]).unwrap(), [1, 2]); + assert_eq!(detail.expanded_removal_ids(&[2]).unwrap(), [1, 2]); + assert!(detail.expanded_removal_ids(&[99]).is_err()); + assert!(detail.columns[0].is_removal_choice()); + assert!(!detail.columns[1].is_removal_choice()); } } diff --git a/web/src/pages/admin/table_definition/ui.rs b/web/src/pages/admin/table_definition/ui.rs index 0c5452b0..dd219153 100644 --- a/web/src/pages/admin/table_definition/ui.rs +++ b/web/src/pages/admin/table_definition/ui.rs @@ -291,6 +291,7 @@ mod tests { }), history: Vec::new(), columns: ColumnDraft::for_append(crate::schema::tests::catalog()), + remove_column_ids: Vec::new(), copy: CopyForm::default(), invoice: InvoiceTemplateForm::default(), status: None, @@ -453,6 +454,9 @@ mod tests { fn adding_columns_and_presentation_are_separate_pages() { let add_html = render_add_columns_page(&page()); assert!(add_html.contains(r#"id="column-form""#), "{add_html}"); + assert!(add_html.contains(r#"name="expected_row_version" value="1""#), "{add_html}"); + assert!(add_html.contains(r#"name="remove_column_ids" value="1""#), "{add_html}"); + assert!(add_html.contains("Adjust columns"), "{add_html}"); assert!(!add_html.contains(r#"name="alias""#), "{add_html}"); let presentation_html = render_presentation_page(&page()); diff --git a/web/src/schema/mod.rs b/web/src/schema/mod.rs index 1b2c809c..b9a1966d 100644 --- a/web/src/schema/mod.rs +++ b/web/src/schema/mod.rs @@ -1416,6 +1416,13 @@ pub(crate) struct ColumnForm { #[serde(default)] pub index: Option, + /// Existing-table structural edits carry these alongside the shared + /// staged-column fields. They stay empty on the add-table builder. + #[serde(default)] + pub remove_column_ids: Vec, + #[serde(default)] + pub expected_row_version: i64, + #[serde(default)] pub column_name_input: String, #[serde(default)] diff --git a/web/templates/pages/admin/table_definition/add_columns.html b/web/templates/pages/admin/table_definition/add_columns.html index 8b9b0777..77041954 100644 --- a/web/templates/pages/admin/table_definition/add_columns.html +++ b/web/templates/pages/admin/table_definition/add_columns.html @@ -1,7 +1,7 @@ {# GET /admin/tables/columns/add — crate::pages::admin::table_definition::ui::AddColumnsPage #} {% extends "ui/base.html" %} -{% block title %}{{ nav.tr("td-add-columns-title") }}{% endblock %} +{% block title %}{{ nav.tr("td-adjust-columns-title") }}{% endblock %} {% block content %}
diff --git a/web/templates/pages/admin/table_definition/add_columns_panel.html b/web/templates/pages/admin/table_definition/add_columns_panel.html index 6f775c89..11004114 100644 --- a/web/templates/pages/admin/table_definition/add_columns_panel.html +++ b/web/templates/pages/admin/table_definition/add_columns_panel.html @@ -3,12 +3,39 @@ {% if page.table_is_writable() %}
-

{{ nav.tr("td-add-columns-to") }} {{ page.selection.table }}

-

{{ nav.tr("td-append-hint") }}

+

{{ nav.tr("td-adjust-columns-of") }} {{ page.selection.table }}

+

{{ nav.tr("td-adjust-hint") }}

+ {% if let Some(detail) = page.detail %} + +

{{ nav.tr("td-existing-columns") }}

+ + + + {% for column in detail.columns %} + + + + + + + {% endfor %} + +
{{ nav.tr("td-remove-column") }}{{ nav.tr("td-col-name") }}{{ nav.tr("td-col-type") }}{{ nav.tr("td-col-notes") }}
+ {% if column.is_removal_choice() %} + + {% else %}{% endif %} + {{ column.name }}{{ column.field_type }} + {% if column.generated %}{{ nav.tr("column-flag-generated") }}{% endif %} + {% if column.read_only %}{{ nav.tr("column-flag-read-only") }}{% endif %} +
+ {% endif %} +

{{ nav.tr("td-new-columns") }}

{% include "pages/admin/table_definition/column_panel.html" %}
diff --git a/web/templates/pages/admin/table_definition/column_panel.html b/web/templates/pages/admin/table_definition/column_panel.html index 2642a718..b7256a0c 100644 --- a/web/templates/pages/admin/table_definition/column_panel.html +++ b/web/templates/pages/admin/table_definition/column_panel.html @@ -216,5 +216,5 @@ {% endfor %}
- +
diff --git a/web/templates/pages/admin/table_definition/context.html b/web/templates/pages/admin/table_definition/context.html index da54e6d8..a3a4b524 100644 --- a/web/templates/pages/admin/table_definition/context.html +++ b/web/templates/pages/admin/table_definition/context.html @@ -40,7 +40,7 @@ {% if page.selection.has_table() %} {% if page.table_is_writable() %} - {{ nav.tr("td-tab-add-columns") }}{{ nav.tr("td-tab-add-columns-sub") }} + {{ nav.tr("td-tab-adjust-columns") }}{{ nav.tr("td-tab-adjust-columns-sub") }} {{ nav.tr("td-tab-presentation") }}{{ nav.tr("td-tab-presentation-sub") }}