martes, 16 de abril de 2019

17. Vaadin Loginform (2). Adding style

updated on April 17, 2019

0. Introduction


It is important to give style to the components. Vaadin, sometimes is rejecting to assing some styles to the components, so it is important to test it.

1. Using CSS

We will put the CSS files in this folder:

  • Deployed Resources/webapp/frontend/css


2. The @HtmlImport annotation of the class

We will annotate the use of the "CSS file" in the LoginForm class with @HtmlImport(css/LoginForm.css).


1
2
3
4
5
6
@Route("")
@PageTitle("Login")
@HtmlImport("css/LoginForm.css")
@SuppressWarnings("serial")
public class LoginForm extends VerticalLayout implements II18nChange{
 

Here is the CSS code of LoginForm.css


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
!-- Remember to import custom-style, which is included in the Polymer package -->
<link rel="import"
      href="../bower_components/polymer/lib/elements/custom-style.html">


<custom-style>
  <style>
   .edu-login{
    
     /*
     height: 100%;
     margin: 0;
    padding: 0;
    
    */
    max-width: 600px; 
    max-height: 600px;
    color: var(--lumo-primary-text-color);
    /** Water image: Chrome needs url reltives from app while other url are relatives from css file */
     background: linear-gradient(to bottom right, rgba(255,255,255,.3), rgba(255,255,255,.99)),
                 url("../img/enterprise/enterprise02.jpeg"), /* GOOD in eclipse; BAD in chrome*/ 
                 url("frontend/img/enterprise/enterprise02.jpeg"); /* BAD in eclipse; GOOD in chrome*/     background-position: center; /* Center the image */
        background-repeat: no-repeat; /* Do not repeat the image */
        background-size: cover; /* Resize the background image to cover the entire container */            
    }
    .edu-login-header{
     width: 100%;
     border-width:5px;  
        border-bottom-style: solid;
        border-color: DodgerBlue;
        /*box-shadow: 10px 10px 5px LightGray;*/
        
        /*box-shadow: 0px 1px 3px Blue;*/
    }
    .edu-login-lang{
     width: 100%;
     min-width: 300px;
        /*box-shadow: 10px 10px 5px gray;*/
    }
    .edu-login-login{
     
     /*background: LightYellow;*/
        /*box-shadow: 5px 5px 3px LightGray;*/
    }
    .edu-login-title{
     /*background: yellow;*/
     width: 100%;
    }
       
    .edu-login-buttons{
     /*background: yellow;*/
     /*color: var(--lumo-primary-text-color);*/
     width: 100%;
    }
    
    /*****************************************/
    /*   MAIN VIEW                           */
    /*****************************************/
    
    .edu-main-header {
     width: 100%;
     background: yellow;
     margin: 0px;
     border: 0px;
     padding: 0px;
    }
    .edu-main-v1 {
     background: gray;
     margin: 0px;
     border: 0px;
     padding: 0px;
    }
    .edu-main-h11 {
     background: green;
     margin: 0px;
     border: 0px;
     padding: 0px;
    }
    .edu-main-h12 {
     background: beige;
     margin: 0px;
    }
   
    /*****************************************/
    
    /* Stack login-screen vertically on narrow screen */
    /*
    @media (max-width: 800px) {
     
    }*/
    
    
  </style>
</custom-style>


3. Setting stile to components

There are some ways of setting styles to components, some methods are only allowed to certain component types:

  1. component.setClassName("edu-login-header"). In this case, the style is in line 27.
  2. component.getStyle().set("font-size", "150%").set("text-align", "center"). It is used in a label. You can concatenate "sets".
  3. component.setWidth("15em"). In this casse it is applied to a combo.
If the setClassName() method of the components is ignored by Vaadin then you should try the options 2 and 3.


4. Analyzing the Lofinform.css file


Here is a snippet of code showing an image in the background with transparency and gradient. Note that it did not work well on all browsers, so some alternatives have been used to offset this handicap.


1
2
3
4
5
6
7
/** Water image: Chrome needs url reltives from app while other url are relatives from css file */
     background: linear-gradient(to bottom right, rgba(255,255,255,.3), rgba(255,255,255,.99)),
                 url("../img/enterprise/enterprise02.jpeg"), /* GOOD in eclipse; BAD in chrome*/ 
                 url("frontend/img/enterprise/enterprise02.jpeg"); /* BAD in eclipse; GOOD in chrome*/
     background-position: center; /* Center the image */
        background-repeat: no-repeat; /* Do not repeat the image */
        background-size: cover; /* Resize the background image to cover the entire container */            

The rest of the details include common tags as : margin, border....

5. The LoginForm class with style.
Here is the new code of the class


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 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
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
package openadmin.ui;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.Html;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.dependency.HtmlImport;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.PasswordField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.router.PageTitle;
import com.vaadin.flow.router.Route;

import openadmin.session.SessionData;
import openadmin.utils.VaadinUtils;


@Route("")
@PageTitle("Login")
@HtmlImport("css/LoginForm.css")
@SuppressWarnings("serial")
public class LoginForm extends VerticalLayout implements II18nChange{
 private TextField userName;
 private PasswordField password;
 private Button login;
 private LocaleCombo langCombo;
 private Label lblUserName;
 private Label lblPassword;
 private Label lTitle;
 private Image imageLang;
 
 @Inject
 private SessionData sesData;
 
