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.badge;
35  
36  import info.magnolia.context.Context;
37  import info.magnolia.i18nsystem.SimpleTranslator;
38  import info.magnolia.icons.MagnoliaIcons;
39  import info.magnolia.ui.api.location.Location;
40  import info.magnolia.ui.api.location.LocationController;
41  import info.magnolia.ui.theme.ResurfaceTheme;
42  
43  import javax.inject.Inject;
44  
45  import com.vaadin.shared.ui.ContentMode;
46  import com.vaadin.ui.Button;
47  import com.vaadin.ui.Composite;
48  import com.vaadin.ui.CssLayout;
49  import com.vaadin.ui.Label;
50  import com.vaadin.ui.VerticalLayout;
51  
52  /**
53   * Base abstract class for header badge, a component displaying item count and status e.g. for tasks and notifications.
54   */
55  public abstract class AbstractBadge extends Composite {
56  
57      private static final String BADGE_INDICATOR = "%s<span class='status " + MagnoliaIcons.RADIO_FILL.getCssClass() + " color-green'></span>";
58      private final VerticalLayout layout = new VerticalLayout();
59      private final Label itemCount = new Label();
60      private final String userName;
61      private final SimpleTranslator i18n;
62  
63      @Inject
64      AbstractBadge(LocationController controller, Context context, SimpleTranslator i18n) {
65          this.userName = context.getUser().getName();
66          this.i18n = i18n;
67  
68          layout.setSizeUndefined();
69          layout.setMargin(true);
70          layout.setSpacing(false);
71          layout.addStyleName("header-component");
72  
73          itemCount.addStyleNames("indicator", "heading-2");
74          itemCount.setContentMode(ContentMode.HTML);
75  
76          Button openArrow = new Button(MagnoliaIcons.ARROW1_S);
77          openArrow.addStyleNames(ResurfaceTheme.BUTTON_ICON, "open-arrow");
78          openArrow.addClickListener(event -> {
79              if (getLocation().getAppName().equals(controller.getWhere().getAppName())) {
80                  onBadgeDeselected();
81              } else {
82                  controller.goTo(getLocation());
83              }
84          });
85  
86          CssLayout cssLayout = new CssLayout();
87          cssLayout.addComponents(itemCount, openArrow);
88  
89          Label label = new Label(getCaption());
90          label.addStyleName("label");
91  
92          layout.addComponents(cssLayout, label);
93  
94          setCompositionRoot(layout);
95      }
96  
97      protected void onBadgeDeselected() {
98      }
99  
100     /**
101      * Updates badge with the items' current status.
102      * @see #getStatus()
103      */
104     void update() {
105         final Status status = getStatus();
106         layout.setDescription(status.getDescription());
107 
108         if (status.newItemsAvailable()) {
109             itemCount.setValue(String.format(BADGE_INDICATOR, status.getItemCountAsString()));
110         } else {
111             itemCount.setValue(status.getItemCountAsString());
112         }
113     }
114 
115     /**
116      * @return the {@link Status} of the item type.
117      */
118     abstract Status getStatus();
119 
120     /**
121      * @return the {@link Location} to go to upon clicking the badge.
122      */
123     abstract Location getLocation();
124 
125     String getUserName() {
126         return userName;
127     }
128 
129     SimpleTranslator getI18n() {
130         return i18n;
131     }
132 
133     /**
134      * Item status. Helps to visually indicate if a badge contains new items.
135      * Provides a description text and the overall item count.
136      * Count depends on the item type, e.g. notifications, tasks, etc.
137      */
138     static final class Status {
139         private final boolean newItemsAvailable;
140         private final int itemCount;
141         private final String description;
142 
143         Status(boolean newItemsAvailable, int itemCount, String description) {
144             this.newItemsAvailable = newItemsAvailable;
145             this.itemCount = itemCount;
146             this.description = description;
147         }
148 
149         boolean newItemsAvailable() {
150             return newItemsAvailable;
151         }
152 
153         int getItemCount() {
154             return itemCount;
155         }
156 
157         String getDescription() {
158             return description;
159         }
160 
161         String getItemCountAsString() {
162             return itemCount >= 100 ? "99+" : String.valueOf(itemCount);
163         }
164     }
165 }