Chapter 4. The Logout and Multilingual Capabilities

In this chapter, we are going to implement the multilingual capability of the system. This feature will allow the system to display the translation of the labels according to the language selected by the user (using some HTML5 features as well).

We will also learn how to implement the logout capability so that the user can end the session, and also for security reasons, we will learn how to implement a session timeout warning for the user, in the case of inactivity (not using the mouse or keyboard for a while).

Also, after the user is authenticated, we need to display the application. In this chapter, we will learn how to implement the base of the application.

So, in this chapter, we will cover:

  • The base of the application
  • The logout capability
  • Activity monitoring and session timeout warnings
  • Structuring the application to receive the multilingual capability
  • Creating the change language component
  • Handling the change language component at runtime

While we cover all the application capabilities, we will cover some Ext JS components as well.

The base of the application – view/main/Main.js

When we implemented the success function in the Submit button listener on the login controller, we mentioned the Packt.view.main.Main class. We are going to reuse this class (it was automatically created by Sencha Cmd when we created the project) as the base of our application. Before we start with the hands-on approach, let's take a look at what is going to be the result of the application by the end of this chapter:

The base of the application – view/main/Main.js

The Viewport

Whenever we construct an application entirely with Ext JS (because we do have the option of using a single component rendered to a <div> tag if we want to, in a manner similar to what is done in jQuery), we need to use a component that is going to be the base of the application. This component is the Viewport. The Viewport is a specialized container representing the viewable application area (the browser viewport). The Viewport renders itself to the document body, and automatically sizes itself to the size of the browser viewport and manages window resizing. There might only be one Viewport created in an application.

Before we create the Viewport, if we click on the Submit button of the Login screen, we will see a grayish screen, even though we are calling Ext.create('Packt.view.main.Main'), inside the LoginController class. This means Packt.view.main.Main is being created, but nothing is being displayed on the screen. This is because the Main class is not being rendered as a child of any component, and it is also not being rendered to the HTML body. But we are going to change this behavior by changing it to a Viewport.

Open the app/view/main/Main.js file. In the second line of code, you will find the following snippet:

extend: 'Ext.container.Container'

The Main class that was created by Sencha Cmd is extending the Container component. The Container component is the simplest container component in the Ext JS API. It supports adding and removing items to it, and it is also the parent class to many other components, such as Panel, Window, and TabPanel. We are going to change Ext.container.Container to Ext.container.Viewport so that we can use the Main class as the base class of our application. Save the code, refresh the browser, and give it a try. The next time you click on the Submit button, you should see the original code created by Sencha Cmd after you are logged in.

Using the Viewport plugin

Extending the Ext.container.Viewport class is the classic and traditional way of having a Viewport in Ext JS applications. Ext JS 5 introduces a new way of using a Viewport by using the Viewport plugin (Ext.plugin.Viewport).

Note

To learn more about Ext JS plugins, please read http://www.sencha.com/blog/advanced-plugin-development-with-ext-js/.

To use the plugin, first roll back the changes we made in the preceding topic (the Main class will continue to extend Ext.container.Container) and add the following code after the extend code:

Ext.define('Packt.view.main.Main', {
    extend: 'Ext.container.Container',

    plugins: 'viewport',

    xtype: 'app-main',

Using the plugins configuration has the same result as extending the Viewport class. This plugin transforms any component into a Viewport, making it fill all the available space in the browser. The advantage of this plugin is that we can still reuse this class in other contexts, for example, inside a window.

We know that the ptype (plugin type) of the Viewport plugin is viewport by accessing the documentation:

Using the Viewport plugin

Tip

Always remember that the documentation needs to be your best friend while developing Ext JS applications!

Organizing the main screen using the Border layout

As we learned in Chapter 1, Sencha Ext JS Overview, the Border layout can be used to organize the children of a parent container into five regions: north, south, west, east, and center.

The center region is the only one that is mandatory to have. The other ones are optional. Looking at the following screenshot, we can see that we are going to organize our main screen into four regions: center, north, south, and west:

Organizing the main screen using the Border layout

Let's take a look at the items configuration of the Main class (you can replace the code that was generated by Sencha Cmd with the following code):

items: [{
    region: 'center',   // #1
    xtype: 'mainpanel'
},{
    xtype: 'appheader', // #2
    region: 'north'
},{
    xtype: 'appfooter', // #3
    region: 'south'
},{
    xtype: 'container', // #4
    region: 'west',
    width: 200,
    split: true
}]

In the center region, we have mainpanel (#1). In Chapter 5, Advanced Dynamic Menu, we are going to create a dynamic menu that will give the options to the user to open the screens the user is entitled to. Each screen the user opens will be created as a tab in mainpanel. We will create it in a minute.

In the north region, we have the header (#2), and in the south region, we have the footer (#3). We will also work on them in a minute.

In the west region, we have container (#4), which we will use in the next chapter to render the dynamic menu. For now, we will leave the space reserved for it.

It is important to know that for the center region, we do not need to specify width or height. The container that is being rendered in the center region is going to use whatever space is left in the Border layout. For the south and north regions, you are required to specify height. We will do this when we create Header and Footer. The south and north regions are going to use all the available horizontal space that is available in the screen—limited by height—which is why width is not required. For the west and east regions, it is required to specify width. As we are only using the west region, we specified 200 pixels (#4).

Creating the main TabPanel component

We need to create the mainpanel component that we are using in the center region of the Main class. To do so, we are going to create a new file named Panel.js inside the app/view/main folder, and we are going to write the following code inside it:

Ext.define('Packt.view.main.Panel', { // #1
    extend: 'Ext.tab.Panel',          // #2
    xtype: 'mainpanel',             // #3

    activeTab: 0,                     // #4

    items: [
        {
            xtype: 'panel',                      // #5
            closable: false,                     // #6
            iconCls: 'fa fa-home fa-lg tabIcon', // #7
            title: 'Home'          // #8 
        }
    ]
});

As usual, we will start with the name of the class. The class name convention is app namespace + folder (inside app) + filename (without the .js extension), which will result in Packt.view.main.Panel (#1). The main.Panel class is extending the TabPanel component (#2).

In line #3, we have xtype of the main.Panel class. This is the xytpe class we used to instantiate this class inside the Main class. In line #4, we have the activeTab configuration. When we set a tab to active, the TabPanel component is going to display the contents of the tab, and it is also going to highlight it.

As we learned in Chapter 1, Sencha Ext JS Overview, the TabPanel component is a container that has tabs as children organized by the Card layout, which means that the user will see the content of one active tab at a time. Each child declared inside the items configuration is an instance of the tab class (Ext.tab.Tab), and it can be of any type as we have in line #5. So as not to display an empty screen, we are displaying a 'Home' tab (#8) that is a panel (#5), which means it can have toolbars and other components inside it as well. This Home tab cannot be closed (#6); otherwise, the user will see a blank space in the middle of the main screen, and we do not want that. We are also setting a Font Awesome icon in the format of home in line #7 for it to look prettier.

You can use this Home tab to display announcements or to behave like a dashboard, where the user will see a summary of all the pending tasks.

Creating the footer

The next step is creating the footer of the main screen. We are going to create a new file named Footer.js inside app/view/main with the following code inside it:

Ext.define('Packt.view.main.Footer', {
    extend: 'Ext.container.Container', //#1
    xtype: 'appfooter',                //#2

    cls: 'app-footer',                 //#3

    height: 30,                        //#4

    layout: 'center',                  //#5

    items: [
        {
            xtype: 'component',               //#6
            width: 350,                       //#7
            componentCls: 'app-footer-title', //#8
            bind: {
                html: '{footer}'              //#9
            }
        }
    ]
});

Footer is going to extend from the Container class (#1). The Container class is the lightest component that we can create that can have items inside it. We should give preference to use it whenever possible. We will discuss this in greater detail later. Then, we declare the xtype class (#2), which is the alias we are using to instantiate this class in the Main class.

Tip

Always remember that the convention for aliases (xtype) is to use all letters in lowercase. If you would like to, you can separate words with "-" (a hyphen) depending on your personal preference.

If we look at the first image of this chapter, we will note that the footer has a top border. We add a style on line #3 that adds this border to the footer. The cls configuration allows us to add extra CSS to a component in Ext JS. It is available to all components. We will add the style to our CSS in a minute.

As we are declaring Footer in the south region of the Main class, you are required to set the height parameter. We can do this inside the Footer class or inside the Main class when declaring the south region. In this case, we are setting it inside the Footer class (#4).

Inside the Footer class, we want to have only one component in this example, which is text (you can use a copyright message), and we are going to display it using HTML. We also want this text to be centered. For this reason, we can use the center layout (#5). To use the center layout, the parent container needs to have only one child component (because it inherits from the fit layout, which only supports a single child as well). It is also required to declare the width parameter of the child component (#7); in this case, the text we are going to display is approximately 350 pixels wide.

Note

In Ext JS 4, the Center layout was used as a UX plugin shipped with the Ext JS SDK. In Ext JS 5, this layout was promoted to the native API, but it kept backwards compatibility. In the layout configuration, you can use center (introduced in Ext JS 5) and also keep using ux.center (from Ext JS 4) if you are migrating an application from Ext JS 4 to 5.

To render the HTML, we are going to use the lightest and simplest component as possible, which is component (#6). As we also want to apply some CSS to our text, we are going to use the componentCls (#8) class, which is a CSS class that is added to a component's root-level element.

Note that there is no text declared anywhere inside the Footer class. Instead, we are binding the html configuration to a value (#9) named footer. This is also part of the new MVVM architecture that we are also going to use in this chapter. In the preceding chapter, we only used the View and ViewController classes for the login capability. In this chapter, we are going to use the complete feature: View, ViewController, and ViewModel from the MVVM architecture (Sencha Cmd already generated these classes when we created the project, so we better reuse them!). For now, keep in mind that this is part of the ModelView binding that we will dive into in the next topic.

A quick word about modular CSS

Let's discuss another way of adding CSS to our application. We already know that the best practice to add CSS to our application is to add using Sass inside the sass/etc folder as we did in the previous examples. However, there are some styles that we create to apply to specific components, and we are not going to reuse them throughout the application. Instead of adding these CSS styles to our all.scss file and having a big file that can give us a headache later if we need to maintain it, we can use a more modular CSS approach to create specific CSS for our Ext JS views.

Inside the sass folder, create a new folder named src (if it has not been created by Sencha Cmd automatically), and inside src, create a new folder named view. Inside view, create a new folder named main. We will have the directory sass/src/view/main. Inside this directory, create a file named Footer.scss with the following content inside it:

$packt-footer-text-color: rgb(11, 103, 196); //#1

.app-footer-title {
  color: $packt-footer-text-color; //#2
  font-size: 12px;
  font-weight: bold;
}

.app-footer {
  border-top: 1px solid darken($packt-footer-text-color, 15); //#3
}

In line #1, we declare a Sass variable with a bluish color (the same blue color as the TabPanel background). We are reusing this variable in lines #2 and #3 in the styles we created to use in our Footer class.

Note

In line #3, we use the darken function from Sass, which accepts a color and a number from 0-100, the percentage to which we want to make the color darker. For more information, please refer to the Sass documentation at http://goo.gl/JsAnVz.

The view/main/Footer.scss file has the same path as the view/main/Footer.js file. Note that this way, it is easier to maintain the styles specific to the Footer class. We will do the same for the Header class in the next topic. We separate the CSS into modules for it to be easier to read and maintain, and when we do the build, all the CSS will be concatenated into a single production CSS file—this is called modular CSS. See, developing applications with Ext JS is not all about Ext JS; we can apply the knowledge from other frontend technologies as well!

Creating the Header class

Next, we are going to create the Header class. The Header class contains the logo of the application along with the application name, the dropdown that offers the translation capability, and the Logout button. To create the header, we are going to create a new file, Header.js, inside the app/view/main folder with the following code:

Ext.define('Packt.view.main.Header', {
    extend: 'Ext.toolbar.Toolbar', //#1
    xtype: 'appheader',            //#2

    requires: [
        'Packt.view.locale.Translation' //#3
    ],

    ui: 'footer',                       //#4

    items: [{
            xtype: 'component',         //#5
            bind: {                     //#6
                html: '{appHeaderIcon}' 
            }
        },{
            xtype: 'component',
            componentCls: 'app-header-title', //#7
            bind: {                           //#8
                html: '{appName}'
            }
        },{
            xtype: 'tbfill'           //#9
        },{
            xtype: 'translation'      //#10
        },{
            xtype: 'tbseparator'      //#11
        },{
            xtype: 'button',          //#12
            itemId: 'logout',         //#13
            text: 'Logout',         
            reference: 'logout',      //#14
            iconCls: 'fa fa-sign-out fa-lg buttonIcon', //#15
            listeners: {  
                click: 'onLogout'  //#16
            }
        }
    ]
});

Our Header class is going to extend the Toolbar class (#1). The Toolbar class is usually used inside panels and its subclasses (grid, form, tree) to organize buttons, but it can also be used to hold other components as we are going to do in this example. We will cover more about toolbars in other chapters as well. We are also declaring an xtype class for the Header class that we are making a reference to in the Main class (#2).

Whenever we use an xtype class created by ourselves, Ext JS does not understand what component we are trying to instantiate. For this reason, we require the class we are referring to. For example, in line #3, we reference the class of the translation component we are instantiating using its xtype class in line #10. We are going to develop this component later in the chapter.

Note

Note that in the Main class, we did not use requires yet. We need to go back and add the required Header, Footer, and main.Panel classes.

The ui configuration allows us to use a specific theme for a component. The Toolbar component has the configuration ui: 'footer' (#4), which gives the toolbar a transparent background. The footer value is included in the Ext JS SDK, and it makes the toolbar transparent. We are going to create some custom ui configurations when we discuss themes later in this book.

The two first children items of the Header class are the icon (#5) and the application name. For the icon, we are going to use Font Awesome to display an icon in the format of a desktop. For the title of the application, we will use the same approach we used in the case of the Footer class. We are also using a componentCls configuration (#7) to style it. We get both values (icon-#6 and application name-#8) from the ViewModel, which we will cover in a minute.

The next item is a toolbar fill (#9). This component will align the translation (#10) and logout buttons (#13) to the right, filling the Toolbar class with space in the middle (between the application title and the buttons).

Note

Instead of { xtype: 'tbfill' }, we could also use '->' as a shortcut.

We also have the logout button declared on line #12. We are going to assign itemId so that we can reference this button globally by the application. We will need it when we work with the session monitor capability. The itemId needs to be unique in its scope; in this case, it needs to be unique within this class, but it is going to be even better if it is unique at the application level.

As we are going to use the ViewController class to handle the logout, we will declare a reference (#14) to make it easier to retrieve the button reference inside the ViewController class, and we are also going to declare the listener (#16), which means that the onLogout function from the ViewController class is going to be executed when we click on the Logout button.

We are also setting an icon to the Logout button from Font Awesome (#15). By default, the icon will have the color black. The button text is white, and we want the icon to have the same color as the text. For this reason, we add a custom style (buttonIcon).

At last, we have the toolbar separator declared on line #11. This simply adds a separator ("|") between the buttons.

Note

Likewise, tbfill, the toolbar separator, also has a shortcut. Instead of { xtype: ' tbseparator' }, we could also use '-'.

Creating the Header CSS

Just as we did with the Footer class, we are also going to create a filename, Header.scss, inside the sass/view/main folder with the following content inside it:

$packt-header-text-color: #2a3f5d;

.app-header-logo {
  color: $packt-header-text-color;
}

.app-header-title {
  padding: 5px 0 5px 3px;
  color: $packt-header-text-color;
  font-size: 18px;
  font-weight: bold;
}

The app-header-logo was created to customize the color of the icon to be the same as the application title. We are using the Sass variable inside both styles. The text color of the title is a dark blue.

Customizing the Font Awesome icon colors

By default, the Font Awesome icons will be displayed in black. But we want some of the icons to have the same color as our theme. We can do this customization using CSS as well.

We have declared two styles to customize the Font Awesome icons until now. The first one was inside the Panel class (tabIcon), and the second one is the Logout button (buttonIcon). So we also need to add these styles to our CSS. To follow the modular CSS approach, let's create a new file, iconColors.scss, under sass/etc with the following content:

$packt-button-icon-color: #fff;
$packt-tab-icon-color: rgb(11, 103, 196);

.tabIcon {
  color: $packt-tab-icon-color;
}

.buttonIcon {
  color: $packt-button-icon-color;
}

Tip

We will get used to using Sass variables to make our life easier if we decide to customize the Ext JS theme later!

Then, all we need to do is import this file in the all.scss file:

@import "fontAwesome/font-awesome";
@import "iconColors";

The main screen and MVVM

Now, it's time to put everything together. Let's take a look at how the Main class looks with the complete code:

Ext.define('Packt.view.main.Main', {
    extend: 'Ext.container.Container',
    plugins: 'viewport',
    xtype: 'app-main',

    requires: [ //#1        'Packt.view.main.Header',        'Packt.view.main.Footer',        'Packt.view.main.Panel',        'Packt.view.main.MainController',        'Packt.view.main.MainModel'    ],
    
    controller: 'main', //#2
    viewModel: {
        type: 'main' //#3
    },

    layout: {
        type: 'border'
    },

    items: [{
        region: 'center',
        xtype: 'mainpanel'
    },{
        xtype: 'appheader',
        region: 'north'
    },{
        xtype: 'appfooter',
        region: 'south'
    },{
        xtype: 'container',
        region: 'west',
        width: 200,
        split: true
    }]
});

We need to add the requires declaration of all the classes we created (and we are referencing them by their xtype classes) and also the Main ViewModel and Main ViewController class that were already created by Sencha Cmd.

The controller (#2) and viewModel (#3) declarations were already added by Sencha Cmd when we created the project. We are simply reusing them by referencing their types.

The main ViewModel

If we open the MainModel.js file inside the app/view/main folder, we will see some content inside it already. We are going to add more content to it, and the file is going to look as follows:

Ext.define('Packt.view.main.MainModel', { //#1
    extend: 'Ext.app.ViewModel', //#2

    alias: 'viewmodel.main', //#3

    data: {
        name: 'Packt', //#4
        appName: 'DVD Rental Store', //#5
        appHeaderIcon: '<span class="fa fa-desktop fa-lg app-header-logo">', //#6
        footer: 'Mastering ExtJS book - Loiane Groner - http://packtpub.com' //#7
    }
});

Let's start with the name of the class (#1). The naming convention for ViewModel suggested by Sencha is the name of the view (Main) + "Model", resulting in MainModel. A ViewModel extends from the ViewModel class (#2) introduced in Ext JS 5, along with the MVVM architecture. The alias (#3) of a ViewModel is defined by "viewmodel." + the name of the type we want to assign. In this case, Sencha already created this class for us with the type main. That is why we can reference this alias in the View class using the following code:

viewModel: {
    type: 'main'
}

The data configuration allows us to populate values in the ViewModel class. The name field (#4) was created by Sencha Cmd, so we are going to keep it (you can remove it if you want). The appName (#5) and appHeaderIcon (#6) properties are being used by Header and footer (#7) is being used by the Footer class.

MainModel is bound to the Main class (View). Because Header and Footer are items of the Main component, they can also reference MainModel.

This is the simplest way in which we can create the ViewModel class, with prepopulated data. We will provide other advanced examples throughout this book, but we need to start with baby steps!

Note

For more information about ViewModel, data binding, and how to bind different data types, please read the following Sencha guide: http://goo.gl/qta6kH.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset