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

knowledgepixels / nanodash / 27622721129

16 Jun 2026 01:55PM UTC coverage: 26.963% (+6.3%) from 20.697%
27622721129

Pull #483

github

web-flow
Merge 73a4d0fe1 into 663f14f46
Pull Request #483: Space/resource About pages, ref-aware spaces, and magic query params

1542 of 6717 branches covered (22.96%)

Branch coverage included in aggregate %.

3407 of 11638 relevant lines covered (29.27%)

4.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/QueryResult.java
1
package com.knowledgepixels.nanodash;
2

3
import com.knowledgepixels.nanodash.component.menu.ViewDisplayMenu;
4
import com.knowledgepixels.nanodash.domain.AbstractResourceWithProfile;
5
import com.knowledgepixels.nanodash.page.NanodashPage;
6
import org.apache.wicket.markup.html.basic.Label;
7
import org.apache.wicket.markup.html.panel.Panel;
8
import org.apache.wicket.request.mapper.parameter.PageParameters;
9
import org.nanopub.extra.services.ApiResponse;
10
import org.nanopub.extra.services.QueryRef;
11

12
import java.io.Serializable;
13
import java.util.ArrayList;
14
import java.util.List;
15

16
/**
17
 * Abstract base class for displaying query results in different formats.
18
 */
19
public abstract class QueryResult extends Panel {
20

21
    /**
22
     * A view-level action, shown as a top entry of the view's dropdown menu.
23
     */
24
    public record MenuAction(String label, Class<? extends NanodashPage> pageClass, PageParameters params) implements Serializable {
×
25
    }
26

27
    protected final List<MenuAction> menuActions = new ArrayList<>();
×
28
    protected String contextId;
29
    protected String partId;
30
    protected String postPublishTab;
31
    protected boolean finalized = false;
×
32
    protected final QueryRef queryRef;
33
    protected final ViewDisplay viewDisplay;
34
    protected final ApiResponse response;
35
    protected AbstractResourceWithProfile resourceWithProfile;
36
    protected AbstractResourceWithProfile pageResource;
37
    protected boolean showViewDisplayMenu = true;
×
38
    protected final GrlcQuery grlcQuery;
39

40
    /**
41
     * Constructor for QueryResult.
42
     *
43
     * @param markupId    the markup ID
44
     * @param queryRef    the query reference
45
     * @param response    the API response
46
     * @param viewDisplay the view display
47
     */
48
    public QueryResult(String markupId, QueryRef queryRef, ApiResponse response, ViewDisplay viewDisplay) {
49
        super(markupId);
×
50
        this.queryRef = queryRef;
×
51
        this.viewDisplay = viewDisplay;
×
52
        this.response = response;
×
53
        this.grlcQuery = GrlcQuery.get(queryRef);
×
54
    }
×
55

56
    @Override
57
    protected void onBeforeRender() {
58
        if (!finalized) {
×
59
            // View-level actions used to render as a button strip in the header here;
60
            // they now live as the top entries of the view's dropdown menu instead.
61
            add(new Label("buttons").setVisible(false));
×
62
            if (showViewDisplayMenu) {
×
63
                if (viewDisplay.getNanopubId() != null || !menuActions.isEmpty()) {
×
64
                    add(new ViewDisplayMenu("np", viewDisplay, queryRef, pageResource, menuActions));
×
65
                } else {
66
                    add(new Label("np").setVisible(false));
×
67
                }
68
            }
69
            finalized = true;
×
70
        }
71
        super.onBeforeRender();
×
72
    }
×
73

74
    /**
75
     * The view-level actions to render as top entries of the view's dropdown menu.
76
     *
77
     * @return the collected view-level menu actions
78
     */
79
    public List<MenuAction> getMenuActions() {
80
        return menuActions;
×
81
    }
82

83
    /**
84
     * Set the resource with profile for this component.
85
     *
86
     * @param resourceWithProfile The resource with profile to set.
87
     */
88
    public void setResourceWithProfile(AbstractResourceWithProfile resourceWithProfile) {
89
        this.resourceWithProfile = resourceWithProfile;
×
90
    }
×
91

92
    public void setPageResource(AbstractResourceWithProfile pageResource) {
93
        this.pageResource = pageResource;
×
94
    }
×
95

96
    /**
97
     * Set the context ID for this component.
98
     *
99
     * @param contextId The context ID to set.
100
     */
101
    public void setContextId(String contextId) {
102
        this.contextId = contextId;
×
103
    }
×
104

105
    /**
106
     * Set the part ID when this view is shown on a part page (e.g. paper collection).
107
     * Used for redirect-after-publish to return to the part page.
108
     *
109
     * @param partId The part ID to set, or null when on the main context page.
110
     */
111
    public void setPartId(String partId) {
112
        this.partId = partId;
×
113
    }
×
114

115
    /**
116
     * Set the tab to return to after publishing one of this view's action
117
     * buttons (e.g. {@code "about"} so a space's About-tab views send the user
118
     * back to About instead of the default Content tab). Null leaves the
119
     * post-publish redirect on its default tab.
120
     *
121
     * @param postPublishTab the tab name, or null for the default
122
     */
123
    public void setPostPublishTab(String postPublishTab) {
124
        this.postPublishTab = postPublishTab;
×
125
    }
×
126

127
    /**
128
     * @return the tab to return to after publishing via an action button, or null for the default
129
     */
130
    public String getPostPublishTab() {
131
        return postPublishTab;
×
132
    }
133

134
    // A view-level action button; collected here and rendered as a top entry of the
135
    // view's dropdown menu (see ViewDisplayMenu).
136
    public void addButton(String label, Class<? extends NanodashPage> pageClass, PageParameters parameters) {
137
        if (parameters == null) {
×
138
            parameters = new PageParameters();
×
139
        }
140
        if (contextId != null) {
×
141
            parameters.set("context", contextId);
×
142
        }
143
        menuActions.add(new MenuAction(label, pageClass, parameters));
×
144
    }
×
145

146
    /**
147
     * Whether all result rows fit on the first page, so no pagination is needed
148
     * and the filter textfield can be hidden. Also true when the page size is
149
     * unlimited ({@code < 1}).
150
     *
151
     * @return true if all entries fit on the first page
152
     */
153
    protected boolean fitsOnFirstPage() {
154
        int pageSize = viewDisplay.getPageSize();
×
155
        return pageSize < 1 || response.getData().size() <= pageSize;
×
156
    }
157

158
    /**
159
     * Whether the empty state should point the viewer to the view-level actions:
160
     * the underlying response (not just a filtered view of it) has no rows, and
161
     * there is at least one action the viewer is entitled to.
162
     *
163
     * @return true if the empty-state call-to-action buttons should show
164
     */
165
    protected boolean hasEmptyStateActions() {
166
        return response.getData().isEmpty() && !menuActions.isEmpty();
×
167
    }
168

169
    /**
170
     * Populate the component with the query results.
171
     */
172
    protected abstract void populateComponent();
173

174
}
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