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

knowledgepixels / nanodash / 18653097879

20 Oct 2025 01:11PM UTC coverage: 13.053% (-0.5%) from 13.583%
18653097879

push

github

web-flow
Merge pull request #265 from knowledgepixels/252-datetime-picker-datetime-literal-placeholders

Add date pickers for date/datetime literal placeholders

450 of 4316 branches covered (10.43%)

Branch coverage included in aggregate %.

1157 of 7995 relevant lines covered (14.47%)

0.65 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/SpacePage.java
1
package com.knowledgepixels.nanodash.page;
2

3
import java.time.LocalDateTime;
4
import java.time.ZoneId;
5
import java.time.format.DateTimeFormatter;
6
import java.util.ArrayList;
7
import java.util.List;
8

9
import org.apache.wicket.Component;
10
import org.apache.wicket.extensions.ajax.markup.html.AjaxLazyLoadPanel;
11
import org.apache.wicket.markup.html.basic.Label;
12
import org.apache.wicket.markup.html.link.AbstractLink;
13
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
14
import org.apache.wicket.markup.html.link.ExternalLink;
15
import org.apache.wicket.model.Model;
16
import org.apache.wicket.request.mapper.parameter.PageParameters;
17
import org.eclipse.rdf4j.model.IRI;
18
import org.nanopub.Nanopub;
19
import org.nanopub.extra.services.FailedApiCallException;
20

21
import com.knowledgepixels.nanodash.Space;
22
import com.knowledgepixels.nanodash.SpaceMemberRole;
23
import com.knowledgepixels.nanodash.User;
24
import com.knowledgepixels.nanodash.Utils;
25
import com.knowledgepixels.nanodash.component.ButtonList;
26
import com.knowledgepixels.nanodash.component.ItemListElement;
27
import com.knowledgepixels.nanodash.component.ItemListPanel;
28
import com.knowledgepixels.nanodash.component.PinGroupList;
29
import com.knowledgepixels.nanodash.component.SpaceUserList;
30
import com.knowledgepixels.nanodash.component.TitleBar;
31
import com.knowledgepixels.nanodash.component.ViewList;
32
import com.knowledgepixels.nanodash.connector.ConnectorConfig;
33
import com.knowledgepixels.nanodash.connector.GenOverviewPage;
34

35
/**
36
 * The ProjectPage class represents a space page in the Nanodash application.
37
 */
