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

knowledgepixels / nanodash / 22940870611

11 Mar 2026 07:03AM UTC coverage: 15.749% (+0.02%) from 15.73%
22940870611

Pull #382

github

web-flow
Merge 02d79f650 into 6fa5481c1
Pull Request #382: Refactor HTML pages using Wicket markup inheritance

705 of 5423 branches covered (13.0%)

Branch coverage included in aggregate %.

1743 of 10121 relevant lines covered (17.22%)

2.35 hits per line

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

0.0
src/main/java/com/knowledgepixels/nanodash/page/UserPage.java
1
package com.knowledgepixels.nanodash.page;
2

3
import com.knowledgepixels.nanodash.NanodashSession;
4
import com.knowledgepixels.nanodash.Utils;
5
import com.knowledgepixels.nanodash.View;
6
import com.knowledgepixels.nanodash.ViewDisplay;
7
import com.knowledgepixels.nanodash.component.*;
8
import com.knowledgepixels.nanodash.domain.IndividualAgent;
9
import com.knowledgepixels.nanodash.domain.User;
10
import org.apache.wicket.Component;
11
import org.apache.wicket.ajax.AjaxRequestTarget;
12
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
13
import org.apache.wicket.markup.html.WebMarkupContainer;
14
import org.apache.wicket.markup.html.basic.Label;
15
import org.apache.wicket.markup.html.image.ExternalImage;
16
import org.apache.wicket.markup.html.image.Image;
17
import org.apache.wicket.markup.html.link.AbstractLink;
18
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
19
import org.apache.wicket.markup.html.panel.EmptyPanel;
20
import org.apache.wicket.model.Model;
21
import org.apache.wicket.request.flow.RedirectToUrlException;
22
import org.apache.wicket.request.mapper.parameter.PageParameters;
23
import org.apache.wicket.request.resource.ContextRelativeResourceReference;
24
import org.eclipse.rdf4j.model.IRI;
25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
27

28
import java.util.ArrayList;
29
import java.util.List;
30
import java.util.Optional;
31

32
/**
33
 * Page that shows a user profile, including their nanopubs and stats.
34
 */
