← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 5920: Impl new solution for user feedback on long processes. Added a Notifier interface and InMemoryNot...

 

Merge authors:
  Lars Helge Øverland (larshelge)
------------------------------------------------------------
revno: 5920 [merge]
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Sun 2012-02-12 18:13:48 +0100
message:
  Impl new solution for user feedback on long processes. Added a Notifier interface and InMemoryNotifier implementation which provides methods for adding and retrieving notifications. Notification has category, level, time and message properties.
added:
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/InMemoryNotifier.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/Notification.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/NotificationCategory.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/NotificationLevel.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/Notifier.java
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/htmlNotifications.vm
  dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/commons/action/GetNotificationsAction.java
  dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/datamart/
  dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/datamart/action/
  dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/datamart/action/StartExportAction.java
  dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/javascript/dataMart.js
  dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/viewDataMartForm.vm
modified:
  dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/engine/DataMartEngine.java
  dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/engine/DefaultDataMartEngine.java
  dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/impl/DefaultDataMartService.java
  dhis-2/dhis-services/dhis-service-datamart-default/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/scheduling/DataMartTask.java
  dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/Clock.java
  dhis-2/dhis-support/dhis-support-system/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-commons/src/main/resources/dhis-web-commons.xml
  dhis-2/dhis-web/dhis-web-reporting/src/main/resources/META-INF/dhis/beans.xml
  dhis-2/dhis-web/dhis-web-reporting/src/main/resources/org/hisp/dhis/reporting/i18n_module.properties
  dhis-2/dhis-web/dhis-web-reporting/src/main/resources/struts.xml
  dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/menu.vm


--
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-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/engine/DataMartEngine.java'
--- dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/engine/DataMartEngine.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/engine/DataMartEngine.java	2012-02-12 13:16:57 +0000
@@ -31,7 +31,6 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import org.hisp.dhis.common.ProcessState;
 import org.hisp.dhis.organisationunit.OrganisationUnitGroup;
 
 /**
@@ -57,5 +56,5 @@
      */
     void export( Collection<Integer> dataElementIds, Collection<Integer> indicatorIds,
         Collection<Integer> periodIds, Collection<Integer> organisationUnitIds, Collection<Integer> organisationUnitGroupIds,
-        boolean completeExport, ProcessState processState );
+        boolean completeExport );
 }

=== modified file 'dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/engine/DefaultDataMartEngine.java'
--- dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/engine/DefaultDataMartEngine.java	2012-02-02 20:01:36 +0000
+++ dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/engine/DefaultDataMartEngine.java	2012-02-12 17:11:20 +0000
@@ -37,7 +37,6 @@
 
 import org.hisp.dhis.aggregation.AggregatedDataValueService;
 import org.hisp.dhis.aggregation.AggregatedOrgUnitDataValueService;
-import org.hisp.dhis.common.ProcessState;
 import org.hisp.dhis.dataelement.DataElement;
 import org.hisp.dhis.dataelement.DataElementCategoryService;
 import org.hisp.dhis.dataelement.DataElementOperand;
@@ -64,6 +63,7 @@
 import org.hisp.dhis.system.filter.AggregatableDataElementFilter;
 import org.hisp.dhis.system.filter.OrganisationUnitAboveOrEqualToLevelFilter;
 import org.hisp.dhis.system.filter.PastAndCurrentPeriodFilter;
+import org.hisp.dhis.system.notification.Notifier;
 import org.hisp.dhis.system.util.Clock;
 import org.hisp.dhis.system.util.ConcurrentUtils;
 import org.hisp.dhis.system.util.ConversionUtils;
@@ -73,6 +73,7 @@
 import org.springframework.transaction.annotation.Transactional;
 
 import static org.hisp.dhis.setting.SystemSettingManager.*;
