├── .gitignore
├── LICENSE
├── README.md
├── betternavi
├── README.md
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── vaadin
│ │ └── example
│ │ ├── AboutView.java
│ │ ├── AboutViewDesign.java
│ │ ├── DashboardView.java
│ │ ├── DashboardViewDesign.java
│ │ ├── MainLayout.java
│ │ ├── MainLayoutDesign.java
│ │ ├── MyUI.java
│ │ ├── OrderView.java
│ │ └── OrderViewDesign.java
│ ├── resources
│ └── org
│ │ └── vaadin
│ │ └── example
│ │ ├── AboutViewDesign.html
│ │ ├── DashboardViewDesign.html
│ │ ├── MainLayoutDesign.html
│ │ └── OrderViewDesign.html
│ └── webapp
│ └── VAADIN
│ └── themes
│ └── mytheme
│ ├── addons.scss
│ ├── designs.scss
│ ├── favicon.ico
│ ├── mytheme.scss
│ └── styles.scss
├── emailclient-tutorial-data
├── README.adoc
├── pom.xml
├── src
│ └── main
│ │ ├── java
│ │ └── org
│ │ │ └── vaadin
│ │ │ └── example
│ │ │ ├── backend
│ │ │ ├── AbstractEntity.java
│ │ │ ├── CdiConfig.java
│ │ │ ├── DatabaseInitialization.java
│ │ │ ├── Message.java
│ │ │ ├── MessageFacade.java
│ │ │ └── MessageRepository.java
│ │ │ └── ui
│ │ │ ├── FolderView.java
│ │ │ ├── MainLayout.java
│ │ │ ├── MainLayoutDesign.java
│ │ │ ├── MessageComponent.java
│ │ │ ├── MessageDesign.java
│ │ │ ├── MessageModifiedEvent.java
│ │ │ ├── MyUI.java
│ │ │ └── themes
│ │ │ └── mytheme
│ │ │ └── MyTheme.java
│ │ ├── resources
│ │ ├── META-INF
│ │ │ ├── apache-deltaspike.properties
│ │ │ └── persistence.xml
│ │ └── org
│ │ │ └── vaadin
│ │ │ └── example
│ │ │ └── ui
│ │ │ ├── MainLayoutDesign.html
│ │ │ └── MessageDesign.html
│ │ └── webapp
│ │ ├── VAADIN
│ │ └── themes
│ │ │ └── mytheme
│ │ │ ├── addons.scss
│ │ │ ├── designs.scss
│ │ │ ├── favicon.ico
│ │ │ ├── mytheme.scss
│ │ │ └── styles.scss
│ │ └── WEB-INF
│ │ └── beans.xml
└── tutorial-images
│ └── email-client-with-data.png
├── emailclient-tutorial
├── README.md
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── vaadin
│ │ └── example
│ │ ├── ApplicationDesign.java
│ │ ├── Message.java
│ │ ├── MessageDesign.java
│ │ └── MyUI.java
│ ├── resources
│ └── org
│ │ └── vaadin
│ │ └── example
│ │ ├── ApplicationDesign.html
│ │ └── MessageDesign.html
│ └── webapp
│ └── VAADIN
│ └── themes
│ └── mytheme
│ ├── addons.scss
│ ├── designs.scss
│ ├── favicon.ico
│ ├── mytheme.scss
│ └── styles.scss
└── simplenavi
├── README.md
├── pom.xml
└── src
└── main
├── java
└── org
│ └── vaadin
│ └── example
│ ├── MainLayout.java
│ ├── MainLayoutDesign.java
│ ├── MyUI.java
│ ├── PermissionsView.java
│ ├── PermissionsViewDesign.java
│ ├── PluginsView.java
│ ├── PluginsViewDesign.java
│ ├── StatsView.java
│ └── StatsViewDesign.java
├── resources
└── org
│ └── vaadin
│ └── example
│ ├── MainLayoutDesign.html
│ ├── PermissionsViewDesign.html
│ ├── PluginsViewDesign.html
│ └── StatsViewDesign.html
└── webapp
└── VAADIN
└── themes
└── mytheme
├── addons.scss
├── favicon.ico
├── mytheme.scss
└── styles.scss
/.gitignore:
--------------------------------------------------------------------------------
1 | .settings
2 | .project
3 | .classpath
4 | *.class
5 | rebel.xml
6 | target
7 | .designer
8 | styles.scss.cache
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Vaadin Designer tutorials
2 | This repository contains sample codes of various tutorials related to Vaadin application development using Vaadin Designer.
3 | * simplenavi and betternavi are sample codes of a tutorial found here: https://vaadin.com/wiki/-/wiki/Main/View+navigation+with+Vaadin+Designer
4 | * emailclient-tutorial is about using Vaadin Designer to build a bit more complex application design. The tutorial is written in the readme file (nicely formatted of course) and contains a link to a nice video.
5 | * emailclient-tutorial-data shows you how to connect an existing datasource to your complex application design. The basis for the UI is the same as in emailclient-tutorial and the datasource is implemented as an EJB facade and Apache DeltaSpike repository.
6 |
--------------------------------------------------------------------------------
/betternavi/README.md:
--------------------------------------------------------------------------------
1 | `This tutorial is written using Java 8`
2 |
3 | betternavi
4 | ==============
5 |
6 | Template for a simple Vaadin application that only requires a Servlet 3.0 container to run.
7 |
8 |
9 | Workflow
10 | ========
11 |
12 | To compile the entire project, run "mvn install".
13 | To run the application, run "mvn jetty:run" and open http://localhost:8080/ .
14 |
15 | To develop the theme, simply update the relevant theme files and reload the application.
16 | Pre-compiling a theme eliminates automatic theme updates at runtime - see below for more information.
17 |
18 | Debugging client side code
19 | - run "mvn vaadin:run-codeserver" on a separate console while the application is running
20 | - activate Super Dev Mode in the debug window of the application
21 |
22 | To produce a deployable production mode WAR:
23 | - change productionMode to true in the servlet class configuration (nested in the UI class)
24 | - run "mvn clean vaadin:compile-theme package"
25 | - See below for more information. Running "mvn clean" removes the pre-compiled theme.
26 | - test with "mvn jetty:run-war
27 |
28 | Using a precompiled theme
29 | -------------------------
30 |
31 | When developing the application, Vaadin can compile the theme on the fly when needed,
32 | or the theme can be precompiled to speed up page loads.
33 |
34 | To precompile the theme run "mvn vaadin:compile-theme". Note, though, that once
35 | the theme has been precompiled, any theme changes will not be visible until the
36 | next theme compilation or running the "mvn clean" target.
37 |
38 | When developing the theme, running the application in the "run" mode (rather than
39 | in "debug") in the IDE can speed up consecutive on-the-fly theme compilations
40 | significantly.
41 |
--------------------------------------------------------------------------------
/betternavi/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.vaadin.example
6 | betternavi
7 | war
8 | 1.0-SNAPSHOT
9 | betternavi
10 |
11 |
12 | 3
13 |
14 |
15 |
16 | 7.7.3
17 | ${vaadin.version}
18 | 9.2.3.v20140905
19 | 1.8
20 | 1.8
21 | UTF-8
22 |
23 | local
24 |
25 |
26 |
27 |
28 | vaadin-addons
29 | https://maven.vaadin.com/vaadin-addons
30 |
31 |
32 |
33 |
34 |
35 |
36 | com.vaadin
37 | vaadin-bom
38 | ${vaadin.version}
39 | pom
40 | import
41 |
42 |
43 |
44 |
45 |
46 |
47 | javax.servlet
48 | javax.servlet-api
49 | 3.0.1
50 | provided
51 |
52 |
53 | com.vaadin
54 | vaadin-server
55 |
56 |
57 | com.vaadin
58 | vaadin-push
59 |
60 |
61 | com.vaadin
62 | vaadin-client-compiled
63 |
64 |
65 | com.vaadin
66 | vaadin-themes
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-compiler-plugin
75 | 3.0
76 |
77 | ${project.encoding}
78 | ${project.source.version}
79 | ${project.target.version}
80 |
81 |
82 |
83 | org.apache.maven.plugins
84 | maven-resources-plugin
85 | 2.6
86 |
87 | ${project.encoding}
88 |
89 |
90 |
91 | org.apache.maven.plugins
92 | maven-war-plugin
93 | 2.3
94 |
95 | false
96 |
97 | WEB-INF/classes/VAADIN/gwt-unitCache/**,
98 | WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**
99 |
100 |
101 |
102 | com.vaadin
103 | vaadin-maven-plugin
104 | ${vaadin.plugin.version}
105 |
106 | -Xmx512M -Xss1024k
107 | ${basedir}/target/classes/VAADIN/widgetsets
108 | false
109 | false
110 |
111 | true
112 |
113 |
114 |
115 |
116 | update-theme
117 | update-widgetset
118 | compile
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | org.apache.maven.plugins
127 | maven-source-plugin
128 | 2.4
129 |
130 |
131 | org.apache.maven.plugins
132 | maven-clean-plugin
133 | 2.6.1
134 |
135 |
136 |
137 |
138 | src/main/webapp/VAADIN/themes
139 |
140 | **/styles.css
141 | **/styles.scss.cache
142 |
143 |
144 |
145 |
146 |
147 |
148 |
150 |
151 | org.eclipse.jetty
152 | jetty-maven-plugin
153 | ${jetty.plugin.version}
154 |
155 | 2
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | vaadin-prerelease
165 |
166 | false
167 |
168 |
169 |
170 |
171 | vaadin-prereleases
172 | https://maven.vaadin.com/vaadin-prereleases
173 |
174 |
175 | vaadin-snapshots
176 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/
177 |
178 | false
179 |
180 |
181 | true
182 |
183 |
184 |
185 |
186 |
187 | vaadin-prereleases
188 | https://maven.vaadin.com/vaadin-prereleases
189 |
190 |
191 | vaadin-snapshots
192 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/
193 |
194 | false
195 |
196 |
197 | true
198 |
199 |
200 |
201 |
202 |
203 |
204 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/AboutView.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.navigator.View;
4 | import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
5 |
6 | public class AboutView extends AboutViewDesign implements View {
7 |
8 | public static final String VIEW_NAME = "about";
9 |
10 | @Override
11 | public void enter(ViewChangeEvent event) {
12 | // TODO Auto-generated method stub
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/AboutViewDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.VerticalLayout;
6 | import com.vaadin.ui.declarative.Design;
7 |
8 | /**
9 | * !! DO NOT EDIT THIS FILE !!
10 | *
11 | * This class is generated by Vaadin Designer and will be overwritten.
12 | *
13 | * Please make a subclass with logic and additional interfaces as needed,
14 | * e.g class LoginView extends LoginDesign implements View { … }
15 | */
16 | @DesignRoot
17 | @AutoGenerated
18 | @SuppressWarnings("serial")
19 | public class AboutViewDesign extends VerticalLayout {
20 | public AboutViewDesign() {
21 | Design.read(this);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/DashboardView.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.navigator.View;
4 | import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
5 |
6 | public class DashboardView extends DashboardViewDesign implements View {
7 |
8 | public static final String VIEW_NAME = "dashboard";
9 |
10 | @Override
11 | public void enter(ViewChangeEvent event) {
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/DashboardViewDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.CssLayout;
6 | import com.vaadin.ui.Label;
7 | import com.vaadin.ui.declarative.Design;
8 |
9 | /**
10 | * !! DO NOT EDIT THIS FILE !!
11 | *
12 | * This class is generated by Vaadin Designer and will be overwritten.
13 | *
14 | * Please make a subclass with logic and additional interfaces as needed,
15 | * e.g class LoginView extends LoginDesign implements View { … }
16 | */
17 | @DesignRoot
18 | @AutoGenerated
19 | @SuppressWarnings("serial")
20 | public class DashboardViewDesign extends CssLayout {
21 | protected Label billing_header_label;
22 | protected CssLayout dashboard_item5;
23 | protected Label dashboard_item_header;
24 | protected Label statistics_label;
25 | protected Label statistics_label2;
26 | protected Label statistics_label4;
27 | protected Label statistics_label3;
28 | protected Label statistics_label5;
29 | protected CssLayout dashboard_item26;
30 | protected Label dashboard_item_header2;
31 | protected Label statistics_label6;
32 | protected Label statistics_label7;
33 | protected Label statistics_label8;
34 | protected Label statistics_label9;
35 | protected Label statistics_label10;
36 | protected CssLayout dashboard_item27;
37 | protected Label dashboard_item_header3;
38 | protected Label statistics_label18;
39 | protected Label statistics_label12;
40 | protected Label statistics_label16;
41 | protected Label statistics_label17;
42 | protected Label statistics_label19;
43 |
44 | public DashboardViewDesign() {
45 | Design.read(this);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/MainLayout.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import java.util.Iterator;
4 |
5 | import com.vaadin.navigator.Navigator;
6 | import com.vaadin.navigator.View;
7 | import com.vaadin.navigator.ViewDisplay;
8 | import com.vaadin.ui.Button;
9 | import com.vaadin.ui.Component;
10 | import com.vaadin.ui.UI;
11 |
12 | public class MainLayout extends MainLayoutDesign implements ViewDisplay {
13 |
14 | private static final String STYLE_SELECTED = "selected";
15 | private Navigator navigator;
16 |
17 | public MainLayout() {
18 | navigator = new Navigator(UI.getCurrent(), (ViewDisplay) this);
19 | addNavigatorView(DashboardView.VIEW_NAME, DashboardView.class,
20 | menuButton1);
21 | addNavigatorView(OrderView.VIEW_NAME, OrderView.class, menuButton2);
22 | addNavigatorView(AboutView.VIEW_NAME, AboutView.class, menuButton3);
23 | if (navigator.getState().isEmpty()) {
24 | navigator.navigateTo(DashboardView.VIEW_NAME);
25 | }
26 | }
27 |
28 | private void doNavigate(String viewName) {
29 | getUI().getNavigator().navigateTo(viewName);
30 | }
31 |
32 | private void addNavigatorView(String viewName,
33 | Class extends View> viewClass, Button menuButton) {
34 | navigator.addView(viewName, viewClass);
35 | menuButton.addClickListener(event -> doNavigate(viewName));
36 | menuButton.setData(viewClass.getName());
37 | }
38 |
39 | private void adjustStyleByData(Component component, Object data) {
40 | if (component instanceof Button) {
41 | if (data != null && data.equals(((Button) component).getData())) {
42 | component.addStyleName(STYLE_SELECTED);
43 | } else {
44 | component.removeStyleName(STYLE_SELECTED);
45 | }
46 | }
47 | }
48 |
49 | @Override
50 | public void showView(View view) {
51 | if (view instanceof Component) {
52 | scroll_panel.setContent((Component) view);
53 | Iterator it = side_bar.iterator();
54 | while (it.hasNext()) {
55 | adjustStyleByData(it.next(), view.getClass().getName());
56 | }
57 | } else {
58 | throw new IllegalArgumentException("View is not a Component");
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/MainLayoutDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.CssLayout;
6 | import com.vaadin.ui.HorizontalLayout;
7 | import com.vaadin.ui.Label;
8 | import com.vaadin.ui.NativeButton;
9 | import com.vaadin.ui.Panel;
10 | import com.vaadin.ui.TextField;
11 | import com.vaadin.ui.VerticalLayout;
12 | import com.vaadin.ui.declarative.Design;
13 |
14 | /**
15 | * !! DO NOT EDIT THIS FILE !!
16 | *
17 | * This class is generated by Vaadin Designer and will be overwritten.
18 | *
19 | * Please make a subclass with logic and additional interfaces as needed,
20 | * e.g class LoginView extends LoginDesign implements View { … }
21 | */
22 | @DesignRoot
23 | @AutoGenerated
24 | @SuppressWarnings("serial")
25 | public class MainLayoutDesign extends VerticalLayout {
26 | protected CssLayout header_bar;
27 | protected NativeButton user_menu;
28 | protected Label user_name_label;
29 | protected TextField search_field;
30 | protected HorizontalLayout main_area;
31 | protected CssLayout side_bar;
32 | protected NativeButton menuButton1;
33 | protected NativeButton menuButton2;
34 | protected NativeButton menuButton3;
35 | protected Panel scroll_panel;
36 |
37 | public MainLayoutDesign() {
38 | Design.read(this);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/MyUI.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import javax.servlet.annotation.WebServlet;
4 |
5 | import com.vaadin.annotations.Theme;
6 | import com.vaadin.annotations.VaadinServletConfiguration;
7 | import com.vaadin.server.VaadinRequest;
8 | import com.vaadin.server.VaadinServlet;
9 | import com.vaadin.ui.UI;
10 |
11 | /**
12 | *
13 | */
14 | @Theme("mytheme")
15 | public class MyUI extends UI {
16 |
17 | @Override
18 | protected void init(VaadinRequest vaadinRequest) {
19 | setContent(new MainLayout());
20 | }
21 |
22 | @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
23 | @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
24 | public static class MyUIServlet extends VaadinServlet {
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/OrderView.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.navigator.View;
4 | import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
5 |
6 | public class OrderView extends OrderViewDesign implements View {
7 |
8 | public static final String VIEW_NAME = "order";
9 |
10 | @Override
11 | public void enter(ViewChangeEvent event) {
12 | // TODO Auto-generated method stub
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/betternavi/src/main/java/org/vaadin/example/OrderViewDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.CssLayout;
6 | import com.vaadin.ui.FormLayout;
7 | import com.vaadin.ui.HorizontalLayout;
8 | import com.vaadin.ui.Label;
9 | import com.vaadin.ui.NativeButton;
10 | import com.vaadin.ui.TextField;
11 | import com.vaadin.ui.declarative.Design;
12 |
13 | /**
14 | * !! DO NOT EDIT THIS FILE !!
15 | *
16 | * This class is generated by Vaadin Designer and will be overwritten.
17 | *
18 | * Please make a subclass with logic and additional interfaces as needed,
19 | * e.g class LoginView extends LoginDesign implements View { … }
20 | */
21 | @DesignRoot
22 | @AutoGenerated
23 | @SuppressWarnings("serial")
24 | public class OrderViewDesign extends CssLayout {
25 | protected Label billing_header_label;
26 | protected CssLayout main_content_wrapper;
27 | protected FormLayout billing_form;
28 | protected Label email_header_label;
29 | protected TextField email_field;
30 | protected Label address_label;
31 | protected HorizontalLayout name_wrapper;
32 | protected TextField firstname_field;
33 | protected TextField lastname_field;
34 | protected TextField address_field;
35 | protected TextField company_field;
36 | protected TextField city_field;
37 | protected HorizontalLayout name_wrapper2;
38 | protected TextField state_field;
39 | protected TextField zip_field;
40 | protected TextField country_field;
41 | protected TextField phone_field;
42 | protected FormLayout order_summary_layout;
43 | protected Label order_heading;
44 | protected CssLayout order_item;
45 | protected Label order_label;
46 | protected NativeButton cancel_order_button;
47 | protected Label tax_sum;
48 | protected Label total_sum;
49 |
50 | public OrderViewDesign() {
51 | Design.read(this);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/betternavi/src/main/resources/org/vaadin/example/AboutViewDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | About view
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/betternavi/src/main/resources/org/vaadin/example/DashboardViewDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
85 |
86 |
87 |
88 |
89 |
90 | General Vaadin Statistics
91 |
92 |
93 |
94 | Monthly Vaadin Statistics
95 |
96 |
97 | Vaadin Addon Downloads
98 | 232,392
99 |
100 |
101 | Vaadin Designer Downloads
102 | 114,036
103 |
104 |
105 | Vaadin Charts Downloads
106 | 151,663
107 |
108 |
109 | Vaadin TestBench Downloads
110 | 96,691
111 |
112 |
113 | Vaadin Homepage Visits
114 | 471,484
115 |
116 |
117 |
118 |
119 | Vaadin Release Info
120 |
121 |
122 | Current Vaadin Version
123 | 7.5.4
124 |
125 |
126 | Open Framework Tickets
127 | 36
128 |
129 |
130 | Open Designer Tickets
131 | 12
132 |
133 |
134 | Open Vaadin Charts Tickets
135 | 23
136 |
137 |
138 | Next Vaadin Framework release
139 | 10.10.2010
140 |
141 |
142 |
143 |
144 | Upcoming Vaadin Trainings
145 |
146 |
147 | Turku, Finland
148 | Sep 9, 2015
149 |
150 |
151 | Berlin, Germany
152 | Sep 14, 2015
153 |
154 |
155 | San Jose, U.S
156 | Sep 21, 2015
157 |
158 |
159 | München, Germany
160 | Oct 5, 2015
161 |
162 |
163 | Rome, Italy
164 | Oct 19, 2015
165 |
166 |
167 |
168 |
169 |
--------------------------------------------------------------------------------
/betternavi/src/main/resources/org/vaadin/example/MainLayoutDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 | John Smith
195 |
196 |
197 |
198 |
199 |
200 |
201 | Dashboard
202 |
203 |
204 | Order
205 |
206 |
207 | About
208 |
209 |
210 |
211 |
212 |
213 |
214 |
--------------------------------------------------------------------------------
/betternavi/src/main/resources/org/vaadin/example/OrderViewDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
145 |
146 |
147 |
148 |
149 |
150 | Billing Information
151 |
152 |
153 |
154 |
155 | Please enter your email address
156 |
157 |
158 |
159 | Please enter your billing address
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 | Order Summary
178 |
179 |
180 |
181 | Vaadin Designer License
182 |
$ 389.00
183 |
184 |
185 |
186 |
187 |
188 | Tax :
189 | $0.00
190 |
191 |
192 | Total :
193 | $ 389.00
194 |
195 |
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/betternavi/src/main/webapp/VAADIN/themes/mytheme/addons.scss:
--------------------------------------------------------------------------------
1 | /* This file is automatically managed and will be overwritten from time to time. */
2 | /* Do not manually edit this file. */
3 |
4 | /* Import and include this mixin into your project theme to include the addon themes */
5 | @mixin addons {
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/betternavi/src/main/webapp/VAADIN/themes/mytheme/designs.scss:
--------------------------------------------------------------------------------
1 | // Styles imported from MainLayoutDesign.html
2 | $v-font-size: 16px;
3 | $v-font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
4 | $v-border-radius: 0;
5 | $v-textfield-bevel: false;
6 | $v-textfield-shadow: false;
7 | $v-shadow: false;
8 | $v-bevel: false;
9 | $v-gradient: false;
10 | $v-textfield-border: 0;
11 | .root-layout.navigation-template-vaadin {
12 | $root-background-color: #ffffff;
13 | $main-color: #5AAAFA;
14 | $menu-color: #5AAAFA;
15 | $header-label-font-size: 1.618em;
16 | background-color: $root-background-color;
17 |
18 | .v-nativebutton{
19 | background: none;
20 | border: none;
21 |
22 | &:hover{
23 | cursor: pointer;
24 | }
25 | }
26 |
27 | .scroll-panel{
28 | background-color: $root-background-color;
29 | border: none;
30 | border-radius: 0;
31 | }
32 |
33 | .header-bar{
34 | background-color: $menu-color;
35 | padding: 0px 15px 0 15px;
36 | vertical-align: middle;
37 | height: 65px;
38 |
39 | > * {
40 | color: #FFFFFF;
41 | float: right;
42 | padding: 0;
43 | line-height: 20px;
44 | margin-left: 15px;
45 |
46 | /** Vertically center everything **/
47 | position: relative;
48 | top: 50%;
49 | -webkit-transform: translateY(-50%);
50 | -ms-transform: translateY(-50%);
51 | transform: translateY(-50%);
52 | }
53 |
54 | > .search-field{
55 | background: none;
56 | border-bottom: solid 2px #fff;
57 | padding-left: 5px;
58 |
59 | &.v-textfield-prompt{
60 | color: #ffffff;
61 | font-style: italic;
62 | }
63 | }
64 |
65 | }
66 |
67 | .side-bar {
68 |
69 | background-color: #000;
70 | width: 100px;
71 |
72 | > .menu-button{
73 | position: relative;
74 | color: $main-color;
75 | height: 90px;
76 |
77 | &.selected{
78 | background-color: $root-background-color;
79 |
80 | .v-nativebutton-caption {
81 | color: #1A1314;
82 | }
83 | }
84 |
85 | .v-nativebutton-caption{
86 | font-size: .7em;
87 | color: #E9E0E0;
88 | text-transform: uppercase;
89 | position: absolute;
90 | bottom: 8px;
91 | text-align: center;
92 | left: 0;
93 | right: 0;
94 | margin-left: auto;
95 | margin-right: auto;
96 | }
97 |
98 | .v-icon{
99 | position: absolute;
100 | font-size: 35px;
101 | margin-left: auto;
102 | margin-right: auto;
103 | top: 10px;
104 | left: 0;
105 | right: 0;
106 | }
107 | }
108 | }
109 |
110 | .header-label{
111 | font-size: $header-label-font-size;
112 | width: 100%;
113 | margin-bottom: 20px;
114 | color: #000000;
115 | border-bottom: 3px solid #D0C7C7;
116 | }
117 |
118 | .header-label-small{
119 | width: 100%;
120 | color: $main-color;
121 | text-transform: uppercase;
122 | border-bottom: 2px solid #D0C7C7;
123 | }
124 |
125 | .dashboard-layout{
126 | padding: 60px 60px 0 60px;
127 | }
128 |
129 | .dashboard-item{
130 | background-color: #f6f3f3;
131 | border: 1px solid white;
132 | margin: 0 30px 30px 0px;
133 | padding: 15px;
134 |
135 | > .statistics-label{
136 | margin-top: 15px;
137 |
138 | .statistics-value{
139 | float: right;
140 | font-weight: bold;
141 | }
142 | }
143 | }
144 |
145 | &[width-range~="321px-768px"]{
146 | .dashboard-layout{
147 | padding: 10px;
148 | }
149 |
150 | .dashboard-item{
151 | width: 100% !important;
152 | min-width: 321px;
153 | margin: 0;
154 | }
155 |
156 | .side-bar{
157 | width: 60px;
158 |
159 | > .menu-button{
160 |
161 | height: 50px;
162 |
163 | > .v-nativebutton-caption{
164 | visibility: hidden;
165 | }
166 |
167 | > .v-icon{
168 | top: 0;
169 | }
170 | }
171 | }
172 |
173 | .header-bar{
174 | height: 45px;
175 | padding: 2px;
176 | }
177 | }
178 | }
179 |
180 | .navigation-template-vaadin[width-range~="321px-768px"]{
181 | visibility: visible;
182 | }
183 |
184 | // Styles imported from DashboardViewDesign.html
185 | $v-font-size: 16px;
186 | $v-font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
187 | $v-border-radius: 0;
188 | $v-textfield-bevel: false;
189 | $v-textfield-shadow: false;
190 | $v-shadow: false;
191 | $v-bevel: false;
192 | $v-gradient: false;
193 | $v-textfield-border: 0;
194 | .root-layout.dashboard-view-template-vaadin {
195 | $root-background-color: #ffffff;
196 | $main-color: #5AAAFA;
197 | $menu-color: #5AAAFA;
198 | $header-label-font-size: 1.618em;
199 | background-color: $root-background-color;
200 | padding: 60px;
201 |
202 | .v-nativebutton{
203 | background: none;
204 | border: none;
205 |
206 | &:hover{
207 | cursor: pointer;
208 | }
209 | }
210 |
211 | .header-label{
212 | font-size: $header-label-font-size;
213 | width: 100%;
214 | margin-bottom: 20px;
215 | color: #000000;
216 | border-bottom: 3px solid #D0C7C7;
217 | }
218 |
219 | .header-label-small{
220 | width: 100%;
221 | color: $main-color;
222 | text-transform: uppercase;
223 | border-bottom: 2px solid #D0C7C7;
224 | }
225 |
226 | .dashboard-layout{
227 | padding: 60px 60px 0 60px;
228 | }
229 |
230 | .dashboard-item{
231 | background-color: #f6f3f3;
232 | border: 1px solid white;
233 | margin: 0 30px 30px 0px;
234 | padding: 15px;
235 |
236 | > .statistics-label{
237 | margin-top: 15px;
238 |
239 | .statistics-value{
240 | float: right;
241 | font-weight: bold;
242 | }
243 | }
244 | }
245 |
246 | &[width-range~="321px-768px"]{
247 | padding: 10px;
248 |
249 | .dashboard-layout{
250 | padding: 10px;
251 | }
252 |
253 | .dashboard-item{
254 | width: 100% !important;
255 | min-width: 321px;
256 | margin: 0;
257 | }
258 | }
259 | }
260 |
261 | .dashboard-view-template-vaadin[width-range~="321px-768px"]{
262 | visibility: visible;
263 | }
264 |
265 | // Styles imported from OrderViewDesign.html
266 | $v-font-size: 16px;
267 | $v-font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
268 | $v-border-radius: 0;
269 | $v-textfield-bevel: false;
270 | $v-textfield-shadow: false;
271 | $v-shadow: false;
272 | $v-bevel: false;
273 | $v-gradient: false;
274 | $v-textfield-border: 0;
275 | .root-layout.form-template-vaadin {
276 | $root-background-color: #ffffff;
277 | $header-bar-height: 100px;
278 | $main-color: #5AAAFA;
279 | $menu-color: #5AAAFA;
280 | $header-label-font-size: 1.618em;
281 | background-color: $root-background-color;
282 | padding: 60px;
283 |
284 | .v-nativebutton{
285 | background: none;
286 | border: none;
287 |
288 | &:hover{
289 | cursor: pointer;
290 | }
291 | }
292 |
293 | .header-label{
294 | font-size: $header-label-font-size;
295 | width: 100%;
296 | margin-bottom: 20px;
297 | color: #000000;
298 | border-bottom: 3px solid #D0C7C7;
299 | }
300 |
301 | .header-label-small{
302 | width: 100%;
303 | color: $main-color;
304 | text-transform: uppercase;
305 | border-bottom: 2px solid #D0C7C7;
306 | }
307 |
308 | .billing-formlayout {
309 |
310 | background: #f6f3f3;
311 | border: solid 1px #ffffff;
312 | margin: 0 30px 0 0px;
313 | float: left;
314 | padding: 20px;
315 | width: 100%;
316 | max-width: 722px;
317 |
318 | .form-textfield{
319 | background: none;
320 | border-bottom: 2px solid #D0C7C7;
321 | }
322 |
323 | .email-field{
324 | min-width: 250px;
325 | }
326 | }
327 |
328 | .order-summary-layout{
329 | background: #8CD211;
330 | border: #ffffff;
331 | float: right;
332 | padding: 20px;
333 |
334 | .header-label-small {
335 | color: #ffffff;
336 | border-bottom-color: #C8F08F;
337 | }
338 |
339 | .v-label{
340 | color: #ffffff;
341 | }
342 |
343 | .cancel-order-button{
344 | background: none;
345 | border: none;
346 | position: relative;
347 | margin-left: 15px;
348 | margin-top: 10px;
349 | padding: 0;
350 | float: right;
351 |
352 | .v-icon{
353 | font-size: 25px;
354 | width: 25px;
355 | height: 25px;
356 | line-height: 25px;
357 | color: #4B8400;
358 | }
359 | }
360 |
361 | .order-sum{
362 | position: absolute;
363 | left: 170px;
364 | text-align: right;
365 | width: 150px;
366 | }
367 |
368 | .total-sum{
369 | border-top: solid 2px #C8F08F;
370 | color: #C8F08F !important;
371 | font-size: 2em;
372 | &:first-letter {
373 | font-weight: 400;
374 | }
375 | }
376 | }
377 |
378 | &[width-range~="321px-768px"]{
379 | padding: 10px;
380 |
381 | .billing-formlayout{
382 | margin: 15px 0 0 0;
383 | width: 100% !important;
384 | }
385 |
386 | .order-summary-layout{
387 | margin: 15px 0 0 0;
388 | }
389 | }
390 |
391 | &[width-range~="769px-1426px"]{
392 | .billing-formlayout{
393 | margin-bottom: 30px;
394 | }
395 |
396 | .order-summary-layout{
397 | float: left;
398 | }
399 | }
400 | }
401 |
402 | .form-template-vaadin[width-range~="321px-768px"],
403 | .form-template-vaadin[width-range~="769px-1426px"]{
404 | visibility: visible;
405 | }
406 |
407 |
--------------------------------------------------------------------------------
/betternavi/src/main/webapp/VAADIN/themes/mytheme/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaadin/designer-tutorials/5a810e6e5c3cb78f4396405c909491dcd8d84533/betternavi/src/main/webapp/VAADIN/themes/mytheme/favicon.ico
--------------------------------------------------------------------------------
/betternavi/src/main/webapp/VAADIN/themes/mytheme/mytheme.scss:
--------------------------------------------------------------------------------
1 | // Global variable overrides. Must be declared before importing Valo.
2 |
3 | // Defines the plaintext font size, weight and family. Font size affects general component sizing.
4 | //$v-font-size: 16px;
5 | //$v-font-weight: 300;
6 | //$v-font-family: "Open Sans", sans-serif;
7 |
8 | // Defines the border used by all components.
9 | //$v-border: 1px solid (v-shade 0.7);
10 | //$v-border-radius: 4px;
11 |
12 | // Affects the color of some component elements, e.g Button, Panel title, etc
13 | //$v-background-color: hsl(210, 0%, 98%);
14 | // Affects the color of content areas, e.g Panel and Window content, TextField input etc
15 | //$v-app-background-color: $v-background-color;
16 |
17 | // Affects the visual appearance of all components
18 | //$v-gradient: v-linear 8%;
19 | //$v-bevel-depth: 30%;
20 | //$v-shadow-opacity: 5%;
21 |
22 | // Defines colors for indicating status (focus, success, failure)
23 | //$v-focus-color: valo-focus-color(); // Calculates a suitable color automatically
24 | //$v-friendly-color: #2c9720;
25 | //$v-error-indicator-color: #ed473b;
26 |
27 | // For more information, see: https://vaadin.com/book/-/page/themes.valo.html
28 | // Example variants can be copy/pasted from https://vaadin.com/wiki/-/wiki/Main/Valo+Examples
29 |
30 | @import "../valo/valo.scss";
31 |
32 | @mixin mytheme {
33 | @include valo;
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/betternavi/src/main/webapp/VAADIN/themes/mytheme/styles.scss:
--------------------------------------------------------------------------------
1 | @import "designs.scss";
2 | @import "mytheme.scss";
3 | @import "addons.scss";
4 |
5 | // This file prefixes all rules with the theme name to avoid causing conflicts with other themes.
6 | // The actual styles should be defined in mytheme.scss
7 |
8 | .mytheme {
9 | @include addons;
10 | @include mytheme;
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/README.adoc:
--------------------------------------------------------------------------------
1 | `This tutorial is written using Java 8, Vaadin 7.7.3 and Designer 1.2`
2 |
3 | = Connecting your designs to data
4 |
5 | In the following tutorial I’ll show you how you can connect your Vaadin Designer based views to a real database backend
6 | with only a few steps. The sample code in this tutorial is based on a previous link:https://github.com/vaadin/designer-tutorials/tree/master/emailclient-tutorial[one] where I demonstrated building a design
7 | of an email client. Now we’ll add fetching message entities from a real database and writing some modifications
8 | back to the database. The data access is done through a stateless EJB accessing a JPA repository.
9 | The repository is implemented using Apache link:https://deltaspike.apache.org/documentation/[DeltaSpike].
10 |
11 | image::https://raw.githubusercontent.com/vaadin/designer-tutorials/develop/emailclient-tutorial-data/tutorial-images/email-client-with-data.png[Screenshot]
12 |
13 |
14 | I assume you have installed link:https://vaadin.com/designer[Vaadin Designer] and you are using Eclipse. In this tutorial I used
15 |
16 | - Java 8 and Java EE 7 Web Specification APIs
17 | - Eclipse Neon
18 | - Vaadin 7.7.3
19 | - Designer 1.2.0
20 | - Java EE 7 container e.g. Wildfly 9.
21 |
22 | == For the impatient one
23 | If you just want to see the end result and the completed code and don’t feel like doing it yourself, you can get the end result from link:https://github.com/vaadin/designer-tutorials/tree/master/emailclient-tutorial-data[here]. However, I would recommend going through all the steps yourself.
24 |
25 | `git clone --depth 1 \https://github.com/vaadin/designer-tutorials.git`
26 |
27 | == Quick start
28 | The key point in this tutorial is to show you how to connect your designs to data, and as I want to keep this tutorial as short as possible, I’ve implemented the data part and the UI designs for you. Just fork or clone link:https://github.com/vaadin/designer-tutorials/tree/emailclient-tutorial-data-start/emailclient-tutorial-data[this] repository and you are almost good to go.
29 |
30 | `git clone --depth 1 --no-single-branch \https://github.com/vaadin/designer-tutorials.git --branch emailclient-tutorial-data-start`
31 |
32 | What you need, in addition to the code, is: *Eclipse (Luna or newer)*, *Vaadin Designer*, and *Java EE 7* compatible container (e.g. Wildfly 9). The project is a Maven project and has been created using `vaadin-archetype-application`. The project pom has all the necessary dependencies like `deltaspike-data-module-api`, `javaee-web-api`, etc. The project also uses a Vaadin CDI add-on to allow using our UI components as CDI managed beans and to easily inject the data source.
33 |
34 | Import the project into Eclipse using `File > Import... > Existing Maven Projects`. Select the emailclient-tutorial-data directory as the root directory of your project.
35 |
36 | If you get stuck with the tutorial or you have some other questions, you can post them in this forum thread https://vaadin.com/forum#!/thread/11628010.
37 |
38 | == The backend
39 | *The backend is already done in the project, so you don’t have to do the following steps. This is here just for your information.*
40 |
41 | A simple and safe way to do the data access is through a stateless EJB facade accessing repositories. With the stateless bean you get the thread-safety and instance pooling by the container. To the Facade you can inject your repository. Using an EJB means that the transaction boundary should be in the EJB level and not in the JPA level. For that reason you need to put `apache-deltaspike.properties` file in `src/main/resources/META-INF` and define the transcation strategy to be container managed JTA transactions.
42 |
43 | `globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy`
44 |
45 | Another necessary step is to expose the EntityManager to the DeltaSpike Data module. This is done via CDI producer.
46 |
47 | [source, java]
48 | ----
49 | public class CdiConfig {
50 |
51 | @Produces
52 | @Dependent
53 | @PersistenceContext(unitName = "tutorialdb")
54 | public EntityManager entityManager;
55 | }
56 | ----
57 |
58 | === Entity
59 | In this simple example you only need a single JPA entity, which represents the listed message. An AbstractEntity here is a base class containing version and id fields.
60 |
61 | [source, java]
62 | ----
63 | @Entity
64 | public class Message extends AbstractEntity {
65 |
66 | private boolean read;
67 | private boolean trashed;
68 | private String sender;
69 | @Enumerated(EnumType.STRING)
70 | private Flag flag;
71 |
72 | public enum Flag {
73 | FLAG_STAR
74 | }
75 |
76 | @Temporal(TemporalType.TIMESTAMP)
77 | private Date sent;
78 | private String subject;
79 |
80 | @Lob
81 | private String body;
82 |
83 | // …
84 | // getters and setters skipped for brevity
85 | }
86 | ----
87 |
88 | === Repository
89 | With DeltaSpike, defining a repository is very simple. In this sample I just extended EntityRepository and added the needed methods. The EntityRepository has already the basic CRUD methods, and I only needed to add my custom methods there. The methods use DeltaSpike’s automatically generated query implementations by naming conventions.
90 |
91 | [source, java]
92 | ----
93 | @Repository
94 | public interface MessageRepository extends EntityRepository {
95 | QueryResult findByRead(boolean read);
96 |
97 | QueryResult findByFlagIsNotNullAndRead(boolean read);
98 |
99 | List findByFlagIsNotNullAndTrashed(boolean trashed);
100 | }
101 | ----
102 |
103 | === Facade
104 | A simple stateless EJB facade accessing repositories. Inject your repository to the facade.
105 |
106 | [source, java]
107 | ----
108 | @Stateless
109 | public class MessageFacade {
110 |
111 | @Inject
112 | private MessageRepository repository;
113 |
114 | // …
115 | // business logic and data operations go here
116 | }
117 | ----
118 |
119 | == UI views and navigation
120 | The starting point project already contains a bunch of UI logic and a couple of Vaadin Designer design files e.g. the folder navigation works both by clicking from the UI and navigating using a URL. There is also a logic to updating the unread messages count in the menu item badges on the left side. This implementation is out of scope of the tutorial and we can focus on the list of messages in the FolderView, but I still want to describe a bit what is happening in the UI.
121 |
122 | MyUI is annotated with `@CDIUI` coming from Vaadin CDI. It sets up a Navigator and uses CDIViewProvider with navigator. CDViewProvider understands `@CDIView` annotated views. MyUI also defines a ServletContextListener to initialize test data.
123 |
124 | MainLayout is extending MainLayoutDesign which is the content of our UI, having a menu on the left side and a toolbar on the top. The lower right area is the view content area for Navigator. MainLayout has a bunch of boiler-plate code to manage the button selected style, click events, formatting Valo themed menu items etc. You should take a look at it just maybe out of curiosity, but it’s not necessary for this tutorial.
125 |
126 | FolderView is simply extending VerticalLayout and implements com.vaadin.navigator.View. It is annotated with `@CDIView` and uses view parameters to communicate which folder is the currently selected one and based on that parameter we can fetch the appropriate messages from the backend and display them. For each of the folders, we are using the same view class just because the content of the views is the same apart from the dynamic list of messages.
127 |
128 | MessageModifiedEvent is a CDI event we use later on in the tutorial.
129 |
130 | It’s worth mentioning that the application uses a custom theme. There’s not much style definitions in the `mytheme.scss`, but some sizing, alignment, colors, and such. The style names needed for this tutorial are available in link:https://github.com/vaadin/designer-tutorials/blob/master/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/themes/mytheme/MyTheme.java[`MyTheme.java`].
131 |
132 | MessageDesign is the still a bit static message UI component you should use in message listing.
133 |
134 | == Let’s get coding!
135 | Let’s add some functionality to this currently a somewhat dumb application. When the user selects a message folder, the list of messages should be shown. Also, when the user clicks a message that is marked as unread it should be marked as read. The message should display the unread status by showing a colored indicator.
136 |
137 | === Show list of messages
138 | Message facade has methods to provide list messages when a folder is selected. You should fetch the list of messages in FolderView#enter() and then replace the static content of MessageDesign with real data and finally populate the FolderView UI with the fetched messages.
139 |
140 | - Start by extending MessageDesign and name it MessageComponent.
141 | - Add a constructor to create it based on Message entity
142 | - Set the values of appropriate UI components from message properties
143 |
144 | [source, java]
145 | ----
146 | public class MessageComponent extends MessageDesign {
147 | public MessageComponent(Message message) {
148 | senderLabel.setValue(message.getSender());
149 | messageLabel.setCaption(message.getSubject());
150 | messageLabel.setValue(message.getBody());
151 | }
152 | }
153 | ----
154 |
155 | - In FolderView there is a method named refreshFolders, which is called in FolderView#enter. Fetch messages from MessageFacade and populate the FolderView VerticalLayout.
156 |
157 | [source, java]
158 | ----
159 | @Override
160 | public void enter(ViewChangeEvent event) {
161 | String folder = event.getParameters();
162 | refreshFolder(folder);
163 | }
164 |
165 | private void refreshFolder(String folder) {
166 | removeAllComponents();
167 | messageFacade.getFolderMessages(folder).stream()
168 | .map(MessageComponent::new).forEach(this::addComponent);
169 | }
170 | ----
171 |
172 | Ok, so now the message listing is working, but the message unread indicator is not colored for the unread messages
173 | and all the messages have the same indicator icon. Let’s fix that.
174 |
175 | - Flagged messages get a star indicator and unread messages get a circle indicator.
176 | - Indicators of unread messages get a color.
177 | - Read non-flagged messages don’t have an indicator at all.
178 |
179 | [source, java]
180 | ----
181 | public void setIndicator(boolean read, Flag flag) {
182 | MyTheme.MESSAGE_STYLES.forEach(indicatorButton::removeStyleName);
183 | indicatorButton.setIcon(null);
184 | if (flag == Flag.FLAG_STAR) {
185 | indicatorButton.setIcon(FontAwesome.STAR);
186 | if (!read) {
187 | indicatorButton.addStyleName(MyTheme.INDICATOR_STAR_RED);
188 | }
189 | } else if (!read) {
190 | indicatorButton.setIcon(FontAwesome.CIRCLE);
191 | indicatorButton.addStyleName(MyTheme.INDICATOR_CIRCLE);
192 | }
193 | }
194 | ----
195 |
196 | - Call setIndicator in MessageComponent constructor +
197 | `setIndicator(message.isRead(), message.getFlag())`;
198 |
199 | === Marking messages as read
200 | .Let’s add a support for marking messages as read. This requires you to:
201 | - Handle mouse click events in the MessageComponent
202 | - Propagate the click event from the message to the FolderView.
203 | - In the FolderView set the message as read and save the modifications to the database through MessageFacade.
204 | - After the modification transaction is complete, propagate the change to the menu component to refresh
205 | the folder badges (now the custom CDI event MessageModifiedEvent comes into play).
206 |
207 | .Let’s go through this step-by-step:
208 | - To handle a click event in MessageComponent you can use LayoutClickListener.
209 | - From there the click event can be propagated in many ways, but I like Java 8 so let’s
210 | define a functional interface MessageClickListener.
211 |
212 | [source, java]
213 | ----
214 | @FunctionalInterface
215 | interface MessageClickListener {
216 | public void messageClick(MessageComponent source, Message message);
217 | }
218 | ----
219 |
220 | Add MessageClickListener parameter to the constructor and call the listener in LayoutClickListener.
221 |
222 | [source, java]
223 | ----
224 | public MessageComponent(Message message,
225 | MessageClickListener clickListener) {
226 | // …
227 | addLayoutClickListener(
228 | event -> clickListener.messageClick(this, message));
229 | }
230 | ----
231 |
232 | - Fix the FolderView message population to include this new MessageClickListener. So instead of
233 | `MessageComponent::new` call `this::createFromEntity`.
234 |
235 | [source, java]
236 | ----
237 | private void refreshFolder(String folder) {
238 | removeAllComponents();
239 | messageFacade.getFolderMessages(folder).stream()
240 | .map(this::createFromEntity).forEach(this::addComponent);
241 | }
242 |
243 | private MessageComponent createFromEntity(Message entity) {
244 | MessageComponent msg = new MessageComponent(entity,
245 | this::onMessageClicked);
246 | return msg;
247 | }
248 |
249 | private void onMessageClicked(MessageComponent source, Message message) {
250 | }
251 | ----
252 |
253 | .Now the FolderView consumes the click event and you can modify the message.
254 | - Set the message as read and save it through MessageFacade.
255 | - Update the message indicator
256 |
257 | [source, java]
258 | ----
259 | private void onMessageClicked(MessageComponent source, Message message) {
260 | if (!message.isRead()) {
261 | message.setRead(true);
262 | messageFacade.save(message);
263 | source.setIndicator(true, message.getFlag());
264 | }
265 | }
266 | ----
267 |
268 | As an added bonus the message folder badge on the left side menu should update right away so fire a CDI event called
269 | MessageModifiedEvent. MainLayout is already observing that message and waiting eagerly for some updates.
270 | To achieve this I just added @Observes annotated event listener to the MainLayout class.
271 | The event handler then calls MessageFacade and asks for a message count for each of the folders and
272 | maps the results to the menu buttons.
273 | Check it out from link:https://github.com/vaadin/designer-tutorials/blob/master/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/MainLayout.java[MainLayout.java] if you are interested.
274 |
275 | The event is already injected into FolderView so just call: +
276 | `messageSelectEvent.fire(new MessageModifiedEvent(message));`
277 |
278 | == What next?
279 | If you got this far and everything is working just the way you wanted, great job! We used DeltaSpike repositories
280 | and Java EE container features here, but these same principles can be applied to Spring Data, plain JPA
281 | or basically to any data source.
282 |
283 | I need to mention one important thing: If you were to use this same approach in any larger data set,
284 | you would have to implement data paging. Here we loaded all items to a layout, but you can imagine what
285 | happens to the server’s memory usage and the browser’s capability to display the items if the data set gets large.
286 | With DeltaSpike paging can be implemented easily using `QueryResult`. After your data source implements paging,
287 | you only need to add UI controls for getting the next/previous page of data.
288 |
289 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.vaadin.example
6 | emailclient-tutorial-data
7 | war
8 | 1.0-SNAPSHOT
9 | emailclient-tutorial-data
10 |
11 |
12 | 3
13 |
14 |
15 |
16 | 7.7.3
17 | ${vaadin.version}
18 | 9.2.3.v20140905
19 | 1.8
20 | 1.8
21 | UTF-8
22 | 1.5.1
23 |
24 | local
25 |
26 |
27 |
28 |
29 | vaadin-addons
30 | https://maven.vaadin.com/vaadin-addons
31 |
32 |
33 |
34 |
35 |
36 |
37 | com.vaadin
38 | vaadin-bom
39 | ${vaadin.version}
40 | pom
41 | import
42 |
43 |
44 |
45 |
46 |
47 |
48 | javax.servlet
49 | javax.servlet-api
50 | 3.0.1
51 | provided
52 |
53 |
54 | javax
55 | javaee-web-api
56 | 7.0
57 | provided
58 |
59 |
60 | org.apache.deltaspike.modules
61 | deltaspike-data-module-api
62 | ${deltaspike.version}
63 | compile
64 |
65 |
66 | org.apache.deltaspike.modules
67 | deltaspike-data-module-impl
68 | ${deltaspike.version}
69 | runtime
70 |
71 |
72 | com.vaadin
73 | vaadin-server
74 |
75 |
76 | com.vaadin
77 | vaadin-push
78 |
79 |
80 | com.vaadin
81 | vaadin-client-compiled
82 |
83 |
84 | com.vaadin
85 | vaadin-themes
86 |
87 |
88 | com.vaadin
89 | vaadin-cdi
90 | 1.0.3
91 |
92 |
93 |
94 |
95 |
96 |
97 | org.apache.maven.plugins
98 | maven-compiler-plugin
99 | 3.0
100 |
101 | ${project.encoding}
102 | ${project.source.version}
103 | ${project.target.version}
104 |
105 |
106 |
107 | org.apache.maven.plugins
108 | maven-resources-plugin
109 | 2.6
110 |
111 | ${project.encoding}
112 |
113 |
114 |
115 | org.apache.maven.plugins
116 | maven-war-plugin
117 | 2.3
118 |
119 | false
120 |
121 | WEB-INF/classes/VAADIN/gwt-unitCache/**,
122 | WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**
123 |
124 |
125 |
126 | com.vaadin
127 | vaadin-maven-plugin
128 | ${vaadin.plugin.version}
129 |
130 | -Xmx512M -Xss1024k
131 | ${basedir}/target/classes/VAADIN/widgetsets
132 | false
133 | false
134 |
135 | true
136 |
137 |
138 |
139 |
140 | update-theme
141 | update-widgetset
142 | compile
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 | org.apache.maven.plugins
151 | maven-source-plugin
152 | 2.4
153 |
154 |
155 | org.apache.maven.plugins
156 | maven-clean-plugin
157 | 2.6.1
158 |
159 |
160 |
161 |
162 | src/main/webapp/VAADIN/themes
163 |
164 | **/styles.css
165 | **/styles.scss.cache
166 |
167 |
168 |
169 |
170 |
171 |
172 |
174 |
175 | org.eclipse.jetty
176 | jetty-maven-plugin
177 | ${jetty.plugin.version}
178 |
179 | 2
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 | vaadin-prerelease
189 |
190 | false
191 |
192 |
193 |
194 |
195 | vaadin-prereleases
196 | https://maven.vaadin.com/vaadin-prereleases
197 |
198 |
199 | vaadin-snapshots
200 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/
201 |
202 | false
203 |
204 |
205 | true
206 |
207 |
208 |
209 |
210 |
211 | vaadin-prereleases
212 | https://maven.vaadin.com/vaadin-prereleases
213 |
214 |
215 | vaadin-snapshots
216 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/
217 |
218 | false
219 |
220 |
221 | true
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/backend/AbstractEntity.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.backend;
2 |
3 | import java.io.Serializable;
4 |
5 | import javax.persistence.GeneratedValue;
6 | import javax.persistence.GenerationType;
7 | import javax.persistence.Id;
8 | import javax.persistence.MappedSuperclass;
9 | import javax.persistence.Version;
10 |
11 | @MappedSuperclass
12 | public abstract class AbstractEntity implements Serializable {
13 |
14 | @Id
15 | @GeneratedValue(strategy = GenerationType.AUTO)
16 | private Long id;
17 |
18 | @Version
19 | private int version;
20 |
21 | public Long getId() {
22 | return id;
23 | }
24 |
25 | protected void setId(Long id) {
26 | this.id = id;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/backend/CdiConfig.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.backend;
2 |
3 | import javax.enterprise.context.Dependent;
4 | import javax.enterprise.inject.Produces;
5 | import javax.persistence.EntityManager;
6 | import javax.persistence.PersistenceContext;
7 |
8 | public class CdiConfig {
9 |
10 | @Produces
11 | @Dependent
12 | @PersistenceContext(unitName = "tutorialdb")
13 | public EntityManager entityManager;
14 | }
15 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/backend/DatabaseInitialization.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.backend;
2 |
3 | import java.time.LocalDateTime;
4 | import java.time.ZoneOffset;
5 | import java.util.Date;
6 |
7 | import javax.ejb.Stateless;
8 | import javax.inject.Inject;
9 |
10 | import org.vaadin.example.backend.Message.Flag;
11 |
12 | @Stateless
13 | public class DatabaseInitialization {
14 |
15 | @Inject
16 | private MessageRepository msgRepo;
17 |
18 | public void initDatabaseIfEmpty() {
19 |
20 | if (!msgRepo.findAll().isEmpty()) {
21 | return;
22 | }
23 |
24 | createMessage("Marc Englund", "Vaadin Designer 1.0 has arrived",
25 | LocalDateTime.of(2015, 10, 24, 21, 0),
26 | "We are thrilled to announce the release of Vaadin Designer 1.0 after 6 months of intensive beta testing. "
27 | + "Vaadin Designer is available for all developers, to be installed from Eclipse Marketplace today.",
28 | false, null);
29 | createMessage("Jurka Rahikkala",
30 | "10+1 things to know about Vaadin for job seekers",
31 | LocalDateTime.of(2015, 10, 22, 12, 34),
32 | "We are constantly seeking highly skilled software experts to join the team. The Vaadin team is constantly working on several projects, "
33 | + "ranging from our own products (such as Vaadin Framework, Designer and Elements) to several customer projects around the world "
34 | + "(examples at https://vaadin.com/success-stories). Needless to say, these projects do not get done without the right people.",
35 | true, null);
36 | createMessage("Teemu Pöntelin",
37 | "Building a mobile-first app with Polymer and Vaadin Elements",
38 | LocalDateTime.of(2015, 10, 19, 18, 20),
39 | "As you might have noticed, we at Vaadin have been experimenting with bringing our Grid and Charts components to a new audience by wrapping "
40 | + "them into Polymer elements. Polymer is Google’s project to bring Web Components into developers’ hands and into production.",
41 | true, Flag.FLAG_STAR);
42 | createMessage("Tanja Repo", "Come and meet us at JavaOne 2015",
43 | LocalDateTime.of(2015, 10, 13, 17, 50),
44 | "Once again Vaadin packs up for the upcoming JavaOne 2015 and heads to San Francisco, US. JavaOne is ‘the event’ for Java enthusiasts, "
45 | + "where one can hear the best speakers, get insights into the future of Java, and connect with other members of the Java community.",
46 | false, Flag.FLAG_STAR);
47 | }
48 |
49 | private Message createMessage(String sender, String subject,
50 | LocalDateTime dateTime, String body, boolean isRead, Flag flag) {
51 | Message msg = new Message();
52 | msg.setSender(sender);
53 | msg.setSubject(subject);
54 | msg.setSent(Date.from(dateTime.toInstant(ZoneOffset.UTC)));
55 | msg.setBody(body);
56 | msg.setRead(isRead);
57 | msg.setFlag(flag);
58 | msg.setTrashed(false);
59 | msgRepo.saveAndFlush(msg);
60 | return msg;
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/backend/Message.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.backend;
2 |
3 | import java.util.Date;
4 |
5 | import javax.persistence.Entity;
6 | import javax.persistence.EnumType;
7 | import javax.persistence.Enumerated;
8 | import javax.persistence.Lob;
9 | import javax.persistence.Temporal;
10 | import javax.persistence.TemporalType;
11 |
12 | @Entity
13 | public class Message extends AbstractEntity {
14 |
15 | private boolean read;
16 | private boolean trashed;
17 | private String sender;
18 | @Enumerated(EnumType.STRING)
19 | private Flag flag;
20 |
21 | public enum Flag {
22 | FLAG_STAR
23 | }
24 |
25 | @Temporal(TemporalType.TIMESTAMP)
26 | private Date sent;
27 | private String subject;
28 |
29 | @Lob
30 | private String body;
31 |
32 | public boolean isRead() {
33 | return read;
34 | }
35 |
36 | public void setRead(boolean read) {
37 | this.read = read;
38 | }
39 |
40 | public boolean isTrashed() {
41 | return trashed;
42 | }
43 |
44 | public void setTrashed(boolean trashed) {
45 | this.trashed = trashed;
46 | }
47 |
48 | public Flag getFlag() {
49 | return flag;
50 | }
51 |
52 | public void setFlag(Flag flag) {
53 | this.flag = flag;
54 | }
55 |
56 | public String getSender() {
57 | return sender;
58 | }
59 |
60 | public void setSender(String sender) {
61 | this.sender = sender;
62 | }
63 |
64 | public Date getSent() {
65 | return sent;
66 | }
67 |
68 | public void setSent(Date sent) {
69 | this.sent = sent;
70 | }
71 |
72 | public String getSubject() {
73 | return subject;
74 | }
75 |
76 | public void setSubject(String subject) {
77 | this.subject = subject;
78 | }
79 |
80 | public String getBody() {
81 | return body;
82 | }
83 |
84 | public void setBody(String body) {
85 | this.body = body;
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/backend/MessageFacade.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.backend;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 |
7 | import javax.ejb.Stateless;
8 | import javax.inject.Inject;
9 |
10 | @Stateless
11 | public class MessageFacade {
12 |
13 | public static final String FOLDER_INBOX = "inbox";
14 | public static final String FOLDER_DRAFTS = "drafts";
15 | public static final String FOLDER_SENT = "sent";
16 | public static final String FOLDER_JUNK = "junk";
17 | public static final String FOLDER_TRASH = "trash";
18 | public static final String FOLDER_FLAGGED = "flagged";
19 | public static final List FOLDERS = Arrays.asList(FOLDER_INBOX,
20 | FOLDER_DRAFTS, FOLDER_SENT, FOLDER_JUNK, FOLDER_TRASH,
21 | FOLDER_FLAGGED);
22 |
23 | @Inject
24 | private MessageRepository repository;
25 |
26 | public List getFolderMessages(String folder) {
27 | if (FOLDERS.contains(folder)) {
28 | if (folder.equals(FOLDER_INBOX)) {
29 | return repository.findAll();
30 | } else if (folder.equals(FOLDER_FLAGGED)) {
31 | return repository.findByFlagIsNotNullAndTrashed(false);
32 | }
33 | }
34 | return new ArrayList<>();
35 | }
36 |
37 | public long countAllUnread() {
38 | return repository.findByRead(false).count();
39 |
40 | }
41 |
42 | public long countFlaggedUnread() {
43 | return repository.findByFlagIsNotNullAndRead(false).count();
44 | }
45 |
46 | public void save(Message message) {
47 | repository.saveAndFlush(message);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/backend/MessageRepository.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.backend;
2 |
3 | import java.util.List;
4 |
5 | import org.apache.deltaspike.data.api.EntityRepository;
6 | import org.apache.deltaspike.data.api.QueryResult;
7 | import org.apache.deltaspike.data.api.Repository;
8 |
9 | @Repository
10 | public interface MessageRepository extends EntityRepository {
11 | QueryResult findByRead(boolean read);
12 |
13 | QueryResult findByFlagIsNotNullAndRead(boolean read);
14 |
15 | List findByFlagIsNotNullAndTrashed(boolean trashed);
16 | }
17 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/FolderView.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.ui;
2 |
3 | import javax.inject.Inject;
4 |
5 | import org.vaadin.example.backend.Message;
6 | import org.vaadin.example.backend.MessageFacade;
7 |
8 | import com.vaadin.cdi.CDIView;
9 | import com.vaadin.navigator.View;
10 | import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
11 | import com.vaadin.ui.VerticalLayout;
12 |
13 | /**
14 | * View listing messages fetched through MessageFacade. Also handles message
15 | * clicks to mark them as read.
16 | *
17 | */
18 | @CDIView(supportsParameters = true, value = FolderView.VIEW_NAME)
19 | public class FolderView extends VerticalLayout implements View {
20 |
21 | public static final String VIEW_NAME = "folder";
22 |
23 | @Inject
24 | private MessageFacade messageFacade;
25 |
26 | @Inject
27 | javax.enterprise.event.Event messageSelectEvent;
28 |
29 | @Override
30 | public void enter(ViewChangeEvent event) {
31 | String folder = event.getParameters();
32 | refreshFolder(folder);
33 | }
34 |
35 | private void refreshFolder(String folder) {
36 | removeAllComponents();
37 | messageFacade.getFolderMessages(folder).stream()
38 | .map(this::createFromEntity).forEach(this::addComponent);
39 | }
40 |
41 | private MessageComponent createFromEntity(Message entity) {
42 | MessageComponent msg = new MessageComponent(entity,
43 | this::onMessageClicked);
44 | return msg;
45 | }
46 |
47 | private void onMessageClicked(MessageComponent source, Message message) {
48 | if (!message.isRead()) {
49 | message.setRead(true);
50 | messageFacade.save(message);
51 | source.setIndicator(true, message.getFlag());
52 | }
53 | messageSelectEvent.fire(new MessageModifiedEvent(message));
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/MainLayout.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.ui;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import java.util.Optional;
6 | import java.util.function.Supplier;
7 |
8 | import javax.annotation.PostConstruct;
9 | import javax.enterprise.event.Observes;
10 | import javax.inject.Inject;
11 |
12 | import org.vaadin.example.backend.MessageFacade;
13 | import org.vaadin.example.ui.themes.mytheme.MyTheme;
14 |
15 | import com.vaadin.cdi.UIScoped;
16 | import com.vaadin.ui.Button;
17 | import com.vaadin.ui.Component;
18 | import com.vaadin.ui.UI;
19 |
20 | /**
21 | *
22 | * Handles the left-side menu and the top toolbar
23 | */
24 | @UIScoped
25 | public class MainLayout extends MainLayoutDesign {
26 |
27 | @Inject
28 | private MessageFacade messageFacade;
29 |
30 | private Map> badgeSuppliers = new HashMap<>();
31 |
32 | @PostConstruct
33 | protected void init() {
34 | setupMenuButtons();
35 | }
36 |
37 | public void setSelectedFolder(String folder) {
38 | menuItems.forEach(component -> adjustStyleByData(component, folder));
39 | }
40 |
41 | // Adjust all menu badges when a message is modified (marked as read)
42 | public void messageModified(@Observes MessageModifiedEvent event) {
43 | menuItems.forEach(this::setMenuBadge);
44 | }
45 |
46 | void navigateToFolder(String folder) {
47 | UI.getCurrent().getNavigator()
48 | .navigateTo(FolderView.VIEW_NAME + "/" + folder);
49 | }
50 |
51 | private void setupMenuButtons() {
52 | mapButton(inboxButton, MessageFacade.FOLDER_INBOX,
53 | Optional.of(() -> messageFacade.countAllUnread()));
54 | mapButton(draftsButton, MessageFacade.FOLDER_DRAFTS);
55 | mapButton(sentButton, MessageFacade.FOLDER_SENT);
56 | mapButton(junkButton, MessageFacade.FOLDER_JUNK);
57 | mapButton(trashButton, MessageFacade.FOLDER_TRASH);
58 | mapButton(flaggedButton, MessageFacade.FOLDER_FLAGGED,
59 | Optional.of(() -> messageFacade.countFlaggedUnread()));
60 |
61 | menuItems.forEach(this::setMenuBadge);
62 | }
63 |
64 | // Formats a given Button component's caption to contain HTML in a
65 | // particular format required by Valo themed menu item component
66 | private void setMenuBadge(Component component) {
67 | if (component instanceof Button) {
68 | Button button = (Button) component;
69 | if (button.getData() != null
70 | && button.getData() instanceof String) {
71 | String folder = (String) button.getData();
72 | Long count = badgeSuppliers.containsKey(folder)
73 | ? badgeSuppliers.get(folder).get() : 0L;
74 | String badgeText = (count != null && count > 0)
75 | ? (count > 99) ? "99+" : count.toString() : "";
76 | String captionFormat = badgeText.isEmpty() ? ""
77 | : "%s ";
78 | if (captionFormat.isEmpty()) {
79 | component.setCaption(folder);
80 | } else {
81 | component.setCaption(
82 | String.format(captionFormat, folder, badgeText));
83 | }
84 | }
85 | }
86 | }
87 |
88 | // Map button click to a navigation method.
89 | // Map button to a folder name to allow setting selected style when folder
90 | // is navigated without clicking the button.
91 | // Map button to a Supplier method, that provides count for unread items
92 | private void mapButton(Button button, String folderName,
93 | Optional> badgeSupplier) {
94 | button.addClickListener(event -> navigateToFolder(folderName));
95 | button.setData(folderName);
96 | if (badgeSupplier.isPresent()) {
97 | badgeSuppliers.put(folderName, badgeSupplier.get());
98 | }
99 | }
100 |
101 | private void mapButton(Button button, String folderName) {
102 | mapButton(button, folderName, Optional.empty());
103 | }
104 |
105 | // Checks if a given Component has a given folder name as data, and adds or
106 | // removes selected style appropriately
107 | private void adjustStyleByData(Component component, Object data) {
108 | if (component instanceof Button) {
109 | if (data != null && data.equals(((Button) component).getData())) {
110 | component.addStyleName(MyTheme.SELECTED);
111 | } else {
112 | component.removeStyleName(MyTheme.SELECTED);
113 | }
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/MainLayoutDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.ui;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.Button;
6 | import com.vaadin.ui.ComboBox;
7 | import com.vaadin.ui.CssLayout;
8 | import com.vaadin.ui.HorizontalLayout;
9 | import com.vaadin.ui.Panel;
10 | import com.vaadin.ui.VerticalLayout;
11 | import com.vaadin.ui.declarative.Design;
12 |
13 | /**
14 | * !! DO NOT EDIT THIS FILE !!
15 | *
16 | * This class is generated by Vaadin Designer and will be overwritten.
17 | *
18 | * Please make a subclass with logic and additional interfaces as needed,
19 | * e.g class LoginView extends LoginDesign implements View { … }
20 | */
21 | @DesignRoot
22 | @AutoGenerated
23 | @SuppressWarnings("serial")
24 | public class MainLayoutDesign extends HorizontalLayout {
25 | protected Button menuToggle;
26 | protected CssLayout menuItems;
27 | protected Button composeButton;
28 | protected Button inboxButton;
29 | protected Button draftsButton;
30 | protected Button sentButton;
31 | protected Button junkButton;
32 | protected Button trashButton;
33 | protected Button flaggedButton;
34 | protected VerticalLayout content;
35 | protected ComboBox sortCombo;
36 | protected Button deleteButton;
37 | protected Button replyButton;
38 | protected Button replyAllButton;
39 | protected Button forwardButton;
40 | protected ComboBox flagCombo;
41 | protected Panel messagePanel;
42 | protected VerticalLayout messageList;
43 |
44 | public MainLayoutDesign() {
45 | Design.read(this);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/MessageComponent.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.ui;
2 |
3 | import org.vaadin.example.backend.Message;
4 | import org.vaadin.example.backend.Message.Flag;
5 | import org.vaadin.example.ui.themes.mytheme.MyTheme;
6 |
7 | import com.vaadin.server.FontAwesome;
8 |
9 | /**
10 | * This is the place to implement component logic for MessageDesign. The super
11 | * class should not be edited, because Vaadin Designer overwrites it.
12 | *
13 | */
14 | public class MessageComponent extends MessageDesign {
15 |
16 | public MessageComponent(Message message,
17 | MessageClickListener clickListener) {
18 | senderLabel.setValue(message.getSender());
19 | messageLabel.setCaption(message.getSubject());
20 | messageLabel.setValue(message.getBody());
21 |
22 | addLayoutClickListener(
23 | event -> clickListener.messageClick(this, message));
24 | setIndicator(message.isRead(), message.getFlag());
25 | }
26 |
27 | public void setIndicator(boolean read, Flag flag) {
28 | MyTheme.MESSAGE_STYLES.forEach(indicatorButton::removeStyleName);
29 | indicatorButton.setIcon(null);
30 | if (flag == Flag.FLAG_STAR) {
31 | indicatorButton.setIcon(FontAwesome.STAR);
32 | if (!read) {
33 | indicatorButton.addStyleName(MyTheme.INDICATOR_STAR_RED);
34 | }
35 | } else if (!read) {
36 | indicatorButton.setIcon(FontAwesome.CIRCLE);
37 | indicatorButton.addStyleName(MyTheme.INDICATOR_CIRCLE);
38 | }
39 | }
40 |
41 | @FunctionalInterface
42 | interface MessageClickListener {
43 | public void messageClick(MessageComponent source, Message message);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/MessageDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.ui;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.Button;
6 | import com.vaadin.ui.HorizontalLayout;
7 | import com.vaadin.ui.Label;
8 | import com.vaadin.ui.declarative.Design;
9 |
10 | /**
11 | * !! DO NOT EDIT THIS FILE !!
12 | *
13 | * This class is generated by Vaadin Designer and will be overwritten.
14 | *
15 | * Please make a subclass with logic and additional interfaces as needed, e.g
16 | * class LoginView extends LoginDesign implements View { … }
17 | */
18 | @DesignRoot
19 | @AutoGenerated
20 | @SuppressWarnings("serial")
21 | public class MessageDesign extends HorizontalLayout {
22 | protected Button indicatorButton;
23 | protected Label senderLabel;
24 | protected Label messageLabel;
25 |
26 | public MessageDesign() {
27 | Design.read(this);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/MessageModifiedEvent.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.ui;
2 |
3 | import org.vaadin.example.backend.Message;
4 |
5 | /**
6 | * Event is fired by {@link FolderView} and observed by {@link MyUI}.
7 | *
8 | */
9 | public class MessageModifiedEvent {
10 | private final Message message;
11 |
12 | public MessageModifiedEvent(Message message) {
13 | this.message = message;
14 | }
15 |
16 | public Message getMessage() {
17 | return message;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/MyUI.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.ui;
2 |
3 | import javax.inject.Inject;
4 | import javax.servlet.ServletContextEvent;
5 | import javax.servlet.ServletContextListener;
6 | import javax.servlet.annotation.WebListener;
7 |
8 | import org.vaadin.example.backend.DatabaseInitialization;
9 | import org.vaadin.example.backend.MessageFacade;
10 |
11 | import com.vaadin.annotations.Theme;
12 | import com.vaadin.cdi.CDIUI;
13 | import com.vaadin.cdi.CDIViewProvider;
14 | import com.vaadin.navigator.Navigator;
15 | import com.vaadin.navigator.ViewChangeListener;
16 | import com.vaadin.server.VaadinRequest;
17 | import com.vaadin.ui.UI;
18 |
19 | /**
20 | * UI class using Vaadin CDI addon annotation CDIUI, which makes it a managed
21 | * bean and allows to inject dependencies to it.
22 | */
23 | @Theme("mytheme")
24 | @CDIUI("")
25 | public class MyUI extends UI {
26 |
27 | // CDIViewProvider implements com.vaadin.navigator.ViewProvider and
28 | // understands container managed views.
29 | @Inject
30 | private CDIViewProvider viewProvider;
31 |
32 | @Inject
33 | private MainLayout mainLayout;
34 |
35 | @Override
36 | protected void init(VaadinRequest vaadinRequest) {
37 | setContent(mainLayout);
38 |
39 | Navigator navigator = new Navigator(this, mainLayout.messagePanel);
40 | navigator.addProvider(viewProvider);
41 | setNavigator(navigator);
42 |
43 | navigator.addViewChangeListener(new ViewChangeListener() {
44 |
45 | @Override
46 | public boolean beforeViewChange(ViewChangeEvent event) {
47 | return true;
48 | }
49 |
50 | @Override
51 | public void afterViewChange(ViewChangeEvent event) {
52 | String folder = event.getParameters();
53 | mainLayout.setSelectedFolder(folder);
54 | }
55 | });
56 |
57 | if (navigator.getState().isEmpty()) {
58 | mainLayout.navigateToFolder(MessageFacade.FOLDER_INBOX);
59 | }
60 |
61 | }
62 |
63 | // Test data initialization is done in contextInitialized Servlet life-cycle
64 | // event
65 | @WebListener
66 | private static class MyUIServlectContextListener
67 | implements ServletContextListener {
68 |
69 | @Inject
70 | private DatabaseInitialization init;
71 |
72 | @Override
73 | public void contextDestroyed(ServletContextEvent arg0) {
74 | // do nothing
75 | }
76 |
77 | @Override
78 | public void contextInitialized(ServletContextEvent arg0) {
79 | init.initDatabaseIfEmpty();
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/java/org/vaadin/example/ui/themes/mytheme/MyTheme.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example.ui.themes.mytheme;
2 |
3 | import java.util.Arrays;
4 | import java.util.Collections;
5 | import java.util.List;
6 |
7 | public class MyTheme {
8 | public static final String INDICATOR_STAR_RED = "indicator-star-red";
9 | public static final String INDICATOR_CIRCLE = "indicator-circle";
10 | public static final String SELECTED = "selected";
11 |
12 | public static final List MESSAGE_STYLES = Collections
13 | .unmodifiableList(Arrays.asList(MyTheme.INDICATOR_CIRCLE,
14 | MyTheme.INDICATOR_STAR_RED));
15 | }
16 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/resources/META-INF/apache-deltaspike.properties:
--------------------------------------------------------------------------------
1 | globalAlternatives.org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy=org.apache.deltaspike.jpa.impl.transaction.ContainerManagedTransactionStrategy
2 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/resources/META-INF/persistence.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/resources/org/vaadin/example/ui/MainLayoutDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Menu
12 |
13 |
14 |
15 | Compose
16 |
17 |
18 | Inbox
19 |
20 |
21 |
22 | Drafts
23 |
24 |
25 | Sent
26 |
27 |
28 | Junk
29 |
30 |
31 | Trash
32 |
33 |
34 |
35 | Flagged
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Sort by:
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/resources/org/vaadin/example/ui/MessageDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | This is the sender
12 |
13 |
14 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed posuere interdum sem. Quisque ligula eros ullamcorper quis, lacinia quis facilisis sed sapien. Mauris varius diam vitae arcu. Sed arcu lectus auctor vitae, consectetuer et venenatis eget velit. Sed augue orci, lacinia eu tincidunt et eleifend nec lacus. Donec ultricies nisl ut felis, suspendisse potenti.
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/webapp/VAADIN/themes/mytheme/addons.scss:
--------------------------------------------------------------------------------
1 | /* This file is automatically managed and will be overwritten from time to time. */
2 | /* Do not manually edit this file. */
3 |
4 | /* Import and include this mixin into your project theme to include the addon themes */
5 | @mixin addons {
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/webapp/VAADIN/themes/mytheme/designs.scss:
--------------------------------------------------------------------------------
1 | // Styles imported from ApplicationDesign.html
2 | // Workaround for a https://dev.vaadin.com/ticket/19170 to get hidden icons in some environments to show
3 | #responsive-application-template.valo-menu-responsive .valo-menu-part .valo-menu-item span.v-icon {
4 | opacity: 1.0;
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/webapp/VAADIN/themes/mytheme/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaadin/designer-tutorials/5a810e6e5c3cb78f4396405c909491dcd8d84533/emailclient-tutorial-data/src/main/webapp/VAADIN/themes/mytheme/favicon.ico
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/webapp/VAADIN/themes/mytheme/mytheme.scss:
--------------------------------------------------------------------------------
1 | // Valo parameters to make the menu look as desired
2 | $valo-menu-background-color: #433;
3 | $v-focus-color: #433;
4 | $v-border-radius: 10px;
5 |
6 | @import "../valo/valo.scss";
7 |
8 | @mixin mytheme {
9 | @include valo;
10 |
11 | // More spacing around the menu items (and re-align badge after that change)
12 | .valo-menu-item {
13 | line-height: 45px;
14 | .valo-menu-badge {
15 | top: 12px;
16 | }
17 | }
18 |
19 | // Only for the "desktop" (wide) version: make menu wider
20 | .valo-menu-responsive[width-range~="1101px-"] {
21 | .valo-menu-item-caption {
22 | min-width: 150px;
23 | }
24 | }
25 |
26 | // Make the compose button bigger and add some spacing
27 | .compose {
28 | padding-top: 50px;
29 | .v-icon {
30 | font-size: 50px;
31 | color: #ccc;
32 | padding-bottom: 15px;
33 | }
34 |
35 | // Make the compose button react when mousing over
36 | &:hover {
37 | color: white;
38 | .v-icon {
39 | color: white;
40 | }
41 | }
42 |
43 | // Workaround for always visible scroll bar
44 | &:after {
45 | right: 0px;
46 | }
47 | }
48 |
49 | // Just a barely noticeable gradient to make the background a little bit nicer
50 | .valo-menu {
51 | @include linear-gradient(230deg, #433 0%, #382a2a 100%);
52 | }
53 |
54 | // Horizontal lines below the header and message content
55 | .header, .content {
56 | border-bottom: 1px solid #ccc;
57 | }
58 |
59 | .message-layout {
60 | .message-sender {
61 | white-space: nowrap;
62 | overflow: hidden;
63 | }
64 |
65 | .message {
66 | overflow: hidden;
67 | }
68 |
69 | .v-caption-message {
70 | padding-left: 0;
71 | }
72 |
73 | &:hover {
74 | cursor: pointer;
75 | }
76 | }
77 |
78 | .indicator-star-red {
79 | .v-icon {
80 | color: #ff3301;
81 | }
82 | }
83 |
84 | .indicator-circle {
85 | .v-icon {
86 | color: #0398ff;
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/webapp/VAADIN/themes/mytheme/styles.scss:
--------------------------------------------------------------------------------
1 | @import "designs.scss";
2 | @import "mytheme.scss";
3 | @import "addons.scss";
4 |
5 | // This file prefixes all rules with the theme name to avoid causing conflicts with other themes.
6 | // The actual styles should be defined in mytheme.scss
7 |
8 | .mytheme {
9 | @include addons;
10 | @include mytheme;
11 | }
12 |
--------------------------------------------------------------------------------
/emailclient-tutorial-data/src/main/webapp/WEB-INF/beans.xml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaadin/designer-tutorials/5a810e6e5c3cb78f4396405c909491dcd8d84533/emailclient-tutorial-data/src/main/webapp/WEB-INF/beans.xml
--------------------------------------------------------------------------------
/emailclient-tutorial-data/tutorial-images/email-client-with-data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaadin/designer-tutorials/5a810e6e5c3cb78f4396405c909491dcd8d84533/emailclient-tutorial-data/tutorial-images/email-client-with-data.png
--------------------------------------------------------------------------------
/emailclient-tutorial/README.md:
--------------------------------------------------------------------------------
1 | `This tutorial is written using Java 8, Vaadin 7.7.3 and Designer 1.2`
2 |
3 | Building a comprehensive UI from scratch with Vaadin Designer
4 | ==================================
5 | If you just want to see the end result, can fork this project and run the code yourself. However, I recommend starting from scratch and going through all the steps yourself.
6 |
7 | In the following tutorial you will build a bit more extensive application UI than in some of the earlier tutorials. This tutorial familiarizes you with the different features of [Vaadin Designer](https://vaadin.com/designer) and gives you ideas of how the tool can be used more effectively. The tutorial is based on a video, where Marc and Ville from Vaadin demonstrate how Vaadin Designer can be used to create a substantial application from an existing design.
8 |
9 | [](https://www.youtube.com/watch?v=-6Ix8WHgD6g "Vaadin Designer demonstration")
10 |
11 | In the video they use a design from a site called www.100daysui.com where Paul Flavius Nechita made a UI design per day. The design for day [#38](https://dribbble.com/shots/2181203-Day-038-Email-Client/attachments/402034) was a mockup of an email client. This tutorial breaks down the steps in the video to help you follow the same workflow. Let’s see how close we can get to the design with only a little effort.
12 |
13 | Start by creating a project
14 | ---------------------------
15 | Create a new Vaadin 7 project either by using the Vaadin Eclipse plugin or Maven. You should use version 7.7.3 or newer of Vaadin. If you are using Maven, just use vaadin-archetype-application.
16 | ```
17 | mvn archetype:generate -DarchetypeGroupId=com.vaadin -DarchetypeArtifactId=vaadin-archetype-application -DarchetypeVersion=7.7.3
18 | ```
19 | Getting a head start
20 | --------------------
21 | The application UI is divided into three areas: the menu layout on the left side, the action toolbar on the top right, and the list of email messages in the content area on the right. To get a good head start you can use a template called Responsive Application. The template has a menu for the left side and a content area.
22 |
23 | The application layout created with the template is also responsive, meaning that menu items are displayed in a more compact way when the width of the browser window gets smaller, e.g. in a mobile browser. The responsiveness is done using Vaadin Framework’s responsive extension and specific style names in Valo theme. The responsive part is out of the scope of this tutorial.
24 |
25 | * Create a new design in your project by right clicking your project and selecting __New › Other… › Vaadin Design.__
26 | * In the dialog, select the __Responsive Application template__ and give the design the name ApplicationDesign.
27 |
28 | __Your design from the template should look like this__
29 | 
30 |
31 | Beautiful buttons
32 | -----------------
33 | * Remove the blue menuTitle HorizontalLayout that has the text ‘The Application’.
34 | * Select the top most button userButton and change its style from the properties panel.
35 | * Clear the value of PrimaryStyleName property and set the StyleName property value with opening the style editor .
36 | * From ValoTheme, add styles `BUTTON_BORDERLESS` and `BUTTON_ICON_ALIGN_TOP`.
37 | * Click OK to close the style editor.
38 |
39 | As you can see, the button style changed and the button StyleName property has the value ‘borderless icon-align-top’. Sometimes it’s faster just to write the style name instead of using the style editor, if you remember the style name, that is.
40 |
41 | * Modify the userButton
42 | * Set the height to 150px.
43 | * Change its caption to Compose.
44 | * Change its name to composeButton.
45 | * Give a new icon with the icon editor. Select the Font Icons tab and select the icon called `EDIT`.
46 |
47 | The inbox button is ok and can be moved below the composeButton. The rest of the buttons you need to change: name, caption, and icon properties. The template doesn’t contain enough buttons, so you need to add a couple. The easiest way is to copy one of the buttons and paste it a couple of times. To get the little number badge by the button caption, you need to set the HtmlContentAllowed checkbox and set the button caption to contain an Html snippet e.g. ``.
48 |
49 |  FILES_O,  PAPER_PLANE,  EXCLAMATION,  TRASH_O,  FLAG.
50 |
51 | __At this point your application should look like this__
52 | 
53 |
54 | The left side menu looks quite nice already, but you need to style it up a bit to get it to look more like the UI mockup. You need to add the styles to your theme scss file. Remember that any Valo variables need to be set before the valo.scss is imported. All the other style definitions go inside your theme mixin.
55 |
56 | * Change the color of the menu background: `$valo-menu-background-color: #433;`
57 | * Change the menu badge roundness: `$v-border-radius: 10px;`
58 |
59 | Make the menu wider when the layout is in the “desktop” mode. Add a responsive extension CSS “breakpoint”. The topic of responsive layouts is out of our scope, but if you are interested, check out the Book of Vaadin chapter about it: https://vaadin.com/book/-/page/themes.responsive.html.
60 | ```css
61 | .valo-menu-responsive[width-range~="1101px-"] {
62 | .valo-menu-item-caption {
63 | min-width: 150px;
64 | }
65 | }
66 | ```
67 | Add some space around the menu items by making the menu item line height higher and then realign the badge.
68 | ```css
69 | .valo-menu-item {
70 | line-height: 45px;
71 | .valo-menu-badge {
72 | top: 12px;
73 | }
74 | }
75 | ```
76 | And finally make the compose button more dominant. Add another StyleName called compose to composeButton. With these Sass (and CSS) directives, your buttons should look correct.
77 |
78 | ```css
79 | .compose {
80 | padding-top: 50px;
81 | .v-icon {
82 | font-size: 50px;
83 | color: #ccc;
84 | padding-bottom: 15px;
85 | }
86 |
87 | // Make the compose button react when mousing over
88 | &:hover {
89 | color: white;
90 | .v-icon {
91 | color: white;
92 | }
93 | }
94 |
95 | // Workaround for always visible scroll bar
96 | &:after {
97 | right: 0px;
98 | }
99 | }
100 | ```
101 | __With correctly styled buttons your application should look like this__
102 | 
103 |
104 | Toolbar
105 | -------
106 | Now that the left side navigation is looking good, let’s implement the toolbar above the message list.
107 | * First make the content called VerticalLayout full size and then drag a HorizontalLayout and a Panel into the content layout.
108 | * Make sure the Panel is full size and has ExpandRatio 1.0, and the HorizontalLayout has 100% width and an undefined height.
109 | * The expand is set automatically when you click the quick actions for the layout sizes in the Designer.
110 | * Add spacing and margins to the HorizontalLayout and remove margins and spacing from the content layout.
111 | * Set the `PANEL_BORDERLESS` style for the Panel.
112 |
113 | Build the toolbar component structure
114 | * Drag a Label into the toolbar HorizontalLayout
115 | * Value: Sort by
116 | * Align it middle-left with the quick actions
117 | * Drag a ComboBox into the toolbar layout
118 | * Set a width of 150px
119 | * Drag buttons, give them a name, remove their captions, and add their icons:
120 | * Delete button icon: `TIMES`
121 | * Reply button icon: `MAIL_REPLY`
122 | * Reply all button icon: `MAIL_REPLY_ALL`
123 | * Forward button icon: `MAIL_FORWARD.`
124 | * Wrap reply button with a CssLayout by right clicking the button in the Outline and select Wrap with…
125 | * Move ‘reply all’ and ‘forward’ buttons to the CssLayout and change the layout StyleName to `LAYOUT_COMPONENT_GROUP` from Valo Theme.
126 |
127 | Message list
128 | ------------
129 | The scrollable Panel will contain the list of messages in each of the selected folders. There’s a slight challenge to design the message look-and-feel, because the content in the Panel is dynamic and the 1.0 version of Vaadin Designer doesn’t support nested designs nor component compositions. This is likely to be changed in the future, but in the meanwhile, what you want to do in case of dynamic content is to first design the composition in the place it’s going to appear and then detach it to a separate design file. This way you can benefit both from having the visual tools for designing and still keep the composition accessible from Java. Drag a VerticalLayout into the content Panel. Set its width to 100% and put the spacing on. Now you can start with the message itself.
130 |
131 | Build the message component structure
132 | * Drag a HorizontalLayout into the VerticalLayout inside content Panel.
133 | * Width 100%, and height 125px.
134 | * StyleName: message-layout
135 | * Drag a Button into the HorizontalLayout
136 | * Caption: n/a
137 | * Name: indicatorButton
138 | * Icon: Font icon `STAR`
139 | * StyleName: borderless
140 | * Drag a VerticalLayout into the HorizontalLayout
141 | * Expand the width and height to 100%
142 | * StyleName: content
143 | * Drag a Label into the VerticalLayout
144 | * Name: senderLabel
145 | * Expand it to 100% width
146 | * Set the label value to “This is the subject”
147 | * StyleName: bold and message-sender
148 | * Drag another Label into the VerticalLayout below the senderLabel
149 | * Name: messageLabel
150 | * Expand the label to 100% width and height
151 | * Label caption: This is the title
152 | * Label value: Put something e.g. lorem ipsum
153 | * StyleName: message
154 |
155 | Provided you added the style names to the components as instructed, you can use these style definitions.
156 |
157 | To get the horizontal line under each message:
158 | ```css
159 | .header, .content {
160 | border-bottom: 1px solid #ccc;
161 | }
162 | ```
163 | To get the message title and content to behave even if they don’t fit in the given space:
164 | ```css
165 | .message-layout {
166 | .message-sender {
167 | white-space: nowrap;
168 | overflow: hidden;
169 | }
170 |
171 | .message {
172 | overflow: hidden;
173 | }
174 | }
175 | ```
176 | Finally enable the right side margin of the message content VerticalLayout from the properties. Individual margins can be enabled using the margin editor, just click .
177 |
178 | __Completed message item design__
179 | 
180 |
181 | As the final step in implementing the message component you need to create a new design. Name it MessageDesign and use the blank template. Then copy-paste the whole message layout to your new design. At the time of writing this, there is a limitation in Designer, which prevents you pasting to a blank design in the visual view. You need to switch to the source mode and paste your content in between the body elements.
182 |
183 | Create a new Java class called Message as a subclass of MessageDesign. This Message class is the place where you would implement the component logic, but for now, you can leave it empty. Create a bunch of Message instances in a loop to demonstrate how the dynamic content works in your application design
184 | ```java
185 | @Override
186 | protected void init(VaadinRequest vaadinRequest) {
187 | final ApplicationDesign design = new ApplicationDesign();
188 | setContent(design);
189 |
190 | for (int i = 0; i < 10; i++) {
191 | design.messageList.addComponent(new Message());
192 | }
193 | }
194 | ```
195 |
196 | Final result
197 | ------------
198 | The final result looks quite nice. You started from a basic responsive application template and took some simple steps to modify the design to look like the design mockup. First you modified the left side menu to have the correct buttons and styled the compose button to be more dominant. Then you implemented the rest of the application layout to contain a toolbar and a scrollable message list. Finally you created a message component to be used dynamically in your Java code. After these steps your design should look more or less like in the image below. Great job!
199 |
200 | __Finished application__
201 | 
202 |
203 | What now?
204 | ---------
205 | As you probably noticed, the end result isn't completely identical with the original mockup. The email dates are not there and the menu has some more info at the bottom. These are left for you to work on and now you can try out your new Vaadin Designer skills for real!
206 |
--------------------------------------------------------------------------------
/emailclient-tutorial/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.vaadin.example
6 | emailclient-tutorial
7 | war
8 | 1.0-SNAPSHOT
9 | emailclient-tutorial
10 |
11 |
12 | 3
13 |
14 |
15 |
16 | 7.7.3
17 | ${vaadin.version}
18 | 9.2.3.v20140905
19 | 1.8
20 | 1.8
21 | UTF-8
22 |
23 | local
24 |
25 |
26 |
27 |
28 | vaadin-addons
29 | https://maven.vaadin.com/vaadin-addons
30 |
31 |
32 |
33 |
34 |
35 |
36 | com.vaadin
37 | vaadin-bom
38 | ${vaadin.version}
39 | pom
40 | import
41 |
42 |
43 |
44 |
45 |
46 |
47 | javax.servlet
48 | javax.servlet-api
49 | 3.0.1
50 | provided
51 |
52 |
53 | com.vaadin
54 | vaadin-server
55 |
56 |
57 | com.vaadin
58 | vaadin-push
59 |
60 |
61 | com.vaadin
62 | vaadin-client-compiled
63 |
64 |
65 | com.vaadin
66 | vaadin-themes
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-compiler-plugin
75 | 3.0
76 |
77 | ${project.encoding}
78 | ${project.source.version}
79 | ${project.target.version}
80 |
81 |
82 |
83 | org.apache.maven.plugins
84 | maven-resources-plugin
85 | 2.6
86 |
87 | ${project.encoding}
88 |
89 |
90 |
91 | org.apache.maven.plugins
92 | maven-war-plugin
93 | 2.3
94 |
95 | false
96 |
97 | WEB-INF/classes/VAADIN/gwt-unitCache/**,
98 | WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**
99 |
100 |
101 |
102 | com.vaadin
103 | vaadin-maven-plugin
104 | ${vaadin.plugin.version}
105 |
106 | -Xmx512M -Xss1024k
107 | ${basedir}/target/classes/VAADIN/widgetsets
108 | false
109 | false
110 |
111 | true
112 |
113 |
114 |
115 |
116 | update-theme
117 | update-widgetset
118 | compile
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | org.apache.maven.plugins
127 | maven-source-plugin
128 | 2.4
129 |
130 |
131 | org.apache.maven.plugins
132 | maven-clean-plugin
133 | 2.6.1
134 |
135 |
136 |
137 |
138 | src/main/webapp/VAADIN/themes
139 |
140 | **/styles.css
141 | **/styles.scss.cache
142 |
143 |
144 |
145 |
146 |
147 |
148 |
150 |
151 | org.eclipse.jetty
152 | jetty-maven-plugin
153 | ${jetty.plugin.version}
154 |
155 | 2
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | vaadin-prerelease
165 |
166 | false
167 |
168 |
169 |
170 |
171 | vaadin-prereleases
172 | https://maven.vaadin.com/vaadin-prereleases
173 |
174 |
175 | vaadin-snapshots
176 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/
177 |
178 | false
179 |
180 |
181 | true
182 |
183 |
184 |
185 |
186 |
187 | vaadin-prereleases
188 | https://maven.vaadin.com/vaadin-prereleases
189 |
190 |
191 | vaadin-snapshots
192 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/
193 |
194 | false
195 |
196 |
197 | true
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/java/org/vaadin/example/ApplicationDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.Button;
6 | import com.vaadin.ui.ComboBox;
7 | import com.vaadin.ui.CssLayout;
8 | import com.vaadin.ui.HorizontalLayout;
9 | import com.vaadin.ui.VerticalLayout;
10 | import com.vaadin.ui.declarative.Design;
11 |
12 | /**
13 | * !! DO NOT EDIT THIS FILE !!
14 | *
15 | * This class is generated by Vaadin Designer and will be overwritten.
16 | *
17 | * Please make a subclass with logic and additional interfaces as needed,
18 | * e.g class LoginView extends LoginDesign implements View { … }
19 | */
20 | @DesignRoot
21 | @AutoGenerated
22 | @SuppressWarnings("serial")
23 | public class ApplicationDesign extends HorizontalLayout {
24 | protected Button menuToggle;
25 | protected CssLayout menuItems;
26 | protected Button composeButton;
27 | protected Button inboxButton;
28 | protected Button draftsButton;
29 | protected Button sentButton;
30 | protected Button junkButton;
31 | protected Button trashButton;
32 | protected Button flaggedButton;
33 | protected VerticalLayout content;
34 | protected ComboBox sortCombo;
35 | protected Button deleteButton;
36 | protected Button replyButton;
37 | protected Button replyAllButton;
38 | protected Button forwardButton;
39 | protected VerticalLayout messageList;
40 |
41 | public ApplicationDesign() {
42 | Design.read(this);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/java/org/vaadin/example/Message.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | /**
4 | * This is the place to implement component logic for MessageDesign. The super
5 | * class should not be edited, because Vaadin Designer overwrites it.
6 | */
7 | public class Message extends MessageDesign {
8 | }
9 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/java/org/vaadin/example/MessageDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.Button;
6 | import com.vaadin.ui.HorizontalLayout;
7 | import com.vaadin.ui.Label;
8 | import com.vaadin.ui.declarative.Design;
9 |
10 | /**
11 | * !! DO NOT EDIT THIS FILE !!
12 | *
13 | * This class is generated by Vaadin Designer and will be overwritten.
14 | *
15 | * Please make a subclass with logic and additional interfaces as needed,
16 | * e.g class LoginView extends LoginDesign implements View { … }
17 | */
18 | @DesignRoot
19 | @AutoGenerated
20 | @SuppressWarnings("serial")
21 | public class MessageDesign extends HorizontalLayout {
22 | protected Button indicatorButton;
23 | protected Label senderLabel;
24 | protected Label messageLabel;
25 |
26 | public MessageDesign() {
27 | Design.read(this);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/java/org/vaadin/example/MyUI.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import javax.servlet.annotation.WebServlet;
4 |
5 | import com.vaadin.annotations.Theme;
6 | import com.vaadin.annotations.VaadinServletConfiguration;
7 | import com.vaadin.server.VaadinRequest;
8 | import com.vaadin.server.VaadinServlet;
9 | import com.vaadin.ui.UI;
10 |
11 | /**
12 | *
13 | */
14 | @Theme("mytheme")
15 | public class MyUI extends UI {
16 |
17 | @Override
18 | protected void init(VaadinRequest vaadinRequest) {
19 | final ApplicationDesign design = new ApplicationDesign();
20 | setContent(design);
21 |
22 | // This replaces a proper backend just to simulate how the view behaves
23 | // with dynamic content
24 | for (int i = 0; i < 10; i++) {
25 | design.messageList.addComponent(new Message());
26 | }
27 | }
28 |
29 | @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
30 | @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
31 | public static class MyUIServlet extends VaadinServlet {
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/resources/org/vaadin/example/ApplicationDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Menu
12 |
13 |
14 |
15 | Compose
16 |
17 |
18 | Inbox
19 |
20 |
21 |
22 | Drafts
23 |
24 |
25 | Sent
26 |
27 |
28 | Junk
29 |
30 |
31 | Trash
32 |
33 |
34 |
35 | Flagged
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | Sort by:
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/resources/org/vaadin/example/MessageDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | This is the sender
12 |
13 |
14 | Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed posuere interdum sem. Quisque ligula eros ullamcorper quis, lacinia quis facilisis sed sapien. Mauris varius diam vitae arcu. Sed arcu lectus auctor vitae, consectetuer et venenatis eget velit. Sed augue orci, lacinia eu tincidunt et eleifend nec lacus. Donec ultricies nisl ut felis, suspendisse potenti.
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/webapp/VAADIN/themes/mytheme/addons.scss:
--------------------------------------------------------------------------------
1 | /* This file is automatically managed and will be overwritten from time to time. */
2 | /* Do not manually edit this file. */
3 |
4 | /* Import and include this mixin into your project theme to include the addon themes */
5 | @mixin addons {
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/webapp/VAADIN/themes/mytheme/designs.scss:
--------------------------------------------------------------------------------
1 | // Styles imported from ApplicationDesign.html
2 | // Workaround for a https://dev.vaadin.com/ticket/19170 to get hidden icons in some environments to show
3 | #responsive-application-template.valo-menu-responsive .valo-menu-part .valo-menu-item span.v-icon {
4 | opacity: 1.0;
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/webapp/VAADIN/themes/mytheme/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaadin/designer-tutorials/5a810e6e5c3cb78f4396405c909491dcd8d84533/emailclient-tutorial/src/main/webapp/VAADIN/themes/mytheme/favicon.ico
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/webapp/VAADIN/themes/mytheme/mytheme.scss:
--------------------------------------------------------------------------------
1 | // Valo parameters to make the menu look as desired
2 | $valo-menu-background-color: #433;
3 | $v-focus-color: #433;
4 | $v-border-radius: 10px;
5 |
6 | @import "../valo/valo.scss";
7 |
8 | @mixin mytheme {
9 | @include valo;
10 |
11 | // More spacing around the menu items (and re-align badge after that change)
12 | .valo-menu-item {
13 | line-height: 45px;
14 | .valo-menu-badge {
15 | top: 12px;
16 | }
17 | }
18 |
19 | // Only for the "desktop" (wide) version: make menu wider
20 | .valo-menu-responsive[width-range~="1101px-"] {
21 | .valo-menu-item-caption {
22 | min-width: 150px;
23 | }
24 | }
25 |
26 | // Make the compose button bigger and add some spacing
27 | .compose {
28 | padding-top: 50px;
29 | .v-icon {
30 | font-size: 50px;
31 | color: #ccc;
32 | padding-bottom: 15px;
33 | }
34 |
35 | // Make the compose button react when mousing over
36 | &:hover {
37 | color: white;
38 | .v-icon {
39 | color: white;
40 | }
41 | }
42 |
43 | // Workaround for always visible scroll bar
44 | &:after {
45 | right: 0px;
46 | }
47 | }
48 |
49 | // Just a barely noticeable gradient to make the background a little bit nicer
50 | .valo-menu {
51 | @include linear-gradient(230deg, #433 0%, #382a2a 100%);
52 | }
53 |
54 | // Horizontal lines below the header and message content
55 | .header, .content {
56 | border-bottom: 1px solid #ccc;
57 | }
58 |
59 | .message-layout {
60 | .message-sender {
61 | white-space: nowrap;
62 | overflow: hidden;
63 | }
64 |
65 | .message {
66 | overflow: hidden;
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/emailclient-tutorial/src/main/webapp/VAADIN/themes/mytheme/styles.scss:
--------------------------------------------------------------------------------
1 | @import "designs.scss";
2 | @import "mytheme.scss";
3 | @import "addons.scss";
4 |
5 | // This file prefixes all rules with the theme name to avoid causing conflicts with other themes.
6 | // The actual styles should be defined in mytheme.scss
7 |
8 | .mytheme {
9 | @include addons;
10 | @include mytheme;
11 | }
12 |
--------------------------------------------------------------------------------
/simplenavi/README.md:
--------------------------------------------------------------------------------
1 | `This tutorial is written using Java 8`
2 |
3 | simplenavi
4 | ==============
5 |
6 | Template for a simple Vaadin application that only requires a Servlet 3.0 container to run.
7 |
8 |
9 | Workflow
10 | ========
11 |
12 | To compile the entire project, run "mvn install".
13 | To run the application, run "mvn jetty:run" and open http://localhost:8080/ .
14 |
15 | To develop the theme, simply update the relevant theme files and reload the application.
16 | Pre-compiling a theme eliminates automatic theme updates at runtime - see below for more information.
17 |
18 | Debugging client side code
19 | - run "mvn vaadin:run-codeserver" on a separate console while the application is running
20 | - activate Super Dev Mode in the debug window of the application
21 |
22 | To produce a deployable production mode WAR:
23 | - change productionMode to true in the servlet class configuration (nested in the UI class)
24 | - run "mvn clean vaadin:compile-theme package"
25 | - See below for more information. Running "mvn clean" removes the pre-compiled theme.
26 | - test with "mvn jetty:run-war
27 |
28 | Using a precompiled theme
29 | -------------------------
30 |
31 | When developing the application, Vaadin can compile the theme on the fly when needed,
32 | or the theme can be precompiled to speed up page loads.
33 |
34 | To precompile the theme run "mvn vaadin:compile-theme". Note, though, that once
35 | the theme has been precompiled, any theme changes will not be visible until the
36 | next theme compilation or running the "mvn clean" target.
37 |
38 | When developing the theme, running the application in the "run" mode (rather than
39 | in "debug") in the IDE can speed up consecutive on-the-fly theme compilations
40 | significantly.
41 |
--------------------------------------------------------------------------------
/simplenavi/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | org.vaadin.example
6 | simplenavi
7 | war
8 | 1.0-SNAPSHOT
9 | simplenavi
10 |
11 |
12 | 3
13 |
14 |
15 |
16 | 7.7.3
17 | ${vaadin.version}
18 | 9.2.3.v20140905
19 | 1.8
20 | 1.8
21 | UTF-8
22 |
23 | local
24 |
25 |
26 |
27 |
28 | vaadin-addons
29 | https://maven.vaadin.com/vaadin-addons
30 |
31 |
32 |
33 |
34 |
35 |
36 | com.vaadin
37 | vaadin-bom
38 | ${vaadin.version}
39 | pom
40 | import
41 |
42 |
43 |
44 |
45 |
46 |
47 | javax.servlet
48 | javax.servlet-api
49 | 3.0.1
50 | provided
51 |
52 |
53 | com.vaadin
54 | vaadin-server
55 |
56 |
57 | com.vaadin
58 | vaadin-push
59 |
60 |
61 | com.vaadin
62 | vaadin-client-compiled
63 |
64 |
65 | com.vaadin
66 | vaadin-themes
67 |
68 |
69 |
70 |
71 |
72 |
73 | org.apache.maven.plugins
74 | maven-compiler-plugin
75 | 3.0
76 |
77 | ${project.encoding}
78 | ${project.source.version}
79 | ${project.target.version}
80 |
81 |
82 |
83 | org.apache.maven.plugins
84 | maven-resources-plugin
85 | 2.6
86 |
87 | ${project.encoding}
88 |
89 |
90 |
91 | org.apache.maven.plugins
92 | maven-war-plugin
93 | 2.3
94 |
95 | false
96 |
97 | WEB-INF/classes/VAADIN/gwt-unitCache/**,
98 | WEB-INF/classes/VAADIN/widgetsets/WEB-INF/**
99 |
100 |
101 |
102 | com.vaadin
103 | vaadin-maven-plugin
104 | ${vaadin.plugin.version}
105 |
106 | -Xmx512M -Xss1024k
107 | ${basedir}/target/classes/VAADIN/widgetsets
108 | false
109 | false
110 |
111 | true
112 |
113 |
114 |
115 |
116 | update-theme
117 | update-widgetset
118 | compile
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | org.apache.maven.plugins
127 | maven-source-plugin
128 | 2.4
129 |
130 |
131 | org.apache.maven.plugins
132 | maven-clean-plugin
133 | 2.6.1
134 |
135 |
136 |
137 |
138 | src/main/webapp/VAADIN/themes
139 |
140 | **/styles.css
141 | **/styles.scss.cache
142 |
143 |
144 |
145 |
146 |
147 |
148 |
150 |
151 | org.eclipse.jetty
152 | jetty-maven-plugin
153 | ${jetty.plugin.version}
154 |
155 | 2
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | vaadin-prerelease
165 |
166 | false
167 |
168 |
169 |
170 |
171 | vaadin-prereleases
172 | https://maven.vaadin.com/vaadin-prereleases
173 |
174 |
175 | vaadin-snapshots
176 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/
177 |
178 | false
179 |
180 |
181 | true
182 |
183 |
184 |
185 |
186 |
187 | vaadin-prereleases
188 | https://maven.vaadin.com/vaadin-prereleases
189 |
190 |
191 | vaadin-snapshots
192 | https://oss.sonatype.org/content/repositories/vaadin-snapshots/
193 |
194 | false
195 |
196 |
197 | true
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/MainLayout.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.navigator.Navigator;
4 | import com.vaadin.ui.UI;
5 |
6 | public class MainLayout extends MainLayoutDesign {
7 |
8 | public MainLayout() {
9 | Navigator navigator = new Navigator(UI.getCurrent(), contentPanel);
10 | navigator.addView(StatsView.VIEW_NAME, StatsView.class);
11 | navigator.addView(PluginsView.VIEW_NAME, PluginsView.class);
12 | navigator.addView(PermissionsView.VIEW_NAME, PermissionsView.class);
13 |
14 | menuButton1.addClickListener(event -> doNavigate(StatsView.VIEW_NAME));
15 | menuButton2
16 | .addClickListener(event -> doNavigate(PluginsView.VIEW_NAME));
17 | menuButton3.addClickListener(
18 | event -> doNavigate(PermissionsView.VIEW_NAME));
19 |
20 | if (navigator.getState().isEmpty()) {
21 | navigator.navigateTo(StatsView.VIEW_NAME);
22 | } else {
23 | navigator.navigateTo(navigator.getState());
24 | }
25 | }
26 |
27 | private void doNavigate(String viewName) {
28 | getUI().getNavigator().navigateTo(viewName);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/MainLayoutDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.HorizontalLayout;
6 | import com.vaadin.ui.NativeButton;
7 | import com.vaadin.ui.Panel;
8 | import com.vaadin.ui.VerticalLayout;
9 | import com.vaadin.ui.declarative.Design;
10 |
11 | /**
12 | * !! DO NOT EDIT THIS FILE !!
13 | *
14 | * This class is generated by Vaadin Designer and will be overwritten.
15 | *
16 | * Please make a subclass with logic and additional interfaces as needed,
17 | * e.g class LoginView extends LoginDesign implements View { … }
18 | */
19 | @DesignRoot
20 | @AutoGenerated
21 | @SuppressWarnings("serial")
22 | public class MainLayoutDesign extends HorizontalLayout {
23 | protected VerticalLayout menuLayout;
24 | protected NativeButton menuButton1;
25 | protected NativeButton menuButton2;
26 | protected NativeButton menuButton3;
27 | protected Panel contentPanel;
28 |
29 | public MainLayoutDesign() {
30 | Design.read(this);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/MyUI.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import javax.servlet.annotation.WebServlet;
4 |
5 | import com.vaadin.annotations.Theme;
6 | import com.vaadin.annotations.VaadinServletConfiguration;
7 | import com.vaadin.server.VaadinRequest;
8 | import com.vaadin.server.VaadinServlet;
9 | import com.vaadin.ui.UI;
10 |
11 | /**
12 | *
13 | */
14 | @Theme("mytheme")
15 | public class MyUI extends UI {
16 |
17 | @Override
18 | protected void init(VaadinRequest vaadinRequest) {
19 | setContent(new MainLayout());
20 |
21 | }
22 |
23 | @WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
24 | @VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
25 | public static class MyUIServlet extends VaadinServlet {
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/PermissionsView.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.navigator.View;
4 | import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
5 |
6 | public class PermissionsView extends PermissionsViewDesign implements View {
7 |
8 | public static final String VIEW_NAME = "permissions";
9 |
10 | @Override
11 | public void enter(ViewChangeEvent event) {
12 | // TODO Auto-generated method stub
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/PermissionsViewDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.VerticalLayout;
6 | import com.vaadin.ui.declarative.Design;
7 |
8 | /**
9 | * !! DO NOT EDIT THIS FILE !!
10 | *
11 | * This class is generated by Vaadin Designer and will be overwritten.
12 | *
13 | * Please make a subclass with logic and additional interfaces as needed, e.g
14 | * class LoginView extends LoginDesign implements View { … }
15 | */
16 | @DesignRoot
17 | @AutoGenerated
18 | @SuppressWarnings("serial")
19 | public class PermissionsViewDesign extends VerticalLayout {
20 | public PermissionsViewDesign() {
21 | Design.read(this);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/PluginsView.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.navigator.View;
4 | import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
5 |
6 | public class PluginsView extends PluginsViewDesign implements View {
7 |
8 | public static final String VIEW_NAME = "plugins";
9 |
10 | @Override
11 | public void enter(ViewChangeEvent event) {
12 | // TODO Auto-generated method stub
13 |
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/PluginsViewDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.VerticalLayout;
6 | import com.vaadin.ui.declarative.Design;
7 |
8 | /**
9 | * !! DO NOT EDIT THIS FILE !!
10 | *
11 | * This class is generated by Vaadin Designer and will be overwritten.
12 | *
13 | * Please make a subclass with logic and additional interfaces as needed, e.g
14 | * class LoginView extends LoginDesign implements View { … }
15 | */
16 | @DesignRoot
17 | @AutoGenerated
18 | @SuppressWarnings("serial")
19 | public class PluginsViewDesign extends VerticalLayout {
20 | public PluginsViewDesign() {
21 | Design.read(this);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/StatsView.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.navigator.View;
4 | import com.vaadin.navigator.ViewChangeListener.ViewChangeEvent;
5 |
6 | public class StatsView extends StatsViewDesign implements View {
7 |
8 | public static final String VIEW_NAME = "stats";
9 |
10 | @Override
11 | public void enter(ViewChangeEvent event) {
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/simplenavi/src/main/java/org/vaadin/example/StatsViewDesign.java:
--------------------------------------------------------------------------------
1 | package org.vaadin.example;
2 |
3 | import com.vaadin.annotations.AutoGenerated;
4 | import com.vaadin.annotations.DesignRoot;
5 | import com.vaadin.ui.VerticalLayout;
6 | import com.vaadin.ui.declarative.Design;
7 |
8 | /**
9 | * !! DO NOT EDIT THIS FILE !!
10 | *
11 | * This class is generated by Vaadin Designer and will be overwritten.
12 | *
13 | * Please make a subclass with logic and additional interfaces as needed, e.g
14 | * class LoginView extends LoginDesign implements View { … }
15 | */
16 | @DesignRoot
17 | @AutoGenerated
18 | @SuppressWarnings("serial")
19 | public class StatsViewDesign extends VerticalLayout {
20 | public StatsViewDesign() {
21 | Design.read(this);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/simplenavi/src/main/resources/org/vaadin/example/MainLayoutDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | Statistics
11 |
12 |
13 | Plug-ins
14 |
15 |
16 | Permissions
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/simplenavi/src/main/resources/org/vaadin/example/PermissionsViewDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Permissions
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/simplenavi/src/main/resources/org/vaadin/example/PluginsViewDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Plug-ins
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/simplenavi/src/main/resources/org/vaadin/example/StatsViewDesign.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Statistics
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/simplenavi/src/main/webapp/VAADIN/themes/mytheme/addons.scss:
--------------------------------------------------------------------------------
1 | /* This file is automatically managed and will be overwritten from time to time. */
2 | /* Do not manually edit this file. */
3 |
4 | /* Import and include this mixin into your project theme to include the addon themes */
5 | @mixin addons {
6 | }
7 |
8 |
--------------------------------------------------------------------------------
/simplenavi/src/main/webapp/VAADIN/themes/mytheme/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vaadin/designer-tutorials/5a810e6e5c3cb78f4396405c909491dcd8d84533/simplenavi/src/main/webapp/VAADIN/themes/mytheme/favicon.ico
--------------------------------------------------------------------------------
/simplenavi/src/main/webapp/VAADIN/themes/mytheme/mytheme.scss:
--------------------------------------------------------------------------------
1 | // Global variable overrides. Must be declared before importing Valo.
2 |
3 | // Defines the plaintext font size, weight and family. Font size affects general component sizing.
4 | //$v-font-size: 16px;
5 | //$v-font-weight: 300;
6 | //$v-font-family: "Open Sans", sans-serif;
7 |
8 | // Defines the border used by all components.
9 | //$v-border: 1px solid (v-shade 0.7);
10 | //$v-border-radius: 4px;
11 |
12 | // Affects the color of some component elements, e.g Button, Panel title, etc
13 | //$v-background-color: hsl(210, 0%, 98%);
14 | // Affects the color of content areas, e.g Panel and Window content, TextField input etc
15 | //$v-app-background-color: $v-background-color;
16 |
17 | // Affects the visual appearance of all components
18 | //$v-gradient: v-linear 8%;
19 | //$v-bevel-depth: 30%;
20 | //$v-shadow-opacity: 5%;
21 |
22 | // Defines colors for indicating status (focus, success, failure)
23 | //$v-focus-color: valo-focus-color(); // Calculates a suitable color automatically
24 | //$v-friendly-color: #2c9720;
25 | //$v-error-indicator-color: #ed473b;
26 |
27 | // For more information, see: https://vaadin.com/book/-/page/themes.valo.html
28 | // Example variants can be copy/pasted from https://vaadin.com/wiki/-/wiki/Main/Valo+Examples
29 | $v-app-loading-text: "Loading navigation example...";
30 | $v-background-color: #fafafa;
31 | $v-app-background-color: #fff;
32 | $v-panel-background-color: #fff;
33 | $v-font-family: "Source Sans Pro";
34 | $v-font-size: 20px;
35 | $v-font-color: #37404E;
36 | $v-font-weight: 400;
37 |
38 | @import "../valo/valo.scss";
39 |
40 | @mixin mytheme {
41 | @include valo;
42 |
43 | $menu-bg: #0072C6;
44 | $menu-item-color: valo-font-color($menu-bg, 0.8);
45 |
46 | .menu-layout {
47 | background-color: $menu-bg;
48 | }
49 | .menu-item {
50 | position: relative;
51 | padding: 0 40px 0 20px;
52 | text-align: left;
53 | height: 50px;
54 | border: none;
55 | background-color: $menu-bg;
56 | color: $menu-item-color;
57 | outline: none;
58 |
59 | .v-nativebutton-caption {
60 | position: absolute;
61 | bottom: 10px;
62 | left: 2.5em;
63 | }
64 |
65 | .v-icon {
66 | font-size: 30px;
67 | }
68 |
69 | &:active span {
70 | @include transition(color 0.2s linear);
71 | color: darken($menu-item-color, 30%);
72 | }
73 |
74 | &:active .v-icon, &:focus .v-icon {
75 | position: relative;
76 | top: 0;
77 | left: 0;
78 | }
79 |
80 | &:hover {
81 | color: tint($menu-item-color, 50%);
82 | cursor: pointer;
83 | }
84 | }
85 |
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/simplenavi/src/main/webapp/VAADIN/themes/mytheme/styles.scss:
--------------------------------------------------------------------------------
1 | @import "mytheme.scss";
2 | @import "addons.scss";
3 |
4 | // This file prefixes all rules with the theme name to avoid causing conflicts with other themes.
5 | // The actual styles should be defined in mytheme.scss
6 |
7 | .mytheme {
8 | @include addons;
9 | @include mytheme;
10 |
11 | }
12 |
--------------------------------------------------------------------------------