35
public class UserPage extends NanodashPage {
36

37
    private static final Logger logger = LoggerFactory.getLogger(UserPage.class);
×
38

39
    /**
40
     * The mount path for this page.
41
     */
42
    public static final String MOUNT_PATH = "/user";
43

44
    /**
45
     * {@inheritDoc}
46
     */
47
    @Override
48
    public String getMountPath() {
49
        return MOUNT_PATH;
×
50
    }
51

52
    private IRI userIri;
53
    private String pubkeyHashes = "";
×
54

55
    /**
56
     * Constructor for UserPage.
57
     *
58
     * @param parameters Page parameters, must include "id" with the user IRI.
59
     */
60
    public UserPage(final PageParameters parameters) {
61
        super(parameters);
×
62
        setOutputMarkupId(true);
×
63

64
        if (parameters.get("id") == null) throw new RedirectToUrlException(ProfilePage.MOUNT_PATH);
×
65
        final String userIriString = parameters.get("id").toString();
×
66
        userIri = Utils.vf.createIRI(userIriString);
×
67

68
        for (String pk : User.getPubkeyhashes(userIri, null)) {
×
69
            pubkeyHashes += " " + pk;
×
70
        }
×
71
        if (!pubkeyHashes.isEmpty()) pubkeyHashes = pubkeyHashes.substring(1);
×
72

73
        String pageType = "users";
×
74
        add(new TitleBar("titlebar", this, pageType));
×
75

76
        add(new JustPublishedMessagePanel("justPublishedMessage", parameters));
×
77

78
        IRI profilePictureIri = User.getProfilePicture(userIri);
×
79
        if (profilePictureIri != null) {
×
80
            ExternalImage userIcon = new ExternalImage("userIcon", profilePictureIri);
×
81
            add(userIcon);
×
82
        } else {
×
83
            boolean isSoftware = IndividualAgent.isSoftware(userIri);
×
84
            Image userIcon;
85
            if (isSoftware) {
×
86
                userIcon = new Image("userIcon", new ContextRelativeResourceReference("images/bot-icon.svg", false));
×
87
            } else {
88
                userIcon = new Image("userIcon", new ContextRelativeResourceReference("images/user-icon.svg", false));
×
89

90
            }
91
            add(userIcon);
×
92
        }
93

94
        final String displayName = User.getShortDisplayName(userIri);
×
95
        add(new Label("pagetitle", displayName + " (user) | nanodash"));
×
96
        add(new Label("username", displayName));
×
97

98
        add(new ExternalLinkWithActionsPanel("fullid", Model.of(userIriString), Model.of(displayName)));
×
99
        add(new BookmarkablePageLink<Void>("showprofile", ProfilePage.class).setVisible(userIri.equals(NanodashSession.get().getUserIri())));
×
100
        add(new BookmarkablePageLink<Void>("showchannel", ListPage.class, new PageParameters().add("userid", userIriString)));
×
101

102

103
//                final Map<String,String> statsParams = new HashMap<>();
104
//                final String statsQueryName;
105
//                if (pubkeyHashes.isEmpty()) {
106
//                        statsQueryName = "get-user-stats-from-userid";
107
//                        statsParams.put("userid", userIriString);
108
//                } else {
109
//                        statsQueryName = "get-user-stats-from-pubkeys";
110
//                        statsParams.put("userid", userIriString);
111
//                        statsParams.put("pubkeyhashes", pubkeyHashes);
112
//                } 
113
//                Map<String,String> statsMap = ApiCache.retrieveMap(statsQueryName, statsParams);
114
//                if (statsMap != null) {
115
//                        add(new StatsPanel("stats", userIriString, pubkeyHashes, statsMap));
116
//                } else {
117
//                        add(new AjaxLazyLoadPanel<Component>("stats") {
118
//        
119
//                                @Override
120
//                                public Component getLazyLoadComponent(String markupId) {
121
//                                        Map<String,String> m = null;
122
//                                        while (true) {
123
//                                                try {
124
//                                                        Thread.sleep(500);
125
//                                                } catch (InterruptedException ex) {
126
//                                                        logger.error();
127
//                                                }
128
//                                                if (!ApiCache.isRunning(statsQueryName, statsParams)) {
129
//                                                        m = ApiCache.retrieveMap(statsQueryName, statsParams);
130
//                                                        if (m != null) break;
131
//                                                }
132
//                                        }
133
//                                        return new StatsPanel(markupId, userIriString, pubkeyHashes, m);
134
//                                }
135
//
136
//                                @Override
137
//                                protected void onContentLoaded(Component content, Optional<AjaxRequestTarget> target) {
138
//                                        super.onContentLoaded(content, target);
139
//                                        if (target.get() != null) target.get().appendJavaScript("updateElements();");
140
//                                }
141
//        
142
//                        });
143
//                }
144

145
        final List<AbstractLink> viewButtons = new ArrayList<>();
×
146
        viewButtons.add(new AddViewDisplayButton("button",
×
147
                        "https://w3id.org/np/RAQhTCHtfzGCj1YiE1LualWcZjg3thlRiquFWUE14UF-g",
148
                        "latest",
149
                        userIriString,
150
                        userIriString,
151
                        new PageParameters()
152
                                .set("refresh-upon-publish", userIriString)
×
153
                                .set("param_appliesToResource", userIriString)
×
154
                )
155
        );
156

157
        IndividualAgent individualAgent = IndividualAgent.get(userIriString);
×
158
        if (individualAgent.isDataInitialized()) {
×
159
            boolean empty = individualAgent.getTopLevelViewDisplays().isEmpty();
×
160
            if (empty) {
×
161
                add(new WebMarkupContainer("views").setVisible(false));
×
162
            } else {
163
                add(new ViewList("views", individualAgent, null, null, null, individualAgent, viewButtons, false));
×
164
            }
165
            add(new WebMarkupContainer("unconfigured-notice").setVisible(empty));
×
166
            if (empty) {
×
167
                ViewDisplay defaultViewDisplay = new ViewDisplay(View.get("https://w3id.org/np/RAjYa33Z3H1whRl486AW3LMnV11WQqkTqvuHROhKbmtlE/latest-nanopubs-example"));
×
168
                add(new ViewList("latestnanopubsview", individualAgent, List.of(defaultViewDisplay), individualAgent, viewButtons));
×
169
            } else {
×
170
                add(new EmptyPanel("latestnanopubsview").setVisible(false));
×
171
            }
172
        } else {
×
173
            final WebMarkupContainer unconfiguredNotice = new WebMarkupContainer("unconfigured-notice");
×
174
            unconfiguredNotice.setVisible(false);
×
175
            unconfiguredNotice.setOutputMarkupPlaceholderTag(true);
×
176
            add(unconfiguredNotice);
×
177

178
            ViewDisplay defaultViewDisplay = new ViewDisplay(View.get("https://w3id.org/np/RAjYa33Z3H1whRl486AW3LMnV11WQqkTqvuHROhKbmtlE/latest-nanopubs-example"));
×
179
            final ViewList latestNanopubsView = new ViewList("latestnanopubsview", individualAgent, List.of(defaultViewDisplay), individualAgent, viewButtons);
×
180
            latestNanopubsView.setVisible(false);
×
181
            latestNanopubsView.setOutputMarkupPlaceholderTag(true);
×
182
            add(latestNanopubsView);
×
183

184
            add(new AjaxLazyLoadPanel<Component>("views") {
×
185

186
                @Override
187
                public Component getLazyLoadComponent(String markupId) {
188
                    if (individualAgent.getTopLevelViewDisplays().isEmpty()) {
×
189
                        return new ViewList(markupId, individualAgent, null, null, null, null, null, false);
×
190
                    }
191
                    return new ViewList(markupId, individualAgent, null, null, null, individualAgent, viewButtons, false);
×
192
                }
193

194
                @Override
195
                protected boolean isContentReady() {
196
                    return individualAgent.isDataInitialized();
×
197
                }
198

199
                @Override
200
                public Component getLoadingComponent(String id) {
201
                    return new Label(id, "<div class=\"row-section\"><div class=\"col-12\">" + ResultComponent.getWaitIconHtml() + "</div></div>").setEscapeModelStrings(false);
×
202
                }
203

204
                @Override
205
                protected void onContentLoaded(Component content, Optional<AjaxRequestTarget> target) {
206
                    super.onContentLoaded(content, target);
×
207
                    target.ifPresent(t -> {
×
208
                        boolean isEmpty = individualAgent.getTopLevelViewDisplays().isEmpty();
×
209
                        if (isEmpty) {
×
210
                            t.appendJavaScript("document.getElementById('" + getMarkupId() + "').remove();");
×
211
                        }
212
                        unconfiguredNotice.setVisible(isEmpty);
×
213
                        t.add(unconfiguredNotice);
×
214
                        latestNanopubsView.setVisible(isEmpty);
×
215
                        t.add(latestNanopubsView);
×
216
                    });
×
217
                }
×
218

219
            });
220
        }
221
    }
×
222

223
    /**
224
     * <p>hasAutoRefreshEnabled.</p>
225
     *
226
     * @return a boolean
227
     */
228
    protected boolean hasAutoRefreshEnabled() {
229
        return true;
×
230
    }
231

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