• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

knowledgepixels / nanodash / 27947621262

22 Jun 2026 10:54AM UTC coverage: 26.57% (-0.06%) from 26.63%
27947621262

push

github

web-flow
Merge pull request #492 from knowledgepixels/fix/observers-non-approved-union-scoping

feat: position-column tooltip labels on view-displays tables

1552 of 6873 branches covered (22.58%)

Branch coverage included in aggregate %.

3418 of 11832 relevant lines covered (28.89%)

4.25 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
src/main/java/com/knowledgepixels/nanodash/component/QueryResultItemList.java
1
package com.knowledgepixels.nanodash.component;
2

3
import com.knowledgepixels.nanodash.*;
4
import com.knowledgepixels.nanodash.domain.IndividualAgent;
5
import com.knowledgepixels.nanodash.domain.User;
6
import com.knowledgepixels.nanodash.page.PublishPage;
7
import com.knowledgepixels.nanodash.page.UserPage;
8
import org.apache.wicket.ajax.AjaxRequestTarget;
9
import org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigator;
10
import org.apache.wicket.extensions.markup.html.repeater.data.table.NavigatorLabel;
11
import org.apache.wicket.markup.html.WebMarkupContainer;
12
import org.apache.wicket.markup.html.basic.Label;
13
import org.apache.wicket.markup.html.form.TextField;
14
import org.apache.wicket.markup.repeater.Item;
15
import org.apache.wicket.markup.repeater.data.DataView;
16
import org.apache.wicket.model.Model;
17
import org.apache.wicket.request.cycle.RequestCycle;
18
import org.apache.wicket.request.resource.ContextRelativeResourceReference;
19
import org.apache.wicket.util.string.Strings;
20
import org.eclipse.rdf4j.model.IRI;
21
import org.nanopub.extra.services.ApiResponse;
22
import org.nanopub.extra.services.ApiResponseEntry;
23
import org.nanopub.extra.services.QueryRef;
24

25
/**
26
 * Component for displaying query results as a vertical item list.
27
 * Each result row is rendered as a single linked item, with icon handling
28
 * for user_iri and template_iri columns.
29
 */
