[dss-commits] r8856 - in dss/trunk: . data/webroot data/webroot/js websrc websrc/dss-setup-interface websrc/dss-setup-interface/dSS websrc/dss-setup-interface/dSS/data websrc/dss-setup-interface/dSS/grid
dss-commits at forum.digitalstrom.org
dss-commits at forum.digitalstrom.org
Thu Oct 22 14:35:09 CEST 2009
Author: mfernandez
Date: 2009-10-22 14:35:09 +0200 (Thu, 22 Oct 2009)
New Revision: 8856
Added:
dss/trunk/data/webroot/js/dss-setup-interface.js
dss/trunk/websrc/
dss/trunk/websrc/dss-setup-interface/
dss/trunk/websrc/dss-setup-interface/README
dss/trunk/websrc/dss-setup-interface/dSS/
dss/trunk/websrc/dss-setup-interface/dSS/ZoneBrowser.js
dss/trunk/websrc/dss-setup-interface/dSS/ZonePanel.js
dss/trunk/websrc/dss-setup-interface/dSS/ZoneView.js
dss/trunk/websrc/dss-setup-interface/dSS/data/
dss/trunk/websrc/dss-setup-interface/dSS/data/DeviceStore.js
dss/trunk/websrc/dss-setup-interface/dSS/data/ZoneStore.js
dss/trunk/websrc/dss-setup-interface/dSS/grid/
dss/trunk/websrc/dss-setup-interface/dSS/grid/DevicePanel.js
dss/trunk/websrc/dss-setup-interface/dss-setup-interface.js
Modified:
dss/trunk/data/webroot/js/DataView-more.js
dss/trunk/data/webroot/js/setup.js
dss/trunk/data/webroot/setup.html
Log:
Refurbished setup interface
- now uses sprocktes as build environment http://getsprockets.org/
- redesigned for easy addition of new functionality
Modified: dss/trunk/data/webroot/js/DataView-more.js
===================================================================
--- dss/trunk/data/webroot/js/DataView-more.js 2009-10-20 10:57:50 UTC (rev 8855)
+++ dss/trunk/data/webroot/js/DataView-more.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -1,170 +1,87 @@
Ext.DataView.DragSelector = function(cfg){
- cfg = cfg || {};
-
- var view, proxy, tracker;
-
-var rs, bodyRegion, dragRegion = new Ext.lib.Region(0,0,0,0);
-
-var dragSafe = cfg.dragSafe === true;
-
-
-
-this.init = function(dataView){
-
- view = dataView;
-
- view.on('render', onRender);
-
+ cfg = cfg || {};
+ var view, proxy, tracker;
+ var rs, bodyRegion, dragRegion = new Ext.lib.Region(0,0,0,0);
+ var dragSafe = cfg.dragSafe === true;
+
+ this.init = function(dataView){
+ view = dataView;
+ view.on('render', onRender);
+ };
+
+ function fillRegions(){
+ rs = [];
+ view.all.each(function(el){
+ rs[rs.length] = el.getRegion();
+ });
+ bodyRegion = view.el.getRegion();
+ }
+ function cancelClick(){
+ return false;
+ }
+
+ function onStart(e){
+ //view.on('containerclick', cancelClick, view, {single:true});
+
+ if(!proxy){
+ proxy = view.el.createChild({cls:'x-view-selector'});
+ } else {
+ proxy.setDisplayed('block');
+ }
+ fillRegions();
+ view.clearSelections();
+ }
+
+ function onDrag(e){
+ var startXY = tracker.startXY;
+ var xy = tracker.getXY();
+ var x = Math.min(startXY[0], xy[0]);
+ var y = Math.min(startXY[1], xy[1]);
+ var w = Math.abs(startXY[0] - xy[0]);
+ var h = Math.abs(startXY[1] - xy[1]);
+ dragRegion.left = x;
+ dragRegion.top = y;
+ dragRegion.right = x+w;
+ dragRegion.bottom = y+h;
+ dragRegion.constrainTo(bodyRegion);
+ proxy.setRegion(dragRegion);
+ for(var i = 0, len = rs.length; i < len; i++){
+ var r = rs[i], sel = dragRegion.intersect(r);
+ if(sel && !r.selected){
+ r.selected = true;
+ view.select(i, true);
+ } else if(!sel && r.selected) {
+ r.selected = false;
+ view.deselect(i);
+ }
+ }
+ }
+
+ function onEnd(e){
+ if (!Ext.isIE) {
+ view.un('containerclick', cancelClick, view);
+ }
+ if(proxy){
+ proxy.setDisplayed(false);
+ }
+ }
+
+ function onRender(view){
+ tracker = new Ext.dd.DragTracker();//{preventDefault: true});
+ tracker.on({
+ 'dragstart': {
+ fn: onStart,
+ scope: this
+ },
+ 'drag': {
+ fn: onDrag,
+ scope: this
+ },
+ 'dragend': {
+ fn: onEnd,
+ scope:this
+ }
+ });
+ tracker.initEl(view.el);
+ }
};
-
-
-
-function fillRegions(){
-
- rs = [];
-
- view.all.each(function(el){
-
- rs[rs.length] = el.getRegion();
-
- });
-
- bodyRegion = view.el.getRegion();
-
-}
-
-
-
-function cancelClick(){
-
- return false;
-
-}
-
-
-
-function onBeforeStart(e){
-
- return !dragSafe || e.target == view.el.dom;
-
-}
-
-
-
-function onStart(e){
-
- view.on('containerclick', cancelClick, view, {single:true});
-
- if(!proxy){
-
- proxy = view.el.createChild({cls:'x-view-selector'});
-
- }else{
-
- proxy.setDisplayed('block');
-
- }
-
- fillRegions();
-
- view.clearSelections();
-
-}
-
-
-
-function onDrag(e){
-
- var startXY = tracker.startXY;
-
- var xy = tracker.getXY();
-
-
-
- var x = Math.min(startXY[0], xy[0]);
-
- var y = Math.min(startXY[1], xy[1]);
-
- var w = Math.abs(startXY[0] - xy[0]);
-
- var h = Math.abs(startXY[1] - xy[1]);
-
-
-
- dragRegion.left = x;
-
- dragRegion.top = y;
-
- dragRegion.right = x+w;
-
- dragRegion.bottom = y+h;
-
-
-
- dragRegion.constrainTo(bodyRegion);
-
- proxy.setRegion(dragRegion);
-
-
-
- for(var i = 0, len = rs.length; i < len; i++){
-
- var r = rs[i], sel = dragRegion.intersect(r);
-
- if(sel && !r.selected){
-
- r.selected = true;
-
- view.select(i, true);
-
- }else if(!sel && r.selected){
-
- r.selected = false;
-
- view.deselect(i);
-
- }
-
- }
-
-}
-
-
-
-function onEnd(e){
-
- if (!Ext.isIE) {
-
- view.un('containerclick', cancelClick, view);
-
- }
-
- if(proxy){
-
- proxy.setDisplayed(false);
-
- }
-
-}
-
-
-
-function onRender(view){
-
- tracker = new Ext.dd.DragTracker({
-
- onBeforeStart: onBeforeStart,
-
- onStart: onStart,
-
- onDrag: onDrag,
-
- onEnd: onEnd
-
- });
-
- tracker.initEl(view.el);
-
-}
-
-};
\ No newline at end of file
Added: dss/trunk/data/webroot/js/dss-setup-interface.js
===================================================================
--- dss/trunk/data/webroot/js/dss-setup-interface.js (rev 0)
+++ dss/trunk/data/webroot/js/dss-setup-interface.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,463 @@
+Ext.namespace('dSS', 'dSS.data');
+
+dSS.data.ZoneStore = Ext.extend(Ext.data.Store, {
+ constructor: function(config) {
+ var zoneRecord = Ext.data.Record.create([
+ {name:"name"},
+ {name:"id"}
+ ]);
+
+ var zoneReader = new Ext.data.JsonReader(
+ {
+ root: "zones"
+ },
+ zoneRecord
+ );
+
+ Ext.apply(this, { reader: zoneReader });
+ dSS.data.ZoneStore.superclass.constructor.call(this, arguments);
+ }
+});
+
+Ext.namespace('dSS');
+
+dSS.ZoneView = Ext.extend(Ext.DataView, {
+ initComponent: function() {
+
+ var zoneTemplate = new Ext.XTemplate(
+ '<tpl for=".">',
+ '<div class="zone-wrap {css}" id="zone-{id}">',
+ '<span>{name}</span>',
+ '</div>',
+ '</tpl>',
+ '<div class="x-clear"></div>'
+ );
+
+ var zoneStore = new dSS.data.ZoneStore();
+
+ Ext.apply(this, {
+ store: zoneStore,
+ tpl: zoneTemplate,
+ multiSelect: true,
+ layout: 'fit',
+ style: "overflow: auto",
+ overClass:'x-view-over',
+ itemSelector:'div.zone-wrap',
+ emptyText: 'No Rooms to display',
+ plugins: [
+ new Ext.DataView.DragSelector()
+ ]
+ });
+
+ dSS.ZoneView.superclass.initComponent.apply(this, arguments);
+ this.on(
+ 'selectionchange',
+ function(dv,nodes) {
+ var l = nodes.length;
+ var s = l != 1 ? 's' : '';
+ this.findParentByType('dsszonepanel').setTitle("Zones (" + l + ' zone' + s + ' selected)');
+ this.findParentByType('dsszonebrowser').filterDevices();
+ },
+ this
+ );
+
+ this.on(
+ 'render',
+ function() {
+ var zoneView = this;
+ this.dropZone = new Ext.dd.DropZone(zoneView.getEl(), {
+ ddGroup : "zoneDeviceDD",
+ getTargetFromEvent: function(e) {
+ return e.getTarget(zoneView.itemSelector);
+ },
+ onNodeEnter : function(target, dd, e, data){
+ Ext.fly(target).addClass('my-row-highlight-class');
+ },
+ onNodeOut : function(target, dd, e, data){
+ Ext.fly(target).removeClass('my-row-highlight-class');
+ },
+ onNodeOver : function(target, dd, e, data){
+ return Ext.dd.DropZone.prototype.dropAllowed;
+ },
+ onNodeDrop : function(target, dd, e, data){
+ var record = zoneView.getRecord(target);
+ Ext.each(data.selections, function(device) {
+ var currentDevice = device;
+ Ext.Ajax.request({
+ url: '/json/structure/zoneAddDevice',
+ disableCaching: true,
+ method: "GET",
+ scope: zoneView,
+ params: { devid: currentDevice.data.id,
+ zone: record.data.id
+ },
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ if(jsonData.ok) {
+ currentDevice.set("zone", record.data.id);
+ this.getStore().commitChanges();
+ this.findParentByType('dsszonebrowser').filterDevices();
+ }
+ }
+ catch (err) {
+ Ext.MessageBox.alert('Error', 'Could not move device "' + device.data.dsid + '"');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('Error', 'Could not move device "' + device.data.dsid + '"');
+ },
+ });
+ });
+ return true;
+ }
+ });
+ },
+ this
+ );
+ }
+});
+
+Ext.reg('dsszoneview', dSS.ZoneView);
+
+Ext.namespace('dSS');
+
+dSS.ZonePanel = Ext.extend(Ext.Panel, {
+ initComponent: function() {
+ Ext.apply(this, {
+ title:'Zones',
+ layout: 'border',
+ items: [{ xtype: 'dsszoneview', ref: 'zoneView', region: 'center'}]
+ });
+
+ this.tbar = this.buildTopToolbar();
+
+ dSS.ZonePanel.superclass.initComponent.apply(this, arguments);
+ },
+
+ buildTopToolbar: function() {
+ return ['->',
+ {
+ text: 'New Zone',
+ iconCls: 'newZoneAction',
+ handler: this.createNewZone,
+ scope: this
+ },
+ {
+ text: 'Reload',
+ iconCls: 'reloadAction',
+ handler: this.reload,
+ scope: this
+ }
+ ];
+ },
+
+ createNewZone: function() {
+ var zoneStore = this.zoneView.getStore();
+ Ext.Msg.prompt('Create new zone', 'Name for new Zone:', function(btn, text){
+ if (btn == 'ok'){
+ for(var i = 0; i <= zoneStore.data.length; i++) {
+ if(zoneStore.findExact('id', i) === -1) {
+
+ Ext.Ajax.request({
+ url: '/json/structure/addZone',
+ disableCaching: true,
+ method: "GET",
+ params: { zoneID: i },
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ if(jsonData.ok) {
+
+
+
+ Ext.Ajax.request({
+ url: '/json/zone/setName',
+ disableCaching: true,
+ method: "GET",
+ params: { id: i,
+ newName: text},
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ if(jsonData.ok) {
+
+
+ var newZone = new zoneStore.recordType({id: i, name: text}, i);
+ zoneStore.insert(i, newZone);
+
+
+
+ }
+ }
+ catch (err) {
+ Ext.MessageBox.alert('Error', 'Could not create Zone');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('Error', 'Could not create Zone');
+ },
+ });
+
+
+ }
+ }
+ catch (err) {
+ Ext.MessageBox.alert('Error', 'Could not create Zone');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('Error', 'Could not create Zone');
+ },
+ });
+ return;
+ }
+ }
+ }
+ })
+ },
+ reload: function() {
+ this.ownerCt.loadData();
+ }
+});
+
+Ext.reg('dsszonepanel', dSS.ZonePanel);
+Ext.namespace('dSS', 'dSS.data');
+
+dSS.data.DeviceStore = Ext.extend(Ext.data.Store, {
+ constructor: function(config) {
+ var deviceRecord = Ext.data.Record.create([
+ {name:"name"},
+ {name:"id"},
+ {name:"on"},
+ {name:"circuit"},
+ {name:"modulator"},
+ {name:"zone"}
+ ]);
+
+ var deviceReader = new Ext.data.JsonReader(
+ {
+ root:"devices"
+ },
+ deviceRecord
+ );
+
+ Ext.apply(this, { reader: deviceReader });
+ dSS.data.DeviceStore.superclass.constructor.call(this, arguments);
+ }
+});
+
+Ext.namespace('dSS', 'dSS.grid');
+
+dSS.grid.DevicePanel = Ext.extend(Ext.grid.GridPanel, {
+ initComponent: function() {
+
+ var deviceCols = [
+ {id: 'id', header: "id", width: 50, sortable: true, dataIndex: 'id'},
+ {id: 'name', header: "name", width: 50, sortable: true, dataIndex: 'name', editable: true, editor: new Ext.form.TextField()},
+ {header: "on", width: 50, sortable: true, dataIndex: 'on'},
+ {header: "circuit", width: 50, sortable: true, dataIndex: 'circuit'},
+ {header: "modulator", width: 50, sortable: true, dataIndex: 'modulator'},
+ {header: "zone", width: 50, sortable: true, dataIndex: 'zone'},
+ ];
+
+ var editor = new Ext.ux.grid.RowEditor({
+ saveText: 'Update'
+ });
+
+ editor.on('afteredit', function() {
+ deviceStore.commitChanges();
+ filterDevices();
+ });
+
+ var deviceStore = new dSS.data.DeviceStore();
+
+ Ext.apply(this, {
+ store : deviceStore,
+ columns : deviceCols,
+ ddGroup : "zoneDeviceDD",
+ enableDragDrop : true,
+ stripeRows : true,
+ autoExpandColumn : 'id',
+ title : 'Devices',
+ plugins : [editor]
+ });
+
+ dSS.grid.DevicePanel.superclass.initComponent.apply(this, arguments);
+
+ this.on(
+ 'rowcontextmenu',
+ function() {
+ },
+ this
+ );
+ }
+});
+
+Ext.reg('dssdevicepanel', dSS.grid.DevicePanel);
+
+Ext.namespace('dSS');
+
+dSS.ZoneBrowser = Ext.extend(Ext.Panel, {
+ initComponent: function() {
+
+ Ext.apply(this, {
+ layout: 'border',
+ items: [{
+ xtype: 'dsszonepanel',
+ ref: 'zonePanel',
+ region: 'west',
+ width: 225, // give east and west regions a width
+ minSize: 175,
+ maxSize: 400,
+ split: true
+ },{
+ xtype: 'dssdevicepanel',
+ ref: 'devicePanel',
+ minSize: 400,
+ region: 'center'
+ }
+ ]
+ });
+
+ dSS.ZoneBrowser.superclass.initComponent.apply(this, arguments);
+ this.on(
+ 'afterrender',
+ this.loadData,
+ this
+ );
+
+ },
+ allDevices: undefined,
+ filterDevices: function() {
+ var selectedZones = this.zonePanel.zoneView.getSelectedRecords();
+ if(selectedZones.length === 0) {
+ this.devicePanel.getStore().clearFilter();
+ return
+ }
+ this.devicePanel.getStore().filterBy(function(record) {
+ for(var i = 0; i < selectedZones.length; i++) {
+ if(record.data.zone == selectedZones[i].data.id) {
+ return true;
+ }
+ }
+ return false;
+ });
+ },
+ processStructure: function(structure) {
+ var devices = [], zones = [];
+ Ext.each(structure.apartment.zones, function(zone) {
+ if(zone.id === 0) { // Skip zone 0
+ Ext.each(zone.devices, function(device) {
+ devices.push(device);
+ });
+ }
+ zones.push({
+ id: zone.id,
+ name: zone.id === 0 ? 'Uncategorized' : zone.name
+ });
+ Ext.each(zone.devices, function(device) {
+ for(var i = 0; i < devices.length; i++) {
+ if(devices[i].id == device.id) {
+ devices[i].zone = zone.id;
+ }
+ }
+ });
+ });
+ this.zonePanel.zoneView.getStore().loadData({zones: zones});
+ this.allDevices = devices;
+ },
+ processCircuits: function(circuits) {
+ Ext.each(this.allDevices, function(device) {
+ var circuitID = device.circuitID;
+ for( var i = 0; i < circuits.length; i++) {
+ if(circuits[i].busid == circuitID) {
+ device.circuit = circuits[i].name;
+ device.modulator = circuits[i].dsid;
+ }
+ }
+ });
+ var deviceStore = this.devicePanel.getStore();
+ deviceStore.loadData({devices: this.allDevices});
+ if(this.zonePanel.zoneView.getStore().getCount() > 1) {
+ this.zonePanel.zoneView.select(1);
+ } else {
+ this.zonePanel.zoneView.select(0);
+ }
+ },
+ loadStructure: function() {
+ Ext.Ajax.request({
+ url: '/json/apartment/getStructure',
+ disableCaching: true,
+ method: "GET",
+ scope: this,
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ this.processStructure(jsonData);
+ }
+ catch (err) {
+ Ext.MessageBox.alert('AJAX Error', 'Error loading apartment structure: "' + err + '"');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('AJAX Error', 'Could not load "' + request.url + '"');
+ },
+ });
+ },
+ loadCircuits: function() {
+ Ext.Ajax.request({
+ url: '/json/apartment/getCircuits',
+ disableCaching: true,
+ method: "GET",
+ scope: this,
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ this.processCircuits(jsonData.result.circuits);
+ }
+ catch (err) {
+ Ext.MessageBox.alert('AJAX Error', 'Could not load circuits: "' + err + '"');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('AJAX Error', 'Could not load "' + request.url + '"');
+ },
+ });
+ },
+ loadData: function() {
+ this.loadStructure();
+ this.loadCircuits();
+ }
+
+});
+
+Ext.reg('dsszonebrowser', dSS.ZoneBrowser);
+
+Ext.onReady(function(){
+ Ext.get('start').remove();
+ var viewport = new Ext.Viewport({
+ layout: 'border',
+ items: [
+ {
+ xtype: 'box',
+ region: 'north',
+ height: 32, // give north and south regions a height
+ autoEl: {
+ tag: 'div',
+ html:'<h1>digitalSTROM Setup</h1>'
+ }
+ }, {
+ region: 'center',
+ xtype: 'tabpanel',
+ activeItem: 0,
+ items: [
+ {
+ title: 'Zones',
+ xtype: 'dsszonebrowser',
+ ref: 'zonebrowser'
+ }
+ ]
+ }]
+ });
+});
Modified: dss/trunk/data/webroot/js/setup.js
===================================================================
--- dss/trunk/data/webroot/js/setup.js 2009-10-20 10:57:50 UTC (rev 8855)
+++ dss/trunk/data/webroot/js/setup.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -29,19 +29,28 @@
// create the data store
var deviceStore = new Ext.data.Store({
fields : deviceFields,
- reader : deviceReader//,
- // data: deviceData
+ reader : deviceReader
});
var deviceCols = [
{id: 'id', header: "id", width: 50, sortable: true, dataIndex: 'id'},
- {id: 'name', header: "name", width: 50, sortable: true, dataIndex: 'name'},
+ {id: 'name', header: "name", width: 50, sortable: true, dataIndex: 'name', editable: true, editor: new Ext.form.TextField()},
{header: "on", width: 50, sortable: true, dataIndex: 'on'},
{header: "circuit", width: 50, sortable: true, dataIndex: 'circuit'},
{header: "modulator", width: 50, sortable: true, dataIndex: 'modulator'},
{header: "zone", width: 50, sortable: true, dataIndex: 'zone'},
];
+ var editor = new Ext.ux.grid.RowEditor({
+ saveText: 'Update'
+ });
+
+ editor.on('afteredit', function() {
+ console.log('a device has been edited');
+ deviceStore.commitChanges();
+ filterDevices();
+ });
+
var deviceGrid = new Ext.grid.GridPanel({
store : deviceStore,
columns : deviceCols,
@@ -51,9 +60,14 @@
autoExpandColumn : 'id',
width : 500,
region : 'center',
- title : 'Devices'
+ title : 'Devices',
+ plugins : [editor]
});
+ deviceGrid.on('rowcontextmenu', function() {
+ console.log('rowcontextmenu');
+ });
+
var zoneRecord = Ext.data.Record.create([
{name:"name"},
{name:"id"}
@@ -105,10 +119,27 @@
zonePanel.setTitle("Zones (" + l + ' zone' + s + ' selected)');
filterDevices();
}
+ },
+ containerclick: {
+ fn: function() {
+ console.log('container click');
+ }
+ },
+ click: {
+ fn: function() {
+ console.log('click event');
+ }
}
}
});
+ zoneView.on('contextmenu', function() {
+// e.stopEvent();
+ console.log("context");
+// e.preventDefault();
+ }
+ );
+
function filterDevices() {
var selectedZones = zoneView.getSelectedRecords();
if(selectedZones.length === 0) {
@@ -136,7 +167,7 @@
var createZoneAction = new Ext.Action({
text: "New Zone",
handler: function() {
- Ext.Msg.prompt('Name', 'Name:', function(btn, text){
+ Ext.Msg.prompt('Create new zone', 'Name for new Zone:', function(btn, text){
if (btn == 'ok'){
for(var i = 0; i <= zoneStore.data.length; i++) {
if(zoneStore.findExact('id', i) === -1) {
Modified: dss/trunk/data/webroot/setup.html
===================================================================
--- dss/trunk/data/webroot/setup.html 2009-10-20 10:57:50 UTC (rev 8855)
+++ dss/trunk/data/webroot/setup.html 2009-10-22 12:35:09 UTC (rev 8856)
@@ -4,10 +4,16 @@
<title>digitalStrom Setup</title>
<link rel="stylesheet" type="text/css" href="js/lib/extjs/resources/css/ext-all.css" />
+
+ <!-- ExtJS libraries -->
<script type="text/javascript" src="js/lib/extjs/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="js/lib/extjs/ext-all.js"></script>
+
+ <!-- ExtJS extensions -->
<script type="text/javascript" src="js/DataView-more.js"></script>
- <script type="text/javascript" src="js/setup.js"></script>
+ <script type="text/javascript" src="js/lib/extjs/examples/ux/RowEditor.js"></script>
+
+ <script type="text/javascript" src="js/dss-setup-interface.js"></script>
<style>
.zone-wrap{
margin: 4px;
@@ -41,7 +47,7 @@
</style>
</head>
<body>
- <h1>digitalSTROM Setup</h1>
- <div id="panel"></div>
+ <!-- <h1>digitalSTROM Setup</h1> -->
+ <div id="start">loading ...</div>
</body>
</html>
\ No newline at end of file
Added: dss/trunk/websrc/dss-setup-interface/README
===================================================================
--- dss/trunk/websrc/dss-setup-interface/README (rev 0)
+++ dss/trunk/websrc/dss-setup-interface/README 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,10 @@
+This is the setup interface for the digitalSTROM server.
+
+It is written in JavaScript and is based on the extjs JavaScript
+library, see http://www.extjs.com/
+
+Use "sprockets" to build it (see http://getsprockets.org/).
+
+$ sprocketize -I ./ dss-setup-interface.js > out.js
+
+and then copy out.js to where you want.
\ No newline at end of file
Added: dss/trunk/websrc/dss-setup-interface/dSS/ZoneBrowser.js
===================================================================
--- dss/trunk/websrc/dss-setup-interface/dSS/ZoneBrowser.js (rev 0)
+++ dss/trunk/websrc/dss-setup-interface/dSS/ZoneBrowser.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,140 @@
+//= require <dSS/ZonePanel>
+//= require <dSS/grid/DevicePanel>
+
+Ext.namespace('dSS');
+
+dSS.ZoneBrowser = Ext.extend(Ext.Panel, {
+ initComponent: function() {
+
+ Ext.apply(this, {
+ layout: 'border',
+ items: [{
+ xtype: 'dsszonepanel',
+ ref: 'zonePanel',
+ region: 'west',
+ width: 225, // give east and west regions a width
+ minSize: 175,
+ maxSize: 400,
+ split: true
+ },{
+ xtype: 'dssdevicepanel',
+ ref: 'devicePanel',
+ minSize: 400,
+ region: 'center'
+ }
+ ]
+ });
+
+ dSS.ZoneBrowser.superclass.initComponent.apply(this, arguments);
+ this.on(
+ 'afterrender',
+ this.loadData,
+ this
+ );
+
+ },
+ allDevices: undefined,
+ filterDevices: function() {
+ var selectedZones = this.zonePanel.zoneView.getSelectedRecords();
+ if(selectedZones.length === 0) {
+ this.devicePanel.getStore().clearFilter();
+ return
+ }
+ this.devicePanel.getStore().filterBy(function(record) {
+ for(var i = 0; i < selectedZones.length; i++) {
+ if(record.data.zone == selectedZones[i].data.id) {
+ return true;
+ }
+ }
+ return false;
+ });
+ },
+ processStructure: function(structure) {
+ var devices = [], zones = [];
+ Ext.each(structure.apartment.zones, function(zone) {
+ if(zone.id === 0) { // Skip zone 0
+ Ext.each(zone.devices, function(device) {
+ devices.push(device);
+ });
+ }
+ zones.push({
+ id: zone.id,
+ name: zone.id === 0 ? 'Uncategorized' : zone.name
+ });
+ Ext.each(zone.devices, function(device) {
+ for(var i = 0; i < devices.length; i++) {
+ if(devices[i].id == device.id) {
+ devices[i].zone = zone.id;
+ }
+ }
+ });
+ });
+ this.zonePanel.zoneView.getStore().loadData({zones: zones});
+ this.allDevices = devices;
+ },
+ processCircuits: function(circuits) {
+ Ext.each(this.allDevices, function(device) {
+ var circuitID = device.circuitID;
+ for( var i = 0; i < circuits.length; i++) {
+ if(circuits[i].busid == circuitID) {
+ device.circuit = circuits[i].name;
+ device.modulator = circuits[i].dsid;
+ }
+ }
+ });
+ var deviceStore = this.devicePanel.getStore();
+ deviceStore.loadData({devices: this.allDevices});
+ if(this.zonePanel.zoneView.getStore().getCount() > 1) {
+ this.zonePanel.zoneView.select(1);
+ } else {
+ this.zonePanel.zoneView.select(0);
+ }
+ },
+ loadStructure: function() {
+ Ext.Ajax.request({
+ url: '/json/apartment/getStructure',
+ disableCaching: true,
+ method: "GET",
+ scope: this,
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ this.processStructure(jsonData);
+ }
+ catch (err) {
+ Ext.MessageBox.alert('AJAX Error', 'Error loading apartment structure: "' + err + '"');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('AJAX Error', 'Could not load "' + request.url + '"');
+ },
+ });
+ },
+ loadCircuits: function() {
+ Ext.Ajax.request({
+ url: '/json/apartment/getCircuits',
+ disableCaching: true,
+ method: "GET",
+ scope: this,
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ this.processCircuits(jsonData.result.circuits);
+ }
+ catch (err) {
+ Ext.MessageBox.alert('AJAX Error', 'Could not load circuits: "' + err + '"');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('AJAX Error', 'Could not load "' + request.url + '"');
+ },
+ });
+ },
+ loadData: function() {
+ this.loadStructure();
+ this.loadCircuits();
+ }
+
+});
+
+Ext.reg('dsszonebrowser', dSS.ZoneBrowser);
\ No newline at end of file
Added: dss/trunk/websrc/dss-setup-interface/dSS/ZonePanel.js
===================================================================
--- dss/trunk/websrc/dss-setup-interface/dSS/ZonePanel.js (rev 0)
+++ dss/trunk/websrc/dss-setup-interface/dSS/ZonePanel.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,105 @@
+//= require <dSS/ZoneView>
+
+Ext.namespace('dSS');
+
+dSS.ZonePanel = Ext.extend(Ext.Panel, {
+ initComponent: function() {
+ Ext.apply(this, {
+ title:'Zones',
+ layout: 'border',
+ items: [{ xtype: 'dsszoneview', ref: 'zoneView', region: 'center'}]
+ //tbar: ['->', createZoneAction, reloadAction]
+ });
+
+ this.tbar = this.buildTopToolbar();
+
+ dSS.ZonePanel.superclass.initComponent.apply(this, arguments);
+ },
+
+ buildTopToolbar: function() {
+ return ['->',
+ {
+ text: 'New Zone',
+ iconCls: 'newZoneAction',
+ handler: this.createNewZone,
+ scope: this
+ },
+ {
+ text: 'Reload',
+ iconCls: 'reloadAction',
+ handler: this.reload,
+ scope: this
+ }
+ ];
+ },
+
+ createNewZone: function() {
+ var zoneStore = this.zoneView.getStore();
+ Ext.Msg.prompt('Create new zone', 'Name for new Zone:', function(btn, text){
+ if (btn == 'ok'){
+ for(var i = 0; i <= zoneStore.data.length; i++) {
+ if(zoneStore.findExact('id', i) === -1) {
+
+ Ext.Ajax.request({
+ url: '/json/structure/addZone',
+ disableCaching: true,
+ method: "GET",
+ params: { zoneID: i },
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ if(jsonData.ok) {
+
+
+
+ Ext.Ajax.request({
+ url: '/json/zone/setName',
+ disableCaching: true,
+ method: "GET",
+ params: { id: i,
+ newName: text},
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ if(jsonData.ok) {
+
+
+ var newZone = new zoneStore.recordType({id: i, name: text}, i);
+ zoneStore.insert(i, newZone);
+
+
+
+ }
+ }
+ catch (err) {
+ Ext.MessageBox.alert('Error', 'Could not create Zone');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('Error', 'Could not create Zone');
+ },
+ });
+
+
+ }
+ }
+ catch (err) {
+ Ext.MessageBox.alert('Error', 'Could not create Zone');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('Error', 'Could not create Zone');
+ },
+ });
+ return;
+ }
+ }
+ }
+ })
+ },
+ reload: function() {
+ this.ownerCt.loadData();
+ }
+});
+
+Ext.reg('dsszonepanel', dSS.ZonePanel);
Added: dss/trunk/websrc/dss-setup-interface/dSS/ZoneView.js
===================================================================
--- dss/trunk/websrc/dss-setup-interface/dSS/ZoneView.js (rev 0)
+++ dss/trunk/websrc/dss-setup-interface/dSS/ZoneView.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,105 @@
+//= require <dSS/data/ZoneStore>
+
+Ext.namespace('dSS');
+
+dSS.ZoneView = Ext.extend(Ext.DataView, {
+ initComponent: function() {
+
+ var zoneTemplate = new Ext.XTemplate(
+ '<tpl for=".">',
+ '<div class="zone-wrap {css}" id="zone-{id}">',
+ '<span>{name}</span>',
+ '</div>',
+ '</tpl>',
+ '<div class="x-clear"></div>'
+ );
+
+ var zoneStore = new dSS.data.ZoneStore();
+
+ Ext.apply(this, {
+ store: zoneStore,
+ tpl: zoneTemplate,
+// autoHeight:true,
+ multiSelect: true,
+ layout: 'fit',
+ style: "overflow: auto",
+ overClass:'x-view-over',
+ itemSelector:'div.zone-wrap',
+ emptyText: 'No Rooms to display',
+ plugins: [
+ new Ext.DataView.DragSelector()
+ ]
+ });
+
+ dSS.ZoneView.superclass.initComponent.apply(this, arguments);
+ // Here you can add functionality that requires the object to
+ // exist, like event handling.
+ this.on(
+ 'selectionchange',
+ function(dv,nodes) {
+ var l = nodes.length;
+ var s = l != 1 ? 's' : '';
+ this.findParentByType('dsszonepanel').setTitle("Zones (" + l + ' zone' + s + ' selected)');
+ this.findParentByType('dsszonebrowser').filterDevices();
+ },
+ this
+ );
+
+ this.on(
+ 'render',
+ function() {
+ var zoneView = this;
+ this.dropZone = new Ext.dd.DropZone(zoneView.getEl(), {
+ ddGroup : "zoneDeviceDD",
+ getTargetFromEvent: function(e) {
+ return e.getTarget(zoneView.itemSelector);
+ },
+ onNodeEnter : function(target, dd, e, data){
+ Ext.fly(target).addClass('my-row-highlight-class');
+ },
+ onNodeOut : function(target, dd, e, data){
+ Ext.fly(target).removeClass('my-row-highlight-class');
+ },
+ onNodeOver : function(target, dd, e, data){
+ return Ext.dd.DropZone.prototype.dropAllowed;
+ },
+ onNodeDrop : function(target, dd, e, data){
+ var record = zoneView.getRecord(target);
+ Ext.each(data.selections, function(device) {
+ var currentDevice = device;
+ Ext.Ajax.request({
+ url: '/json/structure/zoneAddDevice',
+ disableCaching: true,
+ method: "GET",
+ scope: zoneView,
+ params: { devid: currentDevice.data.id,
+ zone: record.data.id
+ },
+ success: function(result, request) {
+ try {
+ var jsonData = Ext.util.JSON.decode(result.responseText);
+ if(jsonData.ok) {
+ currentDevice.set("zone", record.data.id);
+ this.getStore().commitChanges();
+ this.findParentByType('dsszonebrowser').filterDevices();
+ }
+ }
+ catch (err) {
+ Ext.MessageBox.alert('Error', 'Could not move device "' + device.data.dsid + '"');
+ }
+ },
+ failure: function(result, request) {
+ Ext.MessageBox.alert('Error', 'Could not move device "' + device.data.dsid + '"');
+ },
+ });
+ });
+ return true;
+ }
+ });
+ },
+ this
+ );
+ }
+});
+
+Ext.reg('dsszoneview', dSS.ZoneView);
\ No newline at end of file
Added: dss/trunk/websrc/dss-setup-interface/dSS/data/DeviceStore.js
===================================================================
--- dss/trunk/websrc/dss-setup-interface/dSS/data/DeviceStore.js (rev 0)
+++ dss/trunk/websrc/dss-setup-interface/dSS/data/DeviceStore.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,26 @@
+Ext.namespace('dSS', 'dSS.data');
+
+dSS.data.DeviceStore = Ext.extend(Ext.data.Store, {
+ constructor: function(config) {
+ // create a record constructor for device records
+ var deviceRecord = Ext.data.Record.create([
+ {name:"name"},
+ {name:"id"},
+ {name:"on"},
+ {name:"circuit"},
+ {name:"modulator"},
+ {name:"zone"}
+ ]);
+
+ // a json reader to read the device data
+ var deviceReader = new Ext.data.JsonReader(
+ {
+ root:"devices"
+ },
+ deviceRecord
+ );
+
+ Ext.apply(this, { reader: deviceReader });
+ dSS.data.DeviceStore.superclass.constructor.call(this, arguments);
+ }
+});
Added: dss/trunk/websrc/dss-setup-interface/dSS/data/ZoneStore.js
===================================================================
--- dss/trunk/websrc/dss-setup-interface/dSS/data/ZoneStore.js (rev 0)
+++ dss/trunk/websrc/dss-setup-interface/dSS/data/ZoneStore.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,22 @@
+Ext.namespace('dSS', 'dSS.data');
+
+dSS.data.ZoneStore = Ext.extend(Ext.data.Store, {
+ constructor: function(config) {
+ // create a record constructor for zone records
+ var zoneRecord = Ext.data.Record.create([
+ {name:"name"},
+ {name:"id"}
+ ]);
+
+ // a json reader to read the zone data
+ var zoneReader = new Ext.data.JsonReader(
+ {
+ root: "zones"
+ },
+ zoneRecord
+ );
+
+ Ext.apply(this, { reader: zoneReader });
+ dSS.data.ZoneStore.superclass.constructor.call(this, arguments);
+ }
+});
Added: dss/trunk/websrc/dss-setup-interface/dSS/grid/DevicePanel.js
===================================================================
--- dss/trunk/websrc/dss-setup-interface/dSS/grid/DevicePanel.js (rev 0)
+++ dss/trunk/websrc/dss-setup-interface/dSS/grid/DevicePanel.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,54 @@
+//= require <dSS/data/DeviceStore>
+
+Ext.namespace('dSS', 'dSS.grid');
+
+dSS.grid.DevicePanel = Ext.extend(Ext.grid.GridPanel, {
+ initComponent: function() {
+
+ var deviceCols = [
+ {id: 'id', header: "id", width: 50, sortable: true, dataIndex: 'id'},
+ {id: 'name', header: "name", width: 50, sortable: true, dataIndex: 'name', editable: true, editor: new Ext.form.TextField()},
+ {header: "on", width: 50, sortable: true, dataIndex: 'on'},
+ {header: "circuit", width: 50, sortable: true, dataIndex: 'circuit'},
+ {header: "modulator", width: 50, sortable: true, dataIndex: 'modulator'},
+ {header: "zone", width: 50, sortable: true, dataIndex: 'zone'},
+ ];
+
+ var editor = new Ext.ux.grid.RowEditor({
+ saveText: 'Update'
+ });
+
+ editor.on('afteredit', function() {
+ //console.log('a device has been edited');
+ deviceStore.commitChanges();
+ filterDevices();
+ });
+
+ var deviceStore = new dSS.data.DeviceStore();
+
+ Ext.apply(this, {
+ store : deviceStore,
+ columns : deviceCols,
+ ddGroup : "zoneDeviceDD",
+ enableDragDrop : true,
+ stripeRows : true,
+ autoExpandColumn : 'id',
+ title : 'Devices',
+ plugins : [editor]
+ });
+
+ dSS.grid.DevicePanel.superclass.initComponent.apply(this, arguments);
+
+ // Here you can add functionality that requires the object to
+ // exist, like event handling.
+ this.on(
+ 'rowcontextmenu',
+ function() {
+ //console.log('rowcontextmenu');
+ },
+ this
+ );
+ }
+});
+
+Ext.reg('dssdevicepanel', dSS.grid.DevicePanel);
Added: dss/trunk/websrc/dss-setup-interface/dss-setup-interface.js
===================================================================
--- dss/trunk/websrc/dss-setup-interface/dss-setup-interface.js (rev 0)
+++ dss/trunk/websrc/dss-setup-interface/dss-setup-interface.js 2009-10-22 12:35:09 UTC (rev 8856)
@@ -0,0 +1,29 @@
+//= require <dSS/ZoneBrowser>
+
+Ext.onReady(function(){
+ Ext.get('start').remove();
+ var viewport = new Ext.Viewport({
+ layout: 'border',
+ items: [
+ {
+ xtype: 'box',
+ region: 'north',
+ height: 32, // give north and south regions a height
+ autoEl: {
+ tag: 'div',
+ html:'<h1>digitalSTROM Setup</h1>'
+ }
+ }, {
+ region: 'center',
+ xtype: 'tabpanel',
+ activeItem: 0,
+ items: [
+ {
+ title: 'Zones',
+ xtype: 'dsszonebrowser',
+ ref: 'zonebrowser'
+ }
+ ]
+ }]
+ });
+});
More information about the dss-commits
mailing list