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

knowledgepixels / nanodash / 19768361433

28 Nov 2025 03:44PM UTC coverage: 13.855% (-0.05%) from 13.909%
19768361433

push

github

tkuhn
feat(UserPage): Support for view displays (buttons still missing)

521 of 4896 branches covered (10.64%)

Branch coverage included in aggregate %.

1398 of 8955 relevant lines covered (15.61%)

0.69 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.google.common.collect.ArrayListMultimap;
4
import com.google.common.collect.Multimap;
5
import com.knowledgepixels.nanodash.*;
6
import com.knowledgepixels.nanodash.component.*;
7
import org.apache.wicket.Component;
8
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
9
import org.apache.wicket.markup.html.basic.Label;
10
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
11
import org.apache.wicket.model.Model;
12
import org.apache.wicket.request.flow.RedirectToUrlException;
13
import org.apache.wicket.request.mapper.parameter.PageParameters;
14
import org.eclipse.rdf4j.model.IRI;
15
import org.nanopub.extra.services.ApiResponse;
16
import org.nanopub.extra.services.QueryRef;
17
import org.slf4j.Logger;
18
import org.slf4j.LoggerFactory;
19

20
import java.util.ArrayList;
21
import java.util.List;
22

23
/**
24
 * Page that shows a user profile, including their nanopubs and stats.
25
 */
