From 94212eea53a5f40b7bfc6ba1cf86267b34913b5e Mon Sep 17 00:00:00 2001 From: Owen McGonagle Date: Thu, 6 Nov 2025 15:28:42 -0500 Subject: [PATCH] de-angularize the Key Pairs table This de-angularizes the Key Pairs page while maintaining full functionality of the previous AngularJS implementation. Users can now click a chevron to expand/collapse detailed keypair information (name, type, fingerprint, public key) directly in the table view. Change-Id: Id5e0a7a75fb42499b605e91f9b6ddfea9b7a002e Signed-off-by: Owen McGonagle --- .../dashboards/project/key_pairs/tables.py | 49 +++++++++++++++ .../templates/key_pairs/_chevron_column.html | 10 +++ .../templates/key_pairs/_keypairs_table.html | 61 +++++++++++++++++++ .../templates/key_pairs/expandable_row.html | 26 ++++++++ 4 files changed, 146 insertions(+) create mode 100644 openstack_dashboard/dashboards/project/templates/key_pairs/_chevron_column.html create mode 100644 openstack_dashboard/dashboards/project/templates/key_pairs/_keypairs_table.html create mode 100644 openstack_dashboard/dashboards/project/templates/key_pairs/expandable_row.html diff --git a/openstack_dashboard/dashboards/project/key_pairs/tables.py b/openstack_dashboard/dashboards/project/key_pairs/tables.py index 20bcd44209..f936ff6e4a 100644 --- a/openstack_dashboard/dashboards/project/key_pairs/tables.py +++ b/openstack_dashboard/dashboards/project/key_pairs/tables.py @@ -14,6 +14,7 @@ from urllib import parse +from django.template.loader import render_to_string from django import urls from django.utils.text import format_lazy from django.utils.translation import gettext_lazy as _ @@ -117,8 +118,54 @@ class KeypairsFilterAction(tables.FilterAction): if query in keypair.name.lower()] +def get_chevron_id(table, datum): + """Generate a unique chevron ID for expandable key pair rows. + + This function ensures consistent ID generation between the chevron toggle + column and the expandable detail row. The ID is based on the table name + and the unique object identifier for the datum. + + Args: + table: The DataTable instance (provides table.name and get_object_id()) + datum: The key pair object (passed to get_object_id()) + + Returns: + str: Unique chevron ID "{table_name}_chevron_{object_id}" + + Example: + For a keypair named "test1" in the "keypairs" table: + Returns "keypairs_chevron_test1" + """ + object_id = table.get_object_id(datum) + return "%s_chevron_%s" % (table.name, object_id) + + +class ExpandableKeyPairRow(tables.Row): + """Custom row class for expandable key pair rows.""" + + def render(self): + chevron_id = get_chevron_id(self.table, self.datum) + return render_to_string("key_pairs/expandable_row.html", + {"row": self, "chevron_id": chevron_id}) + + +class ExpandableKeyPairColumn(tables.Column): + """Column that renders a chevron toggle for expandable rows.""" + + def get_data(self, datum): + chevron_id = get_chevron_id(self.table, datum) + return render_to_string( + "key_pairs/_chevron_column.html", + {"chevron_id": chevron_id} + ) + + class KeyPairsTable(tables.DataTable): detail_link = "horizon:project:key_pairs:detail" + chevron = ExpandableKeyPairColumn("chevron", + verbose_name="", + sortable=False, + classes=['chevron_column']) name = tables.Column("name", verbose_name=_("Key Pair Name"), link=detail_link) key_type = tables.Column("type", verbose_name=_("Key Pair Type")) @@ -130,6 +177,8 @@ class KeyPairsTable(tables.DataTable): class Meta(object): name = "keypairs" verbose_name = _("Key Pairs") + row_class = ExpandableKeyPairRow + template = 'key_pairs/_keypairs_table.html' table_actions = (CreateLinkNG, ImportKeyPair, DeleteKeyPairs, KeypairsFilterAction,) row_actions = (DeleteKeyPairs,) diff --git a/openstack_dashboard/dashboards/project/templates/key_pairs/_chevron_column.html b/openstack_dashboard/dashboards/project/templates/key_pairs/_chevron_column.html new file mode 100644 index 0000000000..eb7d75aee9 --- /dev/null +++ b/openstack_dashboard/dashboards/project/templates/key_pairs/_chevron_column.html @@ -0,0 +1,10 @@ +{% load i18n %} + diff --git a/openstack_dashboard/dashboards/project/templates/key_pairs/_keypairs_table.html b/openstack_dashboard/dashboards/project/templates/key_pairs/_keypairs_table.html new file mode 100644 index 0000000000..d4bf1d8fa5 --- /dev/null +++ b/openstack_dashboard/dashboards/project/templates/key_pairs/_keypairs_table.html @@ -0,0 +1,61 @@ +{# Include the original data table template #} +{% include "horizon/common/_data_table.html" %} + +{# Add custom CSS for key pair chevron functionality #} + diff --git a/openstack_dashboard/dashboards/project/templates/key_pairs/expandable_row.html b/openstack_dashboard/dashboards/project/templates/key_pairs/expandable_row.html new file mode 100644 index 0000000000..91a06e4100 --- /dev/null +++ b/openstack_dashboard/dashboards/project/templates/key_pairs/expandable_row.html @@ -0,0 +1,26 @@ +{% load i18n %} + +{% include "horizon/common/_data_table_row.html" %} +{# Detail row - shows key pair information #} + + +
+
+
+
{% trans "Key Pair Name" %}
+
{{ row.datum.name }}
+ +
{% trans "Key Pair Type" %}
+
{{ row.datum.type|default:"ssh" }}
+ +
{% trans "Fingerprint" %}
+
{{ row.datum.fingerprint }}
+ +
{% trans "Public Key" %}
+
{{ row.datum.public_key|default:"N/A" }}
+
+
+
+ + +