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.icons.MagnoliaIcons;
39 import info.magnolia.poc.customer.Customer;
40 import info.magnolia.poc.customer.CustomerStatusRenderer;
41 import info.magnolia.poc.customer.CustomerService;
42 import info.magnolia.ui.theme.ResurfaceTheme;
43 import info.magnolia.ui.vaadin.actionbar.Actionbar;
44 import info.magnolia.ui.vaadin.dialog.BaseDialog;
45 import info.magnolia.ui.vaadin.gwt.client.actionbar.shared.ActionbarItem;
46
47 import java.time.LocalDate;
48 import java.time.format.DateTimeFormatter;
49 import java.util.Arrays;
50 import java.util.List;
51
52 import javax.servlet.annotation.WebServlet;
53
54 import org.jsoup.Jsoup;
55 import org.jsoup.safety.Whitelist;
56 import org.vaadin.addons.ComboBoxMultiselect;
57
58 import com.vaadin.addon.daterangefield.DateRangeField;
59 import com.vaadin.annotations.Theme;
60 import com.vaadin.annotations.Title;
61 import com.vaadin.annotations.VaadinServletConfiguration;
62 import com.vaadin.annotations.Widgetset;
63 import com.vaadin.data.provider.DataProvider;
64 import com.vaadin.data.provider.ListDataProvider;
65 import com.vaadin.icons.VaadinIcons;
66 import com.vaadin.server.ThemeResource;
67 import com.vaadin.server.VaadinRequest;
68 import com.vaadin.server.VaadinServlet;
69 import com.vaadin.shared.ui.ContentMode;
70 import com.vaadin.ui.Button;
71 import com.vaadin.ui.ComboBox;
72 import com.vaadin.ui.Component;
73 import com.vaadin.ui.CssLayout;
74 import com.vaadin.ui.FormLayout;
75 import com.vaadin.ui.Grid;
76 import com.vaadin.ui.HorizontalLayout;
77 import com.vaadin.ui.Image;
78 import com.vaadin.ui.Label;
79 import com.vaadin.ui.Panel;
80 import com.vaadin.ui.TabSheet;
81 import com.vaadin.ui.TextArea;
82 import com.vaadin.ui.TextField;
83 import com.vaadin.ui.TreeGrid;
84 import com.vaadin.ui.UI;
85 import com.vaadin.ui.VerticalLayout;
86 import com.vaadin.ui.components.grid.ItemClickListener;
87 import com.vaadin.ui.renderers.HtmlRenderer;
88 import com.vaadin.ui.themes.ValoTheme;
89
90 @Theme("poctheme")
91 @Title("Magnolia 6 Resurface")
92 @Widgetset("info.magnolia.poc.Widgetset")
93 public class LayoutUI extends UI {
94
95 @WebServlet(value = "/layout/*", asyncSupported = true)
96 @VaadinServletConfiguration(productionMode = false, ui = LayoutUI.class)
97 public static class Servlet extends VaadinServlet {
98 }
99
100 private HorizontalLayout header = new HorizontalLayout();
101 private CssLayout viewPort = new CssLayout();
102
103 @Override
104 protected void init(VaadinRequest request) {
105 header.setStyleName("header");
106 header.setSpacing(false);
107
108
109 CssLayout logoWrapper = createLogoComponent();
110
111
112 CssLayout finderBarContainer = new CssLayout();
113 finderBarContainer.setStyleName("periscope-wrapper");
114
115 Component finderBar = createFinderBar();
116
117 finderBarContainer.addComponent(finderBar);
118
119
120 CssLayout tasksWrapper = new CssLayout();
121 tasksWrapper.setStyleName("tasks-wrapper");
122 Component taskIndicator = createIndicatorComponent("Tasks", "23", "green");
123 tasksWrapper.addComponent(taskIndicator);
124
125
126 CssLayout messageWrapper = new CssLayout();
127 messageWrapper.setStyleName("messages-wrapper");
128 Component messageIndicator = createIndicatorComponent("Messages", "02", "green");
129 messageWrapper.addComponent(messageIndicator);
130
131
132 Component profileWrapper = createProfileComponent();
133 profileWrapper.setStyleName("profile-wrapper");
134
135
136 Component bannerWrapper = createBannerComponent(tasksWrapper);
137 bannerWrapper.setStyleName("banner-wrapper");
138 bannerWrapper.setVisible(false);
139
140
141 Component periscopeWrapper = periscopeComponent();
142 periscopeWrapper.setStyleName("periscope-filter-wrapper");
143 periscopeWrapper.setVisible(true);
144
145 header.addComponents(logoWrapper, finderBarContainer, tasksWrapper, messageWrapper, profileWrapper);
146
147 viewPort.setStyleName("viewport");
148 viewPort.setSizeFull();
149
150 Component tabSheet = createTabSheetComponent();
151 viewPort.addComponents(bannerWrapper, periscopeWrapper, tabSheet);
152
153
154 final VerticalLayout layout = new VerticalLayout();
155 layout.setStyleName("main-wrapper");
156 layout.setSpacing(false);
157 layout.addComponents(header, viewPort);
158 layout.setMargin(false);
159 layout.setExpandRatio(header, 0f);
160 layout.setExpandRatio(viewPort, 1f);
161 layout.setSizeFull();
162
163 setContent(layout);
164 }
165
166 private Component periscopeComponent() {
167 CssLayout periscopeWrapper = new CssLayout();
168 VerticalLayout periscopeFilterWrapper = new VerticalLayout();
169 periscopeFilterWrapper.setWidth(100, Unit.PERCENTAGE);
170
171 HorizontalLayout periscopeFilterHeader = new HorizontalLayout();
172 periscopeFilterHeader.setStyleName("periscope-filter-header-wrapper");
173 Button expandFilterOptionsButton = new Button(MagnoliaIcons.SELECT);
174 expandFilterOptionsButton.addStyleName(ResurfaceTheme.BUTTON_ICON);
175
176 Label searchLabel = new Label("Refined search by");
177 searchLabel.setVisible(false);
178 CssLayout globalTokenLayout = new CssLayout();
179 periscopeFilterHeader.addComponents(expandFilterOptionsButton, searchLabel, globalTokenLayout);
180
181 HorizontalLayout periscopeFilterOptions = new HorizontalLayout();
182 periscopeFilterOptions.setStyleName("periscope-filter-options-wrapper");
183 periscopeFilterOptions.setWidth(100, Unit.PERCENTAGE);
184 periscopeFilterOptions.setVisible(false);
185
186 VerticalLayout supplierLayout = new VerticalLayout();
187 ComboBoxMultiselect<String> supplierFilter = new ComboBoxMultiselect<>("Type");
188 supplierFilter.setStyleGenerator(item -> "periscope-filter-item");
189 supplierFilter.setWidth(100, Unit.PERCENTAGE);
190 supplierFilter.setPlaceholder("Select or search...");
191 ListDataProvider<String> listDataProvider = DataProvider.ofItems("Pages", "Assets", "Stories", "Tours", "Documentation");
192 supplierFilter.setDataProvider(listDataProvider);
193 listDataProvider.setSortComparator(null);
194 supplierFilter.setItemIconGenerator(item -> {
195 switch (item) {
196 case "Tours":
197 return MagnoliaIcons.LANGUAGE_APP;
198 default:
199 return MagnoliaIcons.RESOURCE_FILES_APP;
200 }
201 });
202 supplierFilter.setPageLength(5);
203 CssLayout supplierTokensLayout = new CssLayout();
204 supplierTokensLayout.setStyleName("token-layout");
205 supplierFilter.addValueChangeListener(event -> populateTokenLayout(supplierTokensLayout, supplierFilter, true));
206 supplierLayout.addComponents(supplierFilter, supplierTokensLayout);
207
208 VerticalLayout tagsLayout = new VerticalLayout();
209 ComboBoxMultiselect<String> tagsFilter = new ComboBoxMultiselect<>("Tags");
210 tagsFilter.setStyleGenerator(item -> "periscope-filter-item");
211 tagsFilter.setWidth(100, Unit.PERCENTAGE);
212 tagsFilter.setPlaceholder("Select or search...");
213 tagsFilter.setItems("adventure", "history", "mountains", "exotic", "food", "luxury", "unique", "all-inclusive", "drive", "orient", "wild-animals", "health", "snow", "spirituality", "islands", "sale", "city");
214 tagsFilter.setPageLength(5);
215 CssLayout tagsTokensLayout = new CssLayout();
216 tagsTokensLayout.setStyleName("token-layout");
217 tagsFilter.addValueChangeListener(event -> populateTokenLayout(tagsTokensLayout, tagsFilter, true));
218 tagsLayout.addComponents(tagsFilter, tagsTokensLayout);
219
220 VerticalLayout editorLayout = new VerticalLayout();
221 ComboBoxMultiselect<String> editorFilter = new ComboBoxMultiselect<>("Last editor");
222 editorFilter.setStyleGenerator(item -> "periscope-filter-item");
223 editorFilter.setWidth(100, Unit.PERCENTAGE);
224 editorFilter.setPlaceholder("Select or search...");
225 editorFilter.setItems("Glenn Gomez", "Birdie Ball", "Cecelia Murphy", "Pauline Clarke", "Charlie Strickland", "Georgia Gaza");
226 editorFilter.setPageLength(5);
227 CssLayout editorTokensLayout = new CssLayout();
228 editorTokensLayout.setStyleName("token-layout");
229 editorFilter.addValueChangeListener(event -> populateTokenLayout(editorTokensLayout, editorFilter, true));
230 editorLayout.addComponents(editorFilter, editorTokensLayout);
231
232 VerticalLayout dateLayout = new VerticalLayout();
233 DateRangeField dateRangeField = new DateRangeField("Last edited");
234 dateRangeField.setWidth(100, Unit.PERCENTAGE);
235 dateRangeField.setStyleName("date-range-field");
236 dateRangeField.getBeginDateField().setPlaceholder("Begin date");
237 dateRangeField.getEndDateField().setPlaceholder("End date");
238 LocalDate today = LocalDate.now();
239 dateRangeField.addShortcut("Today", field -> field.setRange(today, today));
240 dateRangeField.addShortcut("Last week", field -> field.setRange(today.minusWeeks(1), today));
241 dateRangeField.addShortcut("Last month", field -> field.setRange(today.minusMonths(1), today));
242 dateRangeField.addShortcut("Last year", field -> field.setRange(today.minusYears(1), today));
243 dateRangeField.addShortcutSeparator();
244 dateRangeField.addShortcut("Clear", DateRangeField::clear);
245 CssLayout dateTokenLayout = new CssLayout();
246 dateTokenLayout.setStyleName("token-layout");
247 dateRangeField.addValueChangeListener(event -> populateDateTokenLayout(dateTokenLayout, dateRangeField, true));
248 dateLayout.addComponents(dateRangeField, dateTokenLayout);
249
250 expandFilterOptionsButton.addClickListener(click -> {
251 if (periscopeFilterOptions.isVisible()) {
252 periscopeFilterOptions.setVisible(false);
253 if (supplierTokensLayout.getComponentCount() < 1 && tagsTokensLayout.getComponentCount() < 1 && editorTokensLayout.getComponentCount() < 1 && dateTokenLayout.getComponentCount() < 1) {
254 searchLabel.setVisible(false);
255 }
256 populateTokenLayout(globalTokenLayout, supplierFilter, true);
257 populateTokenLayout(globalTokenLayout, tagsFilter, false);
258 populateTokenLayout(globalTokenLayout, editorFilter, false);
259 populateDateTokenLayout(globalTokenLayout, dateRangeField, false);
260 globalTokenLayout.setVisible(true);
261 } else {
262 periscopeFilterOptions.setVisible(true);
263 searchLabel.setVisible(true);
264 globalTokenLayout.setVisible(false);
265 }
266 });
267
268 periscopeFilterOptions.addComponents(supplierLayout, tagsLayout, editorLayout, dateLayout);
269
270 periscopeFilterWrapper.addComponents(periscopeFilterHeader, periscopeFilterOptions);
271 periscopeWrapper.addComponent(periscopeFilterWrapper);
272
273 return periscopeWrapper;
274 }
275
276 private void populateTokenLayout(CssLayout privateTokenLayout, ComboBoxMultiselect<String> field, boolean purgeLayout) {
277 if (purgeLayout) {
278 privateTokenLayout.removeAllComponents();
279 }
280 field.getValue().forEach(token -> {
281 Button tokenButton = new Button(token, click -> {
282 privateTokenLayout.removeComponent(click.getButton());
283 field.deselect(click.getButton().getCaption());
284 });
285 tokenButton.setIcon(MagnoliaIcons.CLOSE);
286 tokenButton.addStyleName("periscope-token-button");
287 privateTokenLayout.addComponent(tokenButton);
288 });
289 }
290
291 private void populateDateTokenLayout(CssLayout dateTokenLayout, DateRangeField dateRangeField, boolean purgeLayout) {
292 if (purgeLayout) {
293 dateTokenLayout.removeAllComponents();
294 }
295 if (dateRangeField.getBeginDate() == null && dateRangeField.getEndDate() == null) {
296 return;
297 }
298 String label;
299 if (dateRangeField.getBeginDate() != null && dateRangeField.getEndDate() != null) {
300 label = dateRangeField.getBeginDate().format(DateTimeFormatter.ofPattern("dd.MM.yy"));
301 label += " - ";
302 label += dateRangeField.getEndDate().format(DateTimeFormatter.ofPattern("dd.MM.yy"));
303 } else if (dateRangeField.getBeginDate() != null) {
304 label = "> ";
305 label += dateRangeField.getBeginDate().format(DateTimeFormatter.ofPattern("dd.MM.yy"));
306 } else {
307 label = "< ";
308 label += dateRangeField.getEndDate().format(DateTimeFormatter.ofPattern("dd.MM.yy"));
309 }
310 Button tokenButton = new Button(label, click -> {
311 dateTokenLayout.removeComponent(click.getButton());
312 dateRangeField.clear();
313 });
314 tokenButton.setIcon(MagnoliaIcons.CLOSE);
315 tokenButton.addStyleName("periscope-token-button");
316 dateTokenLayout.addComponent(tokenButton);
317 }
318
319 private CssLayout createLogoComponent() {
320 CssLayout logoWrapper = new CssLayout();
321 logoWrapper.setStyleName("logo-wrapper");
322
323 ThemeResource resource = new ThemeResource("img/logo-magnolia.svg");
324
325 Image image = new Image("Magnolia logo", resource);
326 image.addStyleName("header-component");
327 logoWrapper.addComponent(image);
328 return logoWrapper;
329 }
330
331 private HorizontalLayout createProfileComponent() {
332 HorizontalLayout profileWrapper = new HorizontalLayout();
333 profileWrapper.setSpacing(false);
334 profileWrapper.setMargin(false);
335
336 Label avatar = new Label();
337 avatar.setContentMode(ContentMode.HTML);
338 avatar.addStyleName("header-component");
339 avatar.setValue("<span class='indicator number icon-user-role'></span>");
340 profileWrapper.addComponent(avatar);
341
342 Component profileComponent = createHeaderComponent("public-01", "INT");
343 profileWrapper.addComponent(profileComponent);
344 return profileWrapper;
345 }
346
347 private Component createBannerComponent(CssLayout tasksWrapper) {
348 CssLayout bannerWrapper = new CssLayout();
349 bannerWrapper.setWidth(100, Unit.PERCENTAGE);
350 bannerWrapper.setHeight(80, Unit.PIXELS);
351
352 VerticalLayout banner = new VerticalLayout();
353 banner.addStyleNames("banner", "info");
354 banner.setSpacing(false);
355 banner.setMargin(false);
356
357 Label infoLabel = new Label("Info");
358 infoLabel.addStyleName("header");
359
360 Label bodyLabel = new Label("Your license will expire in 15 days. Renew now.");
361 bodyLabel.addStyleName("body");
362
363 Button closeButton = new Button();
364 closeButton.setCaptionAsHtml(true);
365 closeButton.setPrimaryStyleName("icon-close");
366 closeButton.addStyleName("close");
367 closeButton.addClickListener(e -> bannerWrapper.setVisible(false));
368
369 banner.addComponents(infoLabel, bodyLabel, closeButton);
370 bannerWrapper.addComponent(banner);
371
372 tasksWrapper.addLayoutClickListener(e -> {
373 if (!bannerWrapper.isVisible()) {
374 bannerWrapper.setVisible(true);
375 }
376
377 switch (banner.getStyleName()) {
378 case "banner info":
379 banner.removeStyleName("info");
380 banner.addStyleName("warning");
381 infoLabel.setValue("Warning");
382 bodyLabel.setValue("Your license will expire tomorrow. Magnolia will stop functioning if no valid license is found. Renew now.");
383 break;
384 case "banner warning":
385 banner.removeStyleName("warning");
386 banner.addStyleName("error");
387 infoLabel.setValue("Error");
388 bodyLabel.setValue("The multipart stream ended unexpectedly. More.");
389 break;
390 case "banner error":
391 banner.removeStyleName("error");
392 banner.addStyleName("info");
393 infoLabel.setValue("Info");
394 bodyLabel.setValue("Your license will expire in 15 days. Renew now.");
395 break;
396 }
397 });
398
399 return bannerWrapper;
400 }
401
402 private HorizontalLayout createFinderBar() {
403 HorizontalLayout finderBar = new HorizontalLayout();
404 finderBar.addStyleName("header-component");
405 finderBar.setSpacing(false);
406 finderBar.setMargin(false);
407 finderBar.setSizeFull();
408 Button shellButton = new Button();
409 shellButton.addStyleName("btn-shell icon-appslauncher btn-appslauncher");
410 finderBar.addComponent(shellButton);
411 finderBar.setExpandRatio(shellButton, 0f);
412
413 CssLayout searchField = new CssLayout();
414 searchField.setStyleName("search-field");
415 TextField textField = new TextField();
416 textField.addStyleNames("search-textfield", "heading-2");
417 textField.setPlaceholder("Type to find");
418 searchField.addComponent(textField);
419 Label searchIcon = new Label();
420 searchIcon.setStyleName("icon-search");
421 searchField.addComponent(searchIcon);
422
423 finderBar.addComponent(searchField);
424 finderBar.setExpandRatio(searchField, 1f);
425
426
427 Button voiceButton = new Button();
428 voiceButton.addStyleName("btn-shell icon-target-app btn-voice");
429 finderBar.addComponent(voiceButton);
430 finderBar.setExpandRatio(voiceButton, 0f);
431
432 return finderBar;
433 }
434
435 private Component createIndicatorComponent(String label, String value, String status) {
436 return createHeaderComponent(label, value + "<span class='status icon-status-" + status + " color-" + status + "'></span>");
437 }
438
439 private Component createHeaderComponent(String label, String value) {
440
441 VerticalLayout tasksComponent = new VerticalLayout();
442 tasksComponent.setSpacing(false);
443 tasksComponent.setMargin(false);
444 tasksComponent.setStyleName("header-component");
445 Label taskNumber = new Label();
446 taskNumber.addStyleName("indicator heading-2");
447 taskNumber.setValue(value);
448 taskNumber.setContentMode(ContentMode.HTML);
449 Label taskLabel = new Label(label);
450 taskLabel.addStyleNames("text-tiny");
451 tasksComponent.addComponents(taskNumber, taskLabel);
452
453 return tasksComponent;
454 }
455
456 private Component createTabSheetComponent() {
457
458 TabSheet tabSheetComponent = new TabSheet();
459 tabSheetComponent.addStyleName(ValoTheme.TABSHEET_FRAMED);
460 tabSheetComponent.addStyleName("apps");
461 tabSheetComponent.setSizeFull();
462
463 Component browserSubapp = createBrowserAppComponent();
464 browserSubapp.addStyleName("app");
465 tabSheetComponent.addTab(browserSubapp, "Browser");
466 tabSheetComponent.setSizeFull();
467 browserSubapp.setSizeFull();
468
469 Component detailAppWithVerticalLayout = createDetailAppWithVerticalLayout();
470 detailAppWithVerticalLayout.addStyleName("app");
471 tabSheetComponent.addTab(detailAppWithVerticalLayout, "Detail app w/ VerticalLayout");
472
473 Component detailApp = createDetailAppWithBaseDialog();
474 detailApp.addStyleName("app");
475 tabSheetComponent.addTab(detailApp, "Detail app w/ BaseDialog", MagnoliaIcons.EDIT);
476
477 final TextArea plainText3 = new TextArea();
478 plainText3.setWidth("100%");
479 plainText3.setRows(10);
480 plainText3.setValue("Soccis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. " +
481 "Vestibulum id ligula porta felis euismod semper. " +
482 "Nullam quis risus eget urna mollis ornare vel eu leo. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.");
483 TabSheet.Tab tab3 = tabSheetComponent.addTab(plainText3, "Tab text 3");
484 tab3.setClosable(true);
485
486 Component longLabelWithIconAndCloseButton = createDetailAppWithBaseDialog();
487 longLabelWithIconAndCloseButton.addStyleName("app");
488 TabSheet.Tab tab4 = tabSheetComponent.addTab(longLabelWithIconAndCloseButton, "Super long text so ellipsis is used", MagnoliaIcons.UPLOAD);
489 tab4.setClosable(true);
490
491 return tabSheetComponent;
492 }
493
494 private Component createBrowserAppComponent() {
495 VerticalLayout browser = new VerticalLayout();
496 browser.addStyleName("browser");
497 browser.setSizeFull();
498 browser.setMargin(false);
499
500 VerticalLayout workbench = new VerticalLayout();
501 workbench.addStyleName("workbench");
502 workbench.setSizeFull();
503 workbench.setMargin(false);
504 Component toolBar = buildToolBar();
505 Component contentView = buildContentView();
506 Component statusBar = buildStatusBar();
507 workbench.addComponents(toolBar, contentView, statusBar);
508 workbench.setExpandRatio(toolBar, 0f);
509 workbench.setExpandRatio(contentView, 1f);
510
511 Component actionbar = buildActionBar();
512
513 HorizontalLayout workbenchWrapper = new HorizontalLayout();
514 workbenchWrapper.setSizeFull();
515 workbenchWrapper.addComponents(workbench, actionbar);
516 workbenchWrapper.setExpandRatio(workbench, 1f);
517 workbenchWrapper.setExpandRatio(actionbar, 0f);
518
519
520 browser.addComponents(workbenchWrapper, statusBar);
521 browser.setExpandRatio(workbenchWrapper, 1f);
522 browser.setExpandRatio(statusBar, 0f);
523
524
525 return browser;
526 }
527
528 private Component buildToolBar() {
529 HorizontalLayout toolbar = new HorizontalLayout();
530 toolbar.setWidth(100, PERCENTAGE);
531 toolbar.addStyleName("toolbar");
532 toolbar.setSpacing(true);
533
534 CssLayout viewModes = new CssLayout();
535 viewModes.addStyleName("view-modes");
536
537 Button treeBtn = new Button(MagnoliaIcons.VIEW_TREE);
538 treeBtn.addStyleNames(ResurfaceTheme.BUTTON_ICON, "link active");
539
540 Button listBtn = new Button(MagnoliaIcons.VIEW_LIST);
541 listBtn.addStyleNames(ResurfaceTheme.BUTTON_ICON, "link");
542
543 Button thumbnailBtn = new Button(MagnoliaIcons.VIEW_THUMBNAILS);
544 thumbnailBtn.addStyleNames(ResurfaceTheme.BUTTON_ICON, "link");
545
546 viewModes.addComponents(treeBtn, listBtn, thumbnailBtn);
547
548 CssLayout searchBox = new CssLayout();
549 searchBox.addStyleName("searchbox");
550
551
552
553
554
555
556 toolbar.addComponents(viewModes, searchBox);
557
558 return toolbar;
559 }
560
561 private Component buildContentView() {
562 Panel keyboardPanel = new Panel();
563 keyboardPanel.setSizeFull();
564 keyboardPanel.addStyleName("keyboard-panel");
565
566 TreeGrid<Customer> treeGrid = new TreeGrid<>();
567
568 treeGrid.setSizeFull();
569
570 treeGrid.addColumn(customer -> {
571 String iconHtml;
572 if (customer.isPersisted()) {
573 iconHtml = VaadinIcons.FOLDER_O.getHtml();
574 } else {
575 iconHtml = VaadinIcons.FILE_O.getHtml();
576 }
577 return iconHtml + " " + Jsoup.clean(customer.getLastName(), Whitelist.simpleText());
578 }, new HtmlRenderer()).setCaption("Last Name").setExpandRatio(5);
579 treeGrid.addColumn(Customer::getFirstName).setCaption("First Name").setExpandRatio(2);
580 treeGrid.addColumn(customer -> customer.getStatus().name(), new CustomerStatusRenderer()).setCaption("Status").setExpandRatio(0);
581 treeGrid.addColumn(Customer::getBirthDate).setCaption("Date of Birth").setExpandRatio(2);
582 treeGrid.addColumn(Customer::getEmail).setCaption("Email").setExpandRatio(2);
583
584 treeGrid.setSelectionMode(Grid.SelectionMode.MULTI);
585
586 treeGrid.addItemClickListener((ItemClickListener<Customer>) event -> {
587 if (event.getSource().getSelectionModel().isSelected(event.getItem())) {
588 event.getSource().getSelectionModel().deselect(event.getItem());
589 } else {
590 event.getSource().getSelectionModel().select(event.getItem());
591 }
592 });
593
594
595
596 CustomerService service = CustomerService.getInstance();
597 List<Customer> customers = service.findAll();
598 treeGrid.setItems(customers, Customer::getChildren);
599
600 keyboardPanel.setContent(treeGrid);
601
602 return keyboardPanel;
603 }
604
605 private Component buildStatusBar() {
606 HorizontalLayout statusBar = new HorizontalLayout();
607 statusBar.addStyleName("statusbar");
608 statusBar.setWidth(100, PERCENTAGE);
609
610 Label label = new Label("Profile images / Directors / Managing directors /");
611 label.setWidth(100, PERCENTAGE);
612
613 statusBar.addComponent(label);
614
615 return statusBar;
616 }
617
618 private Component buildActionBar() {
619 Actionbar actionbar = new Actionbar();
620 actionbar.addSection("main", "Actions");
621 actionbar.addAction(new ActionbarItem("addAction", "Add action", "icon-add-item", "addActions"), "main");
622 actionbar.addAction(new ActionbarItem("deleteAction", "Delete action", "icon-delete", "addActions"), "main");
623 actionbar.addAction(new ActionbarItem("editAction", "Edit action", "icon-edit", "editActions"), "main");
624 CssLayout wrapper = new CssLayout();
625 wrapper.addComponent(actionbar);
626 wrapper.setWidthUndefined();
627 wrapper.setHeight(100, Unit.PERCENTAGE);
628 wrapper.addStyleName("actionbar");
629 return wrapper;
630 }
631
632 private Component createDetailAppWithBaseDialog() {
633 HorizontalLayout detail = new HorizontalLayout();
634 detail.addStyleName("detail basedialog");
635 detail.setSizeFull();
636
637 CssLayout detailView = new CssLayout();
638 detailView.addStyleName("detailview");
639 detailView.setSizeFull();
640 detail.addComponent(detailView);
641
642 BaseDialog baseDialog = new BaseDialog();
643 baseDialog.setCaption("Asset");
644 baseDialog.setDialogDescription("This is description");
645 baseDialog.setDescriptionVisibility(true);
646 baseDialog.setSizeFull();
647
648 baseDialog.setContent(createDetailForm());
649
650 CssLayout footer = new CssLayout();
651 footer.setWidth(100, PERCENTAGE);
652 footer.addComponents(createActions());
653 baseDialog.setFooterToolbar(footer);
654
655 Panel panel = new Panel();
656 panel.setSizeFull();
657 panel.setContent(baseDialog);
658
659 detailView.addComponent(panel);
660
661 return detail;
662 }
663
664 private Component createDetailAppWithVerticalLayout() {
665 VerticalLayout detailLayout = new VerticalLayout();
666 detailLayout.addStyleName("detail");
667 detailLayout.setSizeFull();
668 detailLayout.setMargin(false);
669 detailLayout.setSpacing(false);
670
671 Label title = new Label();
672 title.addStyleName("heading-1 title");
673 title.setValue("Asset");
674
675 CssLayout header = new CssLayout();
676 header.addStyleName("detail-header");
677 header.addComponent(title);
678
679 Component detailForm = createDetailForm();
680 detailForm.addStyleName("detail-content");
681
682 CssLayout footer = new CssLayout();
683 footer.addStyleName("detail-footer");
684 footer.setWidth(100, PERCENTAGE);
685 footer.addComponents(createActions());
686
687 detailLayout.addComponents(header, detailForm, footer);
688 detailLayout.setExpandRatio(header, 0f);
689 detailLayout.setExpandRatio(detailForm, 1f);
690 detailLayout.setExpandRatio(footer, 0f);
691
692 return detailLayout;
693 }
694
695 private Component createDetailForm() {
696 TabSheet tabSheetComponent = new TabSheet();
697 tabSheetComponent.setSizeFull();
698 tabSheetComponent.addStyleName(ValoTheme.TABSHEET_FRAMED);
699
700 tabSheetComponent.addTab(createTab1(), "Meta Data");
701 tabSheetComponent.addTab(createTab2(), "Article Info");
702 tabSheetComponent.addTab(createTab3(), "Output channels");
703
704 return tabSheetComponent;
705 }
706
707 private FormLayout createTab1() {
708 FormLayout form = new FormLayout();
709 form.setMargin(true);
710 form.setSizeFull();
711
712 TextField textField = new TextField("Asset name");
713
714 TextField textFieldHover = new TextField("File name");
715 textFieldHover.setDescription("This is file name");
716
717 TextField textFieldFocus = new TextField("Location");
718 textFieldFocus.setValue("Basel ");
719
720 form.addComponents(textField,
721 textFieldHover,
722 textFieldFocus);
723
724 form.iterator().forEachRemaining(
725 component -> component.setWidth(100, PERCENTAGE)
726 );
727
728 return form;
729 }
730
731 private FormLayout createTab2() {
732 FormLayout form = new FormLayout();
733 form.setMargin(true);
734 form.setSizeFull();
735
736 TextField disabledTextField = new TextField("Author");
737 disabledTextField.setEnabled(false);
738
739 TextField textFieldValidation = new TextField("Birthday");
740
741 form.addComponents(disabledTextField,
742 textFieldValidation);
743
744 form.iterator().forEachRemaining(
745 component -> component.setWidth(100, PERCENTAGE)
746 );
747
748 return form;
749 }
750
751 private FormLayout createTab3() {
752 FormLayout form = new FormLayout();
753 form.setMargin(true);
754 form.setSizeFull();
755
756 TextField textFieldWithPlaceHolder = new TextField("Title");
757 textFieldWithPlaceHolder.setPlaceholder("Add title here...");
758
759 TextArea expandable = new TextArea("Description");
760 expandable.setRows(1);
761
762 form.addComponents(textFieldWithPlaceHolder,
763 expandable);
764
765 form.iterator().forEachRemaining(
766 component -> component.setWidth(100, PERCENTAGE)
767 );
768
769 return form;
770 }
771
772 private Component[] createActions() {
773 ComboBox<String> languageSelector = new ComboBox<>();
774 ListDataProvider<String> dataProvider = new ListDataProvider<>(Arrays.asList("English", "Việt Nam"));
775 languageSelector.setEmptySelectionAllowed(false);
776 languageSelector.setPlaceholder("Select...");
777 languageSelector.addStyleName("secondary-actions");
778 languageSelector.setDataProvider(dataProvider);
779
780 Button saveButton = new Button("Save changes");
781 saveButton.addStyleName("commit primary-button primary-actions");
782
783 Button downloadButton = new Button("Download", MagnoliaIcons.SHOW_VERSIONS);
784 downloadButton.addStyleName("download secondary-button primary-actions");
785
786 Button cancelButton = new Button("Cancel");
787 cancelButton.addStyleName("cancel secondary-button primary-actions");
788
789 return new Component[] { languageSelector, saveButton, downloadButton, cancelButton };
790 }
791
792 @Override
793 public boolean equals(Object obj) {
794 return super.equals(obj);
795 }
796
797 @Override
798 public int hashCode() {
799 return super.hashCode();
800 }
801 }