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

knowledgepixels / nanodash / 27145358627

08 Jun 2026 02:39PM UTC coverage: 20.682% (-0.3%) from 20.947%
27145358627

push

github

web-flow
Merge pull request #479 from knowledgepixels/feat/about-pages-478

Resource-page tabs, presets, and role-gated view actions (#478, #302)

1052 of 6429 branches covered (16.36%)

Branch coverage included in aggregate %.

2642 of 11432 relevant lines covered (23.11%)

3.31 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 {
108
                        item.add(new Label("listItem", value));
×
109
                        return;
×
110
                    }
111
                }
112
                item.add(new Label("listItem", ""));
×
113
            }
×
114
        };
115
        dataView.setItemsPerPage(viewDisplay.getPageSize());
×
116

117
        WebMarkupContainer navigation = new WebMarkupContainer("navigation");
×
118
        navigation.add(new NavigatorLabel("navigatorLabel", dataView));
×
119
        AjaxPagingNavigator pagingNavigator = new AjaxPagingNavigator("navigator", dataView);
×
120
        navigation.setVisible(dataView.getPageCount() > 1);
×
121
        navigation.add(pagingNavigator);
×
122

123
        Label noRecordsLabel = new Label("no-records", "(nothing found)") {
×
124
            @Override
125
            protected void onConfigure() {
126
                super.onConfigure();
×
127
                setVisible(filteredDataProvider.size() == 0);
×
128
            }
×
129
        };
130

131
        itemsContainer = new WebMarkupContainer("items-container");
×
132
        itemsContainer.setOutputMarkupId(true);
×
133
        itemsContainer.add(dataView);
×
134
        itemsContainer.add(noRecordsLabel);
×
135
        itemsContainer.add(navigation);
×
136
        add(itemsContainer);
×
137
    }
×
138
}
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