26
public class UserPage extends NanodashPage {
27

28
    private static final Logger logger = LoggerFactory.getLogger(UserPage.class);
×
29

30
    /**
31
     * The mount path for this page.
32
     */
33
    public static final String MOUNT_PATH = "/user";
34

35
    /**
36
     * {@inheritDoc}
37
     */
38
    @Override
39
    public String getMountPath() {
40
        return MOUNT_PATH;
×
41
    }
42

43
    private IRI userIri;
44
    private String pubkeyHashes = "";
×
45

46
    /**
47
     * Constructor for UserPage.
48
     *
49
     * @param parameters Page parameters, must include "id" with the user IRI.
50
     */
51
    public UserPage(final PageParameters parameters) {
52
        super(parameters);
×
53
        setOutputMarkupId(true);
×
54

55
        if (parameters.get("id") == null) throw new RedirectToUrlException(ProfilePage.MOUNT_PATH);
×
56
        final String userIriString = parameters.get("id").toString();
×
57
        userIri = Utils.vf.createIRI(userIriString);
×
58
        //NanodashSession session = NanodashSession.get();
59

60
        for (String pk : User.getPubkeyhashes(userIri, null)) {
×
61
            pubkeyHashes += " " + pk;
×
62
        }
×
63
        if (!pubkeyHashes.isEmpty()) pubkeyHashes = pubkeyHashes.substring(1);
×
64

65
        String pageType = "users";
×
66
        add(new TitleBar("titlebar", this, pageType));
×
67

68
        final String displayName = User.getShortDisplayName(userIri);
×
69
        add(new Label("pagetitle", displayName + " (user) | nanodash"));
×
70
        add(new Label("username", displayName));
×
71

72
        add(new BookmarkablePageLink<Void>("fullid", ExplorePage.class, parameters.set("label", displayName)).setBody(Model.of(userIriString)));
×
73

74
        add(new BookmarkablePageLink<Void>("showprofile", ProfilePage.class).setVisible(userIri.equals(NanodashSession.get().getUserIri())));
×
75

76
//                final Map<String,String> statsParams = new HashMap<>();
77
//                final String statsQueryName;
78
//                if (pubkeyHashes.isEmpty()) {
79
//                        statsQueryName = "get-user-stats-from-userid";
80
//                        statsParams.put("userid", userIriString);
81
//                } else {
82
//                        statsQueryName = "get-user-stats-from-pubkeys";
83
//                        statsParams.put("userid", userIriString);
84
//                        statsParams.put("pubkeyhashes", pubkeyHashes);
85
//                } 
86
//                Map<String,String> statsMap = ApiCache.retrieveMap(statsQueryName, statsParams);
87
//                if (statsMap != null) {
88
//                        add(new StatsPanel("stats", userIriString, pubkeyHashes, statsMap));
89
//                } else {
90
//                        add(new AjaxLazyLoadPanel<Component>("stats") {
91
//        
92
//                                @Override
93
//                                public Component getLazyLoadComponent(String markupId) {
94
//                                        Map<String,String> m = null;
95
//                                        while (true) {
96
//                                                try {
97
//                                                        Thread.sleep(500);
98
//                                                } catch (InterruptedException ex) {
99
//                                                        logger.error();
100
//                                                }
101
//                                                if (!ApiCache.isRunning(statsQueryName, statsParams)) {
102
//                                                        m = ApiCache.retrieveMap(statsQueryName, statsParams);
103
//                                                        if (m != null) break;
104
//                                                }
105
//                                        }
106
//                                        return new StatsPanel(markupId, userIriString, pubkeyHashes, m);
107
//                                }
108
//
109
//                                @Override
110
//                                protected void onContentLoaded(Component content, Optional<AjaxRequestTarget> target) {
111
//                                        super.onContentLoaded(content, target);
112
//                                        if (target.get() != null) target.get().appendJavaScript("updateElements();");
113
//                                }
114
//        
115
//                        });
116
//                }
117

118
        add(new BookmarkablePageLink<Void>("showchannel", ListPage.class, new PageParameters().add("userid", userIriString)));
×
119

120
        final Multimap<String, String> params = ArrayListMultimap.create();
×
121
        final String queryName;
122
        if (pubkeyHashes.isEmpty()) {
×
123
            queryName = "get-latest-nanopubs-from-userid";
×
124
            params.put("userid", userIri.stringValue());
×
125
        } else {
126
            queryName = "get-latest-nanopubs-from-pubkeys";
×
127
            params.put("pubkeyhashes", pubkeyHashes);
×
128
            params.put("userid", userIri.stringValue());
×
129
        }
130
        final QueryRef queryRef = new QueryRef(queryName, params);
×
131
        ApiResponse response = ApiCache.retrieveResponse(queryRef);
×
132
        if (response != null) {
×
133
            add(makeNanopubResultComponent("latestnanopubs", response));
×
134
        } else {
135
            add(new AjaxLazyLoadPanel<Component>("latestnanopubs") {
×
136

137
                @Override
138
                public Component getLazyLoadComponent(String markupId) {
139
                    ApiResponse r = null;
×
140
                    while (true) {
141
                        try {
142
                            Thread.sleep(500);
×
143
                        } catch (InterruptedException ex) {
×
144
                            logger.error("Thread interrupted while waiting for API response", ex);
×
145
                        }
×
146
                        if (!ApiCache.isRunning(queryRef)) {
×
147
                            r = ApiCache.retrieveResponse(queryRef);
×
148
                            if (r != null) break;
×
149
                        }
150
                    }
151
                    return makeNanopubResultComponent(markupId, r);
×
152
                }
153

154
//                                @Override
155
//                                protected void onContentLoaded(Component content, Optional<AjaxRequestTarget> target) {
156
//                                        super.onContentLoaded(content, target);
157
//                                        if (target.get() != null) target.get().appendJavaScript("updateElements();");
158
//                                }
159

160
            });
161
        }
162

163
        Space.triggerAllDataUpdates();
×
164
        add(new ItemListPanel<Space>(
×
165
                "spaces",
166
                "Spaces",
167
                () -> Space.areAllSpacesInitialized(),
×
168
                () -> {
169
                    List<Space> spaces = new ArrayList<>();
×
170
                    for (Space space : Space.getSpaceList()) {
×
171
                        if (space.isMember(userIri)) spaces.add(space);
×
172
                    }
×
173
                    return spaces;
×
174
                },
175
                (s) -> new ItemListElement("item", SpacePage.class, new PageParameters().set("id", s.getId()), s.getLabel(), "(" + s.getTypeLabel() + ")", null)
×
176
        ));
177

178
        if (pubkeyHashes.isEmpty()) {
×
179
            add(new Label("activity", "<span class=\"negative\">Activity cannot be shown for this user due to missing user introduction.</span>").setEscapeModelStrings(false));
×
180
        } else {
181
            final QueryRef activityQueryRef = new QueryRef("get-monthly-type-overview-by-pubkeys");
×
182
            for (String pk : pubkeyHashes.split(" ")) {
×
183
                activityQueryRef.getParams().put("pubkey", pk);
×
184
            }
185
            ApiResponse activityQueryResponse = ApiCache.retrieveResponse(activityQueryRef);
×
186
            if (activityQueryResponse != null) {
×
187
                if (activityQueryResponse.getData().isEmpty()) {
×
188
                    add(new Label("activity", "<em>No recent activity to show for this user.</em>").setEscapeModelStrings(false));
×
189
                } else {
190
                    add(new ActivityPanel("activity", activityQueryResponse));
×
191
                }
192
            } else {
193
                add(new ApiResultComponent("activity", activityQueryRef) {
×
194

195
                    @Override
196
                    public Component getApiResultComponent(String markupId, ApiResponse response) {
197
                        if (response.getData().isEmpty()) {
×
198
                            return new Label(markupId, "<em>No recent activity to show for this user.</em>").setEscapeModelStrings(false);
×
199
                        } else {
200
                            return new ActivityPanel(markupId, response);
×
201
                        }
202
                    }
203
                });
204

205
            }
206
        }
207

208
        IndividualAgent individualAgent = IndividualAgent.get(userIriString);
×
209
        if (individualAgent.isDataInitialized()) {
×
210
            add(new ViewList("views", individualAgent));
×
211
        } else {
212
            add(new AjaxLazyLoadPanel<Component>("views") {
×
213
    
214
                @Override
215
                public Component getLazyLoadComponent(String markupId) {
216
                    return new ViewList(markupId, individualAgent);
×
217
                }
218
    
219
                @Override
220
                protected boolean isContentReady() {
221
                    return individualAgent.isDataInitialized();
×
222
                }
223
    
224
            });
225
        }
226
    }
×
227

228
    private static Component makeNanopubResultComponent(String markupId, ApiResponse response) {
229
        if (response.getData().isEmpty()) {
×
230
            return new Label(markupId, "(none)");
×
231
        } else {
232
            return NanopubResults.fromApiResponse(markupId, response, 5);
×
233
        }
234
    }
235

236
    /**
237
     * <p>hasAutoRefreshEnabled.</p>
238
     *
239
     * @return a boolean
240
     */
241
    protected boolean hasAutoRefreshEnabled() {
242
        return true;
×
243
    }
244

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