Merge "de-angularize the Key Pairs table"

This commit is contained in:
Zuul
2025-11-17 17:31:57 +00:00
committed by Gerrit Code Review
4 changed files with 146 additions and 0 deletions

View File

@@ -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,)

View File

@@ -0,0 +1,10 @@
{% load i18n %}
<a role="button"
class="chevron-toggle collapsed"
data-toggle="collapse"
data-target="#{{ chevron_id }}"
aria-expanded="false"
aria-controls="{{ chevron_id }}"
aria-label="{% trans 'Toggle key pair details' %}">
<span class="fa fa-chevron-right"></span>
</a>

View File

@@ -0,0 +1,61 @@
{# Include the original data table template #}
{% include "horizon/common/_data_table.html" %}
{# Add custom CSS for key pair chevron functionality #}
<style>
/* 5 columns total (Chevron, Name, Type, Fingerprint, Actions) */
/* Force first TWO columns (Chevron, Name) to shrink to content using 1% trick */
table#keypairs th:nth-child(1),
table#keypairs td:nth-child(1),
table#keypairs th:nth-child(2),
table#keypairs td:nth-child(2) {
width: 1%;
white-space: nowrap;
}
/* Type column - moderate space */
table#keypairs th:nth-child(3),
table#keypairs td:nth-child(3) {
width: 15%;
}
/* Fingerprint column - flexible space */
table#keypairs th:nth-child(4),
table#keypairs td:nth-child(4) {
width: 40%;
}
/* Actions column - remaining space */
table#keypairs th:nth-child(5),
table#keypairs td:nth-child(5) {
width: auto;
}
/* Chevron rotation for key pair expandable rows
Uses Bootstrap's automatic .collapsed class management */
a.chevron-toggle {
color: inherit;
}
a.chevron-toggle>span {
transition: transform 0.3s ease;
}
/* Rotate chevron 90 degrees when row is expanded (not collapsed) */
a.chevron-toggle:not(.collapsed)>span {
transform: rotate(90deg);
}
/* Remove padding from detail row cells to eliminate gap when collapsed */
.table>tbody>tr.keypair-detail-row>td {
padding: 0;
overflow: hidden;
margin-top: -1px; /* Get rid of the double horizontal line when collapsed */
}
/* Add margin inner content when expanded */
.table>tbody>tr.keypair-detail-row>td div.keypair-details {
margin: 8px;
}
</style>

View File

@@ -0,0 +1,26 @@
{% load i18n %}
{% include "horizon/common/_data_table_row.html" %}
{# Detail row - shows key pair information #}
<tr class="keypair-detail-row">
<td colspan="{{ row.cells|length }}">
<div id="{{ chevron_id }}" class="collapse">
<div class="keypair-details">
<dl class="dl-horizontal">
<dt>{% trans "Key Pair Name" %}</dt>
<dd>{{ row.datum.name }}</dd>
<dt>{% trans "Key Pair Type" %}</dt>
<dd>{{ row.datum.type|default:"ssh" }}</dd>
<dt>{% trans "Fingerprint" %}</dt>
<dd>{{ row.datum.fingerprint }}</dd>
<dt>{% trans "Public Key" %}</dt>
<dd><pre style="word-break: break-all; white-space: pre-wrap; max-width: 100%; overflow-wrap: break-word;">{{ row.datum.public_key|default:"N/A" }}</pre></dd>
</dl>
</div>
</div>
</td>
</tr>
<tr></tr>