Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattpiwik <matthieu.aubry@gmail.com>2008-08-14 22:31:01 +0400
committermattpiwik <matthieu.aubry@gmail.com>2008-08-14 22:31:01 +0400
commit41672b6a4672f3255589eca229663d193ca3ce3c (patch)
tree3511a17ad2bbd3de9537c3c2cbf53623bfe84c68
parent311c08111198a5a4e85be571fe2c8578dd5d74b5 (diff)
- OMG i totally messed up with SVN: NEVER rename a directory using your OS rename, but use SVN rename, I nearly lost a couple of hours of work
git-svn-id: http://dev.piwik.org/svn/trunk@600 59fd770c-687e-43c8-a1e3-f5a4ff64c105
-rw-r--r--plugins/Dashboard/templates/AddWidget.js245
-rw-r--r--plugins/Dashboard/templates/Dashboard.js361
-rw-r--r--plugins/Dashboard/templates/dashboard.css193
-rw-r--r--plugins/Dashboard/templates/header.tpl25
-rw-r--r--plugins/Dashboard/templates/index.tpl79
5 files changed, 903 insertions, 0 deletions
diff --git a/plugins/Dashboard/templates/AddWidget.js b/plugins/Dashboard/templates/AddWidget.js
new file mode 100644
index 0000000000..45ac05e082
--- /dev/null
+++ b/plugins/Dashboard/templates/AddWidget.js
@@ -0,0 +1,245 @@
+//widgetMenu constructor
+function widgetMenu(dash)
+{
+ this.menu = new Object;
+ this.dashboard = dash;
+}
+
+//Prototype of the widgetMenu object
+widgetMenu.prototype =
+{
+ //function called when the menu is built for the first time
+ init: function(onWidgetLoadCallback)
+ {
+ this.onWidgetLoad = onWidgetLoadCallback;
+ var self = this;
+ self.buildMenu();
+ },
+
+ //function called when a clone of an existing menu is built
+ initBuilt: function(menuDom, onWidgetLoadCallback)
+ {
+ var self = this;
+ self.onWidgetLoad = onWidgetLoadCallback;
+ self.menu = menuDom;
+ self.bindEvents();
+ },
+
+ //create DOM elements of the menu
+ buildMenu: function()
+ {
+ var self = this;
+
+ //load menu widgets list
+ self.menu = $('#widgetChooser');
+ var subMenu1 = $('.subMenu#sub1', self.menu);
+ var subMenu2 = $('.subMenu#sub2', self.menu);
+
+ subMenu1.append('<ol id="menuList"></ol>');
+ subMenu2.append('<ul id="widgetList"></ul>');
+ var lineHeight = $('ol', subMenu1).css('line-height');
+ lineHeight = Number(lineHeight.substring(0, lineHeight.length-2));
+
+ var count=0;
+ for(var plugin in piwik.availableWidgets)
+ {
+ var widgets = piwik.availableWidgets[plugin];
+
+ for(var i in widgets)
+ {
+ var exist = $('.subMenuItem#'+plugin, subMenu1);
+ if(exist.size()==0)
+ {
+ $('ol', subMenu1).append('<li class="subMenuItem" id="'+plugin+'"><span>'+plugin+'</span></li>');
+ $('ul', subMenu2).append('<li class="subMenuItem" id="'+plugin+'"></li>');
+ }
+
+ var sm2Div = $('.subMenuItem#'+plugin, subMenu2);
+ sm2Div.append('<div class="button menuItem" pluginToLoad="'+plugin+'" actionToLoad="'+widgets[i][1]+'">'+widgets[i][0] + '</div>');
+ sm2Div.css('padding-top', count*lineHeight+'px');
+ }
+ count++;
+ }
+
+ $('.subMenuItem', subMenu2).hide();
+ },
+
+ //bind events (click/hover/...) of the menu to appropriate callback
+ bindEvents: function()
+ {
+ var self = this;
+
+ //menu buttons
+ $('.button#hideMenu', self.menu).click(function(){self.hide();});
+ $('#closeMenuIcon', self.menu).click(function(){self.hide();});
+ $('.subMenu#sub3 .widget .handle', self.menu).css('cursor', 'pointer')
+ .click(function(){self.movePreviewToDashboard();});
+
+ //update widget list on submenu#1 mouse over
+ $('.subMenu#sub1 .subMenuItem', self.menu).each(function(){
+ var plugin = $(this).attr('id');
+ var item = $('.subMenu#sub2 .subMenuItem#'+plugin, self.menu);
+
+ $(this).hover(
+ function()
+ {
+ $('#embedThisWidget').empty();
+ $('.widgetDiv.previewDiv', self.menu).empty()
+ .attr('plugin', '')
+ .attr('id', '');
+ $('.menuItem', self.menu).removeClass('menuSelected');
+ $('.subMenu#sub1 .subMenuItem', self.menu).removeClass('menuSelected');
+ $('.subMenu#sub2 .subMenuItem', self.menu).hide();
+ $(this).addClass('menuSelected');
+ item.show();
+ },function(){});
+ });
+
+ //update widget preview on submenu#2 mouse over
+ $('.menuItem', self.menu).hover(
+ function()
+ {
+ if(!$(this).hasClass('menuDisabled'))
+ {
+ var plugin = $(this).attr('pluginToLoad');
+ var action = $(this).attr('actionToLoad');
+
+ $('.menuSelected', self.menu).removeClass('menuSelected');
+ $(this).addClass('menuSelected');
+
+ $('.widgetDiv.previewDiv', self.menu).each(function(){
+ //only reload preview if necessary
+ if($(this).attr('plugin')!=plugin || $(this).attr('id')!=action)
+ {
+ //format the div for upcomming ajax loading and set a temporary content
+ $(this) .attr('plugin', plugin)
+ .attr('id', action)
+ .html('<div id="loadingPiwik"><img src="themes/default/images/loading-blue.gif" /> '+ _pk_translate('Dashboard_LoadingPreview') +'</div>').show();
+ $('#embedThisWidget').empty();
+ loadWidgetInDiv(plugin, action, self.onWidgetLoad);
+ }
+ });
+ }
+ },function(){})
+ .click(function(){ self.movePreviewToDashboard(); });
+ },
+
+ //hide the menu
+ hide: function()
+ {
+ //simply disable modal dialog box
+ $.unblockUI();
+ },
+
+ //show the menu
+ show: function()
+ {
+ var self = this;
+ if(self.dashboard != undefined)
+ {
+ self.filterOutAlreadyLoadedWidget();
+ var dispMenu = $('#widgetChooser').clone(true);
+ $.blockUI(dispMenu, {width:'', top: '5%',left:'10%', right:'10%', margin:"0px", textAlign:'', cursor:'', border:'0px'});
+ menuDom = $('.blockMsg #widgetChooser');
+ }
+ else
+ {
+ menuDom = $('#widgetChooser');
+ }
+ var dispMenuObject = new widgetMenu(self.dashboard);
+ dispMenuObject.initBuilt(menuDom, self.onWidgetLoad);
+ },
+
+ //disable widgets that are already in the dashboard
+ filterOutAlreadyLoadedWidget: function()
+ {
+ var self = this;
+
+ //build a list of loaded widget, parse the dashboard column
+ var widgets = new Array;
+ self.dashboard.getColumns().each(
+ function()
+ {
+ widgets = widgets.concat(getWidgetInDom(this));
+ }
+ );
+
+ //find widget from the loaded list in the menu, and apply
+ //appropriate style and behaviour
+ $('.menuItem', self.menu).each(function(){
+ var plugin = $(this).attr('pluginToLoad');
+ var action = $(this).attr('actionToLoad');
+ if(contains(widgets, plugin+'.'+action))
+ {
+ $(this).addClass('menuDisabled');
+ $(this).attr('title', _pk_translate('Dashboard_TitleWidgetInDashboard'));
+ }
+ else
+ {
+ $(this).removeClass('menuDisabled');
+ $(this).attr('title', _pk_translate('Dashboard_TitleClickToAdd'));
+ }
+ });
+ },
+
+ //move the widget in the preview box to the dashboard, without reloading it
+ movePreviewToDashboard: function()
+ {
+ var self = this;
+
+ $('.widgetDiv.previewDiv', self.menu).each(function(){
+ var plugin = $(this).attr('plugin');
+ var action = $(this).attr('id');
+
+ self.dashboard.addEmptyWidget(1, plugin, action, true);
+
+ var parDiv = $('.widgetDiv[plugin='+plugin+']'+'#'+action, self.dashboard.getColumns()[0]);
+ parDiv.show();
+ parDiv.siblings('.widgetLoading').hide();
+
+ $(this).children().clone(true).appendTo(parDiv);
+ });
+
+ self.hide();
+ self.clearPreviewDiv();
+ self.dashboard.saveLayout();
+ },
+
+ //clear the widget preview box
+ clearPreviewDiv: function()
+ {
+ var self = this;
+ $('.subMenu .widgetDiv.previewDiv', self.menu).empty()
+ .attr('id', '')
+ .attr('plugin', '');
+ $('#embedThisWidget').empty();
+ }
+};
+
+function loadWidgetInDiv(pluginId, actionId, onWidgetLoad)
+{
+ // When ajax replied, we replace the right div with the response
+ function onLoaded(response)
+ {
+ var parDiv = $('.widgetDiv#'+actionId+'[plugin='+pluginId+']');
+ parDiv.siblings('.widgetLoading').hide();
+ parDiv.html($(response));
+ parDiv.show();
+
+ if(typeof onWidgetLoad != 'undefined')
+ {
+ onWidgetLoad(parDiv, pluginId, actionId);
+ }
+ }
+ var ajaxRequest =
+ {
+ type: 'GET',
+ url: 'index.php',
+ dataType: 'html',
+ async: true,
+ error: ajaxHandleError, // on request fails
+ success: onLoaded, // on request succeeds
+ data: "module="+pluginId+"&action="+actionId+"&idSite="+piwik.idSite+"&period="+piwik.period+"&date="+piwik.currentDateStr
+ };
+ $.ajax(ajaxRequest);
+} \ No newline at end of file
diff --git a/plugins/Dashboard/templates/Dashboard.js b/plugins/Dashboard/templates/Dashboard.js
new file mode 100644
index 0000000000..264b0fa248
--- /dev/null
+++ b/plugins/Dashboard/templates/Dashboard.js
@@ -0,0 +1,361 @@
+//there is a problem with loop for-in when we extends javascript Array
+//so I prefer using a separate function to do this
+function contains(array, searchElem) {
+ for(var i=0; i<array.length; i++) {
+ if (array[i]==searchElem) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//Default configuration of the blockUI jquery plugin
+function blockUIConfig()
+{
+ //set default style value for blockUI
+ $.extend($.blockUI.defaults.overlayCSS, { backgroundColor: '#000000', opacity: '0.4'});
+ //disable animation effect
+ $.extend($.blockUI.defaults,{ fadeIn: 0, fadeOut: 0 });
+
+ //unblock UI on 'escape' key pressed...
+ $(window).keydown(
+ function(e)
+ {
+ var key = e.keyCode || e.which;
+ if(key == 27) //escape key ascii code
+ $.unblockUI();
+ }
+ );
+}
+
+
+//dashboard constructor
+function dashboard()
+{
+ this.test = new Object;
+ this.dashArea = new Object;
+ this.dashColumns = new Object;
+ this.layout = '';
+}
+
+//Prototype of the dashboard object
+dashboard.prototype =
+{
+ //function called on dashboard initialisation
+ init: function(layout)
+ {
+ var self = this;
+
+ //save some often used DOM objects
+ self.dashArea = $('#dashboardWidgetsArea');
+ self.dashColumns = $('.col', self.dashDom);
+
+ //dashboard layout
+ self.layout = layout;
+
+ //generate dashboard layout and load every displayed widgets
+ self.generateLayout();
+
+ //setup widget dynamic behaviour
+ self.setupWidgetSortable();
+ },
+
+ //return the DOM corresponding to the dashboard columns
+ getColumns: function()
+ {
+ return this.dashColumns;
+ },
+
+ //'widgetize' every created widgets:
+ //add an handle bar and apply 'sortable' drag&drop effect
+ setupWidgetSortable: function()
+ {
+ var self = this;
+
+ //add a dummy item on each columns
+ self.dashColumns.each(
+ function()
+ {
+ $(this).append('<div class="items dummyItem"><div class="handle dummyHandle"></div></div>');
+ });
+
+ self.hideUnnecessaryDummies();
+
+ self.makeSortable();
+ },
+
+ //generate dashboard DOM corresponding to the initial layout
+ generateLayout: function()
+ {
+ var self = this;
+
+ //dashboardLayout looks like :
+ //'Actions.getActions~Actions.getDownloads|UserCountry.getCountry|Referers.getSearchEngines';
+ //'|' separate columns
+ //'~' separate widgets
+ //'.' separate plugin name from action name
+ var col = self.layout.split('|');
+ for(var i=0; i<col.length; i++)
+ {
+ if(col[i] != '')
+ {
+ var widgets = col[i].split('~');
+ for(var j=0; j<widgets.length; j++)
+ {
+ var wid = widgets[j].split('.');
+ self.addWidgetAndLoad(i+1, wid[0], wid[1]);
+ }
+ }
+ }
+ },
+
+ //add a new widget to the dashboard
+ //colnumber is the column in wich you want to add the widget
+ //plugin/action is the widget to load
+ //onTop: boolean specifying if the widget should be added on top of the column
+ addEmptyWidget: function(colNumber, plugin, action, onTop)
+ {
+ var self = this;
+
+ if(typeof onTop == "undefined")
+ onTop = false;
+
+ var item = '<div class="items"><div class="widget"><div class="widgetLoading">'+ _pk_translate('Dashboard_LoadingWidget') +'</div><div plugin="'+plugin+'"'+' id="'+action+'" class="widgetDiv"></div></div></div>';
+
+ if(onTop)
+ {
+ $(self.dashColumns[colNumber-1]).prepend(item);
+ }
+ else
+ {
+ $(self.dashColumns[colNumber-1]).append(item);
+ }
+
+ //find the title of the widget
+ var title = self.getWidgetTitle(plugin, action);
+
+ //add an handle to each items
+ var widget = $('.widgetDiv#'+action+'[plugin='+plugin+']', self.dashColumns[colNumber-1]).parents('.widget');
+ self.addHandleToWidget(widget, title);
+
+ var button = $('.button#close', widget);
+
+ //Only show handle buttons on mouse hover
+ $(widget).hover(
+ function()
+ {
+ $(this).addClass('widgetHover');
+ $('.handle',this).addClass('handleHover');
+ button.show();
+ },
+ function()
+ {
+ $(this).removeClass('widgetHover');
+ $('.handle',this).removeClass('handleHover');
+ button.hide();
+ }
+ );
+
+ //Bind click event on close button
+ button.click(function(ev){self.onDeleteItem(this, ev);});
+
+ self.makeSortable();
+ },
+
+ //return widget title designated by its plugin/action couple
+ getWidgetTitle: function(plugin, action)
+ {
+ var self = this;
+
+ var title = _pk_translate('Dashboard_WidgetNotFound');
+ var widgets = piwik.availableWidgets[plugin];
+ for(var i in widgets)
+ {
+ if(action == widgets[i][1])
+ title = widgets[i][0];
+ }
+ return title;
+ },
+
+ //add the widget and load it
+ addWidgetAndLoad: function(colNumber, plugin, action, onTop)
+ {
+ var self = this;
+
+ self.addEmptyWidget(colNumber, plugin, action, onTop);
+ self.loadItem($('.items [plugin='+plugin+']#'+action, self.dashArea).parents('.items'));
+ },
+
+ //add an handle bar to a given widget with a particular title
+ addHandleToWidget: function(widget, title)
+ {
+ widget.prepend('<div class="handle">\
+ <div class="button" id="close">\
+ <img src="themes/default/images/close.png" />\
+ </div>\
+ <div class="widgetTitle">'+title+'</div>\
+ </div>');
+ },
+
+ //auxiliary function calling ajax loading procedure for a given DOM element
+ loadItem: function(domElem)
+ {
+ var self = this;
+
+ //load every widgetDiv with asynchronous ajax
+ $('.widgetDiv', domElem).each(
+ function()
+ {
+ // get the ID of the div and load with ajax
+ loadWidgetInDiv($(this).attr('plugin'), $(this).attr('id'));
+ });
+ },
+
+ //apply jquery sortable plugin to the dashboard layout
+ makeSortable: function()
+ {
+ var self = this;
+
+ function getHelper()
+ {
+ return $(this).clone().addClass('helper');
+ }
+
+ function onStart()
+ {
+ self.showDummies();
+ }
+
+ function onStop()
+ {
+ self.hideUnnecessaryDummies();
+ self.saveLayout();
+
+ $('.widgetHover', this).removeClass('widgetHover');
+ $('.handleHover', this).removeClass('handleHover');
+ $('.button#close', this).hide();
+ }
+
+ //launch 'sortable' property on every dashboard widgets
+ self.dashArea.sortableDestroy()
+ .sortable({
+ items:'.items',
+ hoverClass: 'hover',
+ handle: '.handle',
+ helper: getHelper,
+ start: onStart,
+ stop: onStop
+ });
+ },
+
+ //on mouse click on close widget button
+ //we ask for confirmation and we delete the widget from the dashboard
+ onDeleteItem: function(target, ev)
+ {
+ var self = this;
+
+ //ask confirmation and delete item
+ var question = $('.dialog#confirm').clone();
+ $('#yes', question).click(function()
+ {
+ var item = $(target).parents('.items');
+ var plugin = $('.widgetDiv', item).attr('plugin');
+ var action = $('.widgetDiv', item).attr('id');
+
+ //hide confirmation dialog
+ $.unblockUI();
+
+ //the item disapear slowly and is removed from the DOM
+ item.fadeOut(200, function()
+ {
+ $(this).remove();
+ self.showDummies();
+ self.saveLayout();
+ self.makeSortable();
+ });
+
+ //show menu item
+ $('.menu#widgetChooser .menuItem[pluginToLoad='+plugin+'][actionToLoad='+action+']').show();
+ });
+ $('#no', question).click($.unblockUI);
+ $.blockUI(question, { width: '300px', border:'1px solid black' });
+ },
+
+ //dummies are invisible item that help for widget positionning
+ //and keep the column visible even when there aren't widget anymore in it
+ showDummies: function()
+ {
+ var self = this;
+ $('.dummyItem').css('display', 'block');
+ },
+
+ //see showDummies
+ //hide dummies that are not needed for column consistency
+ hideUnnecessaryDummies: function()
+ {
+ var self = this;
+ $('.dummyItem').each(function(){
+ $(this).appendTo($(this).parent());
+ if($(this).siblings().size() > 0)
+ $(this).css('display', 'none');
+ });
+ },
+
+ //save the layout in the database/cookie so the user can
+ //retrieve it the next time he load the dashboard
+ saveLayout: function()
+ {
+ var self = this;
+ var column = new Array;
+
+ //parse the dom to see how our div are organized
+ //build a list of widget sorted by columns
+ self.dashColumns.each(function() {
+ column.push(getWidgetInDom(this));
+ });
+
+ var ajaxRequest =
+ {
+ type: 'GET',
+ url: 'index.php',
+ dataType: 'html',
+ async: true,
+ error: ajaxHandleError, // Callback when the request fails
+ data: { module: 'Dashboard',
+ action: 'saveLayout' }
+ };
+
+ //write layout in a string
+ //using '|' as column separator
+ // and '~' as widget separator
+ var layout = '';
+ for(var i=0; i<column.length; i++)
+ {
+ layout += column[i].join('~');
+ layout += '|';
+ }
+
+ //only save layout if it has changed
+ if(layout != self.layout)
+ {
+ self.layout = layout;
+ ajaxRequest.data['layout'] = layout;
+ $.ajax(ajaxRequest);
+ }
+ },
+
+ //load widget with an ajax request
+
+};
+
+//auxiliary function: list widgets available in a DOM tree
+function getWidgetInDom(domElem)
+{
+ var items = $('.items:not(.dummyItem) .widgetDiv', domElem);
+ var widgets = new Array;
+ for(var i=0; i<items.size(); i++)
+ {
+ widgets.push($(items[i]).attr('plugin')+'.'+$(items[i]).attr('id'));
+ }
+ return widgets;
+}
diff --git a/plugins/Dashboard/templates/dashboard.css b/plugins/Dashboard/templates/dashboard.css
new file mode 100644
index 0000000000..d23c3c657c
--- /dev/null
+++ b/plugins/Dashboard/templates/dashboard.css
@@ -0,0 +1,193 @@
+/*Overriding some dataTable css for better dashboard display*/
+.widgetDiv .parentDiv,.widgetDiv .parentDivGraph,.widgetDiv .parentDivActions,.widgetDiv .parentDivGraphEvolution {
+ width: 100%;
+}
+
+/*--- end of dataTable.css modif*/
+.col {
+ float: left;
+ width: 33%;
+}
+
+.items {
+ background: white;
+}
+
+.hover {
+ border: 2px dashed #E3E3E3;
+}
+
+.widget {
+ border: 1px solid #D2D9EB;
+ margin-top: 10px;
+ margin-bottom: 10px;
+ margin-right: 5px;
+ margin-left: 5px;
+ overflow: hidden;
+}
+
+.widgetHover {
+ border: 1px solid #CBD3E7;
+}
+
+.handle {
+ background: #F0F0FA;
+ border-bottom: 1px solid #D2D9EB;
+ width: 100%;
+ cursor: move;
+ font-size: 10pt;
+ font-weight: bold;
+ padding-bottom: 4px;
+}
+
+.handleHover {
+ background: #E6E6F5;
+}
+
+.widgetTitle {
+ font-size: 14pt;
+ margin-left: 25px;
+}
+
+.widgetDiv {
+ display: none;
+ z-index:1;
+}
+
+.dummyItem {
+ width: 100%;
+ height: 200px;
+ display: block;
+}
+
+.button {
+ cursor: pointer;
+}
+
+#close.button {
+ float: right;
+ display: none;
+ margin: 3px;
+}
+
+.dialog {
+ display: none;
+ padding: 20px 10px;
+ color: #7A0101;
+ cursor: wait;
+ font-size: 1.2em;
+ font-weight: bold;
+ text-align: center;
+}
+
+.helper {
+ width: 33%;
+ opacity: .6;
+ filter: alpha(opacity = 60); /*for IE*/
+}
+
+.dummyHandle {
+ display: none;
+}
+
+.menu {
+ display: none;
+ border: 2px solid #FCB842;
+ background: white;
+}
+
+.menuItem {
+}
+
+.menuSelected {
+ border-bottom: 2px dotted #CCCCCC;
+ margin-bottom: -2px;
+}
+
+.menuDisabled {
+ color: lightgrey;
+ cursor: default;
+}
+
+.widgetLoading {
+ cursor: wait;
+ padding: 10px;
+ text-align: center;
+ font-size: 10pt;
+}
+
+#menuTitleBar {
+ background: #FFC35C;
+ font-size: 14pt;
+ font-weight: bold;
+ padding: 2px 20px 6px 20px;
+ border-bottom: 2px solid #FCB842;
+}
+
+#closeMenuIcon {
+ float: right;
+ margin: 3px;
+}
+
+.subMenu {
+ float: left;
+ margin: 30px;
+}
+
+#sub1.subMenu {
+ cursor: default;
+ margin-left: 50px;
+}
+
+#sub2.subMenu {
+ cursor: pointer;
+}
+
+#sub3.subMenu {
+ float: right;
+ width: 40%
+}
+
+ol#menuList {
+ color: #CCCCCC;
+ list-style-type: lower-roman;
+ line-height: 25px;
+}
+
+ul#widgetList {
+ list-style-type: none;
+ line-height: 25px;
+}
+
+.subMenuItem span {
+ color: black;
+}
+
+.menuClear {
+ clear: both;
+ height: 30px;
+}
+
+#closeMenuIcon {
+ cursor: pointer;
+}
+
+#addWidget {
+ font-weight: bold;
+}
+
+.previewDiv {
+ height: auto;
+}
+
+.widget input {
+ background: #F7F7FF none repeat scroll 0% 50%;
+ border: 1px solid #B3B3B3;
+ color: #0C183A;
+ font-size: 0.7em;
+ padding: 2px;
+}
+
+#widgetChooser {
+ z-index:100;
+} \ No newline at end of file
diff --git a/plugins/Dashboard/templates/header.tpl b/plugins/Dashboard/templates/header.tpl
new file mode 100644
index 0000000000..2a66fc436e
--- /dev/null
+++ b/plugins/Dashboard/templates/header.tpl
@@ -0,0 +1,25 @@
+{* This header is for loading the dashboard in stand alone mode*}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
+<html>
+<body>
+{loadJavascriptTranslations plugins='CoreHome Dashboard'}
+
+<script type="text/javascript" src="libs/jquery/jquery.js"></script>
+
+<script type="text/javascript" src="themes/default/common.js"></script>
+<script type="text/javascript" src="libs/jquery/jquery.dimensions.js"></script>
+<script type="text/javascript" src="libs/jquery/tooltip/jquery.tooltip.js"></script>
+<script type="text/javascript" src="libs/jquery/truncate/jquery.truncate.js"></script>
+<script type="text/javascript" src="libs/jquery/jquery.scrollTo.js"></script>
+<script type="text/javascript" src="libs/jquery/jquery-calendar.js"></script>
+<script type="text/javascript" src="libs/swfobject/swfobject.js"></script>
+
+<script type="text/javascript" src="plugins/CoreHome/templates/datatable.js"></script>
+<script type="text/javascript" src="plugins/CoreHome/templates/date.js"></script>
+
+<script type="text/javascript" src="libs/jquery/jquery.blockUI.js"></script>
+<script type="text/javascript" src="libs/jquery/ui.mouse.js"></script>
+<script type="text/javascript" src="libs/jquery/ui.sortable_modif.js"></script>
+
+<link rel="stylesheet" href="plugins/CoreHome/templates/datatable.css">
+<link rel="stylesheet" href="plugins/Dashboard/templates/dashboard.css">
diff --git a/plugins/Dashboard/templates/index.tpl b/plugins/Dashboard/templates/index.tpl
new file mode 100644
index 0000000000..05fb8955f0
--- /dev/null
+++ b/plugins/Dashboard/templates/index.tpl
@@ -0,0 +1,79 @@
+{loadJavascriptTranslations plugins='CoreHome Dashboard'}
+
+<script type="text/javascript">
+ {* define some global constants for the following javascript includes *}
+ var piwik = new Object;
+
+ {if !empty($layout) }
+ piwik.dashboardLayout = '{$layout}';
+ {else}
+ // Load default layout...
+ piwik.dashboardLayout = 'VisitsSummary.getLastVisitsGraph~VisitorInterest.getNumberOfVisitsPerVisitDuration~UserSettings.getBrowser~ExampleFeedburner.feedburner|Referers.getKeywords~Referers.getWebsites|Referers.getSearchEngines~VisitTime.getVisitInformationPerServerTime~ExampleRssWidget.rssPiwik|';
+ {/if}
+
+ piwik.availableWidgets = {$availableWidgets};
+ piwik.idSite = "{$idSite}";
+ piwik.period = "{$period}";
+ piwik.currentDateStr = "{$date}";
+</script>
+
+{literal}
+<script type="text/javascript">
+$(document).ready( function() {
+ var dash = new dashboard();
+ var menu = new widgetMenu(dash);
+ blockUIConfig();
+ dash.init(piwik.dashboardLayout);
+ menu.init();
+ $('.button#addWidget').click(function(){menu.show();});
+});
+</script>
+{/literal}
+<div id="dashboard">
+
+ <div class="dialog" id="confirm">
+ <img src="themes/default/images/delete.png" style="padding: 10px; position: relative; margin-top: 10%; float: left;"/>
+ <p>{'Dashboard_DeleteWidgetConfirm'|translate}</p>
+ <input id="yes" type="button" value="{'General_Yes'|translate}"/>
+ <input id="no" type="button" value="{'General_No'|translate}"/>
+ </div>
+
+ <div class="button" id="addWidget">
+ {'Dashboard_AddWidget'|translate}
+ </div>
+
+ <div class="menu" id="widgetChooser">
+ <div id="closeMenuIcon"><img src="themes/default/images/close_medium.png" title="{'General_Close'|translate}"/></div>
+ <div id="menuTitleBar">{'Dashboard_SelectWidget'|translate}</div>
+ <div class="subMenu" id="sub1">
+ </div>
+
+ <div class="subMenu" id="sub2">
+ </div>
+
+ <div class="subMenu" id="sub3">
+ <div class="widget">
+ <div class="handle" title="{'Dashboard_AddPreviewedWidget'|translate}">
+ <div class="button" id="close">
+ <img src="themes/default/images/close.png" title="{'General_Close'|translate}"/>
+ </div>
+ <div class="widgetTitle">{'Dashboard_WidgetPreview'|translate}</div>
+ </div>
+ <div class="widgetDiv previewDiv" ></div>
+ </div>
+ </div>
+
+ <div class="menuClear"> </div>
+ </div>
+
+ <div id="dashboardWidgetsArea">
+ <div class="col" id="1">
+ </div>
+
+ <div class="col" id="2">
+ </div>
+
+ <div class="col" id="3">
+ </div>
+ </div>
+</div>