diff --git a/fhem/www/frontend/CHANGED b/fhem/www/frontend/CHANGED index 402e66ab4..fe792f9f7 100644 --- a/fhem/www/frontend/CHANGED +++ b/fhem/www/frontend/CHANGED @@ -1,3 +1,6 @@ +Update vom 27.6.2013 + * "Database Tables" können jetzt über Zeit und Parameter konkretisiert werden + * Bug aus Zeitsprüngen entfernt, damit zwischen Monatswechsel Datum korrekt angezeigt wird Update vom 01.5.2013 * Performance Verbesserungen der Charts * Statistikberechnungen nach ZoomIn hinzugefügt diff --git a/fhem/www/frontend/controls_frontend.txt b/fhem/www/frontend/controls_frontend.txt index 22ac79da6..6defdfe6f 100644 --- a/fhem/www/frontend/controls_frontend.txt +++ b/fhem/www/frontend/controls_frontend.txt @@ -270,14 +270,15 @@ UPD 2013-03-02_01:53:05 770 www/frontend/app/resources/icons/database_refresh.pn UPD 2013-03-02_01:53:05 524 www/frontend/app/resources/icons/resultset_last.png UPD 2013-04-03_07:27:17 733 www/frontend/app/resources/icons/add.png UPD 2013-04-03_07:27:17 389 www/frontend/app/resources/icons/resultset_previous.png -UPD 2013-05-01_05:09:36 2154 www/frontend/app/app.js +UPD 2013-06-27_09:34:38 2201 www/frontend/app/app.js UPD 2013-05-01_05:10:56 27200 www/frontend/app/view/LineChartPanel.js UPD 2013-04-28_02:00:20 1205 www/frontend/app/view/ChartGridPanel.js UPD 2013-04-03_07:26:40 15793 www/frontend/app/view/DevicePanel.js UPD 2013-05-01_05:10:56 8782 www/frontend/app/view/Viewport.js -UPD 2013-04-01_07:05:14 2476 www/frontend/app/view/TableDataGridPanel.js -UPD 2013-05-01_05:10:42 76820 www/frontend/app/controller/ChartController.js -UPD 2013-05-01_05:10:42 13004 www/frontend/app/controller/MainController.js +UPD 2013-06-27_09:35:22 10042 www/frontend/app/view/TableDataGridPanel.js +UPD 2013-06-27_09:34:51 77454 www/frontend/app/controller/ChartController.js +UPD 2013-06-27_09:34:52 13004 www/frontend/app/controller/MainController.js +UPD 2013-06-27_09:34:52 5414 www/frontend/app/controller/TableDataController.js UPD 2013-04-01_07:04:35 202 www/frontend/app/model/ReadingsModel.js UPD 2013-04-01_07:04:36 338 www/frontend/app/model/SavedChartsModel.js UPD 2013-04-01_07:04:34 11535 www/frontend/app/model/ChartModel.js @@ -286,5 +287,5 @@ UPD 2013-04-01_07:04:34 685 www/frontend/app/model/TableDataModel.js UPD 2013-04-01_07:04:54 432 www/frontend/app/store/ChartStore.js UPD 2013-04-01_07:04:54 451 www/frontend/app/store/SavedChartsStore.js UPD 2013-04-01_07:04:54 426 www/frontend/app/store/ReadingsStore.js -UPD 2013-04-01_07:04:54 1048 www/frontend/app/store/TableDataStore.js +UPD 2013-06-27_09:35:10 657 www/frontend/app/store/TableDataStore.js UPD 2013-04-27_06:11:13 439 www/frontend/app/store/DeviceStore.js \ No newline at end of file diff --git a/fhem/www/frontend/www/frontend/app/app.js b/fhem/www/frontend/www/frontend/app/app.js index 579a66ef3..cb00dfed3 100644 --- a/fhem/www/frontend/www/frontend/app/app.js +++ b/fhem/www/frontend/www/frontend/app/app.js @@ -18,7 +18,8 @@ Ext.application({ controllers: [ 'FHEM.controller.MainController', - 'FHEM.controller.ChartController' + 'FHEM.controller.ChartController', + 'FHEM.controller.TableDataController' ], launch: function() { diff --git a/fhem/www/frontend/www/frontend/app/controller/ChartController.js b/fhem/www/frontend/www/frontend/app/controller/ChartController.js index 5b31acb9f..e46d8c160 100644 --- a/fhem/www/frontend/www/frontend/app/controller/ChartController.js +++ b/fhem/www/frontend/www/frontend/app/controller/ChartController.js @@ -1124,21 +1124,30 @@ Ext.define('FHEM.controller.ChartController', { me.minY2Value = 9999999; var starttime = me.getStarttimepicker().getValue(), - dbstarttime = Ext.Date.format(starttime, 'Y-m-d H:i:s'), endtime = me.getEndtimepicker().getValue(), - dbendtime = Ext.Date.format(endtime, 'Y-m-d H:i:s'); + dynamicradio = Ext.ComponentQuery.query('radiogroup[name=dynamictime]')[0]; if(!Ext.isEmpty(starttime) && !Ext.isEmpty(endtime)) { var timediff = Ext.Date.getElapsed(starttime, endtime); if(btn.name === "stepback") { - me.getEndtimepicker().setValue(starttime); - var newstarttime = Ext.Date.add(starttime, Ext.Date.MILLI, -timediff); - me.getStarttimepicker().setValue(newstarttime); + if (dynamicradio.getValue().rb === "month") { + me.getEndtimepicker().setValue(Ext.Date.getLastDateOfMonth(Ext.Date.add(endtime, Ext.Date.MONTH, -1))); + me.getStarttimepicker().setValue(Ext.Date.add(starttime, Ext.Date.MONTH, -1)); + } else { + me.getEndtimepicker().setValue(starttime); + var newstarttime = Ext.Date.add(starttime, Ext.Date.MILLI, -timediff); + me.getStarttimepicker().setValue(newstarttime); + } me.requestChartData(true); } else if (btn.name === "stepforward") { - me.getStarttimepicker().setValue(endtime); - var newendtime = Ext.Date.add(endtime, Ext.Date.MILLI, timediff); - me.getEndtimepicker().setValue(newendtime); + if (dynamicradio.getValue().rb === "month") { + me.getEndtimepicker().setValue(Ext.Date.getLastDateOfMonth(Ext.Date.add(endtime, Ext.Date.MONTH, +1))); + me.getStarttimepicker().setValue(Ext.Date.add(starttime, Ext.Date.MONTH, +1)); + } else { + me.getStarttimepicker().setValue(endtime); + var newendtime = Ext.Date.add(endtime, Ext.Date.MILLI, timediff); + me.getEndtimepicker().setValue(newendtime); + } me.requestChartData(true); } } diff --git a/fhem/www/frontend/www/frontend/app/controller/MainController.js b/fhem/www/frontend/www/frontend/app/controller/MainController.js index cf96d6f01..cc2a2f44b 100644 --- a/fhem/www/frontend/www/frontend/app/controller/MainController.js +++ b/fhem/www/frontend/www/frontend/app/controller/MainController.js @@ -93,7 +93,7 @@ Ext.define('FHEM.controller.MainController', { if (Ext.isDefined(FHEM.version)) { var sp = this.getStatustextfield(); - sp.setText(FHEM.version + "; Frontend Version: 0.7 - 2013-05-01"); + sp.setText(FHEM.version + "; Frontend Version: 0.8 - 2013-06-27"); } //setup west accordion / treepanel diff --git a/fhem/www/frontend/www/frontend/app/controller/TableDataController.js b/fhem/www/frontend/www/frontend/app/controller/TableDataController.js new file mode 100644 index 000000000..1ec5f8090 --- /dev/null +++ b/fhem/www/frontend/www/frontend/app/controller/TableDataController.js @@ -0,0 +1,137 @@ +/** + * The Controller handling Table Data retrieval + */ +Ext.define('FHEM.controller.TableDataController', { + extend: 'Ext.app.Controller', + requires: [ + 'FHEM.view.TableDataGridPanel' + ], + + refs: [ + { + selector: 'button[name=applytablefilter]', + ref: 'applytablefilterbtn' //this.getApplytablefilterbtn() + } + ], + + /** + * init function to register listeners + */ + init: function() { + this.control({ + 'button[name=applytablefilter]': { + click: this.filterTableData + } + }); + }, + + /** + * function handling the filtering of tabledata, preparing querystring + */ + filterTableData: function() { + + var me = this, + devicecombo = Ext.ComponentQuery.query('combo[name=tddevicecombo]')[0], + readingscombo = Ext.ComponentQuery.query('combo[name=tdreadingscombo]')[0], + checkedradio = Ext.ComponentQuery.query('radiogroup[name=tddynamictime]')[0], + starttimepicker = Ext.ComponentQuery.query('datefield[name=tdstarttimepicker]')[0], + endtimepicker = Ext.ComponentQuery.query('datefield[name=tdendtimepicker]')[0], + gridpanel = Ext.ComponentQuery.query('gridpanel[name=tabledatagridpanel]')[0]; + + //check if timerange or dynamic time should be used + checkedradio.eachBox(function(box, idx){ + var date = new Date(); + if (box.checked) { + if (box.inputValue === "year") { + starttime = Ext.Date.parse(date.getUTCFullYear() + "-01-01", "Y-m-d"); + endtime = Ext.Date.parse(date.getUTCFullYear() + 1 + "-01-01", "Y-m-d"); + } else if (box.inputValue === "month") { + starttime = Ext.Date.getFirstDateOfMonth(date); + endtime = Ext.Date.getLastDateOfMonth(date); + } else if (box.inputValue === "week") { + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + //monday starts with 0 till sat with 5, sund with -1 + var dayoffset = date.getDay() - 1, + monday, + nextmonday; + if (dayoffset >= 0) { + monday = Ext.Date.add(date, Ext.Date.DAY, -dayoffset); + } else { + //we have a sunday + monday = Ext.Date.add(date, Ext.Date.DAY, -6); + } + nextmonday = Ext.Date.add(monday, Ext.Date.DAY, 7); + + starttime = monday; + endtime = nextmonday; + } else if (box.inputValue === "day") { + date.setHours(0); + date.setMinutes(0); + date.setSeconds(0); + starttime = date; + endtime = Ext.Date.add(date, Ext.Date.DAY, 1); + } else if (box.inputValue === "hour") { + date.setMinutes(0); + date.setSeconds(0); + starttime = date; + endtime = Ext.Date.add(date, Ext.Date.HOUR, 1); + } else { + Ext.Msg.alert("Error", "Could not setup the dynamic time."); + } + dbstarttime = Ext.Date.format(starttime, 'Y-m-d_H:i:s'); + dbendtime = Ext.Date.format(endtime, 'Y-m-d_H:i:s'); + + starttimepicker.setValue(starttime); + endtimepicker.setValue(endtime); + } else { + dbstarttime = Ext.Date.format(starttimepicker.getValue(), 'Y-m-d_H:i:s'); + dbendtime = Ext.Date.format(endtimepicker.getValue(), 'Y-m-d_H:i:s'); + } + }); + + if (Ext.isEmpty(dbstarttime) || Ext.isEmpty(dbendtime)) { + Ext.Msg.alert("Error", "Please select a timerange first!"); + } else { + //cleanup store + gridpanel.getStore().clearData(); + + var firststart = true; + + gridpanel.getStore().on("beforeprefetch", function(store, operation, eOpts) { + + var url = '../../../fhem?cmd=get+' + FHEM.dblogname + '+-+webchart+' + dbstarttime + '+' + dbendtime + '+'; + if (!Ext.isEmpty(devicecombo.getValue())) { + url += devicecombo.getValue(); + } else { + url += '""'; + } + + url += '+getTableData+""+'; + if (!Ext.isEmpty(readingscombo.rawValue)) { + url += readingscombo.rawValue; + } else { + url += '""'; + } + url += '+""+""+'; + if (firststart) { + url += "0+"; + firststart = false; + } else { + url += operation.start + "+"; + } + url += operation.limit + "&XHR=1" + + if (operation.request) { + operation.request.url = url; + } + + store.proxy.url = url; + }); + gridpanel.getStore().load(); + + } + } + +}); \ No newline at end of file diff --git a/fhem/www/frontend/www/frontend/app/store/TableDataStore.js b/fhem/www/frontend/www/frontend/app/store/TableDataStore.js index 9ec0224fb..7c70d16d6 100644 --- a/fhem/www/frontend/www/frontend/app/store/TableDataStore.js +++ b/fhem/www/frontend/www/frontend/app/store/TableDataStore.js @@ -5,10 +5,10 @@ Ext.define('FHEM.store.TableDataStore', { extend: 'Ext.data.Store', model: 'FHEM.model.TableDataModel', buffered: true, - trailingBufferZone: 200, - leadingBufferZone: 200, + trailingBufferZone: 1000, + leadingBufferZone: 1000, //remoteGroup: true, - pageSize: 200, + pageSize: 1000, proxy: { type: 'ajax', method: 'POST', @@ -19,12 +19,5 @@ Ext.define('FHEM.store.TableDataStore', { totalProperty: 'totalCount' } }, - autoLoad: true, - listeners: { - beforeprefetch: function(store, operation) { - //override stores url to contain start and limit params in our needed notation - store.proxy.url = '../../../fhem?cmd=get+' + FHEM.dblogname + '+-+webchart+""+""+""'; - store.proxy.url += '+getTableData+""+""+""+""+' + operation.start +'+' + operation.limit +'&XHR=1'; - } - } + autoLoad: false }); \ No newline at end of file diff --git a/fhem/www/frontend/www/frontend/app/view/TableDataGridPanel.js b/fhem/www/frontend/www/frontend/app/view/TableDataGridPanel.js index 5acbce5a7..312f02aa3 100644 --- a/fhem/www/frontend/www/frontend/app/view/TableDataGridPanel.js +++ b/fhem/www/frontend/www/frontend/app/view/TableDataGridPanel.js @@ -17,56 +17,192 @@ Ext.define('FHEM.view.TableDataGridPanel', { var me = this; - var tablestore = Ext.create('FHEM.store.TableDataStore'); - - me.items = [ - { - xtype: 'panel', - items: [ - { - xtype: 'fieldset', - title: 'Configure Database Query', - items: [ - { - xtype: 'displayfield', - value: 'The configuration of the Databasequery will follow here...' - } - ] - }, - { - xtype: 'gridpanel', - height: 400, - collapsible: true, - store: tablestore, - width: '100%', - loadMask: true, - selModel: { - pruneRemoved: false - }, - multiSelect: true, - viewConfig: { - trackOver: false - }, - verticalScroller:{ - //trailingBufferZone: 20, // Keep 200 records buffered in memory behind scroll - //leadingBufferZone: 50 // Keep 5000 records buffered in memory ahead of scroll - }, - columns: [ - { text: 'TIMESTAMP', dataIndex: 'TIMESTAMP' }, - { text: 'DEVICE', dataIndex: 'DEVICE' }, - { text: 'TYPE', dataIndex: 'TYPE' }, - { text: 'EVENT', dataIndex: 'EVENT' }, - { text: 'READING', dataIndex: 'READING' }, - { text: 'VALUE', dataIndex: 'VALUE' }, - { text: 'UNIT', dataIndex: 'UNIT' } - ] - } - ] - } - ]; - me.callParent(arguments); + me.tablestore = Ext.create('FHEM.store.TableDataStore'); + + me.devicestore = Ext.create('FHEM.store.DeviceStore', { + proxy: { + type: 'ajax', + noCache: false, + method: 'POST', + url: '../../../fhem?cmd=get+' + FHEM.dblogname + '+-+webchart+""+""+""+getdevices&XHR=1', + reader: { + type: 'json', + root: 'data', + totalProperty: 'totalCount' + } + }, + autoLoad: true + }); + + me.on("afterlayout", function() { + + me.add( + { + xtype: 'fieldset', + title: 'Configure Database Query', + maxHeight: 150, + items: [ + { + xtype: 'fieldset', + layout: 'column', + defaults: { + margin: '5 5 5 10' + }, + items: [ + { + xtype: 'combobox', + name: 'tddevicecombo', + fieldLabel: 'Select Device', + labelWidth: 90, + store: me.devicestore, + allowBlank: false, + queryMode: 'local', + displayField: 'DEVICE', + valueField: 'DEVICE', + listeners: { + select: function(combo) { + var device = combo.getValue(), + readingscombo = combo.up().down('combobox[name=tdreadingscombo]'), + readingsstore = readingscombo.getStore(), + readingsproxy = readingsstore.getProxy(); + + readingsproxy.url = '../../../fhem?cmd=get+' + FHEM.dblogname + '+-+webchart+""+""+' + device + '+getreadings&XHR=1'; + readingsstore.load(); + readingscombo.setDisabled(false); + } + } + }, + { + xtype: 'combobox', + name: 'tdreadingscombo', + fieldLabel: 'Select Reading', + allowBlank: false, + disabled: true, + labelWidth: 90, + inputWidth: 110, + store: Ext.create('FHEM.store.ReadingsStore', { + proxy: { + type: 'ajax', + method: 'POST', + url: '../../../fhem?cmd=get+' + FHEM.dblogname + '+-+webchart+""+""+-+getreadings&XHR=1', + reader: { + type: 'json', + root: 'data', + totalProperty: 'totalCount' + } + }, + autoLoad: false + }), + displayField: 'READING', + valueField: 'READING' + } + ] + }, + { + xtype: 'fieldset', + layout: 'column', + title: 'Select Timerange', + defaults: { + margin: '0 0 0 10' + }, + items: [ + { + xtype: 'radiofield', + fieldLabel: 'Timerange', + labelWidth: 60, + name: 'tdrb', + checked: true, + inputValue: 'timerange', + listeners: { + change: function(tdrb, newval, oldval) { + if (newval === false) { + tdrb.up().down('datefield[name=tdstarttimepicker]').setDisabled(true); + tdrb.up().down('datefield[name=tdendtimepicker]').setDisabled(true); + } else { + tdrb.up().down('datefield[name=tdstarttimepicker]').setDisabled(false); + tdrb.up().down('datefield[name=tdendtimepicker]').setDisabled(false); + } + } + } + }, + { + xtype: 'datefield', + name: 'tdstarttimepicker', + format: 'Y-m-d H:i:s', + fieldLabel: 'Starttime', + allowBlank: false, + labelWidth: 70 + }, + { + xtype: 'datefield', + name: 'tdendtimepicker', + format: 'Y-m-d H:i:s', + fieldLabel: 'Endtime', + allowBlank: false, + labelWidth: 70 + }, + { + xtype: 'radiogroup', + name: 'tddynamictime', + fieldLabel: 'or select a dynamic time', + labelWidth: 140, + allowBlank: true, + defaults: { + labelWidth: 42, + padding: "0 25px 0 0", + checked: false + }, + items: [ + { fieldLabel: 'yearly', name: 'tdrb', inputValue: 'year' }, + { fieldLabel: 'monthly', name: 'tdrb', inputValue: 'month' }, + { fieldLabel: 'weekly', name: 'tdrb', inputValue: 'week' }, + { fieldLabel: 'daily', name: 'tdrb', inputValue: 'day' }, + { fieldLabel: 'hourly', name: 'tdrb', inputValue: 'hour' } + ] + } + ] + }, + { + xtype: 'button', + text: 'Apply Filter', + name: 'applytablefilter', + width: '120' + } + ] + }, + { + xtype: 'gridpanel', + maxHeight: me.up().getHeight() - 290, + name: 'tabledatagridpanel', + store: me.tablestore, + width: '100%', + loadMask: true, + selModel: { + pruneRemoved: false + }, + multiSelect: true, + viewConfig: { + trackOver: false + }, + verticalScroller:{ + //trailingBufferZone: 20, // Keep 200 records buffered in memory behind scroll + //leadingBufferZone: 50 // Keep 5000 records buffered in memory ahead of scroll + }, + columns: [ + { text: 'TIMESTAMP', dataIndex: 'TIMESTAMP', width: 240, sortable: false }, + { text: 'DEVICE', dataIndex: 'DEVICE', width: '10%', sortable: false }, + { text: 'TYPE', dataIndex: 'TYPE', width: '7%', sortable: false }, + { text: 'EVENT', dataIndex: 'EVENT', width: '20%', sortable: false }, + { text: 'READING', dataIndex: 'READING', width: '12%', sortable: false }, + { text: 'VALUE', dataIndex: 'VALUE', width: '20%', sortable: false }, + { text: 'UNIT', dataIndex: 'UNIT', width: '5%', sortable: false } + ] + } + ); + }, me, {single: true}); + } });