1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
84 CssLayout logoWrapper = createLogoComponent();
85
86
87 CssLayout finderBarContainer = new CssLayout();
88 finderBarContainer.setStyleName("periscope-wrapper");
89
90 Component finderBar = createFinderBar();
91
92 finderBarContainer.addComponent(finderBar);
93
94
95 CssLayout tasksWrapper = new CssLayout();
96 tasksWrapper.setStyleName("tasks-wrapper");
97 Component taskIndicator = createIndicatorComponent("Tasks", "23", "green");
98 tasksWrapper.addComponent(taskIndicator);
99
100
101 CssLayout messageWrapper = new CssLayout();
102 messageWrapper.setStyleName("messages-wrapper");
103 Component messageIndicator = createIndicatorComponent("Messages", "02", "green");
104 messageWrapper.addComponent(messageIndicator);
105
106
107 Component profileWrapper = createProfileComponent();
108 profileWrapper.setStyleName("profile-wrapper");
109
110
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
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 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 }