← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 15705: EventChart object introduced.

 

Merge authors:
  Jan Henrik Øverland (janhenrik-overland)
------------------------------------------------------------
revno: 15705 [merge]
committer: Jan Henrik Overland <janhenrik.overland@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2014-06-16 18:21:35 +0200
message:
  EventChart object introduced.
added:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChartService.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/descriptors/EventChartSchemaDescriptor.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/eventchart/
  dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/eventchart/DefaultEventChartService.java
  dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/
  dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/EventChart.hbm.xml
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventChartController.java
modified:
  dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/scripts/plugin.js


--
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
=== added directory 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart'
=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChart.java	2014-06-16 16:20:38 +0000
@@ -0,0 +1,749 @@
+package org.hisp.dhis.eventchart;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.hisp.dhis.common.BaseAnalyticalObject;
+import org.hisp.dhis.common.BaseIdentifiableObject;
+import org.hisp.dhis.common.DimensionalObject;
+import org.hisp.dhis.common.DxfNamespaces;
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.IdentifiableObjectUtils;
+import org.hisp.dhis.common.NameableObject;
+import org.hisp.dhis.common.view.DetailedView;
+import org.hisp.dhis.common.view.DimensionalView;
+import org.hisp.dhis.common.view.ExportView;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.program.Program;
+import org.hisp.dhis.program.ProgramStage;
+import org.hisp.dhis.user.User;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonView;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+
+/**
+ * @author Jan Henrik Overland
+ */
+@JacksonXmlRootElement( localName = "eventchart", namespace = DxfNamespaces.DXF_2_0 )
+public class EventChart
+    extends BaseAnalyticalObject
+{
+    private static final long serialVersionUID = 2570074075484545534L;
+
+    public static final String SIZE_NORMAL = "normal";
+
+    public static final String SIZE_WIDE = "wide";
+
+    public static final String SIZE_TALL = "tall";
+
+    public static final String TYPE_COLUMN = "column";
+
+    public static final String TYPE_STACKED_COLUMN = "stackedcolumn";
+
+    public static final String TYPE_BAR = "bar";
+
+    public static final String TYPE_STACKED_BAR = "stackedbar";
+
+    public static final String TYPE_LINE = "line";
+
+    public static final String TYPE_AREA = "area";
+
+    public static final String TYPE_PIE = "pie";
+
+    public static final String TYPE_RADAR = "radar"; // Spider web
+
+    private Program program;
+
+    private ProgramStage programStage;
+
+    private Date startDate;
+
+    private Date endDate;
+
+    private String domainAxisLabel;
+
+    private String rangeAxisLabel;
+
+    private String type;
+
+    private String series;
+
+    private String category;
+
+    private List<String> filterDimensions = new ArrayList<String>();
+
+    private String countType;
+
+    private boolean hideLegend;
+
+    private boolean regression;
+
+    private boolean hideTitle;
+
+    private boolean hideSubtitle;
+
+    private String title;
+
+    private Double targetLineValue;
+
+    private String targetLineLabel;
+
+    private Double baseLineValue;
+
+    private String baseLineLabel;
+
+    private boolean showData;
+
+    private boolean hideEmptyRows;
+
+    private Double rangeAxisMaxValue;
+
+    private Double rangeAxisMinValue;
+
+    private Integer rangeAxisSteps; // min 1
+
+    private Integer rangeAxisDecimals;
+
+    // -------------------------------------------------------------------------
+    // Transient properties
+    // -------------------------------------------------------------------------
+
+    private transient I18nFormat format;
+
+    private transient List<Period> relativePeriods = new ArrayList<Period>();
+
+    private transient User user;
+
+    private transient List<OrganisationUnit> organisationUnitsAtLevel = new ArrayList<OrganisationUnit>();
+
+    private transient List<OrganisationUnit> organisationUnitsInGroups = new ArrayList<OrganisationUnit>();
+
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
+
+    public EventChart()
+    {
+        setAutoFields();
+    }
+
+    public EventChart( String name )
+    {
+        this();
+        this.name = name;
+    }
+
+    // -------------------------------------------------------------------------
+    // Init
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void init( User user, Date date, OrganisationUnit organisationUnit,
+        List<OrganisationUnit> organisationUnitsAtLevel, List<OrganisationUnit> organisationUnitsInGroups,
+        I18nFormat format )
+    {
+        this.user = user;
+        this.relativePeriodDate = date;
+        this.relativeOrganisationUnit = organisationUnit;
+        this.organisationUnitsAtLevel = organisationUnitsAtLevel;
+        this.organisationUnitsInGroups = organisationUnitsInGroups;
+        this.format = format;
+    }
+
+    // -------------------------------------------------------------------------
+    // Logic
+    // -------------------------------------------------------------------------
+
+    public List<NameableObject> series()
+    {
+        DimensionalObject object = getDimensionalObject( series, relativePeriodDate, user, true,
+            organisationUnitsAtLevel, organisationUnitsInGroups, format );
+
+        return object != null ? object.getItems() : null;
+    }
+
+    public List<NameableObject> category()
+    {
+        DimensionalObject object = getDimensionalObject( category, relativePeriodDate, user, true,
+            organisationUnitsAtLevel, organisationUnitsInGroups, format );
+
+        return object != null ? object.getItems() : null;
+    }
+
+    public List<NameableObject> filters()
+    {
+        List<NameableObject> filterItems = new ArrayList<NameableObject>();
+
+        for ( String filter : filterDimensions )
+        {
+            DimensionalObject object = getDimensionalObject( filter, relativePeriodDate, user, true,
+                organisationUnitsAtLevel, organisationUnitsInGroups, format );
+
+            if ( object != null )
+            {
+                filterItems.addAll( object.getItems() );
+            }
+        }
+
+        return filterItems;
+    }
+
+    public String generateTitle()
+    {
+        return IdentifiableObjectUtils.join( filters() );
+    }
+
+    @Override
+    public void populateAnalyticalProperties()
+    {
+        columns.addAll( getDimensionalObjectList( series ) );
+        rows.addAll( getDimensionalObjectList( category ) );
+
+        for ( String filter : filterDimensions )
+        {
+            filters.addAll( getDimensionalObjectList( filter ) );
+        }
+    }
+
+    public List<OrganisationUnit> getAllOrganisationUnits()
+    {
+        if ( transientOrganisationUnits != null && !transientOrganisationUnits.isEmpty() )
+        {
+            return transientOrganisationUnits;
+        }
+        else
+        {
+            return organisationUnits;
+        }
+    }
+
+    public OrganisationUnit getFirstOrganisationUnit()
+    {
+        List<OrganisationUnit> units = getAllOrganisationUnits();
+        return units != null && !units.isEmpty() ? units.iterator().next() : null;
+    }
+
+    public List<Period> getAllPeriods()
+    {
+        List<Period> list = new ArrayList<Period>();
+
+        list.addAll( relativePeriods );
+
+        for ( Period period : periods )
+        {
+            if ( !list.contains( period ) )
+            {
+                list.add( period );
+            }
+        }
+
+        return list;
+    }
+
+    /**
+     * Sets all dimensions for this chart.
+     * 
+     * @param series the series dimension.
+     * @param category the category dimension.
+     * @param filter the filter dimension.
+     */
+    public void setDimensions( String series, String category, String filter )
+    {
+        this.series = series;
+        this.category = category;
+        this.filterDimensions.clear();
+        this.filterDimensions.add( filter );
+    }
+
+    public boolean isType( String type )
+    {
+        return this.type != null && this.type.equalsIgnoreCase( type );
+    }
+
+    public boolean isTargetLine()
+    {
+        return targetLineValue != null;
+    }
+
+    public boolean isBaseLine()
+    {
+        return baseLineValue != null;
+    }
+
+    public int getWidth()
+    {
+        return 700;
+    }
+
+    public int getHeight()
+    {
+        return 500;
+    }
+
+    // -------------------------------------------------------------------------
+    // Getters and setters properties
+    // -------------------------------------------------------------------------
+
+    @JsonProperty
+    @JsonSerialize( as = BaseIdentifiableObject.class )
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Program getProgram()
+    {
+        return program;
+    }
+
+    public void setProgram( Program program )
+    {
+        this.program = program;
+    }
+
+    @JsonProperty
+    @JsonSerialize( as = BaseIdentifiableObject.class )
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public ProgramStage getProgramStage()
+    {
+        return programStage;
+    }
+
+    public void setProgramStage( ProgramStage programStage )
+    {
+        this.programStage = programStage;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Date getStartDate()
+    {
+        return startDate;
+    }
+
+    public void setStartDate( Date startDate )
+    {
+        this.startDate = startDate;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Date getEndDate()
+    {
+        return endDate;
+    }
+
+    public void setEndDate( Date endDate )
+    {
+        this.endDate = endDate;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getDomainAxisLabel()
+    {
+        return domainAxisLabel;
+    }
+
+    public void setDomainAxisLabel( String domainAxisLabel )
+    {
+        this.domainAxisLabel = domainAxisLabel;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getRangeAxisLabel()
+    {
+        return rangeAxisLabel;
+    }
+
+    public void setRangeAxisLabel( String rangeAxisLabel )
+    {
+        this.rangeAxisLabel = rangeAxisLabel;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getType()
+    {
+        return type;
+    }
+
+    public void setType( String type )
+    {
+        this.type = type;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getSeries()
+    {
+        return series;
+    }
+
+    public void setSeries( String series )
+    {
+        this.series = series;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getCategory()
+    {
+        return category;
+    }
+
+    public void setCategory( String category )
+    {
+        this.category = category;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class } )
+    @JacksonXmlElementWrapper( localName = "filterDimensions", namespace = DxfNamespaces.DXF_2_0 )
+    @JacksonXmlProperty( localName = "filterDimension", namespace = DxfNamespaces.DXF_2_0 )
+    public List<String> getFilterDimensions()
+    {
+        return filterDimensions;
+    }
+
+    public void setFilterDimensions( List<String> filterDimensions )
+    {
+        this.filterDimensions = filterDimensions;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getCountType()
+    {
+        return countType;
+    }
+
+    public void setCountType( String countType )
+    {
+        this.countType = countType;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public boolean isHideLegend()
+    {
+        return hideLegend;
+    }
+
+    public void setHideLegend( boolean hideLegend )
+    {
+        this.hideLegend = hideLegend;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public boolean isRegression()
+    {
+        return regression;
+    }
+
+    public void setRegression( boolean regression )
+    {
+        this.regression = regression;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Double getTargetLineValue()
+    {
+        return targetLineValue;
+    }
+
+    public void setTargetLineValue( Double targetLineValue )
+    {
+        this.targetLineValue = targetLineValue;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getTargetLineLabel()
+    {
+        return targetLineLabel;
+    }
+
+    public void setTargetLineLabel( String targetLineLabel )
+    {
+        this.targetLineLabel = targetLineLabel;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Double getBaseLineValue()
+    {
+        return baseLineValue;
+    }
+
+    public void setBaseLineValue( Double baseLineValue )
+    {
+        this.baseLineValue = baseLineValue;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getBaseLineLabel()
+    {
+        return baseLineLabel;
+    }
+
+    public void setBaseLineLabel( String baseLineLabel )
+    {
+        this.baseLineLabel = baseLineLabel;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public boolean isHideTitle()
+    {
+        return hideTitle;
+    }
+
+    public void setHideTitle( boolean hideTitle )
+    {
+        this.hideTitle = hideTitle;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public boolean isHideSubtitle()
+    {
+        return hideSubtitle;
+    }
+
+    public void setHideSubtitle( Boolean hideSubtitle )
+    {
+        this.hideSubtitle = hideSubtitle;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public String getTitle()
+    {
+        return this.title;
+    }
+
+    public void setTitle( String title )
+    {
+        this.title = title;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public boolean isShowData()
+    {
+        return showData;
+    }
+
+    public void setShowData( boolean showData )
+    {
+        this.showData = showData;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public boolean isHideEmptyRows()
+    {
+        return hideEmptyRows;
+    }
+
+    public void setHideEmptyRows( boolean hideEmptyRows )
+    {
+        this.hideEmptyRows = hideEmptyRows;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public boolean isRewindRelativePeriods()
+    {
+        return rewindRelativePeriods;
+    }
+
+    public void setRewindRelativePeriods( boolean rewindRelativePeriods )
+    {
+        this.rewindRelativePeriods = rewindRelativePeriods;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Double getRangeAxisMaxValue()
+    {
+        return rangeAxisMaxValue;
+    }
+
+    public void setRangeAxisMaxValue( Double rangeAxisMaxValue )
+    {
+        this.rangeAxisMaxValue = rangeAxisMaxValue;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Double getRangeAxisMinValue()
+    {
+        return rangeAxisMinValue;
+    }
+
+    public void setRangeAxisMinValue( Double rangeAxisMinValue )
+    {
+        this.rangeAxisMinValue = rangeAxisMinValue;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Integer getRangeAxisSteps()
+    {
+        return rangeAxisSteps;
+    }
+
+    public void setRangeAxisSteps( Integer rangeAxisSteps )
+    {
+        this.rangeAxisSteps = rangeAxisSteps;
+    }
+
+    @JsonProperty
+    @JsonView( { DetailedView.class, ExportView.class, DimensionalView.class } )
+    @JacksonXmlProperty( namespace = DxfNamespaces.DXF_2_0 )
+    public Integer getRangeAxisDecimals()
+    {
+        return rangeAxisDecimals;
+    }
+
+    public void setRangeAxisDecimals( Integer rangeAxisDecimals )
+    {
+        this.rangeAxisDecimals = rangeAxisDecimals;
+    }
+
+    // -------------------------------------------------------------------------
+    // Getters and setters for transient properties
+    // -------------------------------------------------------------------------
+
+    @JsonIgnore
+    public I18nFormat getFormat()
+    {
+        return format;
+    }
+
+    @JsonIgnore
+    public void setFormat( I18nFormat format )
+    {
+        this.format = format;
+    }
+
+    @JsonIgnore
+    public List<Period> getRelativePeriods()
+    {
+        return relativePeriods;
+    }
+
+    @JsonIgnore
+    public void setRelativePeriods( List<Period> relativePeriods )
+    {
+        this.relativePeriods = relativePeriods;
+    }
+
+    // -------------------------------------------------------------------------
+    // Merge with
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void mergeWith( IdentifiableObject other )
+    {
+        super.mergeWith( other );
+
+        if ( other.getClass().isInstance( this ) )
+        {
+            EventChart eventChart = (EventChart) other;
+
+            program = eventChart.getProgram();
+            programStage = eventChart.getProgramStage();
+            startDate = eventChart.getStartDate();
+            endDate = eventChart.getEndDate();
+            domainAxisLabel = eventChart.getDomainAxisLabel();
+            rangeAxisLabel = eventChart.getRangeAxisLabel();
+            countType = eventChart.getCountType();
+            type = eventChart.getType();
+            series = eventChart.getSeries();
+            category = eventChart.getCategory();
+            hideLegend = eventChart.isHideLegend();
+            regression = eventChart.isRegression();
+            hideTitle = eventChart.isHideTitle();
+            hideSubtitle = eventChart.isHideSubtitle();
+            title = eventChart.getTitle();
+            targetLineValue = eventChart.getTargetLineValue();
+            targetLineLabel = eventChart.getTargetLineLabel();
+            baseLineValue = eventChart.getBaseLineValue();
+            baseLineLabel = eventChart.getBaseLineLabel();
+            showData = eventChart.isShowData();
+            hideEmptyRows = eventChart.isHideEmptyRows();
+            rewindRelativePeriods = eventChart.isRewindRelativePeriods();
+            rangeAxisMaxValue = eventChart.getRangeAxisMaxValue();
+            rangeAxisMinValue = eventChart.getRangeAxisMinValue();
+            rangeAxisSteps = eventChart.getRangeAxisSteps();
+            rangeAxisDecimals = eventChart.getRangeAxisDecimals();
+
+            filterDimensions.clear();
+            filterDimensions.addAll( eventChart.getFilterDimensions() );
+        }
+    }
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChartService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChartService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/eventchart/EventChartService.java	2014-06-16 16:20:38 +0000
@@ -0,0 +1,49 @@
+package org.hisp.dhis.eventchart;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.List;
+
+/**
+* @author Lars Helge Overland
+*/
+public interface EventChartService
+{
+    int saveEventChart( EventChart eventChart );
+    
+    void updateEventChart( EventChart eventChart );
+    
+    EventChart getEventChart( int id );
+    
+    EventChart getEventChart( String uid );
+    
+    void deleteEventChart( EventChart eventChart );
+    
+    List<EventChart> getAllEventCharts();
+}

=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/descriptors/EventChartSchemaDescriptor.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/descriptors/EventChartSchemaDescriptor.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/descriptors/EventChartSchemaDescriptor.java	2014-06-16 16:20:38 +0000
@@ -0,0 +1,65 @@
+package org.hisp.dhis.schema.descriptors;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.hisp.dhis.eventchart.EventChart;
+import org.hisp.dhis.schema.Authority;
+import org.hisp.dhis.schema.AuthorityType;
+import org.hisp.dhis.schema.Schema;
+import org.hisp.dhis.schema.SchemaDescriptor;
+import org.springframework.stereotype.Component;
+
+import com.google.common.collect.Lists;
+
+@Component
+public class EventChartSchemaDescriptor
+    implements SchemaDescriptor
+{
+    public static final String SINGULAR = "eventChart";
+
+    public static final String PLURAL = "eventCharts";
+
+    public static final String API_ENDPOINT = "/" + PLURAL;
+
+    @Override
+    public Schema getSchema()
+    {
+        Schema schema = new Schema( EventChart.class, SINGULAR, PLURAL );
+        schema.setApiEndpoint( API_ENDPOINT );
+        schema.setShareable( true );
+        schema.setOrder( 1540 );
+
+        schema.getAuthorities().add(
+            new Authority( AuthorityType.CREATE_PUBLIC, Lists.newArrayList( "F_EVENTCHART_PUBLIC_ADD" ) ) );
+        schema.getAuthorities().add(
+            new Authority( AuthorityType.EXTERNALIZE, Lists.newArrayList( "F_EVENTCHART_EXTERNAL" ) ) );
+
+        return schema;
+    }
+}

=== added directory 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/eventchart'
=== added file 'dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/eventchart/DefaultEventChartService.java'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/eventchart/DefaultEventChartService.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/eventchart/DefaultEventChartService.java	2014-06-16 16:20:38 +0000
@@ -0,0 +1,83 @@
+package org.hisp.dhis.eventchart;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.List;
+
+import org.hisp.dhis.common.hibernate.HibernateIdentifiableObjectStore;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+* @author Lars Helge Overland
+*/
+@Transactional
+public class DefaultEventChartService
+    implements EventChartService
+{
+    private HibernateIdentifiableObjectStore<EventChart> eventChartStore;
+
+    public void setEventChartStore( HibernateIdentifiableObjectStore<EventChart> eventChartStore )
+    {
+        this.eventChartStore = eventChartStore;
+    }
+
+    // -------------------------------------------------------------------------
+    // EventReportService implementation
+    // -------------------------------------------------------------------------
+
+    public int saveEventChart( EventChart eventChart )
+    {
+        return eventChartStore.save( eventChart );
+    }
+    
+    public void updateEventChart( EventChart eventChart )
+    {
+        eventChartStore.update( eventChart );
+    }
+    
+    public EventChart getEventChart( int id )
+    {
+        return eventChartStore.get( id );
+    }
+    
+    public EventChart getEventChart( String uid )
+    {
+        return eventChartStore.getByUid( uid );
+    }
+    
+    public void deleteEventChart( EventChart eventChart )
+    {
+        eventChartStore.delete( eventChart );
+    }
+    
+    public List<EventChart> getAllEventCharts()
+    {
+        return eventChartStore.getAll();
+    }
+}

=== added directory 'dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart'
=== added file 'dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/EventChart.hbm.xml'
--- dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/EventChart.hbm.xml	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-tracker/src/main/resources/org/hisp/dhis/eventchart/EventChart.hbm.xml	2014-06-16 16:20:38 +0000
@@ -0,0 +1,143 @@
+<?xml version="1.0"?>
+<!DOCTYPE hibernate-mapping PUBLIC
+  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
+  "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd";
+  [<!ENTITY identifiableProperties SYSTEM "classpath://org/hisp/dhis/common/identifiableProperties.hbm">]
+  >
+
+<hibernate-mapping>
+  <class name="org.hisp.dhis.eventchart.EventChart" table="eventchart">
+
+    <cache usage="read-write" />
+
+    <id name="id" column="eventchartid">
+      <generator class="native" />
+    </id>
+    &identifiableProperties;
+
+    <property name="name" column="name" not-null="true" unique="false" length="230" />
+
+    <list name="organisationUnits" table="eventchart_organisationunits">
+      <cache usage="read-write" />
+      <key column="eventchartid" foreign-key="fk_eventchart_organisationunits_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <many-to-many column="organisationunitid" class="org.hisp.dhis.organisationunit.OrganisationUnit"
+        foreign-key="fk_eventchart_organisationunits_organisationunitid" />
+    </list>
+
+    <list name="periods" table="eventchart_periods">
+      <cache usage="read-write" />
+      <key column="eventchartid" foreign-key="fk_eventchart_periods_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <many-to-many column="periodid" class="org.hisp.dhis.period.Period"
+        foreign-key="fk_eventchart_periods_periodid" />
+    </list>
+
+    <many-to-one name="relatives" unique="true" class="org.hisp.dhis.period.RelativePeriods" column="relativeperiodsid"
+      cascade="all-delete-orphan" foreign-key="fk_report_relativeperiodsid" />
+
+    <list name="organisationUnitLevels" table="eventchart_orgunitlevels">
+      <cache usage="read-write" />
+      <key column="eventchartid" foreign-key="fk_eventchart_orgunitlevels_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <element column="orgunitlevel" type="integer" />
+    </list>
+
+    <list name="itemOrganisationUnitGroups" table="eventchart_itemorgunitgroups">
+      <cache usage="read-write" />
+      <key column="eventchartid" foreign-key="fk_eventchart_itemorgunitunitgroups_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <many-to-many column="orgunitgroupid" class="org.hisp.dhis.organisationunit.OrganisationUnitGroup"
+        foreign-key="fk_eventchart_itemorgunitgroups_orgunitgroupid" />
+    </list>
+
+    <list name="attributeDimensions" table="eventchart_attributedimensions" cascade="all, delete-orphan">
+      <key column="eventchartid" foreign-key="fk_eventchart_attributedimensions_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <many-to-many column="trackedentityattributedimensionid" class="org.hisp.dhis.trackedentity.TrackedEntityAttributeDimension"
+        foreign-key="fk_eventchart_attributedimensions_attributedimensionid" />
+    </list>
+
+    <list name="dataElementDimensions" table="eventchart_dataelementdimensions" cascade="all, delete-orphan">
+      <key column="eventchartid" foreign-key="fk_eventchart_dataelementdimensions_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <many-to-many column="trackedentitydataelementdimensionid" class="org.hisp.dhis.trackedentity.TrackedEntityDataElementDimension"
+        foreign-key="fk_eventchart_dataelementdimensions_dataelementdimensionid" />
+    </list>
+
+    <property name="userOrganisationUnit" />
+
+    <property name="userOrganisationUnitChildren" />
+
+    <property name="userOrganisationUnitGrandChildren" />
+
+    <property name="showData" />
+
+    <property name="hideEmptyRows" />
+
+    <property name="rewindRelativePeriods" />
+
+    <property name="rangeAxisMaxValue" />
+
+    <property name="rangeAxisMinValue" />
+
+    <property name="rangeAxisSteps" />
+
+    <property name="rangeAxisDecimals" />
+
+    <many-to-one name="program" class="org.hisp.dhis.program.Program"
+      column="programid" not-null="true" foreign-key="fk_eventchart_programid" />
+
+    <many-to-one name="programStage" class="org.hisp.dhis.program.ProgramStage"
+      column="programstageid" foreign-key="fk_eventchart_programstageid" />
+
+    <property name="startDate" />
+
+    <property name="endDate" />
+
+    <property name="dataType" not-null="true" />
+
+    <list name="columnDimensions" table="eventchart_columns">
+      <cache usage="read-write" />
+      <key column="eventchartid" foreign-key="fk_eventchart_columns_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <element type="string" column="dimension" />
+    </list>
+
+    <list name="rowDimensions" table="eventchart_rows">
+      <cache usage="read-write" />
+      <key column="eventchartid" foreign-key="fk_eventchart_rows_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <element type="string" column="dimension" />
+    </list>
+
+    <list name="filterDimensions" table="eventchart_filters">
+      <cache usage="read-write" />
+      <key column="eventchartid" foreign-key="fk_eventchart_filters_eventchartid" />
+      <list-index column="sort_order" base="0" />
+      <element type="string" column="dimension" />
+    </list>
+
+    <property name="hideEmptyRows" />
+
+    <property name="countType" />
+
+    <property name="sortOrder" />
+
+    <property name="topLimit" />
+
+    <!-- Access properties -->
+    <property name="externalAccess" />
+
+    <many-to-one name="user" class="org.hisp.dhis.user.User" column="userid" foreign-key="fk_eventchart_userid" />
+
+    <property name="publicAccess" length="8" />
+
+    <set name="userGroupAccesses" table="eventchartusergroupaccesses">
+      <cache usage="read-write" />
+      <key column="eventchartid" />
+      <many-to-many class="org.hisp.dhis.user.UserGroupAccess" column="usergroupaccessid" unique="true" />
+    </set>
+
+  </class>
+</hibernate-mapping>

=== added file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventChartController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventChartController.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/event/EventChartController.java	2014-06-16 16:20:38 +0000
@@ -0,0 +1,196 @@
+package org.hisp.dhis.webapi.controller.event;
+
+/*
+ * Copyright (c) 2004-2014, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import org.hisp.dhis.common.DimensionService;
+import org.hisp.dhis.dxf2.utils.JacksonUtils;
+import org.hisp.dhis.eventchart.EventChart;
+import org.hisp.dhis.eventchart.EventChartService;
+import org.hisp.dhis.i18n.I18nFormat;
+import org.hisp.dhis.i18n.I18nManager;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.program.ProgramService;
+import org.hisp.dhis.program.ProgramStageService;
+import org.hisp.dhis.schema.descriptors.EventChartSchemaDescriptor;
+import org.hisp.dhis.webapi.controller.AbstractCrudController;
+import org.hisp.dhis.webapi.utils.ContextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import java.io.InputStream;
+
+import static org.hisp.dhis.common.DimensionalObjectUtils.getDimensions;
+import static org.hisp.dhis.common.DimensionalObjectUtils.toDimension;
+
+/**
+ * @author Jan Henrik Overland
+ */
+@Controller
+@RequestMapping( value = EventChartSchemaDescriptor.API_ENDPOINT )
+public class EventChartController
+    extends AbstractCrudController<EventChart>
+{
+    @Autowired
+    private EventChartService eventChartService;
+
+    @Autowired
+    private DimensionService dimensionService;
+
+    @Autowired
+    private ProgramService programService;
+
+    @Autowired
+    private ProgramStageService programStageService;
+
+    @Autowired
+    private I18nManager i18nManager;
+
+    //--------------------------------------------------------------------------
+    // CRUD
+    //--------------------------------------------------------------------------
+
+    @Override
+    @RequestMapping( method = RequestMethod.POST, consumes = "application/json" )
+    public void postJsonObject( HttpServletResponse response, HttpServletRequest request, InputStream input ) throws Exception
+    {
+        EventChart eventChart = JacksonUtils.fromJson( input, EventChart.class );
+
+        mergeEventChart( eventChart );
+
+        eventChartService.saveEventChart( eventChart );
+
+        ContextUtils.createdResponse( response, "Event chart created", EventChartSchemaDescriptor.API_ENDPOINT + "/" + eventChart.getUid() );
+    }
+
+    @Override
+    @RequestMapping( value = "/{uid}", method = RequestMethod.PUT, consumes = "application/json" )
+    @ResponseStatus( value = HttpStatus.NO_CONTENT )
+    public void putJsonObject( HttpServletResponse response, HttpServletRequest request, @PathVariable( "uid" ) String uid, InputStream input ) throws Exception
+    {
+        EventChart eventChart = eventChartService.getEventChart( uid );
+
+        if ( eventChart == null )
+        {
+            ContextUtils.notFoundResponse( response, "Event chart does not exist: " + uid );
+            return;
+        }
+
+        EventChart newEventChart = JacksonUtils.fromJson( input, EventChart.class );
+
+        mergeEventChart( newEventChart );
+
+        eventChart.mergeWith( newEventChart );
+
+        eventChartService.updateEventChart( eventChart );
+    }
+
+    @Override
+    @RequestMapping( value = "/{uid}", method = RequestMethod.DELETE )
+    @ResponseStatus( value = HttpStatus.NO_CONTENT )
+    public void deleteObject( HttpServletResponse response, HttpServletRequest request, @PathVariable( "uid" ) String uid ) throws Exception
+    {
+        EventChart eventChart = eventChartService.getEventChart( uid );
+
+        if ( eventChart == null )
+        {
+            ContextUtils.notFoundResponse( response, "Event report does not exist: " + uid );
+            return;
+        }
+
+        eventChartService.deleteEventChart( eventChart );
+    }
+
+    //--------------------------------------------------------------------------
+    // Hooks
+    //--------------------------------------------------------------------------
+
+    @Override
+    protected void postProcessEntity( EventChart eventChart )
+        throws Exception
+    {
+        eventChart.populateAnalyticalProperties();
+
+        for ( OrganisationUnit organisationUnit : eventChart.getOrganisationUnits() )
+        {
+            eventChart.getParentGraphMap().put( organisationUnit.getUid(), organisationUnit.getParentGraph() );
+        }
+
+        I18nFormat format = i18nManager.getI18nFormat();
+
+        if ( eventChart.getPeriods() != null && !eventChart.getPeriods().isEmpty() )
+        {
+            for ( Period period : eventChart.getPeriods() )
+            {
+                period.setName( format.formatPeriod( period ) );
+            }
+        }
+    }
+
+    //--------------------------------------------------------------------------
+    // Supportive methods
+    //--------------------------------------------------------------------------
+
+    private void mergeEventChart( EventChart eventChart )
+    {
+        dimensionService.mergeAnalyticalObject( eventChart );
+
+        eventChart.getFilterDimensions().clear();
+        
+        if ( eventChart.getColumns() != null )
+        {
+            eventChart.setSeries( toDimension( eventChart.getColumns().get( 0 ).getDimension() ) );
+        }
+
+        if ( eventChart.getRows() != null )
+        {
+            eventChart.setCategory( toDimension( eventChart.getRows().get( 0 ).getDimension() ) );
+        }
+        
+        eventChart.getFilterDimensions().addAll( getDimensions( eventChart.getFilters() ) );
+
+        if ( eventChart.getProgram() != null )
+        {
+            eventChart.setProgram( programService.getProgram( eventChart.getProgram().getUid() ) );
+        }
+
+        if ( eventChart.getProgramStage() != null )
+        {
+            eventChart.setProgramStage( programStageService.getProgramStage( eventChart.getProgramStage().getUid() ) );
+        }
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/scripts/plugin.js'
--- dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/scripts/plugin.js	2014-06-16 13:20:22 +0000
+++ dhis-2/dhis-web/dhis-web-visualizer/src/main/webapp/dhis-web-visualizer/app/scripts/plugin.js	2014-06-16 15:43:42 +0000
@@ -698,10 +698,12 @@
 						console.log('Response: no valid headers');
 						return;
 					}
-
+                    
 					if (!(Ext.isArray(config.rows) && config.rows.length > 0)) {
-						alert('No values found');
-						return;
+                        if (DV.app) {
+                            alert('No values found');
+                            return;
+                        }
 					}
 
 					if (config.headers.length !== config.rows[0].length) {
@@ -2036,7 +2038,7 @@
                 getDefaultSeriesTitle = function(store) {
                     var a = [];
 
-                    if (Ext.isObject(xLayout.legend) && Ext.isArray(xLayout.legend.seriesNames)) {
+                    if (xLayout.legend && xLayout.legend.seriesNames) {
                         return xLayout.legend.seriesNames;
                     }
                     else {