dhis2-gis
Version:
GIS Web App for DHIS 2
857 lines (767 loc) • 29.3 kB
JavaScript
import arraySort from 'd2-utilizr/lib/arraySort';
import isDefined from 'd2-utilizr/lib/isDefined';
import isNumber from 'd2-utilizr/lib/isNumber';
export default function LegendSetWindow(gis) {
// Stores
var legendSetStore,
legendStore,
tmpLegendStore,
// Objects
LegendSetPanel,
LegendPanel,
// Instances
legendSetPanel,
legendPanel,
// Components
window,
legendSetName,
legendName,
startValue,
endValue,
color,
legendGrid,
create,
update,
cancel,
info,
// Functions
showUpdateLegendSet,
deleteLegendSet,
deleteLegend,
getRequestBody,
reset,
validateLegends,
windowWidth = 450,
windowBorder = 12,
bodyPadding = 2,
legendBodyBorder = 1,
legendBodyPadding = 1,
fieldLabelWidth = 105,
gridPadding = 1;
legendSetStore = Ext.create('Ext.data.Store', {
fields: ['id', 'name'],
proxy: {
type: 'ajax',
url: encodeURI(gis.init.contextPath + '/api/legendSets.json?fields=id,displayName|rename(name)&paging=false'),
reader: {
type: 'json',
root: 'legendSets'
},
pageParam: false,
startParam: false,
limitParam: false
},
listeners: {
load: function(store, records) {
this.sort('name', 'ASC');
info.setText(records.length + ' legend set' + (records.length !== 1 ? 's' : '') + ' available');
}
}
});
legendStore = Ext.create('Ext.data.Store', {
fields: ['id', 'name', 'startValue', 'endValue', 'color'],
proxy: {
type: 'ajax',
url: '',
reader: {
type: 'json',
root: 'legends'
}
},
deleteLegend: deleteLegend,
listeners: {
load: function(store, records) {
var data = [];
for (var i = 0; i < records.length; i++) {
data.push(records[i].data);
}
data = arraySort(data, 'ASC', 'startValue');
tmpLegendStore.add(data);
info.setText(records.length + ' legend sets available');
}
}
});
LegendSetPanel = function() {
var items,
addButton,
legendSetGrid;
addButton = Ext.create('Ext.button.Button', {
text: GIS.i18n.add_new,
height: 26,
style: 'border-radius: 1px',
menu: {},
handler: function() {
showUpdateLegendSet();
}
});
legendSetGrid = Ext.create('Ext.grid.Panel', {
cls: 'gis-grid',
scroll: 'vertical',
height: true,
hideHeaders: true,
currentItem: null,
columns: [
{
dataIndex: 'name',
sortable: false,
width: 369
},
{
xtype: 'actioncolumn',
sortable: false,
width: 40,
items: [
{
iconCls: 'gis-grid-row-icon-edit',
getClass: function() {
return 'tooltip-legendset-edit';
},
handler: function(grid, rowIndex, colIndex, col, event) {
var id = this.up('grid').store.getAt(rowIndex).data.id;
showUpdateLegendSet(id);
}
},
{
iconCls: 'gis-grid-row-icon-delete',
getClass: function() {
return 'tooltip-legendset-delete';
},
handler: function(grid, rowIndex, colIndex, col, event) {
var record = this.up('grid').store.getAt(rowIndex),
id = record.data.id,
name = record.data.name,
message = 'Delete legend set?\n\n' + name;
if (confirm(message)) {
deleteLegendSet(id);
}
}
}
]
},
{
sortable: false,
width: 17
}
],
store: legendSetStore,
listeners: {
render: function() {
var that = this,
maxHeight = gis.viewport.centerRegion.getHeight() - 155,
height;
this.store.on('load', function() {
if (isDefined(that.setHeight)) {
height = 1 + that.store.getCount() * gis.conf.layout.grid.row_height;
that.setHeight(height > maxHeight ? maxHeight : height);
window.doLayout();
}
});
this.store.load();
},
afterrender: function() {
var fn = function() {
var editArray = document.getElementsByClassName('tooltip-legendset-edit'),
deleteArray = document.getElementsByClassName('tooltip-legendset-delete'),
len = editArray.length,
el;
for (var i = 0; i < len; i++) {
el = editArray[i];
Ext.create('Ext.tip.ToolTip', {
target: el,
html: 'Edit',
'anchor': 'bottom',
anchorOffset: -14,
showDelay: 1000
});
el = deleteArray[i];
Ext.create('Ext.tip.ToolTip', {
target: el,
html: 'Delete',
'anchor': 'bottom',
anchorOffset: -14,
showDelay: 1000
});
}
};
Ext.defer(fn, 100);
},
itemmouseenter: function(grid, record, item) {
this.currentItem = Ext.get(item);
this.currentItem.removeCls('x-grid-row-over');
},
select: function() {
this.currentItem.removeCls('x-grid-row-selected');
},
selectionchange: function() {
this.currentItem.removeCls('x-grid-row-focused');
}
}
});
items = [
{
xtype: 'panel',
layout: 'hbox',
cls: 'gis-container-inner',
bodyStyle: 'padding: 0',
style: 'margin-bottom: 1px',
items: [
addButton
]
},
legendSetGrid
];
return items;
};
LegendPanel = function(id) {
var panel,
addLegend,
LegendEditWindow,
validateEditLegendForm,
showUpdateLegend;
// edit legend panel
LegendEditWindow = function(record) {
var editLegendName,
editStartValue,
editEndValue,
editColor,
editCancel,
editUpdate,
editWindow;
editLegendName = Ext.create('Ext.form.field.Text', {
cls: 'gis-textfield',
width: windowWidth - windowBorder - bodyPadding - (2 * legendBodyBorder) - (2 * legendBodyPadding) + 4,
height: 23,
fieldStyle: 'padding-left: 3px; border-color: #bbb',
labelStyle: 'padding-top: 5px; padding-left: 3px',
fieldLabel: GIS.i18n.legend_name,
value: record.data.name
});
editStartValue = Ext.create('Ext.form.field.Number', {
width: 163 + 2,
height: 23,
allowDecimals: true,
style: 'margin-bottom: 0px',
value: record.data.startValue
});
editEndValue = Ext.create('Ext.form.field.Number', {
width: 163 + 2,
height: 23,
allowDecimals: true,
style: 'margin-bottom: 0px; margin-left: 1px',
value: record.data.endValue
});
editColor = Ext.create('Ext.ux.button.ColorButton', {
width: windowWidth - windowBorder - bodyPadding - (2 * legendBodyBorder) - (2 * legendBodyPadding) - fieldLabelWidth + 4,
height: 23,
style: 'border-radius: 1px',
value: record.data.color.replace('#', '')
});
validateEditLegendForm = function() {
if (!(editLegendName.getValue() && isNumber(editStartValue.getValue()) && isNumber(editEndValue.getValue()) && editColor.getValue())) {
return;
}
if (editStartValue.getValue() >= editEndValue.getValue()) {
return;
}
return true;
};
editCancel = Ext.create('Ext.button.Button', {
text: GIS.i18n.cancel,
handler: function() {
editWindow.destroy();
}
});
editUpdate = Ext.create('Ext.button.Button', {
text: GIS.i18n.update,
handler: function() {
if (!validateEditLegendForm()) {
return;
}
record.set('name', editLegendName.getValue());
record.set('startValue', editStartValue.getValue());
record.set('endValue', editEndValue.getValue());
record.set('color', '#' + editColor.getValue());
editWindow.destroy();
window.isDirty = true;
tmpLegendStore.sort('startValue', 'ASC');
}
});
editWindow = Ext.create('Ext.window.Window', {
title: GIS.i18n.edit_legend + ' (' + record.data.name + ')',
width: windowWidth,
modal: true,
shadow: true,
resizable: false,
bodyStyle: 'background: #fff; padding: 1px',
bbar: [
editCancel,
'->',
editUpdate
],
items: [
editLegendName,
{
layout: 'hbox',
cls: 'gis-container-inner',
bodyStyle: 'background: transparent',
items: [
{
html: GIS.i18n.start_end_value + ':',
width: fieldLabelWidth,
bodyStyle: 'background:transparent; padding-top:3px; padding-left:3px'
},
editStartValue,
editEndValue
]
},
{
layout: 'column',
cls: 'gis-container-inner',
bodyStyle: 'background: transparent',
items: [
{
html: GIS.i18n.legend_symbolizer + ':',
width: fieldLabelWidth,
bodyStyle: 'background:transparent; padding-top:3px; padding-left:3px'
},
editColor
]
}
]
});
return editWindow;
};
showUpdateLegend = function(record) {
LegendEditWindow(record).showAt(window.getPosition()[0], window.getPosition()[1] + 55);
};
// legend panel
tmpLegendStore = Ext.create('Ext.data.ArrayStore', {
fields: ['id', 'name', 'startValue', 'endValue', 'color']
});
legendSetName = Ext.create('Ext.form.field.Text', {
cls: 'gis-textfield',
width: windowWidth - windowBorder - bodyPadding,
height: 25,
fieldStyle: 'padding-left: 5px; border-color: #bbb',
labelStyle: 'padding-top: 5px; padding-left: 3px',
fieldLabel: GIS.i18n.legend_set_name,
style: 'margin-bottom: 6px'
});
legendName = Ext.create('Ext.form.field.Text', {
cls: 'gis-textfield',
width: windowWidth - windowBorder - bodyPadding - (2 * legendBodyBorder) - (2 * legendBodyPadding),
height: 23,
fieldStyle: 'padding-left: 3px; border-color: #bbb',
labelStyle: 'padding-top: 5px; padding-left: 3px',
fieldLabel: GIS.i18n.legend_name
});
startValue = Ext.create('Ext.form.field.Number', {
width: 163,
height: 23,
allowDecimals: true,
style: 'margin-bottom: 0px',
value: 0
});
endValue = Ext.create('Ext.form.field.Number', {
width: 163,
height: 23,
allowDecimals: true,
style: 'margin-bottom: 0px; margin-left: 1px',
value: 0
});
color = Ext.create('Ext.ux.button.ColorButton', {
width: windowWidth - windowBorder - bodyPadding - (2 * legendBodyBorder) - (2 * legendBodyPadding) - fieldLabelWidth,
height: 23,
style: 'border-radius: 1px',
value: 'e1e1e1'
});
addLegend = Ext.create('Ext.button.Button', {
text: GIS.i18n.add_legend,
height: 26,
style: 'border-radius: 1px',
handler: function() {
var date = new Date(),
id = date.toISOString(),
ln = legendName.getValue(),
sv = startValue.getValue(),
ev = endValue.getValue(),
co = color.getValue().toUpperCase(),
items = tmpLegendStore.data.items,
data = [];
if (ln && (ev > sv)) {
for (var i = 0; i < items.length; i++) {
data.push(items[i].data);
}
data.push({
id: id,
name: ln,
startValue: sv,
endValue: ev,
color: '#' + co
});
data = arraySort(data, 'ASC', 'startValue');
tmpLegendStore.removeAll();
tmpLegendStore.add(data);
legendName.reset();
startValue.reset();
endValue.reset();
color.reset();
window.isDirty = true;
} else if (!ln) {
gis.alert(GIS.i18n.legend_name_is_required);
} else {
gis.alert(GIS.i18n.end_value_should_be_bigger_than_start_value);
}
}
});
legendGrid = Ext.create('Ext.grid.Panel', {
cls: 'gis-grid',
bodyStyle: 'border-top: 0 none',
width: windowWidth - windowBorder - bodyPadding - (2 * gridPadding),
height: 200,
autoScroll: false, // https://www.sencha.com/forum/archive/index.php/t-144780.html?s=b3a72bbd82e5cc20417f0b5779439b97
scroll:false,
viewConfig: {
style: 'overflow-y:auto'
},
hideHeaders: true,
currentItem: null,
columns: [
{
dataIndex: 'name',
sortable: false,
width: 236
},
{
sortable: false,
width: 45,
renderer: function(value, metaData, record) {
return '<span style="color:' + record.data.color + '">Color</span>';
}
},
{
dataIndex: 'startValue',
sortable: false,
width: 45
},
{
dataIndex: 'endValue',
sortable: false,
width: 45
},
{
xtype: 'actioncolumn',
sortable: false,
width: 40,
items: [
{
iconCls: 'gis-grid-row-icon-edit',
getClass: function() {
return 'tooltip-legendset-edit';
},
handler: function(grid, rowIndex, colIndex, col, event) {
var record = this.up('grid').store.getAt(rowIndex);
showUpdateLegend(record);
}
},
{
iconCls: 'gis-grid-row-icon-delete',
getClass: function() {
return 'tooltip-legend-delete';
},
handler: function(grid, rowIndex, colIndex, col, event) {
var id = this.up('grid').store.getAt(rowIndex).data.id;
deleteLegend(id);
}
}
]
},
{
sortable: false,
width: 17
}
],
store: tmpLegendStore,
listeners: {
itemmouseenter: function(grid, record, item) {
this.currentItem = Ext.get(item);
this.currentItem.removeCls('x-grid-row-over');
},
select: function() {
this.currentItem.removeCls('x-grid-row-selected');
},
selectionchange: function() {
this.currentItem.removeCls('x-grid-row-focused');
},
afterrender: function() {
var fn = function() {
var deleteArray = document.getElementsByClassName('tooltip-legend-delete'),
len = deleteArray.length,
el;
for (var i = 0; i < len; i++) {
el = deleteArray[i];
Ext.create('Ext.tip.ToolTip', {
target: el,
html: 'Delete',
'anchor': 'bottom',
anchorOffset: -14,
showDelay: 1000
});
}
};
Ext.defer(fn, 100);
}
}
});
panel = Ext.create('Ext.panel.Panel', {
cls: 'gis-container-inner',
bodyStyle: 'padding:0px',
legendSetId: id,
items: [
legendSetName,
{
xtype: 'container',
html: GIS.i18n.add_legend,
cls: 'gis-panel-html-title',
style: 'padding-left: 3px; margin-bottom: 3px'
},
{
bodyStyle: 'background-color:#f1f1f1; border:1px solid #ccc; border-radius:1px; padding:' + legendBodyPadding + 'px',
style: 'margin-bottom: 1px',
items: [
legendName,
{
layout: 'hbox',
bodyStyle: 'background: transparent',
items: [
{
html: GIS.i18n.start_end_value + ':',
width: fieldLabelWidth,
bodyStyle: 'background:transparent; padding-top:3px; padding-left:3px'
},
startValue,
endValue
]
},
{
layout: 'column',
cls: 'gis-container-inner',
bodyStyle: 'background: transparent',
items: [
{
html: GIS.i18n.legend_symbolizer + ':',
width: fieldLabelWidth,
bodyStyle: 'background:transparent; padding-top:3px; padding-left:3px'
},
color
]
}
]
},
{
cls: 'gis-container-inner',
bodyStyle: 'text-align: right',
width: windowWidth - windowBorder - bodyPadding,
items: addLegend
},
{
xtype: 'container',
html: GIS.i18n.current_legends,
cls: 'gis-panel-html-title',
style: 'padding-left: 3px; margin-bottom: 3px'
},
{
xtype: 'container',
cls: 'gis-container-inner',
style: 'padding:' + gridPadding + 'px',
items: legendGrid,
layout: 'fit'
}
]
});
if (id) {
legendStore.proxy.url = encodeURI(gis.init.contextPath + '/api/legendSets/' + id + '.json?fields=legends[id,displayName|rename(name),startValue,endValue,color]');
legendStore.load();
legendSetName.setValue(legendSetStore.getById(id).data.name);
}
return panel;
};
showUpdateLegendSet = function(id) {
legendPanel = new LegendPanel(id);
window.removeAll();
window.add(legendPanel);
info.hide();
cancel.show();
if (id) {
update.show();
}
else {
create.show();
}
};
deleteLegendSet = function(id) {
if (id) {
Ext.Ajax.request({
url: encodeURI(gis.init.contextPath + '/api/legendSets/' + id),
method: 'DELETE',
success: function() {
legendSetStore.load();
gis.store.legendSets.load();
}
});
}
};
deleteLegend = function(id) {
tmpLegendStore.remove(tmpLegendStore.getById(id));
};
getRequestBody = function() {
var items = tmpLegendStore.data.items,
body;
body = {
name: legendSetName.getValue(),
symbolizer: gis.conf.finals.widget.symbolizer_color,
legends: []
};
for (var i = 0; i < items.length; i++) {
var item = items[i];
body.legends.push({
name: item.data.name,
startValue: item.data.startValue,
endValue: item.data.endValue,
color: item.data.color
});
}
return body;
};
reset = function() {
legendPanel.destroy();
legendSetPanel = new LegendSetPanel();
window.removeAll();
window.add(legendSetPanel);
window.isDirty = false;
info.show();
cancel.hide();
create.hide();
update.hide();
};
validateLegends = function() {
var items = tmpLegendStore.data.items,
item,
prevItem;
if (items.length === 0) {
gis.alert('At least one legend is required');
return false;
}
for (var i = 1; i < items.length; i++) {
item = items[i].data;
prevItem = items[i - 1].data;
if (item.startValue < prevItem.endValue) {
var msg = 'Overlapping legends not allowed!\n\n' +
prevItem.name + ' (' + prevItem.startValue + ' - ' + prevItem.endValue + ')\n' +
item.name + ' (' + item.startValue + ' - ' + item.endValue + ')';
gis.alert(msg);
return false;
}
if (prevItem.endValue < item.startValue) {
var msg = 'Legend gaps detected!\n\n' +
prevItem.name + ' (' + prevItem.startValue + ' - ' + prevItem.endValue + ')\n' +
item.name + ' (' + item.startValue + ' - ' + item.endValue + ')\n\n' +
'Proceed anyway?';
if (!confirm(msg)) {
return false;
}
}
}
return true;
};
create = Ext.create('Ext.button.Button', {
text: GIS.i18n.create,
hidden: true,
handler: function() {
if (legendSetName.getValue() && validateLegends()) {
if (legendSetStore.findExact('name', legendSetName.getValue()) !== -1) {
gis.alert('Name already in use');
return;
}
var body = JSON.stringify(getRequestBody());
Ext.Ajax.request({
url: encodeURI(gis.init.contextPath + '/api/legendSets/'),
method: 'POST',
headers: {'Content-Type': 'application/json'},
params: body,
success: function() {
gis.store.legendSets.load();
reset();
}
});
}
}
});
update = Ext.create('Ext.button.Button', {
text: GIS.i18n.update,
hidden: true,
handler: function() {
if (legendSetName.getValue() && validateLegends()) {
var body = getRequestBody(),
id = legendPanel.legendSetId;
body.id = id;
body = JSON.stringify(getRequestBody());
Ext.Ajax.request({
url: encodeURI(gis.init.contextPath + '/api/legendSets/' + id),
method: 'PUT',
headers: {'Content-Type': 'application/json'},
params: body,
success: function() {
reset();
}
});
}
}
});
cancel = Ext.create('Ext.button.Button', {
text: GIS.i18n.cancel,
hidden: true,
handler: function() {
reset();
}
});
info = Ext.create('Ext.form.Label', {
cls: 'gis-label-info',
width: 400,
height: 22
});
window = Ext.create('Ext.window.Window', {
title: GIS.i18n.legendsets,
iconCls: 'gis-window-title-icon-legendset', //todo
bodyStyle: 'padding:1px; background-color:#fff',
resizable: false,
width: windowWidth,
modal: true,
items: new LegendSetPanel(),
destroyOnBlur: true,
bbar: {
height: 27,
items: [
info,
cancel,
'->',
create,
update
]
},
listeners: {
show: function(w) {
this.setPosition(269, 33);
if (!w.hasDestroyOnBlurHandler) {
gis.util.gui.window.addDestroyOnBlurHandler(w);
}
},
beforeclose: function() {
if (window.isDirty) {
return confirm('The legend set has unsaved modifications. Close anyway?');
}
}
}
});
return window;
};