30
public class QueryResultItemList extends QueryResult {
31

32
    private FilteredQueryResultDataProvider filteredDataProvider;
33
    private final Model<String> filterModel = Model.of("");
×
34
    private WebMarkupContainer itemsContainer;
35

36
    QueryResultItemList(String markupId, QueryRef queryRef, ApiResponse response, ViewDisplay viewDisplay) {
37
        super(markupId, queryRef, response, viewDisplay);
×
38

39
        String label = grlcQuery.getLabel();
×
40
        if (viewDisplay.getTitle() != null) {
×
41
            label = viewDisplay.getTitle();
×
42
        }
43
        add(new Label("label", label));
×
44
        setOutputMarkupId(true);
×
45

46
        TextField<String> filterField = new TextField<>("filter", filterModel);
×
47
        filterField.setOutputMarkupId(true);
×
48
        filterField.add(new FilterUpdatingBehavior() {
×
49
            @Override
50
            protected void onUpdate(AjaxRequestTarget target) {
51
                if (filteredDataProvider != null && itemsContainer != null) {
×
52
                    filteredDataProvider.setFilterText(filterModel.getObject());
×
53
                    target.add(itemsContainer);
×
54
                }
55
            }
×
56
        });
57
        filterField.setVisible(!fitsOnFirstPage());
×
58
        add(filterField);
×
59

60
        populateComponent();
×
61
    }
×
62

63
    @Override
64
    protected void populateComponent() {
65
        QueryResultDataProvider dataProvider = new QueryResultDataProvider(response.getData());
×
66
        filteredDataProvider = new FilteredQueryResultDataProvider(dataProvider, response);
×
67

68
        DataView<ApiResponseEntry> dataView = new DataView<>("items", filteredDataProvider) {
×
69
            @Override
70
            protected void populateItem(Item<ApiResponseEntry> item) {
71
                ApiResponseEntry entry = item.getModelObject();
×
72
                for (String key : response.getHeader()) {
×
73
                    if (key.endsWith("_label") || key.endsWith("_label_multi")) continue;
×
74
                    String value = entry.get(key);
×
75
                    if (value == null || value.isBlank()) continue;
×
76
                    String entryLabel = entry.get(key + "_label");
×
77

78
                    if (key.endsWith("user_iri")) {
×
79
                        IRI userIri = Utils.vf.createIRI(value);
×
80
                        IRI profilePicIri = User.getProfilePicture(userIri);
×
81
                        String imgSrc;
82
                        String iconClass;
83
                        if (profilePicIri != null) {
×
84
                            imgSrc = Strings.escapeMarkup(profilePicIri.stringValue()).toString();
×
85
                            iconClass = "user-icon";
×
86
                        } else if (IndividualAgent.isSoftware(userIri)) {
×
87
                            imgSrc = RequestCycle.get().urlFor(new ContextRelativeResourceReference("images/bot-icon.svg", false), null).toString();
×
88
                            iconClass = "bot-icon";
×
89
                        } else {
90
                            imgSrc = RequestCycle.get().urlFor(new ContextRelativeResourceReference("images/user-icon.svg", false), null).toString();
×
91
                            iconClass = "user-icon";
×
92
                        }
93
                        String displayLabel = (entryLabel != null && !entryLabel.isBlank()) ? entryLabel : User.getShortDisplayName(userIri);
×
94
                        String userUrl = UserPage.MOUNT_PATH + "?id=" + Utils.urlEncode(value);
×
95
                        String html = "<img class=\"" + iconClass + "\" src=\"" + imgSrc + "\" /> <a href=\"" + Strings.escapeMarkup(userUrl) + "\">" + Strings.escapeMarkup(displayLabel) + "</a>";
×
96
                        item.add(new Label("listItem", html).setEscapeModelStrings(false));
×
97
                        return;
×
98
                    } else if (key.endsWith("template_iri")) {
×
99
                        String displayLabel = (entryLabel != null && !entryLabel.isBlank()) ? entryLabel : value;
×
100
                        String templateUrl = PublishPage.MOUNT_PATH + "?template=" + Utils.urlEncode(value) + "&template-version=latest";
×
101
                        String html = "<span class=\"form-icon\"></span> <a href=\"" + Strings.escapeMarkup(templateUrl) + "\">" + Strings.escapeMarkup(displayLabel) + "</a>";
×
102
                        item.add(new Label("listItem", html).setEscapeModelStrings(false));
×
103
                        return;
×
104
                    } else if (value.matches("https?://.*")) {
×
105
                        item.add(new NanodashLink("listItem", value, null, null, entryLabel, contextId));
×
106
                        return;
×
107
                    } else if (entryLabel != null && !entryLabel.isBlank() && !entryLabel.equals(value)) {
×
108
                        // Separate display label for a (non-IRI) literal value; the full
109
                        // literal is shown on hover via the standard styled tooltip.
110
                        String html = "<span class=\"tooltip\"><span class=\"tooltiptext tooltiptext-auto\">" + Strings.escapeMarkup(value) + "</span>" + Strings.escapeMarkup(entryLabel) + "</span>";
×
111
                        item.add(new Label("listItem", html).setEscapeModelStrings(false));
×
112
                        return;
×
113
                    } else {
114
                        item.add(new Label("listItem", value));
×
115
                        return;
×
116
                    }
117
                }
118
                item.add(new Label("listItem", ""));
×
119
            }
×
120
        };
121
        dataView.setItemsPerPage(viewDisplay.getPageSize());
×
122

123
        WebMarkupContainer navigation = new WebMarkupContainer("navigation");
×
124
        navigation.add(new NavigatorLabel("navigatorLabel", dataView));
×
125
        AjaxPagingNavigator pagingNavigator = new AjaxPagingNavigator("navigator", dataView);
×
126
        navigation.setVisible(dataView.getPageCount() > 1);
×
127
        navigation.add(pagingNavigator);
×
128

129
        Label noRecordsLabel = new Label("no-records", "(nothing found)") {
×
130
            @Override
131
            protected void onConfigure() {
132
                super.onConfigure();
×
133
                setVisible(filteredDataProvider.size() == 0);
×
134
            }
×
135
        };
136

137
        itemsContainer = new WebMarkupContainer("items-container");
×
138
        itemsContainer.setOutputMarkupId(true);
×
139
        itemsContainer.add(dataView);
×
140
        itemsContainer.add(noRecordsLabel);
×
141
        itemsContainer.add(navigation);
×
142
        add(itemsContainer);
×
143
    }
×
144
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc