View Javadoc
1   /**
2    * This file Copyright (c) 2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.admincentral.banner;
35  
36  import static info.magnolia.ui.api.message.MessageType.*;
37  
38  import info.magnolia.event.EventBus;
39  import info.magnolia.i18nsystem.SimpleTranslator;
40  import info.magnolia.icons.MagnoliaIcons;
41  import info.magnolia.ui.api.event.AdmincentralEventBus;
42  import info.magnolia.ui.api.location.DefaultLocation;
43  import info.magnolia.ui.api.location.LocationController;
44  import info.magnolia.ui.api.message.Message;
45  import info.magnolia.ui.contentapp.detail.DetailLocation;
46  import info.magnolia.ui.framework.message.MessageEvent;
47  import info.magnolia.ui.framework.message.MessageEventHandler;
48  
49  import java.util.Optional;
50  import java.util.stream.Stream;
51  
52  import javax.inject.Inject;
53  import javax.inject.Named;
54  
55  import com.google.common.base.Strings;
56  import com.google.common.collect.Lists;
57  import com.vaadin.ui.Button;
58  import com.vaadin.ui.Component;
59  import com.vaadin.ui.CssLayout;
60  
61  /**
62   * Banner container is a wrapper layout around {@link Banner}s. It it also subscribed to listen to the {@link MessageEvent}s.
63   * When {@link MessageEvent} occurs, container will create banner based on the message type and adds it to the layout.
64   */
65  public class BannerContainer extends CssLayout implements MessageEventHandler {
66  
67      private final EventBus eventBus;
68  
69      private final LocationController locationController;
70  
71      private final SimpleTranslator i18n;
72  
73      @Inject
74      public BannerContainer(@Named(AdmincentralEventBus.NAME) EventBus eventBus, LocationController locationController, SimpleTranslator i18n) {
75          this.eventBus = eventBus;
76          this.locationController = locationController;
77          this.i18n = i18n;
78  
79          initialize();
80      }
81  
82      private void initialize() {
83          setVisible(false);
84          setWidth(100, Unit.PERCENTAGE);
85          addStyleName("banner-container");
86  
87          addComponentAttachListener(e -> {
88              if (getComponentCount() > 0 && !isVisible()) {
89                  setVisible(true);
90              }
91          });
92  
93          addComponentDetachListener(e -> {
94              if (getComponentCount() == 0 && isVisible()) {
95                  setVisible(false);
96              }
97          });
98  
99          eventBus.addHandler(MessageEvent.class, this);
100     }
101 
102     @Override
103     public void messageSent(MessageEvent event) {
104         final Message message = event.getMessage();
105 
106         MagnoliaIcons icon;
107         String bannerStyle;
108 
109         if (WARNING.equals(message.getType())) {
110             icon = MagnoliaIcons.WARNING_L;
111             bannerStyle = WARNING.toString().toLowerCase();
112         } else if (ERROR.equals(message.getType())) {
113             icon = MagnoliaIcons.ERROR;
114             bannerStyle = ERROR.toString().toLowerCase();
115         } else {
116             icon = MagnoliaIcons.INFO_L;
117             bannerStyle = INFO.toString().toLowerCase();
118         }
119 
120         Banner.Title title = new Banner.Title(icon, message.getSubject());
121         Banner banner = new Banner(message.getId(), bannerStyle, title);
122         Button readMoreButton = new Button(i18n.translate("ui.banner.button.readmore"), e -> goToMessageDetail(message.getId()));
123         banner.addButton(readMoreButton);
124 
125         if (banners().count() > 0) {
126             Button readAllButton = new Button(i18n.translate("ui.banner.button.readall"), e -> goToMessages());
127             banner.addButton(readAllButton);
128         }
129 
130         Optional.ofNullable(Strings.emptyToNull(message.getMessage()))
131                 .map(Banner.Body::new)
132                 .ifPresent(banner::display);
133 
134         // we allow to display only one banner at a time
135         closeAllBanners();
136 
137         addComponent(banner);
138     }
139 
140     private Stream<Banner> banners() {
141         return Lists.newArrayList(iterator()).stream().filter(this::isBanner).map(this::asBanner);
142     }
143 
144     private void goToMessages() {
145         closeAllBanners();
146         locationController.goTo(new DefaultLocation("app", "messages-content-app"));
147     }
148 
149     private void goToMessageDetail(String messageId) {
150         closeAllBanners();
151         locationController.goTo(new DetailLocation("messages-content-app", "detail", messageId));
152     }
153 
154     private boolean isBanner(Component component) {
155         return component instanceof Banner;
156     }
157 
158     private Banner asBanner(Component component) {
159         return (Banner) component;
160     }
161 
162     private void closeAllBanners() {
163         banners().forEach(Banner::close);
164     }
165 
166     @Override
167     public void messageCleared(MessageEvent event) {
168     }
169 
170     @Override
171     public void messageRemoved(MessageEvent messageEvent) {
172     }
173 }