38
public class SpacePage extends NanodashPage {
39

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

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

53
    /**
54
     * Space object with the data shown on this page.
55
     */
56
    private Space space;
57

58
    private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
×
59

60
    /**
61
     * Constructor for the SpacePage.
62
     *
63
     * @param parameters the page parameters
64
     * @throws org.nanopub.extra.services.FailedApiCallException if the API call fails
65
     */
66
    public SpacePage(final PageParameters parameters) throws FailedApiCallException {
67
        super(parameters);
×
68

69
        space = Space.get(parameters.get("id").toString());
×
70
        Nanopub np = space.getRootNanopub();
×
71

72
        add(new TitleBar("titlebar", this, "connectors"));
×
73

74
        add(new Label("pagetitle", space.getLabel() + " (space) | nanodash"));
×
75
        add(new Label("spacename", space.getLabel()));
×
76
        add(new Label("spacetype", space.getTypeLabel()));
×
77
        add(new ExternalLink("id", space.getId(), space.getId()));
×
78
        add(new BookmarkablePageLink<Void>("np", ExplorePage.class, new PageParameters().add("id", np.getUri())));
×
79

80
        add(new ItemListPanel<String>(
×
81
                "altids",
82
                "Alternative IDs:",
83
                space.getAltIDs(),
×
84
                id -> new ItemListElement("item", ExplorePage.class, new PageParameters().add("id", id), id)
×
85
            ));
86

87
        if (space.getStartDate() != null) {
×
88
            String dateString;
89
            LocalDateTime dt = LocalDateTime.ofInstant(space.getStartDate().toInstant(), ZoneId.systemDefault());
×
90
            dateString = dateTimeFormatter.format(dt);
×
91
            if (space.getEndDate() != null) {
×
92
                dt = LocalDateTime.ofInstant(space.getEndDate().toInstant(), ZoneId.systemDefault());
×
93
                String endDate = dateTimeFormatter.format(dt);
×
94
                if (!dateString.equals(endDate)) {
×
95
                    dateString += " - " + endDate;
×
96
                }
97
            }
98
            add(new Label("date", dateString));
×
99
        } else {
×
100
            add(new Label("date").setVisible(false));
×
101
        }
102

103
        add(new Label("description", "<span>" + Utils.sanitizeHtml(space.getDescription()) + "</span>").setEscapeModelStrings(false));
×
104

105
        final List<AbstractLink> pinButtons = new ArrayList<>();
×
106

107
        AbstractLink addPinnedTemplateButton = new BookmarkablePageLink<NanodashPage>("button", PublishPage.class, new PageParameters()
×
108
                .add("template", "https://w3id.org/np/RA2YwreWrGW9HkzWls8jgwaIINKUB5ZTli1aFKQt13dUk")
×
109
                .add("param_space", space.getId())
×
110
                .add("context", space.getId())
×
111
            );
112
        addPinnedTemplateButton.setBody(Model.of("+ template"));
×
113
        pinButtons.add(addPinnedTemplateButton);
×
114

115
        AbstractLink addPinnedQueryButton = new BookmarkablePageLink<NanodashPage>("button", PublishPage.class, new PageParameters()
×
116
                .add("template", "https://w3id.org/np/RAuLESdeRUlk1GcTwvzVXShiBMI0ntJs2DL2Bm5DzW_ZQ")
×
117
                .add("param_space", space.getId())
×
118
            );
119
        addPinnedQueryButton.setBody(Model.of("+ query"));
×
120
        pinButtons.add(addPinnedQueryButton);
×
121

122
        if (space.isDataInitialized()) {
×
123
            add(new PinGroupList("pin-groups", space));
×
124
            add(new ButtonList("pin-buttons", space, null, null, pinButtons));
×
125
        } else {
126
            add(new AjaxLazyLoadPanel<Component>("pin-groups") {
×
127
    
128
                @Override
129
                public Component getLazyLoadComponent(String markupId) {
130
                    return new PinGroupList(markupId, space);
×
131
                }
132
    
133
                @Override
134
                protected boolean isContentReady() {
135
                    return space.isDataInitialized();
×
136
                }
137
    
138
            });
139
            add(new AjaxLazyLoadPanel<Component>("pin-buttons") {
×
140
    
141
                @Override
142
                public Component getLazyLoadComponent(String markupId) {
143
                    return new ButtonList(markupId, space, null, null, pinButtons);
×
144
                }
145
    
146
                @Override
147
                protected boolean isContentReady() {
148
                    return space.isDataInitialized();
×
149
                }
150

151
                public Component getLoadingComponent(String id) {
152
                    return new Label(id).setVisible(false);
×
153
                };
154
    
155
            });
156
        }
157

158
        final List<AbstractLink> viewButtons = new ArrayList<>();
×
159
        AbstractLink addViewButton = new BookmarkablePageLink<NanodashPage>("button", PublishPage.class, new PageParameters()
×
160
                .add("template", "https://w3id.org/np/RAKKxyVdBLv-T1o5psQBtmGQvy1XBmh4LaJf7KxLmwszk")
×
161
                .add("param_space", space.getId())
×
162
            );
163
        addViewButton.setBody(Model.of("+"));
×
164
        viewButtons.add(addViewButton);
×
165

166
        if (space.isDataInitialized()) {
×
167
            add(new ViewList("views", space));
×
168
            add(new ButtonList("view-buttons", space, null, null, viewButtons));
×
169
        } else {
170
            add(new AjaxLazyLoadPanel<Component>("views") {
×
171
    
172
                @Override
173
                public Component getLazyLoadComponent(String markupId) {
174
                    return new ViewList(markupId, space);
×
175
                }
176
    
177
                @Override
178
                protected boolean isContentReady() {
179
                    return space.isDataInitialized();
×
180
                }
181
    
182
            });
183
            add(new AjaxLazyLoadPanel<Component>("view-buttons") {
×
184
    
185
                @Override
186
                public Component getLazyLoadComponent(String markupId) {
187
                    return new ButtonList(markupId, space, null, null, viewButtons);
×
188
                }
189
    
190
                @Override
191
                protected boolean isContentReady() {
192
                    return space.isDataInitialized();
×
193
                }
194

195
                public Component getLoadingComponent(String id) {
196
                    return new Label(id).setVisible(false);
×
197
                };
198
    
199
            });
200
        }
201

202
        add(new ItemListPanel<>(
×
203
                "roles",
204
                "Roles:",
205
                () -> space.isDataInitialized(),
×
206
                () -> space.getRoles(),
×
207
                r -> new ItemListElement("item", ExplorePage.class, new PageParameters().add("id", r.getId()), r.getName())
×
208
            )
209
            .makeInline()
×
210
            .setSpace(space)
×
211
            .addAdminButton("+", PublishPage.class, new PageParameters()
×
212
                    .add("template", "https://w3id.org/np/RARBzGkEqiQzeiHk0EXFcv9Ol1d-17iOh9MoFJzgfVQDc")
×
213
                    .add("param_space", space.getId())
×
214
                    .add("template-version", "latest")
×
215
                )
216
            );
217

218
        add(new ItemListPanel<IRI>(
×
219
                "users",
220
                "Users",
221
                () -> space.isDataInitialized(),
×
222
                () -> space.getUsers(),
×
223
                m -> {
224
                        String roleLabel = "(";
×
225
                        for (SpaceMemberRole r : space.getMemberRoles(m)) {
×
226
                            roleLabel += r.getName() + ", ";
×
227
                        }
×
228
                        roleLabel = roleLabel.replaceFirst(", $", ")");
×
229
                        return new ItemListElement("item", UserPage.class, new PageParameters().add("id", m), User.getShortDisplayName(m), roleLabel);
×
230
                    }
231
            ));
232

233

234
        if (space.isDataInitialized()) {
×
235
            add(new SpaceUserList("user-lists", space));
×
236
        } else {
237
            add(new AjaxLazyLoadPanel<Component>("user-lists") {
×
238
    
239
                @Override
240
                public Component getLazyLoadComponent(String markupId) {
241
                    return new SpaceUserList(markupId, space);
×
242
                }
243
    
244
                @Override
245
                protected boolean isContentReady() {
246
                    return space.isDataInitialized();
×
247
                }
248
    
249
            });
250
        }
251

252
        add(new ItemListPanel<Space>(
×
253
                "superspaces",
254
                "Part of",
255
                space.getSuperspaces(),
×
256
                (space) -> new ItemListElement("item", SpacePage.class, new PageParameters().add("id", space), space.getLabel(), "(" + space.getTypeLabel() + ")")
×
257
            ));
258

259
        addSubspacePanel("Alliance", true);
×
260
        addSubspacePanel("Consortium", false);
×
261
        addSubspacePanel("Organization", true);
×
262
        addSubspacePanel("Taskforce", false);
×
263
        addSubspacePanel("Division", true);
×
264
        addSubspacePanel("Taskunit", false);
×
265
        addSubspacePanel("Group", true);
×
266
        addSubspacePanel("Project", false);
×
267
        addSubspacePanel("Program", true);
×
268
        addSubspacePanel("Initiative", false);
×
269
        addSubspacePanel("Outlet", true);
×
270
        addSubspacePanel("Campaign", false);
×
271
        addSubspacePanel("Community", true);
×
272
        addSubspacePanel("Event", false);
×
273

274
        String shortId = space.getId().replace("https://w3id.org/spaces/", "");
×
275
        ConnectorConfig cc = ConnectorConfig.get(shortId);
×
276
        if (cc != null) {
×
277
            add(new BookmarkablePageLink<Void>("content-button", GenOverviewPage.class, new PageParameters().add("journal", shortId)).setBody(Model.of("Nanopublication Submissions")));
×
278
        } else {
279
            add(new Label("content-button").setVisible(false));
×
280
        }
281
    }
×
282

283
    private void addSubspacePanel(String type, boolean openEnded) {
284
        String typePl = type + "s";
×
285
        typePl = typePl.replaceFirst("ys$", "ies");
×
286

287
        add(new ItemListPanel<>(
×
288
                typePl.toLowerCase(),
×
289
                typePl,
290
                space.getSubspaces("https://w3id.org/kpxl/gen/terms/" + type),
×
291
                (space) -> new ItemListElement("item", SpacePage.class, new PageParameters().add("id", space), space.getLabel())
×
292
            )
293
            .setSpace(space)
×
294
            .setReadyFunction(space::isDataInitialized)
×
295
            .addMemberButton("+", PublishPage.class, new PageParameters()
×
296
                    .add("template", openEnded ? "https://w3id.org/np/RA7dQfmndqKmooQ4PlHyQsAql9i2tg_8GLHf_dqtxsGEQ" : "https://w3id.org/np/RAaE7NP9RNIx03AHZxanFMdtUuaTfe50ns5tHhpEVloQ4")
×
297
                    .add("param_type", "https://w3id.org/kpxl/gen/terms/" + type)
×
298
                    .add("param_space", space.getId().replaceFirst("https://w3id.org/spaces/", "") + "/<...>")
×
299
                    .add("template-version", "latest"))
×
300
            );
301
    }
×
302

303
    /**
304
     * Checks if auto-refresh is enabled for this page.
305
     *
306
     * @return true if auto-refresh is enabled, false otherwise
307
     */
308
    protected boolean hasAutoRefreshEnabled() {
309
        return true;
×
310
    }
311

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