update Piwik to version 2.16 (fixes #91)
This commit is contained in:
parent
9abe039dc8
commit
47263617c5
45 changed files with 418860 additions and 226988 deletions
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -13,6 +13,7 @@ use Piwik\Common;
|
|||
use Piwik\Date;
|
||||
use Piwik\Db;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Config;
|
||||
use Piwik\Segment;
|
||||
|
||||
/**
|
||||
|
|
@ -22,7 +23,15 @@ use Piwik\Segment;
|
|||
*/
|
||||
class API extends \Piwik\Plugin\API
|
||||
{
|
||||
const DEACTIVATE_SEGMENT_EVENT = 'SegmentEditor.deactivate';
|
||||
/**
|
||||
* @var Model
|
||||
*/
|
||||
private $model;
|
||||
|
||||
public function __construct(Model $model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
protected function checkSegmentValue($definition, $idSite)
|
||||
{
|
||||
|
|
@ -78,18 +87,38 @@ class API extends \Piwik\Plugin\API
|
|||
protected function checkAutoArchive($autoArchive, $idSite)
|
||||
{
|
||||
$autoArchive = (int)$autoArchive;
|
||||
if ($autoArchive) {
|
||||
$exception = new Exception("To prevent abuse, autoArchive=1 requires Super User or ControllerAdmin access.");
|
||||
if (empty($idSite)) {
|
||||
if (!Piwik::hasUserSuperUserAccess()) {
|
||||
throw $exception;
|
||||
}
|
||||
} else {
|
||||
if (!Piwik::isUserHasAdminAccess($idSite)) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
if (!$autoArchive) {
|
||||
return $autoArchive;
|
||||
}
|
||||
|
||||
$exception = new Exception(
|
||||
"Please contact Support to make these changes on your behalf. ".
|
||||
" To modify a pre-processed segment, a user must have admin access or super user access. "
|
||||
);
|
||||
|
||||
// Segment 'All websites' and pre-processed requires Super User
|
||||
if (empty($idSite)) {
|
||||
if (!Piwik::hasUserSuperUserAccess()) {
|
||||
throw $exception;
|
||||
}
|
||||
return $autoArchive;
|
||||
}
|
||||
|
||||
// if real-time segments are disabled, then allow user to create pre-processed report
|
||||
$realTimeSegmentsDisabled = !Config::getInstance()->General['enable_create_realtime_segments'];
|
||||
if($realTimeSegmentsDisabled) {
|
||||
// User is at least view
|
||||
if(!Piwik::isUserHasViewAccess($idSite)) {
|
||||
throw $exception;
|
||||
}
|
||||
return $autoArchive;
|
||||
}
|
||||
|
||||
// pre-processed segment for a given website requires admin access
|
||||
if(!Piwik::isUserHasAdminAccess($idSite)) {
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return $autoArchive;
|
||||
}
|
||||
|
||||
|
|
@ -100,6 +129,7 @@ class API extends \Piwik\Plugin\API
|
|||
if (empty($segment)) {
|
||||
throw new Exception("Requested segment not found");
|
||||
}
|
||||
|
||||
return $segment;
|
||||
}
|
||||
|
||||
|
|
@ -110,12 +140,45 @@ class API extends \Piwik\Plugin\API
|
|||
}
|
||||
}
|
||||
|
||||
protected function checkUserCanModifySegment($segment)
|
||||
protected function checkUserCanAddNewSegment($idSite)
|
||||
{
|
||||
if(Piwik::hasUserSuperUserAccess()) {
|
||||
if (empty($idSite)
|
||||
&& !SegmentEditor::isAddingSegmentsForAllWebsitesEnabled()
|
||||
) {
|
||||
throw new Exception(Piwik::translate('SegmentEditor_AddingSegmentForAllWebsitesDisabled'));
|
||||
}
|
||||
|
||||
if (!$this->isUserCanAddNewSegment($idSite)) {
|
||||
throw new Exception(Piwik::translate('SegmentEditor_YouDontHaveAccessToCreateSegments'));
|
||||
}
|
||||
}
|
||||
|
||||
public function isUserCanAddNewSegment($idSite)
|
||||
{
|
||||
if (Piwik::isUserIsAnonymous()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$requiredAccess = Config::getInstance()->General['adding_segment_requires_access'];
|
||||
|
||||
$authorized =
|
||||
($requiredAccess == 'view' && Piwik::isUserHasViewAccess($idSite)) ||
|
||||
($requiredAccess == 'admin' && Piwik::isUserHasAdminAccess($idSite)) ||
|
||||
($requiredAccess == 'superuser' && Piwik::hasUserSuperUserAccess())
|
||||
;
|
||||
|
||||
return $authorized;
|
||||
}
|
||||
|
||||
protected function checkUserCanEditOrDeleteSegment($segment)
|
||||
{
|
||||
if (Piwik::hasUserSuperUserAccess()) {
|
||||
return;
|
||||
}
|
||||
if($segment['login'] != Piwik::getCurrentUserLogin()) {
|
||||
|
||||
$this->checkUserIsNotAnonymous();
|
||||
|
||||
if ($segment['login'] != Piwik::getCurrentUserLogin()) {
|
||||
throw new Exception($this->getMessageCannotEditSegmentCreatedBySuperUser());
|
||||
}
|
||||
}
|
||||
|
|
@ -128,19 +191,29 @@ class API extends \Piwik\Plugin\API
|
|||
*/
|
||||
public function delete($idSegment)
|
||||
{
|
||||
$this->checkUserIsNotAnonymous();
|
||||
|
||||
$segment = $this->getSegmentOrFail($idSegment);
|
||||
$this->checkUserCanEditOrDeleteSegment($segment);
|
||||
|
||||
$this->checkUserCanModifySegment($segment);
|
||||
/**
|
||||
* Triggered before a segment is deleted or made invisible.
|
||||
*
|
||||
* This event can be used by plugins to throw an exception
|
||||
* or do something else.
|
||||
*
|
||||
* @param int $idSegment The ID of the segment being deleted.
|
||||
*/
|
||||
Piwik::postEvent('SegmentEditor.deactivate', array($idSegment));
|
||||
|
||||
$this->sendSegmentDeactivationEvent($idSegment);
|
||||
$this->getModel()->deleteSegment($idSegment);
|
||||
|
||||
$db = Db::get();
|
||||
$db->delete(Common::prefixTable('segment'), 'idsegment = ' . $idSegment);
|
||||
return true;
|
||||
}
|
||||
|
||||
private function getModel()
|
||||
{
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies an existing stored segment.
|
||||
*
|
||||
|
|
@ -155,20 +228,14 @@ class API extends \Piwik\Plugin\API
|
|||
*/
|
||||
public function update($idSegment, $name, $definition, $idSite = false, $autoArchive = false, $enabledAllUsers = false)
|
||||
{
|
||||
$this->checkUserIsNotAnonymous();
|
||||
$segment = $this->getSegmentOrFail($idSegment);
|
||||
|
||||
$this->checkUserCanModifySegment($segment);
|
||||
$this->checkUserCanEditOrDeleteSegment($segment);
|
||||
|
||||
$idSite = $this->checkIdSite($idSite);
|
||||
$this->checkSegmentName($name);
|
||||
$definition = $this->checkSegmentValue($definition, $idSite);
|
||||
$definition = $this->checkSegmentValue($definition, $idSite);
|
||||
$enabledAllUsers = $this->checkEnabledAllUsers($enabledAllUsers);
|
||||
$autoArchive = $this->checkAutoArchive($autoArchive, $idSite);
|
||||
|
||||
if ($this->segmentVisibilityIsReduced($idSite, $enabledAllUsers, $segment)) {
|
||||
$this->sendSegmentDeactivationEvent($idSegment);
|
||||
}
|
||||
$autoArchive = $this->checkAutoArchive($autoArchive, $idSite);
|
||||
|
||||
$bind = array(
|
||||
'name' => $name,
|
||||
|
|
@ -179,11 +246,18 @@ class API extends \Piwik\Plugin\API
|
|||
'ts_last_edit' => Date::now()->getDatetime(),
|
||||
);
|
||||
|
||||
$db = Db::get();
|
||||
$db->update(Common::prefixTable("segment"),
|
||||
$bind,
|
||||
"idsegment = $idSegment"
|
||||
);
|
||||
/**
|
||||
* Triggered before a segment is modified.
|
||||
*
|
||||
* This event can be used by plugins to throw an exception
|
||||
* or do something else.
|
||||
*
|
||||
* @param int $idSegment The ID of the segment which visibility is reduced.
|
||||
*/
|
||||
Piwik::postEvent('SegmentEditor.update', array($idSegment, $bind));
|
||||
|
||||
$this->getModel()->updateSegment($idSegment, $bind);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -200,14 +274,13 @@ class API extends \Piwik\Plugin\API
|
|||
*/
|
||||
public function add($name, $definition, $idSite = false, $autoArchive = false, $enabledAllUsers = false)
|
||||
{
|
||||
$this->checkUserIsNotAnonymous();
|
||||
$this->checkUserCanAddNewSegment($idSite);
|
||||
$idSite = $this->checkIdSite($idSite);
|
||||
$this->checkSegmentName($name);
|
||||
$definition = $this->checkSegmentValue($definition, $idSite);
|
||||
$enabledAllUsers = $this->checkEnabledAllUsers($enabledAllUsers);
|
||||
$autoArchive = $this->checkAutoArchive($autoArchive, $idSite);
|
||||
|
||||
$db = Db::get();
|
||||
$bind = array(
|
||||
'name' => $name,
|
||||
'definition' => $definition,
|
||||
|
|
@ -218,8 +291,10 @@ class API extends \Piwik\Plugin\API
|
|||
'ts_created' => Date::now()->getDatetime(),
|
||||
'deleted' => 0,
|
||||
);
|
||||
$db->insert(Common::prefixTable("segment"), $bind);
|
||||
return $db->lastInsertId();
|
||||
|
||||
$id = $this->getModel()->createSegment($bind);
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -232,12 +307,12 @@ class API extends \Piwik\Plugin\API
|
|||
public function get($idSegment)
|
||||
{
|
||||
Piwik::checkUserHasSomeViewAccess();
|
||||
|
||||
if (!is_numeric($idSegment)) {
|
||||
throw new Exception("idSegment should be numeric.");
|
||||
}
|
||||
$segment = Db::get()->fetchRow("SELECT * " .
|
||||
" FROM " . Common::prefixTable("segment") .
|
||||
" WHERE idsegment = ?", $idSegment);
|
||||
|
||||
$segment = $this->getModel()->getSegment($idSegment);
|
||||
|
||||
if (empty($segment)) {
|
||||
return false;
|
||||
|
|
@ -255,6 +330,7 @@ class API extends \Piwik\Plugin\API
|
|||
if ($segment['deleted']) {
|
||||
throw new Exception("This segment is marked as deleted. ");
|
||||
}
|
||||
|
||||
return $segment;
|
||||
}
|
||||
|
||||
|
|
@ -274,46 +350,51 @@ class API extends \Piwik\Plugin\API
|
|||
|
||||
$userLogin = Piwik::getCurrentUserLogin();
|
||||
|
||||
$model = new Model();
|
||||
if (empty($idSite)) {
|
||||
$segments = $model->getAllSegments($userLogin);
|
||||
$model = $this->getModel();
|
||||
if(Piwik::hasUserSuperUserAccess()) {
|
||||
$segments = $model->getAllSegmentsForAllUsers($idSite);
|
||||
} else {
|
||||
$segments = $model->getAllSegmentsForSite($idSite, $userLogin);
|
||||
if (empty($idSite)) {
|
||||
$segments = $model->getAllSegments($userLogin);
|
||||
} else {
|
||||
$segments = $model->getAllSegmentsForSite($idSite, $userLogin);
|
||||
}
|
||||
}
|
||||
|
||||
$segments = $this->sortSegmentsCreatedByUserFirst($segments);
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* When deleting or making a segment invisible, allow plugins to throw an exception or propagate the action
|
||||
* Sorts segment in a particular order:
|
||||
*
|
||||
* @param $idSegment
|
||||
* 1) my segments
|
||||
* 2) segments created by the super user that were shared with all users
|
||||
* 3) segments created by other users (which are visible to all super users)
|
||||
*
|
||||
* @param $segments
|
||||
* @return array
|
||||
*/
|
||||
private function sendSegmentDeactivationEvent($idSegment)
|
||||
private function sortSegmentsCreatedByUserFirst($segments)
|
||||
{
|
||||
/**
|
||||
* Triggered before a segment is deleted or made invisible.
|
||||
*
|
||||
* This event can be used by plugins to throw an exception
|
||||
* or do something else.
|
||||
*
|
||||
* @param int $idSegment The ID of the segment being deleted.
|
||||
*/
|
||||
Piwik::postEvent(self::DEACTIVATE_SEGMENT_EVENT, array($idSegment));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $idSiteNewValue
|
||||
* @param $enableAllUserNewValue
|
||||
* @param $segment
|
||||
* @return bool
|
||||
*/
|
||||
private function segmentVisibilityIsReduced($idSiteNewValue, $enableAllUserNewValue, $segment)
|
||||
{
|
||||
$allUserVisibilityIsDropped = $segment['enable_all_users'] && !$enableAllUserNewValue;
|
||||
$allWebsiteVisibilityIsDropped = !isset($segment['idSite']) && $idSiteNewValue;
|
||||
|
||||
return $allUserVisibilityIsDropped || $allWebsiteVisibilityIsDropped;
|
||||
$orderedSegments = array();
|
||||
foreach($segments as $id => &$segment) {
|
||||
if($segment['login'] == Piwik::getCurrentUserLogin()) {
|
||||
$orderedSegments[] = $segment;
|
||||
unset($segments[$id]);
|
||||
}
|
||||
}
|
||||
foreach($segments as $id => &$segment) {
|
||||
if($segment['enable_all_users'] == 1) {
|
||||
$orderedSegments[] = $segment;
|
||||
unset($segments[$id]);
|
||||
}
|
||||
}
|
||||
foreach($segments as $id => &$segment) {
|
||||
$orderedSegments[] = $segment;
|
||||
}
|
||||
return $orderedSegments;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\SegmentEditor;
|
||||
|
||||
/**
|
||||
*/
|
||||
class Controller extends \Piwik\Plugin\Controller
|
||||
{
|
||||
public function getSelector()
|
||||
{
|
||||
$selector = new SegmentSelectorControl();
|
||||
return $selector->render();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -8,18 +8,37 @@
|
|||
*/
|
||||
namespace Piwik\Plugins\SegmentEditor;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Common;
|
||||
use Piwik\Date;
|
||||
use Piwik\Db;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Segment;
|
||||
use Piwik\DbHelper;
|
||||
|
||||
/**
|
||||
* The SegmentEditor Model lets you persist and read custom Segments from the backend without handling any logic.
|
||||
*/
|
||||
class Model
|
||||
{
|
||||
private static $rawPrefix = 'segment';
|
||||
|
||||
protected function getTable()
|
||||
{
|
||||
return Common::prefixTable(self::$rawPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all stored segments that haven't been deleted. Ignores the site the segments are enabled
|
||||
* for and whether to auto archive or not.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAllSegmentsAndIgnoreVisibility()
|
||||
{
|
||||
$sql = "SELECT * FROM " . $this->getTable() . " WHERE deleted = 0";
|
||||
|
||||
$segments = $this->getDb()->fetchAll($sql);
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all stored segments.
|
||||
*
|
||||
|
|
@ -40,7 +59,7 @@ class Model
|
|||
$sql = $this->buildQuerySortedByName("($whereIdSite enable_only_idsite = 0)
|
||||
AND deleted = 0 AND auto_archive = 1");
|
||||
|
||||
$segments = Db::get()->fetchAll($sql, $bind);
|
||||
$segments = $this->getDb()->fetchAll($sql, $bind);
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
|
@ -56,7 +75,7 @@ class Model
|
|||
$bind = array($userLogin);
|
||||
$sql = $this->buildQuerySortedByName('deleted = 0 AND (enable_all_users = 1 OR login = ?)');
|
||||
|
||||
$segments = Db::get()->fetchAll($sql, $bind);
|
||||
$segments = $this->getDb()->fetchAll($sql, $bind);
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
|
@ -74,16 +93,90 @@ class Model
|
|||
$sql = $this->buildQuerySortedByName('(enable_only_idsite = ? OR enable_only_idsite = 0)
|
||||
AND deleted = 0
|
||||
AND (enable_all_users = 1 OR login = ?)');
|
||||
$segments = Db::get()->fetchAll($sql, $bind);
|
||||
$segments = $this->getDb()->fetchAll($sql, $bind);
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be used _only_ by Super Users
|
||||
* @param $idSite
|
||||
* @return array
|
||||
*/
|
||||
public function getAllSegmentsForAllUsers($idSite = false)
|
||||
{
|
||||
$bind = array();
|
||||
$sqlWhereCondition = '';
|
||||
|
||||
if(!empty($idSite)) {
|
||||
$bind = array($idSite);
|
||||
$sqlWhereCondition = '(enable_only_idsite = ? OR enable_only_idsite = 0) AND';
|
||||
}
|
||||
|
||||
$sqlWhereCondition = $this->buildQuerySortedByName($sqlWhereCondition . ' deleted = 0');
|
||||
$segments = $this->getDb()->fetchAll($sqlWhereCondition, $bind);
|
||||
|
||||
return $segments;
|
||||
}
|
||||
|
||||
public function deleteSegment($idSegment)
|
||||
{
|
||||
$db = $this->getDb();
|
||||
$db->delete($this->getTable(), 'idsegment = ' . (int) $idSegment);
|
||||
}
|
||||
|
||||
public function updateSegment($idSegment, $segment)
|
||||
{
|
||||
$idSegment = (int) $idSegment;
|
||||
|
||||
$db = $this->getDb();
|
||||
$db->update($this->getTable(), $segment, "idsegment = $idSegment");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function createSegment($segment)
|
||||
{
|
||||
$db = $this->getDb();
|
||||
$db->insert($this->getTable(), $segment);
|
||||
$id = $db->lastInsertId();
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
public function getSegment($idSegment)
|
||||
{
|
||||
$db = $this->getDb();
|
||||
$segment = $db->fetchRow("SELECT * FROM " . $this->getTable() . " WHERE idsegment = ?", $idSegment);
|
||||
|
||||
return $segment;
|
||||
}
|
||||
|
||||
private function getDb()
|
||||
{
|
||||
return Db::get();
|
||||
}
|
||||
|
||||
private function buildQuerySortedByName($where)
|
||||
{
|
||||
$sql = "SELECT * FROM " . Common::prefixTable("segment") .
|
||||
" WHERE $where ORDER BY name ASC";
|
||||
|
||||
return $sql;
|
||||
return "SELECT * FROM " . $this->getTable() . " WHERE $where ORDER BY name ASC";
|
||||
}
|
||||
|
||||
public static function install()
|
||||
{
|
||||
$segmentTable = "`idsegment` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`definition` TEXT NOT NULL,
|
||||
`login` VARCHAR(100) NOT NULL,
|
||||
`enable_all_users` tinyint(4) NOT NULL default 0,
|
||||
`enable_only_idsite` INTEGER(11) NULL,
|
||||
`auto_archive` tinyint(4) NOT NULL default 0,
|
||||
`ts_created` TIMESTAMP NULL,
|
||||
`ts_last_edit` TIMESTAMP NULL,
|
||||
`deleted` tinyint(4) NOT NULL default 0,
|
||||
PRIMARY KEY (`idsegment`)";
|
||||
|
||||
DbHelper::createTable(self::$rawPrefix, $segmentTable);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -8,35 +8,17 @@
|
|||
*/
|
||||
namespace Piwik\Plugins\SegmentEditor;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Common;
|
||||
use Piwik\Config;
|
||||
use Piwik\Db;
|
||||
use Piwik\DbHelper;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Version;
|
||||
|
||||
/**
|
||||
*/
|
||||
class SegmentEditor extends \Piwik\Plugin
|
||||
{
|
||||
/**
|
||||
* @see Piwik\Plugin::getInformation
|
||||
* @see Piwik\Plugin::registerEvents
|
||||
*/
|
||||
public function getInformation()
|
||||
{
|
||||
return array(
|
||||
'description' => 'Create and reuse custom visitor Segments with the Segment Editor.',
|
||||
'authors' => array(array('name' => 'Piwik', 'homepage' => 'http://piwik.org/')),
|
||||
'version' => Version::VERSION,
|
||||
'license' => 'GPL v3+',
|
||||
'license_homepage' => 'http://www.gnu.org/licenses/gpl.html'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Piwik\Plugin::getListHooksRegistered
|
||||
*/
|
||||
public function getListHooksRegistered()
|
||||
public function registerEvents()
|
||||
{
|
||||
return array(
|
||||
'Segments.getKnownSegmentsToArchiveForSite' => 'getKnownSegmentsToArchiveForSite',
|
||||
|
|
@ -44,13 +26,14 @@ class SegmentEditor extends \Piwik\Plugin
|
|||
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
|
||||
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
|
||||
'Template.nextToCalendar' => 'getSegmentEditorHtml',
|
||||
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
|
||||
);
|
||||
}
|
||||
|
||||
function getSegmentEditorHtml(&$out)
|
||||
{
|
||||
$controller = new Controller();
|
||||
$out .= $controller->getSelector();
|
||||
$selector = new SegmentSelectorControl();
|
||||
$out .= $selector->render();
|
||||
}
|
||||
|
||||
public function getKnownSegmentsToArchiveAllSites(&$segments)
|
||||
|
|
@ -69,27 +52,17 @@ class SegmentEditor extends \Piwik\Plugin
|
|||
{
|
||||
$model = new Model();
|
||||
$segmentToAutoArchive = $model->getSegmentsToAutoArchive($idSite);
|
||||
|
||||
foreach ($segmentToAutoArchive as $segmentInfo) {
|
||||
$segments[] = $segmentInfo['definition'];
|
||||
}
|
||||
|
||||
$segments = array_unique($segments);
|
||||
}
|
||||
|
||||
public function install()
|
||||
{
|
||||
$segmentTable = "`idsegment` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`definition` TEXT NOT NULL,
|
||||
`login` VARCHAR(100) NOT NULL,
|
||||
`enable_all_users` tinyint(4) NOT NULL default 0,
|
||||
`enable_only_idsite` INTEGER(11) NULL,
|
||||
`auto_archive` tinyint(4) NOT NULL default 0,
|
||||
`ts_created` TIMESTAMP NULL,
|
||||
`ts_last_edit` TIMESTAMP NULL,
|
||||
`deleted` tinyint(4) NOT NULL default 0,
|
||||
PRIMARY KEY (`idsegment`)";
|
||||
|
||||
DbHelper::createTable('segment', $segmentTable);
|
||||
Model::install();
|
||||
}
|
||||
|
||||
public function getJsFiles(&$jsFiles)
|
||||
|
|
@ -101,4 +74,21 @@ class SegmentEditor extends \Piwik\Plugin
|
|||
{
|
||||
$stylesheets[] = "plugins/SegmentEditor/stylesheets/segmentation.less";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether adding segments for all websites is enabled or not.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isAddingSegmentsForAllWebsitesEnabled()
|
||||
{
|
||||
return Config::getInstance()->General['allow_adding_segments_for_all_websites'] == 1;
|
||||
}
|
||||
|
||||
public function getClientSideTranslationKeys(&$translationKeys)
|
||||
{
|
||||
$translationKeys[] = 'SegmentEditor_CustomSegment';
|
||||
$translationKeys[] = 'SegmentEditor_VisibleToSuperUser';
|
||||
$translationKeys[] = 'SegmentEditor_SharedWithYou';
|
||||
}
|
||||
}
|
||||
|
|
|
|||
147
www/analytics/plugins/SegmentEditor/SegmentFormatter.php
Normal file
147
www/analytics/plugins/SegmentEditor/SegmentFormatter.php
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\SegmentEditor;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Config;
|
||||
use Piwik\Db;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Segment;
|
||||
use Piwik\Segment\SegmentExpression;
|
||||
|
||||
/**
|
||||
*/
|
||||
class SegmentFormatter
|
||||
{
|
||||
/**
|
||||
* @var SegmentList
|
||||
*/
|
||||
private $segmentList;
|
||||
|
||||
private $matchesMetric = array(
|
||||
SegmentExpression::MATCH_EQUAL => 'General_OperationEquals',
|
||||
SegmentExpression::MATCH_NOT_EQUAL => 'General_OperationNotEquals',
|
||||
SegmentExpression::MATCH_LESS_OR_EQUAL => 'General_OperationAtMost',
|
||||
SegmentExpression::MATCH_GREATER_OR_EQUAL => 'General_OperationAtLeast',
|
||||
SegmentExpression::MATCH_LESS => 'General_OperationLessThan',
|
||||
SegmentExpression::MATCH_GREATER => 'General_OperationGreaterThan',
|
||||
);
|
||||
|
||||
private $matchesDimension = array(
|
||||
SegmentExpression::MATCH_EQUAL => 'General_OperationIs',
|
||||
SegmentExpression::MATCH_NOT_EQUAL => 'General_OperationIsNot',
|
||||
SegmentExpression::MATCH_CONTAINS => 'General_OperationContains',
|
||||
SegmentExpression::MATCH_DOES_NOT_CONTAIN => 'General_OperationDoesNotContain',
|
||||
SegmentExpression::MATCH_STARTS_WITH => 'General_OperationStartsWith',
|
||||
SegmentExpression::MATCH_ENDS_WITH => 'General_OperationEndsWith'
|
||||
);
|
||||
|
||||
private $operators = array(
|
||||
SegmentExpression::BOOL_OPERATOR_AND => 'General_And',
|
||||
SegmentExpression::BOOL_OPERATOR_OR => 'General_Or',
|
||||
SegmentExpression::BOOL_OPERATOR_END => '',
|
||||
);
|
||||
|
||||
public function __construct(SegmentList $segmentList)
|
||||
{
|
||||
$this->segmentList = $segmentList;
|
||||
}
|
||||
|
||||
public function getHumanReadable($segmentString, $idSite)
|
||||
{
|
||||
if (empty($segmentString)) {
|
||||
return Piwik::translate('SegmentEditor_DefaultAllVisits');
|
||||
}
|
||||
|
||||
try {
|
||||
$segment = new SegmentExpression(urldecode($segmentString));
|
||||
$expressions = $segment->parseSubExpressions();
|
||||
} catch (Exception $e) {
|
||||
$segment = new SegmentExpression($segmentString);
|
||||
$expressions = $segment->parseSubExpressions();
|
||||
}
|
||||
|
||||
$readable = '';
|
||||
foreach ($expressions as $expression) {
|
||||
$operator = $expression[SegmentExpression::INDEX_BOOL_OPERATOR];
|
||||
$operand = $expression[SegmentExpression::INDEX_OPERAND];
|
||||
$name = $operand[SegmentExpression::INDEX_OPERAND_NAME];
|
||||
|
||||
$segment = $this->segmentList->findSegment($name, $idSite);
|
||||
|
||||
if (empty($segment)) {
|
||||
throw new Exception(sprintf("The segment '%s' does not exist.", $name));
|
||||
}
|
||||
|
||||
$readable .= $segment['name'] . ' ';
|
||||
$readable .= $this->getTranslationForComparison($operand, $segment['type']) . ' ';
|
||||
$readable .= $this->getFormattedValue($operand);
|
||||
$readable .= $this->getTranslationForBoolOperator($operator) . ' ';
|
||||
}
|
||||
|
||||
$readable = trim($readable);
|
||||
|
||||
return $readable;
|
||||
}
|
||||
|
||||
private function getTranslationForComparison($operand, $segmentType)
|
||||
{
|
||||
$operator = $operand[SegmentExpression::INDEX_OPERAND_OPERATOR];
|
||||
|
||||
$translation = $operator;
|
||||
|
||||
if ($operator === SegmentExpression::MATCH_IS_NULL_OR_EMPTY) {
|
||||
return Piwik::translate('SegmentEditor_SegmentOperatorIsNullOrEmpty');
|
||||
}
|
||||
|
||||
if ($operator === SegmentExpression::MATCH_IS_NOT_NULL_NOR_EMPTY) {
|
||||
return Piwik::translate('SegmentEditor_SegmentOperatorIsNotNullNorEmpty');
|
||||
}
|
||||
|
||||
if ($segmentType === 'dimension' && !empty($this->matchesDimension[$operator])) {
|
||||
$translation = Piwik::translate($this->matchesDimension[$operator]);
|
||||
}
|
||||
if ($segmentType === 'metric' && !empty($this->matchesMetric[$operator])) {
|
||||
$translation = Piwik::translate($this->matchesMetric[$operator]);
|
||||
}
|
||||
|
||||
return strtolower($translation);
|
||||
}
|
||||
|
||||
private function getFormattedValue($operand)
|
||||
{
|
||||
$operator = $operand[SegmentExpression::INDEX_OPERAND_OPERATOR];
|
||||
|
||||
if ($operator === SegmentExpression::MATCH_IS_NULL_OR_EMPTY
|
||||
|| $operator === SegmentExpression::MATCH_IS_NOT_NULL_NOR_EMPTY) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = $operand[SegmentExpression::INDEX_OPERAND_VALUE];
|
||||
|
||||
if (empty($value)) {
|
||||
$value = '';
|
||||
}
|
||||
|
||||
return '"' . $value . '" ';
|
||||
}
|
||||
|
||||
private function getTranslationForBoolOperator($operator)
|
||||
{
|
||||
$translation = '';
|
||||
|
||||
if (!empty($this->operators[$operator])) {
|
||||
$translation = Piwik::translate($this->operators[$operator]);
|
||||
} elseif (!empty($operator)) {
|
||||
$translation = $operator;
|
||||
}
|
||||
|
||||
return $translation;
|
||||
}
|
||||
}
|
||||
32
www/analytics/plugins/SegmentEditor/SegmentList.php
Normal file
32
www/analytics/plugins/SegmentEditor/SegmentList.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\SegmentEditor;
|
||||
|
||||
use Piwik\API\Request;
|
||||
use Piwik\Config;
|
||||
use Piwik\Db;
|
||||
|
||||
/**
|
||||
*/
|
||||
class SegmentList
|
||||
{
|
||||
public function findSegment($segmentName, $idSite)
|
||||
{
|
||||
$segments = Request::processRequest('API.getSegmentsMetadata', array(
|
||||
'idSites' => array($idSite),
|
||||
));
|
||||
|
||||
foreach ($segments as $segment) {
|
||||
if ($segment['segment'] == $segmentName && !empty($segmentName)) {
|
||||
return $segment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\SegmentEditor;
|
||||
|
||||
use Piwik\DataAccess\LogQueryBuilder;
|
||||
use Piwik\Plugins\SegmentEditor\Services\StoredSegmentService;
|
||||
use Piwik\Segment\SegmentExpression;
|
||||
use Piwik\SettingsServer;
|
||||
|
||||
/**
|
||||
* Decorates segment sub-queries in archiving queries w/ the idSegment of the segment, if
|
||||
* a stored segment exists.
|
||||
*
|
||||
* This class is configured for use in SegmentEditor's DI config.
|
||||
*/
|
||||
class SegmentQueryDecorator extends LogQueryBuilder
|
||||
{
|
||||
/**
|
||||
* @var StoredSegmentService
|
||||
*/
|
||||
private $storedSegmentService;
|
||||
|
||||
public function __construct(StoredSegmentService $storedSegmentService)
|
||||
{
|
||||
$this->storedSegmentService = $storedSegmentService;
|
||||
}
|
||||
|
||||
public function getSelectQueryString(SegmentExpression $segmentExpression, $select, $from, $where, $bind, $groupBy,
|
||||
$orderBy, $limit)
|
||||
{
|
||||
$result = parent::getSelectQueryString($segmentExpression, $select, $from, $where, $bind, $groupBy, $orderBy,
|
||||
$limit);
|
||||
|
||||
$prefixParts = array();
|
||||
|
||||
if (SettingsServer::isArchivePhpTriggered()) {
|
||||
$prefixParts[] = 'trigger = CronArchive';
|
||||
}
|
||||
|
||||
$idSegments = $this->getSegmentIdOfExpression($segmentExpression);
|
||||
if (!empty($idSegments)) {
|
||||
$prefixParts[] = "idSegments = [" . implode(', ', $idSegments) . "]";
|
||||
}
|
||||
|
||||
if (!empty($prefixParts)) {
|
||||
$result['sql'] = "/* " . implode(', ', $prefixParts) . " */\n" . $result['sql'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function getSegmentIdOfExpression(SegmentExpression $segmentExpression)
|
||||
{
|
||||
$allSegments = $this->storedSegmentService->getAllSegmentsAndIgnoreVisibility();
|
||||
|
||||
$idSegments = array();
|
||||
foreach ($allSegments as $segment) {
|
||||
if ($segmentExpression->getSegmentDefinition() == $segment['definition']) {
|
||||
$idSegments[] = $segment['idsegment'];
|
||||
}
|
||||
}
|
||||
return $idSegments;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -8,11 +8,14 @@
|
|||
*/
|
||||
namespace Piwik\Plugins\SegmentEditor;
|
||||
|
||||
use Piwik\API\Request;
|
||||
use Piwik\Common;
|
||||
use Piwik\Config;
|
||||
use Piwik\Container\StaticContainer;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\API\API as APIMetadata;
|
||||
use Piwik\View\UIControl;
|
||||
use Piwik\Plugins\SegmentEditor\API as SegmentEditorAPI;
|
||||
|
||||
/**
|
||||
* Generates the HTML for the segment selector control (which includes the segment editor).
|
||||
|
|
@ -30,17 +33,23 @@ class SegmentSelectorControl extends UIControl
|
|||
|
||||
$this->jsClass = "SegmentSelectorControl";
|
||||
$this->cssIdentifier = "segmentEditorPanel";
|
||||
$this->cssClass = "piwikTopControl";
|
||||
$this->cssClass = "piwikTopControl borderedControl piwikSelector";
|
||||
|
||||
$this->idSite = $idSite ?: Common::getRequestVar('idSite', false, 'int');
|
||||
|
||||
$this->selectedSegment = Common::getRequestVar('segment', false, 'string');
|
||||
|
||||
$formatter = StaticContainer::get('Piwik\Plugins\SegmentEditor\SegmentFormatter');
|
||||
$this->segmentDescription = $formatter->getHumanReadable(Request::getRawSegmentFromRequest(), $this->idSite);
|
||||
|
||||
$this->isAddingSegmentsForAllWebsitesEnabled = SegmentEditor::isAddingSegmentsForAllWebsitesEnabled();
|
||||
|
||||
$segments = APIMetadata::getInstance()->getSegmentsMetadata($this->idSite);
|
||||
|
||||
$segmentsByCategory = $customVariablesSegments = array();
|
||||
$visitTitle = Piwik::translate('General_Visit');
|
||||
$segmentsByCategory = array();
|
||||
foreach ($segments as $segment) {
|
||||
if ($segment['category'] == Piwik::translate('General_Visit')
|
||||
if ($segment['category'] == $visitTitle
|
||||
&& ($segment['type'] == 'metric' && $segment['segment'] != 'visitIp')
|
||||
) {
|
||||
$metricsLabel = Piwik::translate('General_Metrics');
|
||||
|
|
@ -49,7 +58,6 @@ class SegmentSelectorControl extends UIControl
|
|||
}
|
||||
$segmentsByCategory[$segment['category']][] = $segment;
|
||||
}
|
||||
uksort($segmentsByCategory, array($this, 'sortSegmentCategories'));
|
||||
|
||||
$this->createRealTimeSegmentsIsEnabled = Config::getInstance()->General['enable_create_realtime_segments'];
|
||||
$this->segmentsByCategory = $segmentsByCategory;
|
||||
|
|
@ -67,7 +75,8 @@ class SegmentSelectorControl extends UIControl
|
|||
}
|
||||
}
|
||||
|
||||
$this->authorizedToCreateSegments = !Piwik::isUserIsAnonymous();
|
||||
$this->authorizedToCreateSegments = SegmentEditorAPI::getInstance()->isUserCanAddNewSegment($this->idSite);
|
||||
$this->isUserAnonymous = Piwik::isUserIsAnonymous();
|
||||
$this->segmentTranslations = $this->getTranslations();
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +85,8 @@ class SegmentSelectorControl extends UIControl
|
|||
return array('availableSegments',
|
||||
'segmentTranslations',
|
||||
'isSegmentNotAppliedBecauseBrowserArchivingIsDisabled',
|
||||
'selectedSegment');
|
||||
'selectedSegment',
|
||||
'authorizedToCreateSegments');
|
||||
}
|
||||
|
||||
private function wouldApplySegment($savedSegment)
|
||||
|
|
@ -90,15 +100,6 @@ class SegmentSelectorControl extends UIControl
|
|||
return (bool) $savedSegment['auto_archive'];
|
||||
}
|
||||
|
||||
public function sortSegmentCategories($a, $b)
|
||||
{
|
||||
// Custom Variables last
|
||||
if ($a == Piwik::translate('CustomVariables_CustomVariables')) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function getTranslations()
|
||||
{
|
||||
$translationKeys = array(
|
||||
|
|
@ -110,6 +111,8 @@ class SegmentSelectorControl extends UIControl
|
|||
'General_OperationGreaterThan',
|
||||
'General_OperationContains',
|
||||
'General_OperationDoesNotContain',
|
||||
'General_OperationStartsWith',
|
||||
'General_OperationEndsWith',
|
||||
'General_OperationIs',
|
||||
'General_OperationIsNot',
|
||||
'General_OperationContains',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\SegmentEditor\Services;
|
||||
|
||||
use Piwik\Plugins\SegmentEditor\Model;
|
||||
use Piwik\Cache\Transient as TransientCache;
|
||||
|
||||
|
||||
/**
|
||||
* Service layer class for stored segments.
|
||||
*/
|
||||
class StoredSegmentService
|
||||
{
|
||||
/**
|
||||
* @var Model
|
||||
*/
|
||||
private $model;
|
||||
|
||||
/**
|
||||
* @var TransientCache
|
||||
*/
|
||||
private $transientCache;
|
||||
|
||||
public function __construct(Model $model, TransientCache $transientCache)
|
||||
{
|
||||
$this->model = $model;
|
||||
$this->transientCache = $transientCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all stored segments that haven't been deleted.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAllSegmentsAndIgnoreVisibility()
|
||||
{
|
||||
$cacheKey = 'SegmentEditor.getAllSegmentsAndIgnoreVisibility';
|
||||
if (!$this->transientCache->contains($cacheKey)) {
|
||||
$result = $this->model->getAllSegmentsAndIgnoreVisibility();
|
||||
|
||||
$this->transientCache->save($cacheKey, $result);
|
||||
}
|
||||
return $this->transientCache->fetch($cacheKey);
|
||||
}
|
||||
}
|
||||
7
www/analytics/plugins/SegmentEditor/config/config.php
Normal file
7
www/analytics/plugins/SegmentEditor/config/config.php
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
'Piwik\DataAccess\LogQueryBuilder' => DI\get('Piwik\Plugins\SegmentEditor\SegmentQueryDecorator'),
|
||||
|
||||
);
|
||||
BIN
www/analytics/plugins/SegmentEditor/images/edit_segment.png
Normal file
BIN
www/analytics/plugins/SegmentEditor/images/edit_segment.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
/*!
|
||||
* Piwik - Web Analytics
|
||||
* Piwik - free/libre analytics platform
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
|
|
@ -7,6 +7,12 @@
|
|||
|
||||
Segmentation = (function($) {
|
||||
|
||||
function preselectFirstMetricMatch(rowNode)
|
||||
{
|
||||
var matchValue = $(rowNode).find('.metricMatchBlock option:first').attr('value');
|
||||
$(rowNode).find('.metricMatchBlock select').val(matchValue);
|
||||
}
|
||||
|
||||
var segmentation = function segmentation(config) {
|
||||
if (!config.target) {
|
||||
throw new Error("target property must be set in config to segment editor control element");
|
||||
|
|
@ -26,6 +32,8 @@ Segmentation = (function($) {
|
|||
|
||||
self.timer = ""; // variable for further use in timing events
|
||||
self.searchAllowed = true;
|
||||
self.filterTimer = "";
|
||||
self.filterAllowed = true;
|
||||
|
||||
self.availableMatches = [];
|
||||
self.availableMatches["metric"] = [];
|
||||
|
|
@ -35,12 +43,14 @@ Segmentation = (function($) {
|
|||
self.availableMatches["metric"][">="] = self.translations['General_OperationAtLeast'];
|
||||
self.availableMatches["metric"]["<"] = self.translations['General_OperationLessThan'];
|
||||
self.availableMatches["metric"][">"] = self.translations['General_OperationGreaterThan'];
|
||||
|
||||
|
||||
self.availableMatches["dimension"] = [];
|
||||
self.availableMatches["dimension"]["=="] = self.translations['General_OperationIs'];
|
||||
self.availableMatches["dimension"]["!="] = self.translations['General_OperationIsNot'];
|
||||
self.availableMatches["dimension"]["=@"] = self.translations['General_OperationContains'];
|
||||
self.availableMatches["dimension"]["!@"] = self.translations['General_OperationDoesNotContain'];
|
||||
self.availableMatches["dimension"]["=^"] = self.translations['General_OperationStartsWith'];
|
||||
self.availableMatches["dimension"]["=$"] = self.translations['General_OperationEndsWith'];
|
||||
|
||||
segmentation.prototype.setAvailableSegments = function (segments) {
|
||||
this.availableSegments = segments;
|
||||
|
|
@ -61,44 +71,23 @@ Segmentation = (function($) {
|
|||
this.currentSegmentStr = segmentStr;
|
||||
};
|
||||
|
||||
segmentation.prototype.shortenSegmentName = function(name, length){
|
||||
|
||||
if(typeof length === "undefined") length = 16;
|
||||
if(typeof name === "undefined") name = "";
|
||||
var i;
|
||||
|
||||
if(name.length > length)
|
||||
{
|
||||
for(i = length; i > 0; i--){
|
||||
if(name[i] === " "){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == 0){
|
||||
i = length-3;
|
||||
}
|
||||
|
||||
return name.slice(0,i)+"...";
|
||||
}
|
||||
return name;
|
||||
};
|
||||
|
||||
segmentation.prototype.markCurrentSegment = function(){
|
||||
var current = this.getSegment();
|
||||
|
||||
var segmentationTitle = $(this.content).find(".segmentationTitle");
|
||||
if( current != "")
|
||||
{
|
||||
var selector = 'div.segmentList ul li[data-definition="'+current+'"]';
|
||||
var currentDecoded = piwikHelper.htmlDecode(current);
|
||||
var selector = 'div.segmentList ul li[data-definition="'+currentDecoded+'"]';
|
||||
var foundItems = $(selector, this.target);
|
||||
var title = $('<strong></strong>');
|
||||
|
||||
if( foundItems.length > 0) {
|
||||
var name = $(foundItems).first().find("span.segname").text();
|
||||
title.text(name);
|
||||
var idSegment = $(foundItems).first().attr('data-idsegment');
|
||||
var title = getSegmentName( getSegmentFromId(idSegment));
|
||||
} else {
|
||||
title.text("Custom Segment");
|
||||
title = _pk_translate('SegmentEditor_CustomSegment');
|
||||
}
|
||||
segmentationTitle.html(title);
|
||||
segmentationTitle.addClass('segment-clicked').html( title );
|
||||
}
|
||||
else {
|
||||
$(this.content).find(".segmentationTitle").text(this.translations['SegmentEditor_DefaultAllVisits']);
|
||||
|
|
@ -120,26 +109,25 @@ Segmentation = (function($) {
|
|||
};
|
||||
|
||||
var getMockedInputSet = function(){
|
||||
if(typeof mockedInputSet === "undefined"){
|
||||
var mockedInputSet = self.editorTemplate.find("div.segment-row-inputs").clone();
|
||||
}
|
||||
return mockedInputSet.clone();
|
||||
var mockedInputSet = self.editorTemplate.find("div.segment-row-inputs").clone();
|
||||
var clonedInput = mockedInputSet.clone();
|
||||
preselectFirstMetricMatch(clonedInput);
|
||||
|
||||
return clonedInput;
|
||||
};
|
||||
|
||||
var getMockedInputRowHtml = function(){
|
||||
if(typeof mockedInputRow === "undefined"){
|
||||
var mockedInputRow = '<div class="segment-row"><a class="segment-close" href="#"></a><div class="segment-row-inputs">'+getMockedInputSet().html()+'</div></div>';
|
||||
}
|
||||
var mockedInputRow = '<div class="segment-row"><a class="segment-close" href="#"></a><div class="segment-row-inputs">'+getMockedInputSet().html()+'</div></div>';
|
||||
return mockedInputRow;
|
||||
};
|
||||
|
||||
var getMockedFormRow = function(){
|
||||
if(typeof mockedFormRow === "undefined")
|
||||
{
|
||||
var mockedFormRow = self.editorTemplate.find("div.segment-rows").clone();
|
||||
$(mockedFormRow).find(".segment-row").append(getMockedInputSet()).after(getAddOrBlockButtonHtml).after(getOrDiv());
|
||||
}
|
||||
return mockedFormRow.clone();
|
||||
var mockedFormRow = self.editorTemplate.find("div.segment-rows").clone();
|
||||
$(mockedFormRow).find(".segment-row").append(getMockedInputSet()).after(getAddOrBlockButtonHtml).after(getOrDiv());
|
||||
var clonedRow = mockedFormRow.clone();
|
||||
preselectFirstMetricMatch(clonedRow);
|
||||
|
||||
return clonedRow;
|
||||
};
|
||||
|
||||
var getInitialStateRowsHtml = function(){
|
||||
|
|
@ -156,11 +144,13 @@ Segmentation = (function($) {
|
|||
};
|
||||
|
||||
var appendSpecifiedRowHtml= function(metric) {
|
||||
$(self.form).find(".segment-content > h3").after(getMockedFormRow());
|
||||
var mockedRow = getMockedFormRow();
|
||||
$(self.form).find(".segment-content > h3").after(mockedRow);
|
||||
$(self.form).find(".segment-content").append(getAndDiv());
|
||||
$(self.form).find(".segment-content").append(getAddNewBlockButtonHtml());
|
||||
doDragDropBindings();
|
||||
$(self.form).find(".metricList").val(metric).trigger("change");
|
||||
preselectFirstMetricMatch(mockedRow);
|
||||
};
|
||||
|
||||
var appendComplexRowHtml = function(block){
|
||||
|
|
@ -208,28 +198,68 @@ Segmentation = (function($) {
|
|||
var getListHtml = function() {
|
||||
var html = self.editorTemplate.find("> .listHtml").clone();
|
||||
var segment, injClass;
|
||||
|
||||
var listHtml = '<li data-idsegment="" ' +
|
||||
(self.currentSegmentStr == "" ? " class='segmentSelected' " : "")
|
||||
+ ' data-definition=""><span class="segname">' + self.translations['SegmentEditor_DefaultAllVisits']
|
||||
+ ' ' + self.translations['General_DefaultAppended']
|
||||
+ '</span></li> ';
|
||||
(self.currentSegmentStr == "" ? " class='segmentSelected' " : "")
|
||||
+ ' data-definition=""><span class="segname">' + self.translations['SegmentEditor_DefaultAllVisits']
|
||||
+ ' ' + self.translations['General_DefaultAppended']
|
||||
+ '</span></li> ';
|
||||
|
||||
var isVisibleToSuperUserNoticeAlreadyDisplayedOnce = false;
|
||||
var isVisibleToSuperUserNoticeShouldBeClosed = false;
|
||||
|
||||
var isSharedWithMeBySuperUserNoticeAlreadyDisplayedOnce = false;
|
||||
var isSharedWithMeBySuperUserNoticeShouldBeClosed = false;
|
||||
|
||||
if(self.availableSegments.length > 0) {
|
||||
|
||||
for(var i = 0; i < self.availableSegments.length; i++)
|
||||
{
|
||||
segment = self.availableSegments[i];
|
||||
|
||||
if(isSegmentSharedWithMeBySuperUser(segment) && !isSharedWithMeBySuperUserNoticeAlreadyDisplayedOnce) {
|
||||
isSharedWithMeBySuperUserNoticeAlreadyDisplayedOnce = true;
|
||||
isSharedWithMeBySuperUserNoticeShouldBeClosed = true;
|
||||
listHtml += '<span class="segmentsSharedWithMeBySuperUser"><hr> ' + _pk_translate('SegmentEditor_SharedWithYou') + ':<br/><br/>';
|
||||
}
|
||||
|
||||
if(isSegmentVisibleToSuperUserOnly(segment) && !isVisibleToSuperUserNoticeAlreadyDisplayedOnce) {
|
||||
// close <span class="segmentsSharedWithMeBySuperUser">
|
||||
if(isSharedWithMeBySuperUserNoticeShouldBeClosed) {
|
||||
isSharedWithMeBySuperUserNoticeShouldBeClosed = false;
|
||||
listHtml += '</span>';
|
||||
}
|
||||
|
||||
isVisibleToSuperUserNoticeAlreadyDisplayedOnce = true;
|
||||
isVisibleToSuperUserNoticeShouldBeClosed = true;
|
||||
listHtml += '<span class="segmentsVisibleToSuperUser"><hr> ' + _pk_translate('SegmentEditor_VisibleToSuperUser') + ':<br/><br/>';
|
||||
}
|
||||
|
||||
|
||||
injClass = "";
|
||||
if( segment.definition == self.currentSegmentStr){
|
||||
var checkSelected = segment.definition;
|
||||
if(!$.browser.mozilla) {
|
||||
checkSelected = encodeURIComponent(checkSelected);
|
||||
}
|
||||
|
||||
if( checkSelected == self.currentSegmentStr){
|
||||
injClass = 'class="segmentSelected"';
|
||||
}
|
||||
listHtml += '<li data-idsegment="'+segment.idsegment+'" data-definition="'+ (segment.definition).replace(/"/g, '"') +'" '
|
||||
+ injClass +' title="'+segment.name+'"><span class="segname">'
|
||||
+ self.shortenSegmentName(segment.name)+'</span>';
|
||||
+injClass+' title="'+ getSegmentTooltipEnrichedWithUsername(segment) +'"><span class="segname">'+getSegmentName(segment)+'</span>';
|
||||
if(self.segmentAccess == "write") {
|
||||
listHtml += '<span class="editSegment">['+ self.translations['General_Edit'].toLocaleLowerCase() +']</span>';
|
||||
listHtml += '<span class="editSegment" title="'+ self.translations['General_Edit'].toLocaleLowerCase() +'"></span>';
|
||||
}
|
||||
listHtml += '</li>';
|
||||
}
|
||||
|
||||
if(isVisibleToSuperUserNoticeShouldBeClosed) {
|
||||
listHtml += '</span>';
|
||||
}
|
||||
|
||||
if(isSharedWithMeBySuperUserNoticeShouldBeClosed) {
|
||||
listHtml += '</span>';
|
||||
}
|
||||
|
||||
$(html).find(".segmentList > ul").append(listHtml);
|
||||
if(self.segmentAccess === "write"){
|
||||
$(html).find(".add_new_segment").html(self.translations['SegmentEditor_AddNewSegment']);
|
||||
|
|
@ -245,20 +275,58 @@ Segmentation = (function($) {
|
|||
return html;
|
||||
};
|
||||
|
||||
var isSegmentVisibleToSuperUserOnly = function(segment) {
|
||||
return hasSuperUserAccessAndSegmentCreatedByAnotherUser(segment)
|
||||
&& segment.enable_all_users == 0;
|
||||
};
|
||||
|
||||
var isSegmentSharedWithMeBySuperUser = function(segment) {
|
||||
return segment.login != piwik.userLogin
|
||||
&& segment.enable_all_users == 1;
|
||||
};
|
||||
|
||||
var hasSuperUserAccessAndSegmentCreatedByAnotherUser = function(segment) {
|
||||
return piwik.hasSuperUserAccess && segment.login != piwik.userLogin;
|
||||
};
|
||||
|
||||
var getSegmentTooltipEnrichedWithUsername = function(segment) {
|
||||
var segmentName = segment.name;
|
||||
if(hasSuperUserAccessAndSegmentCreatedByAnotherUser(segment)) {
|
||||
segmentName += ' (';
|
||||
segmentName += _pk_translate('General_CreatedByUser', [segment.login]);
|
||||
|
||||
if(segment.enable_all_users == 0) {
|
||||
segmentName += ', ' + _pk_translate('SegmentEditor_VisibleToSuperUser');
|
||||
}
|
||||
|
||||
segmentName += ')';
|
||||
}
|
||||
return sanitiseSegmentName(segmentName);
|
||||
};
|
||||
|
||||
var getSegmentName = function(segment) {
|
||||
return sanitiseSegmentName(segment.name);
|
||||
};
|
||||
|
||||
var sanitiseSegmentName = function(segment) {
|
||||
segment = piwikHelper.escape(segment);
|
||||
return segment;
|
||||
}
|
||||
|
||||
var getFormHtml = function() {
|
||||
var html = self.editorTemplate.find("> .segment-element").clone();
|
||||
// set left margin to center form
|
||||
var segmentsDropdown = $(html).find(".available_segments_select");
|
||||
var segment, newOption;
|
||||
newOption = '<option data-idsegment="" data-definition="" title="'
|
||||
+ self.translations['SegmentEditor_AddNewSegment']
|
||||
+ '">' + self.translations['SegmentEditor_AddNewSegment']
|
||||
+ '</option>';
|
||||
+ self.translations['SegmentEditor_AddNewSegment']
|
||||
+ '">' + self.translations['SegmentEditor_AddNewSegment']
|
||||
+ '</option>';
|
||||
segmentsDropdown.append(newOption);
|
||||
for(var i = 0; i < self.availableSegments.length; i++)
|
||||
{
|
||||
segment = self.availableSegments[i];
|
||||
newOption = '<option data-idsegment="'+segment.idsegment+'" data-definition="'+(segment.definition).replace(/"/g, '"')+'" title="'+segment.name+'">'+self.shortenSegmentName(segment.name)+'</option>';
|
||||
newOption = '<option data-idsegment="'+segment.idsegment+'" data-definition="'+(segment.definition).replace(/"/g, '"')+'" title="'+getSegmentTooltipEnrichedWithUsername(segment)+'">'+getSegmentName(segment)+'</option>';
|
||||
segmentsDropdown.append(newOption);
|
||||
}
|
||||
$(html).find(".segment-content > h3").after(getInitialStateRowsHtml()).show();
|
||||
|
|
@ -267,14 +335,13 @@ Segmentation = (function($) {
|
|||
|
||||
var closeAllOpenLists = function() {
|
||||
$(".segmentationContainer", self.target).each(function() {
|
||||
if($(this).closest('.segmentEditorPanel').hasClass("visible"))
|
||||
if($(this).closest('.segmentEditorPanel').hasClass("expanded"))
|
||||
$(this).trigger("click");
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
var findAndExplodeByMatch = function(metric){
|
||||
var matches = ["==" , "!=" , "<=", ">=", "=@" , "!@","<",">"];
|
||||
var matches = ["==" , "!=" , "<=", ">=", "=@" , "!@","<",">", "=^", "=$"];
|
||||
var newMetric = {};
|
||||
var minPos = metric.length;
|
||||
var match, index;
|
||||
|
|
@ -332,10 +399,15 @@ Segmentation = (function($) {
|
|||
var openEditForm = function(segment){
|
||||
addForm("edit", segment);
|
||||
|
||||
$(self.form).find(".segment-content > h3 > span").text(segment.name);
|
||||
$(self.form).find(".segment-content > h3 > span")
|
||||
.html( getSegmentName(segment) )
|
||||
.prop('title', getSegmentTooltipEnrichedWithUsername(segment));
|
||||
|
||||
$(self.form).find('.available_segments_select > option[data-idsegment="'+segment.idsegment+'"]').prop("selected",true);
|
||||
|
||||
$(self.form).find('.available_segments a.dropList').text(self.shortenSegmentName(segment.name, 16));
|
||||
$(self.form).find('.available_segments a.dropList')
|
||||
.html( getSegmentName(segment) )
|
||||
.prop( 'title', getSegmentTooltipEnrichedWithUsername(segment));
|
||||
|
||||
if(segment.definition != ""){
|
||||
revokeInitialStateRows();
|
||||
|
|
@ -351,21 +423,67 @@ Segmentation = (function($) {
|
|||
doDragDropBindings();
|
||||
};
|
||||
|
||||
var bindEvents = function() {
|
||||
var displayFormAddNewSegment = function (e) {
|
||||
closeAllOpenLists();
|
||||
addForm("new");
|
||||
doDragDropBindings();
|
||||
};
|
||||
|
||||
var filterSegmentList = function (keyword) {
|
||||
var curTitle;
|
||||
clearFilterSegmentList();
|
||||
$(self.target).find(" .filterNoResults").remove();
|
||||
|
||||
$(self.target).find(".segmentList li").each(function () {
|
||||
curTitle = $(this).prop('title');
|
||||
$(this).hide();
|
||||
if (curTitle.toLowerCase().indexOf(keyword.toLowerCase()) !== -1) {
|
||||
$(this).show();
|
||||
}
|
||||
});
|
||||
|
||||
if ($(self.target).find(".segmentList li:visible").length == 0) {
|
||||
$(self.target).find(".segmentList li:first")
|
||||
.before("<li class=\"filterNoResults grayed\">" + self.translations['General_SearchNoResults'] + "</li>");
|
||||
}
|
||||
|
||||
if ($(self.target).find(".segmentList .segmentsVisibleToSuperUser li:visible").length == 0) {
|
||||
$(self.target).find(".segmentList .segmentsVisibleToSuperUser").hide();
|
||||
}
|
||||
if ($(self.target).find(".segmentList .segmentsSharedWithMeBySuperUser li:visible").length == 0) {
|
||||
$(self.target).find(".segmentList .segmentsSharedWithMeBySuperUser").hide();
|
||||
}
|
||||
}
|
||||
|
||||
var clearFilterSegmentList = function () {
|
||||
$(self.target).find(" .filterNoResults").remove();
|
||||
$(self.target).find(".segmentList li").each(function () {
|
||||
$(this).show();
|
||||
});
|
||||
$(self.target).find(".segmentList .segmentsVisibleToSuperUser").show();
|
||||
$(self.target).find(".segmentList .segmentsSharedWithMeBySuperUser").show();
|
||||
}
|
||||
|
||||
var bindEvents = function () {
|
||||
self.target.on('click', '.segmentationContainer', function (e) {
|
||||
// hide all other modals connected with this widget
|
||||
if (self.content.closest('.segmentEditorPanel').hasClass("visible")) {
|
||||
if ($(e.target).hasClass("jspDrag") === true) {
|
||||
if (self.content.closest('.segmentEditorPanel').hasClass("expanded")) {
|
||||
if ($(e.target).hasClass("jspDrag") === true
|
||||
|| $(e.target).hasClass("segmentFilterContainer") === true
|
||||
|| $(e.target).parents().hasClass("segmentFilterContainer") === true
|
||||
|| $(e.target).hasClass("filterNoResults")) {
|
||||
e.stopPropagation();
|
||||
} else {
|
||||
self.jscroll.destroy();
|
||||
self.target.closest('.segmentEditorPanel').removeClass('visible');
|
||||
if (self.jscroll) {
|
||||
self.jscroll.destroy();
|
||||
}
|
||||
self.target.closest('.segmentEditorPanel').removeClass('expanded');
|
||||
}
|
||||
} else {
|
||||
// for each visible segmentationContainer -> trigger click event to close and kill scrollpane - very important !
|
||||
closeAllOpenLists();
|
||||
self.target.closest('.segmentEditorPanel').addClass('visible');
|
||||
|
||||
self.target.closest('.segmentEditorPanel').addClass('expanded');
|
||||
self.target.find('.segmentFilter').val(self.translations['General_Search']).trigger('keyup');
|
||||
self.jscroll = self.target.find(".segmentList").jScrollPane({
|
||||
autoReinitialise: true,
|
||||
showArrows:true
|
||||
|
|
@ -384,36 +502,68 @@ Segmentation = (function($) {
|
|||
|
||||
self.target.on("click", ".segmentList li", function (e) {
|
||||
if ($(e.currentTarget).hasClass("grayed") !== true) {
|
||||
var segment = {};
|
||||
segment.idsegment = $(this).attr("data-idsegment");
|
||||
segment.definition = $(this).data("definition");
|
||||
segment.name = $(this).attr("title");
|
||||
var idsegment = $(this).attr("data-idsegment");
|
||||
segmentDefinition = $(this).data("definition");
|
||||
|
||||
self.setSegment(segment.definition);
|
||||
self.setSegment(segmentDefinition);
|
||||
self.markCurrentSegment();
|
||||
self.segmentSelectMethod( segment.definition );
|
||||
toggleLoadingMessage(segment.definition.length);
|
||||
self.segmentSelectMethod( segmentDefinition );
|
||||
toggleLoadingMessage(segmentDefinition.length);
|
||||
}
|
||||
});
|
||||
|
||||
self.target.on('click', '.add_new_segment', function (e) {
|
||||
e.stopPropagation();
|
||||
closeAllOpenLists();
|
||||
addForm("new");
|
||||
doDragDropBindings();
|
||||
displayFormAddNewSegment(e);
|
||||
});
|
||||
|
||||
self.target.on('change', "select.metricList", function (e, persist) {
|
||||
if (typeof persist === "undefined") {
|
||||
persist = false;
|
||||
}
|
||||
alterMatchesList(this, persist);
|
||||
alterMatchesList(this, true);
|
||||
|
||||
doDragDropBindings();
|
||||
|
||||
autoSuggestValues(this, persist);
|
||||
});
|
||||
|
||||
// attach event that will clear segment list filtering input after clicking x
|
||||
self.target.on('click', ".segmentFilterContainer span", function (e) {
|
||||
$(e.target).parent().find(".segmentFilter").val(self.translations['General_Search']).trigger('keyup');
|
||||
});
|
||||
|
||||
self.target.on('blur', ".segmentFilter", function (e) {
|
||||
if ($(e.target).parent().find(".segmentFilter").val() == "") {
|
||||
$(e.target).parent().find(".segmentFilter").val(self.translations['General_Search'])
|
||||
}
|
||||
});
|
||||
|
||||
self.target.on('click', ".segmentFilter", function (e) {
|
||||
if ($(e.target).val() == self.translations['General_Search']) {
|
||||
$(e.target).val("");
|
||||
}
|
||||
});
|
||||
|
||||
self.target.on('keyup', ".segmentFilter", function (e) {
|
||||
var search = $(e.currentTarget).val();
|
||||
if (search == self.translations['General_Search']) {
|
||||
search = "";
|
||||
}
|
||||
|
||||
if (search.length >= 2) {
|
||||
clearTimeout(self.filterTimer);
|
||||
self.filterAllowed = true;
|
||||
self.filterTimer = setTimeout(function () {
|
||||
filterSegmentList(search);
|
||||
}, 500);
|
||||
}
|
||||
else {
|
||||
self.filterTimer = false;
|
||||
clearFilterSegmentList();
|
||||
}
|
||||
});
|
||||
|
||||
//
|
||||
// segment editor form events
|
||||
//
|
||||
|
|
@ -436,10 +586,12 @@ Segmentation = (function($) {
|
|||
|
||||
self.target.on('blur', "input.edit_segment_name", function (e) {
|
||||
var newName = $(this).val();
|
||||
if(newName.trim() != '') {
|
||||
$(e.currentTarget).parents("h3").find("span").text(newName).show();
|
||||
$(self.form).find("a.editSegmentName").show();
|
||||
$(this).remove();
|
||||
var segmentNameNode = $(e.currentTarget).parents("h3").find("span");
|
||||
|
||||
if(newName.trim()) {
|
||||
segmentNameNode.text(newName);
|
||||
} else {
|
||||
$(this).val(segmentNameNode.text());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -529,29 +681,38 @@ Segmentation = (function($) {
|
|||
|
||||
// upon clicking - add new segment block, then bind 'x' action to newly added row
|
||||
self.target.on('click', ".segment-add-row a", function(event, data){
|
||||
$(self.form).find(".segment-and:last").after(getAndDiv()).after(getMockedFormRow());
|
||||
var mockedRow = getMockedFormRow();
|
||||
$(self.form).find(".segment-and:last").after(getAndDiv()).after(mockedRow);
|
||||
if(typeof data !== "undefined"){
|
||||
$(self.form).find(".metricList:last").val(data);
|
||||
}
|
||||
$(self.form).find(".metricList:last").trigger('change');
|
||||
preselectFirstMetricMatch(mockedRow);
|
||||
doDragDropBindings();
|
||||
});
|
||||
|
||||
self.target.on("click", ".segment-add-row span", function(event, data){
|
||||
if(typeof data !== "undefined") {
|
||||
$(self.form).find(".segment-and:last").after(getAndDiv()).after(getMockedFormRow());
|
||||
var mockedRow = getMockedFormRow();
|
||||
$(self.form).find(".segment-and:last").after(getAndDiv()).after(mockedRow);
|
||||
preselectFirstMetricMatch(mockedRow);
|
||||
$(self.form).find(".metricList:last").val(data).trigger('change');
|
||||
doDragDropBindings();
|
||||
}
|
||||
});
|
||||
|
||||
// add new OR block
|
||||
self.target.on("click", ".segment-add-or a", function(event, data){
|
||||
$(event.currentTarget).parents(".segment-rows").find(".segment-or:last").after(getOrDiv()).after(getMockedInputRowHtml());
|
||||
self.target.on("click", ".segment-add-or a", function(event, data){
|
||||
var parentRows = $(event.currentTarget).parents(".segment-rows");
|
||||
|
||||
parentRows.find(".segment-or:last").after(getOrDiv()).after(getMockedInputRowHtml());
|
||||
if(typeof data !== "undefined"){
|
||||
$(event.currentTarget).parents(".segment-rows").find(".metricList:last").val(data);
|
||||
parentRows.find(".metricList:last").val(data);
|
||||
}
|
||||
$(event.currentTarget).parents(".segment-rows").find(".metricList:last").trigger('change');
|
||||
parentRows.find(".metricList:last").trigger('change');
|
||||
|
||||
var addedRow = parentRows.find('.segment-row:last');
|
||||
preselectFirstMetricMatch(addedRow);
|
||||
doDragDropBindings();
|
||||
});
|
||||
|
||||
|
|
@ -591,6 +752,15 @@ Segmentation = (function($) {
|
|||
segmentName: segmentName
|
||||
}, 'GET');
|
||||
ajaxHandler.useRegularCallbackInCaseOfError = true;
|
||||
ajaxHandler.setTimeout(20000);
|
||||
ajaxHandler.setErrorCallback(function(response) {
|
||||
loadingElement.hide();
|
||||
inputElement.autocomplete({
|
||||
source: [],
|
||||
minLength: 0
|
||||
});
|
||||
$(inputElement).autocomplete('search', $(inputElement).val());
|
||||
});
|
||||
ajaxHandler.setCallback(function(response) {
|
||||
loadingElement.hide();
|
||||
|
||||
|
|
@ -633,7 +803,12 @@ Segmentation = (function($) {
|
|||
}
|
||||
|
||||
matchSelector.append(optionsHtml);
|
||||
matchSelector.val(oldMatch);
|
||||
|
||||
if (matchSelector.find('option[value="' + oldMatch + '"]').length) {
|
||||
matchSelector.val(oldMatch);
|
||||
} else {
|
||||
preselectFirstMetricMatch(matchSelector.parent());
|
||||
}
|
||||
};
|
||||
|
||||
var getAddNewBlockButtonHtml = function()
|
||||
|
|
@ -664,20 +839,15 @@ Segmentation = (function($) {
|
|||
};
|
||||
|
||||
function openEditFormGivenSegment(option) {
|
||||
var segment = {};
|
||||
segment.idsegment = option.attr("data-idsegment");
|
||||
var idsegment = option.attr("data-idsegment");
|
||||
|
||||
var segmentExtra = getSegmentFromId(segment.idsegment);
|
||||
for(var item in segmentExtra)
|
||||
{
|
||||
segment[item] = segmentExtra[item];
|
||||
if(idsegment.length == 0) {
|
||||
displayFormAddNewSegment();
|
||||
} else {
|
||||
var segment = getSegmentFromId(idsegment);
|
||||
segment.definition = option.data("definition");
|
||||
openEditForm(segment);
|
||||
}
|
||||
|
||||
segment.name = option.attr("title");
|
||||
|
||||
segment.definition = option.data("definition");
|
||||
|
||||
openEditForm(segment);
|
||||
}
|
||||
|
||||
var doDragDropBindings = function(){
|
||||
|
|
@ -731,7 +901,7 @@ Segmentation = (function($) {
|
|||
// 1 - do most obvious selection -> mark whole categories matching search string
|
||||
// also expand whole category
|
||||
$(self.form).find('.segment-nav div > ul > li').each( function(){
|
||||
curStr = normalizeSearchString($(this).find("a.metric_category").text());
|
||||
curStr = normalizeSearchString($(this).find("a.metric_category").text());
|
||||
if(curStr.indexOf(search) > -1) {
|
||||
$(this).addClass("searchFound");
|
||||
$(this).find("ul").show();
|
||||
|
|
@ -739,7 +909,7 @@ Segmentation = (function($) {
|
|||
$(this).show();
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
// 2 - among all unselected categories find metrics which match and mark parent as search result
|
||||
$(self.form).find(".segment-nav div > ul > li:not(.searchFound)").each(function(){
|
||||
|
|
@ -788,8 +958,8 @@ Segmentation = (function($) {
|
|||
}
|
||||
|
||||
search = search.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
|
||||
.replace(/\s+/g, '_') // collapse whitespace and replace by underscore
|
||||
.replace(/-+/g, '-'); // collapse dashes
|
||||
.replace(/\s+/g, '_') // collapse whitespace and replace by underscore
|
||||
.replace(/-+/g, '-'); // collapse dashes
|
||||
return search;
|
||||
};
|
||||
|
||||
|
|
@ -816,7 +986,12 @@ Segmentation = (function($) {
|
|||
placeSegmentationFormControls();
|
||||
|
||||
if(mode == "edit") {
|
||||
$(self.form).find('.enable_all_users_select > option[value="'+segment.enable_all_users+'"]').prop("selected",true);
|
||||
var userSelector = $(self.form).find('.enable_all_users_select > option[value="' + segment.enable_all_users + '"]').prop("selected",true);
|
||||
|
||||
// Replace "Visible to me" by "Visible to $login" when user is super user
|
||||
if(hasSuperUserAccessAndSegmentCreatedByAnotherUser(segment)) {
|
||||
$(self.form).find('.enable_all_users_select > option[value="' + 0 + '"]').text(segment.login);
|
||||
}
|
||||
$(self.form).find('.visible_to_website_select > option[value="'+segment.enable_only_idsite+'"]').prop("selected",true);
|
||||
$(self.form).find('.auto_archive_select > option[value="'+segment.auto_archive+'"]').prop("selected",true);
|
||||
|
||||
|
|
@ -849,7 +1024,7 @@ Segmentation = (function($) {
|
|||
};
|
||||
|
||||
var closeForm = function () {
|
||||
self.form.unbind().remove();
|
||||
$(self.form).unbind().remove();
|
||||
self.target.closest('.segmentEditorPanel').removeClass('editing');
|
||||
};
|
||||
|
||||
|
|
@ -907,43 +1082,43 @@ Segmentation = (function($) {
|
|||
var makeDropList = function(spanId, selectId){
|
||||
var select = $(self.form).find(selectId).hide();
|
||||
var dropList = $( '<a class="dropList dropdown">' )
|
||||
.insertAfter( select )
|
||||
.text( select.children(':selected').text() )
|
||||
.autocomplete({
|
||||
delay: 0,
|
||||
minLength: 0,
|
||||
appendTo: "body",
|
||||
source: function( request, response ) {
|
||||
response( select.children( "option" ).map(function() {
|
||||
var text = $( this ).text();
|
||||
return {
|
||||
label: text,
|
||||
value: this.value,
|
||||
option: this
|
||||
};
|
||||
}) );
|
||||
},
|
||||
select: function( event, ui ) {
|
||||
event.preventDefault();
|
||||
ui.item.option.selected = true;
|
||||
// Mark original select>option
|
||||
$(spanId + ' option[value="' + ui.item.value + '"]', self.editorTemplate).prop('selected', true);
|
||||
dropList.text(ui.item.label);
|
||||
$(self.form).find(selectId).trigger("change");
|
||||
}
|
||||
})
|
||||
.click(function() {
|
||||
// close all other droplists made by this form
|
||||
$("a.dropList").autocomplete("close");
|
||||
// close if already visible
|
||||
if ( $(this).autocomplete( "widget" ).is(":visible") ) {
|
||||
$(this).autocomplete("close");
|
||||
return;
|
||||
}
|
||||
// pass empty string as value to search for, displaying all results
|
||||
$(this).autocomplete( "search", "" );
|
||||
.insertAfter( select )
|
||||
.text( select.children(':selected').text() )
|
||||
.autocomplete({
|
||||
delay: 0,
|
||||
minLength: 0,
|
||||
appendTo: "body",
|
||||
source: function( request, response ) {
|
||||
response( select.children( "option" ).map(function() {
|
||||
var text = $( this ).text();
|
||||
return {
|
||||
label: text,
|
||||
value: this.value,
|
||||
option: this
|
||||
};
|
||||
}) );
|
||||
},
|
||||
select: function( event, ui ) {
|
||||
event.preventDefault();
|
||||
ui.item.option.selected = true;
|
||||
// Mark original select>option
|
||||
$(spanId + ' option[value="' + ui.item.value + '"]', self.editorTemplate).prop('selected', true);
|
||||
dropList.text(ui.item.label);
|
||||
$(self.form).find(selectId).trigger("change");
|
||||
}
|
||||
})
|
||||
.click(function() {
|
||||
// close all other droplists made by this form
|
||||
$("a.dropList").autocomplete("close");
|
||||
// close if already visible
|
||||
if ( $(this).autocomplete( "widget" ).is(":visible") ) {
|
||||
$(this).autocomplete("close");
|
||||
return;
|
||||
}
|
||||
// pass empty string as value to search for, displaying all results
|
||||
$(this).autocomplete( "search", "" );
|
||||
|
||||
});
|
||||
});
|
||||
$('body').on('mouseup',function (e) {
|
||||
if (!$(e.target).parents(spanId).length
|
||||
&& !$(e.target).is(spanId)
|
||||
|
|
@ -990,14 +1165,13 @@ Segmentation = (function($) {
|
|||
return segmentation;
|
||||
})(jQuery);
|
||||
|
||||
|
||||
$(document).ready(function() {
|
||||
var exports = require('piwik/UI');
|
||||
var UIControl = exports.UIControl;
|
||||
|
||||
/**
|
||||
* Sets up and handles events for the segment selector & editor control.
|
||||
*
|
||||
*
|
||||
* @param {Element} element The HTML element generated by the SegmentSelectorControl PHP class. Should
|
||||
* have the CSS class 'segmentEditorPanel'.
|
||||
* @constructor
|
||||
|
|
@ -1023,7 +1197,7 @@ $(document).ready(function() {
|
|||
this.changeSegmentList = function () {};
|
||||
|
||||
var cleanupSegmentDefinition = function(definition) {
|
||||
definition = definition.replace("'", "%29");
|
||||
definition = definition.replace("'", "%27");
|
||||
definition = definition.replace("&", "%26");
|
||||
return definition;
|
||||
};
|
||||
|
|
@ -1083,7 +1257,7 @@ $(document).ready(function() {
|
|||
}
|
||||
}
|
||||
|
||||
self.props.availableSegments[idx] = params;
|
||||
$.extend( self.props.availableSegments[idx], params);
|
||||
self.rebuild();
|
||||
|
||||
self.impl.setSegment(params.definition);
|
||||
|
|
@ -1098,7 +1272,6 @@ $(document).ready(function() {
|
|||
ajaxHandler.send(true);
|
||||
};
|
||||
|
||||
|
||||
var deleteSegment = function(params){
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams({
|
||||
|
|
@ -1140,16 +1313,18 @@ $(document).ready(function() {
|
|||
};
|
||||
|
||||
var segmentFromRequest = encodeURIComponent(self.props.selectedSegment)
|
||||
|| broadcast.getValueFromHash('segment')
|
||||
|| broadcast.getValueFromUrl('segment');
|
||||
|| broadcast.getValueFromHash('segment')
|
||||
|| broadcast.getValueFromUrl('segment');
|
||||
if($.browser.mozilla) {
|
||||
segmentFromRequest = decodeURIComponent(segmentFromRequest);
|
||||
}
|
||||
|
||||
var userSegmentAccess = (this.props.authorizedToCreateSegments) ? "write" : "read";
|
||||
|
||||
this.impl = new Segmentation({
|
||||
"target" : this.$element.find(".segmentListContainer"),
|
||||
"editorTemplate": $('.SegmentEditor', self.$element),
|
||||
"segmentAccess" : "write",
|
||||
"segmentAccess" : userSegmentAccess,
|
||||
"availableSegments" : this.props.availableSegments,
|
||||
"addMethod": addSegment,
|
||||
"updateMethod": updateSegment,
|
||||
|
|
@ -1170,7 +1345,7 @@ $(document).ready(function() {
|
|||
}
|
||||
|
||||
if ($(e.target).closest('.segmentListContainer').length === 0
|
||||
&& self.$element.hasClass("visible")
|
||||
&& self.$element.hasClass("expanded")
|
||||
) {
|
||||
$(".segmentationContainer", self.$element).trigger("click");
|
||||
}
|
||||
|
|
@ -1178,8 +1353,6 @@ $(document).ready(function() {
|
|||
|
||||
$('body').on('mouseup', this.onMouseUp);
|
||||
|
||||
// re-initialize top controls since the size of the control is not the same after it's
|
||||
// initialized.
|
||||
initTopControls();
|
||||
};
|
||||
|
||||
|
|
@ -1213,4 +1386,4 @@ $(document).ready(function() {
|
|||
});
|
||||
|
||||
exports.SegmentSelectorControl = SegmentSelectorControl;
|
||||
});
|
||||
});
|
||||
|
|
|
|||
25
www/analytics/plugins/SegmentEditor/lang/bg.json
Normal file
25
www/analytics/plugins/SegmentEditor/lang/bg.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"SegmentEditor": {
|
||||
"AddANDorORCondition": "Добавяне на %s условие",
|
||||
"AddNewSegment": "Добави нов сегмент",
|
||||
"AreYouSureDeleteSegment": "Сигурни ли сте, че искате да изтриете този сегмент?",
|
||||
"AutoArchivePreProcessed": "Сегментираните отчети са предварително обработени (за по-голяма бързина се изисква archive.php cron)",
|
||||
"AutoArchiveRealTime": "Сегментираните отчети са обработени в реално време",
|
||||
"ChooseASegment": "Избери сегмент",
|
||||
"DefaultAllVisits": "Всички посещения",
|
||||
"DragDropCondition": "Състояние „Плъзгане & Пускане“",
|
||||
"LoadingSegmentedDataMayTakeSomeTime": "Обработката на сегментирани данни за посетителите може да отнеме няколко минути…",
|
||||
"OperatorAND": "И",
|
||||
"OperatorOR": "ИЛИ",
|
||||
"SaveAndApply": "Запази & Приложи",
|
||||
"SegmentDisplayedAllWebsites": "всички сайтове",
|
||||
"SegmentDisplayedThisWebsiteOnly": "само този уебсайт",
|
||||
"SegmentIsDisplayedForWebsite": "и се показва за",
|
||||
"SegmentNotApplied": "Сегмент '%s' не е приложен",
|
||||
"SelectSegmentOfVisitors": "Изберете сегмент на посетителите:",
|
||||
"ThisSegmentIsVisibleTo": "Този сегмент е видим за:",
|
||||
"VisibleToAllUsers": "всички потребители",
|
||||
"VisibleToMe": "аз",
|
||||
"YouMustBeLoggedInToCreateSegments": "Трябва да сте вписани, за да създавате и редактирате персонализираните посетителски сегменти."
|
||||
}
|
||||
}
|
||||
36
www/analytics/plugins/SegmentEditor/lang/cs.json
Normal file
36
www/analytics/plugins/SegmentEditor/lang/cs.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"SegmentEditor": {
|
||||
"PluginDescription": "Vytvářejte a znovu použijte vlastní segmenty návštěvníků za použití editoru segmentů.",
|
||||
"AddANDorORCondition": "Přidat podmínku %s",
|
||||
"AddNewSegment": "Přidat nový segment",
|
||||
"AreYouSureDeleteSegment": "Opravdu chcete odstranit tento segment?",
|
||||
"AutoArchivePreProcessed": "Segmentovaná hlášení jsou předzpracována rychleji (vyžadují cron)",
|
||||
"AutoArchiveRealTime": "Segmentovaná hlášení jsou zpracována v reálném čase",
|
||||
"ChooseASegment": "Zvolte segment",
|
||||
"CurrentlySelectedSegment": "Aktuálně vybraný segment: %s",
|
||||
"DataAvailableAtLaterDate": "Vaše segmentovaná analytická hlášení budou dostupná později. Omlouváme se za tuto nepříjemnost.",
|
||||
"DefaultAllVisits": "Všechny návštěvy",
|
||||
"DragDropCondition": "Přetáhněte podmínku",
|
||||
"LoadingSegmentedDataMayTakeSomeTime": "Zpracování segmentovaných dat návštěvníků může pár minut trvat...",
|
||||
"OperatorAND": "AND",
|
||||
"OperatorOR": "OR",
|
||||
"SaveAndApply": "Uložit a použít",
|
||||
"SegmentDisplayedAllWebsites": "Všechny webové stránky",
|
||||
"SegmentDisplayedThisWebsiteOnly": "Pouze tyto webové stránky",
|
||||
"SegmentIsDisplayedForWebsite": "A zobrazený po",
|
||||
"SegmentNotApplied": "Segment %s není aplikován",
|
||||
"SegmentNotAppliedMessage": "Požadujete data pro vlastní segment %s, ale konfigurace Piwiku aktuálně nedovoluje z důvodů výkonu zpracování hlášení v reálném čase.",
|
||||
"SelectSegmentOfVisitors": "Vyberte segment návštěvníků",
|
||||
"ThisSegmentIsVisibleTo": "Tento segment je viditelný",
|
||||
"VisibleToAllUsers": "Všem uživatelům",
|
||||
"VisibleToMe": "Mně",
|
||||
"YouMayChangeSetting": "Jinak můžete nastavení změnit v souboru %1$s, nebo můžete upravit tento segment a zvolit %2$s.",
|
||||
"YouMustBeLoggedInToCreateSegments": "Pro vytváření a úpravu vlastních segmentů návštěvníků musíte být přihlášen.",
|
||||
"YouDontHaveAccessToCreateSegments": "Pro vytváření a úpravu segmentů nemáte požadovanou přístupovou úroveň.",
|
||||
"AddingSegmentForAllWebsitesDisabled": "Přidávání segmentů pro všechny stránky bylo zakázáno.",
|
||||
"SegmentXIsAUnionOf": "%s je propojení těchto segmentů:",
|
||||
"CustomSegment": "Vlastní segment",
|
||||
"SegmentOperatorIsNullOrEmpty": "je nulový nebo prázdný",
|
||||
"SegmentOperatorIsNotNullNorEmpty": "není nulový nebo prázdný"
|
||||
}
|
||||
}
|
||||
30
www/analytics/plugins/SegmentEditor/lang/da.json
Normal file
30
www/analytics/plugins/SegmentEditor/lang/da.json
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"SegmentEditor": {
|
||||
"AddANDorORCondition": "Tilføj %s betingelse",
|
||||
"AddNewSegment": "Tilføj nyt segment",
|
||||
"AreYouSureDeleteSegment": "Er du sikker på, at du vil slette dette segment?",
|
||||
"AutoArchivePreProcessed": "Segmenterede rapporter behandles på forhånd (er hurtigere, kræver archive.php cron)",
|
||||
"AutoArchiveRealTime": "Segmenterede rapporter behandles tidstro",
|
||||
"ChooseASegment": "Vælg et segment",
|
||||
"DataAvailableAtLaterDate": "Dine segmenterede analyserapporter vil være tilgængelig senere. Vi undskylder ulejligheden.",
|
||||
"DefaultAllVisits": "Alle besøg",
|
||||
"DragDropCondition": "Træk og slip betingelse",
|
||||
"LoadingSegmentedDataMayTakeSomeTime": "Behandling af segmenterede besøgsdata kan tage et par minutter...",
|
||||
"OperatorAND": "OG",
|
||||
"OperatorOR": "ELLER",
|
||||
"SaveAndApply": "Gem og anvend",
|
||||
"SegmentDisplayedAllWebsites": "alle websteder",
|
||||
"SegmentDisplayedThisWebsiteOnly": "kun dette websted",
|
||||
"SegmentIsDisplayedForWebsite": "og vises for",
|
||||
"SegmentNotApplied": "Segment '%s' anvendes ikke",
|
||||
"SegmentNotAppliedMessage": "Du beder om data til brugerdefineret segment '%s', Piwik konfigurationen forhindrer tidstro behandling af rapporter pga ydeevne grunde.",
|
||||
"SelectSegmentOfVisitors": "Vælg et segment af besøgende:",
|
||||
"ThisSegmentIsVisibleTo": "Segmentet er synligt for:",
|
||||
"VisibleToAllUsers": "Alle brugere",
|
||||
"VisibleToMe": "mig",
|
||||
"YouMayChangeSetting": "Alternativt kan du ændre indstillingen i konfigurationsfilen (%1$s), eller redigere dette segment og vælg '%2$s'.",
|
||||
"YouMustBeLoggedInToCreateSegments": "Du skal være logget ind for at oprette og anvende brugerdefinerede besøgssegmenter.",
|
||||
"YouDontHaveAccessToCreateSegments": "Du har ikke det nødvendige adgangsniveau til at oprette og redigere segmenter.",
|
||||
"AddingSegmentForAllWebsitesDisabled": "Tilføjelse af segmenter for alle websteder er blevet deaktiveret."
|
||||
}
|
||||
}
|
||||
35
www/analytics/plugins/SegmentEditor/lang/de.json
Normal file
35
www/analytics/plugins/SegmentEditor/lang/de.json
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"SegmentEditor": {
|
||||
"PluginDescription": "Erstellen und verwenden sie eigene Besucher-Segmente mit dem Segment-Editor",
|
||||
"AddANDorORCondition": "%s Bedingung hinzufügen",
|
||||
"AddNewSegment": "Neues Segment hinzufügen",
|
||||
"AreYouSureDeleteSegment": "Möchten Sie dieses Segment wirklich löschen?",
|
||||
"AutoArchivePreProcessed": "Segmentierte Berichte werden im Voraus verarbeitet (schneller, benötigt archive.php Cron)",
|
||||
"AutoArchiveRealTime": "Segmentierte Berichte werden in Echtzeit verarbeitet.",
|
||||
"ChooseASegment": "Segment auswählen",
|
||||
"CurrentlySelectedSegment": "Aktuell ausgewähltes Segment: %s",
|
||||
"DataAvailableAtLaterDate": "Ihre segmentierten Analytik-Berichte stehen später zur Verfügung. Wir entschuldigen uns für die Unannehmlichkeit.",
|
||||
"DefaultAllVisits": "Alle Besuche",
|
||||
"DragDropCondition": "Bedingung durch Drag & Drop hinzufügen",
|
||||
"LoadingSegmentedDataMayTakeSomeTime": "Die Verarbeitung der segmentierten Besucherdaten kann einige Minuten dauern...",
|
||||
"OperatorAND": "UND",
|
||||
"OperatorOR": "ODER",
|
||||
"SaveAndApply": "Speichern & Übernehmen",
|
||||
"SegmentDisplayedAllWebsites": "alle Websites",
|
||||
"SegmentDisplayedThisWebsiteOnly": "nur diese Website",
|
||||
"SegmentIsDisplayedForWebsite": "und wird angezeigt für",
|
||||
"SegmentNotApplied": "Segment '%s' nicht angewendet",
|
||||
"SegmentNotAppliedMessage": "Sie fragen Daten für das benutzerdefinierte Segment '%s' an, die Piwik-Konfiguration verhindert jedoch aktuell Echtzeit-Verarbeitung von Berichten aus Performance-Gründen.",
|
||||
"SelectSegmentOfVisitors": "Wählen Sie ein Segment an Besuchern aus:",
|
||||
"ThisSegmentIsVisibleTo": "Dieses Segment ist sichtbar für:",
|
||||
"VisibleToAllUsers": "alle Benutzer",
|
||||
"VisibleToMe": "mich",
|
||||
"YouMayChangeSetting": "Alternativ können Sie die Einstellung in der Konfigurationsdatei (%1$s) ändern, oder ändern Sie dieses Segment und wählen '%2$s'.",
|
||||
"YouMustBeLoggedInToCreateSegments": "Sie müssen sich anmelden um eigene Besuchersegmente anzulegen oder zu bearbeiten.",
|
||||
"YouDontHaveAccessToCreateSegments": "Sie haben nicht die benötigten Berechtigungen um Segmente anzulegen und zu bearbeiten.",
|
||||
"AddingSegmentForAllWebsitesDisabled": "Das Hinzufügen von Segmenten wurde für alle Websites deaktiviert.",
|
||||
"CustomSegment": "Benutzerdefiniertes Segment",
|
||||
"SegmentOperatorIsNullOrEmpty": "Ist NULL oder leer",
|
||||
"SegmentOperatorIsNotNullNorEmpty": "Ist weder NULL noch leer"
|
||||
}
|
||||
}
|
||||
36
www/analytics/plugins/SegmentEditor/lang/el.json
Normal file
36
www/analytics/plugins/SegmentEditor/lang/el.json
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"SegmentEditor": {
|
||||
"PluginDescription": "Δημιουργήστε και επαναχρησιμοποιήστε τα προσαρμοσμένα Τμήματα επισκεπτών με τον Επεξεργαστή Τμημάτων.",
|
||||
"AddANDorORCondition": "Προσθήκη της %s συνθήκης",
|
||||
"AddNewSegment": "Προσθήκη νέου τμήματος",
|
||||
"AreYouSureDeleteSegment": "Είστε σίγουροι για τη διαγραφή του τμήματος;",
|
||||
"AutoArchivePreProcessed": "οι αναφορές τμημάτων προεπεξεργάζονται (γρηγορότερα, απαιτείται το archive.php με cron)",
|
||||
"AutoArchiveRealTime": "οι αναφορές τμημάτων επεξεργάζονται σε πραγματικό χρόνο",
|
||||
"ChooseASegment": "Επιλέξτε ένα τμήμα",
|
||||
"CurrentlySelectedSegment": "Επιλεγμένο τμήμα αυτή τη στιγμή: %s",
|
||||
"DataAvailableAtLaterDate": "Οι τμηματικές αναφορές αναλυτικών θα είναι αργότερα διαθέσιμες. Ζητούμε συγγνώμη για την ταλαιπωρία.",
|
||||
"DefaultAllVisits": "Όλες οι επισκέψεις",
|
||||
"DragDropCondition": "Συνθήκη με Σύρε & Άσε",
|
||||
"LoadingSegmentedDataMayTakeSomeTime": "Η επεξεργασία των δεδομένων των τμημάτων επισκεπτών μπορεί να διαρκέσει κάποια λεπτά...",
|
||||
"OperatorAND": "ΚΑΙ",
|
||||
"OperatorOR": "Ή",
|
||||
"SaveAndApply": "Αποθήκευση και εφαρμογή",
|
||||
"SegmentDisplayedAllWebsites": "όλους τους ιστοτόπους",
|
||||
"SegmentDisplayedThisWebsiteOnly": "μόνο αυτόν τον ιστοτόπο",
|
||||
"SegmentIsDisplayedForWebsite": "και εμφανίζεται για",
|
||||
"SegmentNotApplied": "Το τμήμα '%s' δεν εφαρμόζεται",
|
||||
"SegmentNotAppliedMessage": "Ζητάτε δεδομένα για το Προσαρμοσμένο Τμήμα '%s', ωστόσο η τρέχουσα παραμετροποίηση του Piwik εμποδίζει την σε πραγματικό χρόνο επεξεργασία των αναφορών για λόγους απόδοσης.",
|
||||
"SelectSegmentOfVisitors": "Επιλέξτε ένα τμήμα επισκεπτών:",
|
||||
"ThisSegmentIsVisibleTo": "Το τμήμα αυτό είναι ορατό σε:",
|
||||
"VisibleToAllUsers": "όλους τους χρήστες",
|
||||
"VisibleToMe": "εμένα",
|
||||
"YouMayChangeSetting": "Εναλλακτικά, μπορείτε να αλλάξετε τη ρύθμιση στο αρχείο ρυθμίσεων (%1$s), ή να τροποποιήσετε το Τμήμα αυτό και να επιλέξετε '%2$s'.",
|
||||
"YouMustBeLoggedInToCreateSegments": "Θα πρέπει να έχετε κάνει είσοδο για να δημιουργήσετε και να επεξεργαστείτε προσαρμοσμένα τμήματα επισκεπτών.",
|
||||
"YouDontHaveAccessToCreateSegments": "Δεν διαθέτετε την απαιτούμενη πρόσβαση ασφαλείας για να δημιουργείτε και να τροποποιείτε τμήματα.",
|
||||
"AddingSegmentForAllWebsitesDisabled": "Η προσθήκη τμημάτων έχει απενεργοποιηθεί για όλους τους ιστοτόπους.",
|
||||
"SegmentXIsAUnionOf": "Το %s είναι η ένωση αυτών των τμημάτων:",
|
||||
"CustomSegment": "Προσαρμοσμένο τμήμα",
|
||||
"SegmentOperatorIsNullOrEmpty": "είναι άκυρο (null) ή κενό",
|
||||
"SegmentOperatorIsNotNullNorEmpty": "δεν είναι άκυρο (null) ή άδειο"
|
||||
}
|
||||
}
|
||||
38
www/analytics/plugins/SegmentEditor/lang/en.json
Normal file
38
www/analytics/plugins/SegmentEditor/lang/en.json
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"SegmentEditor": {
|
||||
"PluginDescription": "Create and reuse custom visitor Segments with the Segment Editor.",
|
||||
"AddANDorORCondition": "Add %s condition",
|
||||
"AddNewSegment": "Add new segment",
|
||||
"AreYouSureDeleteSegment": "Are you sure you want to delete this segment?",
|
||||
"AutoArchivePreProcessed": "segmented reports are pre-processed (faster, requires cron)",
|
||||
"AutoArchiveRealTime": "segmented reports are processed in real time",
|
||||
"ChooseASegment": "Choose a segment",
|
||||
"CurrentlySelectedSegment": "Currently selected segment: %s",
|
||||
"DataAvailableAtLaterDate": "Your segmented analytics reports will be available later. We apologize for the inconvenience.",
|
||||
"DefaultAllVisits": "All visits",
|
||||
"DragDropCondition": "Drag & Drop condition",
|
||||
"LoadingSegmentedDataMayTakeSomeTime": "Processing segmented visitor data may take a few minutes...",
|
||||
"OperatorAND": "AND",
|
||||
"OperatorOR": "OR",
|
||||
"SaveAndApply": "Save & Apply",
|
||||
"SegmentDisplayedAllWebsites": "all websites",
|
||||
"SegmentDisplayedThisWebsiteOnly": "this website only",
|
||||
"SegmentIsDisplayedForWebsite": "and displayed for",
|
||||
"SegmentNotApplied": "Segment '%s' not applied",
|
||||
"SegmentNotAppliedMessage": "You are requesting data for the Custom Segment '%s', this Piwik configuration currently prevents real time processing of reports for performance reasons.",
|
||||
"SelectSegmentOfVisits": "Select a segment of visits:",
|
||||
"ThisSegmentIsVisibleTo": "This segment is visible to:",
|
||||
"VisibleToAllUsers": "all users",
|
||||
"VisibleToMe": "me",
|
||||
"YouMayChangeSetting": "Alternatively you may change the setting in the config file (%1$s), or edit this Segment and choose '%2$s'.",
|
||||
"VisibleToSuperUser": "Visible to you because you have Super User access",
|
||||
"SharedWithYou": "Shared with you",
|
||||
"YouMustBeLoggedInToCreateSegments": "You must be logged in to create and edit custom visitor segments.",
|
||||
"YouDontHaveAccessToCreateSegments": "You don't have the required access level to create and edit segments.",
|
||||
"AddingSegmentForAllWebsitesDisabled": "Adding segments for all websites has been disabled.",
|
||||
"SegmentXIsAUnionOf": "%s is a union of these segments:",
|
||||
"CustomSegment": "Custom Segment",
|
||||
"SegmentOperatorIsNullOrEmpty": "is null or empty",
|
||||
"SegmentOperatorIsNotNullNorEmpty": "is not null nor empty"
|
||||
}
|
||||
}
|
||||
31
www/analytics/plugins/SegmentEditor/lang/es.json
Normal file
31
www/analytics/plugins/SegmentEditor/lang/es.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"SegmentEditor": {
|
||||
"PluginDescription": "Cree y reutilize Segmentos de visitante personalizados con el Editor de Segmento.",
|
||||
"AddANDorORCondition": "Agregar condición %s",
|
||||
"AddNewSegment": "Agregar nuevo segmento",
|
||||
"AreYouSureDeleteSegment": "¿Está seguro que desea eliminar este segmento?",
|
||||
"AutoArchivePreProcessed": "los informes segmentados son pre-procesados (rápidamente, requiere cron)",
|
||||
"AutoArchiveRealTime": "los informes segmentados son procesados en tiempo real",
|
||||
"ChooseASegment": "Elegir un segmento",
|
||||
"DataAvailableAtLaterDate": "Sus informes analíticos segmentados estarán disponibles más tarde. Lamentamos la inconveniencia.",
|
||||
"DefaultAllVisits": "Todas las visitas",
|
||||
"DragDropCondition": "Arrastrar & soltar condición",
|
||||
"LoadingSegmentedDataMayTakeSomeTime": "Procesando los datos de visitante segmentados pueden tomar unos minutos…",
|
||||
"OperatorAND": "Y",
|
||||
"OperatorOR": "O",
|
||||
"SaveAndApply": "Guardar & aplicar",
|
||||
"SegmentDisplayedAllWebsites": "todos los sitios de internet",
|
||||
"SegmentDisplayedThisWebsiteOnly": "este sitio de internet únicamente",
|
||||
"SegmentIsDisplayedForWebsite": "y mostrado para",
|
||||
"SegmentNotApplied": "Segmento '%s' no aplicado",
|
||||
"SegmentNotAppliedMessage": "Está solicitando datos para el segmento personalizado '%s', esta configuración de Piwik actualmente impide el proceso en tiempo real de informes por razones de rendimiento.",
|
||||
"SelectSegmentOfVisitors": "Seleccione un segmento de visitantes:",
|
||||
"ThisSegmentIsVisibleTo": "Este segmento es visible para:",
|
||||
"VisibleToAllUsers": "todos los usuarios",
|
||||
"VisibleToMe": "yo",
|
||||
"YouMayChangeSetting": "Alternativamente puede cambiar la configuración en el archivo config (%1$s) o modificar este segmento y elegir '%2$s'.",
|
||||
"YouMustBeLoggedInToCreateSegments": "Debe estar conectado para crear y editar segmentos de usuario personalizados.",
|
||||
"YouDontHaveAccessToCreateSegments": "No posee el nivel de acceso requerido para crear y editar segmentos.",
|
||||
"AddingSegmentForAllWebsitesDisabled": "Añadir segmentos para todos los sitios de internet se ha deshabilitado."
|
||||
}
|
||||
}
|
||||
21
www/analytics/plugins/SegmentEditor/lang/et.json
Normal file
21
www/analytics/plugins/SegmentEditor/lang/et.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"SegmentEditor": {
|
||||
"AddANDorORCondition": "Lisa %s tingimus",
|
||||
"AddNewSegment": "Lisa uus segment",
|
||||
"AutoArchivePreProcessed": "segmentide raportid protsessitakse ette (kiirem, aga vajab archive.php cron seadistust)",
|
||||
"AutoArchiveRealTime": "segmentide raportid protsessitakse reaalajas",
|
||||
"ChooseASegment": "Vali segment",
|
||||
"DefaultAllVisits": "Kõik külastused",
|
||||
"DragDropCondition": "Lohista hiirega tingimused siia",
|
||||
"OperatorAND": "JA",
|
||||
"OperatorOR": "VÕI",
|
||||
"SaveAndApply": "Salvesta ja rakenda",
|
||||
"SegmentDisplayedAllWebsites": "kõik veebilehed",
|
||||
"SegmentDisplayedThisWebsiteOnly": "ainult see veebileht",
|
||||
"SegmentIsDisplayedForWebsite": "ja kuvatakse veebilehele",
|
||||
"SelectSegmentOfVisitors": "Vali külastajate segment:",
|
||||
"ThisSegmentIsVisibleTo": "Antud segment on nähtav:",
|
||||
"VisibleToAllUsers": "kõik kasutajad",
|
||||
"VisibleToMe": "mina"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue