dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #36848
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18837: EV range set + layout value dimension implemented.
Merge authors:
Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 18837 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2015-04-09 09:54:08 +0200
message:
EV range set + layout value dimension implemented.
modified:
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-reports/scripts/core.js
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-reports/styles/style.css
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/i18n/i18n_app.properties
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/app.js
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/core.js
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/styles/style.css
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/app.js
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/styles/style.css
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/styles/style.css
--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk
Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-reports/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-reports/scripts/core.js 2015-04-01 15:34:05 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-reports/scripts/core.js 2015-04-09 06:29:13 +0000
@@ -314,7 +314,7 @@
// hideEmptyRows: boolean (false)
- // : boolean (false)
+ // collapseDataDimensions: boolean (false)
// outputType: string ('EVENT') - 'EVENT', 'TRACKED_ENTITY_INSTANCE', 'ENROLLMENT'
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-reports/styles/style.css'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-reports/styles/style.css 2015-03-11 16:35:26 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-reports/styles/style.css 2015-04-08 13:50:25 +0000
@@ -340,11 +340,11 @@
.ns-viewport-text * {
padding: 3px 10px;
- font-size: 13px;
+ font-size: 11px;
color: #515a62;
}
.ns-viewport-text h3 {
- font-size: 15px;
+ font-size: 14px;
font-weight: 500;
color: #333;
padding: 0 0 8px 0;
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/i18n/i18n_app.properties'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/i18n/i18n_app.properties 2015-04-03 15:43:32 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/i18n/i18n_app.properties 2015-04-08 13:50:25 +0000
@@ -180,8 +180,8 @@
you_do_not_have_access_to_all_items_in_this_favorite=You do not have access to all items in this favorite
example1=Creating a chart
example2=Select items from any of the dimensions in the left menu
-example3=Click Layout to arrange your dimensions on table rows and columns
-example4=Click Update to create your table
+example3=Click Layout to arrange your dimensions on chart series and categories
+example4=Click Update to create your chart
example5=Working with a chart
example6=Click Options to show trend lines, target lines, axis titles and more
example7=Click Favorites to save your chart for later use
@@ -200,6 +200,7 @@
series_dimension=Series dimension
category_dimension=Category dimension
chart_filter=Chart filter
+report_filter=Report filter
value=Value
average=Average
count=Count
@@ -214,3 +215,6 @@
user_sub_units=User sub-units
user_sub_x2_units=User sub-x2-units
hide_na_data=Hide n/a data
+duplicate=Duplicate
+remove=Remove
+select=Select
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/app.js 2015-04-03 15:43:32 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/app.js 2015-04-09 07:42:56 +0000
@@ -108,12 +108,18 @@
// data items
(function() {
- var operatorCmpWidth = 70,
- valueCmpWidth = 306,
+ var scrollbarWidth = /\bchrome\b/.test(navigator.userAgent.toLowerCase()) ? 8 : 17,
+ nameCmpWidth = 440 - scrollbarWidth,
buttonCmpWidth = 20,
- nameCmpWidth = 400,
- namePadding = '2px 3px',
- margin = '3px 0 1px';
+ operatorCmpWidth = 70,
+ searchCmpWidth = 70,
+ triggerCmpWidth = 17,
+ valueCmpWidth = 235,
+ rangeSetWidth = 135,
+ namePadding = '3px 3px',
+ margin = '3px 0 1px',
+ removeCmpStyle = 'padding: 0; margin-left: 3px',
+ defaultRangeSetId = 'default';
Ext.define('Ext.ux.panel.DataElementIntegerContainer', {
extend: 'Ext.container.Container',
@@ -122,44 +128,96 @@
bodyStyle: 'border:0 none',
style: 'margin: ' + margin,
getRecord: function() {
- var record = {};
+ var record = {},
+ isRange = this.rangeSetCmp.getValue() !== defaultRangeSetId;
record.dimension = this.dataElement.id;
record.name = this.dataElement.name;
- if (this.valueCmp.getValue()) {
- record.filter = this.operatorCmp.getValue() + ':' + this.valueCmp.getValue();
- }
+ if (isRange) {
+ record.legendSet = {
+ id: this.rangeSetCmp.getValue()
+ };
+
+ if (this.rangeValueCmp.getValue().length) {
+ record.filter = 'IN:' + this.rangeValueCmp.getValue().join(';');
+ }
+ }
+ else {
+ if (this.valueCmp.getValue()) {
+ record.filter = this.operatorCmp.getValue() + ':' + this.valueCmp.getValue();
+ }
+ }
return record;
},
setRecord: function(record) {
- if (record.filter) {
+ if (Ext.isObject(record.legendSet) && record.legendSet.id) {
+ this.rangeSetCmp.pendingValue = record.legendSet.id;
+ this.onRangeSetSelect(record.legendSet.id);
+
+ if (record.filter) {
+ var a = record.filter.split(':');
+
+ if (a.length > 1 && Ext.isString(a[1])) {
+ this.onRangeSearchSelect(a[1].split(';'), true);
+ }
+ }
+ }
+ else if (record.filter) {
+ this.rangeSetCmp.pendingValue = defaultRangeSetId;
+
var a = record.filter.split(':');
- this.operatorCmp.setValue(a[0]);
- this.valueCmp.setValue(a[1]);
+ if (a.length > 1) {
+ this.operatorCmp.setValue(a[0]);
+ this.valueCmp.setValue(a[1]);
+ }
+ else {}
}
},
initComponent: function() {
- var container = this;
+ var container = this,
+ idProperty = 'id',
+ nameProperty = 'name',
+ displayProperty = 'displayName';
this.nameCmp = Ext.create('Ext.form.Label', {
text: this.dataElement.name,
- width: nameCmpWidth,
+ flex: 1,
style: 'padding:' + namePadding
});
+ this.addCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: 'padding: 0',
+ height: 18,
+ text: NS.i18n.duplicate,
+ handler: function() {
+ container.duplicateDataElement();
+ }
+ });
+
+ this.removeCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: removeCmpStyle,
+ height: 18,
+ text: NS.i18n.remove,
+ handler: function() {
+ container.removeDataElement();
+ }
+ });
+
this.operatorCmp = Ext.create('Ext.form.field.ComboBox', {
- valueField: 'id',
- displayField: 'name',
+ valueField: idProperty,
+ displayField: nameProperty,
queryMode: 'local',
editable: false,
width: operatorCmpWidth,
style: 'margin-bottom:0',
value: 'EQ',
store: {
- fields: ['id', 'name'],
+ fields: [idProperty, nameProperty],
data: [
{id: 'EQ', name: '='},
{id: 'GT', name: '>'},
@@ -172,32 +230,231 @@
});
this.valueCmp = Ext.create('Ext.form.field.Number', {
- width: valueCmpWidth,
+ width: nameCmpWidth - operatorCmpWidth - rangeSetWidth,
style: 'margin-bottom:0'
});
- this.addCmp = Ext.create('Ext.button.Button', {
- text: '+',
- width: buttonCmpWidth,
- handler: function() {
- container.duplicateDataElement();
+ this.rangeSearchStore = Ext.create('Ext.data.Store', {
+ fields: [idProperty, nameProperty]
+ });
+
+ // function
+ this.filterSearchStore = function(isLayout) {
+ var selected = container.rangeValueCmp.getValue();
+
+ // hack, using internal method to activate dropdown before filtering
+ if (isLayout) {
+ container.rangeSearchCmp.onTriggerClick();
+ container.rangeSearchCmp.collapse();
+ }
+
+ // filter
+ container.rangeSearchStore.clearFilter();
+
+ container.rangeSearchStore.filterBy(function(record) {
+ return !Ext.Array.contains(selected, record.data[idProperty]);
+ });
+ };
+
+ // function
+ this.onRangeSearchSelect = function(ids, isLayout) {
+ ids = Ext.Array.from(ids);
+
+ // store
+ for (var i = 0, id; i < ids.length; i++) {
+ id = ids[i];
+
+ if (container.rangeValueStore.findExact(idProperty, id) === -1) {
+ container.rangeValueStore.add(container.rangeSearchStore.getAt(container.rangeSearchStore.findExact(idProperty, id)).data);
+ }
+ }
+
+ // search cmp
+ container.rangeSearchCmp.select([]);
+
+ // filter
+ container.filterSearchStore(isLayout);
+ };
+
+ this.rangeSearchCmp = Ext.create('Ext.form.field.ComboBox', {
+ multiSelect: true,
+ width: operatorCmpWidth,
+ style: 'margin-bottom: 0',
+ emptyText: NS.i18n.select + '..',
+ valueField: idProperty,
+ displayField: displayProperty,
+ editable: false,
+ queryMode: 'local',
+ hidden: true,
+ store: this.rangeSearchStore,
+ listConfig: {
+ minWidth: operatorCmpWidth + (nameCmpWidth - operatorCmpWidth - rangeSetWidth)
+ },
+ listeners: {
+ select: function() {
+ container.onRangeSearchSelect(Ext.Array.from(this.getValue())[0]);
+ },
+ expand: function() {
+ container.filterSearchStore();
+ }
}
});
- this.removeCmp = Ext.create('Ext.button.Button', {
- text: 'x',
- width: buttonCmpWidth,
- handler: function() {
- container.removeDataElement();
+ this.rangeValueStore = Ext.create('Ext.data.Store', {
+ fields: [idProperty, nameProperty],
+ listeners: {
+ add: function() {
+ container.rangeValueCmp.select(this.getRange());
+ },
+ remove: function() {
+ container.rangeValueCmp.select(this.getRange());
+ }
+ }
+ });
+
+ this.rangeValueCmp = Ext.create('Ext.form.field.ComboBox', {
+ multiSelect: true,
+ style: 'margin-bottom: 0',
+ width: nameCmpWidth - operatorCmpWidth - rangeSetWidth,
+ valueField: idProperty,
+ displayField: nameProperty,
+ emptyText: 'No selected items',
+ editable: false,
+ hideTrigger: true,
+ queryMode: 'local',
+ hidden: true,
+ store: container.rangeValueStore,
+ listConfig: {
+ minWidth: valueCmpWidth,
+ cls: 'ns-optionselector'
+ },
+ setOptionValues: function(records) {
+ var me = this;
+
+ container.rangeValueStore.removeAll();
+ container.rangeValueStore.loadData(records);
+
+ me.setValue(records);
+ },
+ listeners: {
+ change: function(cmp, newVal, oldVal) {
+ newVal = Ext.Array.from(newVal);
+ oldVal = Ext.Array.from(oldVal);
+
+ if (newVal.length < oldVal.length) {
+ var id = Ext.Array.difference(oldVal, newVal)[0];
+ container.rangeValueStore.removeAt(container.rangeValueStore.findExact(idProperty, id));
+ }
+ }
+ }
+ });
+
+ // function
+ this.onRangeSetSelect = function(id) {
+ if (!id || id === defaultRangeSetId) {
+ container.operatorCmp.show();
+ container.valueCmp.show();
+ container.rangeSearchCmp.hide();
+ container.rangeValueCmp.hide();
+ }
+ else {
+ var ranges;
+
+ container.operatorCmp.hide();
+ container.valueCmp.hide();
+ container.rangeSearchCmp.show();
+ container.rangeValueCmp.show();
+
+ ranges = Ext.clone(ns.core.init.idLegendSetMap[id].legends);
+
+ // display name
+ for (var i = 0; i < ranges.length; i++) {
+ range = ranges[i];
+ range.displayName = range.name + ' (' + range.startValue + ' - ' + range.endValue + ')';
+ }
+
+ container.rangeSearchStore.loadData(ranges);
+ container.rangeSearchStore.sort('startValue', 'ASC');
+ }
+ };
+
+ this.rangeSetCmp = Ext.create('Ext.form.field.ComboBox', {
+ cls: 'ns-combo h22',
+ style: 'margin-bottom: 0',
+ width: rangeSetWidth,
+ height: 22,
+ fieldStyle: 'height: 22px',
+ queryMode: 'local',
+ valueField: idProperty,
+ displayField: nameProperty,
+ editable: false,
+ storage: {},
+ pendingValue: null,
+ setPendingValue: function() {
+ if (this.pendingValue) {
+ this.setValue(this.pendingValue);
+ container.onRangeSetSelect(this.pendingValue);
+
+ this.pendingValue = null;
+ }
+
+ if (!this.getValue()) {
+ this.pendingValue = defaultRangeSetId;
+ this.setPendingValue();
+ }
+ },
+ store: Ext.create('Ext.data.Store', {
+ fields: [idProperty, nameProperty]
+ }),
+ listeners: {
+ added: function(cb) {
+ cb.store.add({
+ id: defaultRangeSetId,
+ name: 'No range set'
+ });
+
+ //cb.setValue(defaultRangeSetId);
+
+ Ext.Ajax.request({
+ url: ns.core.init.contextPath + '/api/dataElements/' + container.dataElement.id + '.json?fields=legendSet[id,name]',
+ success: function(r) {
+ r = Ext.decode(r.responseText);
+
+ if (Ext.isObject(r) && Ext.isObject(r.legendSet)) {
+ cb.store.add(r.legendSet);
+
+ cb.setValue(r.legendSet.id);
+ container.onRangeSetSelect(r.legendSet.id);
+ }
+ },
+ callback: function() {
+ cb.setPendingValue();
+ }
+ });
+ },
+ select: function(cb, r) {
+ var id = Ext.Array.from(r)[0].data.id;
+ container.onRangeSetSelect(id);
+ }
}
});
this.items = [
- this.nameCmp,
+ {
+ xtype: 'container',
+ layout: 'hbox',
+ width: nameCmpWidth,
+ items: [
+ this.nameCmp,
+ this.addCmp,
+ this.removeCmp
+ ]
+ },
+ this.rangeSearchCmp,
+ this.rangeValueCmp,
this.operatorCmp,
this.valueCmp,
- this.addCmp,
- this.removeCmp
+ this.rangeSetCmp
];
this.callParent();
@@ -231,10 +488,31 @@
this.nameCmp = Ext.create('Ext.form.Label', {
text: this.dataElement.name,
- width: nameCmpWidth,
+ flex: 1,
style: 'padding:' + namePadding
});
+ this.addCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: 'padding: 0',
+ height: 18,
+ text: 'Duplicate',
+ handler: function() {
+ container.duplicateDataElement();
+ }
+ });
+
+ this.removeCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: removeCmpStyle,
+ height: 18,
+ text: 'Remove',
+ handler: function() {
+ container.removeDataElement();
+ }
+ });
+
+
this.operatorCmp = Ext.create('Ext.form.field.ComboBox', {
valueField: 'id',
displayField: 'name',
@@ -253,32 +531,23 @@
});
this.valueCmp = Ext.create('Ext.form.field.Text', {
- width: valueCmpWidth,
+ width: nameCmpWidth - operatorCmpWidth,
style: 'margin-bottom:0'
});
- this.addCmp = Ext.create('Ext.button.Button', {
- text: '+',
- width: buttonCmpWidth,
- handler: function() {
- container.duplicateDataElement();
- }
- });
-
- this.removeCmp = Ext.create('Ext.button.Button', {
- text: 'x',
- width: buttonCmpWidth,
- handler: function() {
- container.removeDataElement();
- }
- });
-
this.items = [
- this.nameCmp,
+ {
+ xtype: 'container',
+ layout: 'hbox',
+ width: nameCmpWidth,
+ items: [
+ this.nameCmp,
+ this.addCmp,
+ this.removeCmp
+ ]
+ },
this.operatorCmp,
- this.valueCmp,
- this.addCmp,
- this.removeCmp
+ this.valueCmp
];
this.callParent();
@@ -316,10 +585,30 @@
this.nameCmp = Ext.create('Ext.form.Label', {
text: this.dataElement.name,
- width: nameCmpWidth,
+ flex: 1,
style: 'padding:' + namePadding
});
+ this.addCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: 'padding: 0',
+ height: 18,
+ text: 'Duplicate',
+ handler: function() {
+ container.duplicateDataElement();
+ }
+ });
+
+ this.removeCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: removeCmpStyle,
+ height: 18,
+ text: 'Remove',
+ handler: function() {
+ container.removeDataElement();
+ }
+ });
+
this.operatorCmp = Ext.create('Ext.form.field.ComboBox', {
valueField: 'id',
displayField: 'name',
@@ -342,33 +631,24 @@
});
this.valueCmp = Ext.create('Ext.form.field.Date', {
- width: valueCmpWidth,
+ width: nameCmpWidth - operatorCmpWidth,
style: 'margin-bottom:0',
format: 'Y-m-d'
});
- this.addCmp = Ext.create('Ext.button.Button', {
- text: '+',
- width: buttonCmpWidth,
- handler: function() {
- container.duplicateDataElement();
- }
- });
-
- this.removeCmp = Ext.create('Ext.button.Button', {
- text: 'x',
- width: buttonCmpWidth,
- handler: function() {
- container.removeDataElement();
- }
- });
-
this.items = [
- this.nameCmp,
+ {
+ xtype: 'container',
+ layout: 'hbox',
+ width: nameCmpWidth,
+ items: [
+ this.nameCmp,
+ this.addCmp,
+ this.removeCmp
+ ]
+ },
this.operatorCmp,
- this.valueCmp,
- this.addCmp,
- this.removeCmp
+ this.valueCmp
];
this.callParent();
@@ -403,48 +683,59 @@
this.nameCmp = Ext.create('Ext.form.Label', {
text: this.dataElement.name,
- width: nameCmpWidth,
+ flex: 1,
style: 'padding:' + namePadding
});
+ this.addCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: 'padding: 0',
+ height: 18,
+ text: 'Duplicate',
+ handler: function() {
+ container.duplicateDataElement();
+ }
+ });
+
+ this.removeCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: removeCmpStyle,
+ height: 18,
+ text: 'Remove',
+ handler: function() {
+ container.removeDataElement();
+ }
+ });
+
this.valueCmp = Ext.create('Ext.form.field.ComboBox', {
valueField: 'id',
displayField: 'name',
queryMode: 'local',
editable: false,
- width: operatorCmpWidth + valueCmpWidth,
+ width: nameCmpWidth,
style: 'margin-bottom:0',
value: 'true',
store: {
fields: ['id', 'name'],
data: [
- {id: 'true', name: EV.i18n.yes},
- {id: 'false', name: EV.i18n.no}
+ {id: 'true', name: ER.i18n.yes},
+ {id: 'false', name: ER.i18n.no}
]
}
});
- this.addCmp = Ext.create('Ext.button.Button', {
- text: '+',
- width: buttonCmpWidth,
- handler: function() {
- container.duplicateDataElement();
- }
- });
-
- this.removeCmp = Ext.create('Ext.button.Button', {
- text: 'x',
- width: buttonCmpWidth,
- handler: function() {
- container.removeDataElement();
- }
- });
-
this.items = [
- this.nameCmp,
- this.valueCmp,
- this.addCmp,
- this.removeCmp
+ {
+ xtype: 'container',
+ layout: 'hbox',
+ width: nameCmpWidth,
+ items: [
+ this.nameCmp,
+ this.addCmp,
+ this.removeCmp
+ ]
+ },
+ this.valueCmp
];
this.callParent();
@@ -457,12 +748,6 @@
layout: 'column',
bodyStyle: 'border:0 none',
style: 'margin: ' + margin,
- addCss: function() {
- var css = '.optionselector .x-boundlist-selected { background-color: #fff; border-color: #fff } \n';
- css += '.optionselector .x-boundlist-selected.x-boundlist-item-over { background-color: #ddd; border-color: #ddd } \n';
-
- Ext.util.CSS.createStyleSheet(css);
- },
getRecord: function() {
var items = this.valueCmp.getValue(),
record = {
@@ -507,14 +792,32 @@
idProperty = 'code',
nameProperty = 'name';
- this.addCss();
-
this.nameCmp = Ext.create('Ext.form.Label', {
text: this.dataElement.name,
- width: nameCmpWidth,
+ flex: 1,
style: 'padding:' + namePadding
});
+ this.addCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: 'padding: 0',
+ height: 18,
+ text: 'Duplicate',
+ handler: function() {
+ container.duplicateDataElement();
+ }
+ });
+
+ this.removeCmp = Ext.create('Ext.button.Button', {
+ cls: 'ns-linkbutton',
+ style: removeCmpStyle,
+ height: 18,
+ text: 'Remove',
+ handler: function() {
+ container.removeDataElement();
+ }
+ });
+
this.operatorCmp = Ext.create('Ext.form.field.ComboBox', {
valueField: 'id',
displayField: 'name',
@@ -540,7 +843,7 @@
optionSetId = optionSetId || container.dataElement.optionSet.id;
pageSize = pageSize || 100;
- dhis2.ev.store.get('optionSets', optionSetId).done( function(obj) {
+ dhis2.er.store.get('optionSets', optionSetId).done( function(obj) {
if (Ext.isObject(obj) && Ext.isArray(obj.options) && obj.options.length) {
var data = [];
@@ -592,7 +895,7 @@
this.searchCmp = Ext.create('Ext.form.field.ComboBox', {
multiSelect: true,
- width: 62,
+ width: operatorCmpWidth - triggerCmpWidth,
style: 'margin-bottom:0',
emptyText: 'Search..',
valueField: idProperty,
@@ -601,7 +904,7 @@
enableKeyEvents: true,
queryMode: 'local',
listConfig: {
- minWidth: 346
+ minWidth: nameCmpWidth - operatorCmpWidth
},
store: this.searchStore,
listeners: {
@@ -643,7 +946,7 @@
this.triggerCmp = Ext.create('Ext.button.Button', {
cls: 'ns-button-combotrigger',
disabledCls: 'ns-button-combotrigger-disabled',
- width: 18,
+ width: triggerCmpWidth,
height: 22,
handler: function(b) {
container.searchStore.loadOptionSet();
@@ -665,7 +968,7 @@
this.valueCmp = Ext.create('Ext.form.field.ComboBox', {
multiSelect: true,
style: 'margin-bottom:0',
- width: 226,
+ width: nameCmpWidth - operatorCmpWidth - operatorCmpWidth,
valueField: idProperty,
displayField: nameProperty,
emptyText: 'No selected items',
@@ -675,13 +978,13 @@
queryMode: 'local',
listConfig: {
minWidth: 266,
- cls: 'optionselector'
+ cls: 'ns-optionselector'
},
setOptionValues: function(codeArray) {
var me = this,
records = [];
- dhis2.ev.store.get('optionSets', container.dataElement.optionSet.id).done( function(obj) {
+ dhis2.er.store.get('optionSets', container.dataElement.optionSet.id).done( function(obj) {
if (Ext.isObject(obj) && Ext.isArray(obj.options) && obj.options.length) {
records = container.getRecordsByCode(obj.options, codeArray);
@@ -705,31 +1008,21 @@
}
});
- this.addCmp = Ext.create('Ext.button.Button', {
- text: '+',
- width: buttonCmpWidth,
- style: 'font-weight:bold',
- handler: function() {
- container.duplicateDataElement();
- }
- });
-
- this.removeCmp = Ext.create('Ext.button.Button', {
- text: 'x',
- width: buttonCmpWidth,
- handler: function() {
- container.removeDataElement();
- }
- });
-
this.items = [
- this.nameCmp,
+ {
+ xtype: 'container',
+ layout: 'hbox',
+ width: nameCmpWidth,
+ items: [
+ this.nameCmp,
+ this.addCmp,
+ this.removeCmp
+ ]
+ },
this.operatorCmp,
this.searchCmp,
this.triggerCmp,
- this.valueCmp,
- this.addCmp,
- this.removeCmp
+ this.valueCmp
];
this.callParent();
@@ -1006,6 +1299,9 @@
filterStore,
onValueSelect,
value,
+ val,
+ onCollapseDataDimensionsChange,
+ collapseDataDimensions,
aggregationType,
getStore,
@@ -1030,14 +1326,13 @@
dataType = 'aggregated_values',
defaultValueId = 'default';
- getStore = function(data) {
- var config = {};
+ getStore = function(applyConfig) {
+ var config = {},
+ store;
config.fields = ['id', 'name'];
- if (data) {
- config.data = data;
- }
+ Ext.apply(config, applyConfig);
config.getDimensionNames = function() {
var dimensionNames = [];
@@ -1049,7 +1344,9 @@
return Ext.clone(dimensionNames);
};
- return Ext.create('Ext.data.Store', config);
+ store = Ext.create('Ext.data.Store', config);
+
+ return store;
};
getStoreKeys = function(store) {
@@ -1065,11 +1362,11 @@
return keys;
};
- colStore = getStore();
- rowStore = getStore();
- fixedFilterStore = getStore();
- filterStore = getStore();
- valueStore = getStore();
+ colStore = getStore({name: 'colStore'});
+ rowStore = getStore({name: 'rowStore'});
+ fixedFilterStore = getStore({name: 'fixedFilterStore'});
+ filterStore = getStore({name: 'filterStore'});
+ valueStore = getStore({name: 'valueStore'});
// store functions
valueStore.addDefaultData = function() {
@@ -1204,7 +1501,7 @@
height: 25,
items: {
xtype: 'label',
- text: NS.i18n.chart_filter,
+ text: NS.i18n.report_filter,
cls: 'ns-toolbar-multiselect-leftright-label'
}
},
@@ -1230,7 +1527,6 @@
store: filterStore,
listeners: {
afterrender: function(ms) {
-
ms.store.on('add', function() {
Ext.defer( function() {
ms.boundList.getSelectionModel().deselectAll();
@@ -1242,7 +1538,7 @@
aggregationType = Ext.create('Ext.form.field.ComboBox', {
cls: 'ns-combo h22',
- width: 70,
+ width: 80,
height: 22,
style: 'margin: 0',
fieldStyle: 'height: 22px',
@@ -1263,15 +1559,7 @@
},
store: Ext.create('Ext.data.Store', {
fields: ['id', 'text'],
- data: [
- {id: 'COUNT', text: NS.i18n.count},
- {id: 'AVERAGE', text: NS.i18n.average},
- {id: 'SUM', text: NS.i18n.sum},
- {id: 'STDDEV', text: NS.i18n.stddev},
- {id: 'VARIANCE', text: NS.i18n.variance},
- {id: 'MIN', text: NS.i18n.min},
- {id: 'MAX', text: NS.i18n.max}
- ]
+ data: ns.core.conf.aggregationType.data
}),
resetData: function() {
this.setDisabled();
@@ -1287,7 +1575,11 @@
// remove ux and layout item
if (hasDimension(id, valueStore)) {
- ns.app.accordion.getUx(id).removeDataElement();
+ var uxArray = ns.app.accordion.getUxArray(id);
+
+ for (var i = 0; i < uxArray.length; i++) {
+ uxArray[i].removeDataElement();
+ }
}
}
};
@@ -1325,6 +1617,42 @@
}
});
+ val = Ext.create('Ext.panel.Panel', {
+ bodyStyle: 'padding: 1px',
+ width: defaultWidth,
+ height: 220,
+ items: value,
+ tbar: {
+ height: 25,
+ style: 'padding: 1px',
+ items: [
+ {
+ xtype: 'label',
+ height: 22,
+ style: 'padding-left: 6px; line-height: 22px',
+ text: NS.i18n.value
+ },
+ '->',
+ aggregationType
+ ]
+ }
+ });
+
+ onCollapseDataDimensionsChange = function(value) {
+ toggleDataItems(value);
+ toggleValueGui(value);
+ };
+
+ collapseDataDimensions = Ext.create('Ext.form.field.Checkbox', {
+ boxLabel: NS.i18n.collapse_data_dimensions,
+ style: 'margin-left: 3px',
+ listeners: {
+ change: function(chb, value) {
+ onCollapseDataDimensionsChange(value);
+ }
+ }
+ });
+
selectPanel = Ext.create('Ext.panel.Panel', {
bodyStyle: 'border:0 none',
items: [
@@ -1350,37 +1678,25 @@
bodyStyle: 'border:0 none',
items: [
row,
- {
- xtype: 'panel',
- bodyStyle: 'padding: 1px',
- width: defaultWidth,
- height: 220,
- items: value,
- tbar: {
- height: 25,
- style: 'padding: 1px',
- items: [
- {
- xtype: 'label',
- height: 22,
- style: 'padding-left: 6px; line-height: 22px',
- text: NS.i18n.value
- },
- '->',
- aggregationType
- ]
- }
- }
+ val
]
}
]
});
- addDimension = function(record, store, excludedStores) {
- var store = dimensionStoreMap[record.id] || store || filterStore;
+ addDimension = function(record, store, excludedStores, force) {
+ store = store && force ? store : dimensionStoreMap[record.id] || store || filterStore;
- if (!hasDimension(record.id, excludedStores) && record.id !== value.getValue()) {
- store.add(record);
+ if (hasDimension(record.id, excludedStores)) {
+ if (force) {
+ removeDimension(record.id);
+ store.add(record);
+ }
+ }
+ else {
+ if (record.id !== value.getValue()) {
+ store.add(record);
+ }
}
};
@@ -1432,6 +1748,10 @@
map[record.data.id] = fixedFilterStore;
});
+ //valueStore.each(function(record) {
+ //map[record.data.id] = valueStore;
+ //});
+
return map;
};
@@ -1462,6 +1782,57 @@
fixedFilterStore.setListHeight();
};
+ toggleDataItems = function(param) {
+ var stores = [colStore, rowStore, filterStore, fixedFilterStore],
+ collapse = Ext.isObject(param) && param.collapseDataItems ? param.collapseDataItems : param,
+ keys = ['ou', 'pe', 'dates'],
+ dy = ['dy'],
+ keys;
+
+ // clear filters
+ for (var i = 0, store; i < stores.length; i++) {
+ stores[i].clearFilter();
+ }
+
+ // add dy if it does not exist
+ if (!hasDimension('dy')) {
+ addDimension({
+ id: 'dy',
+ name: NS.i18n.data
+ }, rowStore);
+ }
+
+ // keys
+ if (collapse) { // included keys
+ keys = ['ou', 'pe', 'dates', 'dy'];
+ }
+ else { // excluded keys
+ keys = ['dy'];
+ }
+
+ // data items
+ for (var i = 0, store, include; i < stores.length; i++) {
+ store = stores[i];
+
+ if (collapse) {
+ store.filterBy(function(record, id) {
+ return Ext.Array.contains(keys, record.data.id);
+ });
+ }
+ else {
+ store.filterBy(function(record, id) {
+ return !Ext.Array.contains(keys, record.data.id);
+ });
+ }
+ }
+ };
+
+ toggleValueGui = function(param) {
+ var collapse = Ext.isObject(param) && param.collapseDataItems ? param.collapseDataItems : param;
+
+ val.setDisabled(collapse);
+ };
+
window = Ext.create('Ext.window.Window', {
title: NS.i18n.table_layout,
bodyStyle: 'background-color:#fff; padding:' + margin + 'px',
@@ -1469,6 +1840,7 @@
autoShow: true,
modal: true,
resizable: false,
+ dataType: dataType,
colStore: colStore,
rowStore: rowStore,
fixedFilterStore: fixedFilterStore,
@@ -1478,9 +1850,14 @@
addDimension: addDimension,
removeDimension: removeDimension,
hasDimension: hasDimension,
+ dimensionStoreMap: dimensionStoreMap,
saveState: saveState,
resetData: resetData,
reset: reset,
+ onCollapseDataDimensionsChange: onCollapseDataDimensionsChange,
+ collapseDataDimensions: collapseDataDimensions,
+ toggleDataItems: toggleDataItems,
+ toggleValueGui: toggleValueGui,
getValueConfig: function() {
var config = {},
valueId = value.getValue();
@@ -1492,23 +1869,42 @@
return config;
},
- hideOnBlur: true,
+ getOptions: function() {
+ return {
+ collapseDataDimensions: collapseDataDimensions.getValue()
+ };
+ },
+ hideOnBlur: true,
items: selectPanel,
bbar: [
'->',
{
text: NS.i18n.hide,
- handler: function() {
- window.hide();
- }
+ listeners: {
+ added: function(b) {
+ b.on('click', function() {
+ window.hide();
+ });
+ }
+ }
},
{
text: '<b>' + NS.i18n.update + '</b>',
- handler: function() {
- ns.app.viewport.update();
-
- window.hide();
- }
+ listeners: {
+ added: function(b) {
+ b.on('click', function() {
+ var config = ns.core.web.report.getLayoutConfig();
+
+ if (!config) {
+ return;
+ }
+
+ ns.core.web.report.getData(config, false);
+
+ window.hide();
+ });
+ }
+ }
}
],
listeners: {
@@ -3108,8 +3504,10 @@
baseWidth = 446,
toolWidth = 36,
+ accBaseWidth = baseWidth - 2,
- accBaseWidth = baseWidth - 2;
+ conf = ns.core.conf,
+ rp = conf.period.relativePeriods;
// stores
@@ -3227,14 +3625,13 @@
levels = [],
groups = [],
- optionsWindow = ns.app.aggregateOptionsWindow;
+ optionsWindow = ns.app.aggregateOptionsWindow;
reset();
+ //ns.app.typeToolbar.setType(layout.dataType);
ns.app.aggregateLayoutWindow.reset();
-
- // type
- ns.app.viewport.chartType.setChartType(layout.type);
+ //ns.app.queryLayoutWindow.reset();
// data
programStore.add(layout.program);
@@ -3373,10 +3770,12 @@
var load;
programId = layout ? layout.program.id : programId;
+
+ // reset
stage.clearValue();
-
dataElementsByStageStore.removeAll();
dataElementSelected.removeAllDataElements(true);
+ ns.app.aggregateLayoutWindow.value.resetData();
load = function(stages) {
stage.enable();
@@ -3623,16 +4022,16 @@
return hasDataElement;
},
- getUxById: function(dataElementId) {
- var ux;
+ getUxArrayById: function(dataElementId) {
+ var uxArray = [];
this.items.each(function(item) {
if (item.dataElement.id === dataElementId) {
- ux = item;
+ uxArray.push(item);
}
});
- return ux;
+ return uxArray;
},
removeAllDataElements: function(reset) {
var items = this.items.items,
@@ -3652,6 +4051,7 @@
index = index || dataElementSelected.items.items.length;
getUxType = function(element) {
+
if (Ext.isObject(element.optionSet) && Ext.isString(element.optionSet.id)) {
return 'Ext.ux.panel.OrganisationUnitGroupSetContainer';
}
@@ -3690,6 +4090,7 @@
}
ns.app.aggregateLayoutWindow.removeDimension(element.id, ns.app.aggregateLayoutWindow.valueStore);
+ //ns.app.queryLayoutWindow.removeDimension(element.id);
}
};
@@ -3706,8 +4107,8 @@
selectDataElements = function(items, layout) {
var dataElements = [],
allElements = [],
- fixedFilterElementIds = [],
aggWindow = ns.app.aggregateLayoutWindow,
+ //queryWindow = ns.app.queryLayoutWindow,
includeKeys = ['int', 'number', 'bool', 'boolean', 'trueOnly'],
ignoreKeys = ['pe', 'ou'],
recordMap = {
@@ -3715,14 +4116,15 @@
'ou': {id: 'ou', name: 'Organisation units'}
},
extendDim = function(dim) {
+ var md = ns.app.response.metaData,
+ dimConf = ns.core.conf.finals.dimension;
+
dim.id = dim.id || dim.dimension;
- dim.name = dim.name || ns.app.response.metaData.names[dim.dimension];
+ dim.name = dim.name || md.names[dim.dimension] || dimConf.objectNameMap[dim.dimension].name;
return dim;
};
- fixedFilterElementIds = [];
-
// data element objects
for (var i = 0, item; i < items.length; i++) {
item = items[i];
@@ -3771,7 +4173,7 @@
element.name = element.name || element.displayName;
recordMap[element.id] = element;
- // add ux if not selected as value
+ // dont add ux if dim is selected as value
if (element.id !== aggWindow.value.getValue()) {
ux = addUxFromDataElement(element);
@@ -3780,49 +4182,54 @@
}
}
- store = Ext.Array.contains(includeKeys, element.type) || element.optionSet ? aggWindow.rowStore : aggWindow.fixedFilterStore;
-
- if (store === aggWindow.fixedFilterStore) {
- fixedFilterElementIds.push(element.id);
- }
+ store = Ext.Array.contains(includeKeys, element.type) || element.optionSet ? aggWindow.colStore : aggWindow.fixedFilterStore;
aggWindow.addDimension(element, store, valueStore);
+ //queryWindow.colStore.add(element);
}
- if (layout) { // && layout.dataType === 'aggregated_values') {
- aggWindow.reset(true);
-
- if (layout.startDate && layout.endDate) {
- aggWindow.fixedFilterStore.add({id: dimConf.startEndDate.value, name: dimConf.startEndDate.name});
- }
-
- if (layout.columns) {
+ // favorite
+ if (layout && layout.dataType === 'aggregated_values') {
+
+ // start end dates
+ if (layout.startDate && layout.endDate) {
+ aggWindow.fixedFilterStore.add({id: dimConf.startEndDate.value, name: dimConf.startEndDate.name});
+ }
+
+ // columns
+ if (layout.columns) {
for (var i = 0, record, dim; i < layout.columns.length; i++) {
dim = layout.columns[i];
record = recordMap[dim.dimension];
- aggWindow.colStore.add(record || extendDim(Ext.clone(dim)));
+ aggWindow.addDimension(record || extendDim(Ext.clone(dim)), aggWindow.colStore, null, true);
}
}
- if (layout.rows) {
+ // rows
+ if (layout.rows) {
for (var i = 0, record, dim; i < layout.rows.length; i++) {
dim = layout.rows[i];
record = recordMap[dim.dimension];
- aggWindow.rowStore.add(record || extendDim(Ext.clone(dim)));
+ aggWindow.addDimension(record || extendDim(Ext.clone(dim)), aggWindow.rowStore, null, true);
}
}
- if (layout.filters) {
+ // filters
+ if (layout.filters) {
for (var i = 0, store, record, dim; i < layout.filters.length; i++) {
dim = layout.filters[i];
record = recordMap[dim.dimension];
store = Ext.Array.contains(includeKeys, element.type) || element.optionSet ? aggWindow.filterStore : aggWindow.fixedFilterStore;
- store.add(record || extendDim(Ext.clone(dim)));
+ aggWindow.addDimension(record || extendDim(Ext.clone(dim)), store, null, true);
}
}
+
+ // collapse data dimensions
+ aggWindow.collapseDataDimensions.setValue(layout.collapseDataDimensions);
+ aggWindow.onCollapseDataDimensionsChange(layout.collapseDataDimensions);
}
};
@@ -5414,6 +5821,9 @@
return;
}
+ // dy
+ map['dy'] = [{dimension: 'dy'}];
+
// pe
if (periodMode.getValue() === 'dates') {
view.startDate = startDate.getSubmitValue();
@@ -5459,110 +5869,71 @@
//map['longitude'] = [{dimension: 'longitude'}];
//map['latitude'] = [{dimension: 'latitude'}];
- // dimensions
- if (layoutWindow.colStore) {
- layoutWindow.colStore.each(function(item) {
- a = map[item.data.id] || [];
-
- if (a.length) {
- if (a.length === 1) {
- columns.push(a[0]);
- }
- else {
- var dim;
-
- for (var i = 0; i < a.length; i++) {
- if (!dim) {
- dim = a[i];
- }
- else {
- dim.filter += ':' + a[i].filter;
- }
- }
-
- columns.push(dim);
- }
- }
- });
- }
-
- if (layoutWindow.rowStore) {
- layoutWindow.rowStore.each(function(item) {
- a = map[item.data.id] || [];
-
- if (a.length) {
- if (a.length === 1) {
- rows.push(a[0]);
- }
- else {
- var dim;
-
- for (var i = 0; i < a.length; i++) {
- if (!dim) {
- dim = a[i];
- }
- else {
- dim.filter += ':' + a[i].filter;
- }
- }
-
- rows.push(dim);
- }
- }
- });
- }
-
- if (layoutWindow.filterStore) {
- layoutWindow.filterStore.each(function(item) {
- a = map[item.data.id] || [];
-
- if (a.length) {
- if (a.length === 1) {
- filters.push(a[0]);
- }
- else {
- var dim;
-
- for (var i = 0; i < a.length; i++) {
- if (!dim) {
- dim = a[i];
- }
- else {
- dim.filter += ':' + a[i].filter;
- }
- }
-
- filters.push(dim);
- }
- }
- });
- }
-
- if (layoutWindow.fixedFilterStore) {
- layoutWindow.fixedFilterStore.each(function(item) {
- a = map[item.data.id] || [];
-
- if (a.length) {
- if (a.length === 1) {
- filters.push(a[0]);
- }
- else {
- var dim;
-
- for (var i = 0; i < a.length; i++) {
- if (!dim) {
- dim = a[i];
- }
- else {
- dim.filter += ':' + a[i].filter;
- }
- }
-
- filters.push(dim);
- }
- }
- });
- }
+ addAxisDimension = function(a, axis) {
+ if (a.length) {
+ if (a.length === 1) {
+ axis.push(a[0]);
+ }
+ else {
+ var dim;
+
+ for (var i = 0; i < a.length; i++) {
+ if (!dim) { //todo ??
+ dim = a[i];
+ }
+ else {
+ dim.filter += ':' + a[i].filter;
+ }
+ }
+
+ axis.push(dim);
+ }
+ }
+ };
+
+ // columns
+ store = layoutWindow.colStore;
+
+ if (store) {
+ data = store.snapshot || store.data;
+
+ data.each(function(item) {
+ addAxisDimension(map[item.data.id] || [], columns);
+ });
+ }
+
+ // rows
+ store = layoutWindow.rowStore;
+
+ if (store) {
+ data = store.snapshot || store.data;
+
+ data.each(function(item) {
+ addAxisDimension(map[item.data.id] || [], rows);
+ });
+ }
+
+ // filters
+ store = layoutWindow.filterStore;
+
+ if (store) {
+ data = store.snapshot || store.data;
+
+ data.each(function(item) {
+ addAxisDimension(map[item.data.id] || [], filters);
+ });
+ }
+
+ // fixed filters
+ store = layoutWindow.fixedFilterStore;
+
+ if (store) {
+ data = store.snapshot || store.data;
+
+ data.each(function(item) {
+ addAxisDimension(map[item.data.id] || [], filters);
+ });
+ }
if (columns.length) {
view.columns = columns;
@@ -5644,6 +6015,10 @@
setGui: setGui,
getView: getView,
+ getUxArray: function(id) {
+ return dataElementSelected.getUxArrayById(id);
+ },
+
listeners: {
added: function() {
ns.app.accordion = this;
@@ -7157,18 +7532,17 @@
}
},
afterrender: function(p) {
- var liStyle = 'padding:3px 10px; color:#333',
- html = '';
+ var html = '';
- html += '<div style="padding:20px">';
- html += '<div style="font-size:14px; padding-bottom:8px">' + NS.i18n.example1 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example2 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example3 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example4 + '</div>';
- html += '<div style="font-size:14px; padding-top:20px; padding-bottom:8px">' + NS.i18n.example5 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example6 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example7 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example8 + '</div>';
+ html += '<div class="ns-viewport-text" style="padding:20px">';
+ html += '<h3>' + NS.i18n.example1 + '</h3>';
+ html += '<div>- ' + NS.i18n.example2 + '</div>';
+ html += '<div>- ' + NS.i18n.example3 + '</div>';
+ html += '<div>- ' + NS.i18n.example4 + '</div>';
+ html += '<h3 style="padding-top:20px">' + NS.i18n.example5 + '</h3>';
+ html += '<div>- ' + NS.i18n.example6 + '</div>';
+ html += '<div>- ' + NS.i18n.example7 + '</div>';
+ html += '<div>- ' + NS.i18n.example8 + '</div>';
html += '</div>';
p.update(html);
@@ -7470,6 +7844,15 @@
}
});
+ // legend sets
+ requests.push({
+ url: contextPath + '/api/legendSets.json?fields=id,name,legends[id,name,startValue,endValue,color]&paging=false',
+ success: function(r) {
+ init.legendSets = Ext.decode(r.responseText).legendSets || [];
+ fn();
+ }
+ });
+
// dimensions
requests.push({
url: init.contextPath + '/api/organisationUnitGroupSets.json?fields=id,' + namePropertyUrl + '&paging=false',
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/core.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/core.js 2015-04-03 15:43:32 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/scripts/core.js 2015-04-09 07:52:01 +0000
@@ -3,16 +3,509 @@
// ext config
Ext.Ajax.method = 'GET';
+ Ext.isIE = (/trident/.test(Ext.userAgent));
+
+ Ext.isIE11 = Ext.isIE && (/rv:11.0/.test(Ext.userAgent));
+
+ Ext.util.CSS.createStyleSheet = function(cssText, id) {
+ var ss,
+ head = document.getElementsByTagName("head")[0],
+ styleEl = document.createElement("style");
+
+ styleEl.setAttribute("type", "text/css");
+
+ if (id) {
+ styleEl.setAttribute("id", id);
+ }
+
+ if (Ext.isIE && !Ext.isIE11) {
+ head.appendChild(styleEl);
+ ss = styleEl.styleSheet;
+ ss.cssText = cssText;
+ }
+ else {
+ try {
+ styleEl.appendChild(document.createTextNode(cssText));
+ }
+ catch(e) {
+ styleEl.cssText = cssText;
+ }
+ head.appendChild(styleEl);
+ ss = styleEl.styleSheet ? styleEl.styleSheet : (styleEl.sheet || document.styleSheets[document.styleSheets.length-1]);
+ }
+ this.cacheStyleSheet(ss);
+ return ss;
+ };
+
// override
+ Ext.override(Ext.chart.Chart, {
+ insetPaddingObject: {},
+
+ alignAxes: function() {
+ var me = this,
+ axes = me.axes,
+ legend = me.legend,
+ edges = ['top', 'right', 'bottom', 'left'],
+ chartBBox,
+ insetPadding = me.insetPadding,
+ insetPaddingObject = me.insetPaddingObject,
+ insets = {
+ top: insetPaddingObject.top || insetPadding,
+ right: insetPaddingObject.right || insetPadding,
+ bottom: insetPaddingObject.bottom || insetPadding,
+ left: insetPaddingObject.left || insetPadding
+ };
+
+ function getAxis(edge) {
+ var i = axes.findIndex('position', edge);
+ return (i < 0) ? null : axes.getAt(i);
+ }
+
+
+ Ext.each(edges, function(edge) {
+ var isVertical = (edge === 'left' || edge === 'right'),
+ axis = getAxis(edge),
+ bbox;
+
+
+ if (legend !== false) {
+ if (legend.position === edge) {
+ bbox = legend.getBBox();
+ insets[edge] += (isVertical ? bbox.width : bbox.height) + insets[edge];
+ }
+ }
+
+
+
+ if (axis && axis.bbox) {
+ bbox = axis.bbox;
+ insets[edge] += (isVertical ? bbox.width : bbox.height);
+ }
+ });
+
+ chartBBox = {
+ x: insets.left,
+ y: insets.top,
+ width: me.curWidth - insets.left - insets.right,
+ height: me.curHeight - insets.top - insets.bottom
+ };
+ me.chartBBox = chartBBox;
+
+
+
+ axes.each(function(axis) {
+ var pos = axis.position,
+ isVertical = (pos === 'left' || pos === 'right');
+
+ axis.x = (pos === 'right' ? chartBBox.x + chartBBox.width : chartBBox.x);
+ axis.y = (pos === 'top' ? chartBBox.y : chartBBox.y + chartBBox.height);
+ axis.width = (isVertical ? chartBBox.width : chartBBox.height);
+ axis.length = (isVertical ? chartBBox.height : chartBBox.width);
+ });
+ }
+ });
+
Ext.override(Ext.chart.series.Line, {
drawSeries: function() {
var ak=this,au=ak.chart,S=au.axes,ao=au.getChartStore(),V=ao.getCount(),u=ak.chart.surface,am={},R=ak.group,K=ak.showMarkers,aA=ak.markerGroup,D=au.shadow,C=ak.shadowGroups,X=ak.shadowAttributes,O=ak.smooth,q=C.length,ar=["M"],T=["M"],d=["M"],b=["M"],J=au.markerIndex,ai=[].concat(ak.axis),ah,av=[],ag={},aa=[],v={},I=false,Q=[],az=ak.markerStyle,Z=ak.style,t=ak.colorArrayStyle,P=t&&t.length||0,L=Ext.isNumber,aw=ak.seriesIdx,g=ak.getAxesForXAndYFields(),l=g.xAxis,ay=g.yAxis,ac,h,ab,ad,A,c,ae,H,G,f,e,s,r,W,N,M,at,m,F,E,aB,n,p,B,a,Y,af,z,aq,w,ap,o,ax,an,al,U,k,aj;if(ak.fireEvent("beforedraw",ak)===false){return}if(!V||ak.seriesIsHidden){aj=this.items;if(aj){for(N=0,at=aj.length;N<at;++N){if(aj[N].sprite){aj[N].sprite.hide(true)}}}return}an=Ext.apply(az||{},ak.markerConfig);U=an.type;delete an.type;al=Z;if(!al["stroke-width"]){al["stroke-width"]=0.5}if(J&&aA&&aA.getCount()){for(N=0;N<J;N++){E=aA.getAt(N);aA.remove(E);aA.add(E);aB=aA.getAt(aA.getCount()-2);E.setAttributes({x:0,y:0,translate:{x:aB.attr.translation.x,y:aB.attr.translation.y}},true)}}ak.unHighlightItem();ak.cleanHighlights();ak.setBBox();am=ak.bbox;ak.clipRect=[am.x,am.y,am.width,am.height];for(N=0,at=ai.length;N<at;N++){m=S.get(ai[N]);if(m){F=m.calcEnds();if(m.position=="top"||m.position=="bottom"){z=F.from;aq=F.to}else{w=F.from;ap=F.to}}}if(ak.xField&&!L(z)&&(l=="bottom"||l=="top")&&!S.get(l)){m=Ext.create("Ext.chart.axis.Axis",{chart:au,fields:[].concat(ak.xField)}).calcEnds();z=m.from;aq=m.to}if(ak.yField&&!L(w)&&(ay=="right"||ay=="left")&&!S.get(ay)){m=Ext.create("Ext.chart.axis.Axis",{chart:au,fields:[].concat(ak.yField)}).calcEnds();w=m.from;ap=m.to}if(isNaN(z)){z=0;Y=am.width/((V-1)||1)}else{Y=am.width/((aq-z)||(V-1)||1)}if(isNaN(w)){w=0;af=am.height/((V-1)||1)}else{af=am.height/((ap-w)||(V-1)||1)}ak.eachRecord(function(j,x){p=j.get(ak.xField);if(typeof p=="string"||typeof p=="object"&&!Ext.isDate(p)||l&&S.get(l)&&S.get(l).type=="Category"){if(p in ag){p=ag[p]}else{p=ag[p]=x}}B=j.get(ak.yField);if(typeof B=="undefined"||(typeof B=="string"&&!B)){if(Ext.isDefined(Ext.global.console)){Ext.global.console.warn("[Ext.chart.series.Line] Skipping a store element with an undefined value at ",j,p,B)}return}if(typeof B=="object"&&!Ext.isDate(B)||ay&&S.get(ay)&&S.get(ay).type=="Category"){B=x}Q.push(x);av.push(p);aa.push(B)});at=av.length;if(at>am.width){a=ak.shrink(av,aa,am.width);av=a.x;aa=a.y}ak.items=[];k=0;at=av.length;for(N=0;N<at;N++){p=av[N];B=aa[N];if(B===false){if(T.length==1){T=[]}I=true;ak.items.push(false);continue}else{H=(am.x+(p-z)*Y).toFixed(2);G=((am.y+am.height)-(B-w)*af).toFixed(2);if(I){I=false;T.push("M")}T=T.concat([H,G])}if((typeof r=="undefined")&&(typeof G!="undefined")){r=G;s=H}if(!ak.line||au.resizing){ar=ar.concat([H,am.y+am.height/2])}if(au.animate&&au.resizing&&ak.line){ak.line.setAttributes({path:ar},true);if(ak.fillPath){ak.fillPath.setAttributes({path:ar,opacity:0.2},true)}if(ak.line.shadows){ac=ak.line.shadows;for(M=0,q=ac.length;M<q;M++){h=ac[M];h.setAttributes({path:ar},true)}}}if(K){E=aA.getAt(k++);if(!E){E=Ext.chart.Shape[U](u,Ext.apply({group:[R,aA],x:0,y:0,translate:{x:+(f||H),y:e||(am.y+am.height/2)},value:'"'+p+", "+B+'"',zIndex:4000},an));E._to={translate:{x:+H,y:+G}}}else{E.setAttributes({value:'"'+p+", "+B+'"',x:0,y:0,hidden:false},true);E._to={translate:{x:+H,y:+G}}}}ak.items.push({series:ak,value:[p,B],point:[H,G],sprite:E,storeItem:ao.getAt(Q[N])});f=H;e=G}if(T.length<=1){return}if(ak.smooth){b=Ext.draw.Draw.smooth(T,L(O)?O:ak.defaultSmoothness)}d=O?b:T;if(au.markerIndex&&ak.previousPath){ad=ak.previousPath;if(!O){Ext.Array.erase(ad,1,2)}}else{ad=T}if(!ak.line){ak.line=u.add(Ext.apply({type:"path",group:R,path:ar,stroke:al.stroke||al.fill},al||{}));if(D){ak.line.setAttributes(Ext.apply({},ak.shadowOptions),true)}ak.line.setAttributes({fill:"none",zIndex:3000});if(!al.stroke&&P){ak.line.setAttributes({stroke:t[aw%P]},true)}if(D){ac=ak.line.shadows=[];for(ab=0;ab<q;ab++){ah=X[ab];ah=Ext.apply({},ah,{path:ar});h=u.add(Ext.apply({},{type:"path",group:C[ab]},ah));ac.push(h)}}}if(ak.fill){c=d.concat([["L",H,am.y+am.height],["L",s,am.y+am.height],["L",s,r]]);if(!ak.fillPath){ak.fillPath=u.add({group:R,type:"path",opacity:al.opacity||0.3,fill:al.fill||t[aw%P],path:ar})}}W=K&&aA.getCount();if(au.animate){A=ak.fill;o=ak.line;ae=ak.renderer(o,false,{path:d},N,ao);Ext.apply(ae,al||{},{stroke:al.stroke||al.fill});delete ae.fill;o.show(true);if(au.markerIndex&&ak.previousPath){ak.animation=ax=ak.onAnimate(o,{to:ae,from:{path:ad}})}else{ak.animation=ax=ak.onAnimate(o,{to:ae})}if(D){ac=o.shadows;for(M=0;M<q;M++){ac[M].show(true);if(au.markerIndex&&ak.previousPath){ak.onAnimate(ac[M],{to:{path:d},from:{path:ad}})}else{ak.onAnimate(ac[M],{to:{path:d}})}}}if(A){ak.fillPath.show(true);ak.onAnimate(ak.fillPath,{to:Ext.apply({},{path:c,fill:al.fill||t[aw%P],"stroke-width":0},al||{})})}if(K){k=0;for(N=0;N<at;N++){if(ak.items[N]){n=aA.getAt(k++);if(n){ae=ak.renderer(n,ao.getAt(N),n._to,N,ao);ak.onAnimate(n,{to:Ext.apply(ae,an||{})});n.show(true)}}}for(;k<W;k++){n=aA.getAt(k);n.hide(true)}}}else{ae=ak.renderer(ak.line,false,{path:d,hidden:false},N,ao);Ext.apply(ae,al||{},{stroke:al.stroke||al.fill});delete ae.fill;ak.line.setAttributes(ae,true);if(D){ac=ak.line.shadows;for(M=0;M<q;M++){ac[M].setAttributes({path:d,hidden:false},true)}}if(ak.fill){ak.fillPath.setAttributes({path:c,hidden:false},true)}if(K){k=0;for(N=0;N<at;N++){if(ak.items[N]){n=aA.getAt(k++);if(n){ae=ak.renderer(n,ao.getAt(N),n._to,N,ao);n.setAttributes(Ext.apply(an||{},ae||{}),true);n.show(true)}}}for(;k<W;k++){n=aA.getAt(k);n.hide(true)}}}if(au.markerIndex){if(ak.smooth){Ext.Array.erase(T,1,2)}else{Ext.Array.splice(T,1,0,T[1],T[2])}ak.previousPath=T}ak.renderLabels();ak.renderCallouts();ak.fireEvent("draw",ak);
}
});
- Ext.isIE = function() {
- return /trident/.test(Ext.userAgent);
- }();
+ Ext.override(Ext.chart.Legend, {
+ updatePosition: function() {
+ var me = this,
+ x, y,
+ legendWidth = me.width,
+ legendHeight = me.height,
+ padding = me.padding,
+ chart = me.chart,
+ chartBBox = chart.chartBBox,
+ insets = chart.insetPadding,
+ chartWidth = chartBBox.width - (insets * 2),
+ chartHeight = chartBBox.height - (insets * 2),
+ chartX = chartBBox.x + insets,
+ chartY = chartBBox.y + insets,
+ surface = chart.surface,
+ mfloor = Math.floor;
+
+ if (me.isDisplayed()) {
+ // Find the position based on the dimensions
+ switch(me.position) {
+ case "left":
+ x = insets;
+ y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
+ break;
+ case "right":
+ x = mfloor(surface.width - legendWidth) - insets;
+ y = mfloor(chartY + chartHeight / 2 - legendHeight / 2);
+ break;
+ case "top":
+ x = mfloor((chartX + chartBBox.width) / 2 - legendWidth / 2) - 7;
+ y = insets;
+ break;
+ case "bottom":
+ x = mfloor(chartX + chartWidth / 2 - legendWidth / 2);
+ y = mfloor(surface.height - legendHeight) - insets;
+ break;
+ default:
+ x = mfloor(me.origX) + insets;
+ y = mfloor(me.origY) + insets;
+ }
+ me.x = x;
+ me.y = y;
+
+ // Update the position of each item
+ Ext.each(me.items, function(item) {
+ item.updatePosition();
+ });
+ // Update the position of the outer box
+ me.boxSprite.setAttributes(me.getBBox(), true);
+ }
+ }
+ });
+
+ Ext.override(Ext.chart.LegendItem, {
+ createLegend: function(config) {
+ var me = this,
+ index = config.yFieldIndex,
+ series = me.series,
+ seriesType = series.type,
+ idx = me.yFieldIndex,
+ legend = me.legend,
+ surface = me.surface,
+ refX = legend.x + me.x,
+ refY = legend.y + me.y,
+ bbox, z = me.zIndex,
+ markerConfig, label, mask,
+ radius, toggle = false,
+ seriesStyle = Ext.apply(series.seriesStyle, series.style),
+ labelMarkerSize = legend.labelMarkerSize || 10;
+
+ function getSeriesProp(name) {
+ var val = series[name];
+ return (Ext.isArray(val) ? val[idx] : val);
+ }
+
+ label = me.add('label', surface.add({
+ type: 'text',
+ x: 30,
+ y: 0,
+ zIndex: z || 0,
+ font: legend.labelFont,
+ fill: legend.labelColor || '#000',
+ text: getSeriesProp('title') || getSeriesProp('yField')
+ }));
+
+ if (seriesType === 'line' || seriesType === 'scatter') {
+ if (seriesType === 'line') {
+ me.add('line', surface.add({
+ type: 'path',
+ path: 'M0.5,0.5L16.5,0.5',
+ zIndex: z,
+ "stroke-width": series.lineWidth,
+ "stroke-linejoin": "round",
+ "stroke-dasharray": series.dash,
+ stroke: seriesStyle.stroke || '#000',
+ style: {
+ cursor: 'pointer'
+ }
+ }));
+ }
+ if (series.showMarkers || seriesType === 'scatter') {
+ markerConfig = Ext.apply(series.markerStyle, series.markerConfig || {});
+ me.add('marker', Ext.chart.Shape[markerConfig.type](surface, {
+ fill: markerConfig.fill,
+ x: 8.5,
+ y: 0.5,
+ zIndex: z,
+ radius: markerConfig.radius || markerConfig.size,
+ style: {
+ cursor: 'pointer'
+ }
+ }));
+ }
+ }
+ else {
+ me.add('box', surface.add({
+ type: 'rect',
+ zIndex: z,
+ x: 6,
+ y: 0,
+ width: labelMarkerSize,
+ height: labelMarkerSize,
+ fill: series.getLegendColor(index),
+ style: {
+ cursor: 'pointer'
+ }
+ }));
+ }
+
+ me.setAttributes({
+ hidden: false
+ }, true);
+
+ bbox = me.getBBox();
+
+ mask = me.add('mask', surface.add({
+ type: 'rect',
+ x: bbox.x,
+ y: bbox.y,
+ width: bbox.width || 20,
+ height: bbox.height || 20,
+ zIndex: (z || 0) + 1000,
+ fill: '#f00',
+ opacity: 0,
+ style: {
+ 'cursor': 'pointer'
+ }
+ }));
+
+
+ me.on('mouseover', function() {
+ label.setStyle({
+ 'font-weight': 'bold'
+ });
+ mask.setStyle({
+ 'cursor': 'pointer'
+ });
+ series._index = index;
+ series.highlightItem();
+ }, me);
+
+ me.on('mouseout', function() {
+ label.setStyle({
+ 'font-weight': 'normal'
+ });
+ series._index = index;
+ series.unHighlightItem();
+ }, me);
+
+ if (!series.visibleInLegend(index)) {
+ toggle = true;
+ label.setAttributes({
+ opacity: 0.5
+ }, true);
+ }
+
+ me.on('mousedown', function() {
+ if (!toggle) {
+ series.hideAll();
+ label.setAttributes({
+ opacity: 0.5
+ }, true);
+ } else {
+ series.showAll();
+ label.setAttributes({
+ opacity: 1
+ }, true);
+ }
+ toggle = !toggle;
+ }, me);
+ me.updatePosition({x:0, y:0});
+ }
+ });
+
+ Ext.override(Ext.chart.axis.Axis, {
+ drawHorizontalLabels: function() {
+ var me = this,
+ labelConf = me.label,
+ floor = Math.floor,
+ max = Math.max,
+ axes = me.chart.axes,
+ position = me.position,
+ inflections = me.inflections,
+ ln = inflections.length,
+ labels = me.labels,
+ labelGroup = me.labelGroup,
+ maxHeight = 0,
+ ratio,
+ gutterY = me.chart.maxGutter[1],
+ ubbox, bbox, point, prevX, prevLabel,
+ projectedWidth = 0,
+ textLabel, attr, textRight, text,
+ label, last, x, y, i, firstLabel;
+
+ last = ln - 1;
+ // get a reference to the first text label dimensions
+ point = inflections[0];
+ firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0]));
+ ratio = Math.floor(Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0)));
+
+ for (i = 0; i < ln; i++) {
+ point = inflections[i];
+ text = me.label.renderer(labels[i]) || '';
+ textLabel = me.getOrCreateLabel(i, text);
+ bbox = textLabel._bbox;
+ maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding);
+ x = floor(point[0] - (ratio? bbox.height : bbox.width) / 2);
+ if (me.chart.maxGutter[0] == 0) {
+ if (i == 0 && axes.findIndex('position', 'left') == -1) {
+ x = point[0];
+ }
+ else if (i == last && axes.findIndex('position', 'right') == -1) {
+ x = point[0] - bbox.width;
+ }
+ }
+ if (position == 'top') {
+ y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2);
+ }
+ else {
+ y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2);
+ }
+
+ var moveLabels = labelConf.rotate && labelConf.rotate.degrees && !Ext.Array.contains([0,90,180,270,360], labelConf.rotate.degrees),
+ adjust = Math.floor((textLabel.text.length - 12) * -1 * 0.75),
+ newX = moveLabels ? point[0] - textLabel._bbox.width + adjust: x;
+
+ textLabel.setAttributes({
+ hidden: false,
+ x: newX,
+ y: y
+ }, true);
+
+ // skip label if there isn't available minimum space
+ if (i != 0 && (me.intersect(textLabel, prevLabel)
+ || me.intersect(textLabel, firstLabel))) {
+ textLabel.hide(true);
+ continue;
+ }
+
+ prevLabel = textLabel;
+ }
+
+ return maxHeight;
+ }
+ });
+
+ Ext.override(Ext.chart.axis.Radial, {
+ drawLabel: function() {
+ var chart = this.chart,
+ surface = chart.surface,
+ bbox = chart.chartBBox,
+ store = chart.store,
+ centerX = bbox.x + (bbox.width / 2),
+ centerY = bbox.y + (bbox.height / 2),
+ rho = Math.min(bbox.width, bbox.height) /2,
+ max = Math.max, round = Math.round,
+ labelArray = [], label,
+ fields = [], nfields,
+ categories = [], xField,
+ aggregate = !this.maximum,
+ maxValue = this.maximum || 0,
+ steps = this.steps, i = 0, j, dx, dy,
+ pi2 = Math.PI * 2,
+ cos = Math.cos, sin = Math.sin,
+ display = this.label.display,
+ draw = display !== 'none',
+ margin = 10,
+
+ labelColor = '#333',
+ labelFont = 'normal 9px sans-serif',
+ seriesStyle = chart.seriesStyle;
+
+ labelColor = seriesStyle ? seriesStyle.labelColor : labelColor;
+ labelFont = seriesStyle ? seriesStyle.labelFont : labelFont;
+
+ if (!draw) {
+ return;
+ }
+
+ //get all rendered fields
+ chart.series.each(function(series) {
+ fields.push(series.yField);
+ xField = series.xField;
+ });
+
+ //get maxValue to interpolate
+ store.each(function(record, i) {
+ if (aggregate) {
+ for (i = 0, nfields = fields.length; i < nfields; i++) {
+ maxValue = max(+record.get(fields[i]), maxValue);
+ }
+ }
+ categories.push(record.get(xField));
+ });
+ if (!this.labelArray) {
+ if (display != 'categories') {
+ //draw scale
+ for (i = 1; i <= steps; i++) {
+ label = surface.add({
+ type: 'text',
+ text: round(i / steps * maxValue),
+ x: centerX,
+ y: centerY - rho * i / steps,
+ 'text-anchor': 'middle',
+ 'stroke-width': 0.1,
+ stroke: '#333',
+ fill: labelColor,
+ font: labelFont
+ });
+ label.setAttributes({
+ hidden: false
+ }, true);
+ labelArray.push(label);
+ }
+ }
+ if (display != 'scale') {
+ //draw text
+ for (j = 0, steps = categories.length; j < steps; j++) {
+ dx = cos(j / steps * pi2) * (rho + margin);
+ dy = sin(j / steps * pi2) * (rho + margin);
+ label = surface.add({
+ type: 'text',
+ text: categories[j],
+ x: centerX + dx,
+ y: centerY + dy,
+ 'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start'),
+ fill: labelColor,
+ font: labelFont
+ });
+ label.setAttributes({
+ hidden: false
+ }, true);
+ labelArray.push(label);
+ }
+ }
+ }
+ else {
+ labelArray = this.labelArray;
+ if (display != 'categories') {
+ //draw values
+ for (i = 0; i < steps; i++) {
+ labelArray[i].setAttributes({
+ text: round((i + 1) / steps * maxValue),
+ x: centerX,
+ y: centerY - rho * (i + 1) / steps,
+ 'text-anchor': 'middle',
+ 'stroke-width': 0.1,
+ stroke: '#333',
+ fill: labelColor,
+ font: labelFont
+ }, true);
+ }
+ }
+ if (display != 'scale') {
+ //draw text
+ for (j = 0, steps = categories.length; j < steps; j++) {
+ dx = cos(j / steps * pi2) * (rho + margin);
+ dy = sin(j / steps * pi2) * (rho + margin);
+ if (labelArray[i + j]) {
+ labelArray[i + j].setAttributes({
+ type: 'text',
+ text: categories[j],
+ x: centerX + dx,
+ y: centerY + dy,
+ 'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start'),
+ fill: labelColor,
+ font: labelFont
+ }, true);
+ }
+ }
+ }
+ }
+ this.labelArray = labelArray;
+ }
+ });
// namespace
EV = {};
@@ -33,13 +526,15 @@
// conf
(function() {
+
+ // finals
conf.finals = {
dimension: {
data: {
value: 'data',
- name: NS.i18n.data,
- dimensionName: 'dx',
- objectName: 'dx',
+ name: NS.i18n.data || 'Data',
+ dimensionName: 'dy',
+ objectName: 'dy',
warning: {
filter: '...'//NS.i18n.wm_multiple_filter_ind_de
}
@@ -150,6 +645,7 @@
dimConf.objectNameMap[dimConf.organisationUnit.objectName] = dimConf.organisationUnit;
dimConf.objectNameMap[dimConf.dimension.objectName] = dimConf.dimension;
+ // period
conf.period = {
periodTypes: [
{id: 'Daily', name: NS.i18n.daily},
@@ -165,6 +661,26 @@
]
};
+ // aggregation type
+ conf.aggregationType = {
+ data: [
+ {id: 'COUNT', name: NS.i18n.count, text: NS.i18n.count},
+ {id: 'AVERAGE', name: NS.i18n.average, text: NS.i18n.average},
+ {id: 'SUM', name: NS.i18n.sum, text: NS.i18n.sum},
+ {id: 'STDDEV', name: NS.i18n.stddev, text: NS.i18n.stddev},
+ {id: 'VARIANCE', name: NS.i18n.variance, text: NS.i18n.variance},
+ {id: 'MIN', name: NS.i18n.min, text: NS.i18n.min},
+ {id: 'MAX', name: NS.i18n.max, text: NS.i18n.max}
+ ],
+ idNameMap: {}
+ };
+
+ for (var i = 0, obj; i < conf.aggregationType.data.length; i++) {
+ obj = conf.aggregationType.data[i];
+ conf.aggregationType.idNameMap[obj.id] = obj.text;
+ }
+
+ // gui layout
conf.layout = {
west_width: 452,
west_fill: 2,
@@ -200,6 +716,7 @@
multiselect_fill_reportingrates: 315
};
+ // chart
conf.chart = {
style: {
inset: 30,
@@ -210,6 +727,15 @@
}
};
+ // report
+ conf.report = {
+ digitGroupSeparator: {
+ 'comma': ',',
+ 'space': ' '
+ }
+ };
+
+ // url
conf.url = {
analysisFields: [
'*',
@@ -789,6 +1315,29 @@
return o;
};
+ support.prototype.array.getObjectDataById = function(array, sourceArray, properties, idProperty) {
+ array = Ext.Array.from(array);
+ sourceArray = Ext.Array.from(sourceArray);
+ properties = Ext.Array.from(properties);
+ idProperty = idProperty || 'id';
+
+ for (var i = 0, obj; i < array.length; i++) {
+ obj = array[i];
+
+ for (var j = 0, sourceObj; j < sourceArray.length; j++) {
+ sourceObj = sourceArray[j];
+
+ if (Ext.isString(obj[idProperty]) && sourceObj[idProperty] && obj[idProperty].indexOf(sourceObj.id) !== -1) {
+ for (var k = 0, property; k < properties.length; k++) {
+ property = properties[k];
+
+ obj[property] = sourceObj[property];
+ }
+ }
+ }
+ }
+ };
+
// object
support.prototype.object = {};
@@ -871,6 +1420,10 @@
support.prototype.number.prettyPrint = function(number, separator) {
separator = separator || 'space';
+ if (!Ext.isNumber(number)) {
+ return;
+ }
+
if (separator === 'none') {
return number;
}
@@ -1301,6 +1854,32 @@
return xLayout;
};
+ // collapse data dimensions?
+ (function() {
+ var keys = xLayout.collapseDataDimensions ? ['dy', 'pe', 'ou'] : ['dy'],
+ dimensionsToRemove = [];
+
+ // find dimensions to remove
+ for (var i = 0, dim; i < dimensions.length; i++) {
+ dim = dimensions[i];
+
+ if (xLayout.collapseDataDimensions && !Ext.Array.contains(keys, dim.dimension)) {
+ dimensionsToRemove.push(dim);
+ }
+ else if (!xLayout.collapseDataDimensions && Ext.Array.contains(keys, dim.dimension)) {
+ dimensionsToRemove.push(dim);
+ }
+ }
+
+ // remove dimensions
+ for (var i = 0, dim; i < dimensionsToRemove.length; i++) {
+ removeDimensionFromXLayout(dimensionsToRemove[i].dimension);
+ }
+
+ // update dimensions array
+ dimensions = Ext.Array.clean([].concat(xLayout.columns || [], xLayout.rows || [], xLayout.filters || []));
+ }());
+
// items
for (var i = 0, dim, header; i < dimensions.length; i++) {
dim = dimensions[i];
@@ -1320,30 +1899,34 @@
}
}
- // restore order for options
+ // restore item order
for (var i = 0, orgDim; i < originalDimensions.length; i++) {
orgDim = originalDimensions[i];
+ // if sorting and row dim, dont restore order
+ if (layout.sorting && Ext.Array.contains(xLayout.rowDimensionNames, orgDim.dimension)) {
+ continue;
+ }
+
+ // user specified options/legends
if (Ext.isString(orgDim.filter)) {
var a = orgDim.filter.split(':');
if (a[0] === 'IN' && a.length > 1 && Ext.isString(a[1])) {
- var options = a[1].split(';'),
- items = [];
+ var options = a[1].split(';');
- for (var j = 0, dim; j < dimensions.length; j++) {
+ for (var j = 0, dim, items; j < dimensions.length; j++) {
dim = dimensions[j];
if (dim.dimension === orgDim.dimension && dim.items && dim.items.length) {
- var items = [];
+ items = [];
for (var k = 0, option; k < options.length; k++) {
option = options[k];
for (var l = 0, item; l < dim.items.length; l++) {
item = dim.items[l];
-
- if (item.name === option) {
+ if (item.id === option || item.id === (dim.dimension + option)) {
items.push(item);
}
}
@@ -1354,6 +1937,21 @@
}
}
}
+ // no specified legends -> sort by start value
+ else if (orgDim.legendSet && orgDim.legendSet.id) {
+ for (var j = 0, dim, items; j < dimensions.length; j++) {
+ dim = dimensions[j];
+
+ if (dim.dimension === orgDim.dimension && dim.items && dim.items.length) {
+
+ // get start/end value
+ support.prototype.array.getObjectDataById(dim.items, init.idLegendSetMap[orgDim.legendSet.id].legends, ['startValue', 'endValue']);
+
+ // sort by start value
+ support.prototype.array.sort(dim.items, 'ASC', 'startValue');
+ }
+ }
+ }
}
// re-layout
@@ -1997,7 +2595,10 @@
web.analytics.getParamString = function(layout, format) {
var paramString,
dimensions = Ext.Array.clean([].concat(layout.columns || [], layout.rows || [])),
- ignoreKeys = ['longitude', 'latitude'],
+ ignoreKeys = ['dy', 'longitude', 'latitude'],
+ dataTypeMap = {
+ 'aggregated_values': 'aggregate'
+ },
nameItemsMap;
paramString = '/api/analytics/events/aggregate/' + layout.program.id + '.' + (format || 'json') + '?';
@@ -2025,6 +2626,13 @@
paramString += encodeURIComponent(item.id) + ((j < (dim.items.length - 1)) ? ';' : '');
}
}
+ else if (Ext.isObject(dim.legendSet) && dim.legendSet.id) {
+ paramString += '-' + dim.legendSet.id;
+
+ if (dim.filter) {
+ paramString += ':' + encodeURIComponent(dim.filter);
+ }
+ }
else {
paramString += dim.filter ? ':' + encodeURIComponent(dim.filter) : '';
}
@@ -2046,6 +2654,13 @@
paramString += j < dim.items.length - 1 ? ';' : '';
}
}
+ else if (Ext.isObject(dim.legendSet) && dim.legendSet.id) {
+ paramString += '-' + dim.legendSet.id;
+
+ if (dim.filter) {
+ paramString += ':' + encodeURIComponent(dim.filter);
+ }
+ }
else {
paramString += dim.filter ? ':' + encodeURIComponent(dim.filter) : '';
}
@@ -2078,6 +2693,11 @@
// display property
paramString += '&displayProperty=' + init.userAccount.settings.keyAnalysisDisplayProperty.toUpperCase();
+ // collapse data items
+ if (layout.collapseDataDimensions) {
+ paramString += '&collapseDataDimensions=true';
+ }
+
return paramString;
};
@@ -2454,7 +3074,12 @@
fields: store.numericFields,
minimum: minimum < 0 ? minimum : 0,
label: {
- renderer: Ext.util.Format.numberRenderer(renderer)
+ //renderer: Ext.util.Format.numberRenderer(renderer),
+ renderer: function(v) {
+ return support.prototype.number.prettyPrint(v);
+ },
+ style: {},
+ rotate: {}
},
labelTitle: {
font: 'bold 13px ' + conf.chart.style.fontFamily
@@ -2462,13 +3087,13 @@
grid: {
odd: {
opacity: 1,
- stroke: '#aaa',
- 'stroke-width': 0.1
+ stroke: '#000',
+ 'stroke-width': 0.03
},
even: {
opacity: 1,
- stroke: '#aaa',
- 'stroke-width': 0.1
+ stroke: '#000',
+ 'stroke-width': 0.03
}
}
};
@@ -2571,13 +3196,34 @@
};
if (xLayout.showValues) {
+ var labelFont = conf.chart.style.fontFamily,
+ labelColor = 'black';
+
+ if (Ext.isObject(xLayout.seriesStyle)) {
+ var style = xLayout.seriesStyle;
+
+ // label
+ labelColor = style.labelColor || labelColor;
+
+ if (style.labelFont) {
+ labelFont = style.labelFont;
+ }
+ else {
+ labelFont = style.labelFontWeight ? style.labelFontWeight + ' ' : 'normal ';
+ labelFont += style.labelFontSize ? parseFloat(style.labelFontSize) + 'px ' : '11px ';
+ labelFont += style.labelFontFamily ? style.labelFontFamily : conf.chart.style.fontFamily;
+ }
+ }
+
main.label = {
display: 'outside',
'text-anchor': 'middle',
field: store.rangeFields,
- font: conf.chart.style.fontFamily,
+ font: labelFont,
+ fill: labelColor,
renderer: function(n) {
- return n === '0.0' ? '' : n;
+ n = n === '0.0' ? '' : n;
+ return support.prototype.number.prettyPrint(n);
}
};
}
@@ -2655,7 +3301,7 @@
renderer: function(si, item) {
if (item.value) {
var value = item.value[1] === '0.0' ? '-' : item.value[1];
- this.update('<div style="text-align:center"><div style="font-size:17px; font-weight:bold">' + value + '</div><div style="font-size:10px">' + si.data[conf.finals.data.domain] + '</div></div>');
+ this.update('<div style="font-size:17px; font-weight:bold">' + support.prototype.number.prettyPrint(value) + '</div><div style="font-size:10px">' + si.data[conf.finals.data.domain] + '</div>');
}
}
};
@@ -2802,8 +3448,10 @@
tmpText = '';
if (operator === 'IN') {
- for (var ii = 0; ii < valueArray.length; ii++) {
- tmpText += (tmpText.length ? ', ' : '') + valueArray[ii];
+ for (var ii = 0, value; ii < valueArray.length; ii++) {
+ value = valueArray[ii];
+
+ tmpText += (tmpText.length ? ', ' : '') + (md.booleanNames[value] || md.optionNames[value] || md.names[value] || value);
}
text += tmpText;
@@ -2841,6 +3489,14 @@
}
}
+ // aggregation type
+ if (Ext.isObject(layout.value) && layout.value.id && layout.aggregationType) {
+ var value = layout.value.id;
+
+ text += text.length ? ', ' : '';
+ text += (md.booleanNames[value] || md.optionNames[value] || md.names[value] || value) + ' (' + conf.aggregationType.idNameMap[layout.aggregationType] + ')';
+ }
+
fontSize = (centerRegion.getWidth() / text.length) < 11.6 ? 13 : 18;
return Ext.create('Ext.draw.Sprite', {
@@ -3340,12 +3996,12 @@
}
// legend set map
- //init.idLegendSetMap = {};
+ init.idLegendSetMap = {};
- //for (var i = 0, set; i < init.legendSets.length; i++) {
- //set = init.legendSets[i];
- //init.idLegendSetMap[set.id] = set;
- //}
+ for (var i = 0, set; i < init.legendSets.length; i++) {
+ set = init.legendSets[i];
+ init.idLegendSetMap[set.id] = set;
+ }
}());
// instance
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/styles/style.css'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/styles/style.css 2015-02-25 14:51:26 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-visualizer/styles/style.css 2015-04-08 13:50:25 +0000
@@ -312,6 +312,23 @@
/*----------------------------------------------------------------------------
+ * NS viewport
+ *--------------------------------------------------------------------------*/
+
+.ns-viewport-text * {
+ padding: 3px 10px;
+ font-size: 11px;
+ color: #515a62;
+}
+.ns-viewport-text h3 {
+ font-size: 14px;
+ font-weight: 500;
+ color: #333;
+ padding: 0 0 8px 0;
+}
+
+
+/*----------------------------------------------------------------------------
* Panel
*--------------------------------------------------------------------------*/
@@ -414,13 +431,13 @@
/* Custom */
.ns-combo.h21 .x-form-trigger {
- height: 21px;
+ height: 21px !important;
}
.ns-combo.h22 .x-form-trigger {
- height: 22px;
+ height: 22px !important;
}
.ns-combo.h24 .x-form-trigger {
- height: 24px;
+ height: 24px !important;
}
/*----------------------------------------------------------------------------
@@ -795,6 +812,19 @@
cursor: default !important;
}
+ /* Link button */
+.ns-linkbutton.x-btn-default-small {
+ border: 1px solid transparent;
+ background: transparent;
+}
+.ns-linkbutton .x-btn-inner {
+ color: #3162c5;
+ padding: 0;
+}
+.ns-linkbutton.x-btn-over .x-btn-inner {
+ text-decoration: underline;
+}
+
/*----------------------------------------------------------------------------
* Tooltip
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/app.js 2015-03-31 16:30:59 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/scripts/app.js 2015-04-08 13:50:25 +0000
@@ -6226,18 +6226,17 @@
ns.app.centerRegion = this;
},
afterrender: function(p) {
- var liStyle = 'padding:3px 10px; color:#333',
- html = '';
+ var html = '';
- html += '<div style="padding:20px">';
- html += '<div style="font-size:14px; padding-bottom:8px">' + NS.i18n.example1 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example2 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example3 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example4 + '</div>';
- html += '<div style="font-size:14px; padding-top:20px; padding-bottom:8px">' + NS.i18n.example5 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example6 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example7 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example8 + '</div>';
+ html += '<div class="ns-viewport-text" style="padding:20px">';
+ html += '<h3>' + NS.i18n.example1 + '</h3>';
+ html += '<div>- ' + NS.i18n.example2 + '</div>';
+ html += '<div>- ' + NS.i18n.example3 + '</div>';
+ html += '<div>- ' + NS.i18n.example4 + '</div>';
+ html += '<h3 style="padding-top:20px">' + NS.i18n.example5 + '</h3>';
+ html += '<div>- ' + NS.i18n.example6 + '</div>';
+ html += '<div>- ' + NS.i18n.example7 + '</div>';
+ html += '<div>- ' + NS.i18n.example8 + '</div>';
html += '</div>';
p.update(html);
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/styles/style.css'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/styles/style.css 2015-03-31 14:29:54 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-pivot/styles/style.css 2015-04-08 13:50:25 +0000
@@ -312,6 +312,23 @@
/*----------------------------------------------------------------------------
+ * NS viewport
+ *--------------------------------------------------------------------------*/
+
+.ns-viewport-text * {
+ padding: 3px 10px;
+ font-size: 11px;
+ color: #515a62;
+}
+.ns-viewport-text h3 {
+ font-size: 14px;
+ font-weight: 500;
+ color: #333;
+ padding: 0 0 8px 0;
+}
+
+
+/*----------------------------------------------------------------------------
* Panel
*--------------------------------------------------------------------------*/
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js 2015-03-31 16:28:36 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/scripts/app.js 2015-04-08 13:50:25 +0000
@@ -6314,18 +6314,17 @@
}
},
afterrender: function(p) {
- var liStyle = 'padding:3px 10px; color:#333',
- html = '';
+ var html = '';
- html += '<div style="padding:20px">';
- html += '<div style="font-size:14px; padding-bottom:8px">' + NS.i18n.example1 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example2 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example3 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example4 + '</div>';
- html += '<div style="font-size:14px; padding-top:20px; padding-bottom:8px">' + NS.i18n.example5 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example6 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example7 + '</div>';
- html += '<div style="' + liStyle + '">- ' + NS.i18n.example8 + '</div>';
+ html += '<div class="ns-viewport-text" style="padding:20px">';
+ html += '<h3>' + NS.i18n.example1 + '</h3>';
+ html += '<div>- ' + NS.i18n.example2 + '</div>';
+ html += '<div>- ' + NS.i18n.example3 + '</div>';
+ html += '<div>- ' + NS.i18n.example4 + '</div>';
+ html += '<h3 style="padding-top:20px">' + NS.i18n.example5 + '</h3>';
+ html += '<div>- ' + NS.i18n.example6 + '</div>';
+ html += '<div>- ' + NS.i18n.example7 + '</div>';
+ html += '<div>- ' + NS.i18n.example8 + '</div>';
html += '</div>';
p.update(html);
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/styles/style.css'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/styles/style.css 2015-03-09 13:15:43 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-visualizer/styles/style.css 2015-04-08 13:50:25 +0000
@@ -131,6 +131,23 @@
/*----------------------------------------------------------------------------
+ * NS viewport
+ *--------------------------------------------------------------------------*/
+
+.ns-viewport-text * {
+ padding: 3px 10px;
+ font-size: 11px;
+ color: #515a62;
+}
+.ns-viewport-text h3 {
+ font-size: 14px;
+ font-weight: 500;
+ color: #333;
+ padding: 0 0 8px 0;
+}
+
+
+/*----------------------------------------------------------------------------
* Panel
*--------------------------------------------------------------------------*/