 public LoginForm() {
 }
 
 /**
  * Initialization
  */
 @PostConstruct
 private void init() {
  setClassName("edu-login");
  add(getHeaderPanel());
  add(getLangSelectorPanel());
  add(getLoginPanel());
 }
 
 
 /** Enterprise header **/
 private HorizontalLayout getHeaderPanel() {
 
  HorizontalLayout headerPanel = new HorizontalLayout();
  headerPanel.setClassName("edu-login-header");
  
  Image logo = new Image("frontend/img/enterprise/enterprise05.jpeg", "logo");
  headerPanel.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER, logo);
  headerPanel.add(logo);
  
  HorizontalLayout title = new HorizontalLayout();
  title.setJustifyContentMode(FlexComponent.JustifyContentMode.CENTER);
  
  lTitle=new Label(getTranslation ("main.enterprise"));
  lTitle.getStyle()
   .set("font-size", "150%")
   .set("text-align", "center");
  
  headerPanel.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER, lTitle);
  title.add(lTitle);
  title.setClassName("edu-login-title");
  headerPanel.add(title);
  return headerPanel;
 }

 private HorizontalLayout getLangSelectorPanel() {
  
  HorizontalLayout langSelPanel = new HorizontalLayout();
  langSelPanel.setClassName("edu-login-lang");
  langSelPanel.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
  
  // 1. Language ComboBox.
  langCombo = new LocaleCombo(sesData, this);
  langCombo.setWidth("15em");
  langCombo.setClassName("edu-langcombo");
  langCombo.getStyle().set("font-weight","bold");
  
  
  langSelPanel.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER, langCombo);
  langSelPanel.add(langCombo);
    
  // 2.Flag Icon
  imageLang = new Image("frontend/icon/flags/" + sesData.getLangEnum().name() + ".png", "language");
  //imageLang = new Image("frontend/icon/flags/" + lEnum.name() + ".png", "language");  // Jetty
  imageLang.getStyle().set("vertical-align", "middle").set("padding-left", "25");
  
  
  langSelPanel.setVerticalComponentAlignment(FlexComponent.Alignment.CENTER, imageLang);
  langSelPanel.add(imageLang);

  return langSelPanel;
 }
 
 private Component getLoginPanel() {
         
        VerticalLayout loginPanel= new VerticalLayout();
        loginPanel.setClassName("edu-login-login");
        
        VerticalLayout loginForm = new VerticalLayout();
        loginForm.setWidth("300px");
  
        // 1. User
        lblUserName = new Label(getTranslation ("login.user"));
  userName=new TextField();
  userName.setValue("admin");
  userName.setWidth("5em");
  loginForm.add(lblUserName, userName);
   
  //2. Password
  lblPassword = new Label(getTranslation("login.password"));
  password = new PasswordField();
  password.setWidth("15em");
  loginForm.add(lblPassword, password);
  
  
  //3. Line separation
  loginForm.add(new Html("<br/>"));
  
  //4. Buttons layout
  HorizontalLayout buttonsLay = new HorizontalLayout();
  buttonsLay.setClassName("edu-login-buttons");
  buttonsLay.setJustifyContentMode(FlexComponent.JustifyContentMode.END);
  loginForm.add(buttonsLay);
  
  buttonsLay.add(login = new Button(getTranslation("login.login"), VaadinIcon.SIGN_IN.create()));
  
  //5. Login button
  login.addClickListener(event -> login()); //assign action to button
  login.addThemeVariants(ButtonVariant.LUMO_PRIMARY, ButtonVariant.LUMO_PRIMARY);
  
  //6 Keyboard event listeners 
  loginForm.getElement().addEventListener("keypress", event -> login()).setFilter("event.key == 'Enter'");
  loginPanel.setHorizontalComponentAlignment(FlexComponent.Alignment.CENTER, loginForm);
  loginPanel.add(loginForm);
  
  return loginPanel;
 }
 
 /**
  * Try to log in if credentials are correct 
  */
 private void login() {
  if (userName.getValue().length()<1 || password.getValue().length()<1) {
   showNotification("login.invalid_credentials", 2000);
   userName.focus();
  
  // usr & password credentials 
  }else if (userName.getValue().equals("user") && password.getValue().equals("password")) {
   VaadinUtils.setSessionAttribute("CURRENT_USER", userName.getValue());
   getUI().get().navigate("main");
   
  }else {
   showNotification("login.invalid_credentials", 2000);
   userName.focus();
  }
 }

 /**
  * Show notification 
  * @param i18nKey
  * @param duration
  */
 public void showNotification(String i18nKey, int duration) {
  String translatedMessage=this.getTranslation(i18nKey);
  Notification not=new Notification(translatedMessage);
  not.setDuration(duration);
  not.open();
 }
 /**
  * Change labels according to Locale
  */
 @Override
 public void changeI18nLabels() {
  lTitle.setText(getTranslation ("main.enterprise"));
  lblUserName.setText(getTranslation("login.user"));
  lblPassword.setText(getTranslation("login.password"));
  login.setText(getTranslation("login.login"));
  imageLang.setSrc("frontend/icon/flags/" + sesData.getLangEnum().name() + ".png");
  //imageLang.setSrc("frontend/icon/flags/" + lEnum.name() + ".png");  //Jetty
 }
}

and here is the output.


Happy codding

No hay comentarios:

Publicar un comentario