Browse Source

#47 highlight text matches in search results

tags/0.17
Henning Jacobs 3 months ago
parent
commit
13dd7c5c8b
4 changed files with 42 additions and 1 deletions
  1. +2
    -0
      kube_web/templates/assets/kube-web.css
  2. +8
    -1
      kube_web/templates/search.html
  3. +22
    -0
      kube_web/web.py
  4. +10
    -0
      tests/e2e/test_search.py

+ 2
- 0
kube_web/templates/assets/kube-web.css View File

@@ -83,6 +83,8 @@ form .checkboxes label { margin-right: 0.5rem; padding-top: 0.375em; }
.search-result p { font-size: 0.75rem; }
.search-result h3.title { margin: 0 0 0.5rem 0; }
.search-result { margin-bottom: 1.5rem; }
.search-result p { margin-bottom: 0.25rem; }
.search-result em { font-style: normal; background: hsl(48, 100%, 67%) }

/* Pygments CSS
* print(HtmlFormatter(style='friendly').get_style_defs('.highlight'))

+ 8
- 1
kube_web/templates/search.html View File

@@ -70,8 +70,15 @@
<div class="search-result">
<h3 class="title is-6"><a href="{{ result.link }}">{{ result.title }} ({{ result.kind }})</a></h3>
<p><a href="{{ result.link }}">{{ result.link }}</a></p>
{% if result.created or result.matches: %}
<p>
{% if result.created: %}
<p>Created: {{ result.created.replace('T', ' ').replace('Z', '') }}</p>
Created: {{ result.created.replace('T', ' ').replace('Z', '') }}
{% endif %}
{% for pre, highlight, post in result.matches: %}
<span class="match">{{ pre }}<em>{{ highlight }}</em>{{ post }}</span>
{% endfor %}
</p>
{% endif %}
<p>
{% for key, val in result.labels.items()|sort: %}

+ 22
- 0
kube_web/web.py View File

@@ -79,6 +79,8 @@ SEARCH_OFFERED_RESOURCE_TYPES = [
"nodes",
]

SEARCH_MATCH_CONTEXT_LENGTH = 20


TABLE_CELL_FORMATTING = {
"events": {"Type": {"Warning": "has-text-warning"}},
@@ -760,6 +762,7 @@ async def search(
if col["name"] == "Name":
name_column = i
break
filter_query_lower = filter_query.lower()
for row in table.rows:
name = row["cells"][name_column]
if namespaced:
@@ -767,11 +770,30 @@ async def search(
link = f"/clusters/{_cluster.name}/namespaces/{ns}/{_type}/{name}"
else:
link = f"/clusters/{_cluster.name}/{_type}/{name}"
matches = []
if filter_query:
for cell in row["cells"]:
idx = str(cell).lower().find(filter_query_lower)
if idx > -1:
pre_start = max(idx - SEARCH_MATCH_CONTEXT_LENGTH, 0)
end = idx + len(filter_query_lower)
post_end = min(
idx
+ len(filter_query_lower)
+ SEARCH_MATCH_CONTEXT_LENGTH,
len(cell),
)
matches.append(
(cell[pre_start:idx], cell[idx:end], cell[end:post_end])
)
if len(matches) >= 3:
break
results.append(
{
"title": name,
"kind": clazz.kind,
"link": link,
"matches": matches,
"labels": row["object"]["metadata"].get("labels", {}),
"created": row["object"]["metadata"]["creationTimestamp"],
}

+ 10
- 0
tests/e2e/test_search.py View File

@@ -42,3 +42,13 @@ def test_search_non_standard_resource_type(session):
# check that the type was added as checkbox
labels = response.html.find("label.checkbox")
assert "PodSecurityPolicy" in [label.text for label in labels]


def test_search_container_image_match_highlight(session):
response = session.get("/search?q=hjacobs/wrong-container-image:&type=deployments")
response.raise_for_status()
match = response.html.find(".search-result .match", first=True)
assert (
'<span class="match"><em>hjacobs/wrong-container-image:</em>0.1</span>'
== match.html
)

Loading…
Cancel
Save