2 * Sone - WebInterface.java - Copyright © 2010–2019 David Roden
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 package net.pterodactylus.sone.web;
20 import static com.google.common.collect.FluentIterable.from;
21 import static java.util.logging.Logger.getLogger;
23 import java.util.Collection;
24 import java.util.HashMap;
27 import java.util.TimeZone;
28 import java.util.UUID;
29 import java.util.logging.Logger;
30 import javax.annotation.Nonnull;
31 import javax.annotation.Nullable;
32 import javax.inject.Named;
34 import net.pterodactylus.sone.core.Core;
35 import net.pterodactylus.sone.core.ElementLoader;
36 import net.pterodactylus.sone.core.event.*;
37 import net.pterodactylus.sone.data.Post;
38 import net.pterodactylus.sone.data.PostReply;
39 import net.pterodactylus.sone.data.Sone;
40 import net.pterodactylus.sone.freenet.L10nFilter;
41 import net.pterodactylus.sone.freenet.Translation;
42 import net.pterodactylus.sone.main.Loaders;
43 import net.pterodactylus.sone.main.PluginHomepage;
44 import net.pterodactylus.sone.main.PluginVersion;
45 import net.pterodactylus.sone.main.PluginYear;
46 import net.pterodactylus.sone.main.SonePlugin;
47 import net.pterodactylus.sone.notify.ListNotification;
48 import net.pterodactylus.sone.notify.ListNotificationFilter;
49 import net.pterodactylus.sone.notify.PostVisibilityFilter;
50 import net.pterodactylus.sone.notify.ReplyVisibilityFilter;
51 import net.pterodactylus.sone.template.LinkedElementRenderFilter;
52 import net.pterodactylus.sone.template.ParserFilter;
53 import net.pterodactylus.sone.template.RenderFilter;
54 import net.pterodactylus.sone.template.ShortenFilter;
55 import net.pterodactylus.sone.text.TimeTextConverter;
56 import net.pterodactylus.sone.web.ajax.BookmarkAjaxPage;
57 import net.pterodactylus.sone.web.ajax.CreatePostAjaxPage;
58 import net.pterodactylus.sone.web.ajax.CreateReplyAjaxPage;
59 import net.pterodactylus.sone.web.ajax.DeletePostAjaxPage;
60 import net.pterodactylus.sone.web.ajax.DeleteProfileFieldAjaxPage;
61 import net.pterodactylus.sone.web.ajax.DeleteReplyAjaxPage;
62 import net.pterodactylus.sone.web.ajax.DismissNotificationAjaxPage;
63 import net.pterodactylus.sone.web.ajax.EditAlbumAjaxPage;
64 import net.pterodactylus.sone.web.ajax.EditImageAjaxPage;
65 import net.pterodactylus.sone.web.ajax.EditProfileFieldAjaxPage;
66 import net.pterodactylus.sone.web.ajax.FollowSoneAjaxPage;
67 import net.pterodactylus.sone.web.ajax.GetLikesAjaxPage;
68 import net.pterodactylus.sone.web.ajax.GetLinkedElementAjaxPage;
69 import net.pterodactylus.sone.web.ajax.GetNotificationsAjaxPage;
70 import net.pterodactylus.sone.web.ajax.GetPostAjaxPage;
71 import net.pterodactylus.sone.web.ajax.GetReplyAjaxPage;
72 import net.pterodactylus.sone.web.ajax.GetStatusAjaxPage;
73 import net.pterodactylus.sone.web.ajax.GetTimesAjaxPage;
74 import net.pterodactylus.sone.web.ajax.GetTranslationAjaxPage;
75 import net.pterodactylus.sone.web.ajax.LikeAjaxPage;
76 import net.pterodactylus.sone.web.ajax.LockSoneAjaxPage;
77 import net.pterodactylus.sone.web.ajax.MarkAsKnownAjaxPage;
78 import net.pterodactylus.sone.web.ajax.MoveProfileFieldAjaxPage;
79 import net.pterodactylus.sone.web.ajax.UnbookmarkAjaxPage;
80 import net.pterodactylus.sone.web.ajax.UnfollowSoneAjaxPage;
81 import net.pterodactylus.sone.web.ajax.UnlikeAjaxPage;
82 import net.pterodactylus.sone.web.ajax.UnlockSoneAjaxPage;
83 import net.pterodactylus.sone.web.page.FreenetRequest;
84 import net.pterodactylus.sone.web.page.TemplateRenderer;
85 import net.pterodactylus.sone.web.pages.*;
86 import net.pterodactylus.util.notify.Notification;
87 import net.pterodactylus.util.notify.NotificationManager;
88 import net.pterodactylus.util.notify.TemplateNotification;
89 import net.pterodactylus.util.template.Template;
90 import net.pterodactylus.util.template.TemplateContextFactory;
91 import net.pterodactylus.util.web.RedirectPage;
92 import net.pterodactylus.util.web.TemplatePage;
94 import freenet.clients.http.SessionManager;
95 import freenet.clients.http.SessionManager.Session;
96 import freenet.clients.http.ToadletContext;
98 import com.codahale.metrics.*;
99 import com.google.common.base.Optional;
100 import com.google.common.collect.ImmutableSet;
101 import com.google.common.eventbus.Subscribe;
102 import com.google.inject.Inject;
105 * Bundles functionality that a web interface of a Freenet plugin needs, e.g.
106 * references to l10n helpers.
108 public class WebInterface implements SessionProvider {
111 private static final Logger logger = getLogger(WebInterface.class.getName());
113 /** The loaders for templates, pages, and classpath providers. */
114 private final Loaders loaders;
116 /** The notification manager. */
117 private final NotificationManager notificationManager;
119 /** The Sone plugin. */
120 private final SonePlugin sonePlugin;
122 /** The form password. */
123 private final String formPassword;
125 /** The template context factory. */
126 private final TemplateContextFactory templateContextFactory;
127 private final TemplateRenderer templateRenderer;
129 /** The parser filter. */
130 private final ParserFilter parserFilter;
131 private final ShortenFilter shortenFilter;
132 private final RenderFilter renderFilter;
134 private final ListNotificationFilter listNotificationFilter;
135 private final PostVisibilityFilter postVisibilityFilter;
136 private final ReplyVisibilityFilter replyVisibilityFilter;
138 private final ElementLoader elementLoader;
139 private final LinkedElementRenderFilter linkedElementRenderFilter;
140 private final TimeTextConverter timeTextConverter = new TimeTextConverter();
141 private final L10nFilter l10nFilter;
143 private final PageToadletRegistry pageToadletRegistry;
144 private final MetricRegistry metricRegistry;
145 private final Translation translation;
147 /** The “new post” notification. */
148 private final ListNotification<Post> newPostNotification;
150 /** The “new reply” notification. */
151 private final ListNotification<PostReply> newReplyNotification;
153 /** The invisible “local post” notification. */
154 private final ListNotification<Post> localPostNotification;
156 /** The invisible “local reply” notification. */
157 private final ListNotification<PostReply> localReplyNotification;
159 /** Notifications for sone inserts. */
160 private final Map<Sone, TemplateNotification> soneInsertNotifications = new HashMap<>();
163 public WebInterface(SonePlugin sonePlugin, Loaders loaders, ListNotificationFilter listNotificationFilter,
164 PostVisibilityFilter postVisibilityFilter, ReplyVisibilityFilter replyVisibilityFilter,
165 ElementLoader elementLoader, TemplateContextFactory templateContextFactory,
166 TemplateRenderer templateRenderer,
167 ParserFilter parserFilter, ShortenFilter shortenFilter,
168 RenderFilter renderFilter,
169 LinkedElementRenderFilter linkedElementRenderFilter,
170 PageToadletRegistry pageToadletRegistry, MetricRegistry metricRegistry, Translation translation, L10nFilter l10nFilter,
171 NotificationManager notificationManager, @Named("newRemotePost") ListNotification<Post> newPostNotification,
172 @Named("newRemotePostReply") ListNotification<PostReply> newReplyNotification,
173 @Named("localPost") ListNotification<Post> localPostNotification) {
174 this.sonePlugin = sonePlugin;
175 this.loaders = loaders;
176 this.listNotificationFilter = listNotificationFilter;
177 this.postVisibilityFilter = postVisibilityFilter;
178 this.replyVisibilityFilter = replyVisibilityFilter;
179 this.elementLoader = elementLoader;
180 this.templateRenderer = templateRenderer;
181 this.parserFilter = parserFilter;
182 this.shortenFilter = shortenFilter;
183 this.renderFilter = renderFilter;
184 this.linkedElementRenderFilter = linkedElementRenderFilter;
185 this.pageToadletRegistry = pageToadletRegistry;
186 this.metricRegistry = metricRegistry;
187 this.l10nFilter = l10nFilter;
188 this.translation = translation;
189 this.notificationManager = notificationManager;
190 this.newPostNotification = newPostNotification;
191 this.newReplyNotification = newReplyNotification;
192 this.localPostNotification = localPostNotification;
193 formPassword = sonePlugin.pluginRespirator().getToadletContainer().getFormPassword();
195 this.templateContextFactory = templateContextFactory;
196 templateContextFactory.addTemplateObject("webInterface", this);
197 templateContextFactory.addTemplateObject("formPassword", formPassword);
199 /* create notifications. */
200 Template localReplyNotificationTemplate = loaders.loadTemplate("/templates/notify/newReplyNotification.html");
201 localReplyNotification = new ListNotification<>("local-reply-notification", "replies", localReplyNotificationTemplate, false);
209 * Returns the Sone core used by the Sone plugin.
211 * @return The Sone core
214 public Core getCore() {
215 return sonePlugin.core();
219 * Returns the template context factory of the web interface.
221 * @return The template context factory
223 public TemplateContextFactory getTemplateContextFactory() {
224 return templateContextFactory;
227 private Session getCurrentSessionWithoutCreation(ToadletContext toadletContenxt) {
228 return getSessionManager().useSession(toadletContenxt);
231 private Session getOrCreateCurrentSession(ToadletContext toadletContenxt) {
232 Session session = getCurrentSessionWithoutCreation(toadletContenxt);
233 if (session == null) {
234 session = getSessionManager().createSession(UUID.randomUUID().toString(), toadletContenxt);
239 public Sone getCurrentSoneCreatingSession(ToadletContext toadletContext) {
240 Collection<Sone> localSones = getCore().getLocalSones();
241 if (localSones.size() == 1) {
242 return localSones.iterator().next();
244 return getCurrentSone(getOrCreateCurrentSession(toadletContext));
247 public Sone getCurrentSoneWithoutCreatingSession(ToadletContext toadletContext) {
248 Collection<Sone> localSones = getCore().getLocalSones();
249 if (localSones.size() == 1) {
250 return localSones.iterator().next();
252 return getCurrentSone(getCurrentSessionWithoutCreation(toadletContext));
256 * Returns the currently logged in Sone.
260 * @return The currently logged in Sone, or {@code null} if no Sone is
261 * currently logged in
263 private Sone getCurrentSone(Session session) {
264 if (session == null) {
267 String soneId = (String) session.getAttribute("Sone.CurrentSone");
268 if (soneId == null) {
271 return getCore().getLocalSone(soneId);
276 public Sone getCurrentSone(@Nonnull ToadletContext toadletContext, boolean createSession) {
277 return createSession ? getCurrentSoneCreatingSession(toadletContext) : getCurrentSoneWithoutCreatingSession(toadletContext);
281 * Sets the currently logged in Sone.
283 * @param toadletContext
284 * The toadlet context
286 * The Sone to set as currently logged in
289 public void setCurrentSone(@Nonnull ToadletContext toadletContext, @Nullable Sone sone) {
290 Session session = getOrCreateCurrentSession(toadletContext);
292 session.removeAttribute("Sone.CurrentSone");
294 session.setAttribute("Sone.CurrentSone", sone.getId());
299 * Returns the notification manager.
301 * @return The notification manager
303 public NotificationManager getNotifications() {
304 return notificationManager;
308 public Optional<Notification> getNotification(@Nonnull String notificationId) {
309 return Optional.fromNullable(notificationManager.getNotification(notificationId));
313 public Collection<Notification> getNotifications(@Nullable Sone currentSone) {
314 return listNotificationFilter.filterNotifications(notificationManager.getNotifications(), currentSone);
317 public Translation getTranslation() {
322 * Returns the session manager of the node.
324 * @return The node’s session manager
326 public SessionManager getSessionManager() {
327 return sonePlugin.pluginRespirator().getSessionManager("Sone");
331 * Returns the node’s form password.
333 * @return The form password
335 public String getFormPassword() {
340 public Collection<Post> getNewPosts(@Nullable Sone currentSone) {
341 Set<Post> allNewPosts = ImmutableSet.<Post> builder()
342 .addAll(newPostNotification.getElements())
343 .addAll(localPostNotification.getElements())
345 return from(allNewPosts).filter(postVisibilityFilter.isVisible(currentSone)).toSet();
349 * Returns the replies that have been announced as new in the
350 * {@link #newReplyNotification}.
352 * @return The new replies
354 public Set<PostReply> getNewReplies() {
355 return ImmutableSet.<PostReply> builder().addAll(newReplyNotification.getElements()).addAll(localReplyNotification.getElements()).build();
359 public Collection<PostReply> getNewReplies(@Nullable Sone currentSone) {
360 Set<PostReply> allNewReplies = ImmutableSet.<PostReply>builder()
361 .addAll(newReplyNotification.getElements())
362 .addAll(localReplyNotification.getElements())
364 return from(allNewReplies).filter(replyVisibilityFilter.isVisible(currentSone)).toSet();
372 * Returns whether the first start notification is currently displayed.
374 * @return {@code true} if the first-start notification is currently
375 * displayed, {@code false} otherwise
377 private boolean hasFirstStartNotification() {
378 return notificationManager.getNotification("first-start-notification") != null;
386 * Starts the web interface and registers all toadlets.
388 public void start() {
393 * Stops the web interface and unregisters all toadlets.
396 pageToadletRegistry.unregisterToadlets();
404 * Register all toadlets.
406 private void registerToadlets() {
407 Template postTemplate = loaders.loadTemplate("/templates/include/viewPost.html");
408 Template replyTemplate = loaders.loadTemplate("/templates/include/viewReply.html");
409 Template openSearchTemplate = loaders.loadTemplate("/templates/xml/OpenSearch.xml");
411 pageToadletRegistry.addPage(new RedirectPage<FreenetRequest>("", "index.html"));
412 pageToadletRegistry.addPage(new IndexPage(this, loaders, templateRenderer, postVisibilityFilter));
413 pageToadletRegistry.addPage(new NewPage(this, loaders, templateRenderer));
414 pageToadletRegistry.addPage(new CreateSonePage(this, loaders, templateRenderer));
415 pageToadletRegistry.addPage(new KnownSonesPage(this, loaders, templateRenderer));
416 pageToadletRegistry.addPage(new EditProfilePage(this, loaders, templateRenderer));
417 pageToadletRegistry.addPage(new EditProfileFieldPage(this, loaders, templateRenderer));
418 pageToadletRegistry.addPage(new DeleteProfileFieldPage(this, loaders, templateRenderer));
419 pageToadletRegistry.addPage(new CreatePostPage(this, loaders, templateRenderer));
420 pageToadletRegistry.addPage(new CreateReplyPage(this, loaders, templateRenderer));
421 pageToadletRegistry.addPage(new ViewSonePage(this, loaders, templateRenderer));
422 pageToadletRegistry.addPage(new ViewPostPage(this, loaders, templateRenderer));
423 pageToadletRegistry.addPage(new LikePage(this, loaders, templateRenderer));
424 pageToadletRegistry.addPage(new UnlikePage(this, loaders, templateRenderer));
425 pageToadletRegistry.addPage(new DeletePostPage(this, loaders, templateRenderer));
426 pageToadletRegistry.addPage(new DeleteReplyPage(this, loaders, templateRenderer));
427 pageToadletRegistry.addPage(new LockSonePage(this, loaders, templateRenderer));
428 pageToadletRegistry.addPage(new UnlockSonePage(this, loaders, templateRenderer));
429 pageToadletRegistry.addPage(new FollowSonePage(this, loaders, templateRenderer));
430 pageToadletRegistry.addPage(new UnfollowSonePage(this, loaders, templateRenderer));
431 pageToadletRegistry.addPage(new ImageBrowserPage(this, loaders, templateRenderer));
432 pageToadletRegistry.addPage(new CreateAlbumPage(this, loaders, templateRenderer));
433 pageToadletRegistry.addPage(new EditAlbumPage(this, loaders, templateRenderer));
434 pageToadletRegistry.addPage(new DeleteAlbumPage(this, loaders, templateRenderer));
435 pageToadletRegistry.addPage(new UploadImagePage(this, loaders, templateRenderer));
436 pageToadletRegistry.addPage(new EditImagePage(this, loaders, templateRenderer));
437 pageToadletRegistry.addPage(new DeleteImagePage(this, loaders, templateRenderer));
438 pageToadletRegistry.addPage(new MarkAsKnownPage(this, loaders, templateRenderer));
439 pageToadletRegistry.addPage(new BookmarkPage(this, loaders, templateRenderer));
440 pageToadletRegistry.addPage(new UnbookmarkPage(this, loaders, templateRenderer));
441 pageToadletRegistry.addPage(new BookmarksPage(this, loaders, templateRenderer));
442 pageToadletRegistry.addPage(new SearchPage(this, loaders, templateRenderer));
443 pageToadletRegistry.addPage(new DeleteSonePage(this, loaders, templateRenderer));
444 pageToadletRegistry.addPage(new LoginPage(this, loaders, templateRenderer));
445 pageToadletRegistry.addPage(new LogoutPage(this, loaders, templateRenderer));
446 pageToadletRegistry.addPage(new OptionsPage(this, loaders, templateRenderer));
447 pageToadletRegistry.addPage(new RescuePage(this, loaders, templateRenderer));
448 pageToadletRegistry.addPage(new AboutPage(this, loaders, templateRenderer, new PluginVersion(SonePlugin.getPluginVersion()), new PluginYear(sonePlugin.getYear()), new PluginHomepage(sonePlugin.getHomepage())));
449 pageToadletRegistry.addPage(new InvalidPage(this, loaders, templateRenderer));
450 pageToadletRegistry.addPage(new NoPermissionPage(this, loaders, templateRenderer));
451 pageToadletRegistry.addPage(new EmptyImageTitlePage(this, loaders, templateRenderer));
452 pageToadletRegistry.addPage(new EmptyAlbumTitlePage(this, loaders, templateRenderer));
453 pageToadletRegistry.addPage(new DismissNotificationPage(this, loaders, templateRenderer));
454 pageToadletRegistry.addPage(new DebugPage(this, loaders, templateRenderer));
455 pageToadletRegistry.addDebugPage(new MetricsPage(this, loaders, templateRenderer, metricRegistry));
456 pageToadletRegistry.addPage(loaders.<FreenetRequest>loadStaticPage("css/", "/static/css/", "text/css"));
457 pageToadletRegistry.addPage(loaders.<FreenetRequest>loadStaticPage("javascript/", "/static/javascript/", "text/javascript"));
458 pageToadletRegistry.addPage(loaders.<FreenetRequest>loadStaticPage("images/", "/static/images/", "image/png"));
459 pageToadletRegistry.addPage(new TemplatePage<FreenetRequest>("OpenSearch.xml", "application/opensearchdescription+xml", templateContextFactory, openSearchTemplate));
460 pageToadletRegistry.addPage(new GetImagePage(this));
461 pageToadletRegistry.addPage(new GetTranslationAjaxPage(this));
462 pageToadletRegistry.addPage(new GetStatusAjaxPage(this, elementLoader, timeTextConverter, l10nFilter, TimeZone.getDefault()));
463 pageToadletRegistry.addPage(new GetNotificationsAjaxPage(this));
464 pageToadletRegistry.addPage(new DismissNotificationAjaxPage(this));
465 pageToadletRegistry.addPage(new CreatePostAjaxPage(this));
466 pageToadletRegistry.addPage(new CreateReplyAjaxPage(this));
467 pageToadletRegistry.addPage(new GetReplyAjaxPage(this, replyTemplate));
468 pageToadletRegistry.addPage(new GetPostAjaxPage(this, postTemplate));
469 pageToadletRegistry.addPage(new GetLinkedElementAjaxPage(this, elementLoader, linkedElementRenderFilter));
470 pageToadletRegistry.addPage(new GetTimesAjaxPage(this, timeTextConverter, l10nFilter, TimeZone.getDefault()));
471 pageToadletRegistry.addPage(new MarkAsKnownAjaxPage(this));
472 pageToadletRegistry.addPage(new DeletePostAjaxPage(this));
473 pageToadletRegistry.addPage(new DeleteReplyAjaxPage(this));
474 pageToadletRegistry.addPage(new LockSoneAjaxPage(this));
475 pageToadletRegistry.addPage(new UnlockSoneAjaxPage(this));
476 pageToadletRegistry.addPage(new FollowSoneAjaxPage(this));
477 pageToadletRegistry.addPage(new UnfollowSoneAjaxPage(this));
478 pageToadletRegistry.addPage(new EditAlbumAjaxPage(this));
479 pageToadletRegistry.addPage(new EditImageAjaxPage(this, parserFilter, shortenFilter, renderFilter));
480 pageToadletRegistry.addPage(new LikeAjaxPage(this));
481 pageToadletRegistry.addPage(new UnlikeAjaxPage(this));
482 pageToadletRegistry.addPage(new GetLikesAjaxPage(this));
483 pageToadletRegistry.addPage(new BookmarkAjaxPage(this));
484 pageToadletRegistry.addPage(new UnbookmarkAjaxPage(this));
485 pageToadletRegistry.addPage(new EditProfileFieldAjaxPage(this));
486 pageToadletRegistry.addPage(new DeleteProfileFieldAjaxPage(this));
487 pageToadletRegistry.addPage(new MoveProfileFieldAjaxPage(this));
489 pageToadletRegistry.registerToadlets();
493 * Returns the Sone insert notification for the given Sone. If no
494 * notification for the given Sone exists, a new notification is created and
498 * The Sone to get the insert notification for
499 * @return The Sone insert notification
501 private TemplateNotification getSoneInsertNotification(Sone sone) {
502 synchronized (soneInsertNotifications) {
503 TemplateNotification templateNotification = soneInsertNotifications.get(sone);
504 if (templateNotification == null) {
505 templateNotification = new TemplateNotification(loaders.loadTemplate("/templates/notify/soneInsertNotification.html"));
506 templateNotification.set("insertSone", sone);
507 soneInsertNotifications.put(sone, templateNotification);
509 return templateNotification;
518 * Notifies the web interface that a new {@link PostReply} was found.
520 * @param newPostReplyFoundEvent
524 public void newReplyFound(NewPostReplyFoundEvent newPostReplyFoundEvent) {
525 PostReply reply = newPostReplyFoundEvent.getPostReply();
526 boolean isLocal = reply.getSone().isLocal();
528 localReplyNotification.add(reply);
529 if (!hasFirstStartNotification()) {
530 notificationManager.addNotification(localReplyNotification);
536 public void markPostKnown(MarkPostKnownEvent markPostKnownEvent) {
537 removePost(markPostKnownEvent.getPost());
541 public void markReplyKnown(MarkPostReplyKnownEvent markPostReplyKnownEvent) {
542 removeReply(markPostReplyKnownEvent.getPostReply());
546 public void postRemoved(PostRemovedEvent postRemovedEvent) {
547 removePost(postRemovedEvent.getPost());
550 private void removePost(Post post) {
551 newPostNotification.remove(post);
555 public void replyRemoved(PostReplyRemovedEvent postReplyRemovedEvent) {
556 removeReply(postReplyRemovedEvent.getPostReply());
559 private void removeReply(PostReply reply) {
560 localReplyNotification.remove(reply);
564 * Notifies the web interface that a {@link Sone} is being inserted.
566 * @param soneInsertingEvent
570 public void soneInserting(SoneInsertingEvent soneInsertingEvent) {
571 TemplateNotification soneInsertNotification = getSoneInsertNotification(soneInsertingEvent.getSone());
572 soneInsertNotification.set("soneStatus", "inserting");
573 if (soneInsertingEvent.getSone().getOptions().isSoneInsertNotificationEnabled()) {
574 notificationManager.addNotification(soneInsertNotification);
579 * Notifies the web interface that a {@link Sone} was inserted.
581 * @param soneInsertedEvent
585 public void soneInserted(SoneInsertedEvent soneInsertedEvent) {
586 TemplateNotification soneInsertNotification = getSoneInsertNotification(soneInsertedEvent.getSone());
587 soneInsertNotification.set("soneStatus", "inserted");
588 soneInsertNotification.set("insertDuration", soneInsertedEvent.getInsertDuration() / 1000);
589 if (soneInsertedEvent.getSone().getOptions().isSoneInsertNotificationEnabled()) {
590 notificationManager.addNotification(soneInsertNotification);
595 * Notifies the web interface that a {@link Sone} insert was aborted.
597 * @param soneInsertAbortedEvent
601 public void soneInsertAborted(SoneInsertAbortedEvent soneInsertAbortedEvent) {
602 TemplateNotification soneInsertNotification = getSoneInsertNotification(soneInsertAbortedEvent.getSone());
603 soneInsertNotification.set("soneStatus", "insert-aborted");
604 soneInsertNotification.set("insert-error", soneInsertAbortedEvent.getCause());
605 if (soneInsertAbortedEvent.getSone().getOptions().isSoneInsertNotificationEnabled()) {
606 notificationManager.addNotification(soneInsertNotification);
611 public void debugActivated(@Nonnull DebugActivatedEvent debugActivatedEvent) {
612 pageToadletRegistry.activateDebugMode();