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.poc;
35  
36  import static com.vaadin.server.Sizeable.Unit.PERCENTAGE;
37  
38  import info.magnolia.ui.incub.CollapsibleCompositeField;
39  import info.magnolia.ui.incub.DamUploadField;
40  
41  import java.time.LocalDate;
42  import java.util.Arrays;
43  
44  import javax.servlet.annotation.WebServlet;
45  
46  import com.vaadin.annotations.Theme;
47  import com.vaadin.annotations.Title;
48  import com.vaadin.annotations.VaadinServletConfiguration;
49  import com.vaadin.annotations.Widgetset;
50  import com.vaadin.data.provider.ListDataProvider;
51  import com.vaadin.server.ThemeResource;
52  import com.vaadin.server.VaadinRequest;
53  import com.vaadin.server.VaadinServlet;
54  import com.vaadin.shared.ui.ContentMode;
55  import com.vaadin.ui.Button;
56  import com.vaadin.ui.ComboBox;
57  import com.vaadin.ui.Component;
58  import com.vaadin.ui.CssLayout;
59  import com.vaadin.ui.DateField;
60  import com.vaadin.ui.HorizontalLayout;
61  import com.vaadin.ui.Image;
62  import com.vaadin.ui.Label;
63  import com.vaadin.ui.Panel;
64  import com.vaadin.ui.TabSheet;
65  import com.vaadin.ui.TextArea;
66  import com.vaadin.ui.TextField;
67  import com.vaadin.ui.UI;
68  import com.vaadin.ui.VerticalLayout;
69  
70  @Theme("poctheme")
71  @Title("Magnolia 6 Resurface")
72  @Widgetset("info.magnolia.poc.Widgetset")
73  public class CollapsibleCompositeFieldsUI extends UI {
74  
75      private HorizontalLayout header = new HorizontalLayout();
76      private CssLayout viewPort = new CssLayout();
77  
78      @Override
79      protected void init(VaadinRequest request) {
80          header.setStyleName("header");
81          header.setSpacing(false);
82  
83          // Create logo
84          CssLayout logoWrapper = createLogoComponent();
85  
86          // Create finder bar
87          CssLayout finderBarContainer = new CssLayout();
88          finderBarContainer.setStyleName("periscope-wrapper");
89  
90          Component finderBar = createFinderBar();
91  
92          finderBarContainer.addComponent(finderBar);
93  
94          // Create tasks indicator
95          CssLayout tasksWrapper = new CssLayout();
96          tasksWrapper.setStyleName("tasks-wrapper");
97          Component taskIndicator = createIndicatorComponent("Tasks", "23", "green");
98          tasksWrapper.addComponent(taskIndicator);
99  
100         // Create message indicator
101         CssLayout messageWrapper = new CssLayout();
102         messageWrapper.setStyleName("messages-wrapper");
103         Component messageIndicator = createIndicatorComponent("Messages", "02", "green");
104         messageWrapper.addComponent(messageIndicator);
105 
106         // Create profile component
107         Component profileWrapper = createProfileComponent();
108         profileWrapper.setStyleName("profile-wrapper");
109 
110         // Create banner component
111         Component bannerWrapper = createBannerComponent(tasksWrapper);
112         bannerWrapper.setStyleName("banner-wrapper");
113         bannerWrapper.setVisible(false);
114 
115         header.addComponents(logoWrapper, finderBarContainer, tasksWrapper, messageWrapper, profileWrapper);
116 
117         viewPort.setStyleName("viewport");
118         viewPort.setSizeFull();
119 
120         Component tabSheet = createTabSheetComponent();
121         viewPort.addComponents(bannerWrapper, tabSheet);
122 
123         final VerticalLayout layout = new VerticalLayout();
124         layout.setStyleName("main-wrapper");
125         layout.setSpacing(false);
126         layout.addComponents(header, viewPort);
127         layout.setMargin(false);
128         layout.setExpandRatio(header, 0f);
129         layout.setExpandRatio(viewPort, 1f);
130         layout.setSizeFull();
131 
132         setContent(layout);
133     }
134 
135     private CssLayout createLogoComponent() {
136         CssLayout logoWrapper = new CssLayout();
137         logoWrapper.setStyleName("logo-wrapper");
138 
139         ThemeResource resource = new ThemeResource("img/logo-magnolia.svg");
140         // Show the image in the application
141         Image image = new Image("Magnolia logo", resource);
142         image.addStyleName("header-component");
143         logoWrapper.addComponent(image);
144         return logoWrapper;
145     }
146 
147     private HorizontalLayout createProfileComponent() {
148         HorizontalLayout profileWrapper = new HorizontalLayout();
149         profileWrapper.setSpacing(false);
150         profileWrapper.setMargin(false);
151 
152         Label avatar = new Label();
153         avatar.setContentMode(ContentMode.HTML);
154         avatar.addStyleName("header-component");
155         avatar.setValue("<span class='indicator number icon-user-role'></span>");
156         profileWrapper.addComponent(avatar);
157 
158         Component profileComponent = createHeaderComponent("public-01", "INT");
159         profileWrapper.addComponent(profileComponent);
160         return profileWrapper;
161     }
162 
163     private Component createBannerComponent(CssLayout tasksWrapper) {
164         CssLayout bannerWrapper = new CssLayout();
165         bannerWrapper.setWidth(100, Unit.PERCENTAGE);
166         bannerWrapper.setHeight(80, Unit.PIXELS);
167 
168         VerticalLayout banner = new VerticalLayout();
169         banner.addStyleNames("banner", "info");
170         banner.setSpacing(false);
171         banner.setMargin(false);
172 
173         Label infoLabel = new Label("Info");
174         infoLabel.addStyleName("header");
175 
176         Label bodyLabel = new Label("Your license will expire in 15 days. Renew now.");
177         bodyLabel.addStyleName("body");
178 
179         Button closeButton = new Button();
180         closeButton.setCaptionAsHtml(true);
181         closeButton.setPrimaryStyleName("icon-close");
182         closeButton.addStyleName("close");
183         closeButton.addClickListener(e -> bannerWrapper.setVisible(false));
184 
185         banner.addComponents(infoLabel, bodyLabel, closeButton);
186         bannerWrapper.addComponent(banner);
187 
188         tasksWrapper.addLayoutClickListener(e -> {
189             if (!bannerWrapper.isVisible()) {
190                 bannerWrapper.setVisible(true);
191             }
192 
193             switch (banner.getStyleName()) {
194             case "banner info":
195                 banner.removeStyleName("info");
196                 banner.addStyleName("warning");
197                 infoLabel.setValue("Warning");
198                 bodyLabel.setValue("Your license will expire tomorrow. Magnolia will stop functioning if no valid license is found. Renew now.");
199                 break;
200             case "banner warning":
201                 banner.removeStyleName("warning");
202                 banner.addStyleName("error");
203                 infoLabel.setValue("Error");
204                 bodyLabel.setValue("The multipart stream ended unexpectedly. More.");
205                 break;
206             case "banner error":
207                 banner.removeStyleName("error");
208                 banner.addStyleName("info");
209                 infoLabel.setValue("Info");
210                 bodyLabel.setValue("Your license will expire in 15 days. Renew now.");
211                 break;
212             }
213         });
214 
215         return bannerWrapper;
216     }
217 
218     private HorizontalLayout createFinderBar() {
219         HorizontalLayout finderBar = new HorizontalLayout();
220         finderBar.addStyleName("header-component");
221         finderBar.setSpacing(false);
222         finderBar.setMargin(false);
223         finderBar.setSizeFull();
224         Button shellButton = new Button();
225         shellButton.addStyleName("btn-shell icon-appslauncher btn-appslauncher");
226         finderBar.addComponent(shellButton);
227         finderBar.setExpandRatio(shellButton, 0f);
228 
229         CssLayout searchField = new CssLayout();
230         searchField.setStyleName("search-field");
231         TextField textField = new TextField();
232         textField.addStyleNames("search-textfield", "heading-2");
233         textField.setPlaceholder("Type to find");
234         searchField.addComponent(textField);
235         Label searchIcon = new Label();
236         searchIcon.setStyleName("icon-search");
237         searchField.addComponent(searchIcon);
238 
239         finderBar.addComponent(searchField);
240         finderBar.setExpandRatio(searchField, 1f);
241 
242 
243         Button voiceButton = new Button();
244         voiceButton.addStyleName("btn-shell icon-target-app btn-voice");
245         finderBar.addComponent(voiceButton);
246         finderBar.setExpandRatio(voiceButton, 0f);
247 
248         return finderBar;
249     }
250 
251     private Component createIndicatorComponent(String label, String value, String status) {
252         return createHeaderComponent(label, value + "<span class='status icon-status-" + status + " color-" + status + "'></span>");
253     }
254 
255     private Component createHeaderComponent(String label, String value) {
256 
257         VerticalLayout tasksComponent = new VerticalLayout();
258         tasksComponent.setSpacing(false);
259         tasksComponent.setMargin(false);
260         tasksComponent.setStyleName("header-component");
261         Label taskNumber = new Label();
262         taskNumber.addStyleName("indicator heading-2");
263         taskNumber.setValue(value);
264         taskNumber.setContentMode(ContentMode.HTML);
265         Label taskLabel = new Label(label);
266         taskLabel.addStyleNames("text-tiny");
267         tasksComponent.addComponents(taskNumber, taskLabel);
268 
269         return tasksComponent;
270     }
271 
272     private Component createTabSheetComponent() {
273 
274         TabSheet tabSheetComponent = new TabSheet();
275         tabSheetComponent.addStyleName("apps");
276         tabSheetComponent.setSizeFull();
277 
278         Component detailAppWithVerticalLayout = createDetailAppWithVerticalLayout();
279         detailAppWithVerticalLayout.addStyleName("app");
280         tabSheetComponent.addTab(detailAppWithVerticalLayout, "Assets");
281 
282         return tabSheetComponent;
283     }
284 
285     private Component createDetailAppWithVerticalLayout() {
286         VerticalLayout detailLayout = new VerticalLayout();
287         detailLayout.addStyleName("detail");
288         detailLayout.setSizeFull();
289         detailLayout.setMargin(false);
290         detailLayout.setSpacing(false);
291 
292         Label title = new Label();
293         title.addStyleName("heading-1 title");
294         title.setValue("Asset");
295 
296         CssLayout header = new CssLayout();
297         header.addStyleName("detail-header");
298         header.addComponent(title);
299 
300         VerticalLayout fieldsLayout = createCompositeFieldsLayout();
301         fieldsLayout.addStyleName("detail-content");
302 
303         Panel collapsibleCompositeFieldPanel = new Panel();
304         collapsibleCompositeFieldPanel.setSizeFull();
305         collapsibleCompositeFieldPanel.setContent(fieldsLayout);
306 
307         CssLayout footer = new CssLayout();
308         footer.addStyleName("detail-footer");
309         footer.setWidth(100, PERCENTAGE);
310         footer.addComponents(createActions());
311 
312         detailLayout.addComponents(header, collapsibleCompositeFieldPanel);
313         detailLayout.setExpandRatio(header, 0f);
314         detailLayout.setExpandRatio(collapsibleCompositeFieldPanel, 1f);
315 
316         return detailLayout;
317     }
318 
319     private VerticalLayout createCompositeFieldsLayout() {
320 
321         VerticalLayout collapsibleCompositeFieldsLayout = new VerticalLayout();
322         collapsibleCompositeFieldsLayout.addStyleName("collapsible-compositefield-layout");
323         collapsibleCompositeFieldsLayout.setMargin(false);
324         collapsibleCompositeFieldsLayout.setHeightUndefined();
325         collapsibleCompositeFieldsLayout.addComponents(createCompositeFieldImageUpload(), createCompositeFieldDescription(), createCompositeFieldMetaData(), createCompositeFieldPublishingInfo());
326         return collapsibleCompositeFieldsLayout;
327     }
328 
329     private Component createCompositeFieldImageUpload() {
330         DamUploadFieldploadField">DamUploadField damUploadField = new DamUploadField();
331         damUploadField.setCaption("Media *");
332         damUploadField.setWidth(100, PERCENTAGE);
333         return new CollapsibleCompositeField("Image upload", false, damUploadField);
334     }
335 
336     private Component createCompositeFieldDescription() {
337         TextField assetName = new TextField("Asset name");
338         assetName.setValue("siamak-djamei-62268");
339         TextField caption = new TextField("Caption");
340         TextField describeAssetUsing = new TextField("Describe asset using");
341         TextField identifier = new TextField("Identifier");
342         identifier.setValue("b8772c13-5931-4800-8183-012b5baf087d");
343         identifier.setEnabled(false);
344         TextField type = new TextField("Type");
345         type.setEnabled(false);
346         return new CollapsibleCompositeField("Description", false, assetName, caption, describeAssetUsing, identifier, type);     }
347 
348     private Component createCompositeFieldMetaData() {
349         TextField language = new TextField("Language");
350         TextField title = new TextField("Title");
351         TextField subject = new TextField("Subject");
352         TextField coverage = new TextField("Coverage");
353         TextArea description = new TextArea("Description");
354         description.setRows(2);
355         return new CollapsibleCompositeField("Meta data", false, language, title, subject, coverage, description);
356 
357     }
358 
359     private Component createCompositeFieldPublishingInfo() {
360         DateField dateField = new DateField("Date field");
361         dateField.setDateFormat("yyyy-MM-dd");
362         dateField.setValue(LocalDate.now());
363         dateField.setEnabled(false);
364         TextField user = new TextField("User");
365         user.setValue("superuser");
366         user.setEnabled(false);
367         TextField publisher = new TextField("Publisher");
368         TextField contributor = new TextField("Contributor");
369         TextField rights = new TextField("Rights");
370         TextField source = new TextField("Source");
371         TextField relation = new TextField("Relation");
372         return new CollapsibleCompositeField("Publishing info", false, dateField, user, publisher, contributor, rights, source, relation);
373     }
374 
375     private Component[] createActions() {
376         ComboBox<String> languageSelector = new ComboBox<>();
377         ListDataProvider<String> dataProvider = new ListDataProvider<>(Arrays.asList("English", "Việt Nam"));
378         languageSelector.setEmptySelectionAllowed(false);
379         languageSelector.setPlaceholder("Select...");
380         languageSelector.addStyleName("secondary-actions");
381         languageSelector.setDataProvider(dataProvider);
382 
383         Button saveButton = new Button("Save changes");
384         saveButton.addStyleName("commit primary-button primary-actions");
385 
386         Button downloadButton = new Button("Download");
387         downloadButton.addStyleName("download secondary-button primary-actions");
388 
389         Button cancelButton = new Button("Cancel");
390         cancelButton.addStyleName("cancel secondary-button primary-actions");
391 
392         return new Component[] { languageSelector, saveButton, downloadButton, cancelButton };
393     }
394 
395     @WebServlet(value = "/collapsibleCompositeFields/*", asyncSupported = true)
396     @VaadinServletConfiguration(productionMode = false, ui = CollapsibleCompositeFieldsUI.class)
397     public static class Servlet extends VaadinServlet {
398     }
399 }