+import static org.hisp.dhis.system.notification.NotificationCategory.DATAMART;
 
 /**
  * @author Lars Helge Overland
@@ -174,6 +175,13 @@
     {
         this.systemSettingManager = systemSettingManager;
     }
+    
+    private Notifier notifier;
+
+    public void setNotifier( Notifier notifier )
+    {
+        this.notifier = notifier;
+    }
 
     // -------------------------------------------------------------------------
     // DataMartEngine implementation
@@ -182,11 +190,12 @@
     @Transactional
     public void export( Collection<Integer> dataElementIds, Collection<Integer> indicatorIds,
         Collection<Integer> periodIds, Collection<Integer> organisationUnitIds, Collection<Integer> organisationUnitGroupIds, 
-        boolean completeExport, ProcessState state )
+        boolean completeExport )
     {
         final int cpuCores = SystemUtils.getCpuCores();
         
         Clock clock = new Clock().startClock().logTime( "Data mart export process started, number of CPU cores: " + cpuCores + ", " + SystemUtils.getMemoryString() );
+        notifier.notify( DATAMART, "Process started" );
 
         // ---------------------------------------------------------------------
         // Replace null with empty collection
@@ -208,7 +217,8 @@
         final Collection<OrganisationUnitGroup> organisationUnitGroups = organisationUnitGroupService.getOrganisationUnitGroups( organisationUnitGroupIds );
         final Collection<DataElement> dataElements = dataElementService.getDataElements( dataElementIds );
 
-        clock.logTime( "Retrieved objects" );
+        clock.logTime( "Retrieved meta-data objects" );
+        notifier.notify( DATAMART, "Filtering meta-data" );
 
         // ---------------------------------------------------------------------
         // Filter objects
@@ -220,6 +230,7 @@
         expressionService.filterInvalidIndicators( indicators );
 
         clock.logTime( "Filtered objects" );
+        notifier.notify( DATAMART, "Loading indicator formulas" );
 
         // ---------------------------------------------------------------------
         // Explode indicator expressions
@@ -232,6 +243,7 @@
         }
 
         clock.logTime( "Exploded indicator expressions" );
+        notifier.notify( DATAMART, "Loading data elements" );
 
         // ---------------------------------------------------------------------
         // Get operands
@@ -245,6 +257,7 @@
         allOperands.addAll( indicatorOperands );
 
         clock.logTime( "Retrieved operands: " + allOperands.size() );
+        notifier.notify( DATAMART, "Loading periods" );
 
         // ---------------------------------------------------------------------
         // Filter out future periods
@@ -253,6 +266,7 @@
         FilterUtils.filter( periods, new PastAndCurrentPeriodFilter() );
         
         clock.logTime( "Number of periods: " + periods.size() );
+        notifier.notify( DATAMART, "Filtering data elements without data" );
         
         // ---------------------------------------------------------------------
         // Remove operands without data
@@ -263,13 +277,12 @@
         indicatorOperands.retainAll( allOperands );
         
         clock.logTime( "Number of operands with data: " + allOperands.size() + ", " + SystemUtils.getMemoryString() );
+        notifier.notify( DATAMART, "Populating crosstabulation table" );
 
         // ---------------------------------------------------------------------
         // Create crosstabtable
         // ---------------------------------------------------------------------
 
-        state.setMessage( "crosstabulating_data" );
-
         final Collection<Integer> intersectingPeriodIds = ConversionUtils.getIdentifiers( Period.class, periodService.getIntersectionPeriods( periods ) );
         final Set<Integer> childrenIds = organisationUnitService.getOrganisationUnitHierarchy().getChildren( organisationUnitIds );
         final List<List<Integer>> childrenPages = new PaginatedList<Integer>( childrenIds ).setNumberOfPages( cpuCores ).getPages();
@@ -288,15 +301,16 @@
         
         clock.logTime( "Populated crosstab table, " + SystemUtils.getMemoryString() );
 
+        // ---------------------------------------------------------------------
+        // 1. Create aggregated data cache
+        // ---------------------------------------------------------------------
+
         final boolean isIndicators = indicators != null && indicators.size() > 0;
         
-        // ---------------------------------------------------------------------
-        // 1. Create aggregated data cache
-        // ---------------------------------------------------------------------
-
         crossTabService.createAggregatedDataCache( indicatorOperands, key );
         
         clock.logTime( "Created aggregated data cache, number of indicator operands: " + indicatorOperands.size() + ", operands with data: " + allOperands.size() );
+        notifier.notify( DATAMART, "Dropping database indexes" );
         
         // ---------------------------------------------------------------------
         // 2. Drop potential indexes
@@ -305,6 +319,7 @@
         aggregatedDataValueService.dropIndex( true, isIndicators );
         
         clock.logTime( "Dropped potential indexes" );
+        notifier.notify( DATAMART, "Deleting existing data element data" );
         
         // ---------------------------------------------------------------------
         // 3. Delete existing aggregated datavalues
@@ -320,13 +335,12 @@
         }
 
         clock.logTime( "Deleted existing aggregated datavalues" );
+        notifier.notify( DATAMART, "Exporting data for data elements" );
         
         // ---------------------------------------------------------------------
         // 4. Export data element values
         // ---------------------------------------------------------------------
 
-        state.setMessage( "exporting_data_for_data_elements" );
-
         List<List<OrganisationUnit>> organisationUnitPages = new PaginatedList<OrganisationUnit>( organisationUnits ).setNumberOfPages( cpuCores ).getPages();
 
         if ( allOperands.size() > 0 )
@@ -342,10 +356,11 @@
             }
 
             ConcurrentUtils.waitForCompletion( futures );
-            
-            clock.logTime( "Exported values for data element operands (" + allOperands.size() + "), pages: " + organisationUnitPages.size() + ", " + SystemUtils.getMemoryString() );
         }
-
+        
+        clock.logTime( "Exported values for data element operands (" + allOperands.size() + "), pages: " + organisationUnitPages.size() + ", " + SystemUtils.getMemoryString() );
+        notifier.notify( DATAMART, "Deleting existing indicator data" );
+        
         // ---------------------------------------------------------------------
         // 5. Delete existing aggregated indicatorvalues
         // ---------------------------------------------------------------------
@@ -360,13 +375,12 @@
         }
 
         clock.logTime( "Deleted existing aggregated indicatorvalues" );
+        notifier.notify( DATAMART, "Exporting data for indicators" );
         
         // ---------------------------------------------------------------------
         // 6. Export indicator values
         // ---------------------------------------------------------------------
 
-        state.setMessage( "exporting_data_for_indicators" );
-
         if ( isIndicators )
         {
             List<Future<?>> futures = new ArrayList<Future<?>>();
@@ -378,9 +392,10 @@
             }
 
             ConcurrentUtils.waitForCompletion( futures );
-            
-            clock.logTime( "Exported values for indicators (" + indicators.size() + "), pages: " + organisationUnitPages.size() + ", " + SystemUtils.getMemoryString() );
         }
+        
+        clock.logTime( "Exported values for indicators (" + indicators.size() + "), pages: " + organisationUnitPages.size() + ", " + SystemUtils.getMemoryString() );
+        notifier.notify( DATAMART, "Creating database indexes" );
 
         // ---------------------------------------------------------------------
         // 7. Drop aggregated data cache
@@ -416,6 +431,7 @@
             crossTabService.createAggregatedOrgUnitDataCache( indicatorOperands, key );
             
             clock.logTime( "Created aggregated org unit data cache" );
+            notifier.notify( DATAMART, "Dropping database indexes" );
             
             // -----------------------------------------------------------------
             // 2. Drop potential indexes
@@ -424,6 +440,7 @@
             aggregatedOrgUnitDataValueService.dropIndex( true, isIndicators );
 
             clock.logTime( "Dropped potential org unit indexes" );
+            notifier.notify( DATAMART, "Deleting existing data element data" );
 
             // ---------------------------------------------------------------------
             // 3. Delete existing aggregated datavalues
@@ -439,13 +456,12 @@
             }
 
             clock.logTime( "Deleted existing aggregated org unit datavalues" );
+            notifier.notify( DATAMART, "Exporting data for data elements" );
 
             // ---------------------------------------------------------------------
             // 4. Export data element values
             // ---------------------------------------------------------------------
 
-            state.setMessage( "exporting_data_for_data_elements" );
-
             Collection<OrganisationUnit> groupOrganisationUnits = new HashSet<OrganisationUnit>( organisationUnits );
             
             FilterUtils.filter( groupOrganisationUnits, new OrganisationUnitAboveOrEqualToLevelFilter( groupLevel ) );
@@ -465,10 +481,11 @@
                 }
 
                 ConcurrentUtils.waitForCompletion( futures );
-                
-                clock.logTime( "Exported values for data element operands (" + allOperands.size() + "), pages: " + organisationUnitPages.size()  + ", " + SystemUtils.getMemoryString() );
             }
-
+            
+            clock.logTime( "Exported values for data element operands (" + allOperands.size() + "), pages: " + organisationUnitPages.size()  + ", " + SystemUtils.getMemoryString() );
+            notifier.notify( DATAMART, "Deleting existing indicator data" );
+            
             // ---------------------------------------------------------------------
             // 5. Delete existing aggregated indicatorvalues
             // ---------------------------------------------------------------------
@@ -483,13 +500,12 @@
             }
 
             clock.logTime( "Deleted existing aggregated org unit indicatorvalues" );
+            notifier.notify( DATAMART, "Exporting data for indicators" );
 
             // ---------------------------------------------------------------------
             // 6. Export indicator values
             // ---------------------------------------------------------------------
 
-            state.setMessage( "exporting_data_for_indicators" );
-
             if ( isIndicators )
             {
                 List<Future<?>> futures = new ArrayList<Future<?>>();
@@ -501,9 +517,10 @@
                 }
 
                 ConcurrentUtils.waitForCompletion( futures );
-                
-                clock.logTime( "Exported values for indicators (" + indicators.size() + "), pages: " + organisationUnitPages.size() + ", " + SystemUtils.getMemoryString() );
             }
+            
+            clock.logTime( "Exported values for indicators (" + indicators.size() + "), pages: " + organisationUnitPages.size() + ", " + SystemUtils.getMemoryString() );
+            notifier.notify( DATAMART, "Creating database indexes" );
 
             // ---------------------------------------------------------------------
             // 7. Drop aggregated data cache
@@ -534,7 +551,7 @@
         crossTabService.dropCrossTabTable( key );
         
         clock.logTime( "Dropped crosstab table" );
-
         clock.logTime( "Data mart export process completed" );
+        notifier.notify( DATAMART, "Data mart process completed" );
     }
 }

=== modified file 'dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/impl/DefaultDataMartService.java'
--- dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/impl/DefaultDataMartService.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-services/dhis-service-datamart-default/src/main/java/org/hisp/dhis/datamart/impl/DefaultDataMartService.java	2012-02-12 13:16:57 +0000
@@ -42,7 +42,6 @@
 import org.hisp.dhis.period.Period;
 import org.hisp.dhis.period.PeriodService;
 import org.hisp.dhis.period.RelativePeriods;
-import org.hisp.dhis.system.process.OutputHolderState;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -97,14 +96,14 @@
             getIdentifiers( Indicator.class, dataMartExport.getIndicators() ), 
             getIdentifiers( Period.class, allPeriods ),
             getIdentifiers( OrganisationUnit.class, dataMartExport.getOrganisationUnits() ),
-            null, false, new OutputHolderState() );
+            null, false );
     }
 
  
     public void export( Collection<Integer> dataElementIds, Collection<Integer> indicatorIds,
         Collection<Integer> periodIds, Collection<Integer> organisationUnitIds )
     {
-        dataMartEngine.export( dataElementIds, indicatorIds, periodIds, organisationUnitIds, null, false, new OutputHolderState() );
+        dataMartEngine.export( dataElementIds, indicatorIds, periodIds, organisationUnitIds, null, false );
     }
     
     public void export( Collection<Integer> dataElementIds, Collection<Integer> indicatorIds,
@@ -122,7 +121,7 @@
             periodIds.addAll( getIdentifiers( Period.class, periodService.reloadPeriods( relatives.getRelativePeriods() ) ) );
         }
         
-        dataMartEngine.export( dataElementIds, indicatorIds, periodIds, organisationUnitIds, organisationUnitGroupIds, completeExport, new OutputHolderState() );
+        dataMartEngine.export( dataElementIds, indicatorIds, periodIds, organisationUnitIds, organisationUnitGroupIds, completeExport );
     }
     
     // -------------------------------------------------------------------------

=== modified file 'dhis-2/dhis-services/dhis-service-datamart-default/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-services/dhis-service-datamart-default/src/main/resources/META-INF/dhis/beans.xml	2012-02-02 20:01:36 +0000
+++ dhis-2/dhis-services/dhis-service-datamart-default/src/main/resources/META-INF/dhis/beans.xml	2012-02-12 13:16:57 +0000
@@ -36,6 +36,7 @@
     <property name="organisationUnitService" ref="org.hisp.dhis.organisationunit.OrganisationUnitService" />
 	<property name="organisationUnitGroupService" ref="org.hisp.dhis.organisationunit.OrganisationUnitGroupService" />
 	<property name="systemSettingManager" ref="org.hisp.dhis.setting.SystemSettingManager" />
+	<property name="notifier" ref="notifier" />
   </bean>
 
   <bean id="internal-process-DataMart" class="org.hisp.dhis.datamart.DataMartInternalProcess" scope="prototype">

=== added directory 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification'
=== added file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/InMemoryNotifier.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/InMemoryNotifier.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/InMemoryNotifier.java	2012-02-12 17:11:20 +0000
@@ -0,0 +1,73 @@
+package org.hisp.dhis.system.notification;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.annotation.PostConstruct;
+
+public class InMemoryNotifier
+    implements Notifier
+{
+    private int MAX_SIZE = 1000;
+    
+    private List<Notification> notifications;
+    
+    @PostConstruct
+    public void init()
+    {
+        notifications = new ArrayList<Notification>();
+    }
+
+    // -------------------------------------------------------------------------
+    // Notifier implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public void notify( NotificationCategory category, String message )
+    {
+        notify( NotificationLevel.INFO, category, message );
+    }
+    
+    @Override
+    public void notify( NotificationLevel level, NotificationCategory category, String message )
+    {
+        Notification notification = new Notification( level, category, new Date(), message );
+        
+        notifications.add( 0, notification );
+        
+        if ( notifications.size() > MAX_SIZE )
+        {
+            notifications.remove( MAX_SIZE );
+        }
+    }
+
+    @Override
+    public List<Notification> getNotifications( int max )
+    {
+        max = max > notifications.size() ? notifications.size() : max;
+        
+        return notifications.subList( 0, max );
+    }
+
+    @Override
+    public List<Notification> getNotifications( NotificationCategory category, int max )
+    {
+        List<Notification> list = new ArrayList<Notification>();
+        
+        for ( Notification notification : notifications )
+        {
+            if ( list.size() == max )
+            {
+                break;
+            }
+            
+            if ( category.equals( notification.getCategory() ) )
+            {
+                list.add( notification );
+            }
+        }
+        
+        return list;
+    }
+}

=== added file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/Notification.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/Notification.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/Notification.java	2012-02-12 13:16:57 +0000
@@ -0,0 +1,129 @@
+package org.hisp.dhis.system.notification;
+
+import java.util.Date;
+
+import org.hisp.dhis.common.CodeGenerator;
+
+public class Notification
+{
+    private String uid;
+    
+    private NotificationLevel level;
+    
+    private NotificationCategory category;
+    
+    private Date time;
+    
+    private String message;
+
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
+
+    public Notification()
+    {
+        this.uid = CodeGenerator.generateCode();
+    }
+
+    public Notification( NotificationLevel level, NotificationCategory category, Date time, String message )
+    {
+        this.uid = CodeGenerator.generateCode();
+        this.level = level;
+        this.category = category;
+        this.time = time;
+        this.message = message;
+    }
+
+    // -------------------------------------------------------------------------
+    // Get and set
+    // -------------------------------------------------------------------------
+
+    public NotificationLevel getLevel()
+    {
+        return level;
+    }
+
+    public String getUid()
+    {
+        return uid;
+    }
+
+    public void setUid( String uid )
+    {
+        this.uid = uid;
+    }
+
+    public void setLevel( NotificationLevel level )
+    {
+        this.level = level;
+    }
+
+    public NotificationCategory getCategory()
+    {
+        return category;
+    }
+
+    public void setCategory( NotificationCategory category )
+    {
+        this.category = category;
+    }
+
+    public Date getTime()
+    {
+        return time;
+    }
+
+    public void setTime( Date time )
+    {
+        this.time = time;
+    }
+
+    public String getMessage()
+    {
+        return message;
+    }
+
+    public void setMessage( String message )
+    {
+        this.message = message;
+    }
+
+    // -------------------------------------------------------------------------
+    // equals, hashCode, toString
+    // -------------------------------------------------------------------------
+
+    @Override
+    public int hashCode()
+    {
+        return uid.hashCode();
+    }
+
+    @Override
+    public boolean equals( Object object )
+    {
+        if ( this == object )
+        {
+            return true;
+        }
+        
+        if ( object == null )
+        {
+            return false;
+        }
+        
+        if ( getClass() != object.getClass() )
+        {
+            return false;
+        }
+        
+        final Notification other = (Notification) object;
+        
+        return uid.equals( other.uid );
+    }
+
+    @Override
+    public String toString()
+    {
+        return "[Level: " + level + ", category: " + category + ", time: " + time + ", message: " + message + "]";
+    }
+}

=== added file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/NotificationCategory.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/NotificationCategory.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/NotificationCategory.java	2012-02-12 13:16:57 +0000
@@ -0,0 +1,7 @@
+package org.hisp.dhis.system.notification;
+
+public enum NotificationCategory
+{
+    DATAMART,
+    IMPORT
+}

=== added file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/NotificationLevel.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/NotificationLevel.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/NotificationLevel.java	2012-02-12 13:16:57 +0000
@@ -0,0 +1,8 @@
+package org.hisp.dhis.system.notification;
+
+public enum NotificationLevel
+{
+    INFO,
+    WARN,
+    ERROR
+}

=== added file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/Notifier.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/Notifier.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/notification/Notifier.java	2012-02-12 13:38:06 +0000
@@ -0,0 +1,14 @@
+package org.hisp.dhis.system.notification;
+
+import java.util.List;
+
+public interface Notifier
+{
+    void notify( NotificationCategory category, String message );
+    
+    void notify(  NotificationLevel level, NotificationCategory category, String message );
+    
+    List<Notification> getNotifications( int max );
+    
+    List<Notification> getNotifications( NotificationCategory category, int max );
+}

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/scheduling/DataMartTask.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/scheduling/DataMartTask.java	2012-02-11 13:10:26 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/scheduling/DataMartTask.java	2012-02-12 13:38:06 +0000
@@ -86,6 +86,17 @@
     
     private SystemSettingManager systemSettingManager;
 
+    // -------------------------------------------------------------------------
+    // Params
+    // -------------------------------------------------------------------------
+
+    private List<Period> periods;
+    
+    public void setPeriods( List<Period> periods )
+    {
+        this.periods = periods;
+    }
+
     private boolean last6Months;
 
     public void setLast6Months( boolean last6Months )
@@ -100,6 +111,10 @@
         this.from6To12Months = from6To12Months;
     }
 
+    // -------------------------------------------------------------------------
+    // Constructors
+    // -------------------------------------------------------------------------
+
     public DataMartTask()
     {
     }
@@ -119,7 +134,11 @@
         this.dataSetService = dataSetService;
         this.systemSettingManager = systemSettingManager;
     }
-    
+
+    // -------------------------------------------------------------------------
+    // Runnable implementation
+    // -------------------------------------------------------------------------
+
     @Override  
     @SuppressWarnings("unchecked")  
     public void run()
@@ -142,23 +161,35 @@
         completenessService.exportDataSetCompleteness( dataSetIds, periodIds, organisationUnitIds ); 
     }
 
+    // -------------------------------------------------------------------------
+    // Supportive methods
+    // -------------------------------------------------------------------------
+
     /**
-     * Generates periods based on parameters and period types argument.
+     * Generates periods based on parameters and period types argument. Returns
+     * the list of periods with class scope if it has been set and has one or
+     * more periods. Returns a list of relative periods based on the given set
+     * of period types otherwise.
      */
     public List<Period> getPeriods( Set<String> periodTypes )
     {
-        List<Period> periods = new RelativePeriods().getRelativePeriods( periodTypes ).getRelativePeriods( 1 );
+        if ( periods != null && periods.size() > 0 )
+        {
+            return periods;
+        }
+        
+        List<Period> relativePeriods = new RelativePeriods().getRelativePeriods( periodTypes ).getRelativePeriods( 1 );
         
         if ( periodTypes.contains( YearlyPeriodType.NAME ) ) // Add last year
         {
-            periods.addAll( new RelativePeriods().setLastYear( true ).getRelativePeriods( 1 ) );
+            relativePeriods.addAll( new RelativePeriods().setLastYear( true ).getRelativePeriods( 1 ) );
         }
         
         final Date date = new Cal().now().subtract( Calendar.MONTH, 7 ).time();
         
         if ( last6Months )
         {
-            FilterUtils.filter( periods, new Filter<Period>()
+            FilterUtils.filter( relativePeriods, new Filter<Period>()
             {
                 public boolean retain( Period period )
                 {
@@ -168,7 +199,7 @@
         }
         else if ( from6To12Months )
         {
-            FilterUtils.filter( periods, new Filter<Period>()
+            FilterUtils.filter( relativePeriods, new Filter<Period>()
             {
                 public boolean retain( Period period )
                 {
@@ -177,6 +208,6 @@
             } );
         }
         
-        return periods;
+        return relativePeriods;
     }
 }

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/Clock.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/Clock.java	2011-12-26 10:07:59 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/Clock.java	2012-02-12 13:16:57 +0000
@@ -54,6 +54,11 @@
         return this;
     }
     
+    public String time()
+    {
+        return DurationFormatUtils.formatDurationHMS( super.getSplitTime() );
+    }
+    
     public Clock logTime( String message )
     {
         super.split();

=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-support/dhis-support-system/src/main/resources/META-INF/dhis/beans.xml	2012-01-05 20:39:23 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/resources/META-INF/dhis/beans.xml	2012-02-12 13:16:57 +0000
@@ -28,4 +28,6 @@
   
   <bean id="org.hisp.dhis.system.velocity.VelocityManager" class="org.hisp.dhis.system.velocity.VelocityManager" />
 
+  <bean id="notifier" class="org.hisp.dhis.system.notification.InMemoryNotifier"/>
+
 </beans>

=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/htmlNotifications.vm'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/htmlNotifications.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/ajax/htmlNotifications.vm	2012-02-12 17:11:30 +0000
@@ -0,0 +1,23 @@
+<style type="text/css">
+.notificationTable {
+  background-color: #ffffbf;
+  border: 1px solid #cccc00;
+  padding: 6px;
+  border-radius: 3px;
+}
+
+.notificationTable td {
+  padding: 3px;
+}
+</style>
+
+<table class="notificationTable">
+<col width="120">
+<col width="380">
+#foreach( $notification in $notifications )
+<tr>
+	<td>${format.formatDateTime( $notification.time )}:</td>
+	<td>${encoder.htmlEncode( $notification.message )} #if( $velocityCount == 1 )&nbsp;<img src='../images/ajax-loader-bar.gif'>#end</td>
+</tr>
+#end
+</table>
\ No newline at end of file

=== added file 'dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/commons/action/GetNotificationsAction.java'
--- dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/commons/action/GetNotificationsAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/java/org/hisp/dhis/commons/action/GetNotificationsAction.java	2012-02-12 17:11:30 +0000
@@ -0,0 +1,107 @@
+package org.hisp.dhis.commons.action;
+
+/*
+ * Copyright (c) 2004-2012, 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.system.notification.Notification;
+import org.hisp.dhis.system.notification.NotificationCategory;
+import org.hisp.dhis.system.notification.Notifier;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Lars Helge Overland
+ */
+public class GetNotificationsAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+    
+    private Notifier notifier;
+
+    public void setNotifier( Notifier notifier )
+    {
+        this.notifier = notifier;
+    }
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+    
+    private String category;
+
+    public void setCategory( String category )
+    {
+        this.category = category;
+    }
+
+    private Integer max;
+
+    public void setMax( Integer max )
+    {
+        this.max = max;
+    }
+
+    // -------------------------------------------------------------------------
+    // Output
+    // -------------------------------------------------------------------------
+    
+    private List<Notification> notifications;
+    
+    public List<Notification> getNotifications()
+    {
+        return notifications;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+    
+    @Override
+    public String execute()
+        throws Exception
+    {
+        max = max != null ? max : 20;
+        
+        if ( category != null )
+        {
+            NotificationCategory notificationCategory = NotificationCategory.valueOf( category.toUpperCase() );
+            
+            notifications = notifier.getNotifications( notificationCategory, max );
+        }
+        else
+        {
+            notifications = notifier.getNotifications( max );
+        }
+            
+        return SUCCESS;
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml	2012-02-02 20:01:36 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/resources/META-INF/dhis/beans.xml	2012-02-12 17:11:20 +0000
@@ -318,6 +318,10 @@
 
   <!-- Common actions -->
 
+  <bean id="org.hisp.dhis.commons.action.GetNotificationsAction" class="org.hisp.dhis.commons.action.GetNotificationsAction" scope="prototype">
+	<property name="notifier" ref="notifier" />
+  </bean>
+
   <bean id="org.hisp.dhis.commons.action.GetUserAction" class="org.hisp.dhis.commons.action.GetUserAction" scope="prototype">
     <property name="userService" ref="org.hisp.dhis.user.UserService" />
   </bean>

=== modified file 'dhis-2/dhis-web/dhis-web-commons/src/main/resources/dhis-web-commons.xml'
--- dhis-2/dhis-web/dhis-web-commons/src/main/resources/dhis-web-commons.xml	2012-01-20 10:38:11 +0000
+++ dhis-2/dhis-web/dhis-web-commons/src/main/resources/dhis-web-commons.xml	2012-02-12 17:11:20 +0000
@@ -315,6 +315,11 @@
 
   <package name="dhis-web-commons-ajax" extends="dhis-web-commons" namespace="/dhis-web-commons-ajax">
 
+    <action name="getNotifications" class="org.hisp.dhis.commons.action.GetNotificationsAction">
+	  <result name="success" type="velocity">/dhis-web-commons/ajax/htmlNotifications.vm</result>
+      <param name="onExceptionReturn">plainTextError</param>
+    </action>
+
     <action name="getCategoryOptionCombos" class="org.hisp.dhis.commons.action.GetCategoryOptionCombosAction">
       <result name="success" type="velocity-xml">
         /dhis-web-commons/ajax/xmlCategoryOptionCombos.vm

=== added directory 'dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/datamart'
=== added directory 'dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/datamart/action'
=== added file 'dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/datamart/action/StartExportAction.java'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/datamart/action/StartExportAction.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/java/org/hisp/dhis/reporting/datamart/action/StartExportAction.java	2012-02-12 14:40:54 +0000
@@ -0,0 +1,80 @@
+package org.hisp.dhis.reporting.datamart.action;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.hisp.dhis.period.Period;
+import org.hisp.dhis.period.PeriodService;
+import org.hisp.dhis.system.scheduling.DataMartTask;
+import org.hisp.dhis.system.scheduling.Scheduler;
+import org.hisp.dhis.system.util.DateUtils;
+
+import com.opensymphony.xwork2.Action;
+
+public class StartExportAction
+    implements Action
+{
+    // -------------------------------------------------------------------------
+    // Dependencies
+    // -------------------------------------------------------------------------
+
+    private Scheduler scheduler;
+    
+    public void setScheduler( Scheduler scheduler )
+    {
+        this.scheduler = scheduler;
+    }
+
+    private DataMartTask dataMartTask;
+
+    public void setDataMartTask( DataMartTask dataMartTask )
+    {
+        this.dataMartTask = dataMartTask;
+    }
+    
+    private PeriodService periodService;
+
+    public void setPeriodService( PeriodService periodService )
+    {
+        this.periodService = periodService;
+    }
+
+    // -------------------------------------------------------------------------
+    // Input
+    // -------------------------------------------------------------------------
+
+    private String startDate;
+    
+    public void setStartDate( String startDate )
+    {
+        this.startDate = startDate;
+    }
+
+    private String endDate;
+
+    public void setEndDate( String endDate )
+    {
+        this.endDate = endDate;
+    }
+
+    // -------------------------------------------------------------------------
+    // Action implementation
+    // -------------------------------------------------------------------------
+
+    @Override
+    public String execute()
+        throws Exception
+    {
+        Date start = DateUtils.getMediumDate( startDate );
+        Date end = DateUtils.getMediumDate( endDate );
+        
+        List<Period> periods = new ArrayList<Period>( periodService.getPeriodsBetweenDates( start, end ) );
+        
+        dataMartTask.setPeriods( periods );
+        
+        scheduler.executeTask( dataMartTask );
+        
+        return SUCCESS;
+    }
+}

=== modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/resources/META-INF/dhis/beans.xml'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/resources/META-INF/dhis/beans.xml	2012-02-12 12:21:49 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/resources/META-INF/dhis/beans.xml	2012-02-12 14:40:54 +0000
@@ -242,6 +242,15 @@
     <property name="organisationUnitGroupService" ref="org.hisp.dhis.organisationunit.OrganisationUnitGroupService" />
   </bean>
   
+  <!-- Data mart -->
+  
+  <bean id="org.hisp.dhis.reporting.datamart.action.StartExportAction" class="org.hisp.dhis.reporting.datamart.action.StartExportAction"
+	scope="prototype">
+	<property name="scheduler" ref="scheduler"/>
+	<property name="dataMartTask" ref="dataMartLast12MonthsTask"/>
+	<property name="periodService" ref="org.hisp.dhis.period.PeriodService"/>
+  </bean>
+  
   <!-- Export -->
 
   <bean id="org.hisp.dhis.reporting.exp.ExportDataMartAction" class="org.hisp.dhis.reporting.exp.ExportDataMartAction"

=== modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/resources/org/hisp/dhis/reporting/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/resources/org/hisp/dhis/reporting/i18n_module.properties	2012-02-05 13:08:51 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/resources/org/hisp/dhis/reporting/i18n_module.properties	2012-02-12 14:40:54 +0000
@@ -40,7 +40,6 @@
 add_children= Add children
 create_and_save= Create and Save
 create= Create
-skip_data_mart= Skip data mart
 indicators= Indicators
 organisation_units= Organisation units
 periods= Periods
@@ -401,4 +400,9 @@
 last_six_month=Last six-month
 last_2_sixmonths=Last 2 six-months
 available_organisation_unit_groups=Available organisation unit groups
-selected_organisation_unit_groups=Selected organisation unit groups
\ No newline at end of file
+selected_organisation_unit_groups=Selected organisation unit groups
+data_mart = Data Mart
+data_mart_management = Data mart management
+start_date = Start date
+end_date = End date
+start_export = Start export
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/resources/struts.xml'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/resources/struts.xml	2012-02-12 12:21:49 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/resources/struts.xml	2012-02-12 14:40:54 +0000
@@ -271,6 +271,20 @@
       <result name="success" type="chart"></result>
     </action>
 	
+	<!-- Data mart -->
+	
+	<action name="displayDataMartForm" class="org.hisp.dhis.reporting.action.NoAction">
+	  <result name="success" type="velocity">/main.vm</result>
+      <param name="page">/dhis-web-reporting/viewDataMartForm.vm</param>
+      <param name="menu">/dhis-web-reporting/menu.vm</param>
+      <param name="javascripts">javascript/dataMart.js</param>
+	</action>
+	
+	<action name="startExport" class="org.hisp.dhis.reporting.datamart.action.StartExportAction">
+	  <result name="success" type="velocity-json">/dhis-web-commons/ajax/jsonResponseSuccess.vm</result>
+      <param name="onExceptionReturn">plainTextError</param>
+	</action>
+	
 	<!-- Datamart CSV Export -->
 
     <action name="weeklyDataValues" class="org.hisp.dhis.reporting.exp.ExportDataMartAction">

=== added file 'dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/javascript/dataMart.js'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/javascript/dataMart.js	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/javascript/dataMart.js	2012-02-12 17:11:20 +0000
@@ -0,0 +1,20 @@
+
+$( document ).ready( function() {
+	datePickerInRange( 'startDate' , 'endDate' );
+} );
+
+function startExport()
+{
+	var url = 'startExport.action';
+	var startDate = $( '#startDate' ).val();
+	var endDate = $( '#endDate' ).val();
+	
+	$.get( url, { startDate:startDate, endDate:endDate }, pingNotifications );
+}
+
+function pingNotifications()
+{
+	$( '#notificationDiv' ).load( '../dhis-web-commons-ajax/getNotifications.action?category=DATAMART' );
+	
+	setTimeout( "pingNotifications()", 2000 );
+}
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/menu.vm'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/menu.vm	2012-02-05 13:28:15 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/menu.vm	2012-02-12 14:40:54 +0000
@@ -9,3 +9,8 @@
 	<li><a href="displayManageTableForm.action">$i18n.getString( "report_table" )&nbsp;</a></li>
 	<li><a href="displayPivotTableForm.action">$i18n.getString( "pivot_table" )&nbsp;</a></li>
 </ul>
+
+<h2>$i18n.getString( "data_mart" )&nbsp;</h2>
+<ul>
+	<li><a href="displayDataMartForm.action">$i18n.getString( "data_mart" )&nbsp;</a></li>
+</ul>
\ No newline at end of file

=== added file 'dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/viewDataMartForm.vm'
--- dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/viewDataMartForm.vm	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-reporting/src/main/webapp/dhis-web-reporting/viewDataMartForm.vm	2012-02-12 17:11:20 +0000
@@ -0,0 +1,23 @@
+
+<h3>$i18n.getString( "data_mart_management" )</h3>
+
+<div id="critiera" class="inputCriteria" style="width:380px;height:110px;">
+<table>
+<col width="120">
+<col width="240">
+<tr>
+	<td>$i18n.getString( "start_date" )</td>
+	<td><input type="text" id="startDate" style="width:200px"></td>
+</tr>
+<tr>
+	<td>$i18n.getString( "end_date" )</td>
+	<td><input type="text" id="endDate" style="width:200px"></td>
+</tr>
+<tr>
+	<td></td>
+	<td><input type="button" onclick="startExport()" value="$i18n.getString( 'start_export' )" style="width:120px"></td>
+</tr>
+</table>
+</div>
+
+<div id="notificationDiv"></div>
\ No newline at end of file