More and more subpages

We know that the other subpage in our application, the SQL log page, is going to be very similar to the web log page. This should be raising an eyebrow with regard to code duplication. We could pull out the grid and the chart header from the Web view into separate classes and turn them into reusable components, but is this the right thing to do? These components won't be reused! They have their place in only one location in the application to power the subpages. Unlike HistoricalRequestChart, which is used in both the dashboard and the subpages, these are only needed for one job.

Let's consider another approach: subclassing. We could create a new component that contains the chart, form fields, and grid from the Web view, and add some configuration options that give us the customization we need. This might look like the following command:

// app/view/SubPage.js
Ext.define('Instrumatics.view.SubPage',{
    extend: 'Ext.Container',

    requires: [
        'Instrumatics.ux.chart.HistoricalRequestChart'
    ],

    xtype: 'subpage',

    config: {

        layout: {
            type: 'vbox',
            align: 'stretch'
        },

        chartCfg: {
            header: {
                items: [
                    { xtype: 'datefield', fieldLabel: 'From', labelAlign: 'right', bind: '{currentStartDate}' },
                    { xtype: 'datefield', fieldLabel: 'To', labelAlign: 'right', bind: '{currentEndDate}', labelWidth: 30 },
                    { xtype: 'button', text: 'Refresh', margin: '0 0 0 10' }
                ]
            },
            margin: 10, xtype: 'historical-request-chart', bind: '{logData}', flex: 1
        },

        gridCfg: {
            xtype: 'grid',
            margin: 10,
            hideHeaders: true,
            viewConfig: {
              trackOver: false
            },
            disableSelection: true,
            header: {
                title: 'Breakdown',
                items: [
                    {
                        xtype: 'combo',
                        labelAlign: 'right', labelWidth: 60,
                        fieldLabel: 'Category',
                        bind: {
                            store: '{categories}',
                            value: '{currentCategory}'
                        },
                        queryMode: 'local',
                        editable: false,
                        forceSelection: true,
                        displayField: 'text',
                        valueField: 'value'
                    }
                ]
            },
            bind: '{logStatistics}',
            flex: 1,
            width: '100%',
            columns: [
                { name: 'Label', dataIndex: 'label', flex: 1 },
                { name: 'Percentage', dataIndex: 'percentage', flex: 1 }
            ]
        }
    },

    initComponent: function(arguments) {
        this.callParent(arguments);
        this.add(this.getChartCfg());
        this.add(this.getGridCfg());
    }
});

We've pulled the entire configuration from the Web view into this base class called SubPage and separated out the key components, namely, the chart and the grid. We're also harnessing the power of the Ext JS class system by wrapping these in the config section, which not only generates get and set methods for gridCfg and chartCfg, but also provides us with a shortcut to override parts of these config objects. Let's demonstrate by showing the SQL view, which is powered by our new SubPage class:

// app/view/sql/Sql.js
Ext.define("Instrumatics.view.sql.Sql",{
    extend: "Instrumatics.view.SubPage",
    xtype: 'sql-logs',
    viewModel: {
        type: "sql-sql"
    },
    chartCfg: {
        title: 'SQL Requests'
    }
});

Yep, that's it! We've managed to get the same functionality that the Web view had, but reusing lots of the code. Note that chartCfg is exposed for us to configure, which means that all we have to do is set viewModel and the chart's title configuration and we're all set.

Turns out we can do the same for the view model too:

    // app/view/SubPageModel.js
Ext.define('Instrumatics.view.SubPageModel', {
    extend: 'Ext.app.ViewModel',
    stores: {
        logData: {
            type: 'logentries',
            autoLoad: true,
            remoteFilter: true,
            filters: [
                { property: 'startDate', value: '{currentStartDate}' },
                { property: 'endDate', value: '{currentEndDate}' }
            ]
        },

        logStatistics: {
            type: 'statistics',
            autoLoad: true,
            remoteFilter: true,
            filters: [
                { property: 'category', value: '{currentCategory}' },
                { property: 'startDate', value: '{currentStartDate}' },
                { property: 'endDate', value: '{currentEndDate}' }
            ]
        }
    },


    data: {
        currentStartDate: null,
        currentEndDate: null
    }
});

And the following SQL view model:

Ext.define('Instrumatics.view.sql.SqlModel', {
    extend: 'Instrumatics.view.SubPageModel',
    alias: 'viewmodel.sql-sql',

    stores: {
        categories: {
            fields: ['text', 'value'],
            data: [{
                text: 'Query Source', value: 'source'
            },{
                text: 'Query Type', value: 'type'
            }]
        }
    },

    data: {
        currentCategory: 'source'
    }
});

The Web and SQL views now share code in a logical way without polluting our UX namespace with classes that don't belong there. In future, we could easily add on more views like this, but for now, we've got a fantastic way to avoid code duplication and keep our application well structured.

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

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