添加 Piwik 到代码库中。

+YUCHENG HU+

git-svn-id: https://svn.code.sf.net/p/hawebs/svn@484 a2543c7e-f6e9-4f8a-8bff-1ffc34733512
This commit is contained in:
YuCheng Hu
2010-07-10 04:53:17 +00:00
parent b282d1a279
commit 49c48e9cec
66 changed files with 5166 additions and 0 deletions
@@ -0,0 +1,92 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Controller.php 2067 2010-04-09 09:18:01Z matt $
*
* @category Piwik_Plugins
* @package Piwik_CoreHome
*/
/**
*
* @package Piwik_CoreHome
*/
class Piwik_CoreHome_Controller extends Piwik_Controller
{
function getDefaultAction()
{
return 'redirectToCoreHomeIndex';
}
function redirectToCoreHomeIndex()
{
$defaultReport = Piwik_UsersManager_API::getInstance()->getUserPreference(Piwik::getCurrentUserLogin(), Piwik_UsersManager_API::PREFERENCE_DEFAULT_REPORT);
$module = 'CoreHome';
$action = 'index';
// User preference: default report to load is the All Websites dashboard
if($defaultReport == 'MultiSites'
&& Piwik_PluginsManager::getInstance()->isPluginActivated('MultiSites'))
{
$module = 'MultiSites';
}
if($defaultReport == Piwik::getLoginPluginName())
{
$module = Piwik::getLoginPluginName();
}
parent::redirectToIndex($module, $action);
}
public function showInContext()
{
$controllerName = Piwik_Common::getRequestVar('moduleToLoad');
$actionName = Piwik_Common::getRequestVar('actionToLoad', 'index');
$view = $this->getDefaultIndexView();
$view->content = Piwik_FrontController::getInstance()->fetchDispatch( $controllerName, $actionName );
echo $view->render();
}
protected function getDefaultIndexView()
{
$view = Piwik_View::factory('index');
$this->setGeneralVariablesView($view);
$view->menu = Piwik_GetMenu();
$view->content = '';
return $view;
}
protected function setDateTodayIfWebsiteCreatedToday()
{
$date = Piwik_Common::getRequestVar('date', false);
if($date == 'today')
{
return;
}
$websiteId = Piwik_Common::getRequestVar('idSite', false);
if ($websiteId) {
$website = new Piwik_Site($websiteId);
$datetimeCreationDate = $this->site->getCreationDate()->getDatetime();
$creationDateLocalTimezone = Piwik_Date::factory($datetimeCreationDate, $website->getTimezone())->toString('Y-m-d');
$todayLocalTimezone = Piwik_Date::factory('now', $website->getTimezone())->toString('Y-m-d');
if( $creationDateLocalTimezone == $todayLocalTimezone )
{
Piwik::redirectToModule( 'CoreHome', 'index',
array( 'date' => 'today',
'idSite' => $websiteId,
'period' => Piwik_Common::getRequestVar('period'))
);
}
}
}
public function index()
{
$this->setDateTodayIfWebsiteCreatedToday();
$view = $this->getDefaultIndexView();
echo $view->render();
}
}
@@ -0,0 +1,28 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: CoreHome.php 2264 2010-06-03 16:53:43Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_CoreHome
*/
/**
*
* @package Piwik_CoreHome
*/
class Piwik_CoreHome extends Piwik_Plugin
{
public function getInformation()
{
return array(
'description' => Piwik_Translate('CoreHome_PluginDescription'),
'author' => 'Piwik',
'author_homepage' => 'http://piwik.org/',
'version' => Piwik_Version::VERSION,
);
}
}
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<dwsync>
<file name="index.tpl" server="hawebs.net//www/hawebs.net/piwik/" local="129230032218750000" remote="129229996200000000" />
<file name="piwik_tag.tpl" server="hawebs.net//www/hawebs.net/piwik/" local="129230031367031250" remote="129229995000000000" />
</dwsync>
@@ -0,0 +1,319 @@
/* broadcast object is to help maintain a hash for link clicks and ajax calls
* so we can have back button and refresh button working.
*
* Other file that currently depending on this are:
* calendar.js
* period_select.tpl
* sites_selections.tpl
* menu.js, ...etc
*/
// Load this once and only once.
broadcast = {};
broadcast.init = function() {
if(typeof broadcast.isInit != 'undefined') {
return;
}
broadcast.isInit = true;
// Initialize history plugin.
// The callback is called at once by present location.hash
$.historyInit(broadcast.pageload);
piwikHelper.showAjaxLoading();
}
/************************************************
*
* Broadcast Main Methods:
*
************************************************/
/**========== PageLoad function =================
* This function is called when:
* 1. after calling $.historyInit();
* 2. after calling $.historyLoad(); //look at broadcast.changeParameter();
* 3. after pushing "Go Back" button of a browser
*/
broadcast.pageload = function( hash ) {
broadcast.init();
// hash doesn't contain the first # character.
if( hash ) {
// restore ajax loaded state
broadcast.loadAjaxContent(hash);
} else {
// start page
$('#content').empty();
}
};
/* ============================================
* propagateAjax -- update hash values then make ajax calls.
* example :
* 1) <a href="javascript:broadcast.propagateAjax('module=Referers&action=getKeywords')">View keywords report</a>
* 2) Main menu li also goes through this function. check out onClickLi();
*
* Will propagate your new value into the current hash string and make ajax calls.
*
* NOTE: this method will only make ajax call and replacing main content.
*/
broadcast.propagateAjax = function (ajaxUrl)
{
broadcast.init();
// available in global scope
var currentHashStr = window.location.hash;
// Because $.history plugin doesn't care about # or ? sign in front of the query string
// We take it out if it exists
currentHashStr = currentHashStr.replace(/^\?|^#/,'');
ajaxUrl = ajaxUrl.replace(/^\?|&#/,'');
var params_vals = ajaxUrl.split("&");
for( var i=0; i<params_vals.length; i++ )
{
currentHashStr = broadcast.updateParamValue(params_vals[i],currentHashStr);
}
// if the module is not 'Goals', we specifically unset the 'idGoal' parameter
// this is to ensure that the URLs are clean (and that clicks on graphs work as expected - they are broken with the extra parameter)
if(broadcast.getParamValue('action', currentHashStr) != 'goalReport')
{
currentHashStr = broadcast.updateParamValue('idGoal=', currentHashStr);
}
// Let history know about this new Hash and load it.
$.historyLoad(currentHashStr);
};
/*
* propagateNewPage() -- update url value and load new page,
* Example:
* 1) We want to update idSite to both search query and hash then reload the page,
* 2) update period to both search query and hash then reload page.
*
* ** If you'd like to make ajax call with new values then use propagateAjax ** *
*
* Expecting:
* str = "param1=newVal1&param2=newVal2";
*
* Currently being use by:
*
* handlePeriodClick,
* calendar.js,
* sites_seletion.tpl
*
* NOTE: This method will refresh the page with new values.
*/
broadcast.propagateNewPage = function (str)
{
broadcast.init();
var params_vals = str.split("&");
// available in global scope
var currentSearchStr = window.location.search;
var currentHashStr = window.location.hash;
for( var i=0; i<params_vals.length; i++ ) {
// update both the current search query and hash string
currentSearchStr = broadcast.updateParamValue(params_vals[i],currentSearchStr);
if(currentHashStr.length != 0 ) {
currentHashStr = broadcast.updateParamValue(params_vals[i],currentHashStr);
}
}
// Now load the new page.
window.location.href = currentSearchStr + currentHashStr;
};
/*************************************************
*
* Broadcast Supporter Methods:
*
*************************************************/
/*
* updateParamValue(newParamValue,urlStr) -- Helping propagate funtions to update value to url string.
* eg. I want to update date value to search query or hash query
*
* Expecting:
* urlStr : A Hash or search query string. e.g: module=whatever&action=index=date=yesterday
* newParamValue : A param value pair: e.g: date=2009-05-02
*
* Return module=whatever&action=index&date=2009-05-02
*/
broadcast.updateParamValue = function(newParamValue,urlStr)
{
var p_v = newParamValue.split("=");
var paramName = p_v[0];
var valFromUrl = broadcast.getParamValue(paramName,urlStr);
// if set 'idGoal=' then we remove the parameter from the URL automatically (rather than passing an empty value)
var paramValue = p_v[1];
if(paramValue == '')
{
newParamValue = '';
}
if( valFromUrl != '') {
// replacing current param=value to newParamValue;
var regToBeReplace = new RegExp(paramName + '=' + valFromUrl, 'ig');
urlStr = urlStr.replace( regToBeReplace, newParamValue );
} else if(newParamValue != '') {
urlStr += (urlStr == '') ? newParamValue : '&' + newParamValue;
}
return urlStr;
};
/*
* broadcast.loadAjaxContent
*/
broadcast.loadAjaxContent = function(urlAjax)
{
urlAjax = urlAjax.match(/^\?/) ? urlAjax : "?" + urlAjax;
piwikHelper.showAjaxLoading();
$('#content').hide();
$("object").remove();
broadcast.lastUrlRequested = urlAjax;
function sectionLoaded(content)
{
if(content.substring(0, 14) == '<!DOCTYPE html') {
window.location.reload();
return;
}
if(urlAjax == broadcast.lastUrlRequested) {
$('#content').html( content ).show();
piwikHelper.hideAjaxLoading();
broadcast.lastUrlRequested = null;
}
}
piwikMenu.activateMenu(
broadcast.getParamValue('module', urlAjax),
broadcast.getParamValue('action', urlAjax),
broadcast.getParamValue('idGoal', urlAjax)
);
ajaxRequest = {
type: 'GET',
url: urlAjax,
dataType: 'html',
async: true,
error: broadcast.customAjaxHandleError, // Callback when the request fails
success: sectionLoaded, // Callback when the request succeeds
data: new Object
};
$.ajax(ajaxRequest);
return false;
};
broadcast.customAjaxHandleError = function ()
{
broadcast.lastUrlRequested = null;
ajaxHandleError();
};
/*
* Return hash string if hash exists on address bar.
* else return false;
*/
broadcast.isHashExists = function()
{
var hashStr = broadcast.getHashFromUrl();
if ( hashStr != "" ) {
return hashStr;
} else {
return false;
}
},
/*
* Get Hash from given url or from current location.
* return empty string if no hash present.
*/
broadcast.getHashFromUrl = function(url)
{
var hashStr = "";
// If url provided, give back the hash from url, else get hash from current address.
if( url && url.match('#') ) {
hashStr = url.substring(url.indexOf("#"),url.length);
}
else {
hashStr = location.hash;
}
return hashStr;
};
/*
* Get search query from given url or from current location.
* return empty string if no search query present.
*/
broadcast.getSearchFromUrl = function(url)
{
var searchStr = "";
// If url provided, give back the hash from url, else get hash from current address.
if( url && url.match(/\?/) ) {
searchStr = url.substring(url.indexOf("?"),url.length);
} else {
searchStr = location.search;
}
return searchStr;
};
/*
* help to get param value for any given url string with provided param name
* if no url is provided, it will get param from current address.
* return:
* Empty String if param is not found.
*/
broadcast.getValueFromUrl = function (param, url)
{
var searchString = '';
if( url ) {
var urlParts = url.split('#');
searchString = urlParts[0];
} else {
searchString = location.search;
}
return broadcast.getParamValue(param,searchString);
};
/*
* help to get value from hash parameter for any given url string with provided param name
* if no url is provided, it will get param from current address.
* return:
* Empty String if param is not found.
*/
broadcast.getValueFromHash = function(param, url)
{
var hashStr = this.getHashFromUrl(url);
return broadcast.getParamValue(param,hashStr);
};
/*
* return value for the requested param, will return the first match.
* out side of this class should use getValueFromHash() or getValueFromUrl() instead.
* return:
* Empty String if param is not found.
*/
broadcast.getParamValue = function (param, url)
{
var startStr = url.indexOf(param);
if( startStr >= 0 ) {
var endStr = url.indexOf("&", startStr);
if( endStr == -1 ) {
endStr = url.length;
}
return url.substring(startStr + param.length +1,endStr);
} else {
return '';
}
};
@@ -0,0 +1,164 @@
Date.prototype.getWeek = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((((this - onejan) / 86400000) + onejan.getDay())/7);
}
var splitDate = piwik.currentDateString.split("-");
var currentYear = splitDate[0];
var currentMonth = splitDate[1] - 1;
var currentDay = splitDate[2];
var currentDate = new Date(currentYear, currentMonth, currentDay);
var todayDate = new Date;
var todayMonth = todayDate.getMonth();
var todayYear = todayDate.getFullYear();
var todayDay = todayDate.getDate();
function highlightCurrentPeriod( date )
{
var valid = false;
var dateMonth = date.getMonth();
var dateYear = date.getFullYear();
var dateDay = date.getDate();
var style = '';
// we don't color dates in the future
if( dateMonth == todayMonth
&& dateYear == todayYear
&& dateDay >= todayDay
)
{
return [true, ''];
}
// we don't color dates before the minimum date
if( dateYear < piwik.minDateYear
|| ( dateYear == piwik.minDateYear
&&
(
(dateMonth == piwik.minDateMonth - 1
&& dateDay < piwik.minDateDay)
|| (dateMonth < piwik.minDateMonth - 1)
)
)
)
{
return [true, ''];
}
// we color all day of the month for the same year for the month period
if(piwik.period == "month"
&& dateMonth == currentMonth
&& dateYear == currentYear
)
{
valid = true;
}
// we color all day of the year for the year period
else if(piwik.period == "year"
&& dateYear == currentYear
)
{
valid = true;
}
else if(piwik.period == "week"
&& date.getWeek() == currentDate.getWeek()
&& dateYear == currentYear
)
{
valid = true;
}
else if( piwik.period == "day"
&& dateDay == currentDay
&& dateMonth == currentMonth
&& dateYear == currentYear
)
{
valid = true;
}
if(valid)
{
return [true, 'ui-datepicker-current-period'];
}
return [true, ''];
}
function updateDate(dateText, inst)
{
var date = dateText;
// Let broadcast do its job:
// It will replace date value to both search query and hash and load the new page.
broadcast.propagateNewPage('date=' + date);
}
$(document).ready(function(){
$('#datepicker').datepicker({
onSelect: updateDate,
showOtherMonths: false,
dateFormat: 'yy-mm-dd',
firstDay: 1,
minDate: new Date(piwik.minDateYear, piwik.minDateMonth - 1, piwik.minDateDay),
maxDate: new Date(piwik.maxDateYear, piwik.maxDateMonth - 1, piwik.maxDateDay),
prevText: "",
nextText: "",
currentText: "",
beforeShowDay: highlightCurrentPeriod,
defaultDate: currentDate,
changeMonth: true,
changeYear: true,
// jquery-ui-i18n 1.7.2 lacks some translations, so we use our own
dayNamesMin: [
_pk_translate('CoreHome_DaySu_js'),
_pk_translate('CoreHome_DayMo_js'),
_pk_translate('CoreHome_DayTu_js'),
_pk_translate('CoreHome_DayWe_js'),
_pk_translate('CoreHome_DayTh_js'),
_pk_translate('CoreHome_DayFr_js'),
_pk_translate('CoreHome_DaySa_js')],
dayNamesShort: [
_pk_translate('CoreHome_ShortDay_1_js'),
_pk_translate('CoreHome_ShortDay_2_js'),
_pk_translate('CoreHome_ShortDay_3_js'),
_pk_translate('CoreHome_ShortDay_4_js'),
_pk_translate('CoreHome_ShortDay_5_js'),
_pk_translate('CoreHome_ShortDay_6_js'),
_pk_translate('CoreHome_ShortDay_7_js')],
dayNames: [
_pk_translate('CoreHome_LongDay_1_js'),
_pk_translate('CoreHome_LongDay_2_js'),
_pk_translate('CoreHome_LongDay_3_js'),
_pk_translate('CoreHome_LongDay_4_js'),
_pk_translate('CoreHome_LongDay_5_js'),
_pk_translate('CoreHome_LongDay_6_js'),
_pk_translate('CoreHome_LongDay_7_js')],
monthNamesShort: [
_pk_translate('CoreHome_ShortMonth_1_js'),
_pk_translate('CoreHome_ShortMonth_2_js'),
_pk_translate('CoreHome_ShortMonth_3_js'),
_pk_translate('CoreHome_ShortMonth_4_js'),
_pk_translate('CoreHome_ShortMonth_5_js'),
_pk_translate('CoreHome_ShortMonth_6_js'),
_pk_translate('CoreHome_ShortMonth_7_js'),
_pk_translate('CoreHome_ShortMonth_8_js'),
_pk_translate('CoreHome_ShortMonth_9_js'),
_pk_translate('CoreHome_ShortMonth_10_js'),
_pk_translate('CoreHome_ShortMonth_11_js'),
_pk_translate('CoreHome_ShortMonth_12_js')],
monthNames: [
_pk_translate('CoreHome_MonthJanuary_js'),
_pk_translate('CoreHome_MonthFebruary_js'),
_pk_translate('CoreHome_MonthMarch_js'),
_pk_translate('CoreHome_MonthApril_js'),
_pk_translate('CoreHome_MonthMay_js'),
_pk_translate('CoreHome_MonthJune_js'),
_pk_translate('CoreHome_MonthJuly_js'),
_pk_translate('CoreHome_MonthAugust_js'),
_pk_translate('CoreHome_MonthSeptember_js'),
_pk_translate('CoreHome_MonthOctober_js'),
_pk_translate('CoreHome_MonthNovember_js'),
_pk_translate('CoreHome_MonthDecember_js')]
});
});
@@ -0,0 +1,44 @@
.tagCloud {
width:100%;
}
.tagCloud img {
border:0;
}
.tagCloud .word a {
text-decoration:none;
}
.tagCloud .word {
padding: 4px 8px 4px 0;
white-space: nowrap;
}
.tagCloud .valueIsZero {
text-decoration: line-through;
}
.tagCloud span.size0, .tagCloud span.size0 a {
color: #344971;
font-size: 28px;
}
.tagCloud span.size1, .tagCloud span.size1 a {
color: #344971;
font-size: 24px;
}
.tagCloud span.size2, .tagCloud span.size2 a {
color: #4B74AD;
font-size:20px;
}
.tagCloud span.size3, .tagCloud span.size3 a {
color: #A3A8B6;
font-size: 16px;
}
.tagCloud span.size4, .tagCloud span.size4 a {
color: #A3A8B6;
font-size: 15px;
}
.tagCloud span.size5, .tagCloud span.size5 a {
color: #A3A8B6;
font-size: 14px;
}
.tagCloud span.size6, .tagCloud span.size6 a {
color: #A3A8B6;
font-size: 11px;
}
@@ -0,0 +1,18 @@
<div id="{$properties.uniqueId}">
<div class="tagCloud">
{if count($cloudValues) == 0}
<div class="pk-emptyDataTable">{'General_NoDataForTagCloud'|translate}</div>
{else}
{foreach from=$cloudValues key=word item=value}
<span title="{$value.word} ({$value.value} {$columnTranslation})" class="word size{$value.size} {* we strike tags with 0 hits *} {if $value.value == 0}valueIsZero{/if}">
{if false !== $labelMetadata[$value.word].url}<a href="{$labelMetadata[$value.word].url}" target="_blank">{/if}
{if false !== $labelMetadata[$value.word].logo}<img src="{$labelMetadata[$value.word].logo}" width="{$value.logoWidth}" />{else}
{$value.wordTruncated}{/if}{if false !== $labelMetadata[$value.word].url}</a>{/if}</span>
{/foreach}
{/if}
{if $properties.show_footer}
{include file="CoreHome/templates/datatable_footer.tpl"}
{/if}
{include file="CoreHome/templates/datatable_js.tpl"}
</div>
</div>
@@ -0,0 +1,365 @@
/*Overriding some dataTable css for better dashboard display*/
.widget .dataTableWrapper,
.widget .dataTableAllColumnsWrapper,
.widget .dataTableGraphWrapper,
.widget .dataTableActionsWrapper,
.widget .dataTableGraphEvolutionWrapper {
width: 100%;
}
.widget {
z-index:1;
}
/* container of each table */
.dataTableWrapper {
width: 450px;
/* not more than 450px to make sure 2 tables can fit horizontally on a 1024 screen */
}
.dataTableAllColumnsWrapper {
width: 535px;
}
.subdataTableWrapper{
width: 95%;
}
.subdataTableAllColumnsWrapper {
width: 95%;
}
.dataTableActionsWrapper {
width: 500px;
}
.dataTableGraphWrapper {
width: 500px;
}
.dataTableGraphEvolutionWrapper {
width: 100%;
}
/* main data table */
table.dataTable {
width: 100%;
padding: 0;
border-spacing: 0;
margin: 0;
font-size: 0.9em;
}
table.dataTable td.label,
table.subDataTable td.label,
table.dataTableActions td.label {
width: 100%;
white-space:nowrap;
}
table.dataTable img,
table.subDataTable img,
table.dataTableActions img {
vertical-align: middle;
}
table.dataTable img {
border: 0;
margin-right: 1em;
margin-left: 0.5em;
}
table.dataTable tr.subDataTable {
cursor: pointer;
}
table.dataTable th {
margin: 0;
color: #6D929B;
border-right: 1px solid #C1DAD7;
border-bottom: 1px solid #C1DAD7;
border-top: 1px solid #C1DAD7;
text-align: left;
padding: 6px 6px 6px 12px;
background: #D4E3ED url(images/bg_header.jpg) repeat-x;
}
table.dataTable th.first {
-moz-border-radius:6px 0 0 0;
-webkit-border-radius:6px 0 0 0;
}
table.dataTable th.last {
-moz-border-radius:0 6px 0 0;
-webkit-border-radius:0 6px 0 0;
}
table.dataTable th.columnSorted {
font-weight: bold;
padding-right: 20px;
}
table.dataTable td {
border-right: 1px solid #C1DAD7;
border-bottom: 1px solid #C1DAD7;
border-left: 0;
padding: 5px 5px 5px 12px;
background: #fff;
}
table.dataTable td,table.dataTable td a {
margin: 0;
text-decoration: none;
color: #4f6b72;
}
table.dataTable td.labeleven,table.dataTable td.columneven {
background: #F9FAFA;
}
table.dataTable td.columneven {
color: #797268;
}
table.dataTable td.labeleven {
background-image: url(images/bullet2.gif);
background-repeat: no-repeat;
color: #797268;
}
table.dataTable td.labelodd {
background: #fff url(images/bullet1.gif) no-repeat;
}
table.dataTable td.label,table.subActionsDataTable td.label,table.actionsDataTable td.label
{
border-top: 0;
border-left: 1px solid #C1DAD7;
}
table.dataTable th.label {
border-left: 1px solid #C1DAD7;
}
/* the cell containing the subdatatable */
table.dataTable .cellSubDataTable {
border-left: 1px solid #C1DAD7;
padding: 0;
margin: 0;
}
/* A link in a column in the DataTable */
table.dataTable td #urlLink {
display: none;
}
/* SUBDATATABLE */ /* a datatable inside another datatable */
table.subDataTable {
background: #FFFFFF;
margin: 10px;
}
table.subDataTable td {
border: 0;
}
table.subDataTable thead th {
font-weight: normal;
font-size: 1.1em;
text-align: left;
border: 0;
border-bottom:1px solid #D1D1D1;
border-right:1px solid #D1D1D1;
border-top:1px solid #D1D1D1;
padding: .3em 1em;
color: #333333;
background: #FFE9C6;
}
table.subDataTable td.labeleven,table.subDataTable td.labelodd {
background-image: none;
}
table.subDataTable td {
border-right: 1px solid #E5E5E5;
border-bottom: 1px solid #E5E5E5;
border-left: 0;
}
table.subDataTable td,table.subDataTable td a {
color: #615B53;
}
table.subDataTable td.labeleven,table.subDataTable td.columneven {
color: #2D2A27;
}
table.subDataTable td.label {
width: 80%;
}
table.subDataTable td.labelodd,table.subDataTable td.labelodd a {
background: #ffffff;
}
table.subDataTable td.label {
padding: 5px;
}
table.dataTable img {
margin-left:0;
}
/* misc SPAN and DIV */
table thead div {
}
#sortIconContainer {
float: right;
}
#sortIcon {
margin: 0px;
position: absolute;
}
.dataTablePages {
color: #BFBFBF;
font-weight: bold;
margin: 10px;
font-size: 0.9em;
}
.dataTableSearchPattern {
display: inline;
white-space: nowrap;
}
.dataTableSearchPattern input {
font-size: 0.7em;
padding: 2px;
border: 1px solid #B3B3B3;
color: #0C183A;
}
.dataTableSearchPattern input:hover {
background: #F7F7FF none repeat scroll 0%;
}
.dataTableSearchPattern #keyword {
background: transparent url(images/search.png) no-repeat scroll 4px
center;
padding: 3px 3px 3px 20px;
}
.dataTableExcludeLowPopulation,.dataTableNext,.dataTablePrevious {
font-size: 0.9em;
color: #184A83;
text-decoration: underline;
cursor: pointer;
}
/* @todo are these supposed to be together? */
.subDataTable.dataTableFeatures {
padding-top: 0px;
padding-bottom: 5px;
width: 100%;
}
.dataTableFeatures {
padding-top: 10px;
padding-bottom: 10px;
width: 100%;
text-align: center;
}
.dataTableExcludeLowPopulation {
float: right;
font-size: 0.8em;
color: #C3C6D8;
text-align: right;
}
.dataTableNext,.dataTablePrevious,.dataTableSearchPattern,.pk-loadingDataTable
{
display: none;
}
.subDataTable .dataTableFooterIcons {
height: 0px;
}
.dataTableFooterIcons {
float: right;
height: 18px;
}
.exportToFormatIcons {
float: right;
}
.dataTableFooterIconsShow {
float: right;
}
.dataTableFooterIcons,.dataTableFooterIcons a {
text-decoration: none;
color: #8894B1;
font-size:0.9em;
}
.dataTableSpacer {
clear: both;
}
.pk-loadingDataTable {
float: left;
font-size: 0.9em;
color: #193B6C;
padding: 0.5em;
}
/* Actions table */
table.dataTableActions tr td.labelodd {
background-image: none;
}
/* levels higher than 4 have a default padding left */
tr.subActionsDataTable td.label,tr.actionsDataTable td.label {
padding-left: 7em;
}
tr.level0 td.label {
padding-left: +1.5em;
}
tr.level1 td.label {
padding-left: +2.5em;
}
tr.level2 td.label {
padding-left: +3.5em;
}
tr.level3 td.label {
padding-left: +4.5em;
}
tr.level4 td.label {
padding-left: +5em;
}
/* less right margins for the link image in the Pa*/
table.dataTableActions img.link {
margin-right: 0.3em;
margin-left:-0.5em;
}
tr td.label img.plusMinus {
margin-right: 0em;
margin-left:-1em;
}
.pk-emptyDataTable {
padding-top: 20px;
padding-bottom: 10px;
text-align: center;
font-size: 0.9em;
font-style: italic;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,41 @@
<div id="{$properties.uniqueId}">
<div class="{if isset($javascriptVariablesToSet.idSubtable)&& $javascriptVariablesToSet.idSubtable!=0}sub{/if}{if $javascriptVariablesToSet.viewDataTable=='tableAllColumns'}dataTableAllColumnsWrapper{elseif $javascriptVariablesToSet.viewDataTable=='tableGoals'}dataTableAllColumnsWrapper{else}dataTableWrapper{/if}">
{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
{$arrayDataTable.message}
{else}
{if count($arrayDataTable) == 0}
<div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div>
{else}
<a name="{$properties.uniqueId}"></a>
<table cellspacing="0" class="dataTable">
<thead>
<tr>
{foreach from=$dataTableColumns item=column name=head}
<th class="sortable {if $smarty.foreach.head.first}first{elseif $smarty.foreach.head.last}last{/if}" id="{$column}"><div id="thDIV">{$columnTranslations[$column]}</div></th>
{/foreach}
</tr>
</thead>
<tbody>
{foreach from=$arrayDataTable item=row}
<tr {if $row.idsubdatatable && $javascriptVariablesToSet.controllerActionCalledWhenRequestSubTable != null}class="subDataTable" id="{$row.idsubdatatable}"{/if}>
{foreach from=$dataTableColumns item=column}
<td>
{if !$row.idsubdatatable && $column=='label' && !empty($row.metadata.url)}<span class="urlLink">{$row.metadata.url}</span>{/if}
{if $column=='label'}{logoHtml metadata=$row.metadata alt=$row.columns.label}{/if}
{if isset($row.columns[$column])}{$row.columns[$column]}{else}{$defaultWhenColumnValueNotDefined}{/if}
</td>
{/foreach}
</tr>
{/foreach}
</tbody>
</table>
{/if}
{if $properties.show_footer}
{include file="CoreHome/templates/datatable_footer.tpl"}
{/if}
{include file="CoreHome/templates/datatable_js.tpl"}
{/if}
</div>
</div>
@@ -0,0 +1,39 @@
<div id="{$properties.uniqueId}">
<div class="dataTableActionsWrapper">
{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
{$arrayDataTable.message}
{else}
{if count($arrayDataTable) == 0}
<div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div>
{else}
<table cellspacing="0" class="dataTable dataTableActions">
<thead>
<tr>
{foreach from=$dataTableColumns item=column name=head}
<th class="sortable {if $smarty.foreach.head.first}first{elseif $smarty.foreach.head.last}last{/if}" id="{$column}"><div id="thDIV">{if !empty($columnDescriptions[$column])}<label title='{$columnDescriptions[$column]|escape:'html'}'>{/if}{$columnTranslations[$column]|escape:'html'}{if !empty($columnDescriptions[$column])}</label>{/if}</div></td>
{/foreach}
</tr>
</thead>
<tbody>
{foreach from=$arrayDataTable item=row}
<tr {if $row.idsubdatatable}class="rowToProcess subActionsDataTable" id="{$row.idsubdatatable}"{else} class="actionsDataTable rowToProcess"{/if}>
{foreach from=$dataTableColumns item=column}
<td>
{if !$row.idsubdatatable && $column=='label' && isset($row.metadata.url)}<span class="urlLink">{$row.metadata.url}</span>{/if}
{if isset($row.columns[$column])}{$row.columns[$column]}{else}{$defaultWhenColumnValueNotDefined}{/if}
</td>
{/foreach}
</tr>
{/foreach}
</tbody>
</table>
{/if}
{if $properties.show_footer}
{include file="CoreHome/templates/datatable_footer.tpl"}
{/if}
{include file="CoreHome/templates/datatable_actions_js.tpl"}
{/if}
</div>
</div>
@@ -0,0 +1,12 @@
<script type="text/javascript" defer="defer">
$(document).ready(function(){literal}{{/literal}
actionDataTables['{$properties.uniqueId}'] = new actionDataTable();
actionDataTables['{$properties.uniqueId}'].param = {literal}{{/literal}
{foreach from=$javascriptVariablesToSet key=name item=value name=loop}
{$name}: '{$value}'{if !$smarty.foreach.loop.last},{/if}
{/foreach}
{literal}};{/literal}
actionDataTables['{$properties.uniqueId}'].init('{$properties.uniqueId}');
{literal}}{/literal});
</script>
@@ -0,0 +1,36 @@
<div id="{$properties.uniqueId}">
<div class="dataTableActionsWrapper">
{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
{$arrayDataTable.message}
{else}
{if count($arrayDataTable) == 0}
<div class="pk-emptyDataTable">{'CoreHome_TableNoData'|translate}</div>
{else}
<table cellspacing="0" class="dataTable dataTableActions">
<thead>
<tr>
{foreach from=$dataTableColumns item=column}
<th class="sortable" id="{$column}">{$columnTranslations[$column]}</td>
{/foreach}
</tr>
</thead>
<tbody>
{foreach from=$arrayDataTable item=row}
<tr {if $row.idsubdatatable}class="level{$row.level} rowToProcess subActionsDataTable" id="{$row.idsubdatatable}"{else}class="actionsDataTable rowToProcess level{$row.level}"{/if}>
{foreach from=$dataTableColumns item=column}
<td>
{if isset($row.columns[$column])}{$row.columns[$column]}{else}{$defaultWhenColumnValueNotDefined}{/if}
</td>
{/foreach}
</tr>
{/foreach}
</tbody>
</table>
{/if}
{include file="CoreHome/templates/datatable_footer.tpl"}
{include file="CoreHome/templates/datatable_actions_js.tpl"}
{/if}
</div>
</div>
@@ -0,0 +1,19 @@
<tr id="{$properties.uniqueId}"></tr>
{if isset($arrayDataTable.result) and $arrayDataTable.result == 'error'}
{$arrayDataTable.message}
{else}
{if count($arrayDataTable) == 0}
<tr><td colspan="{$nbColumns}">{'CoreHome_CategoryNoData'|translate}</td></tr>
{else}
{foreach from=$arrayDataTable item=row}
<tr {if $row.idsubdatatable}class="subActionsDataTable" id="{$row.idsubdatatable}"{else}class="actionsDataTable"{/if}>
{foreach from=$dataTableColumns item=column}
<td>
{if !$row.idsubdatatable && $column=='label' && isset($row.metadata.url)}<span class="urlLink">{$row.metadata.url}</span>{/if}
{if isset($row.columns[$column])}{$row.columns[$column]}{else}{$defaultWhenColumnValueNotDefined}{/if}
</td>
{/foreach}
</tr>
{/foreach}
{/if}
{/if}
@@ -0,0 +1,73 @@
<div class="dataTableFeatures">
{if $properties.show_exclude_low_population}
<span class="dataTableExcludeLowPopulation"></span>
{/if}
{if $properties.show_offset_information}
<div>
<span class="dataTablePages"></span>
<span class="dataTablePrevious">&lsaquo; {'General_Previous'|translate}</span>
<span class="dataTableNext">{'General_Next'|translate} &rsaquo;</span>
</div>
{/if}
{if $properties.show_search}
<span class="dataTableSearchPattern">
<input id="keyword" type="text" length="15" />
<input type="submit" value="{'General_Search'|translate}" />
</span>
{/if}
{if $properties.show_footer_icons}
<div>
<span class="dataTableFooterIcons">
<span class="exportToFormatIcons" style="display:none;padding-left:4px;">
{if $properties.show_export_as_image_icon}
<span id="dataTableFooterExportAsImageIcon">
<a href="javascript:piwikHelper.OFC.jquery.popup('{$chartDivId}');"><img title="{'General_ExportAsImage_js'|translate}" src="themes/default/images/image.png" /></a>
</span>
{/if}
<img width="16" height="16" src="themes/default/images/export.png" title="{'General_Export'|translate}" />
<span class="linksExportToFormat" style="display:none">
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="CSV" filter_limit="100">CSV</a> |
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="TSV" filter_limit="100">TSV (Excel)</a> |
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="XML" filter_limit="100">XML</a> |
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="JSON" filter_limit="100">Json</a> |
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="PHP" filter_limit="100">Php</a> |
<a target="_blank" class="exportToFormat" methodToCall="{$properties.apiMethodToRequestDataTable}" format="RSS" filter_limit="100" date="last10"><img border="0" src="themes/default/images/feed.png" /></a>
</span>
{if $properties.show_all_views_icons}
<a class="viewDataTable" format="cloud"><img width="16" height="16" src="themes/default/images/tagcloud.png" title="{'General_TagCloud'|translate}" /></a>
<a class="viewDataTable" format="graphVerticalBar"><img width="16" height="16" src="themes/default/images/chart_bar.png" title="{'General_VBarGraph'|translate}" /></a>
<a class="viewDataTable" format="graphPie"><img width="16" height="16" src="themes/default/images/chart_pie.png" title="{'General_Piechart'|translate}" /></a>
{/if}
</span>
<span class="dataTableFooterIconsShow" style="display:none;padding-left:4px;">
<img src="plugins/CoreHome/templates/images/more.png" />
</span>
{if $properties.show_table}
<span class="tableAllColumnsSwitch" style="display:none;float:right;padding-right:4px;border-right:1px solid #82A1D2;">
{if $javascriptVariablesToSet.viewDataTable != 'table'}
<img title="{'General_DisplayNormalTable'|translate}" src="themes/default/images/table.png" />
{elseif $properties.show_table_all_columns}
<img title="{'General_DisplayMoreData'|translate}" src="themes/default/images/table_more.png" />
{/if}
</span>
{/if}
{if $properties.show_goals}
<span class="tableGoals" style="display:none;float:right;padding-right:4px;">
{if $javascriptVariablesToSet.viewDataTable != 'tableGoals'}
<img title="{'General_DisplayGoals'|translate}" src="themes/default/images/goal.png" />
{/if}
</span>
{/if}
</span>
</div>
{/if}
<span class="pk-loadingDataTable"><img src="themes/default/images/loading-blue.gif" /> {'General_LoadingData'|translate}</span>
</div>
<div class="dataTableSpacer" />
@@ -0,0 +1,12 @@
<script type="text/javascript" defer="defer">
$(document).ready(function(){literal}{{/literal}
dataTables['{$properties.uniqueId}'] = new dataTable();
dataTables['{$properties.uniqueId}'].param = {literal}{{/literal}
{foreach from=$javascriptVariablesToSet key=name item=value name=loop}
{$name}: '{$value}'{if !$smarty.foreach.loop.last},{/if}
{/foreach}
{literal}};{/literal}
dataTables['{$properties.uniqueId}'].init('{$properties.uniqueId}');
{literal}}{/literal});
</script>
@@ -0,0 +1,92 @@
$(document).ready(function(){
$("#periodString").hide();
$("#otherPeriods").hide();
$("#datepicker").hide();
$("#periodString").show();
// we get the content of the div before modifying it (append image, etc.)
// so we can restore its value when we want
var savedCurrentPeriod = $("#periodString #currentPeriod").html();
// timeout used to fadeout the menu
var timeout = null;
var timeoutLength;
// restore the normal style of the current period type eg "DAY"
function restoreCurrentPeriod()
{
$("#currentPeriod")
.removeClass("hoverPeriod")
.html(savedCurrentPeriod);
}
// remove the sub menu created that contains the other periods availble
// eg. week | month | year
function removePeriodMenu() {
$("#otherPeriods").fadeOut('fast');
setCurrentPeriodStyle = true;
}
// state machine a bit complex and was hard to come up with
// there should be a simpler way to do it with jquery...
// if set to true, means that we want to style our current period
// for example add bold and append the image
var setCurrentPeriodStyle = true;
$("#periodString #periods")
.hover(function(){
$(this).css({ cursor: "pointer"});
// cancel the timeout
// indeed if the user goes away of the div and goes back on
// we don't hide the submenu!
if(timeout != null)
{
clearTimeout(timeout);
timeout = null;
timeoutLength = 500;
}
else
{
timeoutLength = 0;
setCurrentPeriodStyle = true;
}
if( setCurrentPeriodStyle == true)
{
$("#currentPeriod:not(.hoverPeriod)")
.addClass("hoverPeriod")
.append('&nbsp;<img src="plugins/CoreHome/templates/images/more_period.gif" style="vertical-align:middle" />');
}
}, function(){
restoreCurrentPeriod();
// we callback the function to hide the sub menu
// only if it was visible (otherwise it messes the state machine)
if($("#otherPeriods").is(":visible"))
{
timeout = setTimeout( removePeriodMenu , timeoutLength);
}
setCurrentPeriodStyle = false;
})
.click( function() {
// we restore the initial style on the DAY link
restoreCurrentPeriod();
// the menu shall fadeout after 500ms
timeoutLength = 500;
// appearance!
$("#otherPeriods").fadeIn();
});
$("#periodString #date")
.hover( function(){
$(this).css({ cursor: "pointer"});
}, function(){
})
.click(function(){
$("#datepicker").toggle();
if($("#datepicker").is(":visible"))
{
$("#datepicker .ui-state-highlight").removeClass('ui-state-highlight');
}
});
} );
@@ -0,0 +1,48 @@
<div id="{$properties.uniqueId}">
<div class="{if $graphType=='evolution'}dataTableGraphEvolutionWrapper{else}dataTableGraphWrapper{/if}">
{if $flashParameters.isDataAvailable || !$flashParameters.includeData}
<div><div id="{$chartDivId}">
{'General_RequiresFlash'|translate} >= {$flashParameters.requiredFlashVersion}. <a target="_blank" href="misc/redirectToUrl.php?url={'http://piwik.org/faq/troubleshooting/#faq_53'|escape:"url"}">{'General_GraphHelp'|translate}</a>
</div></div>
<script type="text/javascript">
<!--
{if $flashParameters.includeData}
piwikHelper.OFC.set("{$chartDivId}", '{$flashParameters.data}');
{/if}
swfobject.embedSWF(
"{$flashParameters.ofcLibraryPath}open-flash-chart.swf?{$tag}",
"{$chartDivId}",
"{$flashParameters.width}", "{$flashParameters.height}",
"{$flashParameters.requiredFlashVersion}",
"{$flashParameters.swfLibraryPath}expressInstall.swf",
{literal}{{/literal}
"{if $flashParameters.includeData}x-{/if}data-file":"{$urlGraphData|escape:"url"}",
{if $flashParameters.includeData}
"id":"{$chartDivId}",
{/if}
"loading":"{'General_Loading'|translate|escape:"html"}"
{literal}},
{{/literal}
"allowScriptAccess":"always",
"wmode":"transparent"
{literal}},
{{/literal}
"bgcolor":"#FFFFFF"
{literal}}{/literal}
);
//-->
</script>
{else}
<div><div id="{$chartDivId}" class="pk-emptyGraph">
{'General_NoDataForGraph'|translate}
</div></div>
{/if}
{if $properties.show_footer}
{include file="CoreHome/templates/datatable_footer.tpl"}
{include file="CoreHome/templates/datatable_js.tpl"}
{/if}
</div>
</div>
@@ -0,0 +1,15 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Piwik &rsaquo; {'CoreHome_WebAnalyticsReports'|translate}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Piwik {$piwik_version}" />
<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
{loadJavascriptTranslations plugins='CoreHome'}
{include file="CoreHome/templates/js_global_variables.tpl"}
{include file="CoreHome/templates/js_css_includes.tpl"}
</head>
<body>
{include file="CoreHome/templates/top_bar.tpl"}
{include file="CoreHome/templates/top_screen.tpl"}
@@ -0,0 +1,14 @@
<span id="header_message">
{if $piwikUrl == 'http://piwik.org/demo/'}
{'General_YouAreCurrentlyViewingDemoOfPiwik'|translate:"<a target='_blank' href='http://piwik.org'>Piwik</a>":"<a href='http://piwik.org/'>":"</a>":"<a href='http://piwik.org'>piwik.org</a>"}
{elseif $latest_version_available}
<img src='themes/default/images/warning_small.png' alt='' style="vertical-align: middle;" />
{if $isSuperUser}
{'General_PiwikXIsAvailablePleaseUpdateNow'|translate:$latest_version_available:"<br /><a href='index.php?module=CoreUpdater&action=newVersionAvailable'>":"</a>":"<a href='misc/redirectToUrl.php?url=http://piwik.org/changelog/' target='_blank'>":"</a>"}
{else}
{'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org/' target='_blank'>Piwik</a> <a href='misc/redirectToUrl.php?url=http://piwik.org/changelog/' target='_blank'>$latest_version_available</a>"}
{/if}
{else}
{'General_PiwikIsACollaborativeProjectYouCanContribute'|translate:"<a href='misc/redirectToUrl.php?url=http://piwik.org'>":"$piwik_version</a>":"<br />":"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/contribute/'>":"</a>"}
{/if}
</span>
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

@@ -0,0 +1,49 @@
{assign var=showSitesSelection value=true}
{include file="CoreHome/templates/header.tpl"}
{if isset($menu) && $menu}{include file="CoreHome/templates/menu.tpl"}{/if}
<div style="clear:both;"></div>
{ajaxLoadingDiv}
{ajaxRequestErrorDiv}
<div id="content">
{if $content}{$content}{/if}
</div>
{include file="CoreHome/templates/piwik_tag.tpl"}
{literal}
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-13048050-1']);
_gaq.push(['_setDomainName', '.hawebs.net']);
_gaq.push(['_setLocalRemoteServerMode']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://wa.hawebs.net/" : "http://wa.hawebs.net/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 7);
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
} catch( err ) {}
</script><noscript><p><img src="http://wa.hawebs.net/piwik.php?idsite=7" style="border:0" alt="" /></p></noscript>
<!-- End Piwik Tag -->
{/literal}
</body>
</html>
@@ -0,0 +1,26 @@
<link rel="stylesheet" type="text/css" href="themes/default/common.css" />
<link rel="stylesheet" type="text/css" href="libs/jquery/themes/base/jquery-ui.css" class="ui-theme" />
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/styles.css" />
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/menu.css" />
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/datatable.css" />
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/cloud.css" />
{postEvent name="template_css_import"}
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
<script type="text/javascript" src="libs/jquery/jquery-ui.js"></script>
<script type="text/javascript" src="libs/jquery/jquery.bgiframe.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.blockUI.js"></script>
<script type="text/javascript" src="libs/jquery/fdd2div-modified.js"></script>
<script type="text/javascript" src="libs/jquery/superfish_modified.js"></script>
<script type="text/javascript" src="libs/jquery/jquery.history.js"></script>
<script type="text/javascript" src="libs/swfobject/swfobject.js"></script>
<script type="text/javascript" src="libs/javascript/sprintf.js"></script>
<script type="text/javascript" src="themes/default/common.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/datatable.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/broadcast.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/menu.js"></script>
{postEvent name="template_js_import"}
@@ -0,0 +1,5 @@
<noscript>
<div id="javascriptDisable">
{'CoreHome_JavascriptDisabled'|translate:'<a href="">':'</a>'}
</div>
</noscript>
@@ -0,0 +1,16 @@
<script type="text/javascript">
var piwik = {literal}{}{/literal};
piwik.token_auth = "{$token_auth}";
piwik.piwik_url = "{$piwikUrl|urlencode}";
{if isset($idSite)}piwik.idSite = "{$idSite}";{/if}
{if isset($siteName)}piwik.siteName = "{$siteName}";{/if}
{if isset($siteMainUrl)}piwik.siteMainUrl = "{$siteMainUrl}";{/if}
{if isset($period)}piwik.period = "{$period}";{/if}
{if isset($date)}piwik.currentDateString = "{$date}";{/if}
{if isset($minDateYear)}piwik.minDateYear = {$minDateYear};{/if}
{if isset($minDateMonth)}piwik.minDateMonth = parseInt("{$minDateMonth}", 10);{/if}
{if isset($minDateDay)}piwik.minDateDay = parseInt("{$minDateDay}", 10);{/if}
{if isset($maxDateYear)}piwik.maxDateYear = {$maxDateYear};{/if}
{if isset($maxDateMonth)}piwik.maxDateMonth = parseInt("{$maxDateMonth}", 10);{/if}
{if isset($maxDateDay)}piwik.maxDateDay = parseInt("{$maxDateDay}", 10);{/if}
</script>
@@ -0,0 +1,6 @@
<span id="logo">
<a href="index.php" title="Piwik # {'General_OpenSourceWebAnalytics'|translate}" style="text-decoration: none;">
<span style="color: rgb(245, 223, 114);">P</span><span style="color: rgb(241, 175, 108);">i</span><span style="color: rgb(241, 117, 117);">w</span><span style="color: rgb(155, 106, 58);">i</span><span style="color: rgb(107, 50, 11);">k</span>
{if $currentModule != 'CoreHome'}<span style="padding-left:1em;font-size: 20pt; letter-spacing: -1pt; color: rgb(107, 50, 11);">&rsaquo; {$currentPluginName}</span>{/if}
</a>
</span>
@@ -0,0 +1,119 @@
.nav,.nav * {
margin: 0;
padding: 0;
}
.nav {
z-index:10;
padding-bottom: 2.5em;
height: 2.5em;
float: left;
line-height: 1.0;
margin-bottom: 1.5em;
position: relative;
width:100%;
}
.nav ul {
background: #fff; /*IE6 needs this*/
float: left;
position: relative;
}
/* LEVEL1 NORMAL */
.nav li {
background: #DFE6FF;
border-left: 1px solid #fff;
float: left;
list-style: none;
z-index: 49;
margin-right:1px;
}
.nav li.current ul {
z-index: 49;
}
.nav li.sfHover ul,ul.nav li:hover ul {
z-index: 50;
}
/* LEVEL2 NORMAL */
.nav li li {
background: #FBFFFF;
border-left-color: #AABDE6;
}
.nav a {
border-bottom: 1px solid #CFDEFF;
color: #13a;
display: block;
float: left;
padding: .75em 0 .75em 1em;
text-decoration: none;
width: 8em;
}
.nav li ul {
left: 0;
top: -999em;
position: absolute;
}
.nav li, .nav li:hover,.nav li.sfHover,.nav li.current,.nav a:focus,.nav a:hover,.nav a:active{
-moz-border-radius:5px 5px 0 0;
-webkit-border-radius:5px 5px 0 0;
}
/* LEVEL1 HOVER */
.nav li:hover,.nav li.sfHover,.nav li.current,.nav a:focus,.nav a:hover,.nav a:active {
background: #C9D5FF;
-moz-border-radius:5px 5px 0 0;
-webkit-border-radius:5px 5px 0 0;
}
.nav li {
font-weight: normal;
}
.nav li.sfHover {
font-weight: bold;
}
/* LEVEL2 HOVER */
.nav li li:hover,.nav li li.sfHover,.nav li li a:focus,.nav li li a:hover,.nav li li a:active
{
background: #C9F6FF;
font-weight: bold;
}
.nav li.sfHover a,.nav li.current a,.nav a:focus,.nav a:hover,.nav a:active
{
border-bottom: none;
}
.nav li li.current a {
font-weight: bold;
}
.nav li:hover ul, /* pure CSS hover is removed below */ body .nav li.current ul,
/* this must be more specific than the .superfish override below */ ul.nav li.sfHover ul
{
top: 2.5em;
}
.nav li:hover li ul,.nav li.sfHover li ul {
top: -999em;
}
.nav li li:hover ul, /* pure CSS hover is removed below */ ul.nav li li.sfHover ul
{
top: 2.5em;
}
/*following rule negates pure CSS hovers
so submenu remains hidden and JS controls
when and how it appears*/
.superfish li:hover ul,.superfish li li:hover ul {
top: -999em;
}
@@ -0,0 +1,139 @@
function menu()
{
this.param = {};
}
menu.prototype =
{
menuSectionLoaded: function (content, urlLoaded)
{
if(urlLoaded == menu.prototype.lastUrlRequested)
{
$('#content').html( content ).show();
piwikHelper.hideAjaxLoading();
menu.prototype.lastUrlRequested = null;
}
},
customAjaxHandleError: function ()
{
menu.prototype.lastUrlRequested = null;
piwikHelper.ajaxHandleError();
},
overMainLI: function ()
{
$(this).siblings().removeClass('sfHover');
},
outMainLI: function ()
{
},
onClickLI: function ()
{
var self = this;
var urlAjax = $('a',this).attr('name');
broadcast.propagateAjax(urlAjax);
return false;
},
init: function()
{
var self = this;
this.param.superfish = $('.nav')
.superfish({
pathClass : 'current',
animation : {opacity:'show'},
delay : 2000
});
this.param.superfish.find("li")
.click( self.onClickLI )
;
this.param.superfish
.find("li:has(ul)")
.hover(self.overMainLI, self.outMainLI)
;
// add id to all li menu to suport menu identification.
// for all sub menu we want to have a unique id based on their module and action
// for main menu we want to add just the module as its id.
this.param.superfish.find('li').each(function(){
var url = $(this).find('a').attr('name');
var module = broadcast.getValueFromUrl("module",url);
var action = broadcast.getValueFromUrl("action",url);
var idGoal = broadcast.getValueFromUrl("idGoal",url);
var main_menu = ($(this).parent().attr("class").match(/nav/)) ? true : false;
if(main_menu)
{
$(this).attr({id: module});
}
else
{
// so Goals plugin is a little different than other
// we can't identify by it's modules_action so we uses its idGoals.
if(idGoal != '') {
$(this).attr({id: module + '_' + action + '_' + idGoal});
}
else {
$(this).attr({id: module + '_' + action});
}
}
});
},
activateMenu : function(module,action,idGoal)
{
// getting the right li is a little tricky since goals uses idGoal, and overview is index.
var $li = '';
// So, if module is Goals, idGoal is present, and action is not Index, must be one of the goals
if(module == 'Goals' && idGoal != '' && action != 'index') {
$li = $("#" + module + "_" + action + "_" + idGoal);
} else {
$li = $("#" + module + "_" + action);
}
// we can't find this li based on Module_action? then li only be the main menu. e.g Dashboard.
var no_sub_menu = false;
if($li.size() == 0) {
$li = $("#" + module);
no_sub_menu = true;
}
piwikMenu.param.superfish.find("li").removeClass('sfHover');
if($li.find('ul li').size() != 0 || no_sub_menu == true) {
// we clicked on a MAIN LI
$.fn.superfish.currentActiveMenu = $li;
$li.find('>ul li:first').addClass('sfHover');
$li.find('ul').css({'display':'block','visibility': 'visible'});
} else {
// we are in the SUB UL LI
$.fn.superfish.currentActiveMenu = $li.parents('li');
$li.addClass('sfHover');
$li.parents('ul').css({'display':'block','visibility': 'visible'});
}
$.fn.superfish.currentActiveMenu.showSuperfishUl().siblings().hideSuperfishUl();
},
loadFirstSection: function()
{
var self=this;
if(broadcast.isHashExists() == false) {
$('li:first', self.param.superfish)
.click()
.each(function(){ $(this).showSuperfishUl(); });
}
}
};
$(document).ready( function(){
if($('.nav').size()) {
piwikMenu = new menu();
piwikMenu.init();
piwikMenu.loadFirstSection();
broadcast.init();
}
});
@@ -0,0 +1,14 @@
<ul class="nav">
{foreach from=$menu key=level1 item=level2 name=menu}
<li>
<a name='{$level2._url|@urlRewriteWithParameters}' href='index.php{$level2._url|@urlRewriteBasicView}'>{$level1|translate}</a>
<ul>
{foreach from=$level2 key=name item=urlParameters name=level2}
{if $name != '_url'}
<li><a name='{$urlParameters|@urlRewriteWithParameters}' href='index.php{$urlParameters|@urlRewriteBasicView}'>{$name|translate}</a></li>
{/if}
{/foreach}
</ul>
</li>
{/foreach}
</ul>
@@ -0,0 +1,29 @@
{loadJavascriptTranslations plugins='CoreHome'}
<script type="text/javascript" src="plugins/CoreHome/templates/calendar.js"></script>
<script type="text/javascript" src="plugins/CoreHome/templates/date.js"></script>
<span id="periodString">
<span id="date"><img src='themes/default/images/icon-calendar.gif' style="vertical-align:middle" alt="" /> {$prettyDate}</span> -&nbsp;
<span id="periods">
<span id="currentPeriod">{$periodsNames.$period.singular}</span>
<span id="otherPeriods">
{foreach from=$otherPeriods item=thisPeriod} | <a href='{url period=$thisPeriod}'>{$periodsNames.$thisPeriod.singular}</a>{/foreach}
</span>
</span>
<br />
<span id="datepicker"></span>
</span>
{literal}<script type="text/javascript">
$(document).ready(function() {
// this will trigger to change only the period value on search query and hash string.
$("#otherPeriods a").bind('click',function(e) {
e.preventDefault();
var request_URL = $(e.target).attr("href");
var new_period = broadcast.getValueFromUrl('period',request_URL);
broadcast.propagateNewPage('period='+new_period);
});
});</script>
{/literal}
<div style="clear:both;"></div>
@@ -0,0 +1,46 @@
{if $piwikUrl == 'http://piwik.org/demo/' || $debugTrackVisitsInsidePiwikUI}
<div style="clear:both;"></div>
{literal}
<!-- Piwik -->
<script src="piwik.js" type="text/javascript"></script>
<script type="text/javascript">
try {
var piwikTracker = Piwik.getTracker("piwik.php", 1);
piwikTracker.setCustomData({ 'video_play':1, 'video_finished':0 });
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
} catch(err) {}
</script>
<!-- End Piwik Tag -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-13048050-1']);
_gaq.push(['_setDomainName', '.hawebs.net']);
_gaq.push(['_setLocalRemoteServerMode']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
<!-- Piwik -->
<script type="text/javascript">
var pkBaseURL = (("https:" == document.location.protocol) ? "https://wa.hawebs.net/" : "http://wa.hawebs.net/");
document.write(unescape("%3Cscript src='" + pkBaseURL + "piwik.js' type='text/javascript'%3E%3C/script%3E"));
</script><script type="text/javascript">
try {
var piwikTracker = Piwik.getTracker(pkBaseURL + "piwik.php", 7);
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
} catch( err ) {}
</script><noscript><p><img src="http://wa.hawebs.net/piwik.php?idsite=7" style="border:0" alt="" /></p></noscript>
<!-- End Piwik Tag -->
{/literal}
{/if}
@@ -0,0 +1,36 @@
<span id="sitesSelectionWrapper" style="display:none;" >
{'General_Website'|translate} <span id="selectedSiteName" style="display:none">{$siteName}</span>
<span id="sitesSelection" style="position:absolute">Site
<form action="{url idSite=null}" method="get">
<select name="idSite">
{foreach from=$sites item=info}
<option value="{$info.idsite}" {if $idSite==$info.idsite} selected="selected"{/if}>{$info.name}</option>
{/foreach}
</select>
{hiddenurl idSite=null}
<input type="submit" value="go" />
</form>
</span>
{literal}<script type="text/javascript">
$(document).ready(function() {
var extraPadding = 0;
// if there is only one website, we dont show the arrows image, so no need to add the extra padding
if( $('#sitesSelection').find('option').size() > 1) {
extraPadding = 21;
}
$("#sitesSelectionWrapper").show();
var widthSitesSelection = $("#selectedSiteName").width() + 4 + extraPadding;
$("#sitesSelectionWrapper").css('padding-right', widthSitesSelection);
$("#sitesSelection").fdd2div({CssClassName:"formDiv"});
// this will put the anchor after the url before proceed to different site.
$("#sitesSelection ul li").bind('click',function (e) {
e.preventDefault();
var request_URL = $(e.target).attr("href");
var new_idSite = broadcast.getValueFromUrl('idSite',request_URL);
broadcast.propagateNewPage( 'idSite='+new_idSite );
});
});</script>
{/literal}
</span>
@@ -0,0 +1,36 @@
$(document).ready( function(){
$("a[name='evolutionGraph']").each( function() {
var graph = $(this);
if(graph && graph.size() > 0) {
//try to find sparklines and add them clickable behaviour
$(this).parent().find('div.sparkline').each( function() {
var url = "";
//find the sparkline and get it's src attribute
$("img.sparkline", this).each(function() {
//search viewDataTable parameter and replace it with value for chart
var reg = new RegExp("(viewDataTable=sparkline)", "g");
url = this.src.replace(reg,'viewDataTable=generateDataChartEvolution');
});
if(url != ""){
//on click, reload the graph with the new url
$(this).click( function() {
//get the main page graph and reload with new data
piwikHelper.findSWFGraph(graph.attr('graphId')+"Chart_swf").reload(url);
piwikHelper.lazyScrollTo(graph[0], 400);
});
$(this).hover(
function() {
$(this).css({
"cursor": "pointer",
"border-bottom": "1px dashed #C3C3C3"
});
},
function(){
$(this).css({"border-bottom":"1px solid white"});
}
);
}
});
}
});
});
@@ -0,0 +1,101 @@
h1 {
font-size: 2em;
color: #0F1B2E;
padding-bottom: 1em;
}
h2 {
font-size: 1.3em;
color: #1D3256;
padding-bottom: 0.5em;
clear:both;
}
h2 a {
text-decoration:none;
}
h3 {
font-size: 1.3em;
margin-top: 2em;
color: #1D3256;
}
p {
padding-bottom: 1em;
margin-right: 1em;
margin-left:1em;
}
/* Content */
#content {
margin-left: 10px;
}
/* 2 columns reports */
#leftcolumn {
float: left;
width: 50%;
padding-left: 10px;
}
#rightcolumn {
float: right;
width: 45%;
}
/* not in widget */
.widget #leftcolumn, .widget #rightcolumn {
float:left;
width:100%;
padding-left:10px;
}
/* Calendar*/
div.ui-datepicker {
font-size: 62.5%;
}
.ui-datepicker-current-period a, .ui-datepicker-current-period a:link, .ui-datepicker-current-period a:visited {
border: 1px solid #2E85FF;
color: #2E85FF;
}
#otherPeriods a {
text-decoration: none;
}
#otherPeriods a:hover {
text-decoration: underline;
}
#currentPeriod {
border-bottom: 1px dotted #520202;
}
.hoverPeriod {
cursor: pointer;
font-weight: bold;
border-bottom: 1px solid #520202;
}
div .sparkline {
float:left;
clear:both;
padding-bottom: 1px;
margin-top:10px;
border-bottom:1px solid white;
}
.sparkline img {
vertical-align: middle;
padding-right: 10px;
margin-top: 0;
}
div.pk-emptyGraph {
padding-top: 20px;
padding-bottom: 10px;
text-align: center;
font-size: 0.9em;
font-style: italic;
}
@@ -0,0 +1,26 @@
{assignTopBar}
<div id="topBars">
<div id="topLeftBar">
{foreach from=$topBarElements item=element}
<span class="topBarElem">{if $element.0 == $currentModule}<b>{else}<a href="index.php{$element.2|@urlRewriteWithParameters}" {if isset($element.3)}{$element.3}{/if}>{/if}{$element.1}{if $element.0 == $currentModule}</b>{else}</a>{/if}</span>
{/foreach}
{postEvent name="template_topBar"}
</div>
<div id="topRightBar">
<nobr>
<small>
{'General_HelloUser'|translate:"<strong>$userLogin</strong>"}
{if $userLogin != 'anonymous'}| <a href='index.php?module=CoreAdminHome'>{'General_Settings'|translate}</a>{/if}
{if $showSitesSelection && $showWebsiteSelectorInUserInterface}| {include file=CoreHome/templates/sites_selection.tpl}{/if}
| {if $userLogin == 'anonymous'}<a href='index.php?module={$loginModule}'>{'Login_LogIn'|translate}</a>{else}<a href='index.php?module={$loginModule}&amp;action=logout'>{'Login_Logout'|translate}</a>{/if}
</small>
</nobr>
</div>
<br class="clearAll" />
</div>
@@ -0,0 +1,7 @@
<div id="header">
{include file="CoreHome/templates/header_message.tpl"}
{include file="CoreHome/templates/logo.tpl"}
{include file="CoreHome/templates/period_select.tpl"}
{include file="CoreHome/templates/js_disabled_notice.tpl"}
</div>
<br />
@@ -0,0 +1,73 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Controller.php 2183 2010-05-14 08:04:11Z matt $
*
* @category Piwik_Plugins
* @package Piwik_CorePluginsAdmin
*/
/**
*
* @package Piwik_CorePluginsAdmin
*/
class Piwik_CorePluginsAdmin_Controller extends Piwik_Controller
{
function index()
{
Piwik::checkUserIsSuperUser();
$plugins = array();
$listPlugins = Piwik_PluginsManager::getInstance()->readPluginsDirectory();
foreach($listPlugins as $pluginName)
{
$oPlugin = Piwik_PluginsManager::getInstance()->loadPlugin($pluginName);
$plugins[$pluginName] = array(
'activated' => Piwik_PluginsManager::getInstance()->isPluginActivated($pluginName),
'alwaysActivated' => Piwik_PluginsManager::getInstance()->isPluginAlwaysActivated($pluginName),
);
}
Piwik_PluginsManager::getInstance()->loadTranslations();
$loadedPlugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins();
foreach($loadedPlugins as $oPlugin)
{
$pluginName = $oPlugin->getClassName();
$plugins[$pluginName]['info'] = $oPlugin->getInformation();
}
$view = Piwik_View::factory('manage');
$view->pluginsName = $plugins;
$this->setGeneralVariablesView($view);
$view->menu = Piwik_GetAdminMenu();
if(!Zend_Registry::get('config')->isFileWritable())
{
$view->configFileNotWritable = true;
}
echo $view->render();
}
function deactivate()
{
Piwik::checkUserIsSuperUser();
$this->checkTokenInUrl();
$pluginName = Piwik_Common::getRequestVar('pluginName', null, 'string');
Piwik_PluginsManager::getInstance()->deactivatePlugin($pluginName);
Piwik_Url::redirectToUrl('index.php?module=CorePluginsAdmin&action=index');
}
function activate()
{
Piwik::checkUserIsSuperUser();
$this->checkTokenInUrl();
$pluginName = Piwik_Common::getRequestVar('pluginName', null, 'string');
Piwik_PluginsManager::getInstance()->activatePlugin($pluginName);
Piwik_Url::redirectToUrl('index.php?module=CorePluginsAdmin&action=index');
}
}
@@ -0,0 +1,41 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: CorePluginsAdmin.php 2264 2010-06-03 16:53:43Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_CorePluginsAdmin
*/
/**
*
* @package Piwik_CorePluginsAdmin
*/
class Piwik_CorePluginsAdmin extends Piwik_Plugin
{
public function getInformation()
{
return array(
'description' => Piwik_Translate('CorePluginsAdmin_PluginDescription'),
'author' => 'Piwik',
'author_homepage' => 'http://piwik.org/',
'version' => Piwik_Version::VERSION,
);
}
function getListHooksRegistered()
{
return array('AdminMenu.add' => 'addMenu');
}
function addMenu()
{
Piwik_AddAdminMenu('CorePluginsAdmin_MenuPlugins',
array('module' => 'CorePluginsAdmin', 'action' => 'index'),
Piwik::isUserIsSuperUser(),
$order = 7);
}
}
@@ -0,0 +1,53 @@
{assign var=showSitesSelection value=false}
{assign var=showPeriodSelection value=false}
{include file="CoreAdminHome/templates/header.tpl"}
<div style="max-width:980px;">
<h2>{'CorePluginsAdmin_PluginsManagement'|translate}</h2>
<p>{'CorePluginsAdmin_MainDescription'|translate}</p>
<table class="adminTable">
<thead>
<tr>
<th>{'CorePluginsAdmin_Plugin'|translate}</th>
<th class="num">{'CorePluginsAdmin_Version'|translate}</th>
<th>{'CorePluginsAdmin_Description'|translate}</th>
<th class="status">{'CorePluginsAdmin_Status'|translate}</th>
<th class="action-links">{'CorePluginsAdmin_Action'|translate}</th>
</tr>
</thead>
<tbody id="plugins">
{foreach from=$pluginsName key=name item=plugin}
{if !$plugin.alwaysActivated}
<tr class={if $plugin.activated}"active"{else}"deactivate"{/if}>
<td class="name">
{if isset($plugin.info.homepage)}<a title="{'CorePluginsAdmin_PluginHomepage'|translate}" href="{$plugin.info.homepage}">{/if}
{$name}
{if isset($plugin.info.homepage)}</a>{/if}
</td>
<td class="vers">{$plugin.info.version}</td>
<td class="desc">
{$plugin.info.description|nl2br}
&nbsp;<cite>By
{if isset($plugin.info.author_homepage)}<a title="Author Homepage" href="misc/redirectToUrl.php?url={$plugin.info.author_homepage}">{/if}
{$plugin.info.author}{if isset($plugin.info.author_homepage)}</a>{/if}.</cite>
</td>
<td class="status">
{if $plugin.alwaysActivated}<span title="{'CorePluginsAdmin_ActivatedHelp'|translate}" class="active">{'CorePluginsAdmin_Active'|translate}</span>
{elseif $plugin.activated}{'CorePluginsAdmin_Active'|translate}
{else}{'CorePluginsAdmin_Inactive'|translate}{/if}
</td>
<td class="togl action-links" {if $plugin.alwaysActivated}title="{'CorePluginsAdmin_ActivatedHelp'|translate}"{/if}>
{if $plugin.alwaysActivated} <center>-</center>
{elseif $plugin.activated}<a href='index.php?module=CorePluginsAdmin&action=deactivate&pluginName={$name}&token_auth={$token_auth}'>{'CorePluginsAdmin_Deactivate'|translate}</a>
{else}<a href='index.php?module=CorePluginsAdmin&action=activate&pluginName={$name}&token_auth={$token_auth}'>{'CorePluginsAdmin_Activate'|translate}</a>{/if}
</td>
</tr>
{/if}
{/foreach}
</tbody>
</table>
</div>
{include file="CoreAdminHome/templates/footer.tpl"}
@@ -0,0 +1,334 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Controller.php 2275 2010-06-04 23:59:08Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_CoreUpdater
*/
/**
*
* @package Piwik_CoreUpdater
*/
class Piwik_CoreUpdater_Controller extends Piwik_Controller
{
const CONFIG_FILE_BACKUP = '/config/global.ini.auto-backup-before-update.php';
const PATH_TO_EXTRACT_LATEST_VERSION = '/tmp/latest';
const LATEST_PIWIK_URL = 'http://piwik.org/latest.zip';
private $coreError = false;
private $warningMessages = array();
private $errorMessages = array();
private $deactivatedPlugins = array();
public function newVersionAvailable()
{
Piwik::checkUserIsSuperUser();
$newVersion = $this->checkNewVersionIsAvailableOrDie();
$view = Piwik_View::factory('update_new_version_available');
$view->piwik_version = Piwik_Version::VERSION;
$view->piwik_new_version = $newVersion;
echo $view->render();
}
public function oneClickUpdate()
{
Piwik::checkUserIsSuperUser();
$this->checkNewVersionIsAvailableOrDie();
Piwik::setMaxExecutionTime(0);
$steps = array(
array('oneClick_Download', Piwik_Translate('CoreUpdater_DownloadingUpdateFromX', self::LATEST_PIWIK_URL)),
array('oneClick_Unpack', Piwik_Translate('CoreUpdater_UnpackingTheUpdate')),
array('oneClick_Verify', Piwik_Translate('CoreUpdater_VerifyingUnpackedFiles')),
array('oneClick_CreateConfigFileBackup', Piwik_Translate('CoreUpdater_CreatingBackupOfConfigurationFile', self::CONFIG_FILE_BACKUP)),
array('oneClick_Copy', Piwik_Translate('CoreUpdater_InstallingTheLatestVersion')),
array('oneClick_Finished', Piwik_Translate('CoreUpdater_PiwikUpdatedSuccessfully')),
);
$errorMessage = false;
$messages = array();
foreach($steps as $step) {
try {
$method = $step[0];
$message = $step[1];
$this->$method();
$messages[] = $message;
} catch(Exception $e) {
$errorMessage = $e->getMessage();
break;
}
}
$view = Piwik_View::factory('update_one_click_done');
$view->coreError = $errorMessage;
$view->feedbackMessages = $messages;
echo $view->render();
}
private function checkNewVersionIsAvailableOrDie()
{
$newVersion = Piwik_UpdateCheck::isNewestVersionAvailable();
if(!$newVersion)
{
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionAlreadyLatestVersion', Piwik_Version::VERSION));
}
return $newVersion;
}
private function oneClick_Download()
{
$this->pathPiwikZip = PIWIK_USER_PATH . self::PATH_TO_EXTRACT_LATEST_VERSION . '/latest.zip';
Piwik::checkDirectoriesWritableOrDie( array(self::PATH_TO_EXTRACT_LATEST_VERSION) );
// we catch exceptions in the caller (i.e., oneClickUpdate)
$fetched = Piwik_Http::fetchRemoteFile(self::LATEST_PIWIK_URL, $this->pathPiwikZip);
}
private function oneClick_Unpack()
{
require_once PIWIK_INCLUDE_PATH . '/libs/PclZip/pclzip.lib.php';
$archive = new PclZip($this->pathPiwikZip);
$pathExtracted = PIWIK_USER_PATH . self::PATH_TO_EXTRACT_LATEST_VERSION;
if ( false == ($archive_files = $archive->extract(
PCLZIP_OPT_PATH, $pathExtracted)) )
{
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionArchiveIncompatible', $archive->errorInfo(true)));
}
if ( 0 == count($archive_files) )
{
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionArchiveEmpty'));
}
unlink($this->pathPiwikZip);
$this->pathRootExtractedPiwik = $pathExtracted . '/piwik';
}
private function oneClick_Verify()
{
$someExpectedFiles = array(
'/config/global.ini.php',
'/index.php',
'/core/Piwik.php',
'/piwik.php',
'/plugins/API/API.php'
);
foreach($someExpectedFiles as $file)
{
if(!is_file($this->pathRootExtractedPiwik . $file))
{
throw new Exception(Piwik_TranslateException('CoreUpdater_ExceptionArchiveIncomplete', $file));
}
}
}
private function oneClick_CreateConfigFileBackup()
{
$configFileBefore = PIWIK_USER_PATH . '/config/global.ini.php';
$configFileAfter = PIWIK_USER_PATH . self::CONFIG_FILE_BACKUP;
Piwik::copy($configFileBefore, $configFileAfter);
}
private function oneClick_Copy()
{
/*
* Overwrite the downloaded robots.txt with our local copy
*/
Piwik::copy(PIWIK_DOCUMENT_ROOT . '/robots.txt', $this->pathRootExtractedPiwik . '/robots.txt');
/*
* Copy all files to PIWIK_INCLUDE_PATH.
* These files are accessed through the dispatcher.
*/
Piwik::copyRecursive($this->pathRootExtractedPiwik, PIWIK_INCLUDE_PATH);
/*
* These files are visible in the web root and are generally
* served directly by the web server. May be shared.
*/
if(PIWIK_INCLUDE_PATH !== PIWIK_DOCUMENT_ROOT)
{
/*
* Copy PHP files that expect to be in the document root
*/
$specialCases = array(
'/index.php',
'/piwik.php',
'/js/index.php',
);
foreach($specialCases as $file)
{
Piwik::copy($this->pathRootExtractedPiwik . $file, PIWIK_DOCUMENT_ROOT . $file);
}
/*
* Copy the non-PHP files (e.g., images, css, javascript)
*/
Piwik::copyRecursive($this->pathRootExtractedPiwik, PIWIK_DOCUMENT_ROOT, true);
}
/*
* Config files may be user (account) specific
*/
if(PIWIK_INCLUDE_PATH !== PIWIK_USER_PATH)
{
Piwik::copyRecursive($this->pathRootExtractedPiwik . '/config', PIWIK_USER_PATH . '/config');
}
Piwik::unlinkRecursive($this->pathRootExtractedPiwik, true);
}
private function oneClick_Finished()
{
}
public function index()
{
$language = Piwik_Common::getRequestVar('language', '');
if(!empty($language))
{
Piwik_LanguagesManager_API::getInstance()->setLanguageForSession($language);
}
$this->runUpdaterAndExit();
}
protected function runUpdaterAndExit()
{
$updater = new Piwik_Updater();
$componentsWithUpdateFile = Piwik_CoreUpdater::getComponentUpdates($updater);
if(empty($componentsWithUpdateFile))
{
Piwik::redirectToModule('CoreHome');
}
Piwik::setMaxExecutionTime(0);
if(Piwik_Common::isPhpCliMode())
{
$view = Piwik_View::factory('update_welcome');
$this->doWelcomeUpdates($view, $componentsWithUpdateFile);
if(!$this->coreError)
{
$view = Piwik_View::factory('update_database_done');
$this->doExecuteUpdates($view, $updater, $componentsWithUpdateFile);
}
}
else if(Piwik_Common::getRequestVar('updateCorePlugins', 0, 'integer') == 1)
{
$this->warningMessages = array();
$view = Piwik_View::factory('update_database_done');
$this->doExecuteUpdates($view, $updater, $componentsWithUpdateFile);
}
else
{
$view = Piwik_View::factory('update_welcome');
$view->queries = $updater->getSqlQueriesToExecute();
$this->doWelcomeUpdates($view, $componentsWithUpdateFile);
}
exit;
}
private function doWelcomeUpdates($view, $componentsWithUpdateFile)
{
$view->new_piwik_version = Piwik_Version::VERSION;
$view->commandUpgradePiwik = "<br /><code>php ".Piwik_Common::getPathToPiwikRoot()."/index.php -- \"module=CoreUpdater\" </code>";
$pluginNamesToUpdate = array();
$coreToUpdate = false;
// handle case of existing database with no tables
if(!Piwik::isInstalled())
{
$this->errorMessages[] = Piwik_Translate('CoreUpdater_EmptyDatabaseError', Zend_Registry::get('config')->database->dbname);
$this->coreError = true;
$currentVersion = 'N/A';
}
else
{
$this->errorMessages = array();
try {
$currentVersion = Piwik_GetOption('version_core');
} catch( Exception $e) {
$currentVersion = '<= 0.2.9';
}
foreach($componentsWithUpdateFile as $name => $filenames)
{
if($name == 'core')
{
$coreToUpdate = true;
}
else
{
$pluginNamesToUpdate[] = $name;
}
}
}
// check file integrity
$integrityInfo = Piwik::getFileIntegrityInformation();
if(isset($integrityInfo[1]))
{
if($integrityInfo[0] == false)
{
$this->warningMessages[] = '<b>'.Piwik_Translate('General_FileIntegrityWarningExplanation').'</b>';
}
$this->warningMessages = array_merge($this->warningMessages, array_slice($integrityInfo, 1));
}
$view->coreError = $this->coreError;
$view->warningMessages = $this->warningMessages;
$view->errorMessages = $this->errorMessages;
$view->current_piwik_version = $currentVersion;
$view->pluginNamesToUpdate = $pluginNamesToUpdate;
$view->coreToUpdate = $coreToUpdate;
$view->clearCompiledTemplates();
echo $view->render();
}
private function doExecuteUpdates($view, $updater, $componentsWithUpdateFile)
{
$this->loadAndExecuteUpdateFiles($updater, $componentsWithUpdateFile);
$view->coreError = $this->coreError;
$view->warningMessages = $this->warningMessages;
$view->errorMessages = $this->errorMessages;
$view->deactivatedPlugins = $this->deactivatedPlugins;
$view->clearCompiledTemplates();
echo $view->render();
}
private function loadAndExecuteUpdateFiles($updater, $componentsWithUpdateFile)
{
// if error in any core update, show message + help message + EXIT
// if errors in any plugins updates, show them on screen, disable plugins that errored + CONTINUE
// if warning in any core update or in any plugins update, show message + CONTINUE
// if no error or warning, success message + CONTINUE
foreach($componentsWithUpdateFile as $name => $filenames)
{
try {
$this->warningMessages = array_merge($this->warningMessages, $updater->update($name));
} catch (Piwik_Updater_UpdateErrorException $e) {
$this->errorMessages[] = $e->getMessage();
if($name == 'core')
{
$this->coreError = true;
break;
}
else
{
Piwik_PluginsManager::getInstance()->deactivatePlugin($name);
$this->deactivatedPlugins[] = $name;
}
}
}
}
}
@@ -0,0 +1,71 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: CoreUpdater.php 2264 2010-06-03 16:53:43Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_CoreUpdater
*/
/**
*
* @package Piwik_CoreUpdater
*/
class Piwik_CoreUpdater extends Piwik_Plugin
{
public function getInformation()
{
return array(
'description' => Piwik_Translate('CoreUpdater_PluginDescription'),
'author' => 'Piwik',
'author_homepage' => 'http://piwik.org/',
'version' => Piwik_Version::VERSION,
);
}
function getListHooksRegistered()
{
$hooks = array(
'FrontController.dispatchCoreAndPluginUpdatesScreen' => 'dispatch',
'FrontController.checkForUpdates' => 'updateCheck',
);
return $hooks;
}
public static function getComponentUpdates($updater)
{
$updater->addComponentToCheck('core', Piwik_Version::VERSION);
$plugins = Piwik_PluginsManager::getInstance()->getLoadedPlugins();
foreach($plugins as $pluginName => $plugin)
{
$updater->addComponentToCheck($pluginName, $plugin->getVersion());
}
$componentsWithUpdateFile = $updater->getComponentsWithUpdateFile();
if(count($componentsWithUpdateFile) == 0 && !$updater->hasNewVersion('core'))
{
return null;
}
return $componentsWithUpdateFile;
}
function dispatch()
{
$module = Piwik_Common::getRequestVar('module', '', 'string');
$updater = new Piwik_Updater();
if(self::getComponentUpdates($updater) !== null && $module != 'CoreUpdater')
{
Piwik::redirectToModule('CoreUpdater');
}
}
function updateCheck()
{
Piwik_UpdateCheck::check();
}
}
@@ -0,0 +1,62 @@
{textformat}
{assign var='helpMessage' value='CoreUpdater_HelpMessageContent'|translate:'[':']':"\n\n* "|unescape}
{if $coreError}
[X] {'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'|translate|unescape}
{foreach from=$errorMessages item=message}
* {$message}
{/foreach}
{'CoreUpdater_HelpMessageIntroductionWhenError'|translate|unescape}
* {$helpMessage}
{'CoreUpdater_ErrorDIYHelp'|translate}
* {'CoreUpdater_ErrorDIYHelp_1'|translate}
* {'CoreUpdater_ErrorDIYHelp_2'|translate}
* {'CoreUpdater_ErrorDIYHelp_3'|translate}
* {'CoreUpdater_ErrorDIYHelp_4'|translate}
* {'CoreUpdater_ErrorDIYHelp_5'|translate}
{else}
{if count($warningMessages) > 0}
[!] {'CoreUpdater_WarningMessages'|translate|unescape}
{foreach from=$warningMessages item=message}
* {$message}
{/foreach}
{/if}
{if count($errorMessages) > 0}
[X] {'CoreUpdater_ErrorDuringPluginsUpdates'|translate|unescape}
{foreach from=$errorMessages item=message}
* {$message}
{/foreach}
{if isset($deactivatedPlugins) && count($deactivatedPlugins) > 0}
{assign var=listOfDeactivatedPlugins value=$deactivatedPlugins|@implode:', '}
[!] {'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins'|translate:$listOfDeactivatedPlugins|unescape}
{/if}
{/if}
{if count($errorMessages) > 0 || count($warningMessages) > 0}
{'CoreUpdater_HelpMessageIntroductionWhenWarning'|translate|unescape}
* {$helpMessage}
{else}
{'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'|translate|unescape}
{/if}
{/if}
{/textformat}
@@ -0,0 +1,36 @@
{assign var='helpMessage' value='CoreUpdater_HelpMessageContent'|translate:'[':']':"\n\n* "|unescape}
{textformat}
*** {'CoreUpdater_UpdateTitle'|translate|unescape} ***
{if $coreError}
[X] {'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'|translate|unescape}
{foreach from=$errorMessages item=message}
* {$message}
{/foreach}
{'CoreUpdater_HelpMessageIntroductionWhenError'|translate|unescape}
* {$helpMessage}
{else}
{if $coreToUpdate || count($pluginNamesToUpdate) > 0}
{'CoreUpdater_DatabaseUpgradeRequired'|translate|unescape}
{'CoreUpdater_YourDatabaseIsOutOfDate'|translate|unescape}
{if $coreToUpdate}
{'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY'|translate:$current_piwik_version:$new_piwik_version|unescape}
{/if}
{if count($pluginNamesToUpdate) > 0}
{assign var=listOfPlugins value=$pluginNamesToUpdate|@implode:', '}
{'CoreUpdater_TheFollowingPluginsWillBeUpgradedX'|translate:$listOfPlugins|unescape}
{/if}
{'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient'|translate|unescape}
{/if}
{/if}
{/textformat}
@@ -0,0 +1,3 @@
</div>
</body>
</html>
@@ -0,0 +1,32 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Piwik &rsaquo; {'CoreUpdater_UpdateTitle'|translate}</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="shortcut icon" href="plugins/CoreHome/templates/images/favicon.ico" />
<link rel="stylesheet" type="text/css" href="themes/default/simple_structure.css" />
<link rel="stylesheet" type="text/css" href="libs/jquery/themes/base/jquery-ui.css" class="ui-theme" />
{literal}
<style>
* {
margin: 0;
padding: 0;
}
.topBarElem {
font-family:arial,sans-serif !important;
font-size:13px;
line-height:1.33;
}
</style>
{/literal}
{postEvent name="template_css_import"}
<script type="text/javascript" src="libs/jquery/jquery.js"></script>
<script type="text/javascript" src="libs/jquery/jquery-ui.js"></script>
<script type="text/javascript" src="libs/jquery/fdd2div-modified.js"></script>
</head>
<body>
<div id="content">
<div id="title"><span id="h1">Piwik </span><span id="subh1"> # {'General_OpenSourceWebAnalytics'|translate}</span></div>
@@ -0,0 +1,61 @@
{include file="CoreUpdater/templates/header.tpl"}
{assign var='helpMessage' value='CoreUpdater_HelpMessageContent'|translate:'<a target="_blank" href="misc/redirectToUrl.php?url=http://piwik.org/faq/">':'</a>':'</li><li>'}
{if $coreError}
<br /><br />
<div class="error">
<img src="themes/default/images/error_medium.png" /> {'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'|translate}
{foreach from=$errorMessages item=message}
<pre>{$message}</pre><br />
{/foreach}
</div>
<br />
<p>{'CoreUpdater_HelpMessageIntroductionWhenError'|translate}
<ul><li>{$helpMessage}</li></ul></p>
<p>{'CoreUpdater_ErrorDIYHelp'|translate}
<ul><li>{'CoreUpdater_ErrorDIYHelp_1'|translate}</li>
<li>{'CoreUpdater_ErrorDIYHelp_2'|translate}</li>
<li>{'CoreUpdater_ErrorDIYHelp_3'|translate}</li>
<li>{'CoreUpdater_ErrorDIYHelp_4'|translate}</li>
<li>{'CoreUpdater_ErrorDIYHelp_5'|translate}</li></ul></p>
{else}
{if count($warningMessages) > 0}
<div class="warning">
<p><img src="themes/default/images/warning_medium.png" /> {'CoreUpdater_WarningMessages'|translate}</p>
{foreach from=$warningMessages item=message}
<pre>{$message}</pre><br />
{/foreach}
</div>
{/if}
{if count($errorMessages) > 0}
<div class="warning">
<p><img src="themes/default/images/warning_medium.png" /> {'CoreUpdater_ErrorDuringPluginsUpdates'|translate}</p>
{foreach from=$errorMessages item=message}
<pre>{$message}</pre><br />
{/foreach}
{if isset($deactivatedPlugins) && count($deactivatedPlugins) > 0}
{assign var=listOfDeactivatedPlugins value=$deactivatedPlugins|@implode:', '}
<p style="color:red"><img src="themes/default/images/error_medium.png" /> {'CoreUpdater_WeAutomaticallyDeactivatedTheFollowingPlugins'|translate:$listOfDeactivatedPlugins}</p>
{/if}
</div>
{/if}
{if count($errorMessages) > 0 || count($warningMessages) > 0}
<br />
<p>{'CoreUpdater_HelpMessageIntroductionWhenWarning'|translate}
<ul><li>{$helpMessage}</li></ul>
</p>
{else}
<p class="success">{'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'|translate}</p>
{/if}
<form action="index.php">
<input type="submit" class="submit" value="{'CoreUpdater_ContinueToPiwik'|translate}" />
</form>
{/if}
{include file="CoreUpdater/templates/footer.tpl"}
@@ -0,0 +1,15 @@
{include file="CoreUpdater/templates/header.tpl"}
<p><b>{'CoreUpdater_ThereIsNewVersionAvailableForUpdate'|translate}</b></p>
<p>{'CoreUpdater_YouCanUpgradeAutomaticallyOrDownloadPackage'|translate:$piwik_new_version}</p>
<br />
<form action="index.php">
<input type="hidden" name="module" value="CoreUpdater" />
<input type="hidden" name="action" value="oneClickUpdate" />
<input type="submit" class="submit" value="{'CoreUpdater_UpdateAutomatically'|translate}" />
<a style="margin-left:50px" class="submit button" href="http://piwik.org/latest.zip">{'CoreUpdater_DownloadX'|translate:$piwik_new_version}</a>
</form>
<br />
<a href='index.php'>&laquo; {'General_BackToPiwik'|translate}</a>
{include file="CoreUpdater/templates/footer.tpl"}
@@ -0,0 +1,18 @@
{include file="CoreUpdater/templates/header.tpl"}
{foreach from=$feedbackMessages item=message}
<p>{$message}</p>
{/foreach}
{if $coreError}
<br /><br />
<div class="error"><img src="themes/default/images/error_medium.png" /> {$coreError}</div>
<br /><br />
<div class="warning"><img src="themes/default/images/warning_medium.png" /> {'CoreUpdater_UpdateHasBeenCancelledExplanation'|translate:"<br /><br />":"<a target='_blank' href='misc/redirectToUrl.php?url=http://piwik.org/docs/update/'>":"</a>"}</div>
<br /><br />
{/if}
<form action="index.php">
<input type="submit" class="submit" value="{'CoreUpdater_ContinueToPiwik'|translate}" />
</form>
{include file="CoreUpdater/templates/footer.tpl"}
@@ -0,0 +1,99 @@
{include file="CoreUpdater/templates/header.tpl"}
<span style="float:right">{postEvent name="template_topBar"}</span>
{assign var='helpMessage' value='CoreUpdater_HelpMessageContent'|translate:'<a target="_blank" href="misc/redirectToUrl.php?url=http://piwik.org/faq/">':'</a>':'</li><li>'}
{if $coreError}
<br /><br />
<div class="error">
<img src="themes/default/images/error_medium.png" /> {'CoreUpdater_CriticalErrorDuringTheUpgradeProcess'|translate}
{foreach from=$errorMessages item=message}
<pre>{$message}</pre>
{/foreach}
</div>
<br />
<p>{'CoreUpdater_HelpMessageIntroductionWhenError'|translate}
<ul><li>{$helpMessage}</li></ul></p>
{else}
{if $coreToUpdate || count($pluginNamesToUpdate) > 0}
<p style='font-size:110%;padding-top:1em;'><b>{'CoreUpdater_DatabaseUpgradeRequired'|translate}</b></p>
<p>{'CoreUpdater_YourDatabaseIsOutOfDate'|translate}</p>
{if $coreToUpdate}
<p>{'CoreUpdater_PiwikWillBeUpgradedFromVersionXToVersionY'|translate:$current_piwik_version:$new_piwik_version}</p>
{/if}
{if count($pluginNamesToUpdate) > 0}
{assign var=listOfPlugins value=$pluginNamesToUpdate|@implode:', '}
<p>{'CoreUpdater_TheFollowingPluginsWillBeUpgradedX'|translate:$listOfPlugins}</p>
{/if}
<p><strong>{'CoreUpdater_NoteForLargePiwikInstances'|translate}</strong></p>
<ul>
<li>{'CoreUpdater_TheUpgradeProcessMayFailExecuteCommand'|translate:$commandUpgradePiwik}</li>
<li>{'CoreUpdater_YouCouldManuallyExecuteSqlQueries'|translate}<br />
<a href='#' id='showSql' style='margin-left:20px'> {'CoreUpdater_ClickHereToViewSqlQueries'|translate}</a>
<div id='sqlQueries' style='display:none'>
<br />
<code>
# {'CoreUpdater_NoteItIsExpectedThatQueriesFail'|translate}<br /><br />
{foreach from=$queries item=query}&nbsp;&nbsp;&nbsp;{$query}<br />
{/foreach}
</code>
</div>
<br /><br />
<p><strong>{'CoreUpdater_ReadyToGo'|translate}</strong></p>
<p>{'CoreUpdater_TheUpgradeProcessMayTakeAWhilePleaseBePatient'|translate}</p>
{/if}
{if count($warningMessages) > 0}
<p><i>{$warningMessages[0]}</i>
{if count($warningMessages) > 1}
<button id="more-results" class="ui-button ui-state-default ui-corner-all">{'General_Details'|translate}</button>
{/if}
</p>
{/if}
{if $coreToUpdate || count($pluginNamesToUpdate) > 0}
<br />
<form action="index.php">
<input type="hidden" name="updateCorePlugins" value="1" />
<input type="submit" class="submit" value="{'CoreUpdater_UpgradePiwik'|translate}" />
</form>
{else}
{if count($warningMessages) == 0}
<p class="success">{'CoreUpdater_PiwikHasBeenSuccessfullyUpgraded'|translate}</p>
{/if}
<br />
<form action="index.php">
<input type="submit" class="submit" value="{'CoreUpdater_ContinueToPiwik'|translate}" />
</form>
{/if}
{/if}
{include file="Installation/templates/integrityDetails.tpl"}
{literal}
<style>
code {
background-color:#F0F7FF;
border-color:#00008B;
border-style:dashed dashed dashed solid;
border-width:1px 1px 1px 5px;
direction:ltr;
display:block;
margin:2px 2px 20px;
padding:4px;
text-align:left;
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$('#showSql').click( function () {
$('#sqlQueries').toggle();
});
});
</script>
{/literal}
{include file="CoreUpdater/templates/footer.tpl"}
@@ -0,0 +1,223 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Controller.php 2352 2010-06-22 22:42:37Z matt $
*
* @category Piwik_Plugins
* @package Piwik_Dashboard
*/
/**
*
* @package Piwik_Dashboard
*/
class Piwik_Dashboard_Controller extends Piwik_Controller
{
protected function getDashboardView($template)
{
$view = Piwik_View::factory($template);
$this->setGeneralVariablesView($view);
$view->availableWidgets = json_encode(Piwik_GetWidgetsList());
$layout = $this->getLayout();
if(empty($layout)) {
$layout = $this->getDefaultLayout();
}
$view->layout = $layout;
return $view;
}
public function embeddedIndex()
{
$view = $this->getDashboardView('index');
echo $view->render();
}
public function index()
{
$view = $this->getDashboardView('standalone');
echo $view->render();
}
/**
* Records the layout in the DB for the given user.
*
* @param string $login
* @param int $idDashboard
* @param string $layout
*/
protected function saveLayoutForUser( $login, $idDashboard, $layout)
{
$paramsBind = array($login, $idDashboard, $layout, $layout);
Piwik_Query('INSERT INTO '.Piwik_Common::prefixTable('user_dashboard') .
' (login, iddashboard, layout)
VALUES (?,?,?)
ON DUPLICATE KEY UPDATE layout=?',
$paramsBind);
}
/**
* Returns the layout in the DB for the given user, or false if the layout has not been set yet.
* Parameters must be checked BEFORE this function call
*
* @param string $login
* @param int $idDashboard
* @param string|false $layout
*/
protected function getLayoutForUser( $login, $idDashboard)
{
$paramsBind = array($login, $idDashboard);
$return = Piwik_FetchAll('SELECT layout FROM '.Piwik_Common::prefixTable('user_dashboard') .
' WHERE login = ? AND iddashboard = ?', $paramsBind);
if(count($return) == 0)
{
return false;
}
return $return[0]['layout'];
}
/**
* Saves the layout for the current user
* anonymous = in the session
* authenticated user = in the DB
*/
public function saveLayout()
{
$this->checkTokenInUrl();
$layout = Piwik_Common::getRequestVar('layout');
$idDashboard = Piwik_Common::getRequestVar('idDashboard', 1, 'int' );
$currentUser = Piwik::getCurrentUserLogin();
if($currentUser == 'anonymous')
{
$session = new Zend_Session_Namespace("Piwik_Dashboard");
$session->dashboardLayout = $layout;
}
else
{
$this->saveLayoutForUser($currentUser,$idDashboard, $layout);
}
}
/**
* Get the dashboard layout for the current user (anonymous or loggued user)
*
* @return string $layout
*/
protected function getLayout()
{
$idDashboard = Piwik_Common::getRequestVar('idDashboard', 1, 'int' );
$currentUser = Piwik::getCurrentUserLogin();
if($currentUser == 'anonymous')
{
$session = new Zend_Session_Namespace("Piwik_Dashboard");
if(!isset($session->dashboardLayout))
{
return false;
}
$layout = $session->dashboardLayout;
}
else
{
$layout = $this->getLayoutForUser($currentUser,$idDashboard);
}
// layout was JSON.stringified
$layout = html_entity_decode($layout);
$layout = str_replace("\\\"", "\"", $layout);
// compatibility with the old layout format
if(!empty($layout)
&& strstr($layout, '[[') == false) {
$layout = "'$layout'";
}
$layout = $this->removeDisabledPluginFromLayout($layout);
return $layout;
}
protected function removeDisabledPluginFromLayout($layout)
{
$layout = str_replace("\n", "", $layout);
// if the json decoding works (ie. new Json format)
// we will only return the widgets that are from enabled plugins
if($layoutObject = json_decode($layout, $assoc = false))
{
foreach($layoutObject as &$row)
{
if(!is_array($row))
{
$row = array();
continue;
}
foreach($row as $widgetId => $widget)
{
if(isset($widget->parameters->module)) {
$controllerName = $widget->parameters->module;
$controllerAction = $widget->parameters->action;
if(!Piwik_IsWidgetDefined($controllerName, $controllerAction))
{
unset($row[$widgetId]);
}
}
}
}
$layout = json_encode($layoutObject);
}
return $layout;
}
protected function getDefaultLayout()
{
$defaultLayout = '[
[
{"uniqueId":"widgetVisitsSummarygetEvolutionGraphcolumnsArray","parameters":{"module":"VisitsSummary","action":"getEvolutionGraph","columns":["nb_visits"]}},
{"uniqueId":"widgetVisitorInterestgetNumberOfVisitsPerVisitDuration","parameters":{"module":"VisitorInterest","action":"getNumberOfVisitsPerVisitDuration"}},
{"uniqueId":"widgetUserSettingsgetBrowser","parameters":{"module":"UserSettings","action":"getBrowser"}},
{"uniqueId":"widgetUserCountrygetCountry","parameters":{"module":"UserCountry","action":"getCountry"}},
{"uniqueId":"widgetExampleFeedburnerfeedburner","parameters":{"module":"ExampleFeedburner","action":"feedburner"}}
],
[
{"uniqueId":"widgetReferersgetKeywords","parameters":{"module":"Referers","action":"getKeywords"}},
{"uniqueId":"widgetReferersgetWebsites","parameters":{"module":"Referers","action":"getWebsites"}}
],
[
{"uniqueId":"widgetReferersgetSearchEngines","parameters":{"module":"Referers","action":"getSearchEngines"}},
{"uniqueId":"widgetVisitTimegetVisitInformationPerServerTime","parameters":{"module":"VisitTime","action":"getVisitInformationPerServerTime"}},
{"uniqueId":"widgetExampleRssWidgetrssPiwik","parameters":{"module":"ExampleRssWidget","action":"rssPiwik"}}
]
]';
$defaultLayout = $this->removeDisabledPluginFromLayout($defaultLayout);
return $defaultLayout;
}
}
@@ -0,0 +1,86 @@
<?php
/**
* Piwik - Open source web analytics
*
* @link http://piwik.org
* @license http://www.gnu.org/licenses/gpl-3.0.html Gpl v3 or later
* @version $Id: Dashboard.php 2333 2010-06-22 04:58:13Z vipsoft $
*
* @category Piwik_Plugins
* @package Piwik_Dashboard
*/
/**
* @package Piwik_Dashboard
*/
class Piwik_Dashboard extends Piwik_Plugin
{
public function getInformation()
{
return array(
'description' => Piwik_Translate('Dashboard_PluginDescription'),
'author' => 'Piwik',
'author_homepage' => 'http://piwik.org/',
'version' => Piwik_Version::VERSION,
);
}
public function getListHooksRegistered()
{
return array(
'template_js_import' => 'js',
'template_css_import' => 'css',
'UsersManager.deleteUser' => 'deleteDashboardLayout',
);
}
function js()
{
echo '
<script type="text/javascript" src="plugins/Dashboard/templates/widgetMenu.js"></script>
<script type="text/javascript" src="libs/javascript/json2.js"></script>
<script type="text/javascript" src="plugins/Dashboard/templates/Dashboard.js"></script>
';
}
function css()
{
echo "<link rel=\"stylesheet\" type=\"text/css\" href=\"plugins/Dashboard/templates/dashboard.css\" />\n";
}
function deleteDashboardLayout($notification)
{
$userLogin = $notification->getNotificationObject();
Piwik_Query('DELETE FROM ' . Piwik_Common::prefixTable('user_dashboard') . ' WHERE login = ?', array($userLogin));
}
public function install()
{
// we catch the exception
try{
$sql = "CREATE TABLE ". Piwik_Common::prefixTable('user_dashboard')." (
login VARCHAR( 100 ) NOT NULL ,
iddashboard INT NOT NULL ,
layout TEXT NOT NULL,
PRIMARY KEY ( login , iddashboard )
) DEFAULT CHARSET=utf8 " ;
Piwik_Exec($sql);
} catch(Exception $e){
// mysql code error 1050:table already exists
// see bug #153 http://dev.piwik.org/trac/ticket/153
if(!Zend_Registry::get('db')->isErrNo($e, '1050'))
{
throw $e;
}
}
}
public function uninstall()
{
$sql = "DROP TABLE ". Piwik_Common::prefixTable('user_dashboard') ;
Piwik_Exec($sql);
}
}
Piwik_AddMenu('Dashboard_Dashboard', '', array('module' => 'Dashboard', 'action' => 'embeddedIndex'));
@@ -0,0 +1,253 @@
function dashboard()
{
this.dashboardElement = {};
this.dashboardColumnsElement = {};
this.layout = '';
}
dashboard.prototype =
{
//function called on dashboard initialisation
init: function(layout)
{
var self = this;
//save some often used DOM objects
self.dashboardElement = $('#dashboardWidgetsArea');
self.dashboardColumnsElement = $('.col', self.dashDom);
//dashboard layout
self.layout = layout;
//generate dashboard layout and load every displayed widgets
self.generateLayout();
self.makeSortable();
},
getWidgetsElementsInsideElement: function(elementToSearch)
{
return $('.sortable:not(.dummyItem) .widget', elementToSearch);
},
generateLayout: function()
{
var self = this;
if(typeof self.layout == 'string') {
var layout = {};
//Old dashboard layout format: a string that looks like 'Actions.getActions~Actions.getDownloads|UserCountry.getCountry|Referers.getSearchEngines';
// '|' separate columns
// '~' separate widgets
// '.' separate plugin name from action name
var columns = self.layout.split('|');
for(var columnNumber=0; columnNumber<columns.length; columnNumber++) {
if(columns[columnNumber].length == 0) {
continue;
}
var widgets = columns[columnNumber].split('~');
layout[columnNumber] = {};
for(var j=0; j<widgets.length; j++) {
wid = widgets[j].split('.');
uniqueId = 'widget'+wid[0]+wid[1];
layout[columnNumber][j] = {
"uniqueId": uniqueId,
"parameters": {
"module": wid[0],
"action": wid[1]
}
};
}
}
self.layout = layout;
}
layout = self.layout;
for(var columnNumber in layout) {
var widgetsInColumn = layout[columnNumber];
for(var widgetId in widgetsInColumn) {
widgetParameters = widgetsInColumn[widgetId]["parameters"];
uniqueId = widgetsInColumn[widgetId]["uniqueId"];
if(uniqueId.length>0) {
self.addEmptyWidget(columnNumber, uniqueId, false);
}
}
self.addDummyWidgetAtBottomOfColumn(columnNumber);
}
self.makeSortable();
// load all widgets
$('.widget', self.dashboardElement).each( function() {
var uniqueId = $(this).attr('id');
self.reloadWidget(uniqueId);
});
},
reloadEnclosingWidget: function(domNodeInsideWidget)
{
var uniqueId = $(domNodeInsideWidget).parents('.widget').attr('id');
this.reloadWidget(uniqueId);
},
reloadWidget: function(uniqueId)
{
function onWidgetLoadedReplaceElementWithContent(loadedContent)
{
$('#'+uniqueId+'>.widgetContent', self.dashboardElement).html(loadedContent);
}
widget = widgetsHelper.getWidgetObjectFromUniqueId(uniqueId);
if(widget == false)
{
return;
}
widgetParameters = widget["parameters"];
$.ajax(widgetsHelper.getLoadWidgetAjaxRequest(uniqueId, widgetParameters, onWidgetLoadedReplaceElementWithContent));
},
addDummyWidgetAtBottomOfColumn: function(columnNumber)
{
var self = this;
var columnElement = $(self.dashboardColumnsElement[columnNumber]);
$(columnElement).append(
'<div class="sortable dummyItem">'+
'<div class="widgetTop dummyWidgetTop"></div>'+
'</div>');
},
addEmptyWidget: function(columnNumber, uniqueId, addWidgetOnTop)
{
var self = this;
widgetName = widgetsHelper.getWidgetNameFromUniqueId(uniqueId);
if(widgetName == false) {
widgetName = _pk_translate('Dashboard_WidgetNotFound_js');
}
columnElement = $(self.dashboardColumnsElement[columnNumber]);
emptyWidgetContent = '<div class="sortable">'+
widgetsHelper.getEmptyWidgetHtml(uniqueId, widgetName)+
'</div>';
if(addWidgetOnTop) {
columnElement.prepend(emptyWidgetContent);
} else {
columnElement.append(emptyWidgetContent);
}
widgetElement = $('#'+ uniqueId);
widgetElement
.hover( function() {
$(this).addClass('widgetHover');
$('.widgetTop', this).addClass('widgetTopHover');
$('.button#close', this).show();
}, function() {
$(this).removeClass('widgetHover');
$('.widgetTop', this).removeClass('widgetTopHover');
$('.button#close', this).hide();
});
$('.button#close', widgetElement)
.click( function(ev){
self.onDeleteItem(this, ev);
});
widgetElement.show();
return widgetElement;
},
//apply jquery sortable plugin to the dashboard layout
makeSortable: function()
{
var self = this;
function onStart(event, ui) {
if(!jQuery.support.noCloneEvent) {
$('object', this).hide();
}
}
function onStop(event, ui) {
$('object', this).show();
$('.widgetHover', this).removeClass('widgetHover');
$('.widgetTopHover', this).removeClass('widgetTopHover');
$('.button#close', this).hide();
self.saveLayout();
}
//launch 'sortable' property on every dashboard widgets
self.dashboardElement
.sortable('destroy')
.sortable({
items: 'div.sortable',
opacity: 0.6,
forceHelperSize: true,
forcePlaceholderSize: true,
placeholder: 'hover',
handle: '.widgetTop',
helper: 'clone',
start: onStart,
stop: onStop
});
},
// on mouse click on close widget button
// we ask for confirmation and if 'yes' is clicked, we delete the widget from the dashboard
onDeleteItem: function(target, ev)
{
var self = this;
var question = $('.dialog#confirm');
$('#no', question).click($.unblockUI);
$('#yes', question).click(function() {
var item = $(target).parents('.sortable');
$.unblockUI();
item.fadeOut(200, function() {
$(this).remove();
self.saveLayout();
self.makeSortable();
});
});
$.blockUI({
message: question,
css: { width: '300px', border:'1px solid black' }
});
},
saveLayout: function()
{
var self = this;
// build the layout object to save
var layout = new Array;
var columnNumber = 0;
self.dashboardColumnsElement.each(function() {
layout[columnNumber] = new Array;
var items = self.getWidgetsElementsInsideElement(this);
for(var j=0; j<items.size(); j++) {
widgetElement = items[j];
uniqueId = $(widgetElement).attr('id');
widget = widgetsHelper.getWidgetObjectFromUniqueId(uniqueId);
widgetParameters = widget["parameters"];
layout[columnNumber][j] =
{
"uniqueId": uniqueId,
"parameters": widgetParameters
};
}
columnNumber++;
});
//only save layout if it has changed
layoutString = JSON.stringify(layout);
if(layoutString != JSON.stringify(self.layout)) {
self.layout = layout;
var ajaxRequest =
{
type: 'POST',
url: 'index.php?module=Dashboard&action=saveLayout&token_auth='+piwik.token_auth,
dataType: 'html',
async: true,
error: piwikHelper.ajaxHandleError,
data: { "layout": layoutString }
};
$.ajax(ajaxRequest);
}
}
};
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<dwsync>
<file name="index.tpl" server="hawebs.net//www/hawebs.net/piwik/" local="129229921200000000" remote="129229921200000000" />
<file name="standalone.tpl" server="hawebs.net//www/hawebs.net/piwik/" local="129229921200000000" remote="129229921200000000" />
</dwsync>
@@ -0,0 +1,183 @@
.col {
float: left;
width: 33%;
}
.sortable {
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;
-moz-border-radius:4px;
-webkit-border-radius:4px;
}
.widgetHover {
border: 1px solid #CBD3E7;
}
.widgetContent h2 {
font-size:1.2em;
}
.widgetTop {
background: #F0F0FA;
-moz-border-radius:4px 4px 0 0;
-webkit-border-radius:4px 4px 0 0;
border-bottom: 1px solid #D2D9EB;
width: 100%;
cursor: move;
font-size: 10pt;
font-weight: bold;
padding-bottom: 4px;
}
.widgetTopHover {
background: #E6E6F5;
}
.widgetName {
font-size: 14pt;
margin-left: 25px;
}
.dummyItem {
width: 100%;
height: 150px;
display: block;
visibility:hidden;
}
.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;
}
.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: left;
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;
}
.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;
}
#widgetChooser .widgetTop {
cursor:pointer;
}
@@ -0,0 +1,12 @@
{* 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 xmlns="http://www.w3.org/1999/xhtml">
<head>
{loadJavascriptTranslations plugins='CoreHome Dashboard'}
{include file="CoreHome/templates/js_global_variables.tpl"}
{include file="CoreHome/templates/js_css_includes.tpl"}
<link rel="stylesheet" type="text/css" href="plugins/CoreHome/templates/datatable.css" />
<link rel="stylesheet" type="text/css" href="plugins/Dashboard/templates/dashboard.css" />
</head>
<body>
@@ -0,0 +1,51 @@
{loadJavascriptTranslations plugins='CoreHome Dashboard'}
<script type="text/javascript">
piwik.dashboardLayout = {$layout};
{*
the old dashboard layout style is:
piwik.dashboardLayout = 'VisitsSummary.getEvolutionGraph~VisitorInterest.getNumberOfVisitsPerVisitDuration~UserSettings.getBrowser~ExampleFeedburner.feedburner|Referers.getKeywords~Referers.getWebsites|Referers.getSearchEngines~VisitTime.getVisitInformationPerServerTime~ExampleRssWidget.rssPiwik|';
*}
piwik.availableWidgets = {$availableWidgets};
</script>
{literal}
<script type="text/javascript">
$(document).ready( function() {
piwik.dashboardObject = new dashboard();
var widgetMenuObject = new widgetMenu(piwik.dashboardObject);
piwik.dashboardObject.init(piwik.dashboardLayout);
widgetMenuObject.init();
$('#addWidget.button').click(function(){widgetMenuObject.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>
<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>
@@ -0,0 +1,5 @@
{include file="Dashboard/templates/header.tpl"}
{include file="Dashboard/templates/index.tpl"}
</body>
</html>
@@ -0,0 +1,319 @@
function widgetsHelper()
{
}
widgetsHelper.getWidgetCategoryNameFromUniqueId = function (uniqueId)
{
var widgets = piwik.availableWidgets;
for(var widgetCategory in widgets) {
var widgetInCategory = widgets[widgetCategory];
for(var i in widgetInCategory) {
if(widgetInCategory[i]["uniqueId"] == uniqueId) {
return widgetCategory;
}
}
}
return false;
};
widgetsHelper.getWidgetObjectFromUniqueId = function (uniqueId)
{
var widgets = piwik.availableWidgets;
for(var widgetCategory in widgets) {
var widgetInCategory = widgets[widgetCategory];
for(var i in widgetInCategory) {
if(widgetInCategory[i]["uniqueId"] == uniqueId) {
return widgetInCategory[i];
}
}
}
return false;
};
widgetsHelper.getWidgetNameFromUniqueId = function (uniqueId)
{
widget = this.getWidgetObjectFromUniqueId(uniqueId);
if(widget == false) {
return false;
}
return widget["name"];
};
widgetsHelper.getLoadWidgetAjaxRequest = function (widgetUniqueId, widgetParameters, onWidgetLoadedCallback)
{
var ajaxRequest =
{
widgetUniqueId:widgetUniqueId,
type: 'GET',
url: 'index.php',
dataType: 'html',
async: true,
error: piwikHelper.ajaxHandleError,
success: onWidgetLoadedCallback,
data: piwikHelper.getQueryStringFromParameters(widgetParameters) + "&idSite="+piwik.idSite+"&period="+piwik.period+"&date="+piwik.currentDateString
};
return ajaxRequest;
};
widgetsHelper.getEmptyWidgetHtml = function (uniqueId, widgetName)
{
return '<div id="'+uniqueId+'" class="widget">'+
'<div class="widgetTop">'+
'<div class="button" id="close">'+
'<img src="themes/default/images/close.png" title="'+_pk_translate('Dashboard_Close_js')+'" />'+
'</div>'+
'<div class="widgetName">'+widgetName+'</div>'+
'</div>'+
'<div class="widgetContent">'+
'<div class="widgetLoading">'+
_pk_translate('Dashboard_LoadingWidget_js') +
'</div>'+
'</div>'+
'</div>';
};
// widgetMenu constructor
function widgetMenu(dashboard)
{
this.menu = {};
this.dashboard = dashboard;
}
// widgetMenu object
widgetMenu.prototype =
{
init: function()
{
var self = this;
self.menuElement = $('#widgetChooser');
self.buildMenu();
},
registerCallbackOnWidgetLoad: function( callbackOnWidgetLoad )
{
this.onWidgetLoad = callbackOnWidgetLoad;
},
registerCallbackOnMenuHover: function( callbackOnMenuHover )
{
this.onMenuHover = callbackOnMenuHover;
},
//create DOM elements of the menu
buildMenu: function()
{
var self = this;
var menuWidgetCategories = $('.subMenu#sub1', self.menuElement);
var menuWidgetNames = $('.subMenu#sub2', self.menuElement);
menuWidgetCategories.append('<ol id="menuList"></ol>');
menuWidgetNames.append('<ul id="widgetList"></ul>');
var lineHeight = $('ol', menuWidgetCategories).css('line-height');
lineHeight = Number(lineHeight.substring(0, lineHeight.length-2));
var i=0;
for(var widgetCategory in piwik.availableWidgets) {
var widgets = piwik.availableWidgets[widgetCategory];
for(var j in widgets) {
widgetName = widgets[j]["name"];
widgetUniqueId = widgets[j]["uniqueId"];
widgetParameters = widgets[j]["parameters"];
widgetCategoryId = 'category'+i;
exist = $('.subMenuItem#'+widgetCategoryId, menuWidgetCategories);
if(exist.size() == 0) {
$('ol', menuWidgetCategories)
.append('<li class="subMenuItem" id="'+widgetCategoryId+'">'+
'<span>'+widgetCategory+'</span>'+
'</li>');
$('ul', menuWidgetNames)
.append('<li class="subMenuItem" id="'+widgetCategoryId+'"></li>');
}
// we prepend the ID with "ID" to not conflict with the <div>
// that contains the widget preview and that has the widgetUniqueId already
$('.subMenuItem#'+widgetCategoryId, menuWidgetNames)
.append('<div class="button menuWidgetName" id="'+ 'ID' + widgetUniqueId +'">'+
widgetName +
'</div>')
.css('padding-top', i*lineHeight+'px');
}
i++;
}
$('.subMenuItem', menuWidgetNames).hide();
},
resetMenuState: function ()
{
$('.menuSelected', self.menuElement).removeClass('menuSelected');
$('#sub2 .subMenuItem', self.menuElement).hide();
$('#sub3').empty().html('<div class="widget"></div>');
},
bindEvents: function()
{
var self = this;
if(typeof self.menuInitialized != 'undefined') {
return;
}
self.menuInitialized = true;
// Main menu (widget categories)
$('.subMenu#sub1 .subMenuItem', self.menuElement)
.hover(function() {
self.resetMenuState();
categoryIdHovered = $(this).attr('id');
$('#sub2 #'+categoryIdHovered, self.menuElement).show();
$(this).addClass('menuSelected');
}, function() {}
);
// Sub menu (each widget in the middle column)
$('.menuWidgetName', self.menuElement)
.hover( function() {
if($(this).hasClass('menuDisabled')) {
return;
}
// the ID is prefixed with "ID"
widgetUniqueId = $(this).attr('id').substr(2);
// only reload preview if necessary
if($('#sub3 .widget').attr('id') == widgetUniqueId) {
return;
}
self.expectedWidgetUniqueId = widgetUniqueId;
widget = widgetsHelper.getWidgetObjectFromUniqueId(widgetUniqueId);
widgetParameters = widget['parameters'];
$('.subMenu#sub2 .menuSelected').removeClass('menuSelected');
$(this).addClass('menuSelected');
if(typeof self.onMenuHover != 'undefined') {
self.onMenuHover(widgetUniqueId);
}
emptyWidgetHtml = widgetsHelper.getEmptyWidgetHtml(
widgetUniqueId,
'<div title="'+_pk_translate("Dashboard_AddPreviewedWidget_js")+'">'+
_pk_translate('Dashboard_WidgetPreview_js')+
'</div>'
);
$('#sub3').html(emptyWidgetHtml);
$('#sub3 .widgetTop').click(function() {
self.movePreviewToDashboard();
});
var onWidgetLoadedCallback = function (response) {
if(this.widgetUniqueId != self.expectedWidgetUniqueId) {
return;
}
widgetElement = $('#'+this.widgetUniqueId);
$('.widgetContent', widgetElement).html($(response));
if(typeof self.onWidgetLoad != 'undefined') {
self.onWidgetLoad( widgetUniqueId,
widgetElement
);
}
};
ajaxRequest = widgetsHelper.getLoadWidgetAjaxRequest(widgetUniqueId, widgetParameters, onWidgetLoadedCallback);
$.ajax(ajaxRequest);
}, function() {}
);
},
show: function()
{
var self = this;
if(typeof self.dashboard != 'undefined') {
self.initWidgetMenuForDashboard();
self.filterOutAlreadyLoadedWidget();
$.blockUI({
message: self.menuElement,
centerY: 0,
css: {width:'', top: '5%',left:'10%', right:'10%', margin:"0px", textAlign:'', cursor:'', border:'0px'}
});
}
self.resetMenuState();
self.bindEvents();
},
hideMenu: function()
{
$.unblockUI();
},
filterOutAlreadyLoadedWidget: function()
{
var self = this;
function contains(array, searchElem) {
for(var i=0; i<array.length; i++) {
if (array[i] == searchElem) {
return true;
}
}
return false;
}
var widgets = self.dashboard.getWidgetsElementsInsideElement( self.dashboard.dashboardElement );
var widgetInDashboardUniqueIds = new Array();
for(var i=0; i<widgets.size(); i++) {
widgetInDashboardUniqueIds.push($(widgets[i]).attr('id'));
}
$('.menuWidgetName', self.menuElement).each( function() {
// the ID is prefixed with "ID"
var uniqueId = $(this).attr('id').substr(2);
if(contains(widgetInDashboardUniqueIds, uniqueId)) {
$(this).addClass('menuDisabled');
$(this).attr('title', _pk_translate('Dashboard_TitleWidgetInDashboard_js'));
} else {
$(this).removeClass('menuDisabled');
$(this).attr('title', _pk_translate('Dashboard_TitleClickToAdd_js'));
}
});
},
movePreviewToDashboard: function()
{
var self = this;
if(typeof self.dashboard == 'undefined') {
return;
}
$('#sub3 .widget', self.menuElement).each(function() {
uniqueId = $(this).attr('id');
widgetAddedToDashboard = self.dashboard.addEmptyWidget(0, uniqueId, true);
widgetContentToReplace = $('.widgetContent', widgetAddedToDashboard );
widgetContentLoadedInPreview = $('.widgetContent', this).clone(true);
widgetContentToReplace.replaceWith( widgetContentLoadedInPreview );
});
self.hideMenu();
self.dashboard.makeSortable();
self.dashboard.saveLayout();
},
initWidgetMenuForDashboard: function()
{
var self = this;
if(typeof self.menuInitialized == 'undefined') {
$('.menuWidgetName', self.menuElement)
.click( function() {
if(!$(this).hasClass('menuDisabled')) {
self.movePreviewToDashboard();
}
});
$('.button#hideMenu', self.menuElement)
.click(function() { self.hideMenu(); }
);
$('#closeMenuIcon', self.menuElement)
.click(function() { self.hideMenu(); }
);
$.extend($.blockUI.defaults.overlayCSS, { backgroundColor: '#000000', opacity: '0.4'});
$.extend($.blockUI.defaults,{ fadeIn: 0, fadeOut: 0 });
$(document).keydown( function(e) {
var key = e.keyCode || e.which;
if(key == 27) {
self.hideMenu();
}
});
}
}
};