diff options
author | Ben <ben.burgess@innocraft.com> | 2022-05-25 04:25:04 +0300 |
---|---|---|
committer | Ben <ben.burgess@innocraft.com> | 2022-05-25 04:25:04 +0300 |
commit | 7a3865b02d6c4511db639d61f6de7e9c216fa675 (patch) | |
tree | f73b884c3ce969fba97b391d5652ea0a308d6b7d /plugins/CoreHome | |
parent | 276ed587372cd76f44e51f9a98462c45f1eb8f5c (diff) | |
parent | 53c00a78caf96d24dd8f7f74dc8fd74268b312b1 (diff) |
Merge branch '4.x-dev' into lockaltlockalt
Diffstat (limited to 'plugins/CoreHome')
274 files changed, 16458 insertions, 6553 deletions
diff --git a/plugins/CoreHome/Categories/VisitorsCategory.php b/plugins/CoreHome/Categories/VisitorsCategory.php index 8cbbbb9033..ad75ace57a 100644 --- a/plugins/CoreHome/Categories/VisitorsCategory.php +++ b/plugins/CoreHome/Categories/VisitorsCategory.php @@ -10,7 +10,6 @@ namespace Piwik\Plugins\CoreHome\Categories; use Piwik\Category\Category; use Piwik\Piwik; -use Piwik\Url; class VisitorsCategory extends Category { diff --git a/plugins/CoreHome/Columns/Metrics/ConversionRate.php b/plugins/CoreHome/Columns/Metrics/ConversionRate.php index 16dd7bba1b..31447dd729 100644 --- a/plugins/CoreHome/Columns/Metrics/ConversionRate.php +++ b/plugins/CoreHome/Columns/Metrics/ConversionRate.php @@ -8,7 +8,6 @@ namespace Piwik\Plugins\CoreHome\Columns\Metrics; use Piwik\DataTable\Row; -use Piwik\Metrics; use Piwik\Metrics\Formatter; use Piwik\Piwik; use Piwik\Plugin\ProcessedMetric; diff --git a/plugins/CoreHome/Columns/Metrics/EvolutionMetric.php b/plugins/CoreHome/Columns/Metrics/EvolutionMetric.php index ab34138b8d..d993caf914 100644 --- a/plugins/CoreHome/Columns/Metrics/EvolutionMetric.php +++ b/plugins/CoreHome/Columns/Metrics/EvolutionMetric.php @@ -9,8 +9,12 @@ namespace Piwik\Plugins\CoreHome\Columns\Metrics; use Piwik\DataTable; +use Piwik\Archive\DataTableFactory; use Piwik\DataTable\Row; +use Piwik\Date; use Piwik\Metrics; +use Piwik\Plugins\SitesManager\API; +use Piwik\Site; use Piwik\Metrics\Formatter; use Piwik\Piwik; use Piwik\Plugin\Metric; @@ -37,6 +41,11 @@ class EvolutionMetric extends ProcessedMetric private $evolutionMetricName; /** + * @var string + */ + private $evolutionMetricTrendName; + + /** * @var int */ private $quotientPrecision; @@ -47,6 +56,13 @@ class EvolutionMetric extends ProcessedMetric private $pastData; /** + * @var DataTable + */ + private $currentData; + + private $isLowerBetter = false; + + /** * The list of labels leading to the current subtable being processed. Used to get the proper subtable in * $pastData. * @@ -62,17 +78,23 @@ class EvolutionMetric extends ProcessedMetric * @param string|false $evolutionMetricName The name of the evolution processed metric. Defaults to * $wrapped's name with `'_evolution'` appended. * @param int $quotientPrecision The percent's quotient precision. + * @param DataTable|null $currentData The current datatable, optional but required to calculate the proportionate + * evolution values */ - public function __construct($wrapped, DataTable $pastData = null, $evolutionMetricName = false, $quotientPrecision = 0) + public function __construct($wrapped, ?DataTable $pastData = null, $evolutionMetricName = false, $quotientPrecision = 0, + ?DataTable $currentData = null) { $this->wrapped = $wrapped; + $this->isLowerBetter = Metrics::isLowerValueBetter($this->wrapped); $this->pastData = $pastData; + $this->currentData = $currentData; if (empty($evolutionMetricName)) { $wrappedName = $this->getWrappedName(); $evolutionMetricName = $wrappedName . '_evolution'; } + $this->evolutionMetricTrendName = $evolutionMetricName . '_trend'; $this->evolutionMetricName = $evolutionMetricName; $this->quotientPrecision = $quotientPrecision; } @@ -82,6 +104,11 @@ class EvolutionMetric extends ProcessedMetric return $this->evolutionMetricName; } + public function getTrendName() + { + return $this->evolutionMetricTrendName; + } + public function getTranslatedName() { if ($this->wrapped instanceof Metric) { @@ -93,6 +120,15 @@ class EvolutionMetric extends ProcessedMetric return Piwik::translate('CoreHome_EvolutionMetricName', [$metricName]); } + public function getTrendValue($computedValue = 0) + { + if ($this->isLowerBetter) { + return ($computedValue < 0 ? 1 : ($computedValue > 0 ? -1 : 0)); + } + + return ($computedValue < 0 ? -1 : ($computedValue > 0 ? 1 : 0)); + } + public function compute(Row $row) { $columnName = $this->getWrappedName(); @@ -101,6 +137,16 @@ class EvolutionMetric extends ProcessedMetric $currentValue = $this->getMetric($row, $columnName); $pastValue = $pastRow ? $this->getMetric($pastRow, $columnName) : 0; + // Reduce past value proportionally to match the percent of the current period which is complete, if applicable + $ratio = self::getRatio($this->currentData, $this->pastData, $row); + $period = $this->pastData->getMetadata(DataTableFactory::TABLE_METADATA_PERIOD_INDEX); + $row->setMetadata('ratio', $ratio); + $row->setMetadata('currencySymbol', $row['label'] !== DataTable::ID_SUMMARY_ROW ? Site::getCurrencySymbolFor($row['label']) : API::getInstance()->getDefaultCurrency()); + $row->setMetadata('previous_'.$columnName, $pastValue); + $row->setMetadata('periodName', $period->getLabel()); + $row->setMetadata('previousRange', $period->getLocalizedShortString()); + $pastValue = ($pastValue * $ratio); + $dividend = $currentValue - $pastValue; $divisor = $pastValue; @@ -170,4 +216,56 @@ class EvolutionMetric extends ProcessedMetric } return $result; } + + /** + * Calculate the ratio of time between a past period and current incomplete period + * + * eg. if today is Thursday at 12:00pm and the past period is a week then the ratio is 0.5, exactly half of the + * current incomplete period has passed + * + * If the current period end is in the past then the ratio will always be 1, since the current period is complete. + * + * @param DataTable|null $currentData + * @param DataTable|null $pastData + * @param Row $row + * @return float|int + * @throws \Exception + */ + public static function getRatio(?DataTable $currentData, ?DataTable $pastData, Row $row) + { + $ratio = 1; + + if ($currentData != null && $pastData != null) { + + $p = $pastData->getMetadata(DataTableFactory::TABLE_METADATA_PERIOD_INDEX); + + $pStart = $p->getDateStart()->setTime('00:00:00'); + $pEnd = $p->getDateEnd()->setTime('23:59:59'); + + $c = $currentData->getMetadata(DataTableFactory::TABLE_METADATA_PERIOD_INDEX); + $cStart = $c->getDateStart()->setTime('00:00:00'); + $cEnd = $c->getDateEnd()->setTime('23:59:59'); + + $nowTS = Date::getNowTimestamp(); + + // If we know the date the the datatable data was generated then use that instead of now + $archivedDateStr = $row->getMetadata(DataTable::ARCHIVED_DATE_METADATA_NAME); + + if ($archivedDateStr) { + $archivedDate = Date::factory($archivedDateStr); + if ($archivedDate) { + $nowTS = Date::factory($archivedDate)->getTimestamp(); + } + } + + if ($cStart->getTimestamp() <= $nowTS && $cEnd->getTimestamp() >= $nowTS) { + $secsInPastPeriod = $pEnd->getTimestamp() - $pStart->getTimestamp(); + $secsInCurrentPeriod = $nowTS - $cStart->getTimestamp(); + $ratio = $secsInCurrentPeriod / $secsInPastPeriod; + } + } + + return round($ratio, 3); + + } }
\ No newline at end of file diff --git a/plugins/CoreHome/Columns/Metrics/VisitsPercent.php b/plugins/CoreHome/Columns/Metrics/VisitsPercent.php index 325e1e3e48..49f18a8aa6 100644 --- a/plugins/CoreHome/Columns/Metrics/VisitsPercent.php +++ b/plugins/CoreHome/Columns/Metrics/VisitsPercent.php @@ -13,7 +13,6 @@ use Piwik\DataTable\Row; use Piwik\Metrics\Formatter; use Piwik\Piwik; use Piwik\Plugin\ProcessedMetric; -use Piwik\Plugin\Report; /** * Percent of visits in the whole table. Calculated as: diff --git a/plugins/CoreHome/Columns/ServerMinute.php b/plugins/CoreHome/Columns/ServerMinute.php index 8f2c761d3f..ec1128351f 100644 --- a/plugins/CoreHome/Columns/ServerMinute.php +++ b/plugins/CoreHome/Columns/ServerMinute.php @@ -16,7 +16,7 @@ class ServerMinute extends ActionDimension protected $columnName = 'server_time'; protected $segmentName = 'actionServerMinute'; protected $sqlSegment = 'MINUTE(log_link_visit_action.server_time)'; - protected $nameSingular = 'VisitTime_ColumnServerMinute'; + protected $nameSingular = 'VisitTime_ColumnUTCMinute'; protected $type = self::TYPE_DATETIME; protected $acceptValues = '0, 1, 2, 3, ..., 56, 57, 58, 59'; diff --git a/plugins/CoreHome/Columns/ServerTime.php b/plugins/CoreHome/Columns/ServerTime.php index d2005f11fa..9c41d89db5 100644 --- a/plugins/CoreHome/Columns/ServerTime.php +++ b/plugins/CoreHome/Columns/ServerTime.php @@ -23,7 +23,7 @@ class ServerTime extends ActionDimension protected $columnType = 'DATETIME NOT NULL'; protected $segmentName = 'actionServerHour'; protected $sqlSegment = 'HOUR(log_link_visit_action.server_time)'; - protected $nameSingular = 'VisitTime_ColumnServerHour'; + protected $nameSingular = 'VisitTime_ColumnSiteHour'; protected $type = self::TYPE_DATETIME; public function __construct() diff --git a/plugins/CoreHome/Columns/UserId.php b/plugins/CoreHome/Columns/UserId.php index db23f9b7f0..bc0c77ab74 100644 --- a/plugins/CoreHome/Columns/UserId.php +++ b/plugins/CoreHome/Columns/UserId.php @@ -9,13 +9,11 @@ namespace Piwik\Plugins\CoreHome\Columns; use Piwik\Cache; -use Piwik\Common; use Piwik\DataTable; use Piwik\DataTable\Map; use Piwik\Metrics; use Piwik\Plugin; use Piwik\Plugin\Dimension\VisitDimension; -use Piwik\Plugins\VisitsSummary\API as VisitsSummaryApi; use Piwik\Tracker\Request; use Piwik\Tracker\Visitor; use Piwik\Tracker\Action; diff --git a/plugins/CoreHome/Columns/VisitFirstActionMinute.php b/plugins/CoreHome/Columns/VisitFirstActionMinute.php index 1db6e914f4..47e2d0ff66 100644 --- a/plugins/CoreHome/Columns/VisitFirstActionMinute.php +++ b/plugins/CoreHome/Columns/VisitFirstActionMinute.php @@ -23,7 +23,7 @@ class VisitFirstActionMinute extends VisitDimension protected $sqlSegment = 'MINUTE(log_visit.visit_first_action_time)'; protected $segmentName = 'visitStartServerMinute'; protected $acceptValues = '0, 1, 2, 3, ..., 56, 57, 58, 59'; - protected $nameSingular = 'VisitTime_ColumnVisitStartServerMinute'; + protected $nameSingular = 'VisitTime_ColumnVisitStartUTCMinute'; public function __construct() { diff --git a/plugins/CoreHome/Columns/VisitFirstActionTime.php b/plugins/CoreHome/Columns/VisitFirstActionTime.php index 5f76c50763..56ee0231ed 100644 --- a/plugins/CoreHome/Columns/VisitFirstActionTime.php +++ b/plugins/CoreHome/Columns/VisitFirstActionTime.php @@ -26,7 +26,7 @@ class VisitFirstActionTime extends VisitDimension protected $sqlSegment = 'HOUR(log_visit.visit_first_action_time)'; protected $segmentName = 'visitStartServerHour'; protected $acceptValues = '0, 1, 2, 3, ..., 20, 21, 22, 23'; - protected $nameSingular = 'VisitTime_ColumnVisitStartServerHour'; + protected $nameSingular = 'VisitTime_ColumnVisitStartSiteHour'; public function __construct() { diff --git a/plugins/CoreHome/Columns/VisitGoalBuyer.php b/plugins/CoreHome/Columns/VisitGoalBuyer.php index 904519494b..711380cf9a 100644 --- a/plugins/CoreHome/Columns/VisitGoalBuyer.php +++ b/plugins/CoreHome/Columns/VisitGoalBuyer.php @@ -11,7 +11,6 @@ namespace Piwik\Plugins\CoreHome\Columns; use Piwik\Metrics\Formatter; use Piwik\Piwik; use Piwik\Plugin\Dimension\VisitDimension; -use Piwik\Plugins\CoreHome\Segment; use Piwik\Tracker\Action; use Piwik\Tracker\GoalManager; use Piwik\Tracker\Request; diff --git a/plugins/CoreHome/Columns/VisitLastActionDate.php b/plugins/CoreHome/Columns/VisitLastActionDate.php index 6b2fd67563..9f0d1cdaf9 100644 --- a/plugins/CoreHome/Columns/VisitLastActionDate.php +++ b/plugins/CoreHome/Columns/VisitLastActionDate.php @@ -19,7 +19,7 @@ class VisitLastActionDate extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerDate'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerDate'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCDate'; protected $sqlSegment = 'DATE(log_visit.visit_last_action_time)'; protected $acceptValues = '2018-12-31, 2018-03-20, ...'; diff --git a/plugins/CoreHome/Columns/VisitLastActionDayOfMonth.php b/plugins/CoreHome/Columns/VisitLastActionDayOfMonth.php index e3ef6bd8a1..c263c17cf3 100644 --- a/plugins/CoreHome/Columns/VisitLastActionDayOfMonth.php +++ b/plugins/CoreHome/Columns/VisitLastActionDayOfMonth.php @@ -18,7 +18,7 @@ class VisitLastActionDayOfMonth extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerDayOfMonth'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerDayOfMonth'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCDayOfMonth'; protected $sqlSegment = 'DAYOFMONTH(log_visit.visit_last_action_time)'; protected $acceptValues = '0, 1, 2, 3, ..., 29, 30, 31'; diff --git a/plugins/CoreHome/Columns/VisitLastActionDayOfWeek.php b/plugins/CoreHome/Columns/VisitLastActionDayOfWeek.php index 81c5df338e..9bd42bdc0d 100644 --- a/plugins/CoreHome/Columns/VisitLastActionDayOfWeek.php +++ b/plugins/CoreHome/Columns/VisitLastActionDayOfWeek.php @@ -20,7 +20,7 @@ class VisitLastActionDayOfWeek extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerDayOfWeek'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerDayOfWeek'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCDayOfWeek'; protected $sqlSegment = 'DAYOFWEEK(log_visit.visit_last_action_time)'; protected $acceptValues = '1, 2, 3, 4, 5, 6, 7'; diff --git a/plugins/CoreHome/Columns/VisitLastActionDayOfYear.php b/plugins/CoreHome/Columns/VisitLastActionDayOfYear.php index b00cea3c08..5e3449851f 100644 --- a/plugins/CoreHome/Columns/VisitLastActionDayOfYear.php +++ b/plugins/CoreHome/Columns/VisitLastActionDayOfYear.php @@ -18,7 +18,7 @@ class VisitLastActionDayOfYear extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerDayOfYear'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerDayOfYear'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCDayOfYear'; protected $sqlSegment = 'DAYOFYEAR(log_visit.visit_last_action_time)'; protected $acceptValues = '1, 2, 3, 4, ..., 365, 366'; diff --git a/plugins/CoreHome/Columns/VisitLastActionMinute.php b/plugins/CoreHome/Columns/VisitLastActionMinute.php index b3b50fbd52..a465916cbd 100644 --- a/plugins/CoreHome/Columns/VisitLastActionMinute.php +++ b/plugins/CoreHome/Columns/VisitLastActionMinute.php @@ -25,7 +25,7 @@ class VisitLastActionMinute extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerMinute'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerMinute'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCMinute'; protected $sqlSegment = 'MINUTE(log_visit.visit_last_action_time)'; protected $acceptValues = '0, 1, 2, 3, ..., 56, 57, 58, 59'; diff --git a/plugins/CoreHome/Columns/VisitLastActionMonth.php b/plugins/CoreHome/Columns/VisitLastActionMonth.php index 92094685e2..369d8bf776 100644 --- a/plugins/CoreHome/Columns/VisitLastActionMonth.php +++ b/plugins/CoreHome/Columns/VisitLastActionMonth.php @@ -20,7 +20,7 @@ class VisitLastActionMonth extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerMonth'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerMonth'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCMonth'; protected $sqlSegment = 'MONTH(log_visit.visit_last_action_time)'; protected $acceptValues = '1, 2, 3, ..., 11, 12'; diff --git a/plugins/CoreHome/Columns/VisitLastActionQuarter.php b/plugins/CoreHome/Columns/VisitLastActionQuarter.php index f55daec3e7..1966169456 100644 --- a/plugins/CoreHome/Columns/VisitLastActionQuarter.php +++ b/plugins/CoreHome/Columns/VisitLastActionQuarter.php @@ -18,7 +18,7 @@ class VisitLastActionQuarter extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerQuarter'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerQuarter'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCQuarter'; protected $sqlSegment = 'QUARTER(log_visit.visit_last_action_time)'; protected $acceptValues = '1, 2, 3, 4'; diff --git a/plugins/CoreHome/Columns/VisitLastActionSecond.php b/plugins/CoreHome/Columns/VisitLastActionSecond.php index 34dd1552bd..2915898832 100644 --- a/plugins/CoreHome/Columns/VisitLastActionSecond.php +++ b/plugins/CoreHome/Columns/VisitLastActionSecond.php @@ -18,7 +18,7 @@ class VisitLastActionSecond extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerSecond'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerSecond'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCSecond'; protected $sqlSegment = 'SECOND(log_visit.visit_last_action_time)'; protected $acceptValues = '0, 1, 2, 3, ..., 58, 59'; diff --git a/plugins/CoreHome/Columns/VisitLastActionTime.php b/plugins/CoreHome/Columns/VisitLastActionTime.php index 2ec021f68f..f40643f99c 100644 --- a/plugins/CoreHome/Columns/VisitLastActionTime.php +++ b/plugins/CoreHome/Columns/VisitLastActionTime.php @@ -32,7 +32,7 @@ class VisitLastActionTime extends VisitDimension { protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerHour'; + protected $nameSingular = 'VisitTime_ColumnVisitEndSiteHour'; protected $sqlSegment = 'HOUR(log_visit.visit_last_action_time)'; protected $segmentName = 'visitServerHour'; protected $acceptValues = '0, 1, 2, 3, ..., 20, 21, 22, 23'; diff --git a/plugins/CoreHome/Columns/VisitLastActionWeekOfYear.php b/plugins/CoreHome/Columns/VisitLastActionWeekOfYear.php index 2f3db58d97..44c21a067f 100644 --- a/plugins/CoreHome/Columns/VisitLastActionWeekOfYear.php +++ b/plugins/CoreHome/Columns/VisitLastActionWeekOfYear.php @@ -18,7 +18,7 @@ class VisitLastActionWeekOfYear extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerWeekOfYear'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerWeekOfYear'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCWeekOfYear'; protected $sqlSegment = 'WEEKOFYEAR(log_visit.visit_last_action_time)'; protected $acceptValues = '1, 2, 3, 4, ..., 51, 52, 53'; diff --git a/plugins/CoreHome/Columns/VisitLastActionYear.php b/plugins/CoreHome/Columns/VisitLastActionYear.php index ffc3d2929e..18d05db6e8 100644 --- a/plugins/CoreHome/Columns/VisitLastActionYear.php +++ b/plugins/CoreHome/Columns/VisitLastActionYear.php @@ -18,7 +18,7 @@ class VisitLastActionYear extends VisitDimension protected $columnName = 'visit_last_action_time'; protected $type = self::TYPE_DATETIME; protected $segmentName = 'visitEndServerYear'; - protected $nameSingular = 'VisitTime_ColumnVisitEndServerYear'; + protected $nameSingular = 'VisitTime_ColumnVisitEndUTCYear'; protected $sqlSegment = 'YEAR(log_visit.visit_last_action_time)'; protected $acceptValues = '2016, 2017, 2018, ..., 9998, 9999'; diff --git a/plugins/CoreHome/Columns/VisitTotalTime.php b/plugins/CoreHome/Columns/VisitTotalTime.php index 858028f598..0401a54e04 100644 --- a/plugins/CoreHome/Columns/VisitTotalTime.php +++ b/plugins/CoreHome/Columns/VisitTotalTime.php @@ -10,7 +10,6 @@ namespace Piwik\Plugins\CoreHome\Columns; use Piwik\Config; use Piwik\Plugin\Dimension\VisitDimension; -use Piwik\Plugins\CoreHome\Segment; use Piwik\Tracker\Action; use Piwik\Tracker\Request; use Piwik\Tracker\Visitor; diff --git a/plugins/CoreHome/Columns/VisitorFingerprint.php b/plugins/CoreHome/Columns/VisitorFingerprint.php index cc216a0429..e88b3b5b69 100644 --- a/plugins/CoreHome/Columns/VisitorFingerprint.php +++ b/plugins/CoreHome/Columns/VisitorFingerprint.php @@ -32,7 +32,7 @@ class VisitorFingerprint extends VisitDimension public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory) { $metric = $dimensionMetricFactory->createMetric(ArchivedMetric::AGGREGATION_UNIQUE); - $metric->setTranslatedName(Piwik::translate('Visitor_Fingerprint')); + $metric->setTranslatedName(Piwik::translate('General_VisitorFingerprint')); $metricsList->addMetric($metric); } }
\ No newline at end of file diff --git a/plugins/CoreHome/Columns/VisitorId.php b/plugins/CoreHome/Columns/VisitorId.php index f6b29699b3..ff1596837b 100644 --- a/plugins/CoreHome/Columns/VisitorId.php +++ b/plugins/CoreHome/Columns/VisitorId.php @@ -1,4 +1,5 @@ <?php + /** * Matomo - free/libre analytics platform * @@ -10,12 +11,11 @@ namespace Piwik\Plugins\CoreHome\Columns; use Piwik\Columns\DimensionMetricFactory; use Piwik\Columns\MetricsList; -use Piwik\Metrics\Formatter; use Piwik\Piwik; use Piwik\Plugin\ArchivedMetric; use Piwik\Plugin\Dimension\VisitDimension; +use Piwik\Plugins\Live\Live; use Piwik\Segment\SegmentsList; -use Piwik\Plugins\Live\SystemSettings; use Piwik\Columns\DimensionSegmentFactory; /** @@ -31,7 +31,7 @@ class VisitorId extends VisitDimension protected $segmentName = 'visitorId'; protected $acceptValues = '34c31e04394bdc63 - any 16 Hexadecimal chars ID, which can be fetched using the Tracking API function getVisitorId()'; protected $allowAnonymous = false; - protected $sqlFilterValue = array('Piwik\Common', 'convertVisitorIdToBin'); + protected $sqlFilterValue = ['Piwik\Common', 'convertVisitorIdToBin']; protected $type = self::TYPE_BINARY; public function configureMetrics(MetricsList $metricsList, DimensionMetricFactory $dimensionMetricFactory) @@ -45,9 +45,7 @@ class VisitorId extends VisitDimension public function configureSegments(SegmentsList $segmentsList, DimensionSegmentFactory $dimensionSegmentFactory) { try { - $systemSettings = new SystemSettings(); - $visitorProfileEnabled = $systemSettings->disableVisitorProfile->getValue() === false - && $systemSettings->disableVisitorLog->getValue() === false; + $visitorProfileEnabled = Live::isVisitorProfileEnabled(); } catch (\Zend_Db_Exception $e) { // when running tests the db might not yet be set up when fetching available segments if (!defined('PIWIK_TEST_MODE') || !PIWIK_TEST_MODE) { diff --git a/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php b/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php index bed71d3328..64e2a3403a 100644 --- a/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php +++ b/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php @@ -11,7 +11,6 @@ namespace Piwik\Plugins\CoreHome\Columns; use Piwik\Common; use Piwik\Date; use Piwik\Plugin\Dimension\VisitDimension; -use Piwik\Plugin\Segment; use Piwik\Tracker\Action; use Piwik\Tracker\Request; use Piwik\Tracker\Visitor; diff --git a/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php b/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php index 8837bfdd7b..0e67fe4184 100644 --- a/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php +++ b/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php @@ -10,7 +10,6 @@ namespace Piwik\Plugins\CoreHome\Columns; use Piwik\Date; use Piwik\Plugin\Dimension\VisitDimension; -use Piwik\Plugin\Segment; use Piwik\Tracker\Action; use Piwik\Tracker\Request; use Piwik\Tracker\Visitor; diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php index a8f6fa09b0..6982562ea6 100644 --- a/plugins/CoreHome/Controller.php +++ b/plugins/CoreHome/Controller.php @@ -24,7 +24,6 @@ use Piwik\Plugins\CoreHome\DataTableRowAction\MultiRowEvolution; use Piwik\Plugins\CoreHome\DataTableRowAction\RowEvolution; use Piwik\Plugins\Dashboard\DashboardManagerControl; use Piwik\Plugins\UsersManager\API; -use Piwik\Site; use Piwik\Translation\Translator; use Piwik\UpdateCheck; use Piwik\Url; @@ -326,4 +325,5 @@ class Controller extends \Piwik\Plugin\Controller ViewDataTableManager::saveViewDataTableParameters($login, $reportId, $parameters, $containerId); } + } diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php index 4464aa1cd8..3c9aff2265 100644 --- a/plugins/CoreHome/CoreHome.php +++ b/plugins/CoreHome/CoreHome.php @@ -14,6 +14,7 @@ use Piwik\Columns\MetricsList; use Piwik\Common; use Piwik\Container\StaticContainer; use Piwik\DbHelper; +use Piwik\Development; use Piwik\IP; use Piwik\Piwik; use Piwik\Plugin\ArchivedMetric; @@ -138,18 +139,18 @@ class CoreHome extends \Piwik\Plugin $stylesheets[] = "plugins/CoreHome/stylesheets/layout.less"; $stylesheets[] = "plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.less"; $stylesheets[] = "plugins/CoreHome/vue/src/Notification/Notification.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/quick-access/quick-access.directive.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/QuickAccess/QuickAccess.less"; $stylesheets[] = "plugins/CoreHome/stylesheets/selector.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/report-export/reportexport.popover.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/progressbar/progressbar.directive.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/ReportingPage/ReportingPage.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/ReportExport/ReportExport.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/Progressbar/Progressbar.less"; $stylesheets[] = "plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/period-selector/period-selector.directive.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/MultiPairField/MultiPairField.less"; $stylesheets[] = "plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/sparkline/sparkline.component.less"; - $stylesheets[] = "plugins/CoreHome/angularjs/field-array/field-array.directive.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/Sparkline/Sparkline.less"; + $stylesheets[] = "plugins/CoreHome/vue/src/FieldArray/FieldArray.less"; $stylesheets[] = "plugins/CoreHome/vue/src/Comparisons/Comparisons.less"; $stylesheets[] = "plugins/CoreHome/stylesheets/vue-transitions.less"; } @@ -164,7 +165,11 @@ class CoreHome extends \Piwik\Plugin $jsFiles[] = "node_modules/jquery.scrollto/jquery.scrollTo.min.js"; $jsFiles[] = "node_modules/sprintf-js/dist/sprintf.min.js"; $jsFiles[] = "node_modules/mousetrap/mousetrap.min.js"; - $jsFiles[] = 'node_modules/angular/angular.min.js'; + + $devAngularJs = 'node_modules/angular/angular.js'; + $jsFiles[] = Development::isEnabled() && is_file(PIWIK_INCLUDE_PATH . '/' . $devAngularJs) + ? $devAngularJs : 'node_modules/angular/angular.min.js'; + $jsFiles[] = "node_modules/angular-sanitize/angular-sanitize.min.js"; $jsFiles[] = "node_modules/angular-animate/angular-animate.min.js"; $jsFiles[] = "node_modules/angular-cookies/angular-cookies.min.js"; @@ -192,8 +197,6 @@ class CoreHome extends \Piwik\Plugin $jsFiles[] = "plugins/CoreHome/angularjs/common/services/service.module.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/services/piwik-api.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/common/services/report-metadata-model.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/common/services/reporting-pages-model.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/filters/filter.module.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/filters/translate.js"; @@ -210,14 +213,10 @@ class CoreHome extends \Piwik\Plugin $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/directive.module.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/attributes.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/field-condition.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/show-sensitive-data.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/ignore-click.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/onenter.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/translate.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/dropdown-button.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/select-on-focus.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/side-nav.js"; $jsFiles[] = "plugins/CoreHome/angularjs/common/directives/string-to-number.js"; $jsFiles[] = "plugins/CoreHome/angularjs/piwikApp.js"; @@ -226,76 +225,9 @@ class CoreHome extends \Piwik\Plugin $jsFiles[] = "plugins/CoreHome/angularjs/history/history.service.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/progressbar/progressbar.directive.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/sparkline/sparkline.component.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector.controller.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/siteselector/siteselector.directive.js"; - - - $jsFiles[] = "plugins/CoreHome/angularjs/content-intro/content-intro.directive.js"; - - - $jsFiles[] = "plugins/CoreHome/angularjs/ajax-form/ajax-form.controller.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/widget/widget.directive.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/report-export/reportexport.directive.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/quick-access/quick-access.controller.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/quick-access/quick-access.directive.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/content-table/content-table.directive.js"; - - - $jsFiles[] = "plugins/CoreHome/angularjs/period-selector/period-selector.directive.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/period-selector/period-selector.controller.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/multipairfield/multipairfield.controller.js"; - - $jsFiles[] = "plugins/CoreHome/angularjs/field-array/field-array.directive.js"; - $jsFiles[] = "plugins/CoreHome/angularjs/field-array/field-array.controller.js"; - - - // we have to load these CoreAdminHome files here. If we loaded them in CoreAdminHome, - // there would be JS errors as CoreAdminHome is loaded first. Meaning it is loaded before - // any angular JS file is loaded etc. - $jsFiles[] = "plugins/CoreAdminHome/angularjs/smtp/mail-smtp.controller.js"; - $jsFiles[] = "plugins/CoreAdminHome/angularjs/branding/branding.controller.js"; - $jsFiles[] = "plugins/CoreAdminHome/angularjs/trackingcode/jstrackingcode.controller.js"; - $jsFiles[] = "plugins/CoreAdminHome/angularjs/trackingcode/imagetrackingcode.controller.js"; - $jsFiles[] = "plugins/CoreAdminHome/angularjs/archiving/archiving.controller.js"; - $jsFiles[] = "plugins/CoreAdminHome/angularjs/trackingfailures/trackingfailures.controller.js"; - $jsFiles[] = "plugins/CoreAdminHome/angularjs/trackingfailures/trackingfailures.directive.js"; - // we have to load these CorePluginsAdmin files here. If we loaded them in CorePluginsAdmin, // there would be JS errors as CorePluginsAdmin is loaded first. Meaning it is loaded before // any angular JS file is loaded etc. - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.controller.js"; - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.js"; - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/form/form.directive.js"; - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.js"; - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/field/field.directive.js"; - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/save-button/save-button.directive.js"; - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/plugins/plugin-filter.directive.js"; - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/plugins/plugin-management.directive.js"; - $jsFiles[] = "plugins/CorePluginsAdmin/angularjs/plugins/plugin-upload.directive.js"; $jsFiles[] = "node_modules/iframe-resizer/js/iframeResizer.min.js"; $jsFiles[] = "node_modules/iframe-resizer/js/iframeResizer.contentWindow.min.js"; } @@ -475,5 +407,8 @@ class CoreHome extends \Piwik\Plugin $translationKeys[] = 'General_PreviousYear'; $translationKeys[] = 'CoreHome_ReportingCategoryHelpPrefix'; $translationKeys[] = 'CoreHome_TechDeprecationWarning'; + $translationKeys[] = 'CoreHome_StartDate'; + $translationKeys[] = 'CoreHome_EndDate'; + $translationKeys[] = 'CoreHome_DataForThisReportHasBeenDisabled'; } } diff --git a/plugins/CoreHome/Menu.php b/plugins/CoreHome/Menu.php index 3b3051f606..6cade0124e 100644 --- a/plugins/CoreHome/Menu.php +++ b/plugins/CoreHome/Menu.php @@ -8,10 +8,8 @@ */ namespace Piwik\Plugins\CoreHome; -use Piwik\Db; use Piwik\Menu\MenuTop; use Piwik\Piwik; -use Piwik\Plugin; class Menu extends \Piwik\Plugin\Menu { diff --git a/plugins/CoreHome/Tracker/VisitRequestProcessor.php b/plugins/CoreHome/Tracker/VisitRequestProcessor.php index 65906cd45e..74abe8ffd6 100644 --- a/plugins/CoreHome/Tracker/VisitRequestProcessor.php +++ b/plugins/CoreHome/Tracker/VisitRequestProcessor.php @@ -10,7 +10,6 @@ namespace Piwik\Plugins\CoreHome\Tracker; use Piwik\Common; use Piwik\Date; -use Piwik\Config; use Piwik\EventDispatcher; use Piwik\Exception\UnexpectedWebsiteFoundException; use Piwik\Tracker\Cache; diff --git a/plugins/CoreHome/Widgets/GetDonateForm.php b/plugins/CoreHome/Widgets/GetDonateForm.php index 72431e2d7f..c5ea5cf462 100644 --- a/plugins/CoreHome/Widgets/GetDonateForm.php +++ b/plugins/CoreHome/Widgets/GetDonateForm.php @@ -13,7 +13,6 @@ use Piwik\Piwik; use Piwik\Widget\Widget; use Piwik\Widget\WidgetConfig; use Piwik\Translation\Translator; -use Piwik\View; class GetDonateForm extends Widget { diff --git a/plugins/CoreHome/Widgets/GetSystemSummary.php b/plugins/CoreHome/Widgets/GetSystemSummary.php index 3d56a99790..e09fe22d45 100644 --- a/plugins/CoreHome/Widgets/GetSystemSummary.php +++ b/plugins/CoreHome/Widgets/GetSystemSummary.php @@ -8,7 +8,6 @@ */ namespace Piwik\Plugins\CoreHome\Widgets; -use Piwik\API\Request; use Piwik\Db; use Piwik\Piwik; use Piwik\Plugin; @@ -20,6 +19,7 @@ use Piwik\Widget\WidgetConfig; class GetSystemSummary extends Widget { + const TEST_MYSQL_VERSION = 'mysql-version-redacted'; /** * @var StoredSegmentService */ @@ -108,6 +108,10 @@ class GetSystemSummary extends Widget private function getMySqlVersion() { + if (defined('PIWIK_TEST_MODE')) { + return self::TEST_MYSQL_VERSION; + } + $db = Db::get(); return $db->getServerVersion(); } diff --git a/plugins/CoreHome/angularjs/ajax-form/ajax-form.controller.js b/plugins/CoreHome/angularjs/ajax-form/ajax-form.controller.js deleted file mode 100644 index 5bc6310962..0000000000 --- a/plugins/CoreHome/angularjs/ajax-form/ajax-form.controller.js +++ /dev/null @@ -1,85 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').controller('AjaxFormController', AjaxFormController); - - AjaxFormController.$inject = ['piwikApi', '$filter']; - - function AjaxFormController(piwikApi, $filter) { - var vm = this; - - /** - * Set to non-null when a form submit request returns successfully. When successful, it will - * be the entire JSON parsed response of the request. - * - * @type {null|string} - */ - vm.successfulPostResponse = null; - - /** - * Set to non-null when a form submit request results in an error. When an error occurs, - * it will be set to the string error message. - * - * @type {null|string} - */ - vm.errorPostResponse = null; - - /** - * true if currently submitting a POST request, false if otherwise. - * - * @type {bool} - */ - vm.isSubmitting = false; - - vm.submitForm = submitForm; - - /** - * Sends a POST to the configured API method. - */ - function submitForm() { - var postParams; - - vm.successfulPostResponse = null; - vm.errorPostResponse = null; - - if (vm.sendJsonPayload) { - postParams = {data: JSON.stringify(vm.data)}; - } else { - postParams = vm.data; - } - - vm.isSubmitting = true; - piwikApi.post( - { // GET params - module: 'API', - method: vm.submitApiMethod - }, - postParams, - { // request options - createErrorNotification: !vm.noErrorNotification - } - ).then(function (response) { - vm.successResponse = response; - - if (!vm.noSuccessNotification) { - var UI = require('piwik/UI'); - var notification = new UI.Notification(); - notification.show($filter('translate')('General_YourChangesHaveBeenSaved'), { - context: 'success', - type: 'toast', - id: 'ajaxHelper' - }); - notification.scrollToNotification(); - } - }).catch(function (errorMessage) { - vm.errorPostResponse = errorMessage; - }).finally(function () { - vm.isSubmitting = false; - }); - } - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js b/plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js deleted file mode 100644 index caacca2384..0000000000 --- a/plugins/CoreHome/angularjs/ajax-form/ajax-form.directive.js +++ /dev/null @@ -1,144 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * AngularJS directive that manages an AJAX form. - * - * This directive will detect inputs & selects defined within an element and when a - * submit button is clicked, will post data from the inputs & selects to a Piwik API method. - * - * When the POST request is finished the result will, by default, be displayed as a - * notification. - * - * This directive accepts the following attributes: - * - * - **submit-api-method**: **required** The Piwik API method that handles the POST request. - * - **send-json-payload**: Whether to send the data as a form encoded URL or to send it as JSON. - * If sending as JSON, the payload will still be a form encoded value, - * but will contain a JSON object like `{data: {...form data...}}`. - * - * This is for forms with lots of fields where having the same number - * of parameters in an API method would not be desired. - * - **no-error-notification**: If true, does not display an error notification if the AJAX post - * fails. - * - **no-success-notification**: If true, does not display an error notification if the AJAX - * results in success. - * - * **Custom Success/Error Handling** - * - * On success/failure, the response will be stored in controller scope. Child elements of a - * piwik-ajax-form element can access this data, and thus, can customize what happens when - * a form submit succeeds/fails. - * - * See the ajax-form.controller.js file for more info. - * - * Usage: - * - * <div piwik-ajax-form - * submit-api-method="'MyPlugin.myFormSaveMethod'" - * send-json-payload="true" - * ng-model="myFormData"> - * - * <h2>My Form</h2> - * <input name="myOption" value="myDefaultValue" type="text" /> - * <input name="myOtherOption" type="checkbox" checked="checked" /> - * <input type="submit" value="Submit" ng-disabled="ajaxForm.isSubmitting" /> - * - * <div piwik-notification context='error' ng-show="errorPostResponse">ERROR!</div> - * </div> - */ -(function () { - angular.module('piwikApp').directive('piwikAjaxForm', piwikAjaxForm); - - piwikAjaxForm.$inject = ['$parse']; - - function piwikAjaxForm($parse) { - return { - restrict: 'A', - scope: { - submitApiMethod: '=', - sendJsonPayload: '=', - noErrorNotification: '=', - noSuccessNotification: '=', - useCustomDataBinding: '=' - }, - require: '?ngModel', - controller: 'AjaxFormController', - controllerAs: 'ajaxForm', - transclude: true, - compile: function (element, attrs) { - attrs.noErrorNotification = !! attrs.noErrorNotification; - - return function (scope, element, attrs, ngModel, transclude) { - if (!scope.submitApiMethod) { - throw new Error("submitApiMethod is required"); - } - - scope.ajaxForm.submitApiMethod = scope.submitApiMethod; - scope.ajaxForm.sendJsonPayload = scope.sendJsonPayload; - scope.ajaxForm.noErrorNotification = scope.noErrorNotification; - scope.ajaxForm.noSuccessNotification = scope.noSuccessNotification; - - scope.ajaxForm.data = {}; - - // if a model is supplied, initiate form data w/ model value - if (ngModel) { - var ngModelGetter = $parse(attrs.ngModel); // probably redundant, but I cannot find another way to - // get the ng model value here - scope.ajaxForm.data = ngModelGetter(scope.$parent); - } - - // on change of any input, change appropriate value in model, but only if requested - if (!scope.useCustomDataBinding) { - element.on('change', 'input,select', function () { - setFormValueFromInput(this); - }); - } - - // on submit call controller submit method - element.on('click', 'input[type=submit]', function () { - scope.ajaxForm.submitForm(); - }); - - // make sure child elements can access this directive's scope - transclude(scope, function(clone, scope) { - if (!scope.useCustomDataBinding) { - var $inputs = clone.find('input,select').not('[type=submit]'); - - // initialize form data to input values (include <select>s - $inputs.each(function () { - setFormValueFromInput(this, true); - }); - } - - element.append(clone); - }); - - function setFormValueFromInput(inputElement, skipScopeApply) { - var $ = angular.element, - name = $(inputElement).attr('name'), - val; - - if ($(inputElement).attr('type') == 'checkbox') { - val = $(inputElement).is(':checked'); - } else { - val = $(inputElement).val(); - } - - scope.ajaxForm.data[name] = val; - - if (!skipScopeApply) { - setTimeout(function () { - scope.$apply(); - }, 0); - } - } - }; - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/anchorLinkFix.js b/plugins/CoreHome/angularjs/anchorLinkFix.js index bdc55792a7..677eb31242 100644 --- a/plugins/CoreHome/angularjs/anchorLinkFix.js +++ b/plugins/CoreHome/angularjs/anchorLinkFix.js @@ -75,8 +75,8 @@ function handleScrollToAnchorIfPresentOnPageLoad() { - if (location.hash.substr(0, 2) == '#/') { - var hash = location.hash.substr(2); + if (location.hash.slice(0, 2) == '#/') { + var hash = location.hash.slice(2); scrollToAnchorIfPossible(hash, null); } } @@ -102,7 +102,7 @@ return; } - var hash = newUrl.substr(hashPos + 2); + var hash = newUrl.slice(hashPos + 2); scrollToAnchorIfPossible(hash, event); } diff --git a/plugins/CoreHome/angularjs/common/directives/attributes.js b/plugins/CoreHome/angularjs/common/directives/attributes.js index 125c28171b..7f4a30b60d 100644 --- a/plugins/CoreHome/angularjs/common/directives/attributes.js +++ b/plugins/CoreHome/angularjs/common/directives/attributes.js @@ -20,6 +20,9 @@ piwikAttributes.$inject = ['$sanitize']; + /** + * @deprecated + */ function piwikAttributes(piwik, $sanitize) { return { diff --git a/plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js b/plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js index 867e0c58ec..995950ef2d 100644 --- a/plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js +++ b/plugins/CoreHome/angularjs/common/directives/autocomplete-matched.js @@ -14,12 +14,17 @@ * * <div piwik-autocomplete-matched="searchTerm">{{ name }}</div> * <input type="text" ng-model="searchTerm"> + * + * @deprecated */ (function () { angular.module('piwikApp.directive').directive('piwikAutocompleteMatched', piwikAutocompleteMatched); piwikAutocompleteMatched.$inject = ['piwik', '$sanitize']; + /** + * @deprecated + */ function piwikAutocompleteMatched(piwik, $sanitize) { return { @@ -41,7 +46,7 @@ var startTerm = content.toLowerCase().indexOf(searchTerm.toLowerCase()); if (-1 !== startTerm) { - var word = content.substr(startTerm, searchTerm.length); + var word = content.slice(startTerm, startTerm + searchTerm.length); var escapedword = $sanitize(piwik.helper.htmlEntities(word)); content = content.replace(word, '<span class="autocompleteMatched">' + escapedword + '</span>'); element.html(content); diff --git a/plugins/CoreHome/angularjs/common/directives/dropdown-button.js b/plugins/CoreHome/angularjs/common/directives/dropdown-button.js deleted file mode 100644 index 1a0c001007..0000000000 --- a/plugins/CoreHome/angularjs/common/directives/dropdown-button.js +++ /dev/null @@ -1,45 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div piwik-dropdown-button> - */ -(function () { - angular.module('piwikApp.directive').directive('dropdownButton', piwikDropdownButton); - - piwikDropdownButton.$inject = ['piwik']; - - function piwikDropdownButton(piwik){ - - return { - restrict: 'C', - compile: function (element, attrs) { - // BC for materializecss 0.97 => 1.0 - if (!element.attr('data-target') - && element.attr('data-activates') - ) { - element.attr('data-target', element.attr('data-activates')); - } - - if (element.attr('data-target') && $('#' + element.attr('data-target')).length) { - $(element).dropdown({ - inDuration: 300, - outDuration: 225, - constrainWidth: false, // Does not change width of dropdown to that of the activator - // hover: true, // Activate on hover - belowOrigin: true // Displays dropdown below the button - }); - } - - return function (scope, element, attrs) { - - }; - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/common/directives/field-condition.js b/plugins/CoreHome/angularjs/common/directives/field-condition.js index 01431e5d29..5c4c33ff8e 100644 --- a/plugins/CoreHome/angularjs/common/directives/field-condition.js +++ b/plugins/CoreHome/angularjs/common/directives/field-condition.js @@ -14,6 +14,10 @@ piwikFieldCondition.$inject = ['piwik', '$timeout']; + /** + * Unused. + * @deprecated + */ function piwikFieldCondition(piwik, $timeout){ function evaluate(scope, condition, element) @@ -34,7 +38,7 @@ } else if (element.prop('tagName').toLowerCase() === 'select') { var name = element.val(); if (name.indexOf('string:') === 0) { - return name.substr('string:'.length); + return name.slice('string:'.length); } return name; @@ -85,4 +89,4 @@ }, }; } -})();
\ No newline at end of file +})(); diff --git a/plugins/CoreHome/angularjs/common/directives/ignore-click.js b/plugins/CoreHome/angularjs/common/directives/ignore-click.js index a11c0e29c8..3bb8d724cb 100644 --- a/plugins/CoreHome/angularjs/common/directives/ignore-click.js +++ b/plugins/CoreHome/angularjs/common/directives/ignore-click.js @@ -15,11 +15,14 @@ (function () { angular.module('piwikApp.directive').directive('piwikIgnoreClick', piwikIgnoreClick); - function piwikIgnoreClick() { + /** + * @deprecated + */ + function piwikIgnoreClick() { return function(scope, element, attrs) { $(element).click(function(event) { event.preventDefault(); }); }; } -})();
\ No newline at end of file +})(); diff --git a/plugins/CoreHome/angularjs/common/directives/onenter.js b/plugins/CoreHome/angularjs/common/directives/onenter.js index ce2a73961f..c0b7ed4d51 100644 --- a/plugins/CoreHome/angularjs/common/directives/onenter.js +++ b/plugins/CoreHome/angularjs/common/directives/onenter.js @@ -15,7 +15,10 @@ (function () { angular.module('piwikApp.directive').directive('piwikOnenter', piwikOnenter); - function piwikOnenter() { + /** + * @deprecated + */ + function piwikOnenter() { return function(scope, element, attrs) { element.bind("keydown keypress", function(event) { if(event.which === 13) { @@ -28,4 +31,4 @@ }); }; } -})();
\ No newline at end of file +})(); diff --git a/plugins/CoreHome/angularjs/common/directives/select-on-focus.js b/plugins/CoreHome/angularjs/common/directives/select-on-focus.js deleted file mode 100644 index a76dd30d99..0000000000 --- a/plugins/CoreHome/angularjs/common/directives/select-on-focus.js +++ /dev/null @@ -1,69 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * On focus (click, tab) selects the text within the current element - * - * Example: - * <div piwik-select-on-focus>my dialog</div> - */ -(function () { - angular.module('piwikApp.directive').directive('piwikSelectOnFocus', piwikSelectOnFocus); - - function piwikSelectOnFocus(){ - return { - restrict: 'A', - link: function(scope, element, attr, ctrl) { - - var focusedElement = null; - - var tagName = (element.prop('tagName') + '').toLowerCase(); - var elementSupportsSelect = tagName === 'textarea'; - - function onFocusHandler(event) { - if (focusedElement !== this) { - focusedElement = this; - angular.element(this).select(); - } - } - - function onClickHandler(event) { - // .select() + focus and blur seems to not work on pre elements - var range = document.createRange(); - range.selectNode(this); - var selection = window.getSelection(); - if (selection && selection.rangeCount > 0) { - selection.removeAllRanges(); - } - if (selection) { - selection.addRange(range); - } - } - - function onBlurHandler(event) { - focusedElement = null; - } - - if (elementSupportsSelect) { - element.on('focus', onFocusHandler); - element.on('blur', onBlurHandler); - } else { - element.on('click', onClickHandler); - } - - scope.$on('$destroy', function() { - if (elementSupportsSelect) { - element.off('focus', onFocusHandler); - element.off('blur', onBlurHandler); - } else { - element.off('click', onClickHandler); - } - }); - } - }; - } -})(); diff --git a/plugins/CoreHome/angularjs/common/directives/show-sensitive-data.js b/plugins/CoreHome/angularjs/common/directives/show-sensitive-data.js deleted file mode 100644 index fc111100bb..0000000000 --- a/plugins/CoreHome/angularjs/common/directives/show-sensitive-data.js +++ /dev/null @@ -1,59 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Handles visibility of sensitive data. By default data will be shown replaced with stars (*) - * On click on the element the full data will be shown - * - * Configuration attributes: - * data-show-characters number of characters to show in clear text (defaults to 6) - * data-click-element-selector selector for element that will show the full data on click (defaults to element) - * - * Example: - * <div piwik-show-sensitive-date="some text"></div> - */ -(function () { - angular.module('piwikApp.directive').directive('piwikShowSensitiveData', piwikShowSensitiveData); - - function piwikShowSensitiveData(){ - return { - restrict: 'A', - link: function(scope, element, attr) { - - var sensitiveData = attr.piwikShowSensitiveData || (attr.text ? attr.text() : ''); - var showCharacters = attr.showCharacters || 6; - var clickElement = attr.clickElementSelector || element; - - var protectedData = ''; - if (showCharacters > 0) { - protectedData += sensitiveData.substr(0, showCharacters); - } - protectedData += sensitiveData.substr(showCharacters).replace(/./g, '*'); - element.html(protectedData); - - function onClickHandler(event) { - element.html(sensitiveData); - $(clickElement).css({ - cursor: '' - }); - $(clickElement).tooltip("destroy"); - } - - $(clickElement).tooltip({ - content: _pk_translate('CoreHome_ClickToSeeFullInformation'), - items: '*', - track: true - }); - - $(clickElement).one('click', onClickHandler); - $(clickElement).css({ - cursor: 'pointer' - }); - } - }; - } -})(); diff --git a/plugins/CoreHome/angularjs/common/directives/side-nav.js b/plugins/CoreHome/angularjs/common/directives/side-nav.js deleted file mode 100644 index 1f62df58a3..0000000000 --- a/plugins/CoreHome/angularjs/common/directives/side-nav.js +++ /dev/null @@ -1,48 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Will activate the materialize side nav feature once rendered. We use this directive as it makes sure - * the actual left menu is rendered at the time we init the side nav. - * - * Has to be set on a collaapsible element - * - * Example: - * <div class="collapsible" piwik-side-nav="nav .activateLeftMenu">...</div> - */ -(function () { - angular.module('piwikApp.directive').directive('piwikSideNav', piwikSideNav); - - piwikSideNav.$inject = ['$timeout']; - var initialized = false; - - function piwikSideNav($timeout){ - return { - restrict: 'A', - priority: 10, - link: function(scope, element, attr, ctrl) { - if (attr.piwikSideNav) { - $timeout(function () { - if (!initialized) { - initialized = true; - - var sideNavActivator = $(attr.piwikSideNav).show(); - - $('#' + sideNavActivator.attr('data-target')).sidenav({ - closeOnClick: true - }); - } - - if (element.hasClass('collapsible')) { - element.collapsible(); - } - }); - } - } - }; - } -})(); diff --git a/plugins/CoreHome/angularjs/common/directives/translate.js b/plugins/CoreHome/angularjs/common/directives/translate.js index 49c87f6d4b..badb9208a9 100644 --- a/plugins/CoreHome/angularjs/common/directives/translate.js +++ b/plugins/CoreHome/angularjs/common/directives/translate.js @@ -22,6 +22,9 @@ (function () { angular.module('piwikApp.directive').directive('piwikTranslate', piwikTranslate); + /** + * @deprecated + */ function piwikTranslate() { return { priority: 1, diff --git a/plugins/CoreHome/angularjs/common/filters/evolution.js b/plugins/CoreHome/angularjs/common/filters/evolution.js index d3ba61259b..14adb00db1 100644 --- a/plugins/CoreHome/angularjs/common/filters/evolution.js +++ b/plugins/CoreHome/angularjs/common/filters/evolution.js @@ -8,42 +8,8 @@ angular.module('piwikApp.filter').filter('evolution', evolutionFilter); function evolutionFilter() { - - function calculateEvolution(currentValue, pastValue) - { - pastValue = parseInt(pastValue, 10); - currentValue = parseInt(currentValue, 10) - pastValue; - - var evolution; - - if (currentValue === 0 || isNaN(currentValue)) { - evolution = 0; - } else if (pastValue === 0 || isNaN(pastValue)) { - evolution = 100; - } else { - evolution = (currentValue / pastValue) * 100; - } - - return evolution; - } - - function formatEvolution(evolution) - { - evolution = Math.round(evolution); - - if (evolution > 0) { - evolution = '+' + evolution; - } - - evolution += '%'; - - return evolution; - } - return function(currentValue, pastValue) { - var evolution = calculateEvolution(currentValue, pastValue); - - return formatEvolution(evolution); + return window.CoreHome.getFormattedEvolution(currentValue, pastValue); }; } })(); diff --git a/plugins/CoreHome/angularjs/common/filters/ucfirst.js b/plugins/CoreHome/angularjs/common/filters/ucfirst.js index 3c9094f602..0af633e51e 100644 --- a/plugins/CoreHome/angularjs/common/filters/ucfirst.js +++ b/plugins/CoreHome/angularjs/common/filters/ucfirst.js @@ -15,7 +15,7 @@ } var firstLetter = (value + '').charAt(0).toUpperCase(); - return firstLetter + value.substr(1); + return firstLetter + value.slice(1); }; } })(); diff --git a/plugins/CoreHome/angularjs/common/services/report-metadata-model.js b/plugins/CoreHome/angularjs/common/services/report-metadata-model.js deleted file mode 100644 index 125989ee6e..0000000000 --- a/plugins/CoreHome/angularjs/common/services/report-metadata-model.js +++ /dev/null @@ -1,53 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp.service').factory('reportMetadataModel', reportMetadataModel); - - reportMetadataModel.$inject = ['piwik', 'piwikApi']; - - function reportMetadataModel (piwik, piwikApi) { - - var reportsPromise = null; - - var model = { - reports: [], - fetchReportMetadata: fetchReportMetadata, - findReport: findReport - }; - - return model; - - function findReport(module, action) - { - var found = []; - - angular.forEach(model.reports, function (report) { - if (report.module === module && report.action === action) { - found = report; - } - }); - - return found; - } - - function fetchReportMetadata() - { - if (!reportsPromise) { - reportsPromise = piwikApi.fetch({ - method: 'API.getReportMetadata', - filter_limit: '-1', - idSite: piwik.idSite || piwik.broadcast.getValueFromUrl('idSite') - }).then(function (response) { - model.reports = response; - return response; - }); - } - - return reportsPromise; - } - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/common/services/reporting-pages-model.js b/plugins/CoreHome/angularjs/common/services/reporting-pages-model.js deleted file mode 100644 index c135aad2c5..0000000000 --- a/plugins/CoreHome/angularjs/common/services/reporting-pages-model.js +++ /dev/null @@ -1,76 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp.service').factory('reportingPagesModel', reportingPagesModelService); - - reportingPagesModelService.$inject = ['piwikApi']; - - function reportingPagesModelService (piwikApi) { - var fetchAllPagesPromise = false; - - // those sites are going to be displayed - var model = { - pages : [], - findPage: findPage, - findPageInCategory: findPageInCategory, - reloadAllPages : reloadAllPages, - getAllPages : getAllPages - }; - - return model; - - function findPageInCategory(categoryId) { - var found = null; - - angular.forEach(model.pages, function (page) { - // happens when user switches between sites, in this case check if the same category exists and if so, - // select first entry from that category - if (!found && page && - page.category && page.subcategory && - page.category.id === categoryId && page.subcategory.id) { - found = page; - } - }); - - return found; - } - - function findPage(categoryId, subcategoryId) - { - var found = null; - - angular.forEach(model.pages, function (page) { - if (!found && - page && - page.category && page.subcategory && - page.category.id === categoryId && ('' + page.subcategory.id) === subcategoryId) { - found = page; - } - }); - - return found; - } - - function reloadAllPages() - { - fetchAllPagesPromise = null; - return getAllPages(); - } - - function getAllPages() - { - if (!fetchAllPagesPromise) { - fetchAllPagesPromise = piwikApi.fetch({method: 'API.getReportPagesMetadata', filter_limit: '-1'}).then(function (response) { - model.pages = response; - return response; - }); - } - - return fetchAllPagesPromise; - } - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/content-intro/content-intro.directive.js b/plugins/CoreHome/angularjs/content-intro/content-intro.directive.js deleted file mode 100644 index 6e050ae2e7..0000000000 --- a/plugins/CoreHome/angularjs/content-intro/content-intro.directive.js +++ /dev/null @@ -1,26 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div piwik-content-block> - */ -(function () { - angular.module('piwikApp').directive('piwikContentIntro', piwikContentIntro); - - piwikContentIntro.$inject = ['piwik']; - - function piwikContentIntro(piwik){ - - return { - restrict: 'A', - compile: function (element, attrs) { - element.addClass('piwik-content-intro'); - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/content-table/content-table.directive.js b/plugins/CoreHome/angularjs/content-table/content-table.directive.js deleted file mode 100644 index 57a1fc5587..0000000000 --- a/plugins/CoreHome/angularjs/content-table/content-table.directive.js +++ /dev/null @@ -1,30 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div piwik-content-table> - */ -(function () { - angular.module('piwikApp').directive('piwikContentTable', piwikContentTable); - - piwikContentTable.$inject = ['piwik']; - - function piwikContentTable(piwik){ - - return { - restrict: 'A', - compile: function (element, attrs) { - element.addClass('card card-table entityTable'); - - return function (scope, element, attrs) { - - }; - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/field-array/field-array.controller.js b/plugins/CoreHome/angularjs/field-array/field-array.controller.js deleted file mode 100644 index 02aa7a2215..0000000000 --- a/plugins/CoreHome/angularjs/field-array/field-array.controller.js +++ /dev/null @@ -1,71 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').controller('FieldArrayController', FieldArrayController); - - FieldArrayController.$inject = ['$scope']; - - function FieldArrayController($scope){ - - function getTemplate(field) { - var control = field.uiControl; - if (control === 'password' || control === 'url' || control === 'search' || control === 'email') { - control = 'text'; // we use same template for text and password both - } - - var file = 'field-' + control; - var fieldsSupportingArrays = ['textarea', 'checkbox', 'text']; - if (field.type === 'array' && fieldsSupportingArrays.indexOf(control) !== -1) { - file += '-array'; - } - - return 'plugins/CorePluginsAdmin/angularjs/form-field/' + file + '.html?cb=' + piwik.cacheBuster; - } - - if ($scope.field && !$scope.field.templateFile) { - $scope.field.templateFile = getTemplate($scope.field); - } - - var self = this; - $scope.$watch('formValue', function () { - if (!$scope.formValue || !$scope.formValue.length) { - self.addEntry(); - } else { - self.onEntryChange(); - } - }, true); - - this.onEntryChange = function () { - var hasAny = true; - angular.forEach($scope.formValue, function (entry) { - if (!entry) { - hasAny = false; - } - }); - if (hasAny) { - this.addEntry(); - } - }; - - this.addEntry = function () { - if (angular.isArray($scope.formValue)) { - $scope.formValue.push(''); - } - }; - - this.removeEntry = function (index) { - if (index > -1) { - $scope.formValue.splice(index, 1); - } - }; - - if (!$scope.formValue || !$scope.formValue.length) { - this.addEntry(); - } - } - -})(); diff --git a/plugins/CoreHome/angularjs/field-array/field-array.directive.html b/plugins/CoreHome/angularjs/field-array/field-array.directive.html deleted file mode 100644 index 1ce3fcaecc..0000000000 --- a/plugins/CoreHome/angularjs/field-array/field-array.directive.html +++ /dev/null @@ -1,23 +0,0 @@ -<div class="fieldArray form-group"> - <div ng-repeat="item in formValue track by $index" - class="fieldArrayTable fieldArrayTable{{ $index }} multiple valign-wrapper"> - - <div piwik-field uicontrol="{{ field.uiControl }}" - data-title="{{ field.title }}" - name="{{ name + '-' + $index }}" - full-width="true" - ng-if="field.templateFile" - template-file="{{ field.templateFile }}" - class="fieldUiControl" - ng-model="formValue[$index]" - options="field.availableValues" - ng-change="fieldArray.onEntryChange()" - placeholder=" "> - </div> - - <span ng-click="fieldArray.removeEntry($index)" - title="{{ 'General_Remove'|translate }}" - ng-hide="($index + 1) == (formValue|length)" - class="icon-minus valign"></span> - </div> -</div>
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/field-array/field-array.directive.js b/plugins/CoreHome/angularjs/field-array/field-array.directive.js deleted file mode 100644 index 000f16caa9..0000000000 --- a/plugins/CoreHome/angularjs/field-array/field-array.directive.js +++ /dev/null @@ -1,61 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div matomo-field-array field=".." ng-model="..."> - */ -(function () { - angular.module('piwikApp').directive('matomoFieldArray', matomoFieldArray); - - matomoFieldArray.$inject = ['$document', 'piwik', '$filter']; - - function matomoFieldArray($document, piwik, $filter){ - return { - restrict: 'A', - scope: { - name: '=', - field: '=' - }, - require: "?ngModel", - templateUrl: 'plugins/CoreHome/angularjs/field-array/field-array.directive.html?cb=' + piwik.cacheBuster, - controller: 'FieldArrayController', - controllerAs: 'fieldArray', - compile: function (element, attrs) { - - return function (scope, element, attrs, ngModel) { - - if (ngModel) { - ngModel.$setViewValue(scope.formValue); - } - - scope.$watch('formValue', function (newValue, oldValue) { - if (newValue != oldValue) { - element.trigger('change', newValue); - } - }, true); - - if (ngModel) { - ngModel.$render = function() { - if (angular.isString(ngModel.$viewValue)) { - scope.formValue = JSON.parse(ngModel.$viewValue); - } else { - scope.formValue = ngModel.$viewValue; - } - }; - } - - scope.$watch('formValue', function (newValue, oldValue) { - if (ngModel) { - ngModel.$setViewValue(newValue); - } - }, true); - }; - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/http404check.js b/plugins/CoreHome/angularjs/http404check.js index b18b7be669..bba8ba6a65 100644 --- a/plugins/CoreHome/angularjs/http404check.js +++ b/plugins/CoreHome/angularjs/http404check.js @@ -42,7 +42,7 @@ -1 !== rejection.config.url.indexOf('plugins')) { var posEndUrl = rejection.config.url.indexOf('.html') + 5; - var url = rejection.config.url.substr(0, posEndUrl); + var url = rejection.config.url.slice(0, posEndUrl); var message = 'Please check your server configuration. You may want to whitelist "*.html" files from the "plugins" directory.'; message += ' The HTTP status code is ' + rejection.status + ' for URL "' + url + '"'; diff --git a/plugins/CoreHome/angularjs/multipairfield/multipairfield.controller.js b/plugins/CoreHome/angularjs/multipairfield/multipairfield.controller.js deleted file mode 100644 index 737bdbf94f..0000000000 --- a/plugins/CoreHome/angularjs/multipairfield/multipairfield.controller.js +++ /dev/null @@ -1,129 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').controller('MultiPairFieldController', MultiPairFieldController); - - MultiPairFieldController.$inject = ['$scope']; - - function MultiPairFieldController($scope){ - - function getTemplate(field) { - var control = field.uiControl; - if (control === 'password' || control === 'url' || control === 'search' || control === 'email') { - control = 'text'; // we use same template for text and password both - } - - var file = 'field-' + control; - var fieldsSupportingArrays = ['textarea', 'checkbox', 'text']; - if (field.type === 'array' && fieldsSupportingArrays.indexOf(control) !== -1) { - file += '-array'; - } - - return 'plugins/CorePluginsAdmin/angularjs/form-field/' + file + '.html?cb=' + piwik.cacheBuster; - } - - if ($scope.field1 && !$scope.field1.templateFile) { - $scope.field1.templateFile = getTemplate($scope.field1); - } - - if ($scope.field2 && !$scope.field2.templateFile) { - $scope.field2.templateFile = getTemplate($scope.field2); - } - - if ($scope.field3 && !$scope.field3.templateFile) { - $scope.field3.templateFile = getTemplate($scope.field3); - } - - if ($scope.field4 && !$scope.field4.templateFile) { - $scope.field4.templateFile = getTemplate($scope.field4); - } - - var self = this; - $scope.$watch('formValue', function () { - if (!$scope.formValue || !$scope.formValue.length) { - self.addEntry(); - } else { - self.onEntryChange(); - } - }, true); - - this.onEntryChange = function () { - var hasAny = true; - angular.forEach($scope.formValue, function (table) { - if (!table) { - hasAny = false; - return; - } - - var fieldCount = 0; - if ($scope.field1 && $scope.field2 && $scope.field3 && $scope.field4) { - fieldCount = 4; - } else if ($scope.field1 && $scope.field2 && $scope.field3) { - fieldCount = 3; - } else if ($scope.field1 && $scope.field2) { - fieldCount = 2; - } else if ($scope.field1) { - fieldCount = 1; - } - table.fieldCount = fieldCount; - - if (fieldCount === 4) { - if (!table[$scope.field1.key] && !table[$scope.field2.key] && !table[$scope.field3.key] && !table[$scope.field4.key]) { - hasAny = false; - } - } else if (fieldCount === 3) { - if (!table[$scope.field1.key] && !table[$scope.field2.key] && !table[$scope.field3.key]) { - hasAny = false; - } - } else if (fieldCount === 2) { - if (!table[$scope.field1.key] && !table[$scope.field2.key]) { - hasAny = false; - } - } else if (fieldCount === 1) { - if (!table[$scope.field1.key]) { - hasAny = false; - } - } - - - }); - if (hasAny) { - this.addEntry(); - } - }; - - this.addEntry = function () { - if (angular.isArray($scope.formValue)) { - var obj = {}; - if ($scope.field1 && $scope.field1.key) { - obj[$scope.field1.key] = ''; - } - if ($scope.field2 && $scope.field2.key) { - obj[$scope.field2.key] = ''; - } - if ($scope.field3 && $scope.field3.key) { - obj[$scope.field3.key] = ''; - } - if ($scope.field4 && $scope.field4.key) { - obj[$scope.field4.key] = ''; - } - $scope.formValue.push(obj); - } - }; - - this.removeEntry = function (index) { - if (index > -1) { - $scope.formValue.splice(index, 1); - } - }; - - if (!$scope.formValue || !$scope.formValue.length) { - this.addEntry(); - } - } - -})(); diff --git a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html b/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html deleted file mode 100644 index a14cc99c36..0000000000 --- a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html +++ /dev/null @@ -1,61 +0,0 @@ -<div class="multiPairField form-group"> - <div ng-repeat="(index, item) in formValue" - class="multiPairFieldTable multiPairFieldTable{{ index }} has{{ item.fieldCount }}Fields multiple valign-wrapper"> - - <div piwik-field uicontrol="{{ field1.uiControl }}" - name="{{ name + '-p1-' + $index }}" - data-title="{{ field1.title }}" - full-width="true" - ng-if="field1.templateFile" - template-file="{{ field1.templateFile }}" - class="fieldUiControl fieldUiControl1" - ng-class="{'hasMultiFields': (field1.templateFile && field2.templateFile)}" - ng-model="formValue[index][field1.key]" - options="field1.availableValues" - ng-change="multiPairField.onEntryChange()" - placeholder=" "> - </div> - - <div piwik-field uicontrol="{{ field2.uiControl }}" - name="{{ name + '-p2-' + $index }}" - data-title="{{ field2.title }}" - full-width="true" - ng-if="field2.templateFile" - class="fieldUiControl fieldUiControl2" - template-file="{{ field2.templateFile }}" - options="field2.availableValues" - ng-change="multiPairField.onEntryChange()" - ng-model="formValue[index][field2.key]" - placeholder=" "> - </div> - - <div piwik-field uicontrol="{{ field3.uiControl }}" - data-title="{{ field3.title }}" - full-width="true" - ng-if="field3.templateFile" - class="fieldUiControl fieldUiControl3" - template-file="{{ field3.templateFile }}" - options="field3.availableValues" - ng-change="multiPairField.onEntryChange()" - ng-model="formValue[index][field3.key]" - placeholder=" "> - </div> - - <div piwik-field uicontrol="{{ field4.uiControl }}" - data-title="{{ field4.title }}" - full-width="true" - ng-if="field4.templateFile" - class="fieldUiControl fieldUiControl4" - template-file="{{ field4.templateFile }}" - options="field4.availableValues" - ng-change="multiPairField.onEntryChange()" - ng-model="formValue[index][field4.key]" - placeholder=" "> - </div> - - <span ng-click="multiPairField.removeEntry(index)" - title="{{ 'General_Remove'|translate }}" - ng-hide="(index + 1) == (formValue|length)" - class="icon-minus valign"></span> - </div> -</div>
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.js b/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.js deleted file mode 100644 index d877c05609..0000000000 --- a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.js +++ /dev/null @@ -1,64 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div matomo-multi-pair-field field1=".." field2="" ng-model="..."> - */ -(function () { - angular.module('piwikApp').directive('matomoMultiPairField', matomoMultiPairField); - - matomoMultiPairField.$inject = ['$document', 'piwik', '$filter']; - - function matomoMultiPairField($document, piwik, $filter){ - return { - restrict: 'A', - scope: { - name: '=', - field1: '=', - field2: '=', - field3: '=', - field4: '=' - }, - require: "?ngModel", - templateUrl: 'plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html?cb=' + piwik.cacheBuster, - controller: 'MultiPairFieldController', - controllerAs: 'multiPairField', - compile: function (element, attrs) { - - return function (scope, element, attrs, ngModel) { - - if (ngModel) { - ngModel.$setViewValue(scope.formValue); - } - - scope.$watch('formValue', function (newValue, oldValue) { - if (newValue != oldValue) { - element.trigger('change', newValue); - } - }, true); - - if (ngModel) { - ngModel.$render = function() { - if (angular.isString(ngModel.$viewValue)) { - scope.formValue = JSON.parse(ngModel.$viewValue); - } else { - scope.formValue = ngModel.$viewValue; - } - }; - } - - scope.$watch('formValue', function (newValue, oldValue) { - if (ngModel) { - ngModel.$setViewValue(newValue); - } - }, true); - }; - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/period-selector/period-selector.controller.js b/plugins/CoreHome/angularjs/period-selector/period-selector.controller.js deleted file mode 100644 index 37ad3542aa..0000000000 --- a/plugins/CoreHome/angularjs/period-selector/period-selector.controller.js +++ /dev/null @@ -1,363 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -(function () { - angular.module('piwikApp').controller('PeriodSelectorController', PeriodSelectorController); - - PeriodSelectorController.$inject = ['piwik', '$location', 'piwikPeriods', 'piwikComparisonsService', '$rootScope', 'piwikUrl', '$element', '$timeout']; - - function PeriodSelectorController(piwik, $location, piwikPeriods, piwikComparisonsService, $rootScope, piwikUrl, $element, $timeout) { - var piwikMinDate = new Date(piwik.minDateYear, piwik.minDateMonth - 1, piwik.minDateDay), - piwikMaxDate = new Date(piwik.maxDateYear, piwik.maxDateMonth - 1, piwik.maxDateDay); - - var vm = this; - - vm.comparePeriodDropdownOptions = [ - {key: 'custom', value: _pk_translate('General_Custom')}, - {key: 'previousPeriod', value: _pk_translate('General_PreviousPeriod').replace(/\s+/, piwikHelper.htmlDecode(' '))}, - {key: 'previousYear', value: _pk_translate('General_PreviousYear').replace(/\s+/, piwikHelper.htmlDecode(' '))}, - ]; - - // the period & date currently being viewed - vm.periodValue = null; - vm.dateValue = null; - - vm.selectedPeriod = null; - - vm.startRangeDate = null; - vm.endRangeDate = null; - vm.isRangeValid = null; - - vm.isLoadingNewPage = false; - - vm.isComparing = false; - vm.comparePeriodType = 'previousPeriod'; - vm.compareStartDate = ''; - vm.compareEndDate = ''; - - vm.getCurrentlyViewingText = getCurrentlyViewingText; - vm.changeViewedPeriod = changeViewedPeriod; - vm.setPiwikPeriodAndDate = setPiwikPeriodAndDate; - vm.onApplyClicked = onApplyClicked; - vm.updateSelectedValuesFromHash = updateSelectedValuesFromHash; - vm.getPeriodDisplayText = getPeriodDisplayText; - vm.$onChanges = $onChanges; - vm.onRangeChange = onRangeChange; - vm.isApplyEnabled = isApplyEnabled; - vm.$onInit = init; - vm.isComparisonEnabled = isComparisonEnabled; - - $rootScope.$on('$locationChangeSuccess', setIsComparing); - - function init() { - vm.updateSelectedValuesFromHash(); - setIsComparing(); - initTopControls(); // must be called when a top control changes width - - handleZIndexPositionRelativeCompareDropdownIssue(); - } - - function handleZIndexPositionRelativeCompareDropdownIssue() { - $element.on('focus', '#comparePeriodToDropdown .select-dropdown', function () { - $element.addClass('compare-dropdown-open'); - }).on('blur', '#comparePeriodToDropdown .select-dropdown', function () { - $element.removeClass('compare-dropdown-open'); - }); - } - - function setIsComparing() { - vm.isComparing = piwikComparisonsService.isComparingPeriods(); - } - - function $onChanges(changesObj) { - if (changesObj.periods) { - removeUnrecognizedPeriods(); - } - } - - function onRangeChange(start, end) { - if (!start || !end) { - vm.isRangeValid = false; - return; - } - - vm.isRangeValid = true; - vm.startRangeDate = start; - vm.endRangeDate = end; - } - - function isApplyEnabled() { - if (vm.selectedPeriod === 'range' - && !vm.isRangeValid - ) { - return false; - } - - if (vm.isComparing - && vm.comparePeriodType === 'custom' - && !isCompareRangeValid() - ) { - return false; - } - - return true; - } - - function isCompareRangeValid() { - try { - piwikPeriods.parseDate(vm.compareStartDate); - } catch (e) { - return false; - } - - try { - piwikPeriods.parseDate(vm.compareEndDate); - } catch (e) { - return false; - } - - return true; - } - - function removeUnrecognizedPeriods() { - vm.periods = vm.periods.filter(function (periodLabel) { - return piwikPeriods.isRecognizedPeriod(periodLabel); - }); - } - - function updateSelectedValuesFromHash() { - var strDate = piwikUrl.getSearchParam('date'); - var strPeriod = piwikUrl.getSearchParam('period'); - - vm.periodValue = strPeriod; - vm.selectedPeriod = strPeriod; - - vm.dateValue = vm.startRangeDate = vm.endRangeDate = null; - - try { - piwikPeriods.parse(strPeriod, strDate); - } catch (e) { - return; - } - - if (strPeriod === 'range') { - var period = piwikPeriods.get(strPeriod).parse(strDate); - vm.dateValue = period.startDate; - vm.startRangeDate = formatDate(period.startDate); - vm.endRangeDate = formatDate(period.endDate); - } else { - vm.dateValue = piwikPeriods.parseDate(strDate); - setRangeStartEndFromPeriod(strPeriod, strDate); - } - } - - function getPeriodDisplayText(periodLabel) { - return piwikPeriods.get(periodLabel).getDisplayText(); - } - - function getCurrentlyViewingText() { - var date; - if (vm.periodValue === 'range') { - if (!vm.startRangeDate || ! vm.endRangeDate) { - return _pk_translate('General_Error'); - } - - date = vm.startRangeDate + ',' + vm.endRangeDate; - } else { - if (!vm.dateValue) { - return _pk_translate('General_Error'); - } - - date = formatDate(vm.dateValue); - } - - try { - return piwikPeriods.parse(vm.periodValue, date).getPrettyString(); - } catch (e) { - return _pk_translate('General_Error'); - } - } - - function changeViewedPeriod(period) { - // only change period if it's different from what's being shown currently - if (period === vm.periodValue) { - return; - } - - // can't just change to a range period, w/o setting two new dates - if (period === 'range') { - return; - } - - setPiwikPeriodAndDate(period, vm.dateValue); - } - - function onApplyClicked() { - if (vm.selectedPeriod === 'range') { - var dateString = getSelectedDateString(); - if (!dateString) { - return; - } - - vm.periodValue = 'range'; - - propagateNewUrlParams(dateString, 'range'); - return; - } - - setPiwikPeriodAndDate(vm.selectedPeriod, vm.dateValue); - } - - function getSelectedDateString() { - if (vm.selectedPeriod === 'range') { - var dateFrom = vm.startRangeDate, - dateTo = vm.endRangeDate, - oDateFrom = piwikPeriods.parseDate(dateFrom), - oDateTo = piwikPeriods.parseDate(dateTo); - - if (!isValidDate(oDateFrom) - || !isValidDate(oDateTo) - || oDateFrom > oDateTo - ) { - // TODO: use a notification instead? - $('#alert').find('h2').text(_pk_translate('General_InvalidDateRange')); - piwik.helper.modalConfirm('#alert', {}); - return null; - } - - return dateFrom + ',' + dateTo; - } else { - return formatDate(vm.dateValue); - } - } - - function setPiwikPeriodAndDate(period, date) { - vm.periodValue = period; - vm.selectedPeriod = period; - vm.dateValue = date; - - var currentDateString = formatDate(date); - setRangeStartEndFromPeriod(period, currentDateString); - - propagateNewUrlParams(currentDateString, vm.selectedPeriod); - initTopControls(); - } - - function setRangeStartEndFromPeriod(period, dateStr) { - var dateRange = piwikPeriods.parse(period, dateStr).getDateRange(); - vm.startRangeDate = formatDate(dateRange[0] < piwikMinDate ? piwikMinDate : dateRange[0]); - vm.endRangeDate = formatDate(dateRange[1] > piwikMaxDate ? piwikMaxDate : dateRange[1]); - } - - function getSelectedComparisonParams() { - var previousDate; - - if (!vm.isComparing) { - return {}; - } - - if (vm.comparePeriodType === 'custom') { - return { - comparePeriods: ['range'], - compareDates: [vm.compareStartDate + ',' + vm.compareEndDate], - }; - } else if (vm.comparePeriodType === 'previousPeriod') { - previousDate = getPreviousPeriodDateToSelectedPeriod(); - return { - comparePeriods: [vm.selectedPeriod], - compareDates: [previousDate], - }; - } else if (vm.comparePeriodType === 'previousYear') { - var dateStr = vm.selectedPeriod === 'range' ? (vm.startRangeDate + ',' + vm.endRangeDate) : vm.dateValue; - var currentDateRange = piwikPeriods.parse(vm.selectedPeriod, dateStr).getDateRange(); - currentDateRange[0].setFullYear(currentDateRange[0].getFullYear() - 1); - currentDateRange[1].setFullYear(currentDateRange[1].getFullYear() - 1); - - if (vm.selectedPeriod === 'range') { - return { - comparePeriods: ['range'], - compareDates: [piwikPeriods.format(currentDateRange[0]) + ',' + piwikPeriods.format(currentDateRange[1])], - }; - } - - return { - comparePeriods: [vm.selectedPeriod], - compareDates: [piwikPeriods.format(currentDateRange[0])], - }; - } else { - console.warn("Unknown compare period type: " + vm.comparePeriodType); - return {}; - } - } - - function getPreviousPeriodDateToSelectedPeriod() { - if (vm.selectedPeriod === 'range') { - var currentStartRange = piwikPeriods.parseDate(vm.startRangeDate); - var currentEndRange = piwikPeriods.parseDate(vm.endRangeDate); - var newEndDate = piwikPeriods.RangePeriod.getLastNRange('day', 2, currentStartRange).startDate; - - var rangeSize = Math.floor((currentEndRange - currentStartRange) / 86400000); - var newRange = piwikPeriods.RangePeriod.getLastNRange('day', 1 + rangeSize, newEndDate); - - return piwikPeriods.format(newRange.startDate) + ',' + piwikPeriods.format(newRange.endDate); - } - - var newStartDate = piwikPeriods.RangePeriod.getLastNRange(vm.selectedPeriod, 2, vm.dateValue).startDate; - return piwikPeriods.format(newStartDate); - } - - function propagateNewUrlParams(date, period) { - var compareParams = getSelectedComparisonParams(); - - if (piwik.helper.isAngularRenderingThePage()) { - vm.closePeriodSelector(); // defined in directive - - var $search = $location.search(); - var isCurrentlyComparing = piwikUrl.getSearchParam('compareSegments') || piwikUrl.getSearchParam('comparePeriods'); - if (date !== $search.date || period !== $search.period || vm.isComparing || isCurrentlyComparing) { - // eg when using back button the date might be actually already changed in the URL and we do not - // want to change the URL again - $search.date = date; - $search.period = period; - $search.compareSegments = piwikUrl.getSearchParam('compareSegments') || []; - $.extend($search, compareParams); - - delete $search['compareSegments[]']; - delete $search['comparePeriods[]']; - delete $search['compareDates[]']; - - $location.search($.param($search)); - } - - return; - } - - vm.isLoadingNewPage = true; - - // not in an angular context (eg, embedded dashboard), so must actually - // change the URL - var url = $.param($.extend({ date: date, period: period }, compareParams)); - broadcast.propagateNewPage(url); - } - - function isValidDate(d) { - if (Object.prototype.toString.call(d) !== "[object Date]") { - return false; - } - - return !isNaN(d.getTime()); - } - - function formatDate(date) { - return piwikPeriods.format(date); - } - - function isComparisonEnabled() { - return piwikComparisonsService.isComparisonEnabled(); - } - } -})(); diff --git a/plugins/CoreHome/angularjs/period-selector/period-selector.directive.html b/plugins/CoreHome/angularjs/period-selector/period-selector.directive.html deleted file mode 100644 index a93c638b5a..0000000000 --- a/plugins/CoreHome/angularjs/period-selector/period-selector.directive.html +++ /dev/null @@ -1,134 +0,0 @@ -<div - piwik-expand-on-click - class="periodSelector piwikSelector" -> - <a - id="date" - class="title" - title="{{ 'General_ChooseDate'|translate:periodSelector.getCurrentlyViewingText() }}" - tabindex="-1" - > - <span class="icon icon-calendar"></span> - {{ periodSelector.getCurrentlyViewingText() }} - </a> - <div id="periodMore" class="dropdown"> - <div class="flex"> - <div> - <piwik-date-range-picker - ng-show="periodSelector.selectedPeriod === 'range'" - class="period-range" - start-date="periodSelector.startRangeDate" - end-date="periodSelector.endRangeDate" - range-change="periodSelector.onRangeChange(start, end)" - submit="periodSelector.onApplyClicked()" - > - </piwik-date-range-picker> - <div - class="period-date" - ng-if="periodSelector.selectedPeriod !== 'range'" - > - <piwik-period-date-picker - id="datepicker" - period="periodSelector.selectedPeriod" - date="periodSelector.periodValue === periodSelector.selectedPeriod ? periodSelector.dateValue : null" - select="periodSelector.setPiwikPeriodAndDate(periodSelector.selectedPeriod, date)" - > - </piwik-period-date-picker> - </div> - </div> - - <div class="period-type"> - <h6>{{ 'General_Period'|translate }}</h6> - <div id="otherPeriods"> - <p ng-repeat="period in periodSelector.periods"> - <label - ng-attr-title="{{ period === periodSelector.periodValue ? '' : ('General_DoubleClickToChangePeriod'|translate) }}" - ng-class="{'selected-period-label': period === periodSelector.selectedPeriod}" - ng-dblclick="periodSelector.changeViewedPeriod(period)" - > - <input - type="radio" - name="period" - ng-attr-id="period_id_{{ period }}" - ng-model="periodSelector.selectedPeriod" - ng-checked="periodSelector.selectedPeriod == period" - ng-change="periodSelector.selectedPeriod = period" - ng-dblclick="periodSelector.changeViewedPeriod(period)" - /> - <span>{{ periodSelector.getPeriodDisplayText(period) }}</span> - </label> - </p> - </div> - </div> - </div> - - <div class="compare-checkbox" ng-if="periodSelector.isComparisonEnabled()"> - <label> - <input - id="comparePeriodTo" - type="checkbox" - ng-model="periodSelector.isComparing" - /> - <span>{{ 'General_CompareTo'|translate }}</span> - </label> - - <div - id="comparePeriodToDropdown" - piwik-field - name="comparePeriodToDropdown" - uicontrol="select" - options="periodSelector.comparePeriodDropdownOptions" - ng-model="periodSelector.comparePeriodType" - full-width="true" - disabled="!periodSelector.isComparing" - ng-style="{'visibility' : periodSelector.isComparing ? 'visible' : 'hidden'}" - ></div> - </div> - - <div class="compare-date-range" ng-if="periodSelector.isComparing && periodSelector.comparePeriodType == 'custom'"> - <div> - <div - id="comparePeriodStartDate" - piwik-field - name="comparePeriodStartDate" - uicontrol="text" - ng-model="periodSelector.compareStartDate" - full-width="true" - title="Start Date" - placeholder="YYYY-MM-DD" - ></div> - - <span class="compare-dates-separator"></span> - - <div - id="comparePeriodEndDate" - piwik-field - name="comparePeriodEndDate" - uicontrol="text" - ng-model="periodSelector.compareEndDate" - full-width="true" - title="End Date" - placeholder="YYYY-MM-DD" - ></div> - </div> - </div> - - <div class="apply-button-container"> - <input - type="submit" - value="{{ 'General_Apply'|translate }}" - id="calendarApply" - class="btn" - ng-click="periodSelector.onApplyClicked()" - ng-disabled="!periodSelector.isApplyEnabled()" - /> - </div> - - <div id="ajaxLoadingCalendar" ng-if="periodSelector.isLoadingNewPage"> - <div piwik-activity-indicator loading="true"></div> - <div class="loadingSegment"> - {{ 'SegmentEditor_LoadingSegmentedDataMayTakeSomeTime'|translate }} - </div> - </div> - </div> -</div> diff --git a/plugins/CoreHome/angularjs/period-selector/period-selector.directive.js b/plugins/CoreHome/angularjs/period-selector/period-selector.directive.js deleted file mode 100644 index ab0ab4bbc9..0000000000 --- a/plugins/CoreHome/angularjs/period-selector/period-selector.directive.js +++ /dev/null @@ -1,47 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div piwik-period-selector> - */ -(function () { - angular.module('piwikApp').directive('piwikPeriodSelector', piwikPeriodSelector); - - piwikPeriodSelector.$inject = ['piwik', '$rootScope']; - - function piwikPeriodSelector(piwik, $rootScope) { - return { - restrict: 'A', - scope: { - periods: '<' - }, - templateUrl: 'plugins/CoreHome/angularjs/period-selector/period-selector.directive.html?cb=' + piwik.cacheBuster, - controller: 'PeriodSelectorController', - controllerAs: 'periodSelector', - bindToController: true, - link: function (scope, element) { - scope.periodSelector.closePeriodSelector = closePeriodSelector; - - scope.$on('$locationChangeSuccess', scope.periodSelector.updateSelectedValuesFromHash); - - $rootScope.$on('hidePeriodSelector', function () { - element.hide(); - }); - - // some widgets might hide the period selector using the event above, so ensure it's shown again when switching the page - $rootScope.$on('piwikPageChange', function () { - element.show(); - }); - - function closePeriodSelector() { - element.find('.periodSelector').removeClass('expanded'); - } - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js b/plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js deleted file mode 100644 index 46757a06bd..0000000000 --- a/plugins/CoreHome/angularjs/popover-handler/popover-handler.directive.js +++ /dev/null @@ -1,78 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * When present in the page it listens to a popover URL parameter. - * - * If present it will try to load the related content in a popover or if the URL is empty it will close an - * opened popover. - * - * Example: - * <div piwik-popover-handler></div> - */ -(function () { - angular.module('piwikApp').directive('piwikPopoverHandler', piwikPopoverHandler); - - piwikPopoverHandler.$inject = ['$location', '$rootScope', 'piwik']; - - function piwikPopoverHandler($location, $rootScope, piwik){ - - return { - restrict: 'A', - scope: {}, - controller: function () { - - function close() - { - Piwik_Popover.close(); - } - - function open(popoverParam) - { - // in case the $ was encoded (e.g. when using copy&paste on urls in some browsers) - popoverParam = decodeURIComponent(popoverParam); - // revert special encoding from broadcast.propagateNewPopoverParameter() - popoverParam = popoverParam.replace(/\$/g, '%'); - popoverParam = decodeURIComponent(popoverParam); - - var popoverParamParts = popoverParam.split(':'); - var handlerName = popoverParamParts[0]; - popoverParamParts.shift(); - var param = popoverParamParts.join(':'); - if (typeof piwik.broadcast.popoverHandlers[handlerName] != 'undefined' - && !piwik.broadcast.isLoginPage()) { - piwik.broadcast.popoverHandlers[handlerName](param); - } - } - - function openOrClose() - { - close(); - - // should be rather done by routing - var popoverParam = $location.search().popover; - if (popoverParam) { - open(popoverParam); - } else { - // the URL should only be set to an empty popover if there are no popovers in the stack. - // to avoid avoid any strange inconsistent states, we reset the popover stack here. - broadcast.resetPopoverStack(); - } - } - - $rootScope.$on('$locationChangeSuccess', function () { - // should be rather done by routing - $(function () { - // make sure all popover handles were registered - openOrClose(); - }); - }); - - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/progressbar/progressbar.directive.html b/plugins/CoreHome/angularjs/progressbar/progressbar.directive.html deleted file mode 100644 index 5bbb4e4400..0000000000 --- a/plugins/CoreHome/angularjs/progressbar/progressbar.directive.html +++ /dev/null @@ -1,7 +0,0 @@ -<div class="progressbar"> - <div class="progress"> - <div class="determinate" style="width: 0" - ng-style="{width: (progress + '%')}"></div> - </div> - <span ng-show="!!label"><img src='./plugins/Morpheus/images/loading-blue.gif'/> <span ng-bind-html="label"></span></span> -</div>
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/progressbar/progressbar.directive.js b/plugins/CoreHome/angularjs/progressbar/progressbar.directive.js deleted file mode 100644 index 4c5cdaa488..0000000000 --- a/plugins/CoreHome/angularjs/progressbar/progressbar.directive.js +++ /dev/null @@ -1,54 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div piwik-progressbar> - */ -(function () { - angular.module('piwikApp').directive('piwikProgressbar', piwikProgressbar); - - piwikProgressbar.$inject = ['piwik']; - - function piwikProgressbar(piwik){ - var defaults = { - label: '', - progress: 0 - }; - - return { - restrict: 'A', - scope: { - progress: '=', - label: '=' - }, - templateUrl: 'plugins/CoreHome/angularjs/progressbar/progressbar.directive.html?cb=' + piwik.cacheBuster, - compile: function (element, attrs) { - - for (var index in defaults) { - if (defaults.hasOwnProperty(index) && attrs[index] === undefined) { - attrs[index] = defaults[index]; - } - } - - return function (scope, element, attrs) { - - scope.$watch('progress', function (val, oldVal) { - if (val !== oldVal) { - if (val > 100) { - scope.progress = 100; - } else if (val < 0) { - scope.progress = 0; - } - } - }); - - }; - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/quick-access/quick-access.controller.js b/plugins/CoreHome/angularjs/quick-access/quick-access.controller.js deleted file mode 100644 index f9f28c923c..0000000000 --- a/plugins/CoreHome/angularjs/quick-access/quick-access.controller.js +++ /dev/null @@ -1,90 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').controller('QuickAccessController', QuickAccessController); - - QuickAccessController.$inject = ['$scope', '$filter', 'siteSelectorModel']; - - function QuickAccessController($scope, $filter, siteSelectorModel){ - - this.menuItems = []; - this.numMenuItems = 0; - this.sitesModel = siteSelectorModel; - - this.onKeypress = function (event) { - var areSearchResultsDisplayed = $scope.search && $scope.search.term && $scope.view && $scope.view.searchActive; - var isTabKey = 9 == event.which; - var isEscKey = 27 == event.which; - - if (38 == event.which) { - $scope.highlightPreviousItem(); - event.preventDefault(); - } else if (40 == event.which) { - $scope.highlightNextItem(); - event.preventDefault(); - } else if (13 == event.which) { - $scope.clickQuickAccessMenuItem(); - } else if (isTabKey && areSearchResultsDisplayed) { - $scope.deactivateSearch(); - } else if (isEscKey && areSearchResultsDisplayed) { - $scope.deactivateSearch(); - } - }; - - this.searchMenu = function (searchTerm) { - searchTerm = searchTerm.toLowerCase(); - - var index = -1; - var menuItemsIndex = {}; - var menuItems = []; - - var moveToCategory = function (i, submenuItem) { - submenuItem = angular.copy(submenuItem); // force rerender of element to prevent weird side effects - submenuItem.menuIndex = ++index; // needed for proper highlighting with arrow keys - - var category = submenuItem.category; - if (!(category in menuItemsIndex)) { - menuItems.push({title: category, items: []}); - menuItemsIndex[category] = menuItems.length - 1; - } - - var indexOfCategory = menuItemsIndex[category]; - menuItems[indexOfCategory].items.push(submenuItem); - }; - - $scope.resetSearchIndex(); - - if ($scope.hasSitesSelector) { - this.sitesModel.searchSite(searchTerm); - } - - var topMenuItems = $filter('filter')($scope.getTopMenuItems(), searchTerm); - var leftMenuItems = $filter('filter')($scope.getLeftMenuItems(), searchTerm); - var segmentItems = $filter('filter')($scope.getSegmentItems(), searchTerm); - - $.each(topMenuItems, moveToCategory); - $.each(leftMenuItems, moveToCategory); - $.each(segmentItems, moveToCategory); - - this.numMenuItems = topMenuItems.length + leftMenuItems.length + segmentItems.length; - this.menuItems = menuItems; - }; - - this.selectSite = function (idsite) { - this.sitesModel.loadSite(idsite); - }; - - this.selectMenuItem = function (index) { - $scope.selectMenuItem(index); - }; - - if (typeof initTopControls !== 'undefined' && initTopControls) { - initTopControls(); - } - - } -})(); diff --git a/plugins/CoreHome/angularjs/quick-access/quick-access.directive.html b/plugins/CoreHome/angularjs/quick-access/quick-access.directive.html deleted file mode 100644 index c28c8f1d1f..0000000000 --- a/plugins/CoreHome/angularjs/quick-access/quick-access.directive.html +++ /dev/null @@ -1,48 +0,0 @@ -<div class="quick-access piwikSelector" - ng-class="{active: view.searchActive, expanded: view.searchActive}" - piwik-focus-anywhere-but-here="view.searchActive = false;"> - <span class="icon-search" ng-hide="search.term || view.searchActive" - ng-mouseenter="view.searchActive=true"></span> - <input class="s" - title="{{ quickAccessTitle }}" - ng-keydown="quickAccess.onKeypress($event)" - ng-change="view.searchActive=true;quickAccess.searchMenu(search.term)" - ng-focus="view.searchActive=true" - ng-model="search.term" piwik-focus-if="view.searchActive" - type="text" tabindex="2"/> - <div class="dropdown" ng-show="search.term && view.searchActive"> - <ul ng-hide="(quickAccess.numMenuItems > 0) || (quickAccess.sitesModel.sites | length)"> - <li class="no-result">{{ 'General_SearchNoResults' | translate }}</li> - </ul> - <ul ng-repeat="subcategory in quickAccess.menuItems"> - <li class="quick-access-category" - ng-click="search.term = subcategory.title;quickAccess.searchMenu(search.term)">{{ subcategory.title }}</li> - <li class="result" - ng-class="{selected: submenuEntry.menuIndex == search.index}" - ng-mouseenter="search.index=submenuEntry.menuIndex" - ng-click="quickAccess.selectMenuItem(submenuEntry.index)" - ng-repeat="submenuEntry in subcategory.items"><a>{{ submenuEntry.name | trim }}</a></li> - </ul> - <ul class="quickAccessMatomoSearch"> - <li class="quick-access-category websiteCategory" - ng-show="hasSitesSelector && ((quickAccess.sitesModel.sites | length) || quickAccess.sitesModel.isLoading)" - >{{ 'SitesManager_Sites' | translate }}</li> - <li class="no-result" - ng-show="hasSitesSelector && quickAccess.sitesModel.isLoading">{{ 'MultiSites_LoadingWebsites' | translate }}</li> - <li class="result" - ng-show="hasSitesSelector && !quickAccess.sitesModel.isLoading" - ng-mouseenter="search.index=(quickAccess.numMenuItems + $index)" - ng-class="{selected: (quickAccess.numMenuItems + $index) == search.index}" - ng-click="quickAccess.selectSite(site.idsite)" - ng-repeat="site in quickAccess.sitesModel.sites"><a ng-bind="site.name"></a></li> - </ul> - <ul> - <li class="quick-access-category helpCategory">{{ 'General_HelpResources' | translate }}</li> - <li ng-class="{selected: search.index == 'help'}" - class="quick-access-help" - ng-mouseenter="search.index='help'"> - <a ng-href="https://matomo.org?s={{ urlEncode(search.term) }}" target="_blank">{{'CoreHome_SearchOnMatomo' | translate:(search.term)}}</a> - </li> - </ul> - </div> -</div> diff --git a/plugins/CoreHome/angularjs/quick-access/quick-access.directive.js b/plugins/CoreHome/angularjs/quick-access/quick-access.directive.js deleted file mode 100644 index 7417261c8e..0000000000 --- a/plugins/CoreHome/angularjs/quick-access/quick-access.directive.js +++ /dev/null @@ -1,287 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div piwik-dialog="showDialog">...</div> - * Will show dialog once showDialog evaluates to true. - * - * Will execute the "executeMyFunction" function in the current scope once the yes button is pressed. - */ -(function () { - angular.module('piwikApp').directive('piwikQuickAccess', QuickAccessDirective); - - QuickAccessDirective.$inject = ['$rootElement', '$timeout', 'piwik', '$filter']; - - function QuickAccessDirective ($rootElement, $timeout, piwik, $filter) { - - return { - restrict: 'A', - replace: true, - scope: {}, - templateUrl: 'plugins/CoreHome/angularjs/quick-access/quick-access.directive.html?cb=' + piwik.cacheBuster, - controller: 'QuickAccessController', - controllerAs: 'quickAccess', - link: function (scope, element, attrs) { - - var menuIndex = -1; // the menu index is used to identify which element to click - var topMenuItems = []; // cache for top menu items - var leftMenuItems = []; // cache for left menu items - var segmentItems = []; // cache for segment items - var hasSegmentSelector = angular.element('.segmentEditorPanel').length; - scope.hasSitesSelector = angular.element('.top_controls [piwik-siteselector]').length; - - - var translate = $filter('translate'); - var searchAreasTitle = ''; - var searchAreas = [translate('CoreHome_MenuEntries')]; - - if (hasSegmentSelector) { - searchAreas.push(translate('CoreHome_Segments')); - } - - if (scope.hasSitesSelector) { - searchAreas.push(translate('SitesManager_Sites')); - } - - while (searchAreas.length) { - searchAreasTitle += searchAreas.shift(); - if (searchAreas.length >= 2) { - searchAreasTitle += ', '; - } else if (searchAreas.length === 1) { - searchAreasTitle += ' ' + translate('General_And') + ' '; - } - } - - scope.quickAccessTitle = translate('CoreHome_QuickAccessTitle', searchAreasTitle); - - function trim(str) { - if (str) { - return str.replace(/^\s+|\s+$/g,''); - } - return str; - } - - scope.getTopMenuItems = function() - { - if (topMenuItems && topMenuItems.length) { - return topMenuItems; - } - - var category = _pk_translate('CoreHome_Menu'); - - $rootElement.find('nav .sidenav li > a').each(function (index, element) { - var $element = $(element); - - var text = trim($element.text()); - - if (!text) { - text = trim($element.attr('title')); // possibly a icon, use title instead - } - - if (text) { - topMenuItems.push({name: text, index: ++menuIndex, category: category}); - $element.attr('quick_access', menuIndex); - } - }); - - return topMenuItems; - }; - - scope.getLeftMenuItems = function () - { - if (leftMenuItems && leftMenuItems.length) { - return leftMenuItems; - } - - $rootElement.find('#secondNavBar .menuTab').each(function (index, element) { - var $element = angular.element(element); - var category = trim($element.find('> .item').text()); - - if (category && -1 !== category.lastIndexOf("\n")) { - // remove "\n\nMenu" - category = trim(category.substr(0, category.lastIndexOf("\n"))); - } - - $element.find('li .item').each(function (i, element) { - var $element = angular.element(element); - var text = trim($element.text()); - if (text) { - leftMenuItems.push({name: text, category: category, index: ++menuIndex}); - $element.attr('quick_access', menuIndex); - } - }); - - }); - - return leftMenuItems; - }; - - scope.getSegmentItems = function() - { - if (!hasSegmentSelector) { - return []; - } - - if (segmentItems && segmentItems.length) { - return segmentItems; - } - - var category = _pk_translate('CoreHome_Segments'); - - $rootElement.find('.segmentList [data-idsegment]').each(function (index, element) { - var $element = angular.element(element); - var text = trim($element.find('.segname').text()); - - if (text) { - segmentItems.push({name: text, category: category, index: ++menuIndex}); - $element.attr('quick_access', menuIndex); - } - }); - - return segmentItems; - }; - - scope.activateSearch = function() - { - scope.$eval('view.searchActive = true'); - $timeout(function () { - scope.$apply(); - }, 0); - }; - - scope.deactivateSearch = function() - { - scope.$eval('search.term = ""'); - scope.$eval('view.searchActive = false'); - element.find('input').blur(); - $timeout(function () { - scope.$apply(); - }, 0); - }; - - function isElementInViewport(element) { - - var rect = element.getBoundingClientRect(); - - return ( - rect.top >= 0 && - rect.left >= 0 && - rect.bottom <= $(window).height() && - rect.right <= $(window).width() - ); - } - - function getCurrentlySelectedElement(index) - { - var results = element.find('li.result'); - if (results && results.length && results[scope.search.index]) { - return $(results[scope.search.index]); - } - } - - function makeSureSelectedItemIsInViewport() { - var element = getCurrentlySelectedElement(); - - if (element && element[0] && !isElementInViewport(element[0])) { - scrollFirstElementIntoView(element); - } - } - - function scrollFirstElementIntoView(element) - { - if (element && element[0] && element[0].scrollIntoView) { - // make sure search is visible - element[0].scrollIntoView(); - } - } - - scope.highlightPreviousItem = function() - { - if (0 >= (scope.search.index - 1)) { - scope.search.index = 0; - } else { - scope.search.index--; - } - makeSureSelectedItemIsInViewport(); - }; - - scope.resetSearchIndex = function () { - scope.search.index = 0; - makeSureSelectedItemIsInViewport(); - }; - - scope.highlightNextItem = function() - { - var numTotal = element.find('li.result').length; - - if (numTotal <= (scope.search.index + 1)) { - scope.search.index = numTotal - 1; - } else { - scope.search.index++; - } - - makeSureSelectedItemIsInViewport(); - }; - - scope.clickQuickAccessMenuItem = function() - { - var selectedMenuElement = getCurrentlySelectedElement(); - if (selectedMenuElement) { - $timeout(function () { - selectedMenuElement.click(); - }, 20); - } - }; - - scope.selectMenuItem = function(index) - { - var target = $rootElement.find('[quick_access=' + index + ']'); - - if (target && target.length && target[0]) { - scope.deactivateSearch(); - - var actualTarget = target[0]; - - var href = $(actualTarget).attr('href'); - - if (href && href.length > 10 && actualTarget && actualTarget.click) { - try { - actualTarget.click(); - } catch (e) { - $(actualTarget).click(); - } - } else { - $(actualTarget).click(); - } - } - }; - - scope.urlEncode = function(term) - { - return encodeURIComponent(term); - }; - - piwikHelper.registerShortcut('f', _pk_translate('CoreHome_ShortcutSearch'), function(event) { - if (event.altKey) { - return; - } - if (event.preventDefault) { - event.preventDefault(); - } else { - event.returnValue = false; // IE - } - - scrollFirstElementIntoView(element); - - scope.activateSearch(); - }); - - } - }; - } -})(); diff --git a/plugins/CoreHome/angularjs/report-export/reportexport.directive.js b/plugins/CoreHome/angularjs/report-export/reportexport.directive.js deleted file mode 100644 index a0edb62b11..0000000000 --- a/plugins/CoreHome/angularjs/report-export/reportexport.directive.js +++ /dev/null @@ -1,296 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * - */ -(function () { - angular.module('piwikApp').directive('piwikReportExport', piwikReportExport); - - piwikReportExport.$inject = ['$document', 'piwik', '$compile', '$timeout', '$location', '$httpParamSerializerJQLike']; - - function piwikReportExport($document, piwik, $compile, $timeout, $location, $httpParamSerializerJQLike){ - - return { - restrict: 'A', - scope: { - 'reportTitle': '@', - 'requestParams': '@', - 'reportFormats': '@', - 'apiMethod': '@', - 'maxFilterLimit': '@', - }, - link: function(scope, element, attr) { - - var popoverParamBackup; - - scope.showUrl = false; - - scope.getExportLinkWithoutToken = function() { - return scope.getExportLink(false); - } - - scope.getExportLink = function(withToken) { - withToken = (typeof withToken !== 'undefined') ? withToken : true; - - var dataTable = scope.dataTable; - var format = scope.reportFormat; - - if (!format) { - return; - } - - var method = scope.apiMethod; - var limit = scope.reportLimitAll == 'yes' ? -1 : scope.reportLimit; - var type = scope.reportType; - var params = scope.requestParams; - - if (params && typeof params == "string") { - params = JSON.parse(params); - } else { - params = {}; - } - - var segment = dataTable.param.segment; - var label = dataTable.param.label; - var idGoal = dataTable.param.idGoal; - var idDimension = dataTable.param.idDimension; - var param_date = dataTable.param.date; - - if (format == 'RSS') { - param_date = 'last10'; - } - if (typeof dataTable.param.dateUsedInGraph != 'undefined') { - param_date = dataTable.param.dateUsedInGraph; - } - var period = dataTable.param.period; - - var formatsUseDayNotRange = piwik.config.datatable_export_range_as_day.toLowerCase(); - - if (formatsUseDayNotRange.indexOf(format.toLowerCase()) != -1 - && dataTable.param.period == 'range') { - period = 'day'; - } - - // Below evolution graph, show daily exports - if(dataTable.param.period == 'range' - && dataTable.param.viewDataTable == "graphEvolution") { - period = 'day'; - } - - var exportUrlParams = { - module: 'API' - }; - - if (type == 'processed') { - var apiParams = method.split('.'); - exportUrlParams.method = 'API.getProcessedReport'; - exportUrlParams.apiModule = apiParams[0]; - exportUrlParams.apiAction = apiParams[1]; - } else { - exportUrlParams.method = method; - } - - exportUrlParams.format = format; - exportUrlParams.idSite = dataTable.param.idSite; - exportUrlParams.period = period; - exportUrlParams.date = param_date; - - if (dataTable.param.compareDates - && dataTable.param.compareDates.length - ) { - exportUrlParams.compareDates = dataTable.param.compareDates; - exportUrlParams.compare = '1'; - } - - if (dataTable.param.comparePeriods - && dataTable.param.comparePeriods.length - ) { - exportUrlParams.comparePeriods = dataTable.param.comparePeriods; - exportUrlParams.compare = '1'; - } - - if (dataTable.param.compareSegments - && dataTable.param.compareSegments.length - ) { - exportUrlParams.compareSegments = dataTable.param.compareSegments; - exportUrlParams.compare = '1'; - } - - if (typeof dataTable.param.filter_pattern != "undefined") { - exportUrlParams.filter_pattern = dataTable.param.filter_pattern; - } - - if (typeof dataTable.param.filter_pattern_recursive != "undefined") { - exportUrlParams.filter_pattern_recursive = dataTable.param.filter_pattern_recursive; - } - - if ($.isPlainObject(params)) { - $.each(params, function (index, param) { - if (param === true) { - param = 1; - } else if (param === false) { - param = 0; - } - exportUrlParams[index] = param; - }); - } - - if (scope.optionFlat) { - exportUrlParams.flat = 1; - if (typeof dataTable.param.include_aggregate_rows != "undefined" && dataTable.param.include_aggregate_rows == '1') { - exportUrlParams.include_aggregate_rows = 1; - } - } - - if (!scope.optionFlat && scope.optionExpanded) { - exportUrlParams.expanded = 1; - } - - if (scope.optionFormatMetrics) { - exportUrlParams.format_metrics = 1; - } - - if (dataTable.param.pivotBy) { - exportUrlParams.pivotBy = dataTable.param.pivotBy; - exportUrlParams.pivotByColumnLimit = 20; - - if (dataTable.props.pivot_by_column) { - exportUrlParams.pivotByColumn = dataTable.props.pivot_by_column; - } - } - if (format == 'CSV' || format == 'TSV' || format == 'RSS') { - exportUrlParams.translateColumnNames = 1; - exportUrlParams.language = piwik.language; - } - if (typeof segment != 'undefined') { - exportUrlParams.segment = decodeURIComponent(segment); - } - // Export Goals specific reports - if (typeof idGoal != 'undefined' - && idGoal != '-1') { - exportUrlParams.idGoal = idGoal; - } - // Export Dimension specific reports - if (typeof idDimension != 'undefined' - && idDimension != '-1') { - exportUrlParams.idDimension = idDimension; - } - if (label) { - label = label.split(','); - - if (label.length > 1) { - exportUrlParams.label = label; - } else { - exportUrlParams.label = label[0]; - } - } - - - exportUrlParams.token_auth = 'ENTER_YOUR_TOKEN_AUTH_HERE'; - - if (withToken === true) { - exportUrlParams.token_auth = piwik.token_auth; - exportUrlParams.force_api_session = 1; - } - - exportUrlParams.filter_limit = limit; - - var currentUrl = $location.absUrl(); - var urlParts = currentUrl.split('/'); - urlParts.pop(); - var url = urlParts.join('/'); - - return url + '/index.php?' + $httpParamSerializerJQLike(exportUrlParams); - }; - - element.on('click', function () { - - popoverParamBackup = broadcast.getValueFromHash('popover'); - - var dataTable = scope.dataTable = element.parents('[data-report]').data('uiControlObject'); - var popover = Piwik_Popover.showLoading('Export'); - var formats = JSON.parse(scope.reportFormats); - - scope.reportType = 'default'; - var reportLimit = dataTable.param.filter_limit; - if (scope.maxFilterLimit > 0) { - reportLimit = Math.min(reportLimit, scope.maxFilterLimit); - } - scope.reportLimit = reportLimit > 0 ? reportLimit : 100; - scope.reportLimitAll = reportLimit == -1 ? 'yes' : 'no'; - scope.optionFlat = dataTable.param.flat === true || dataTable.param.flat === 1 || dataTable.param.flat === "1"; - scope.optionExpanded = true; - scope.optionFormatMetrics = false; - scope.hasSubtables = scope.optionFlat || dataTable.numberOfSubtables > 0; - - scope.availableReportFormats = { - default: formats, - processed: { - 'XML': formats['XML'], - 'JSON': formats['JSON'] - } - }; - scope.availableReportTypes = { - default: _pk_translate('CoreHome_StandardReport'), - processed: _pk_translate('CoreHome_ReportWithMetadata') - }; - scope.limitAllOptions = { - yes: _pk_translate('General_All'), - no: _pk_translate('CoreHome_CustomLimit') - }; - - scope.$watch('reportType', function (newVal, oldVal) { - if (!scope.availableReportFormats[newVal].hasOwnProperty(scope.reportFormat)) { - scope.reportFormat = 'XML'; - } - }, true); - - if (scope.maxFilterLimit > 0) { - scope.$watch('reportLimit', function (newVal, oldVal) { - if (parseInt(newVal, 10) > parseInt(scope.maxFilterLimit, 10)) { - scope.reportLimit = oldVal; - } - }, true); - } - - var elem = $document.find('#reportExport').eq(0); - - if (!elem.length) { - elem = angular.element('<span ng-include="\'plugins/CoreHome/angularjs/report-export/reportexport.popover.html?cb=' + piwik.cacheBuster + '\'" id="reportExport"></span>'); - } - - $compile(elem)(scope, function (compiled){ - Piwik_Popover.setTitle(_pk_translate('General_Export') + ' ' + piwikHelper.htmlEntities(scope.reportTitle)); - Piwik_Popover.setContent(compiled); - - if (popoverParamBackup != '') { - Piwik_Popover.onClose(function(){ - $timeout(function(){ - $location.search('popover', popoverParamBackup); - - $timeout(function () { - angular.element(document).injector().get('$rootScope').$apply(); - }, 10); - }, 100); - }); - } - - $timeout(function(){ - popover.dialog(); - $('.exportFullUrl, .btn', popover).tooltip({ - track: true, - show: false, - hide: false - }); - }, 100); - }); - }); - } - }; - } -})(); diff --git a/plugins/CoreHome/angularjs/report-export/reportexport.popover.html b/plugins/CoreHome/angularjs/report-export/reportexport.popover.html deleted file mode 100644 index f206424602..0000000000 --- a/plugins/CoreHome/angularjs/report-export/reportexport.popover.html +++ /dev/null @@ -1,76 +0,0 @@ -<div class="report-export-popover row"> - - <div class="col l6"> - <div piwik-field uicontrol="radio" name="format" - data-title="{{ 'CoreHome_ExportFormat'|translate }}" - ng-model="$parent.reportFormat" - full-width="true" - value="XML" - options="availableReportFormats[$parent.reportType]"> - </div> - - <div piwik-field uicontrol="checkbox" name="option_flat" - data-title="{{ 'CoreHome_FlattenReport'|translate }}" - ng-model="$parent.optionFlat" ng-show="$parent.hasSubtables"> - </div> - <div piwik-field uicontrol="checkbox" name="option_expanded" - data-title="{{ 'CoreHome_ExpandSubtables'|translate }}" - ng-model="$parent.optionExpanded" ng-show="$parent.hasSubtables && !$parent.optionFlat" - > - </div> - <div piwik-field uicontrol="checkbox" name="option_format_metrics" - data-title="{{ 'CoreHome_FormatMetrics'|translate }}" - ng-model="$parent.optionFormatMetrics" - > - </div> - </div> - - <div class="col l6"> - <div piwik-field uicontrol="radio" name="filter_type" - data-title="{{ 'CoreHome_ReportType'|translate }}" - ng-model="$parent.reportType" - full-width="true" - options="availableReportTypes"> - </div> - - <div class="filter_limit"> - <div piwik-field uicontrol="radio" name="filter_limit_all" - data-title="{{ 'CoreHome_RowLimit'|translate }}" - ng-model="$parent.reportLimitAll" - ng-hide="maxFilterLimit > 0" - full-width="false" - options="limitAllOptions"> - </div> - <div piwik-field uicontrol="number" name="filter_limit" - min="1" - ng-model="$parent.reportLimit" - full-width="false" - ng-show="$parent.reportLimitAll == 'no' && maxFilterLimit <= 0"> - </div> - - <div piwik-field uicontrol="number" name="filter_limit" - min="1" - max="{{ scope.reportLimit }}" - ng-model="$parent.reportLimit" - ng-keypress="scope.checkNumberForLimit" - full-width="false" - data-title="{{ 'CoreHome_RowLimit'|translate }} ({{ 'General_ComputedMetricMax'|translate:maxFilterLimit }})" - ng-show="$parent.reportLimitAll == 'no' && maxFilterLimit > 0"> - </div> - </div> - </div> - - <div class="col l12" ng-show="showUrl"> - <textarea piwik-select-on-focus readonly class="exportFullUrl">{{ getExportLinkWithoutToken() }}</textarea> - <div class="tooltip" ng-bind-html="'CoreHome_ExportTooltipWithLink'|translate:'<a target=_blank href=\'?module=UsersManager&action=userSecurity\'>':'</a>':'ENTER_YOUR_TOKEN_AUTH_HERE'"></div> - </div> - - <div class="col l12"> - <a class="btn" ng-attr-href="{{ getExportLink() }}" target="_new" title="{{ 'CoreHome_ExportTooltip'|translate }}">{{ 'General_Export'|translate }}</a> - <a href="javascript:;" ng-click="showUrl=!showUrl" class="toggle-export-url"> - <span ng-show="!showUrl">{{ 'CoreHome_ShowExportUrl'|translate }}</span> - <span ng-show="showUrl">{{ 'CoreHome_HideExportUrl'|translate }}</span> - </a> - </div> - -</div>
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js deleted file mode 100644 index 5b56090de8..0000000000 --- a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu-model.js +++ /dev/null @@ -1,165 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').factory('reportingMenuModel', reportingMenuModelService); - - reportingMenuModelService.$inject = ['$filter', '$q', 'reportingPagesModel', '$location']; - - function reportingMenuModelService ($filter, $q, reportingPagesModel, $location) { - - // those sites are going to be displayed - var model = { - menu: [], - selected: [], - fetchMenuItems: fetchMenuItems, - reloadMenuItems: reloadMenuItems, - findSubcategory: findSubcategory - }; - - return model; - - function isNumeric(text) { - return !isNaN(parseFloat(text)) && isFinite(text); - } - - function findSubcategory(categoryId, subcategoryId) - { - var foundCategory = null; - var foundSubcategory = null; - var foundSubSubcategory = null; - - angular.forEach(model.menu, function (category) { - if (category.id !== categoryId) { - return; - } - angular.forEach(category.subcategories, function (subcategory) { - if (subcategory.id === subcategoryId) { - foundCategory = category; - foundSubcategory = subcategory; - } - - if (subcategory.isGroup) { - angular.forEach(subcategory.subcategories, function (subcat) { - if (subcat.id === subcategoryId) { - foundCategory = category; - foundSubcategory = subcategory; - foundSubSubcategory = subcat; - } - }); - } - }); - }); - - return {category: foundCategory, subcategory: foundSubcategory, subsubcategory: foundSubSubcategory}; - } - - function buildMenuFromPages(pages) - { - var menu = []; - - var activeCategory = $location.search().category; - var activeSubcategory = $location.search().subcategory; - - var categoriesHandled = {}; - angular.forEach(pages, function (page, key) { - var category = page.category; - var categoryId = category.id; - - if (categoriesHandled[categoryId]) { - return; - } - - categoriesHandled[categoryId] = true; - - if (activeCategory && category.id === activeCategory) { - // this doesn't really belong here but placed it here for convenience - category.active = true; - } - - category.subcategories = []; - - var categoryGroups = false; - - angular.forEach(pages, function (page, key) { - if (page.category.id === categoryId) { - var subcategory = page.subcategory; - - if (subcategory.id === activeSubcategory && categoryId === activeCategory) { - subcategory.active = true; - } - - if (page.widgets && page.widgets[0] && isNumeric(page.subcategory.id)) { - // we handle a goal - if (!categoryGroups) { - categoryGroups = angular.copy(subcategory); - categoryGroups.name = $filter('translate')('CoreHome_ChooseX', [category.name]); - categoryGroups.isGroup = true; - categoryGroups.subcategories = []; - categoryGroups.order = 10; - } - - if (subcategory.active) { - categoryGroups.name = subcategory.name; - categoryGroups.active = true; - } - - var goalId = page.subcategory.id; - subcategory.tooltip = subcategory.name + ' (id = ' + goalId + ' )'; - - categoryGroups.subcategories.push(subcategory); - return; - } - - category.subcategories.push(subcategory); - } - }); - - if (categoryGroups && categoryGroups.subcategories && categoryGroups.subcategories.length <= 5) { - angular.forEach(categoryGroups.subcategories, function (subcategory) { - category.subcategories.push(subcategory); - }); - } else if(categoryGroups) { - category.subcategories.push(categoryGroups); - } - - category.subcategories = sortMenuItems(category.subcategories); - - menu.push(category); - - return menu; - }); - - menu = sortMenuItems(menu); - - return menu; - } - - function sortMenuItems(menu) { - return $filter('orderBy')(menu, 'order'); - }; - - function reloadMenuItems() - { - var pagesPromise = reportingPagesModel.reloadAllPages(); - return pagesPromise.then(function (pages) { - model.menu = buildMenuFromPages(pages); - return model.menu; - }); - } - - function fetchMenuItems() - { - var pagesPromise = reportingPagesModel.getAllPages(); - - return pagesPromise.then(function (pages) { - model.menu = buildMenuFromPages(pages); - - return model.menu; - }); - } - } -})(); diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js deleted file mode 100644 index 949d85a9b0..0000000000 --- a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.controller.js +++ /dev/null @@ -1,248 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').controller('ReportingMenuController', ReportingMenuController); - - ReportingMenuController.$inject = ['$scope', 'piwik', '$location', '$timeout', 'reportingMenuModel', '$rootScope', 'piwikUrl']; - - function ReportingMenuController($scope, piwik, $location, $timeout, menuModel, $rootScope, piwikUrl) { - - $scope.helpShownCategory = null; - - var idSite = piwikUrl.getSearchParam('idSite'); - var period = piwikUrl.getSearchParam('period'); - var date = piwikUrl.getSearchParam('date'); - var segment = piwikUrl.getSearchParam('segment'); - - var comparePeriods = piwikUrl.getSearchParam('comparePeriods'); - var compareDates = piwikUrl.getSearchParam('compareDates'); - var compareSegments = piwikUrl.getSearchParam('compareSegments'); - - var showSubcategoryHelpOnLoad = null; - - var initialLoad = true; - - $scope.currentCategory = piwikUrl.getSearchParam('category'); - $scope.currentSubcategory = piwikUrl.getSearchParam('subcategory'); - - function markAllCategoriesAsInactive() - { - angular.forEach(menuModel.menu, function (cat) { - cat.active = false; - }); - } - - function markAllCategoriesAndChildrenInactive() - { - angular.forEach(menuModel.menu, function (cat) { - cat.active = false; - angular.forEach(cat.subcategories, function (subcat) { - subcat.active = false; - - if (subcat.isGroup && subcat.subcategories) { - angular.forEach(subcat.subcategories, function (sub) { - sub.active = false; - }); - - } - }); - }); - } - - $scope.menuModel = menuModel; - - // highlight the currently hovered subcategory (and category) - function enterSubcategory(category, subcategory, subsubcategory) { - if (!category || !subcategory) { - return; - } - - markAllCategoriesAndChildrenInactive(); - - category.active = true; - subcategory.active = true; - - if (subsubcategory) { - subcategory.name = subsubcategory.name; - subsubcategory.active = true; - } - } - - $scope.showHelp = function (category, subcategory, $event) { - if (( $scope.currentCategory !== category.id - || $scope.currentSubcategory !== subcategory.id ) - && $event - ) { - showSubcategoryHelpOnLoad = { category: category, subcategory: subcategory }; - window.location.href = '#?' + $scope.makeUrl(category, subcategory); - return; - } - - var UI = require('piwik/UI'); - var notification = new UI.Notification(); - - if (subcategory === $scope.helpShownCategory) { - notification.remove('reportingmenu-help'); - $scope.helpShownCategory = null; - return; - } - - var prefix = '<strong>' + _pk_translate('CoreHome_ReportingCategoryHelpPrefix', [category.name, subcategory.name]) + '</strong><br/>'; - - var options = { context: 'info', id: 'reportingmenu-help', type: 'transient', noclear: true }; - options['class'] = 'help-notification'; - - notification.show(prefix + subcategory.help, options); - $scope.helpShownCategory = subcategory; - - // move help notification so it is always the first one shown - $('[notification-id=reportingmenu-help]').prependTo($('#notificationContainer')); - }; - - $scope.isNotificationShown = function () { - return !! $('#reportingmenu-help').length; - }; - - $scope.makeUrl = function (category, subcategory) { - var params = { - idSite: idSite, - period: period, - date: decodeURIComponent(date), - segment: decodeURIComponent(segment), - category: category.id, - subcategory: subcategory.id, - }; - - if (compareDates) { - params.compareDates = compareDates; - } - - if (comparePeriods) { - params.comparePeriods = comparePeriods; - } - - if (compareSegments) { - params.compareSegments = compareSegments; - } - - return $.param(params) - // some browsers treat URLs w/ date=a,b differently from date=a%2Cb, causing multiple - // entries to show up in the browser history. this has a compounding effect w/ angular.js, - // which when the back button is pressed to effectively abort the back navigation. - .replace(/%2C/g, ','); - }; - - $scope.loadCategory = function (category) { - var UI = require('piwik/UI'); - UI.Notification.prototype.remove('reportingmenu-help'); - - if (category.active) { - category.active = false; - } else { - markAllCategoriesAsInactive(); - category.active = true; - } - - if (category.active && category.subcategories && category.subcategories.length === 1) { - $scope.helpShownCategory = null; - - var subcategory = category.subcategories[0]; - - if (subcategory.active) { - // we need to manually trigger change as URL would not change and therefore page would not be - // reloaded - $scope.loadSubcategory(category, subcategory); - } else { - var url = $scope.makeUrl(category, subcategory); - $location.search(url); - } - } - }; - - $scope.loadSubcategory = function (category, subcategory) { - var UI = require('piwik/UI'); - UI.Notification.prototype.remove('reportingmenu-help'); - - if (subcategory && subcategory.active) { - $scope.helpShownCategory = null; - - // this menu item is already active, a location change success would not be triggered, - // instead trigger an event - $rootScope.$emit('loadPage', category.id, subcategory.id); - } - }; - - menuModel.fetchMenuItems().then(function (menu) { - if (!$location.search().subcategory) { - // load first, initial page if no subcategory is present - enterSubcategory(menu[0], menu[0].subcategories[0]); - $location.search($scope.makeUrl(menu[0], menu[0].subcategories[0])); - } - }); - - $rootScope.$on('updateReportingMenu', function () { - menuModel.reloadMenuItems().then(function (menu) { - var $search = $location.search(); - var category = $search.category; - var subcategory = $search.subcategory; - // we need to make sure to select same categories again - if (category && subcategory) { - var found = menuModel.findSubcategory(category, subcategory); - if (found) { - enterSubcategory(found.category, found.subcategory, found.subsubcategory); - } - } - }); - if ('object' === typeof widgetsHelper && widgetsHelper.availableWidgets) { - // lets also update widgetslist so will be easier to update list of available widgets in dashboard selector - // immediately - delete widgetsHelper.availableWidgets; - widgetsHelper.getAvailableWidgets(); - } - }); - - $rootScope.$on('$locationChangeSuccess', function () { - var $search = $location.search(); - var category = $search.category; - var subcategory = $search.subcategory; - - period = piwikUrl.getSearchParam('period'); - date = piwikUrl.getSearchParam('date'); - segment = piwikUrl.getSearchParam('segment'); - - comparePeriods = piwikUrl.getSearchParam('comparePeriods'); - compareDates = piwikUrl.getSearchParam('compareDates'); - compareSegments = piwikUrl.getSearchParam('compareSegments'); - - if (!category || !subcategory) { - return; - } - - var found = menuModel.findSubcategory(category, subcategory); - enterSubcategory(found.category, found.subcategory, found.subsubcategory); - }); - - $rootScope.$on('piwikPageChange', function (event) { - if (!initialLoad) { - globalAjaxQueue.abort(); - } - - $scope.helpShownCategory = null; - $scope.currentCategory = piwikUrl.getSearchParam('category'); - $scope.currentSubcategory = piwikUrl.getSearchParam('subcategory'); - - if (showSubcategoryHelpOnLoad) { - $scope.showHelp(showSubcategoryHelpOnLoad.category, showSubcategoryHelpOnLoad.subcategory); - showSubcategoryHelpOnLoad = null; - } - - $('#loadingError').hide(); - - initialLoad = false; - }); - } -})(); diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html deleted file mode 100644 index ff3a549061..0000000000 --- a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html +++ /dev/null @@ -1,72 +0,0 @@ -<div class="reportingMenu"><ul class="navbar hide-on-med-and-down" role="menu" aria-label="{{ 'CoreHome_MainNavigation'|translate }}"> - <li ng-repeat="category in menuModel.menu" - class="menuTab" - role="menuitem" - ng-class="{'active': category.active}"> - <a class="item" tabindex="5" - href="" - ng-click="loadCategory(category)"> - <span class="menu-icon {{ category.icon ? category.icon : 'icon-arrow-right' }}"></span>{{ category.name }} - <span class="hidden"> - {{ 'CoreHome_Menu'|translate }} - </span> - </a> - - <ul role="menu"> - <li ng-repeat="subcategory in category.subcategories" - role="menuitem" - ng-class="{'active': subcategory.active}"> - <div ng-if="subcategory.isGroup" piwik-menudropdown show-search="true" menu-title="{{ subcategory.name|escape }}"> - <a class="item" tabindex="5" - ng-repeat="subcat in subcategory.subcategories" - title="{{ subcat.tooltip }}" - ng-class="{'active': subcat.active}" - ng-href="#?{{ makeUrl(category,subcat) }}" - ng-click='loadSubcategory(category, subcat)'> - {{ subcat.name }} - </a> - </div> - - <a ng-if="!subcategory.isGroup" - ng-href="#?{{ makeUrl(category,subcategory) }}" - class="item" - ng-click='loadSubcategory(category, subcategory)'> - {{ subcategory.name }} - </a> - - <a class="item-help-icon" - tabindex="5" href="javascript:" - ng-if="subcategory.help" - ng-click="showHelp(category, subcategory, $event)" - ng-class="{'active': helpShownCategory == subcategory && subcategory.help}" - > - <span class="icon-help"></span> - </a> - </li> - </ul> - </li> -</ul> -<ul id="mobile-left-menu" class="sidenav hide-on-large-only"> - <li class="no-padding" ng-repeat="category in menuModel.menu"> - <ul class="collapsible collapsible-accordion" piwik-side-nav="nav .activateLeftMenu"> - <li> - <a class="collapsible-header"><i class="{{ category.icon ? category.icon : 'icon-arrow-bottom' }}"></i>{{ category.name }}</a> - <div class="collapsible-body"> - <ul> - <li ng-repeat="subcategory in category.subcategories"> - <a ng-if="subcategory.isGroup" - ng-repeat="subcat in subcategory.subcategories" - ng-click='loadSubcategory(category, subcat)' - ng-href="#?{{ makeUrl(category,subcat) }}">{{ subcat.name }}</a> - <a ng-if="!subcategory.isGroup" - ng-click='loadSubcategory(category, subcategory)' - ng-href="#?{{ makeUrl(category,subcategory) }}">{{ subcategory.name }}</a> - </li> - </ul> - </div> - </li> - </ul> - </li> -</ul> - -</div> diff --git a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js b/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js deleted file mode 100644 index 1f037e8b8c..0000000000 --- a/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.js +++ /dev/null @@ -1,32 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Shows the Piwik reporting menu. - * - * It automatically calls the API to fetch all data. - * - * Example: - * <div piwik-reporting-menu></div> - */ - -(function () { - angular.module('piwikApp').directive('piwikReportingMenu', piwikReportingMenu); - - piwikReportingMenu.$inject = ['piwik']; - - function piwikReportingMenu(piwik){ - - return { - restrict: 'A', - replace: true, - scope: {}, - templateUrl: 'plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html?cb=' + piwik.cacheBuster, - controller: 'ReportingMenuController' - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js b/plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js deleted file mode 100644 index 45228eacc2..0000000000 --- a/plugins/CoreHome/angularjs/reporting-page/reportingpage-model.js +++ /dev/null @@ -1,194 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').factory('reportingPageModel', reportingPageModelService); - - reportingPageModelService.$inject = ['$filter', 'reportingPagesModel', 'reportMetadataModel']; - - function reportingPageModelService ($filter, reportingPagesModel, reportMetadataModel) { - var init = false; - - // those sites are going to be displayed - var model = { - fetchPage: fetchPage, - resetPage: resetPage, - widgets: [], - page: null, - pageContentUrl: '', - evolutionReports: [], - sparklineReports: [] - }; - - return model; - - function resetPage() - { - model.page = null; - model.widgets = []; - model.pageContentUrl = ''; - model.evolutionReports = []; - model.sparklineReports = []; - } - - function sortWidgets(widgets) - { - return $filter('orderBy')(widgets, 'order'); - } - - function shouldBeRenderedWithFullWidth(widget) - { - // rather controller logic - if ((widget.isContainer && widget.layout && widget.layout === 'ByDimension') - || widget.viewDataTable === 'bydimension') { - return true; - } - - if ('undefined' !== typeof widget.isWide && widget.isWide) { - return true; - } - - return widget.viewDataTable && (widget.viewDataTable === 'tableAllColumns' || widget.viewDataTable === 'sparklines' || widget.viewDataTable === 'graphEvolution'); - } - - function buildPage(page) - { - if (!page) { - return; - } - - var widgets = []; - var evolutionReports = []; - var sparklineReports = []; - var reportsToIgnore = []; - - angular.forEach(page.widgets, function (widget) { - - if (isIgnoredReport(reportsToIgnore, widget)) { - return; - } - - reportsToIgnore = reportsToIgnore.concat(getRelatedReports(widget)); - - widgets.push(widget); - }); - - widgets = sortWidgets(widgets); - - var groupedWidgets = []; - - if (widgets.length === 1) { - // if there is only one widget, we always display it full width - groupedWidgets = widgets; - } else { - for (var i = 0; i < widgets.length; i++) { - var widget = widgets[i]; - - if (shouldBeRenderedWithFullWidth(widget) || (widgets[i+1] && shouldBeRenderedWithFullWidth(widgets[i+1]))) { - widget.widgets = sortWidgets(widget.widgets); - - groupedWidgets.push(widget); - } else { - - var counter = 0; - var left = [widget]; - var right = []; - - while (widgets[i+1] && !shouldBeRenderedWithFullWidth(widgets[i+1])) { - i++; - counter++; - if (counter % 2 === 0) { - left.push(widgets[i]); - } else { - right.push(widgets[i]); - } - } - - groupedWidgets.push({group: true, left: left, right: right}); - } - } - } - - var copyWidgets = angular.copy(groupedWidgets); - var copyEvolution = angular.copy(evolutionReports); - var copySparklines = angular.copy(sparklineReports); - - if (copyEvolution.length) { - copyEvolution = markWidgetsInFirstRowOfPage(copyEvolution); - } else if (copySparklines.length) { - copySparklines = markWidgetsInFirstRowOfPage(copySparklines); - } else { - copyWidgets = markWidgetsInFirstRowOfPage(copyWidgets); - } - - // angular.copy forces the page to re-render. Otherwise it won't reload some pages - model.evolutionReports = copyEvolution; - model.sparklineReports = copySparklines; - model.widgets = copyWidgets; - } - - function markWidgetsInFirstRowOfPage(widgets) - { - if (widgets && widgets[0]) { - if (widgets[0].group) { - markWidgetsInFirstRowOfPage(widgets[0].left); - markWidgetsInFirstRowOfPage(widgets[0].right); - } else { - widgets[0].isFirstInPage = true; - } - } - - return widgets; - } - - function getRelatedReports(widget) - { - if (widget.isReport) { - var report = reportMetadataModel.findReport(widget.module, widget.action); - - if (report && report.relatedReports) { - return report.relatedReports; - } - } - - return []; - } - - function isIgnoredReport(reportsToIgnore, widget) - { - var found = false; - - if (widget.isReport) { - angular.forEach(reportsToIgnore, function (report) { - if (report.module === widget.module && - report.action === widget.action) { - found = true; - } - }); - } - - return found; - } - - function fetchPage(category, subcategory) - { - resetPage(); - - var pagesPromise = reportingPagesModel.getAllPages(); - var reportsPromise = reportMetadataModel.fetchReportMetadata(); - - return pagesPromise.then(function () { - model.page = reportingPagesModel.findPage(category, subcategory); - - reportsPromise.then(function () { - buildPage(model.page); - }); - - return model.page; - }); - } - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js b/plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js deleted file mode 100644 index d23590babe..0000000000 --- a/plugins/CoreHome/angularjs/reporting-page/reportingpage.controller.js +++ /dev/null @@ -1,245 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').controller('ReportingPageController', ReportingPageController); - - ReportingPageController.$inject = ['$scope', 'piwik', '$rootScope', '$location', 'reportingPageModel', 'reportingPagesModel', 'notifications', 'piwikUrl', 'piwikPeriods', 'piwikApi']; - - function ReportingPageController($scope, piwik, $rootScope, $location, pageModel, pagesModel, notifications, piwikUrl, $piwikPeriods, piwikApi) { - pageModel.resetPage(); - $scope.pageModel = pageModel; - - var currentCategory = null; - var currentSubcategory = null; - var currentPeriod = null; - var currentDate = null; - var currentSegment = null; - - var currentCompareDates = null; - var currentComparePeriods = null; - var currentCompareSegments = null; - - var hasRawData = false; - var hasNoVisits = false; - var dateLastChecked = null; - - var UI = require('piwik/UI'); - var notification = new UI.Notification(); - - function renderInitialPage() - { - var $search = $location.search(); - currentPeriod = piwikUrl.getSearchParam('period'); - currentDate = piwikUrl.getSearchParam('date'); - currentSegment = $search.segment; - currentCompareSegments = piwikUrl.getSearchParam('compareSegments'); - currentCompareDates = piwikUrl.getSearchParam('compareDates'); - currentComparePeriods = piwikUrl.getSearchParam('comparePeriods'); - $scope.renderPage($search.category, $search.subcategory); - } - - function showOnlyRawDataNotification() { - var attributes = {}; - attributes.id = 'onlyRawData'; - attributes.animate = false; - attributes.context = 'info'; - var url = broadcast.buildReportingUrl('category=General_Visitors&subcategory=Live_VisitorLog') - var message = _pk_translate('CoreHome_PeriodHasOnlyRawData', ['<a href="' + url + '">', '</a>']); - notification.show(message, attributes); - } - - function hideOnlyRawDataNoticifation() { - notification.remove('onlyRawData'); - } - - function showOnlyRawDataMessageIfRequired() { - if (hasRawData && hasNoVisits) { - showOnlyRawDataNotification(); - } - - var $search = $location.search(); - - if ($search.segment !== '') { - hideOnlyRawDataNoticifation(); - return; - } - - var subcategoryExceptions = [ - 'Live_VisitorLog', - 'General_RealTime', - 'UserCountryMap_RealTimeMap', - 'MediaAnalytics_TypeAudienceLog', - 'MediaAnalytics_TypeRealTime', - 'FormAnalytics_TypeRealTime', - 'Goals_AddNewGoal', - ]; - - var categoryExceptions = [ - 'HeatmapSessionRecording_Heatmaps', - 'HeatmapSessionRecording_SessionRecordings', - 'Marketplace_Marketplace', - ]; - - if (subcategoryExceptions.indexOf($search.subcategory) !== -1 || categoryExceptions.indexOf($search.category) !== -1 || $search.subcategory.toLowerCase().indexOf('manage') !== -1) { - hideOnlyRawDataNoticifation(); - return; - } - - var minuteInMilliseconds = 60000; - if (dateLastChecked && (new Date().getTime() - dateLastChecked) < minuteInMilliseconds) { - return; - } - - piwikApi.fetch({ method: 'VisitsSummary.getVisits' }).then(function (json) { - dateLastChecked = new Date().getTime(); - - if (json.value > 0) { - hasNoVisits = false; - hideOnlyRawDataNoticifation(); - return; - } - - hasNoVisits = true; - - if (hasRawData) { - showOnlyRawDataNotification(); - return; - } - - piwikApi.fetch({ method: 'Live.getLastVisitsDetails', filter_limit: 1, doNotFetchActions: 1 }).then(function (json) { - if (json.length == 0) { - hasRawData = false; - hideOnlyRawDataNoticifation(); - return; - } - - hasRawData = true; - showOnlyRawDataNotification(); - }); - }); - } - - $scope.renderPage = function (category, subcategory) { - if (!category || !subcategory) { - pageModel.resetPage(); - $scope.loading = false; - return; - } - - try { - $piwikPeriods.parse(currentPeriod, currentDate); - } catch (e) { - var attributes = {}; - attributes.id = 'invalidDate'; - attributes.animate = false; - attributes.context = 'error'; - notification.show(_pk_translate('CoreHome_DateInvalid'), attributes); - - pageModel.resetPage(); - $scope.loading = false; - return; - } - - notification.remove('invalidDate'); - - $rootScope.$emit('piwikPageChange', {}); - - currentCategory = category; - currentSubcategory = subcategory; - - notifications.clearTransientNotifications(); - - if ($piwikPeriods.parse(currentPeriod, currentDate).containsToday()) { - showOnlyRawDataMessageIfRequired(); - } - - if (category === 'Dashboard_Dashboard' && $.isNumeric(subcategory) && $('[piwik-dashboard]').length) { - // hack to make loading of dashboards faster since all the information is already there in the - // piwik-dashboard widget, we can let the piwik-dashboard widget render the page. We need to find - // a proper solution for this. A workaround for now could be an event or something to let other - // components render a specific page. - $scope.loading = true; - var element = $('[piwik-dashboard]'); - var scope = angular.element(element).scope(); - scope.fetchDashboard(parseInt(subcategory, 10)).then(function () { - $scope.loading = false; - }, function () { - $scope.loading = false; - }); - return; - } - - pageModel.fetchPage(category, subcategory).then(function () { - if (!pageModel.page) { - var page = pagesModel.findPageInCategory(category); - if (page && page.subcategory) { - var $search = $location.search(); - $search.subcategory = page.subcategory.id; - $location.search($search); - return; - } - } - - $scope.hasNoPage = !pageModel.page; - $scope.loading = false; - }); - }; - - $scope.loading = true; // we only set loading on initial load - - renderInitialPage(); - - $rootScope.$on('$locationChangeSuccess', function () { - var $search = $location.search(); - - // should be handled by $route - var category = $search.category; - var subcategory = $search.subcategory; - var period = piwikUrl.getSearchParam('period'); - var date = piwikUrl.getSearchParam('date'); - var segment = $search.segment; - - // $location does not handle array parameters properly - var compareSegments = piwikUrl.getSearchParam('compareSegments'); - var compareDates = piwikUrl.getSearchParam('compareDates'); - var comparePeriods = piwikUrl.getSearchParam('comparePeriods'); - - if (category === currentCategory - && subcategory === currentSubcategory - && period === currentPeriod - && date === currentDate - && segment === currentSegment - && JSON.stringify(compareDates) === JSON.stringify(currentCompareDates) - && JSON.stringify(comparePeriods) === JSON.stringify(currentComparePeriods) - && JSON.stringify(compareSegments) === JSON.stringify(currentCompareSegments) - ) { - // this page is already loaded - return; - } - - if (date !== currentDate || period !== currentPeriod) { - hideOnlyRawDataNoticifation(); - dateLastChecked = null; - hasRawData = false; - hasNoVisits = false; - } - - currentPeriod = period; - currentDate = date; - currentSegment = segment; - currentCompareDates = compareDates; - currentComparePeriods = comparePeriods; - currentCompareSegments = compareSegments; - - $scope.renderPage(category, subcategory); - }); - - $rootScope.$on('loadPage', function (event, category, subcategory) { - $scope.renderPage(category, subcategory); - }); - } -})(); diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html b/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html deleted file mode 100644 index 4abf3a27e2..0000000000 --- a/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html +++ /dev/null @@ -1,17 +0,0 @@ -<div class="reporting-page"> - - <div piwik-activity-indicator loading="loading"></div> - - <div ng-show="hasNoPage">{{ 'CoreHome_NoSuchPage'|translate }}</div> - - <div class="row" ng-repeat="widget in pageModel.widgets"> - <div class="col s12 fullWidgetColumn" ng-if="!widget.group" piwik-widget="widget"></div> - - <div ng-if="widget.group" class="col s12 l6 leftWidgetColumn"> - <div ng-repeat="widgetInGroup in widget.left" piwik-widget="widgetInGroup"></div> - </div> - <div ng-if="widget.group" class="col s12 l6 rightWidgetColumn"> - <div ng-repeat="widgetInGroup in widget.right" piwik-widget="widgetInGroup"></div> - </div> - </div> -</div> diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js b/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js deleted file mode 100644 index 375bd071db..0000000000 --- a/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.js +++ /dev/null @@ -1,31 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Shows a piwik reporting page. - * - * The content to be displayed is automatically loaded via API based on the current URL. The URL parameters - * 'category' and 'subcategory' need to be present in the URL in order to see something in the reporting page. - * - * Example: - * <div piwik-reporting-page></div> - */ -(function () { - angular.module('piwikApp').directive('piwikReportingPage', piwikReportingPage); - - piwikReportingPage.$inject = ['piwik']; - - function piwikReportingPage(piwik){ - - return { - restrict: 'A', - scope: {}, - templateUrl: 'plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html?cb=' + piwik.cacheBuster, - controller: 'ReportingPageController' - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.less b/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.less deleted file mode 100644 index 1d9fde17b9..0000000000 --- a/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.less +++ /dev/null @@ -1,24 +0,0 @@ -.reporting-page { - > .row { - margin-bottom: 0; - } - - .fullWidgetColumn { - padding-left: 0; - padding-right: 0; - } - - .leftWidgetColumn { - padding-left: 0; - } - - .rightWidgetColumn { - padding-right: 0; - } - - .isFirstWidgetInPage { - .card { - margin-top: 0; - } - } -}
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js b/plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js deleted file mode 100644 index 19cc732af5..0000000000 --- a/plugins/CoreHome/angularjs/siteselector/siteselector-model.service.js +++ /dev/null @@ -1,137 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').factory('siteSelectorModel', siteSelectorModel); - - siteSelectorModel.$inject = ['piwikApi', '$filter', 'piwik', '$q']; - - function siteSelectorModel(piwikApi, $filter, piwik, $q) { - - var initialSites = null; - var limitPromise = null; - - var model = { - sites : [], - hasMultipleWebsites : false, - isLoading : false, - firstSiteName : '', - onlySitesWithAdminAccess: false, - updateWebsitesList: updateWebsitesList, - searchSite: searchSite, - loadSite: loadSite, - loadInitialSites: loadInitialSites, - hasMultipleSites: hasMultipleSites - }; - - return model; - - function updateWebsitesList(sites) { - - if (!sites || !sites.length) { - model.sites = []; - return []; - } - - angular.forEach(sites, function (site) { - if (site.group) site.name = '[' + site.group + '] ' + site.name; - }); - - model.sites = sortSites(sites); - - if (!model.firstSiteName) { - model.firstSiteName = model.sites[0].name; - } - - model.hasMultipleWebsites = model.hasMultipleWebsites || sites.length > 1; - - return model.sites; - } - - function searchSite(term) { - - if (!term) { - loadInitialSites(); - return; - } - - if (model.isLoading) { - if (model.currentRequest) { - model.currentRequest.abort(); - } else if (limitPromise) { - limitPromise.abort(); - limitPromise = null; - } - } - - model.isLoading = true; - - if (!limitPromise) { - limitPromise = piwikApi.fetch({method: 'SitesManager.getNumWebsitesToDisplayPerPage'}); - } - - return limitPromise.then(function (response) { - var limit = response.value; - - var methodToCall = 'SitesManager.getPatternMatchSites'; - if (model.onlySitesWithAdminAccess) { - methodToCall = 'SitesManager.getSitesWithAdminAccess'; - } - - model.currentRequest = piwikApi.fetch({ - method: methodToCall, - limit: limit, - pattern: term - }); - - return model.currentRequest; - }).then(function (response) { - if (angular.isDefined(response)) { - return updateWebsitesList(response); - } - }).finally(function () { - model.isLoading = false; - model.currentRequest = null; - }); - } - - function loadSite(idsite) { - if (idsite == 'all') { - document.location.href = piwikHelper.getCurrentQueryStringWithParametersModified(piwikHelper.getQueryStringFromParameters({ - module: 'MultiSites', - action: 'index', - date: piwik.currentDateString, - period: piwik.period - })); - } else { - piwik.broadcast.propagateNewPage('segment=&idSite=' + idsite, false); - } - } - - function sortSites(websites) - { - return $filter('orderBy')(websites, '+name'); - } - - function loadInitialSites() { - if (initialSites) { - model.sites = initialSites; - var deferred = $q.defer(); - deferred.resolve(); - return deferred.promise; - } - - return searchSite('%').then(function () { - initialSites = model.sites; - model.isInitialized = true - }); - } - - function hasMultipleSites() { - return initialSites && initialSites.length > 1; - } - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector.controller.js b/plugins/CoreHome/angularjs/siteselector/siteselector.controller.js deleted file mode 100644 index 8c5760a295..0000000000 --- a/plugins/CoreHome/angularjs/siteselector/siteselector.controller.js +++ /dev/null @@ -1,69 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -(function () { - angular.module('piwikApp').controller('SiteSelectorController', SiteSelectorController); - - SiteSelectorController.$inject = ['$scope', 'siteSelectorModel', 'piwik', 'AUTOCOMPLETE_MIN_SITES']; - - function SiteSelectorController($scope, siteSelectorModel, piwik, AUTOCOMPLETE_MIN_SITES){ - - $scope.model = siteSelectorModel; - - $scope.model.loadInitialSites().then(function(){ - if (!$scope.selectedSite && !$scope.model.hasMultipleSites() && $scope.model.sites[0]) { - $scope.selectedSite = {id: $scope.model.sites[0].idsite, name: $scope.model.sites[0].name}; - } - }); - - $scope.autocompleteMinSites = AUTOCOMPLETE_MIN_SITES; - $scope.activeSiteId = piwik.idSite; - - $scope.switchSite = function (site, $event) { - - // for Mac OS cmd key needs to be pressed, ctrl key on other systems - var controlKey = navigator.userAgent.indexOf("Mac OS X") !== -1 ? $event.metaKey : $event.ctrlKey; - - if ($event && controlKey && $event.target && $event.target.href) { - window.open($event.target.href, "_blank"); - return; - } - - $scope.selectedSite = {id: site.idsite, name: site.name}; - - if (!$scope.switchSiteOnSelect || $scope.activeSiteId == site.idsite) { - return; - } - - $scope.model.loadSite(site.idsite); - }; - - $scope.getUrlAllSites = function () { - var newParameters = 'module=MultiSites&action=index'; - return piwik.helper.getCurrentQueryStringWithParametersModified(newParameters); - }; - $scope.getUrlForSiteId = function (idSite) { - var idSiteParam = 'idSite=' + idSite; - var newParameters = 'segment=&' + idSiteParam; - var hash = piwik.broadcast.isHashExists() ? piwik.broadcast.getHashFromUrl() : ""; - return piwik.helper.getCurrentQueryStringWithParametersModified(newParameters) + - '#' + piwik.helper.getQueryStringWithParametersModified(hash.substring(1), newParameters); - }; - - piwikHelper.registerShortcut('w', _pk_translate('CoreHome_ShortcutWebsiteSelector'), function(event) { - if (event.altKey) { - return; - } - if (event.preventDefault) { - event.preventDefault(); - } else { - event.returnValue = false; // IE - } - $('.siteSelector .title').trigger('click').focus(); - }); - } - -})(); diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector.directive.html b/plugins/CoreHome/angularjs/siteselector/siteselector.directive.html deleted file mode 100644 index 8954b20426..0000000000 --- a/plugins/CoreHome/angularjs/siteselector/siteselector.directive.html +++ /dev/null @@ -1,73 +0,0 @@ -<div piwik-focus-anywhere-but-here="view.showSitesList=false" - class="siteSelector piwikSelector borderedControl" - ng-class="{'expanded': view.showSitesList, 'disabled': !model.hasMultipleSites()}"> - - <script type="text/ng-template" id="siteselector_allsiteslink.html"> - <div ng-click="switchSite({idsite: 'all', name: allSitesText}, $event);view.showSitesList=false;" - class="custom_select_all"> - <a href="{{ getUrlAllSites() }}" - piwik-ignore-click - ng-bind-html="allSitesText" tabindex="4"></a> - </div> - </script> - - <input ng-if="inputName" type="hidden" name="{{ inputName }}" ng-value="selectedSite.id"/> - - <a ng-click="model.hasMultipleSites() && (view.showSitesList=!view.showSitesList) && !model.isLoading && model.loadInitialSites();" - piwik-onenter="view.showSitesList=!view.showSitesList; view.showSitesList && !model.isLoading && model.loadInitialSites();" - href="javascript:void(0)" - ng-attr-title="{{ model.hasMultipleSites() ? _pk_translate('CoreHome_ChangeCurrentWebsite', (selectedSite.name || model.firstSiteName)) : '' }}" - ng-class="{'loading': model.isLoading}" - class="title" tabindex="4"> - <span class="icon icon-arrow-bottom" - ng-class="{'iconHidden': model.isLoading, 'collapsed': !view.showSitesList}"></span> - <span> - <span ng-bind="selectedSite.name || model.firstSiteName" ng-if="selectedSite.name || !placeholder">?</span> - <span ng-if="!selectedSite.name && placeholder" class="placeholder">{{ placeholder }}</span> - </span> - </a> - - <div ng-show="view.showSitesList" class="dropdown"> - - <div class="custom_select_search" ng-show="autocompleteMinSites <= model.sites.length || view.searchTerm"> - <input type="text" - piwik-focus-if="view.showSitesList && (autocompleteMinSites <= model.sites.length || view.searchTerm)" - ng-click="view.searchTerm=''" - ng-model="view.searchTerm" - ng-change="model.searchSite(view.searchTerm)" - placeholder="{{ 'General_Search' | translate }}" - tabindex="4" - class="websiteSearch inp browser-default"/> - <img title="Clear" - ng-show="view.searchTerm" - ng-click="view.searchTerm=''; model.loadInitialSites()" - class="reset" - src="plugins/CoreHome/images/reset_search.png"/> - </div> - - <div ng-if="allSitesLocation=='top' && showAllSitesItem" - ng-include="'siteselector_allsiteslink.html'"></div> - - <div class="custom_select_container"> - <ul class="custom_select_ul_list" ng-click="view.showSitesList=false;"> - <li ng-click="switchSite(site, $event)" - ng-repeat="site in model.sites" - ng-hide="!showSelectedSite && activeSiteId==site.idsite"> - <a piwik-ignore-click href="{{ getUrlForSiteId(site.idsite) }}" - piwik-autocomplete-matched="view.searchTerm" - title="{{ site.name }}" - ng-bind="site.name" tabindex="4"></a> - </li> - </ul> - <ul ng-show="!model.sites.length && view.searchTerm" class="ui-autocomplete ui-front ui-menu ui-widget ui-widget-content ui-corner-all siteSelect"> - <li class="ui-menu-item"> - <a class="ui-corner-all" tabindex="-1">{{ ('SitesManager_NotFound' | translate) + ' ' + view.searchTerm }}</a> - </li> - </ul> - </div> - - <div ng-if="allSitesLocation=='bottom' && showAllSitesItem" - ng-include="'siteselector_allsiteslink.html'"></div> - - </div> -</div> diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector.directive.js b/plugins/CoreHome/angularjs/siteselector/siteselector.directive.js deleted file mode 100644 index 945b70c145..0000000000 --- a/plugins/CoreHome/angularjs/siteselector/siteselector.directive.js +++ /dev/null @@ -1,112 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Usage: - * <div piwik-siteselector> - * - * More advanced example - * <div piwik-siteselector - * show-selected-site="true" show-all-sites-item="true" switch-site-on-select="true" - * all-sites-location="top|bottom" all-sites-text="test" show-selected-site="true" - * show-all-sites-item="true" only-sites-with-admin-access="true"> - * - * Within a form - * <div piwik-siteselector input-name="siteId"> - * - * Events: - * Triggers a `change` event on any change - * <div piwik-siteselector id="mySelector"> - * $('#mySelector').on('change', function (event) { event.id/event.name }) - */ -(function () { - angular.module('piwikApp').directive('piwikSiteselector', piwikSiteselector); - - piwikSiteselector.$inject = ['$document', 'piwik', '$filter', '$timeout']; - - function piwikSiteselector($document, piwik, $filter, $timeout){ - var defaults = { - name: '', - siteid: piwik.idSite, - sitename: piwik.helper.htmlDecode(piwik.siteName), - allSitesLocation: 'bottom', - allSitesText: $filter('translate')('General_MultiSitesSummary'), - showSelectedSite: 'false', - showAllSitesItem: 'true', - switchSiteOnSelect: 'true', - onlySitesWithAdminAccess: 'false' - }; - - return { - restrict: 'A', - scope: { - showSelectedSite: '=', - showAllSitesItem: '=', - switchSiteOnSelect: '=', - onlySitesWithAdminAccess: '=', - inputName: '@name', - allSitesText: '@', - allSitesLocation: '@', - placeholder: '@' - }, - require: "?ngModel", - templateUrl: 'plugins/CoreHome/angularjs/siteselector/siteselector.directive.html?cb=' + piwik.cacheBuster, - controller: 'SiteSelectorController', - compile: function (element, attrs) { - - for (var index in defaults) { - if (attrs[index] === undefined) { - attrs[index] = defaults[index]; - } - } - - return function (scope, element, attrs, ngModel) { - scope.model.onlySitesWithAdminAccess = scope.onlySitesWithAdminAccess; - - if (ngModel) { - ngModel.$setViewValue(scope.selectedSite); - } - - scope.$watch('selectedSite.id', function (newValue, oldValue, scope) { - if (newValue != oldValue) { - element.attr('siteid', newValue); - element.trigger('change', scope.selectedSite); - } - }); - - if (ngModel) { - ngModel.$render = function() { - if (angular.isString(ngModel.$viewValue)) { - scope.selectedSite = JSON.parse(ngModel.$viewValue); - } else { - scope.selectedSite = ngModel.$viewValue; - } - }; - } - - scope.$watch('selectedSite', function (newValue) { - if (ngModel) { - ngModel.$setViewValue(newValue); - } - }); - - scope.$watch('view.showSitesList', function (newValue) { - element.toggleClass('expanded', !! newValue); - }); - - $timeout(function () { - if (attrs.siteid && attrs.sitename) { - scope.selectedSite = {id: attrs.siteid, name: piwik.helper.htmlDecode(attrs.sitename)}; - } - - initTopControls(); - }); - }; - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/sparkline/sparkline.component.js b/plugins/CoreHome/angularjs/sparkline/sparkline.component.js deleted file mode 100644 index 91b70bd3a0..0000000000 --- a/plugins/CoreHome/angularjs/sparkline/sparkline.component.js +++ /dev/null @@ -1,87 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Displays a sparkline. 'module', 'action' and 'date' are required elements of the - * params attribute. - * - * Usage: - * <piwik-sparkline params="{'module': 'API', 'action': 'get', 'date': '...'}"></piwik-sparkline> - */ -(function () { - angular.module('piwikApp').component('piwikSparkline', { - template: '<img />', - bindings: { - seriesIndices: '<', - params: '<' - }, - controller: SparklineController - }); - - SparklineController.$inject = ['$element', '$httpParamSerializer', 'piwikApi', 'piwik', 'piwikPeriods']; - - function SparklineController($element, $httpParamSerializer, piwikApi, piwik, piwikPeriods) { - var vm = this; - vm.$onChanges = $onChanges; - - function $onChanges() { - // done manually due to 'random' query param. since it changes the URL on each digest, depending on angular - // results in an infinite digest - $element.find('img').attr('src', getSparklineUrl()); - } - - function getSparklineUrl() { - var seriesIndices = vm.seriesIndices; - var sparklineColors = piwik.getSparklineColors(); - - if (seriesIndices) { - sparklineColors.lineColor = sparklineColors.lineColor.filter(function (c, index) { - return seriesIndices.indexOf(index) !== -1; - }); - } - - var colors = JSON.stringify(sparklineColors); - - var defaultParams = { - forceView: '1', - viewDataTable: 'sparkline', - widget: $element.closest('[widgetId]').length ? '1' : '0', - showtitle: '1', - colors: colors, - random: Date.now(), - date: getDefaultDate() - }; - - var urlParams = piwikApi.mixinDefaultGetParams($element.extend(defaultParams, vm.params)); - - // Append the token_auth to the URL if it was set (eg. embed dashboard) - var token_auth = piwik.broadcast.getValueFromUrl("token_auth"); - if (token_auth.length && piwik.shouldPropagateTokenAuth) { - urlParams.token_auth = token_auth; - } - - return '?' + $httpParamSerializer(urlParams); - } - - function getDefaultDate() { - if (piwik.period === 'range') { - return piwik.startDateString + ',' + piwik.endDateString; - } - - var dateRange = piwikPeriods.get('range').getLastNRange(piwik.period, 30, piwik.currentDateString).getDateRange(); - - var piwikMinDate = new Date(piwik.minDateYear, piwik.minDateMonth - 1, piwik.minDateDay); - if (dateRange[0] < piwikMinDate) { - dateRange[0] = piwikMinDate; - } - - var startDateStr = piwikPeriods.format(dateRange[0]); - var endDateStr = piwikPeriods.format(dateRange[1]); - return startDateStr + ',' + endDateStr; - } - } -})(); diff --git a/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html b/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html deleted file mode 100644 index 502cdaf723..0000000000 --- a/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html +++ /dev/null @@ -1,23 +0,0 @@ -<div class="reportsByDimensionView"> - - <div class="entityList"> - <div class='dimensionCategory' ng-repeat="category in widgetsByCategory"> - {{ category.name }} - <ul class='listCircle'> - <li ng-repeat="widget in category.widgets" - class="reportDimension" - ng-class="{activeDimension: (selectedWidget.uniqueId===widget.uniqueId)}" - ng-click="selectWidget(widget)"> - <span class='dimension'>{{widget.name}}</span> - </li> - </ul> - </div> - </div> - - <div class="reportContainer"> - <div ng-if="selectedWidget.parameters" class="dimensionReport" - piwik-widget-loader="selectedWidget.parameters"></div> - </div> - <div class="clear"></div> - -</div>
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js b/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js deleted file mode 100644 index 0219b4795e..0000000000 --- a/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.js +++ /dev/null @@ -1,67 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Renders a widget that is a container widget having the layout "ByDimension". - * - * The "ByDimension" layout shows a menu on the left letting you choose any widgets within this container. The - * currently selected widget is shown on the right. - * - * @param {Object} piwikWidgetByDimensionContainer a widget object as returned by the WidgetMetadata API. - * - * Example: - * <div piwik-widget-by-dimension-container="containerWidget"></div> - */ -(function () { - angular.module('piwikApp').directive('piwikWidgetByDimensionContainer', piwikWidgetContainer); - - piwikWidgetContainer.$inject = ['piwik', '$filter']; - - function piwikWidgetContainer(piwik, $filter){ - return { - restrict: 'A', - scope: { - container: '=piwikWidgetByDimensionContainer' - }, - templateUrl: 'plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html?cb=' + piwik.cacheBuster, - compile: function (element, attrs) { - - return function (scope, element, attrs, ngModel) { - - var widgetsSorted = $filter('orderBy')(scope.container.widgets, 'order'); - var widgetsByCategory = {}; - - angular.forEach(widgetsSorted, function (widget) { - var category = widget.subcategory.name; - - if (!widgetsByCategory[category]) { - widgetsByCategory[category] = {name: category, order: widget.order, widgets: []}; - } - - widgetsByCategory[category].widgets.push(widget); - }); - - // only an array can be sorted - var finalWidgetsByCategory = []; - angular.forEach(widgetsByCategory, function (category) { - finalWidgetsByCategory.push(category); - }); - - scope.widgetsByCategory = $filter('orderBy')(finalWidgetsByCategory, 'order'); - - scope.selectWidget = function (widget) { - scope.selectedWidget = angular.copy(widget); // we copy to force rerender - }; - - if (widgetsSorted && widgetsSorted.length) { - scope.selectWidget(widgetsSorted[0]); - } - }; - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html b/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html deleted file mode 100644 index 21ebd3d0cd..0000000000 --- a/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html +++ /dev/null @@ -1,10 +0,0 @@ -<div> - <!-- custom template prevents recursion --> - <script id="mywidget.html" type="text/ng-template"> - <div piwik-widget="widget"></div> - </script> - - <div ng-repeat="widget in container.widgets"> - <div ng-include src="'mywidget.html'"/> - </div> -</div>
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js b/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js deleted file mode 100644 index eb0721f3d5..0000000000 --- a/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.js +++ /dev/null @@ -1,48 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Renders a widget that is a container widget having no specific layout (which is the default). - * - * It shows all widgets vertically aligned one widget after another. - * - * @param {Object} piwikWidgetContainer a widget object as returned by the WidgetMetadata API. - * - * Example: - * <div piwik-widget-container="containerWidget"></div> - */ -(function () { - angular.module('piwikApp').directive('piwikWidgetContainer', piwikWidgetContainer); - - piwikWidgetContainer.$inject = ['piwik']; - - function piwikWidgetContainer(piwik){ - return { - restrict: 'A', - scope: { - container: '=piwikWidgetContainer' - }, - templateUrl: 'plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html?cb=' + piwik.cacheBuster, - compile: function (element, attrs) { - - return function (scope, element, attrs, ngModel) { - scope.$watch('container', function (container) { - if (container && container.widgets && container.widgets[0] && container.widgets[0].parameters) { - var widget = container.widgets[0]; - var isWidgetized = widget.parameters.widget == '1'; - - if (isWidgetized && widget.viewDataTable && widget.viewDataTable == 'graphEvolution') { - // we hide the first title for Visits Overview with Graph and Goal Overview - widget.parameters.showtitle = '0'; - } - } - }); - } - } - }; - } -})();
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html b/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html deleted file mode 100644 index c29f0bbbd1..0000000000 --- a/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html +++ /dev/null @@ -1,15 +0,0 @@ -<div> - <div piwik-activity-indicator loading-message="loadingMessage" loading="loading"></div> - - <div ng-show="loadingFailed"> - <h2 ng-if="widgetName">{{widgetName}}</h2> - - <div class="notification system notification-error"> - {{ 'General_ErrorRequest'|translate:(''):('') }} - <ng-bind-html ng-bind-html="errorFaqLink"></ng-bind-html> - </div> - </div> - - <div class="theWidgetContent"></div> - -</div>
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js b/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js deleted file mode 100644 index a9812701bc..0000000000 --- a/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.js +++ /dev/null @@ -1,218 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Loads any custom widget or URL based on the given parameters. - * - * The currently active idSite, period, date and segment (if needed) is automatically appended to the parameters. If - * this widget is removed from the DOM and requests are in progress, these requests will be aborted. A loading message - * or an error message on failure is shown as well. It's kinda similar to ng-include but there it is not possible to - * listen to HTTP errors etc. - * - * Example: - * <div piwik-widget-loader="{module: '', action: '', ...}"></div> - */ -(function () { - angular.module('piwikApp').directive('piwikWidgetLoader', piwikWidgetLoader); - - piwikWidgetLoader.$inject = ['piwik', 'piwikUrl', '$http', '$compile', '$q', '$location', 'notifications', '$rootScope', '$timeout', 'piwikComparisonsService']; - - function piwikWidgetLoader(piwik, piwikUrl, $http, $compile, $q, $location, notifications, $rootScope, $timeout, piwikComparisonsService){ - var isGeneralSettingsAdminEnabled = piwik.config['enable_general_settings_admin']; - var isPluginsAdminEnabled = piwik.config['enable_plugins_admin']; - return { - restrict: 'A', - transclude: true, - scope: { - piwikWidgetLoader: '=', - widgetName: '@', - loadingMessage: '@' - }, - templateUrl: 'plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html?cb=' + piwik.cacheBuster, - compile: function (element, attrs) { - - return function (scope, element, attrs, ngModel) { - scope.widgetName = attrs.widgetName; - if (piwik.hasSuperUserAccess && (isGeneralSettingsAdminEnabled || isPluginsAdminEnabled)) { - scope.errorFaqLink = '<a rel="noreferrer noopener" target="_blank" href="https://matomo.org/faq/troubleshooting/faq_19489/">' + - _pk_translate('General_ErrorRequestFaqLink') + '</a>'; - } else { - scope.errorFaqLink = ''; - } - - if (!attrs.widgetName) { - scope.loadingMessage = _pk_translate('General_LoadingData'); - } else { - scope.loadingMessage = _pk_translate('General_LoadingPopover', [attrs.widgetName]); - } - - var changeCounter = 0, - currentScope, - currentElement, - httpCanceler, - contentNode = element.find('.theWidgetContent'); - - var cleanupLastWidgetContent = function() { - if (currentElement) { - currentElement.remove(); - currentElement = null; - } - if (currentScope) { - currentScope.$destroy(); - currentScope = null; - } - }; - - var abortHttpRequestIfNeeded = function () { - if (httpCanceler) { - httpCanceler.resolve(); - httpCanceler = null; - } - } - - function getFullWidgetUrl(parameters) { - - var url = $.param(parameters); - - var $urlParams = $location.search(); - - delete $urlParams['comparePeriods[]']; - delete $urlParams['compareDates[]']; - delete $urlParams['compareSegments[]']; - - if ($.isEmptyObject($urlParams) || !$urlParams || !$urlParams['idSite']) { - // happens eg in exported widget etc when URL does not have #?... - $urlParams = {idSite: 'idSite', period: 'period',date: 'date'}; - if (piwikUrl.getSearchParam('widget')) { - $urlParams['widget'] = 'widget'; - } - } else { - $urlParams = angular.copy($urlParams); - delete $urlParams['category']; - delete $urlParams['subcategory']; - } - - if (piwikUrl.getSearchParam('segment')) { - $urlParams['segment'] = 'segment'; - } - - angular.forEach($urlParams, function (value, key) { - if (!(key in parameters)) { - url += '&' + key + '=' + piwikUrl.getSearchParam(key); - } - }); - - if (piwikComparisonsService.isComparisonEnabled()) { - ['comparePeriods', 'compareDates', 'compareSegments'].forEach(function (paramName) { - var value = piwikUrl.getSearchParam(paramName); - if (value) { - var map = {}; - map[paramName] = value; - url += '&' + $.param(map); - } - }); - } - - if (!parameters || !('showtitle' in parameters)) { - url += '&showtitle=1'; - } - - if (piwik.shouldPropagateTokenAuth && broadcast.getValueFromUrl('token_auth')) { - if (!piwik.broadcast.isWidgetizeRequestWithoutSession()) { - url += '&force_api_session=1'; - } - url += '&token_auth=' + encodeURIComponent(broadcast.getValueFromUrl('token_auth')); - } - - url += '&random=' + parseInt(Math.random() * 10000); - - return '?' + url; - } - - function loadWidgetUrl(parameters, thisChangeId) - { - scope.loading = true; - - var url = getFullWidgetUrl(parameters); - - abortHttpRequestIfNeeded(); - cleanupLastWidgetContent(); - - httpCanceler = $q.defer(); - - $http.get(url, {timeout: httpCanceler.promise, headers: {'X-Requested-With': 'XMLHttpRequest'}}).then(function(response) { - if (thisChangeId !== changeCounter || !response.data) { - // another widget was requested meanwhile, ignore this response - return; - } - - httpCanceler = null; - - var newScope = scope.$new(); - currentScope = newScope; - - scope.loading = false; - scope.loadingFailed = false; - - currentElement = contentNode.html(response.data).children(); - - if (scope.widgetName) { - // we need to respect the widget title, which overwrites a possibly set report title - var $title = currentElement.find('> .card-content .card-title'); - if (!$title.length) { - $title = currentElement.find('> h2'); - } - - if ($title.length) { - $title.html(piwik.helper.htmlEntities(scope.widgetName)); - } - } - - $compile(currentElement)(newScope); - - notifications.parseNotificationDivs(); - - $timeout(function () { - $rootScope.$emit('widget:loaded', { - parameters: parameters, - element: currentElement, - }); - }); - })['catch'](function (response) { - if (thisChangeId !== changeCounter) { - // another widget was requested meanwhile, ignore this response - return; - } - - httpCanceler = null; - - cleanupLastWidgetContent(); - - scope.loading = false; - - if (response.xhrStatus === 'abort') { - return; - }; - - scope.loadingFailed = true; - }); - } - - scope.$watch('piwikWidgetLoader', function (parameters, oldUrl) { - if (parameters) { - loadWidgetUrl(parameters, ++changeCounter); - } - }); - - element.on('$destroy', function() { - abortHttpRequestIfNeeded(); - }); - }; - } - }; - } -})(); diff --git a/plugins/CoreHome/angularjs/widget/widget.directive.html b/plugins/CoreHome/angularjs/widget/widget.directive.html deleted file mode 100644 index f0e9c48626..0000000000 --- a/plugins/CoreHome/angularjs/widget/widget.directive.html +++ /dev/null @@ -1,15 +0,0 @@ -<div id="{{ widget.uniqueId }}" - ng-show="view.showWidget" - ng-class="{'isFirstWidgetInPage': widget.isFirstInPage}"> - - <div ng-if="!widget.isContainer && widget.parameters" - piwik-widget-loader="widget.parameters" widget-name="{{ widget.name }}"></div> - - <div ng-if="widget.isContainer && widget.layout!='ByDimension'"> - <div piwik-widget-container="widget"></div> - </div> - - <div ng-if="widget.isContainer && widget.layout=='ByDimension'"> - <div piwik-widget-by-dimension-container="widget"></div> - </div> -</div>
\ No newline at end of file diff --git a/plugins/CoreHome/angularjs/widget/widget.directive.js b/plugins/CoreHome/angularjs/widget/widget.directive.js deleted file mode 100644 index 651c77e409..0000000000 --- a/plugins/CoreHome/angularjs/widget/widget.directive.js +++ /dev/null @@ -1,128 +0,0 @@ -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - -/** - * Renders any kind of widget. If you have a widget and you want to have it rendered, use this directive. It will - * display a name on top and the actual widget below. It can handle any kind of widget, no matter whether it is a - * regular widget or a container. - * - * @param {Object} piwikWidget A widget object as returned by the WidgetMetadata API. - * @param {Object} piwikWidget.middlewareParameters If present, we will request a URL using the given parameters and - * only if this URL returns a JSON `true` the widget will be shown. - * Otherwise the widget won't be shown. - * @param {String} containerId If you do not have a widget object but a containerId we will find the correct widget - * object based on the given containerId. Be aware that we might not find the widget if - * it is for example not available for the current user or period/date. - * @param {Boolean} widgetized true if the widget is widgetized (eg in Dashboard or exported). In this case we will add - * a URL parameter widget=1 to all widgets. Eg sparklines will be then displayed one after - * another (vertically aligned) instead of two next to each other. - * - * Example: - * <div piwik-widget="widget"></div> - * <div piwik-widget containerid="widgetGoalsOverview"></div> // in this case we will find the correct widget automatically - * <div piwik-widget="widget" widetized="true"></div> // disables rating feature, no initial headline - */ -(function () { - angular.module('piwikApp').directive('piwikWidget', piwikWidget); - - piwikWidget.$inject = ['piwik', 'piwikApi', 'reportMetadataModel']; - - function piwikWidget(piwik, piwikApi, reportMetadataModel){ - function findContainerWidget(containerId, scope) { - widgetsHelper.getAvailableWidgets(function (categorizedWidgets) { - - angular.forEach(categorizedWidgets, function (widgets) { - angular.forEach(widgets, function (widget) { - if (widget && widget.isContainer && widget.parameters.containerId === containerId) { - widget = angular.copy(widget); - if (scope.widgetized) { - widget.isFirstInPage = '1'; - widget.parameters.widget = '1'; - angular.forEach(widget.widgets, function (widget) { - widget.parameters.widget = '1'; - widget.parameters.containerId = containerId; - }); - } - scope.widget = widget; - applyMiddleware(scope); - } - }); - }); - - }); - } - - function addReportDocumentationIfPossible(widget) - { - if (widget && widget.isReport && !widget.documentation) { - var report = reportMetadataModel.findReport(widget.module, widget.action); - if (report && report.documentation) { - widget.documentation = report.documentation; - } - } - } - - function applyMiddleware(scope) - { - if (!scope.widget.middlewareParameters) { - scope.$evalAsync('view.showWidget = true'); - } else { - var params = angular.copy(scope.widget.middlewareParameters); - piwikApi.fetch(params).then(function (response) { - var enabled = response ? 'true' : 'false'; - scope.$evalAsync('view.showWidget = ' + enabled); - }); - } - } - - return { - restrict: 'A', - scope: { - widget: '=?piwikWidget', - widgetized: '=?', - containerid: '=' - }, - templateUrl: 'plugins/CoreHome/angularjs/widget/widget.directive.html?cb=' + piwik.cacheBuster, - compile: function (element, attrs) { - - return function (scope, element, attrs, ngModel) { - if (scope.widget) { - addReportDocumentationIfPossible(scope.widget); - applyMiddleware(scope); - } else if (attrs.containerid) { - findContainerWidget(attrs.containerid, scope); - } - - $(element).tooltip({ - track: true, - content: function() { - var $this = $(this); - if ($this.attr('piwik-field') === '') { - // do not show it for form fields - return ''; - } - - var title = $(this).attr('title'); - return piwikHelper.escape(title.replace(/\n/g, '<br />')); - }, - show: {delay: 700, duration: 200}, - hide: false - }); - - scope.$on( - "$destroy", - function () { - try { - $(element).tooltip('destroy'); - } catch (e) {} - } - ); - } - } - }; - } -})(); diff --git a/plugins/CoreHome/javascripts/broadcast.js b/plugins/CoreHome/javascripts/broadcast.js index de6af9a996..22b7c96e73 100644 --- a/plugins/CoreHome/javascripts/broadcast.js +++ b/plugins/CoreHome/javascripts/broadcast.js @@ -100,7 +100,7 @@ var broadcast = { // hash doesn't contain the first # character. if (hash && 0 === (''+hash).indexOf('/')) { - hash = (''+hash).substr(1); + hash = (''+hash).slice(1); } @@ -314,7 +314,7 @@ var broadcast = { * @param {array} paramsToRemove Optional parameters to remove from the URL. * @return {void} */ - propagateNewPage: function (str, showAjaxLoading, strHash, paramsToRemove) { + propagateNewPage: function (str, showAjaxLoading, strHash, paramsToRemove, wholeNewUrl) { // abort all existing ajax requests globalAjaxQueue.abort(); @@ -337,61 +337,66 @@ var broadcast = { } var oldUrl = currentSearchStr + currentHashStr; + var newUrl; - // remove all array query params that are currently set. if we don't do this the array parameters we add - // just get added to the existing parameters. - params_vals.forEach(function (param) { + if (!wholeNewUrl) { + // remove all array query params that are currently set. if we don't do this the array parameters we add + // just get added to the existing parameters. + params_vals.forEach(function (param) { if (/\[]=/.test(decodeURIComponent(param))) { - var paramName = decodeURIComponent(param).split('[]=')[0]; - removeParam(paramName); + var paramName = decodeURIComponent(param).split('[]=')[0]; + removeParam(paramName); } - }); + }); - // remove parameters if needed - paramsToRemove.forEach(function (paramName) { + // remove parameters if needed + paramsToRemove.forEach(function (paramName) { removeParam(paramName); - }); + }); - // update/add parameters based on whether the parameter is an array param or not - params_vals.forEach(function (param) { - if(!param.length) { - return; // updating with empty string would destroy some values + // update/add parameters based on whether the parameter is an array param or not + params_vals.forEach(function (param) { + if (!param.length) { + return; // updating with empty string would destroy some values } if (/\[]=/.test(decodeURIComponent(param))) { // array param value - currentSearchStr = broadcast.addArrayParamValue(param, currentSearchStr); + currentSearchStr = broadcast.addArrayParamValue(param, currentSearchStr); - if (currentHashStr.length !== 0) { - currentHashStr = broadcast.addArrayParamValue(param, currentHashStr); - } + if (currentHashStr.length !== 0) { + currentHashStr = broadcast.addArrayParamValue(param, currentHashStr); + } } else { - // update both the current search query and hash string - currentSearchStr = broadcast.updateParamValue(param, currentSearchStr); + // update both the current search query and hash string + currentSearchStr = broadcast.updateParamValue(param, currentSearchStr); - if (currentHashStr.length !== 0) { - currentHashStr = broadcast.updateParamValue(param, currentHashStr); - } + if (currentHashStr.length !== 0) { + currentHashStr = broadcast.updateParamValue(param, currentHashStr); + } } - }); + }); - var updatedUrl = new RegExp('&updated=([0-9]+)'); - var updatedCounter = updatedUrl.exec(currentSearchStr); - if (!updatedCounter) { + var updatedUrl = new RegExp('&updated=([0-9]+)'); + var updatedCounter = updatedUrl.exec(currentSearchStr); + if (!updatedCounter) { currentSearchStr += '&updated=1'; - } else { + } else { updatedCounter = 1 + parseInt(updatedCounter[1]); currentSearchStr = currentSearchStr.replace(new RegExp('(&updated=[0-9]+)'), '&updated=' + updatedCounter); - } + } - if (strHash && currentHashStr.length != 0) { + if (strHash && currentHashStr.length != 0) { var params_hash_vals = strHash.split("&"); for (var i = 0; i < params_hash_vals.length; i++) { - currentHashStr = broadcast.updateParamValue(params_hash_vals[i], currentHashStr); + currentHashStr = broadcast.updateParamValue(params_hash_vals[i], currentHashStr); } - } + } - // Now load the new page. - var newUrl = currentSearchStr + currentHashStr; + // Now load the new page. + newUrl = currentSearchStr + currentHashStr; + } else { + newUrl = wholeNewUrl; + } var $rootScope = piwikHelper.getAngularDependency('$rootScope'); if ($rootScope) { @@ -499,8 +504,6 @@ var broadcast = { * handler. */ propagateNewPopoverParameter: function (handlerName, value) { - var $location = angular.element(document).injector().get('$location'); - var popover = ''; if (handlerName && '' != value && 'undefined' != typeof value) { popover = handlerName + ':' + value; @@ -519,15 +522,10 @@ var broadcast = { } } - var $window = piwikHelper.getAngularDependency('$window'); - var urlStr = $window.location.hash; - urlStr = broadcast.updateParamValue('popover=' + encodeURIComponent(popover), urlStr); - urlStr = urlStr.replace(/^[#?]+/, ''); - $location.search(urlStr); - - setTimeout(function () { - angular.element(document).injector().get('$rootScope').$apply(); - }, 1); + var MatomoUrl = window.CoreHome.MatomoUrl; + MatomoUrl.updateHash( + Object.assign({}, MatomoUrl.hashParsed.value, { popover }), + ); }, /** @@ -775,8 +773,8 @@ var broadcast = { */ getValueFromHash: function (param, url) { var hashStr = broadcast.getHashFromUrl(url); - if (hashStr.substr(0, 1) == '#') { - hashStr = hashStr.substr(1); + if (hashStr.slice(0, 1) == '#') { + hashStr = hashStr.slice(1); } hashStr = hashStr.split('#')[0]; @@ -797,7 +795,7 @@ var broadcast = { var lookFor = param + '='; if (url.indexOf('?') >= 0) { - url = url.substr(url.indexOf('?')+1); + url = url.slice(url.indexOf('?')+1); } var urlPieces = url.split('&'); diff --git a/plugins/CoreHome/javascripts/corehome.js b/plugins/CoreHome/javascripts/corehome.js index 8ff2e36a85..251ee24d4c 100644 --- a/plugins/CoreHome/javascripts/corehome.js +++ b/plugins/CoreHome/javascripts/corehome.js @@ -92,7 +92,7 @@ $( document ).ready(function() { $('.navbar.collapsible').collapsible(); - $('select').material_select(); + $('select').not('.ui-datepicker select').material_select(); piwikHelper.registerShortcut('?', _pk_translate('CoreHome_ShortcutHelp') , function (event) { // don't open if an modal is already shown diff --git a/plugins/CoreHome/javascripts/dataTable.js b/plugins/CoreHome/javascripts/dataTable.js index 35b73de875..3cd03cbea5 100644 --- a/plugins/CoreHome/javascripts/dataTable.js +++ b/plugins/CoreHome/javascripts/dataTable.js @@ -39,8 +39,9 @@ function DataTable(element) { DataTable._footerIconHandlers = {}; -DataTable.initNewDataTables = function () { - $('div.dataTable').each(function () { +DataTable.initNewDataTables = function (reportId) { + var selector = typeof reportId === 'string' ? '[data-report='+JSON.stringify(reportId)+']' : 'div.dataTable'; + $(selector).each(function () { if (!$(this).attr('id')) { var tableType = $(this).attr('data-table-type') || 'DataTable', klass = require('piwik/UI')[tableType] || require(tableType); @@ -113,7 +114,6 @@ $.extend(DataTable.prototype, UIControl.prototype, { this._init(domElem); this.enableStickHead(domElem); this.initialized = true; - }, enableStickHead: function (domElem) { @@ -376,7 +376,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { self.handleSearchBox(domElem); self.handleColumnDocumentation(domElem); self.handleRowActions(domElem); - self.handleCellTooltips(domElem); + self.handleCellTooltips(domElem); self.handleRelatedReports(domElem); self.handleTriggeredEvents(domElem); self.handleColumnHighlighting(domElem); @@ -425,14 +425,6 @@ $.extend(DataTable.prototype, UIControl.prototype, { $domElem.width(''); parentDataTable.width(''); - var $table = $('table.dataTable', domElem); - if ($table.closest('.reportsByDimensionView').length) { - var requiredTableWidth = $table.width() - 40; // 40 is padding on card content - if (domElem.width() > requiredTableWidth) { - domElem.css('max-width', requiredTableWidth + 'px'); - } - } - var tableWidth = getTableWidth(domElem); if (tableWidth <= maxTableWidth) { @@ -445,9 +437,9 @@ $.extend(DataTable.prototype, UIControl.prototype, { if (dataTableInCard && dataTableInCard.length) { // makes sure card has the same width - dataTableInCard.width(maxTableWidth); + dataTableInCard.css('max-width', maxTableWidth); } else { - $domElem.width(maxTableWidth); + $domElem.css('max-width', maxTableWidth); } if (parentDataTable && parentDataTable.length) { @@ -455,9 +447,9 @@ $.extend(DataTable.prototype, UIControl.prototype, { // applied in getLabelWidth() since they will have the same size. if (dataTableInCard.length) { - dataTableInCard.width(maxTableWidth); + dataTableInCard.css('max-width', maxTableWidth); } else { - parentDataTable.width(maxTableWidth); + parentDataTable.css('max-width', maxTableWidth); } } } @@ -492,8 +484,14 @@ $.extend(DataTable.prototype, UIControl.prototype, { ) { labelWidth = maxLabelWidth; // prevent for instance table in Actions-Pages is not too wide } + var allColumns = $('tr:nth-child(1) td.label', domElem).length; + var firstTableColumn = $('table:first tbody>tr:first td.label', domElem).length; + var amount = allColumns; + if (allColumns > 2 * firstTableColumn) { + amount = 2 * firstTableColumn; + } - return parseInt(labelWidth / $('tr:nth-child(1) td.label', domElem).length, 10); + return parseInt(labelWidth / amount, 10); } function getLabelColumnMinWidth(domElem) @@ -564,7 +562,6 @@ $.extend(DataTable.prototype, UIControl.prototype, { var labelColumnMinWidth = getLabelColumnMinWidth(domElem); var labelColumnMaxWidth = getLabelColumnMaxWidth(domElem); var labelColumnWidth = getLabelWidth(domElem, tableWidth, 125, 440); - if (labelColumnMinWidth > labelColumnWidth) { labelColumnWidth = labelColumnMinWidth; } @@ -808,7 +805,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { $.each(patternsToReplace, function (index, pattern) { if (0 === currentPattern.indexOf(pattern.to)) { - currentPattern = pattern.from + currentPattern.substr(2); + currentPattern = pattern.from + currentPattern.slice(2); } }); @@ -884,7 +881,7 @@ $.extend(DataTable.prototype, UIControl.prototype, { $.each(patternsToReplace, function (index, pattern) { if (0 === keyword.indexOf(pattern.from)) { - keyword = pattern.to + keyword.substr(1); + keyword = pattern.to + keyword.slice(1); } }); @@ -1438,35 +1435,10 @@ $.extend(DataTable.prototype, UIControl.prototype, { }, handleColumnHighlighting: function (domElem) { - var maxWidth = {}; + var currentNthChild = null; var self = this; - // give all values consistent width - $('td', domElem).each(function () { - var $this = $(this); - if ($this.hasClass('label')) { - return; - } - - var table = $this.closest('table'); - var nthChild = $this.parent('tr').children().index($(this)) + 1; - var rows = $('> tbody > tr', table); - - if (!maxWidth[nthChild]) { - maxWidth[nthChild] = 0; - rows.find("td:nth-child(" + (nthChild) + ").column .value").add('> thead th:not(.label) .thDIV', table).each(function (index, element) { - var width = $(element).width(); - if (width > maxWidth[nthChild]) { - maxWidth[nthChild] = width; - } - }); - rows.find("td:nth-child(" + (nthChild) + ").column .value").each(function (index, element) { - $(element).closest('td').css({width: maxWidth[nthChild]}); - }); - } - }); - // highlight all columns on hover $(domElem).on('mouseenter', 'td', function (e) { e.stopPropagation(); @@ -1963,17 +1935,13 @@ $.extend(DataTable.prototype, UIControl.prototype, { // ensure the tooltips of parent elements are hidden when the action tooltip is shown // otherwise it can happen that tooltips for subtable rows are shown as well. open: function() { - var tooltip = $(this).parents().filter(function() { - return jQuery.hasData(this) && $(this).data('ui-tooltip'); - }).tooltip('instance'); + var tooltip = $(this).parents('.matomo-widget').tooltip('instance'); if (tooltip) { tooltip.disable(); } }, close: function() { - var tooltip = $(this).parents().filter(function() { - return jQuery.hasData(this) && $(this).data('ui-tooltip'); - }).tooltip('instance'); + var tooltip = $(this).parents('.matomo-widget').tooltip('instance'); if (tooltip) { tooltip.enable(); } diff --git a/plugins/CoreHome/javascripts/sparkline.js b/plugins/CoreHome/javascripts/sparkline.js index 5457f1fe2e..3aab2976c2 100644 --- a/plugins/CoreHome/javascripts/sparkline.js +++ b/plugins/CoreHome/javascripts/sparkline.js @@ -26,33 +26,35 @@ piwik.getSparklineColors = function () { // initializes each sparkline so they use colors defined in CSS piwik.initSparklines = function() { - $('.sparkline img').each(function () { - var $self = $(this); + $(function () { + $('.sparkline img').each(function () { + var $self = $(this); - if ($self.attr('src')) { + if ($self.attr('src')) { return; - } + } - var seriesIndices = $self.closest('.sparkline').data('series-indices'); - var sparklineColors = piwik.getSparklineColors(); + var seriesIndices = $self.closest('.sparkline').data('series-indices'); + var sparklineColors = piwik.getSparklineColors(); - if (seriesIndices && sparklineColors.lineColor instanceof Array) { + if (seriesIndices && sparklineColors.lineColor instanceof Array) { sparklineColors.lineColor = sparklineColors.lineColor.filter(function (c, index) { - return seriesIndices.indexOf(index) !== -1; + return seriesIndices.indexOf(index) !== -1; }); - } + } - var colors = JSON.stringify(sparklineColors); - var appendToSparklineUrl = '&colors=' + encodeURIComponent(colors); + var colors = JSON.stringify(sparklineColors); + var appendToSparklineUrl = '&colors=' + encodeURIComponent(colors); - // Append the token_auth to the URL if it was set (eg. embed dashboard) - var token_auth = broadcast.getValueFromUrl('token_auth'); - if (token_auth.length && piwik.shouldPropagateTokenAuth) { + // Append the token_auth to the URL if it was set (eg. embed dashboard) + var token_auth = broadcast.getValueFromUrl('token_auth'); + if (token_auth.length && piwik.shouldPropagateTokenAuth) { appendToSparklineUrl += '&token_auth=' + token_auth; - } - $self.attr('width', sparklineDisplayWidth); - $self.attr('height', sparklineDisplayHeight); - $self.attr('src', $self.attr('data-src') + appendToSparklineUrl); + } + $self.attr('width', sparklineDisplayWidth); + $self.attr('height', sparklineDisplayHeight); + $self.attr('src', $self.attr('data-src') + appendToSparklineUrl); + }); }); }; diff --git a/plugins/CoreHome/javascripts/top_controls.js b/plugins/CoreHome/javascripts/top_controls.js index c215e70f0f..f4a793b4b5 100644 --- a/plugins/CoreHome/javascripts/top_controls.js +++ b/plugins/CoreHome/javascripts/top_controls.js @@ -51,7 +51,7 @@ function initTopControls() { } } -//Keyboard controls for Top Controls Calendar through tab and enter. +//Keyboard controls for Top Controls Calendar through tab and enter. $( document ).ready(function() { $('.periodSelector').keydown(function(e){ toggleCalendar(e); @@ -67,7 +67,7 @@ $( document ).ready(function() { }) }); -//Keyboard controls for Top Controls Calendar through tab and enter. +//Keyboard controls for Top Controls Calendar through tab and enter. $( document ).ready(function() { $('.periodSelector').keydown(function(e){ toggleCalendar(e); @@ -85,7 +85,7 @@ $( document ).ready(function() { function toggleCalendar(e){ var calendarOpen = $('.periodSelector').hasClass('expanded'); - + if(e.which==13){ if(calendarOpen){ $('.periodSelector').removeClass('expanded'); @@ -107,4 +107,4 @@ function blockPropegation(){ $('.ui-datepicker-month, .ui-datepicker-year, .periodSelector td a').keydown(function(e){ e.stopPropagation(); }) -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/bg.json b/plugins/CoreHome/lang/bg.json index 0ee2f89f2a..148e72522f 100644 --- a/plugins/CoreHome/lang/bg.json +++ b/plugins/CoreHome/lang/bg.json @@ -1,42 +1,132 @@ { "CoreHome": { + "AdblockIsMaybeUsed": "В случай, че използвате рекламен блокер, моля, деактивирайте го за този сайт, за да сте сигурни, че Matomo работи без проблеми.", + "AddTotalsRowDataTable": "Отчетът не показва общия ред %s Показване на реда с общите суми", "CategoryNoData": "Няма данни в тази категория. Опитайте \"Включи всички данни\".", + "ChangeCurrentWebsite": "Изберете уебсайт. Избран в момента уебсайт: %s", + "ChangePeriod": "Промяна на периода", + "ChangeVisualization": "Промяна на визуализацията", "CheckForUpdates": "Проверка за обновления", "CheckPiwikOut": "Проверка на Matomoi изход!", - "ClickToEditX": "Щракни за промяна на %s", - "CloseWidgetDirections": "Можете да затворите тази джаджа, като кликнете на 'Х' иконата в горната част на джаджата.", + "ChooseX": "Изберете %1$s", + "ClickRowToExpandOrContract": "Кликнете върху този ред, за да разширите или свиете подтаблицата.", + "ClickToEditX": "Кликнете за промяна на %s", + "ClickToSeeFullInformation": "Кликнете, за да видите пълната информация", + "CloseSearch": "Затваряне на търсенето", + "CloseWidgetDirections": "Можете да затворите този уиджет, като кликнете на 'Х' иконата в горната му част.", + "CssDidntLoad": "Вашият браузър не можа да зареди стила на тази страница.", + "CustomLimit": "Персонализиран лимит", + "DataForThisReportHasBeenDisabled": "Понастоящем сегментирането е деактивирано за този отчет. Моля, проверете %1$s този ЧЗВ %2$s за повече подробности.", "DataForThisReportHasBeenPurged": "Датата на този доклад е стара с %s месеца и ще бъде изтрита.", + "DataTableCombineDimensions": "Размерите се показват отделно %s Показване на комбинираните размери", "DataTableExcludeAggregateRows": "Сумарните редове са показани %s Скриване", + "DataTableHowToSearch": "Натиснете Enter или кликнете върху иконата за търсене, за да търсите", "DataTableIncludeAggregateRows": "Сумарните редове са скрити %s Покажи ги", + "DataTableShowDimensions": "Размерите са комбинирани %s Показване на размерите отделно", + "DateInvalid": "Посочената комбинация от дата и период е невалидна. Моля, изберете валидна дата в селектора на дати.", "Default": "подразбиране", + "DevicesSubcategoryHelp": "Разделът Устройства Ви помага да разберете технологията, която Вашите посетители използват за достъп до Вашия сайт. Ще видите отчети за типа устройство и конкретни модели, за да можете да оптимизирате сайта си за най-популярните устройства.", "DonateCall1": "Matomo винаги ще бъде безплатен за използване, но това не означава, че ние нямаме разходи за развитието му.", "DonateCall2": "Matomo се нуждае от вашата подкрепа, за да продължава да расте и процъфтява.", + "DonateCall3": "Ако смятате, че Matomo е добавил значителна стойност към Вашия бизнес или начинание, %1$sмоля, обмислете да дарите %2$s или %3$sза закупуване на премиум функционалности %4$s. Всяка стотинка ще помогне.", + "EndDate": "Крайна дата", + "EndShortcut": "Край", + "EngagementSubcategoryHelp1": "Разделът за ангажираност предоставя отчети, които помагат да се определи количествено колко нови и завърнали се посетители получавате. Можете също да прегледате отчети, които разбиват средното време и броя на страниците на посещение, както и броя пъти, когато посетител е бил на Вашия сайт и най-често срещания брой дни между посещенията.", + "EngagementSubcategoryHelp2": "Това може да Ви помогне да оптимизирате за честота и посещения с високо взаимодействие в допълнение към максимизирането на обхвата Ви.", + "EnterZenMode": "Влезте в режим Zen (скрийте менютата)", + "ExceptionNotAllowlistedIP": "Не можете да използвате Matomo, тъй като Вашият IP %s не е разрешен.", "ExcludeRowsWithLowPopulation": "Всички редове са показани %s С изключение на тези с ниски стойности", + "ExitZenMode": "Излизане от режим Zen (показване на менютата)", + "ExpandSubtables": "Разширете подтаблиците", + "ExportFormat": "Формат за експортиране", + "ExportTooltip": "Забележка: За да използвате генерирания URL адрес за експортиране, ще трябва да посочите означение за удостоверяване на приложението. Можете да конфигурирате тези токени в Администратор -> Сигурност -> Удостоверяване на токени.", + "ExportTooltipWithLink": "Забележка: За да използвате генерирания URL адрес за експортиране, ще трябва да посочите означение за удостоверяване на приложението. Можете да конфигурирате тези токени в %1$s[Администратор -> Сигурност -> Токени]%2$s. Заменете %3$s в URL адреса за експортиране с Вашия токен за удостоверяване. Предупреждение: Никога не споделяйте URL адреса с истинския маркер с никой друг.", "ExternalHelp": "Помощ (отваря се в нов прозорец)", "FlattenDataTable": "Този доклад е йерархичен %s Направете го плосък", + "FlattenReport": "Изравняване на отчета", + "FormatMetrics": "Показатели за форматиране", + "HideExportUrl": "Скриване на URL за експортиране", + "HomeShortcut": "Начало", "IncludeRowsWithLowPopulation": "Редове с ниски стойности са скрити %s Покажи всички редове", "InjectedHostEmailBody": "Здравейте, днес се опитах да достъпя Matomo и се натъкнах на предупреждение за неизвестно име на машината.", "InjectedHostEmailSubject": "Matomo е бил достъпен чрез неизвестно име: %s", - "InjectedHostSuperUserWarning": "Възможно е конфигурацията на Matomo да е неправилна (това се случва когато Matomo е бил изместен на нов сървър или друг адрес). Вие можете или %1$sда щракнете тук и да добавите %2$s като валиден Matomo адрес (ако сте сигурни в достоверността му)%3$s, или %4$sда щракнете тук и да посетите %5$s, за да достъпите Matomo безпасно%6$s.", + "InjectedHostNonSuperUserWarning": "%1$sКликнете тук за безопасен достъп до Matomo%2$s и премахнете това предупреждение. Може също да искате да се свържете с Вашия администратор на Matomo и да го уведомите за този проблем (%3$sкликнете тук за имейл %4$s).", + "InjectedHostSuperUserWarning": "Възможно е конфигурацията на Matomo да е неправилна (това се случва когато Matomo е бил изместен на нов сървър или друг адрес). Вие можете или %1$sда кликнете тук и да добавите %2$s като валиден Matomo адрес (ако сте сигурни в достоверността му)%3$s, или %4$sда кликнете тук и да посетите %5$s, за да достъпите Matomo безопасно%6$s.", "InjectedHostWarningIntro": "В момента достъпвате Matomo от %1$s, но Matomo е настроен да работи чрез този адрес: %2$s.", - "JavascriptDisabled": "JavaScript трябва да бъде разрешен за да използвате Matomo в стандартен изглед.<br \/>Същото е ако JavaScript не е разрешен или браузъра не го поддържа.<br \/>За да използвате стандартен изглед разрешете JavaScript от настройките на Вашия браузър и %1$sопитайте отново%2$s.<br \/>", + "JavascriptDisabled": "JavaScript трябва да бъде разрешен за да използвате Matomo в стандартен изглед.<br>Същото е ако JavaScript не е разрешен или браузърът не го поддържа.<br>За да използвате стандартен изглед разрешете JavaScript от настройките на Вашия браузър и %1$sопитайте отново%2$s.<br>", + "JsDidntLoad": "Вашият браузър не успя да зареди скриптовете на тази страница.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "Водещата отворена платформа за анализ, която зачита поверителността на личните Ви данни.", + "MacPageDown": "Fn + стрелка надясно", + "MacPageUp": "Fn + стрелка наляво", + "MainNavigation": "Основна навигация", "Menu": "Меню", + "MenuEntries": "Записи в менюто", "NoPrivilegesAskPiwikAdmin": "Вие се логнахте в като '%1$s' но изглежда че нямате разрешение от Matomo. %2$s Попитайте Вашият Matomo администратор (клик на email)%3$s да Ви даде \"поглед\" достъп до сайта.", + "NoSuchPage": "Тази страница не съществува", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Актуализацията с едно кликване не е възможна, тъй като използвате Matomo с множество сървъри. Моля, изтеглете най-новата версия от %1$s, за да продължите.", + "OnlyForSuperUserAccess": "Този уиджет се показва в таблото за управление по подразбиране само за потребители с достъп на супер потребител.", + "PageDownShortcutDescription": "за да стигнете до края на страницата", + "PageUpShortcutDescription": "за да стигнете до горната част на страницата", + "PeriodHasOnlyRawData": "Изглежда отчетите за този период все още не са обработени. Искате ли да видите какво се случва сега? Разгледайте %1$sРегистъра на посещенията%2$s или изберете друг период от дата, докато се генерират отчетите.", "PeriodRange": "Период", + "PivotBySubtable": "Този отчет не е пивотиран %1$s Пивот от %2$s", + "Profilable": "Профилируеми", + "QuickAccessTitle": "Потърсете %s. Използвайте клавишите със стрелки, за да навигирате в резултатите от търсенето. Пряк път: Натиснете 'f' за търсене.", + "QuickLinks": "Бързи връзки", + "ReadMoreOnlineGuide": "Прочетете повече по тази тема в онлайн ръководството.", + "RemoveTotalsRowDataTable": "Отчетът показва общия ред %s Премахване на реда с общи суми", "ReportGeneratedOn": "Доклада е генериран за %s", "ReportGeneratedXAgo": "Доклада е генериран преди %s", - "SharePiwikLong": "Здравейте! Туко-що открих прекрасен софтуер с отворен код: Matomo! Matomo позволява проследяването на посетителите на даден сайт безплатно. Задължително трябва да го пробвате!", + "ReportType": "Вид на отчета", + "ReportWithMetadata": "Отчет с метаданни", + "ReportingCategoryHelpPrefix": "Как ми помага страницата за отчитане „%1$s > %2$s“?", + "RowLimit": "Ограничение на редовете", + "SearchOnMatomo": "Потърсете '%1$s' на Matomo.org", + "SeeAvailableVersions": "Вижте наличните версии", + "Segments": "Сегменти", + "SharePiwikLong": "Здравейте! Туко-що открих прекрасен софтуер с отворен код: Matomo! \n\nMatomo позволява проследяването на посетителите на даден сайт безплатно. Задължително трябва да го пробвате!", "SharePiwikShort": "Matomo! Софтуер с отворен код за уеб анализ. Притежавайте вашите собствени данни.", "ShareThis": "Сподели това", + "ShortcutCalendar": "за отваряне на календара (d означава дата)", + "ShortcutHelp": "за отваряне на тази помощ", + "ShortcutSearch": "за отваряне на търсенето (f означава Намери)", + "ShortcutSegmentSelector": "за отваряне на Селектор на сегменти", + "ShortcutWebsiteSelector": "за отваряне на Селектора на уеб сайтове", + "ShortcutZenMode": "за режим Zen", + "ShortcutsAvailable": "Налични преки пътища", + "ShowExportUrl": "Показване на URL за експортиране", "ShowJSCode": "Покажи JavaScript кода за вмъкване в сайта", + "SkipToContent": "Преминете към съдържанието", + "SoftwareSubcategoryHelp": "Разделът за софтуер показва операционните системи, браузърите и плъгините, които Вашите посетители използват за достъп до сайта, така че да можете да оптимизирате сайта си, за да гарантирате, че е напълно съвместим с най-популярните конфигурации.", + "StandardReport": "Стандартен отчет", + "StartDate": "Начална дата", "SubscribeAndBecomePiwikSupporter": "Пристъпете към сигурната страница за плащане (PayPal) за да станете Matomo Supporter!", "SupportPiwik": "Подкрепи Matomo!", + "SupportUsOn": "Подкрепете ни в", + "SystemSummaryMysqlVersion": "Версия на MySQL", + "SystemSummaryNActivatedPlugins": "%d активирани плъгини", + "SystemSummaryNSegments": "%1$d сегменти", + "SystemSummaryNSegmentsWithBreakdown": "%1$d сегменти (%2$s предварително обработени, %3$s обработени в реално време)", + "SystemSummaryNWebsites": "%d уебсайтове", + "SystemSummaryPhpVersion": "PHP версия", + "SystemSummaryPiwikVersion": "Версия Matomo", + "SystemSummaryWidget": "Резюме на системата", "TableNoData": "Няма данни за тази таблица.", + "TechDeprecationWarning": "Започвайки от версия Matomo %1$s, Matomo ще прекрати поддръжката за %2$s. За повече информация %3$sвижте публикацията ни в блога.%4$s", + "ThanksFromAllOfUs": "Благодарим Ви от всички нас в Matomo!", "ThereIsNoDataForThisReport": "Няма данни за този доклад.", "UnFlattenDataTable": "Този доклад е плосък %s Направете го йерархичен", + "UndoPivotBySubtable": "Този отчет е с пивот %s Отмяна на пивот", "ViewAllPiwikVideoTutorials": "Виж всички Matomo помощни клипове", + "VisitStatusOrdered": "Поръчано", + "VisitStatusOrderedThenAbandoned": "Поръчана и след това изоставена кошница", + "VisitTypeReturning": "Връщане", + "VisitTypeReturningCustomer": "Връщащ се клиент", + "VisitorsCategoryHelp1": "Страниците за посетители Ви разказват кои са Вашите посетители. Неща като откъде идват Вашите посетители, какви устройства и браузъри използват и кога обикновено посещават уебсайта Ви. Разберете като цяло коя е Вашата аудитория и потърсете отклонения, за да видите как аудиторията Ви може да нарасне.", + "VisitorsCategoryHelp2": "В допълнение към общата информация за Вашите посетители, можете също да използвате %1$sДневник на посещенията%2$s, за да видите какво се е случило при всяко отделно посещение.", + "VisitorsOverviewHelp": "Прегледът на посетителите Ви помага да разберете популярността на Вашия сайт. Той прави това, като предоставя диаграми, които показват колко посещения получава Вашият сайт за избран период и средното ниво на ангажираност за ключови функции, като например търсения и изтегляния.", "WebAnalyticsReports": "Уеб Анализи Доклади", "YouAreUsingTheLatestVersion": "Вие използвате последна версия на Matomo!", - "SystemSummaryPhpVersion": "PHP версия" + "YourDonationWillHelp": "Вашето дарение директно ще помогне за финансирането на нови функции и подобрения за тази платформа за анализ с отворен код. Това означава, че общността винаги ще се възползва от инструмент, който защитава поверителността и Ви позволява да контролирате данните си." } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/ca.json b/plugins/CoreHome/lang/ca.json index 4c0c1cdf29..5fcc211e8b 100644 --- a/plugins/CoreHome/lang/ca.json +++ b/plugins/CoreHome/lang/ca.json @@ -1,29 +1,132 @@ { "CoreHome": { + "AdblockIsMaybeUsed": "En cas que utilitzeu un bloquejador d'anuncis desactiveu-lo per a aquest lloc, per assegurar-vos que Matomo funciona sense cap problema.", + "AddTotalsRowDataTable": "L'informe no mostra la fila de totals %s Mostra la fila de totals", "CategoryNoData": "No hi ha dades en aquesta categoria. Proveu d'incloure tota la població.", + "ChangeCurrentWebsite": "Trieu un lloc web, lloc web seleccionat actualment: %s", + "ChangePeriod": "Canviar el període", + "ChangeVisualization": "Canviar la visualització", "CheckForUpdates": "Cerca actualitzacions", + "CheckPiwikOut": "Fes una ullada a Matomo!", + "ChooseX": "Trieu %1$s", + "ClickRowToExpandOrContract": "Feu clic en aquesta fila per ampliar o reduir la subtaula.", + "ClickToEditX": "Feu clic per editar %s", + "ClickToSeeFullInformation": "Feu clic per veure tota la informació", + "CloseSearch": "Tancar la cerca", + "CloseWidgetDirections": "Podeu tancar aquest giny fent clic a la icona \"X\" a la part superior del giny.", + "CssDidntLoad": "El vostre navegador no ha pogut carregar l'estil d'aquesta pàgina.", + "CustomLimit": "Límit personalitzat", + "DataForThisReportHasBeenDisabled": "Actualment la segmentació està desactivada per a aquest informe. Si us plau, consulteu %1$saquest FAQ%2$s per obtenir més detalls.", "DataForThisReportHasBeenPurged": "La informació d'aquest informés és anterior a %s mesos d'antiguitat i s'ha purgat.", + "DataTableCombineDimensions": "Les dimensions es mostren per separat %s Mostra les dimensions combinades", "DataTableExcludeAggregateRows": "Es mostren les files aggrupades %s Amaga-ho", + "DataTableHowToSearch": "Premeu Intro o feu clic a la icona de cerca per cercar", "DataTableIncludeAggregateRows": "No es mostren les files agrupades %s Mostra-les", + "DataTableShowDimensions": "Les dimensions s'han combinat %s Mostra les dimensions per separat", + "DateInvalid": "La combinació de data i període indicada no és vàlida. Trieu una data vàlida al selector de dates.", "Default": "per defecte", + "DevicesSubcategoryHelp": "La secció Dispositius us ajuda a entendre la tecnologia que fan servir els vostres visitants per accedir al vostre lloc. Veureu informes sobre el tipus de dispositiu i models específics que us permetran optimitzar el vostre lloc per als dispositius més populars.", + "DonateCall1": "Matomo mai us costarà res d'utilitzar, però això no vol dir que no ens costi res de fer.", + "DonateCall2": "Matomo necessita el vostre suport continuat per créixer i prosperar.", + "DonateCall3": "Si creieu que Matomo ha afegit un valor important al vostre negoci o esforç, %1$si us plau, considereu donar%2$s o %3$scomprar una funció premium%4$s. Cada cèntim ajudarà.", + "EndDate": "Data final", + "EndShortcut": "Final", + "EngagementSubcategoryHelp1": "La secció Implicació ofereix informes que ajuden a quantificar quants visitants nous i recurrents rebeu. També podeu revisar informes que desglossen el temps mitjà i el nombre de pàgines per visita, així com el nombre de vegades que un visitant ha visitat el vostre lloc i el nombre de dies més habitual entre visites.", + "EngagementSubcategoryHelp2": "Això us pot ajudar a optimitzar la freqüència i les visites d'alta interacció, a més de maximitzar el vostre abast.", + "EnterZenMode": "Entra al mode Zen (amaga els menús)", + "ExceptionNotAllowlistedIP": "No podeu utilitzar aquest Matomo perquè la vostra IP %s no està permesa.", "ExcludeRowsWithLowPopulation": "Es mostren totes les files %s No mostris la població inferior", - "FlattenDataTable": "L'informe es jeràrquic %s Feu-lo pla.", + "ExitZenMode": "Sortir del mode Zen (mostrar els menús)", + "ExpandSubtables": "Amplieu les subtaules", + "ExportFormat": "Format d'exportació", + "ExportTooltip": "Nota: per utilitzar l'URL d'exportació generat, haureu d'especificar una autenticació de testimoni d'aplicació. Podeu configurar aquests testimonis a Admin -> Security -> Token Auths.", + "ExportTooltipWithLink": "Nota: per utilitzar l'URL d'exportació generat, haureu d'especificar una autenticació de testimoni d'aplicació. Podeu configurar aquests testimonis a %1$s[Administrador -> Seguretat -> Fitxers d'autenticació]%2$s. Substituïu %3$s a l'URL d'exportació pel vostre testimoni d'autenticació. Avís: mai compartiu l'URL amb el testimoni real amb ningú més.", + "ExternalHelp": "Ajuda (s'obre en una pestanya nova)", + "FlattenDataTable": "L'informe es jeràrquic %s Feu-lo pla", + "FlattenReport": "Allisar l'informe", + "FormatMetrics": "Format de mètriques", + "HideExportUrl": "Amaga l'URL d'exportació", + "HomeShortcut": "Inici", "IncludeRowsWithLowPopulation": "No es mostren les files amb polbació inferior %s Mostra totes les files", "InjectedHostEmailBody": "Hola, He provat d'accedir al Matomo avui i m'he trobat amb l'avís de nom de la màquina desconegut.", "InjectedHostEmailSubject": "S'ha accedit al Matomo amb un nom de màquina desconegut: %s", "InjectedHostNonSuperUserWarning": "%1$sClick here to access Matomo safely%2$s i eliminar aaquest avíst. Potse també voldreu contractar amb l'administrador del vostre Matomo i notificar-li aquesta incidència (%3$sclick here to email%4$s).", "InjectedHostSuperUserWarning": "Pot ser que el Matomo estigui mal configurat (per exemple, si el Matomo s'ha mogut a un nou servidor o URL). Podeu %1$sfer click aquí i afegir %2$s com el nom de la màquina vàlid (si hi confieu)%3$s, o bé %4$s fer click aquí %5$s per accedir al Matomo de forma segura%6$s.", "InjectedHostWarningIntro": "Esteu accedint al Matomo desde %1$s, però el Matomo està configurat per escoltar a l'adreça: %2$s.", - "JavascriptDisabled": "S'ha de tenir el Javascript activat per vistualitzar la vista estàndar del Matomo.<br\/> No obstant això, sembla que el Javascript esta deshabilitat or no està suportat pel vostre navegador<br\/> Per utilitzar la vista estàndarc, activeu el Javascript canviant les opcions del navegador i %1$storneu-ho a probar%2$s.<br \/>", + "JavascriptDisabled": "JavaScript ha d'estar habilitat perquè pugueu utilitzar Matomo amb la vista estàndard.<br>No obstant això sembla que JavaScript està desactivat o no és compatible amb el vostre navegador.<br>Per utilitzar la vista estàndard, activeu JavaScript canviant les opcions del navegador i després %1$storneu-ho a provar%2$s.<br>", + "JsDidntLoad": "El vostre navegador no ha pogut carregar els scripts d'aquesta pàgina.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "La plataforma d'anàlisi oberta líder que respecta la vostra privadesa.", + "MacPageDown": "Fn + fletxa dreta", + "MacPageUp": "Fn + fletxa esquerra", + "MainNavigation": "Navegació principal", + "Menu": "Menú", + "MenuEntries": "Entrades del menú", "NoPrivilegesAskPiwikAdmin": "Esteu identificat com a '%1$s' però sembla que no teniu cap permís establert al Matomo. %2$s Pregunteu al vostre administrador de Matomo (feu click per enviar un email)%3$s que us dongui access per veure un lloc web.", + "NoSuchPage": "Aquesta pàgina no existeix", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "L'actualització d'un sol clic no està disponible perquè utilitzeu Matomo amb diversos servidors. Baixeu la darrera versió de %1$s per continuar.", + "OnlyForSuperUserAccess": "Aquest widget només es mostra al tauler predeterminat per als usuaris que tenen accés de superusuari.", + "PageDownShortcutDescription": "per arribar al final de la pàgina", + "PageUpShortcutDescription": "per anar al capdamunt de la pàgina", + "PeriodHasOnlyRawData": "Sembla que els informes d'aquest període encara no s'han processat. Vols veure què passa ara? Consulteu el %1$sRegistre de visites%2$s o trieu un període de dates diferent mentre no es generin els informes.", "PeriodRange": "Rang", + "PivotBySubtable": "Aquest informe no està orientat %1$s Gira per %2$s", + "Profilable": "Perfilable", + "QuickAccessTitle": "Cerca %s. Utilitzeu les tecles de direcció per navegar pels resultats de la cerca. Drecera: premeu 'f' per cercar.", + "QuickLinks": "Enllaços ràpids", + "ReadMoreOnlineGuide": "Llegiu més sobre aquest tema a la guia en línia.", + "RemoveTotalsRowDataTable": "L'informe mostra la fila de totals %s Elimina la fila de totals", "ReportGeneratedOn": "Informe generat el %s", "ReportGeneratedXAgo": "Informe generat fa %s", + "ReportType": "Tipus d'informe", + "ReportWithMetadata": "Informe amb metadades", + "ReportingCategoryHelpPrefix": "Com m'ajuda la pàgina d'informes \"%1$s > %2$s\"?", + "RowLimit": "Límit de files", + "SearchOnMatomo": "Cerqueu \"%1$s\" a Matomo.org", + "SeeAvailableVersions": "Consulteu les versions disponibles", + "Segments": "Segments", + "SharePiwikLong": "Bones! Acabo de trobar un gran programari lliure: Matomo!\n\nMatomo et permetrà fer un seguiment dels visitants del teu lloc web de forma gratuïta. De veritat que l'hauries de provar!", + "SharePiwikShort": "Matomo! Analítica web gratuïta/lliure. Sigues propietari de les teves dades.", + "ShareThis": "Comparteix-ho", + "ShortcutCalendar": "per obrir el calendari (d vol dir Date)", + "ShortcutHelp": "per mostrar aquesta ajuda", + "ShortcutSearch": "per obrir la cerca (f vol dir Find)", + "ShortcutSegmentSelector": "per obrir el selector Segment", + "ShortcutWebsiteSelector": "per obrir el selector Lloc Web", + "ShortcutZenMode": "per mode Zen", + "ShortcutsAvailable": "Dreceres disponibles", + "ShowExportUrl": "Mostra l'URL d'exportació", "ShowJSCode": "Mostra el codi JavaScript necessari", + "SkipToContent": "Saltar al contingut", + "SoftwareSubcategoryHelp": "La secció Programari mostra els sistemes operatius, els navegadors i els connectors que fan servir els vostres visitants per accedir al lloc perquè pugueu optimitzar el vostre lloc per assegurar-vos que és totalment compatible amb les configuracions més populars.", + "StandardReport": "Informe estàndard", + "StartDate": "Data d'inici", + "SubscribeAndBecomePiwikSupporter": "Aneu a una pàgina de pagament segura amb targeta de crèdit (Paypal) per convertir-vos en un benefactor de Matomo!", + "SupportPiwik": "Dona suport a Matomo!", + "SupportUsOn": "Doneu-nos suport", + "SystemSummaryMysqlVersion": "Versió de MySQL", + "SystemSummaryNActivatedPlugins": "%d connectors activats", + "SystemSummaryNSegments": "%1$d segments", + "SystemSummaryNSegmentsWithBreakdown": "%1$d segments (%2$s preprocessats, %3$s processats en temps real)", + "SystemSummaryNWebsites": "%d llocs web", + "SystemSummaryPhpVersion": "Versió del PHP", + "SystemSummaryPiwikVersion": "Versió de Matomo", + "SystemSummaryWidget": "Resum del sistema", + "TableNoData": "No hi ha dades per a aquesta taula.", + "TechDeprecationWarning": "A partir de la versió de Matomo %1$s, Matomo finalitzarà el suport per a %2$s. Per obtenir més informació %3$sconsulteu la nostra entrada al bloc.%4$s", + "ThanksFromAllOfUs": "Gràcies de part de tots nosaltres a Matomo!", "ThereIsNoDataForThisReport": "No hi ha informació per aquest informe.", "UnFlattenDataTable": "Aquest informe es pla %s Feu-lo jeràrquic", + "UndoPivotBySubtable": "Aquest informe s'ha girat %s Desfés el gir", + "ViewAllPiwikVideoTutorials": "Veure tots els tutorials de vídeo de Matomo", + "VisitStatusOrdered": "Ordenat", + "VisitStatusOrderedThenAbandoned": "Carretó carregat i abandonat", + "VisitTypeReturning": "Habitual", + "VisitTypeReturningCustomer": "Client habitual", + "VisitorsCategoryHelp1": "Les pàgines de Visitants t'expliquen coses sobre qui són els teus visitants. Coses com ara d'on provenen els teus visitants, quins dispositius i navegadors fan servir i quan visiten generalment el teu lloc web. Per entendre, en conjunt, qui és el teu públic i buscar valors atípics per veure com podria créixer el teu públic.", + "VisitorsCategoryHelp2": "A més de la informació general sobre els vostres visitants, també podeu utilitzar el %1$sRegistre de visites%2$s per veure què va passar a cada visita individual.", + "VisitorsOverviewHelp": "La \"Visió general dels visitants\" us ajuda a entendre la popularitat del vostre lloc. Ho fa proporcionant gràfics que mostren quantes visites rep el vostre lloc durant un període seleccionat i el nivell mitjà d'interacció amb les funcions clau, com ara cerques i baixades.", "WebAnalyticsReports": "Informe d'analítica web", "YouAreUsingTheLatestVersion": "Esteu fent servir l'última versió de Matomo!", - "SystemSummaryPhpVersion": "Versió del PHP" + "YourDonationWillHelp": "La teva donació ajudarà directament a finançar noves funcions i millores per a aquesta plataforma d'anàlisi de codi obert. Això significa que la comunitat sempre es beneficiarà d'una eina que protegeixi la privadesa i us permeti mantenir el control de les vostres dades." } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/cs.json b/plugins/CoreHome/lang/cs.json index e234afd9b2..062ccc588f 100644 --- a/plugins/CoreHome/lang/cs.json +++ b/plugins/CoreHome/lang/cs.json @@ -1,21 +1,27 @@ { "CoreHome": { + "AdblockIsMaybeUsed": "Pokud používáte blokovač reklam, zakažte ho pro tyto stránky, aby Matomo správně fungoval.", + "AddTotalsRowDataTable": "Sestava nezobrazuje řádek součtů %s Zobrazit řádek součtů", "CategoryNoData": "V této kategorii nejsou k dispozici žádná data. Zkuste \"Zobrazit všechny výsledky\".", - "ChangeVisualization": "Změnit vizualizaci", + "ChangeCurrentWebsite": "Vyberte web, aktuálně vybraný web: %s", "ChangePeriod": "Změnit období", + "ChangeVisualization": "Změnit vizualizaci", "CheckForUpdates": "Zkontrolovat aktualizace", "CheckPiwikOut": "Vyzkoušejte Matomo!", + "ChooseX": "Vyberte %1$s", + "ClickRowToExpandOrContract": "Klikněte na tento řádek pro rozbalení nebo zbalení podtabulky.", "ClickToEditX": "Klikněte pro úpravu %s", "ClickToSeeFullInformation": "Klikněte pro zobrazení úplné informace", "CloseSearch": "Zavřít vyhledávání", "CloseWidgetDirections": "Tento widget můžete zavřít kliknutím na ikonu X na horní části widgetu.", - "ChooseX": "Vyberte %1$s", + "CssDidntLoad": "Vášmu prohlížeči se nepodařilo načíst styl této stránky.", + "CustomLimit": "Vlastní limit", "DataForThisReportHasBeenPurged": "Data pro toto hlášení jsou starší než %s měsíců a byla odstraněna.", + "DataTableCombineDimensions": "Rozměry jsou zobrazeny samostatně %s Zobrazit rozměry dohromady", "DataTableExcludeAggregateRows": "Agregované řádky jsou zobrazeny %s Skrýt", - "DataTableIncludeAggregateRows": "Agregované řádky jsou skryty %s Zobrazit", "DataTableHowToSearch": "Pro hledání stiskněte enter, nebo klikněte na ikonu vyhledávání", + "DataTableIncludeAggregateRows": "Agregované řádky jsou skryty %s Zobrazit", "DataTableShowDimensions": "Rozměry jsou kombinovány %s Zobrazit rozměry samostatně", - "DataTableCombineDimensions": "Rozměry jsou zobrazeny samostatně %s Zobrazit rozměry dohromady", "DateInvalid": "Uvedená kombinace data a období je neplatná. Vyberte prosím platné datum.", "Default": "výchozí", "DonateCall1": "Matomo lze používat zadarmo, to ale neznamená, že jeho vývoj nic nestojí.", @@ -23,95 +29,89 @@ "DonateCall3": "Pokud se domníváte, že vám Matomo významně pomohl při vašem podnikání nebo projektu, %1$sprosím zvažte příspěvek%2$s nebo %3$szakoupení prémiové funkce%4$s. Každý cent pomůže.", "EndShortcut": "Konec", "EnterZenMode": "Vstup do režimu Zen (skrýt nabídky)", - "ExitZenMode": "Ukončit režim Zen (zobrazit nabídky)", "ExceptionNotAllowlistedIP": "Nemůžete použít toto Matomo, protože vaše IP %s není povolena.", "ExcludeRowsWithLowPopulation": "Všechny řádky jsou zobrazeny %s Vyloučit nízkou populaci", + "ExitZenMode": "Ukončit režim Zen (zobrazit nabídky)", + "ExpandSubtables": "Rozbalit dílčí tabulky", + "ExportFormat": "Formát exportu", "ExternalHelp": "Nápověda (otevře se v nové záložce)", "FlattenDataTable": "Hlášení je hierarchické %s Zploštit", + "FlattenReport": "Srovnat report", "FormatMetrics": "Formátovat metriky", - "ShowExportUrl": "Zobrazit URL exportu", "HideExportUrl": "Skrýt URL exportu", "HomeShortcut": "Domů", - "SupportUsOn": "Podpořte nás na", "IncludeRowsWithLowPopulation": "Řádky s nízkou populací jsou skryty %s Zobrazit všechny řádky", "InjectedHostEmailBody": "Ahoj. Dnes jsem se snažil dostat do \\Matomou a dostal jsem varování o neznámém ménu hostitele.", "InjectedHostEmailSubject": "K Matomo bylo přistupováno s neznámým jménem hostitele %s", "InjectedHostNonSuperUserWarning": "%1$sKlikněte zde pro bezpečný přístup k Matomou%2$s a odstranění tohoto varování. Pokud chcete upozornit administrátora na tento problém, (%3$sklikněte zde pro odeslání emailu%4$s).", "InjectedHostSuperUserWarning": "Matomo může být špatně nakonfigurován, například pokud byl přesunut na nový server nebo URL. Můžete %1$skliknout zde a přidat %2$s jako platné jméno hostitele Matomo (pokud mu důvěřujete)%3$s, nebo %4$s klikněte zde%5$s pro bezpečný přístup k Matomou%6$s.", "InjectedHostWarningIntro": "Nyní přistupujete k Matomou z %1$s, ale byl nakonfigurován, aby naslouchal na následující adrese: %2$s.", - "JavascriptDisabled": "Musíte mít zapnutý JavaScript, jinak Matomo nezobrazíte.<br \/> Nebo jen není Váš prohlížeč mezi podporovanými.<br \/>Pro běžné zobrazení zapněte JavaScript ve svém prohlížeči, poté %1$szkuste znovu%2$s.<br \/>", - "VisitStatusOrdered": "Objednáno", - "VisitStatusOrderedThenAbandoned": "Objednáno a poté opuštěn košík", - "VisitTypeReturning": "Návraty", - "VisitTypeReturningCustomer": "Věrný zákazník", + "JavascriptDisabled": "Musíte mít zapnutý JavaScript, jinak Matomo nezobrazíte.<br /> Nebo jen není Váš prohlížeč mezi podporovanými.<br />Pro běžné zobrazení zapněte JavaScript ve svém prohlížeči, poté %1$szkuste znovu%2$s.<br />", + "JsDidntLoad": "Vášmu prohlížeči se nepodařilo načíst skripty této stránky.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "Nejrozšířenější otevřená aplatforma pro analýzu, která respektuje vaše soukromí.", + "MacPageDown": "Fn + pravá šipka", + "MacPageUp": "Fn + levá šipka", "MainNavigation": "Hlavní navigace", - "YourDonationWillHelp": "Váš dar přímo pomůže financovat nové funkce a vylepšení této analytické platformy s otevřeným zdrojovým kódem. To znamená, že komunita bude vždy těžit z nástroje, který chrání soukromí a umožní vám mít kontrolu nad svými daty.", - "ThanksFromAllOfUs": "Díky vám od nás všech na Matomo!", "Menu": "Menu", + "MenuEntries": "Položky menu", "NoPrivilegesAskPiwikAdmin": "Jste přihlášen jako '%1$s' ale zdá se, že nemáte v Matomo žádná práva. %2$s Zeptejte se Vašeho Matomo administrátora (klikem na email)%3$s aby Vám dal 'view' přístup na stránku.", + "NoSuchPage": "Tato stránka neexistuje", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Aktualizace na jedno kliknutí není dostupná při nasazení Matomou na několika serverech naráz. Stáhněte prosím nejnovější verzi z %1$s a pokračujte.", "OnlyForSuperUserAccess": "Tento widget je na výchozí nástěnce zobrazen pouze pro uživatele se super uživatelským přístupem", + "PageDownShortcutDescription": "dostat se na konec stránky", + "PageUpShortcutDescription": "dostat se na začátek stránky", "PeriodRange": "Rozsah", + "PivotBySubtable": "Toto hlášení není zaměřené %1$s Zaměřit na %2$s", + "Profilable": "Profilovatelné", + "QuickAccessTitle": "Výsledky hledání pro %s. Pro navigaci ve výsledcích vyhledávání použijte šipky. Zkratka: Zmáčknout 'f' pro hledání.", + "QuickLinks": "Rychlé odkazy", + "ReadMoreOnlineGuide": "Další informace o tomto tématu naleznete v online příručce.", + "RemoveTotalsRowDataTable": "Sestava zobrazuje řádek součtů %s Odebrat řádek součtů", "ReportGeneratedOn": "Hlášení vygenerované %s", "ReportGeneratedXAgo": "Hlášení vygenerováno před %s", + "ReportType": "Typ reportu", + "ReportWithMetadata": "Report s metadaty", + "RowLimit": "Limit řádků", + "SearchOnMatomo": "Vyhledat '%1$s' na Matomo.org", + "SeeAvailableVersions": "Prohlédnout dostupné verze", + "Segments": "Segmenty", "SharePiwikLong": "Nazdar! Zrovna jsem našel skvělý open source software Matomo!", "SharePiwikShort": "Matomo! Bezplatná webová analytika. Vlastni svá data.", "ShareThis": "Sdílet", - "ShortcutsAvailable": "Dostupné zkratky", - "ShortcutZenMode": "pro Zen mód", - "ShortcutSegmentSelector": "k otevření selektoru segmentu", - "ShortcutWebsiteSelector": "k otevření selektoru webové stránky", "ShortcutCalendar": "k otevření kalendáře (d znamená datum)", - "ShortcutSearch": "k otevření vyhledávání (f znamená hledání)", "ShortcutHelp": "pro zobrazení této nápovědy", + "ShortcutSearch": "k otevření vyhledávání (f znamená hledání)", + "ShortcutSegmentSelector": "k otevření selektoru segmentu", + "ShortcutWebsiteSelector": "k otevření selektoru webové stránky", + "ShortcutZenMode": "pro Zen mód", + "ShortcutsAvailable": "Dostupné zkratky", + "ShowExportUrl": "Zobrazit URL exportu", "ShowJSCode": "Zobrazit JavaScriptový kód ke vložení", "SkipToContent": "Přejít k obsahu", + "StandardReport": "Standartní report", "SubscribeAndBecomePiwikSupporter": "Pokračujte na zabezpečenou platební stránku (Paypal), pokud se chcete stát podpůrcem Matomou.", "SupportPiwik": "Podpořte Matomo!", + "SupportUsOn": "Podpořte nás na", + "SystemSummaryMysqlVersion": "Verze MySQL", + "SystemSummaryNActivatedPlugins": "%d aktivovaných zásuvných modulů", + "SystemSummaryNSegments": "%1$dsegmentů", + "SystemSummaryNSegmentsWithBreakdown": "%1$d segmentů (%2$s předzpracované, %3$s zpracované v reálném čase)", + "SystemSummaryNWebsites": "%d webových stránek", + "SystemSummaryPhpVersion": "Verze PHP", + "SystemSummaryPiwikVersion": "Verze Matomou", + "SystemSummaryWidget": "Souhrn systému", "TableNoData": "Žádná data", + "ThanksFromAllOfUs": "Díky vám od nás všech na Matomo!", "ThereIsNoDataForThisReport": "Pro toto hlášení nejsou k dispozici žádná data", "UnFlattenDataTable": "Hlášení je ploché %s Vytvořit hierarchický", - "RemoveTotalsRowDataTable": "Sestava zobrazuje řádek součtů %s Odebrat řádek součtů", - "AddTotalsRowDataTable": "Sestava nezobrazuje řádek součtů %s Zobrazit řádek součtů", + "UndoPivotBySubtable": "Toto hlášení bylo zaměřeno %s Vrátit zpět", "ViewAllPiwikVideoTutorials": "Zobrazit všechny návody Matomo", + "VisitStatusOrdered": "Objednáno", + "VisitStatusOrderedThenAbandoned": "Objednáno a poté opuštěn košík", + "VisitTypeReturning": "Návraty", + "VisitTypeReturningCustomer": "Věrný zákazník", "WebAnalyticsReports": "Hlášení", "YouAreUsingTheLatestVersion": "Používáte nejnovější verzi Matomou.", - "ClickRowToExpandOrContract": "Klikněte na tento řádek pro rozbalení nebo zbalení podtabulky.", - "UndoPivotBySubtable": "Toto hlášení bylo zaměřeno %s Vrátit zpět", - "NoSuchPage": "Tato stránka neexistuje", - "PageUpShortcutDescription": "dostat se na začátek stránky", - "PageDownShortcutDescription": "dostat se na konec stránky", - "PivotBySubtable": "Toto hlášení není zaměřené %1$s Zaměřit na %2$s", - "SystemSummaryWidget": "Souhrn systému", - "SystemSummaryNWebsites": "%d webových stránek", - "SystemSummaryNSegments": "%1$dsegmentů", - "SystemSummaryNSegmentsWithBreakdown": "%1$d segmentů (%2$s předzpracované, %3$s zpracované v reálném čase)", - "SystemSummaryNActivatedPlugins": "%d aktivovaných zásuvných modulů", - "SystemSummaryPiwikVersion": "Verze Matomou", - "SystemSummaryMysqlVersion": "Verze MySQL", - "SystemSummaryPhpVersion": "Verze PHP", - "QuickAccessTitle": "Výsledky hledání pro %s. Pro navigaci ve výsledcích vyhledávání použijte šipky. Zkratka: Zmáčknout 'f' pro hledání.", - "MenuEntries": "Položky menu", - "Segments": "Segmenty", - "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Aktualizace na jedno kliknutí není dostupná při nasazení Matomou na několika serverech naráz. Stáhněte prosím nejnovější verzi z %1$s a pokračujte.", - "CssDidntLoad": "Vášmu prohlížeči se nepodařilo načíst styl této stránky.", - "JsDidntLoad": "Vášmu prohlížeči se nepodařilo načíst skripty této stránky.", - "AdblockIsMaybeUsed": "Pokud používáte blokovač reklam, zakažte ho pro tyto stránky, aby Matomo správně fungoval.", - "ChangeCurrentWebsite": "Vyberte web, aktuálně vybraný web: %s", - "LeadingAnalyticsPlatformRespectsYourPrivacy": "Nejrozšířenější otevřená aplatforma pro analýzu, která respektuje vaše soukromí.", - "MacPageUp": "Fn + levá šipka", - "MacPageDown": "Fn + pravá šipka", - "ReportType": "Typ reportu", - "RowLimit": "Limit řádků", - "CustomLimit": "Vlastní limit", - "ExportFormat": "Formát exportu", - "ExpandSubtables": "Rozbalit dílčí tabulky", - "StandardReport": "Standartní report", - "FlattenReport": "Srovnat report", - "ReportWithMetadata": "Report s metadaty", - "ReadMoreOnlineGuide": "Další informace o tomto tématu naleznete v online příručce.", - "SeeAvailableVersions": "Prohlédnout dostupné verze", - "QuickLinks": "Rychlé odkazy", - "Profilable": "Profilovatelné", - "SearchOnMatomo": "Vyhledat '%1$s' na Matomo.org" + "YourDonationWillHelp": "Váš dar přímo pomůže financovat nové funkce a vylepšení této analytické platformy s otevřeným zdrojovým kódem. To znamená, že komunita bude vždy těžit z nástroje, který chrání soukromí a umožní vám mít kontrolu nad svými daty." } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/cy.json b/plugins/CoreHome/lang/cy.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/plugins/CoreHome/lang/cy.json @@ -0,0 +1 @@ +{} diff --git a/plugins/CoreHome/lang/de.json b/plugins/CoreHome/lang/de.json index 2bd616fda0..bbffdaa0a8 100644 --- a/plugins/CoreHome/lang/de.json +++ b/plugins/CoreHome/lang/de.json @@ -2,7 +2,7 @@ "CoreHome": { "AdblockIsMaybeUsed": "Für den Fall, dass Sie einen Ad-Blocker verwenden, deaktivieren Sie diesen bitte für diese Seite, um sicherzustellen, dass Matomo problemlos läuft.", "AddTotalsRowDataTable": "Der Bericht zeigt die Totalzeile nicht %s Zeige Totalzeile", - "CategoryNoData": "Keine Daten in dieser Kategorie. Probieren Sie \"Gesamte Daten einbeziehen\"", + "CategoryNoData": "Keine Daten in dieser Kategorie. Probieren Sie \"Gesamte Daten einbeziehen\".", "ChangeCurrentWebsite": "Wählen Sie eine Webseite, aktuell gewählte Webseite: %s", "ChangePeriod": "Zeitraum ändern", "ChangeVisualization": "Visualisierung ändern", @@ -16,11 +16,12 @@ "CloseWidgetDirections": "Sie können das Widget schließen, indem Sie auf das 'X' oben im Widget klicken.", "CssDidntLoad": "Ihr Browser war nicht in der Lage die Stylesheet-Definitionen der Seite zu laden.", "CustomLimit": "Eigenes Limit", - "DataForThisReportHasBeenPurged": "Die Daten für diesen Bericht sind älter als %s Monate und wurden gelöscht", + "DataForThisReportHasBeenDisabled": "Segmentierung ist für diesen Bericht momentan außer Betrieb. Bitte sehen Sie %1$sdieses FAQ%2$s ein für weitere Einzelheiten.", + "DataForThisReportHasBeenPurged": "Die Daten für diesen Bericht sind älter als %s Monate und wurden gelöscht.", "DataTableCombineDimensions": "Dimensionen werden einzeln angezeigt %s Dimensionen zusammengefasst anzeigen", - "DataTableExcludeAggregateRows": "Aggregierte Zeilen werden angezeigt %s Ausschließen", - "DataTableHowToSearch": "Drücken Sie Enter oder klicken Sie auf das Such-Symbol um eine Suche zu starten.", - "DataTableIncludeAggregateRows": "Aggregierte Zeilen sind ausgeschlossen %s Wieder anzeigen", + "DataTableExcludeAggregateRows": "Aggregierte Zeilen werden angezeigt %s Ausblenden", + "DataTableHowToSearch": "Drücken Sie Enter oder klicken Sie auf das Such-Symbol, um eine Suche zu starten", + "DataTableIncludeAggregateRows": "Aggregierte Zeilen sind ausgeblendet %s Wieder anzeigen", "DataTableShowDimensions": "Dimensionen wurden zusammengefasst %s Dimensionen separat anzeigen", "DateInvalid": "Die angegebene Kombination von Datum und Zeitraum ist ungültig. Bitte in der Datumsselektion eine gültige Auswahl treffen.", "Default": "Standard", @@ -28,8 +29,9 @@ "DonateCall1": "Die Nutzung von Matomo wird immer kostenlos bleiben, was aber nicht heißt, dass es uns nichts kostet, es zu erstellen.", "DonateCall2": "Matomo braucht Ihre dauerhafte Unterstützung um zu wachsen und zu gedeihen.", "DonateCall3": "Finden Sie, dass Matomo einen deutlichen Mehrwert für Sie oder Ihr Unternehmen hat? %1$sBitte spenden Sie%2$s oder überlegen Sie sich unsere %3$sPremium Features zu kaufen%4$s. Jeder Cent hilft.", + "EndDate": "Enddatum", "EndShortcut": "Ende", - "EngagementSubcategoryHelp1": "Der Bereich \"Engagement\" bietet Berichte, die dabei helfen, zu quantifizieren, wie viele neue und wiederkehrende Besucher Sie haben. Sie können auch Berichte einsehen, die die durchschnittliche Zeit und Anzahl der Seiten pro Besuch aufschlüsseln, sowie die Anzahl der Besuche eines Besuchers auf Ihrer Website und die übliche Anzahl an Tagen zwischen den Besuchen.", + "EngagementSubcategoryHelp1": "Der Bereich \"Engagement\" bietet Berichte, die dabei helfen, zu quantifizieren, wie viele neue und wiederkehrende Besucher Sie haben. Sie können auch Berichte einsehen, welche die durchschnittliche Zeit und Anzahl der Seiten pro Besuch aufschlüsseln, sowie die Anzahl der Besuche eines Besuchers auf Ihrer Website und die übliche Anzahl an Tagen zwischen den Besuchen.", "EngagementSubcategoryHelp2": "Dies kann Ihnen helfen, neben der Maximierung Ihrer Reichweite auch die Häufigkeit und die Interaktionsrate zu optimieren.", "EnterZenMode": "\"Zen mode\" aktivieren (Menü verstecken)", "ExceptionNotAllowlistedIP": "Sie können diese Matomo Installation nicht verwenden, weil Ihre IP-Adresse %s nicht erlaubt ist.", @@ -37,8 +39,8 @@ "ExitZenMode": "\"Zen mode\" verlassen (Menü zeigen)", "ExpandSubtables": "Erweitere Untertabellen", "ExportFormat": "Exportformat", - "ExportTooltip": "Hinweis: Um die generierte Export-URL zu verwenden, müssen Sie einen Authentifizierungstoken angeben. Sie können diese Token unter Admin -> Sicherheit -> Authentifizierungstoken konfigurieren.", - "ExportTooltipWithLink": "Hinweis: Um die generierte Export URL zu verwenden, müssen Sie einen App Token Auth angeben. Sie können diese Token in %1$s[Admin -> Security -> Auths Tokens]%2$s konfigurieren. Ersetzen Sie %3$s in der Export URL durch Ihren Auth Token. Warnung: Niemals die URL mit dem effektiven Token jemandem weitergeben.", + "ExportTooltip": "Hinweis: Um die generierte Export-URL zu verwenden, müssen Sie einen Authentifizierungstoken angeben. Sie können diese Token unter Admin -> Sicherheit -> Authentifizierungstoken konfigurieren.", + "ExportTooltipWithLink": "Hinweis: Um die generierte Export URL zu verwenden, müssen Sie einen App Token Auth angeben. Sie können diese Token in %1$s[Admin -> Security -> Auths Tokens]%2$s konfigurieren. Ersetzen Sie %3$s in der Export URL durch Ihren Auth Token. Warnung: Niemals die URL mit dem effektiven Token jemandem weitergeben.", "ExternalHelp": "Hilfe (öffnet in neuem Tab)", "FlattenDataTable": "Der Bericht ist hierarchisch strukturiert %s Flach anzeigen", "FlattenReport": "Flacher Bericht", @@ -49,7 +51,7 @@ "InjectedHostEmailBody": "Hallo, ich habe gerade versucht Matomo aufzurufen und erhielt eine Warnung, dass der Hostname unbekannt ist.", "InjectedHostEmailSubject": "Matomo wurde mit einem unbekannten Hostnamen aufgerufen: %s", "InjectedHostNonSuperUserWarning": "%1$sHier klicken um Matomo sicher zu betreten%2$s und die Warnung zu entfernen. Zusätzlich können Sie den Matomo Administrator kontaktieren und ihn auf dieses Problem hinweisen (%3$sHier klicken um eine E-Mail zu senden%4$s).", - "InjectedHostSuperUserWarning": "Matomo könnte falsch konfiguriert sein (zum Beispiel, wenn Matomo vor kurzem auf einen neuen Server oder eine neue URL umgezogen ist). Sie können entweder %1$shier klicken und %2$s als gültigen Hostnamen hinzufügen (wenn Sie ihm vertrauen)%3$s, oder %4$shier klicken um Matomo unter %5$s sicher zu betreten%6$s", + "InjectedHostSuperUserWarning": "Matomo könnte falsch konfiguriert sein (zum Beispiel, wenn Matomo vor kurzem auf einen neuen Server oder eine neue URL umgezogen ist). Sie können entweder %1$shier klicken und %2$s als gültigen Hostnamen hinzufügen (wenn Sie ihm vertrauen)%3$s, oder %4$shier klicken, um zu %5$s zu gehen und Matomo sicher zu betreten%6$s.", "InjectedHostWarningIntro": "Sie betreten Matomo aktuell von %1$s, allerdings wurde Matomo so konfiguriert, dass es unter dieser Adresse läuft: %2$s.", "JavascriptDisabled": "JavaScript muss aktiviert sein, um die Standardansicht von Matomo zu benutzen.<br>Es scheint jedoch so, als wäre JavaScript bei Ihnen deaktiviert bzw. würde nicht von Ihrem Browser unterstützt.<br>Um die Standardansicht zu benutzen, aktivieren Sie JavaScript in Ihren Browseroptionen und %1$sversuchen Sie es erneut%2$s.<br>", "JsDidntLoad": "Ihr Browser war nicht in der Lage die Skripte der Seite zu laden.", @@ -77,7 +79,7 @@ "ReportGeneratedXAgo": "Bericht erzeugt vor %s", "ReportType": "Art des Berichts", "ReportWithMetadata": "Bericht mit Metadaten", - "ReportingCategoryHelpPrefix": "Wie kann die \"%1$s > %2$s\" Berichtsseite mir helfen?", + "ReportingCategoryHelpPrefix": "Wie kann die \"%1$s > %2$s\" Berichtsseite mir helfen?", "RowLimit": "Zeilenlimit", "SearchOnMatomo": "Suche '%1$s' auf Matomo.org", "SeeAvailableVersions": "Zeige verfügbare Versionen", @@ -97,7 +99,8 @@ "SkipToContent": "Zum Inhalt wechseln", "SoftwareSubcategoryHelp": "Der Softwarebereich zeigt das Betriebssystem, Browser und Plugins welche Ihre Besucher verwenden, um Ihre Seite zu besuchen, sodass Sie Ihre Seite so optimieren können, dass sie mit den meisten Konfigurationen vollständig kompatibel ist.", "StandardReport": "Standard Bericht", - "SubscribeAndBecomePiwikSupporter": "Weiter zur sicheren Seite für Kreditkartenzahlung (Paypal) um ein Unterstützer von Matomo zu werden.", + "StartDate": "Anfangsdatum", + "SubscribeAndBecomePiwikSupporter": "Weiter zur sicheren Webseite für Kreditkartenzahlung (Paypal), um ein Unterstützer von Matomo zu werden!", "SupportPiwik": "Unterstützen Sie Matomo!", "SupportUsOn": "Unterstützen Sie uns auf", "SystemSummaryMysqlVersion": "MySQL-Version", diff --git a/plugins/CoreHome/lang/el.json b/plugins/CoreHome/lang/el.json index 2b9b86d5af..c63276a414 100644 --- a/plugins/CoreHome/lang/el.json +++ b/plugins/CoreHome/lang/el.json @@ -16,6 +16,7 @@ "CloseWidgetDirections": "Μπορείτε να κλείσετε αυτή τη λειτουργία κάνοντας κλικ στο εικονίδιο 'X' στην κορυφή του widget.", "CssDidntLoad": "Το πρόγραμμα πλοήγησής σας δεν κατέστη δυνατό να φορτώσει το στυλ της σελίδας.", "CustomLimit": "Προσαρμοσμένο όριο", + "DataForThisReportHasBeenDisabled": "Η τμηματοποίηση είναι αυτή τη στιγμή ανενεργή για αυτή την αναφορά. Δείτε τις %1$sΣυχνές Ερωτήσεις-Απαντήσεις%2$s για περισσότερες πληροφορίες.", "DataForThisReportHasBeenPurged": "Τα δεδομένα για αυτή την αναφορά είναι περισσότερα από %s μήνες και κόπηκαν.", "DataTableCombineDimensions": "Οι διαστάσεις εμφανίζονται ξεχωριστά %s Εμφάνιση των διαστάσεων συνδυασμένα", "DataTableExcludeAggregateRows": "Οι συγκεντρωτικές εγγραφές είναι ορατές %s Απόκρυψη", @@ -28,6 +29,7 @@ "DonateCall1": "Το Matomo θα είναι πάντα δωρεάν, αλλά αυτό δεν σημαίνει ότι δεν κοστίζει τίποτα για να φτιαχτεί.", "DonateCall2": "Το Matomo χρειάζεται τη συνεχή υποστήριξή σας για να αναπτυχθεί και να ευδοκιμήσει.", "DonateCall3": "Εάν θεωρείτε ότι το Matomo έχει προσθέσει σημαντική αξία στην επιχείρηση ή στο εγχείρημά σας, %1$sπαρακαλούμε σκεφτείτε μια δωρεά%2$s ή %3$sπρομηθευτείτε ένα χαρακτηριστικό επί πληρωμή%4$s. Κάθε λεπτό βοηθάει.", + "EndDate": "Ημερομηνία Λήξης", "EndShortcut": "Τέλος", "EngagementSubcategoryHelp1": "Το τμήμα Ενασχόλησης παρέχει αναφορές που σας βοηθούν να ποσοτικοποιήσετε τον αριθμό των νέων και επιστρεφόμενων επισκεπτών. Μπορείτε να δείτε αναφορές που τμηματοποιούν τον μέσο χρόνο και τον αριθμό των σελίδων ανά επίσκεψη, καθώς και τον αριθμό των φορών που ένας επισκέπτης ήρθε στον ιστοτόπο σας και τον πιο συνηθισμένο αριθμό ημερών μεταξύ επισκέψεων.", "EngagementSubcategoryHelp2": "Αυτό μπορεί να σας βοηθήσει να βελτιστοποιήσετε την συχνότητα και τις επισκέψεις με έντονη διάδραση μεγιστοποιώντας παράλληλα και το εύρος επικοινωνίας σας.", @@ -97,6 +99,7 @@ "SkipToContent": "Μετάβαση στο περιεχόμενο", "SoftwareSubcategoryHelp": "Το τμήμα Λογισμικού σας δείχνει τα λειτουργικά συστήματα, φυλλομετρητές και πρόσθετα που χρησιμοποιούν οι επισκέπτες σας για την προσπέλαση στον ιστοτόπο σας ώστε να βελτιστοποιήσετε τον ιστοτόπο σας έτσι ώστε να εξασφαλίσετε ότι είναι συμβατός με τις περισσότερο δημοφιλείς παραμετροποιήσεις.", "StandardReport": "Κανονική αναφορά", + "StartDate": "Ημερομηνία Έναρξης", "SubscribeAndBecomePiwikSupporter": "Προχωρήστε σε μια ασφαλή σελίδα πληρωμής με πιστωτική κάρτα (Paypal) για να γίνετε Υποστηρικτής του Matomo!", "SupportPiwik": "Στηρίξτε το Matomo!", "SupportUsOn": "Υποστηρίξτε μας στο", diff --git a/plugins/CoreHome/lang/en.json b/plugins/CoreHome/lang/en.json index ee3c5be7ee..e49bcf7889 100644 --- a/plugins/CoreHome/lang/en.json +++ b/plugins/CoreHome/lang/en.json @@ -11,6 +11,7 @@ "CloseWidgetDirections": "You can close this widget by clicking on the 'X' icon at the top of the widget.", "ChooseX": "Choose %1$s", "DataForThisReportHasBeenPurged": "The data for this report is more than %s months old and has been purged.", + "DataForThisReportHasBeenDisabled": "Segmentation is currently disabled for this report. Please check %1$sthis FAQ%2$s for more details.", "DataTableExcludeAggregateRows": "Aggregate rows are shown %s Hide them", "DataTableIncludeAggregateRows": "Aggregate rows are hidden %s Show them", "DataTableHowToSearch": "Press enter or click the search icon to search", @@ -124,6 +125,8 @@ "SoftwareSubcategoryHelp": "The Software section shows the operating systems, browsers and plugins that your visitors are using to access the site so that you can optimise your site to ensure it is fully compatible with the most popular configurations.", "EngagementSubcategoryHelp1": "The Engagement section provides reports that help to quantify how many new and returning visitors you get. You can also review reports that break down the average time and number of pages per visit, as well as the number of times a visitor has been to your site and the most common number of days between visits.", "EngagementSubcategoryHelp2": "This can help you to optimise for frequency and high-interaction visits in addition to maximising your reach.", - "PeriodHasOnlyRawData": "It looks like reports for this period have not been processed yet. Do you want to see what's happening now? Check out the %1$sVisits log%2$s or choose a different date period until the reports are generated." + "PeriodHasOnlyRawData": "It looks like reports for this period have not been processed yet. Do you want to see what's happening now? Check out the %1$sVisits log%2$s or choose a different date period until the reports are generated.", + "StartDate": "Start Date", + "EndDate": "End Date" } } diff --git a/plugins/CoreHome/lang/es-ar.json b/plugins/CoreHome/lang/es-ar.json index 3681084f8c..13c5508c8d 100644 --- a/plugins/CoreHome/lang/es-ar.json +++ b/plugins/CoreHome/lang/es-ar.json @@ -1,128 +1,132 @@ { "CoreHome": { - "CategoryNoData": "No hay datos en esta categoría. Intentá \"Incluir toda la población\".", - "ChangeVisualization": "Cambiar la visualización", + "AdblockIsMaybeUsed": "En el caso de que estés usando un bloqueador de publicidad, por favor, deshabilitalo para este sitio, para asegurarte de que Matomo funciona sin ningún problema.", + "AddTotalsRowDataTable": "El informe no muestra la fila de totales %s Mostrar la fila de totales", + "CategoryNoData": "No hay datos en esta categoría. Intente \"Incluir toda la población\".", + "ChangeCurrentWebsite": "Elegí un sitio web, actualmente está elegido: %s", "ChangePeriod": "Cambiar período", + "ChangeVisualization": "Cambiar la visualización", "CheckForUpdates": "Buscar actualizaciones", - "CheckPiwikOut": "¡Probá Matomo!", + "CheckPiwikOut": "¡Pruebe Matomo!", + "ChooseX": "Elegí %1$s", + "ClickRowToExpandOrContract": "Hacé clic para expandir o contraer la subtabla.", "ClickToEditX": "Hacé clic para editar %s", - "ClickToSeeFullInformation": "Hacé clic para ver la información completa", - "CloseSearch": "Cerrar búsqueda", + "ClickToSeeFullInformation": "Hacé Click para ver la información completa", + "CloseSearch": "Cerrar search", "CloseWidgetDirections": "Podés cerrar este widget haciendo clic en el icono \"X\" en la parte superior del widget.", - "ChooseX": "Elegí %1$s", + "CssDidntLoad": "Tu navegador web no fue capaz de cargar el estilo de esta página.", + "CustomLimit": "Límite personalizado", + "DataForThisReportHasBeenDisabled": "La segmentación se encuentra actualmente \"disabled\" para éste report. Por favor visite %1$seste FAQ%2$s para mas detalles.", "DataForThisReportHasBeenPurged": "Los datos para este informe tienen más de %s meses de antigüedad y han sido eliminados.", + "DataTableCombineDimensions": "Las dimensiones se muestran separadamente %s Mostrar dimensiones combinadas", "DataTableExcludeAggregateRows": "Se muestran las filas acumuladas %s Ocultarlas", - "DataTableIncludeAggregateRows": "Se ocultan las filas agregadas %s Mostrarlas", "DataTableHowToSearch": "Presioná \"Enter\" o hacé clic en el ícono de búsqueda para buscar", + "DataTableIncludeAggregateRows": "Se ocultan las filas agregadas %s Mostrarlas", "DataTableShowDimensions": "Las dimensiones están combinadas %s Mostrar dimensiones separadamente", - "DataTableCombineDimensions": "Las dimensiones se muestran separadamente %s Mostrar dimensiones combinadas", "DateInvalid": "La combinación ofrecida de fecha y período no es válida. Por favor, elegí una fecha válida en el selector de fechas.", "Default": "predeterminado", + "DevicesSubcategoryHelp": "La sección de dispositivos te ayuda a entender la tecnología que tus visitantes están usando para acceder a tu sitio web. Vas a ver informes sobre el tipo de dispositivo y modelos específicos para habilitarte a optimizar tu sitio para los dispositivos más populares.", "DonateCall1": "Matomo nunca te costará nada para usarlo, pero eso no significa que no nos cueste hacerlo.", "DonateCall2": "Matomo necesita de tu contínuo apoyo para crecer y prosperar.", "DonateCall3": "Si sentís que Matomo agregó valor significativo a tu negocio o emprendimiento, %1$spor favor, considerá donar%2$s o %3$scomprar una función prémium%4$s. Cada centavo cuenta.", + "EndDate": "Fecha de finalización", "EndShortcut": "Fin", + "EngagementSubcategoryHelp1": "La sección de compromiso ofrece informes que ayudan a cuantificar cuántos visitantes nuevos y habitués tenés. También podés revisar informes que delimitan el tiempo promedio y número de páginas por visitas, así como el número de veces que un visitante estuvo en tu sitio y la cantidad más común de días entre visitas.", + "EngagementSubcategoryHelp2": "Esto te puede ayudar a optimizar la frecuencia de visitas y su alta interacción, además de maximizar tu alcance.", "EnterZenMode": "Entrar al modo Zen (ocultar los menús)", - "ExitZenMode": "Salir del modo Zen (mostrar los menús)", "ExceptionNotAllowlistedIP": "No podés usar este Matomo ya que tu dirección IP %s no está permitida.", "ExcludeRowsWithLowPopulation": "Se muestran todas las filas %s Excluir baja población", + "ExitZenMode": "Salir del modo Zen (mostrar los menús)", + "ExpandSubtables": "Expandir subtablas", + "ExportFormat": "Exportar formato", + "ExportTooltip": "Nota: para usar la dirección web de exportación generada, vas a necesitar especificar una aplicación de autenticación de token. Podés configurar estos tokens en \"Administración\" > \"Seguridad\" > \"Autenticaciones de tokens\".", + "ExportTooltipWithLink": "Nota: para usar la dirección web de exportación generada, vas a necesitar una aplicación de autenticación de token. Podés configurar estos tokens en %1$s[\"Administración\" > \"Seguridad\" > \"Autenticaciones de tokens\"]%2$s. Reemplazá %3$s en la dirección web de exportación por tu token de autenticación. Advertencia: nunca compartas la dirección web con el token real con nadie.", "ExternalHelp": "Ayuda (se abre en una nueva pestaña)", "FlattenDataTable": "Este informe es jerárquico %s Hacelo plano", + "FlattenReport": "Aplanar informe", "FormatMetrics": "Formatear mediciones", - "ShowExportUrl": "Mostrar dirección web de exportación", "HideExportUrl": "Ocultar dirección web de exportación", "HomeShortcut": "Página principal", - "SupportUsOn": "Apoyanos en", "IncludeRowsWithLowPopulation": "Se ocultan las filas con baja población %s Mostrar todas las filas", "InjectedHostEmailBody": "Hola, hoy intenté acceder a Matomo pero encontré la advertencia sobre nombre de dominio (\"hostname\") desconocido.", "InjectedHostEmailSubject": "Se accedió a Matomo desde un servidor desconocido: %s", "InjectedHostNonSuperUserWarning": "%1$sHacé clic acá para acceder de forma segura a Matomo%2$s y quitar esta advertencia. Podés contactarte con tu administrador de Matomo y notificarlo acerca de este problema (%3$shacé clic acá para enviarle un correo electrónico%4$s).", "InjectedHostSuperUserWarning": "Matomo puede estar desconfigurado (por ejemplo, si Matomo fue mudado recientemente a un nuevo servidor o cambió su dirección web). Podés, o bien %1$shacer clic acá y agregar %2$s como servidores válidos Matomo (si los considerás confiables)%3$s, o bien %4$shacé clic acá y andá a %5$s para acceder de forma segura a Matomo%6$s.", "InjectedHostWarningIntro": "Está accediendo a Matomo desde %1$s, pero Matomo fue configurado para ejecutarse en esta dirección: %2$s.", - "JavascriptDisabled": "JavaScript debe estar habilitado para que puedas usar la vista estándar de Matomo .<br \/>Sin embargo, parece que JavaScript, o bien está deshabilitado, o bien no es soportado por tu navegador. <br \/>Para usar la vista estándar, habilitá JavaScript cambiando la configuración de tu navegador, luego%1$sintentá nuevamente%2$s.<br \/>", - "VisitStatusOrdered": "Ordenado", - "VisitStatusOrderedThenAbandoned": "Ordenado, entonces changuito abandonado", - "VisitTypeReturning": "Regresos", - "VisitTypeReturningCustomer": "Cliente que vuelve", + "JavascriptDisabled": "JavaScript debe estar habilitado para que puedas usar la vista estándar de Matomo .<br />Sin embargo, parece que JavaScript, o bien está deshabilitado, o bien no es soportado por tu navegador. <br />Para usar la vista estándar, habilitá JavaScript cambiando la configuración de tu navegador, luego%1$sintentá nuevamente%2$s.<br />", + "JsDidntLoad": "Tu navegador web no fue capaz de cargar los scripts de esta página.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "La plataforma abierta líder de análisis que respeta tu privacidad.", + "MacPageDown": "\"Fn\" + flecha derecha", + "MacPageUp": "\"Fn\" + flecha izquierda", "MainNavigation": "Navegación principal", - "YourDonationWillHelp": "Tu donación ayudará directamente a crear nuevas funciones y mejoras en esta plataforma de análisis web de código abierto. Esto significa que la comunidad siempre se beneficiará de una herramienta que protege la privacidad y que te permite tener el control de tus datos.", - "ThanksFromAllOfUs": "¡Gracias de parte de todos nosotros en Matomo!", "Menu": "Menú", + "MenuEntries": "Entradas del menú", "NoPrivilegesAskPiwikAdmin": "Iniciaste sesión como \"%1$s\", pero parece que no tenés ningún permiso configurado en Matomo. %2$sConsultá al administrador de tu Matomo (hacé clic para enviarle un correo electrónico)%3$s para que te dé acceso de lectura al sitio web.", + "NoSuchPage": "Esta página no existe", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "La actualización de un clic no está disponible, ya que estás usando Matomo con múltiples servidores. Por favor, descargá la última versión desde %1$s para continuar.", "OnlyForSuperUserAccess": "Este widget se muestra en el panel principal sólo a los usuarios que tengan acceso de súper usuario.", + "PageDownShortcutDescription": "para ir al fin de la página", + "PageUpShortcutDescription": "para ir al comienzo de la página", + "PeriodHasOnlyRawData": "Parece que todavía no se procesaron informes para este período. ¿Querés saber lo que está pasando ahora? Revisá el %1$sregistro de visitas%2$s o elegí un período de fechas diferentes hasta que se generen los informes.", "PeriodRange": "Rango", + "PivotBySubtable": "Este informe no fue pivotado %1$s Pivote por %2$s", + "Profilable": "Perfilable", + "QuickAccessTitle": "Buscar %s. Usá las teclas de flechas para navegar entre los resultados de la búsqueda. Atajo: presioná \"f\" para buscar.", + "QuickLinks": "Enlaces rápidos", + "ReadMoreOnlineGuide": "Leé más sobre este tema en la guía en línea.", + "RemoveTotalsRowDataTable": "El informe muestra la fila de totales %s Quitar la fila de totales", "ReportGeneratedOn": "Informe generado el %s", "ReportGeneratedXAgo": "Informe generado hace %s", + "ReportType": "Tipo de informe", + "ReportWithMetadata": "Informe con metadatos", + "ReportingCategoryHelpPrefix": "¿Cómo puede ayudarme la página de informe \"%1$s > %2$s\"?", + "RowLimit": "Límite fe fila", + "SearchOnMatomo": "Buscá \"%1$s\" en matomo.org", + "SeeAvailableVersions": "Ver las versiones disponibles", + "Segments": "Segmentos", "SharePiwikLong": "¡Hola! Acabo de encontrar otro software libre de calidad: ¡Matomo!\n\nMatomo te permite rastrear visitantes en tu sitio web, gratis. ¡Deberían probarlo!", "SharePiwikShort": "Matomo: análisis web gratis y de código abierto. Conservá tus propios datos.", "ShareThis": "Compartilo", - "ShortcutsAvailable": "Atajos disponibles", - "ShortcutZenMode": "para el modo Zen", - "ShortcutSegmentSelector": "para abrir el selector de Segmento", - "ShortcutWebsiteSelector": "para abrir el selector de Sitio web", "ShortcutCalendar": "para abrir el calendario (\"d\" significa \"fecha\")", - "ShortcutSearch": "para abrir la búsqueda (\"f\" significa \"buscar\")", "ShortcutHelp": "para mostrar esta ayuda", + "ShortcutSearch": "para abrir la búsqueda (\"f\" significa \"buscar\")", + "ShortcutSegmentSelector": "para abrir el selector de Segmento", + "ShortcutWebsiteSelector": "para abrir el selector de Sitio web", + "ShortcutZenMode": "para el modo Zen", + "ShortcutsAvailable": "Atajos disponibles", + "ShowExportUrl": "Mostrar dirección web de exportación", "ShowJSCode": "Mostrar el código JavaScript para insertar", "SkipToContent": "Pasar al contenido", + "SoftwareSubcategoryHelp": "La sección de software muestra los sistemas operativos, navehadores web y plugins que tus visitantes están usando para acceder al sitio, así podés optimizarlo para asegurarte de que es totalmente compatible con las configuraciones más populares.", + "StandardReport": "Informe estándar", + "StartDate": "Fecha de inicio", "SubscribeAndBecomePiwikSupporter": "Continuar a una página de pago con tarjeta de crédito segura (PayPal) ¡para ser un colaborador de Matomo!", "SupportPiwik": "¡Apoyá a Matomo!", + "SupportUsOn": "Apoyanos en", + "SystemSummaryMysqlVersion": "Versión de MySQL", + "SystemSummaryNActivatedPlugins": "%d plugins activos", + "SystemSummaryNSegments": "%1$d segmentos", + "SystemSummaryNSegmentsWithBreakdown": "%1$d segmentos (%2$s preprocesados, %3$s procesados en tiempo real)", + "SystemSummaryNWebsites": "%d sitios web", + "SystemSummaryPhpVersion": "Versión de PHP", + "SystemSummaryPiwikVersion": "Versión de Matomo", + "SystemSummaryWidget": "Resumen del sistema", "TableNoData": "Sin datos para esta tabla.", + "TechDeprecationWarning": "A partir de la versión Matomo %1$s, Matomo no dará soporte para %2$s. Para más información %3$s visite nuestro blog.%4$s", + "ThanksFromAllOfUs": "¡Gracias de parte de todos nosotros en Matomo!", "ThereIsNoDataForThisReport": "No hay datos para este informe.", "UnFlattenDataTable": "Este informe es plano %s Hacelo jerárquico", - "RemoveTotalsRowDataTable": "El informe muestra la fila de totales %s Quitar la fila de totales", - "AddTotalsRowDataTable": "El informe no muestra la fila de totales %s Mostrar la fila de totales", - "ViewAllPiwikVideoTutorials": "Ver todos los videos tutoriales de Matomo", - "WebAnalyticsReports": "Informes de análisis web", - "YouAreUsingTheLatestVersion": "¡Estás usando la última versión de Matomo!", - "ClickRowToExpandOrContract": "Hacé clic para expandir o contraer la subtabla.", "UndoPivotBySubtable": "Este informe fue pivotado %s Deshacerlo", - "NoSuchPage": "Esta página no existe", - "PageUpShortcutDescription": "para ir al comienzo de la página", - "PageDownShortcutDescription": "para ir al fin de la página", - "PivotBySubtable": "Este informe no fue pivotado %1$s Pivote por %2$s", - "SystemSummaryWidget": "Resumen del sistema", - "SystemSummaryNWebsites": "%d sitios web", - "SystemSummaryNSegments": "%1$d segmentos", - "SystemSummaryNSegmentsWithBreakdown": "%1$d segmentos (%2$s preprocesados, %3$s procesados en tiempo real)", - "SystemSummaryNActivatedPlugins": "%d plugins activos", - "SystemSummaryPiwikVersion": "Versión de Matomo", - "SystemSummaryMysqlVersion": "Versión de MySQL", - "SystemSummaryPhpVersion": "Versión de PHP", - "QuickAccessTitle": "Buscar %s. Usá las teclas de flechas para navegar entre los resultados de la búsqueda. Atajo: presioná \"f\" para buscar.", - "MenuEntries": "Entradas del menú", - "Segments": "Segmentos", - "OneClickUpdateNotPossibleAsMultiServerEnvironment": "La actualización de un clic no está disponible, ya que estás usando Matomo con múltiples servidores. Por favor, descargá la última versión desde %1$s para continuar.", - "CssDidntLoad": "Tu navegador web no fue capaz de cargar el estilo de esta página.", - "JsDidntLoad": "Tu navegador web no fue capaz de cargar los scripts de esta página.", - "AdblockIsMaybeUsed": "En el caso de que estés usando un bloqueador de publicidad, por favor, deshabilitalo para este sitio, para asegurarte de que Matomo funciona sin ningún problema.", - "ChangeCurrentWebsite": "Elegí un sitio web, actualmente está elegido: %s", - "LeadingAnalyticsPlatformRespectsYourPrivacy": "La plataforma abierta líder de análisis que respeta tu privacidad.", - "MacPageUp": "\"Fn\" + flecha izquierda", - "MacPageDown": "\"Fn\" + flecha derecha", - "ReportType": "Tipo de informe", - "RowLimit": "Límite fe fila", - "CustomLimit": "Límite personalizado", - "ExportFormat": "Exportar formato", - "ExportTooltip": "Nota: para usar la dirección web de exportación generada, vas a necesitar especificar una aplicación de autenticación de token. Podés configurar estos tokens en \"Administración\" > \"Seguridad\" > \"Autenticaciones de tokens\".", - "ExportTooltipWithLink": "Nota: para usar la dirección web de exportación generada, vas a necesitar una aplicación de autenticación de token. Podés configurar estos tokens en %1$s[\"Administración\" > \"Seguridad\" > \"Autenticaciones de tokens\"]%2$s. Reemplazá %3$s en la dirección web de exportación por tu token de autenticación. Advertencia: nunca compartas la dirección web con el token real con nadie.", - "ExpandSubtables": "Expandir subtablas", - "StandardReport": "Informe estándar", - "FlattenReport": "Aplanar informe", - "ReportWithMetadata": "Informe con metadatos", - "ReadMoreOnlineGuide": "Leé más sobre este tema en la guía en línea.", - "SeeAvailableVersions": "Ver las versiones disponibles", - "QuickLinks": "Enlaces rápidos", - "Profilable": "Perfilable", - "SearchOnMatomo": "Buscá \"%1$s\" en matomo.org", - "ReportingCategoryHelpPrefix": "¿Cómo puede ayudarme la página de informe \"%1$s > %2$s\"?", + "ViewAllPiwikVideoTutorials": "Ver todos los videos tutoriales de Matomo", + "VisitStatusOrdered": "Ordenado", + "VisitStatusOrderedThenAbandoned": "Ordenado, entonces changuito abandonado", + "VisitTypeReturning": "Regresos", + "VisitTypeReturningCustomer": "Cliente que vuelve", "VisitorsCategoryHelp1": "Las páginas de visitantes te dicen cosas sobre quiénes son los visitantes. Cosas como desde dónde vienen, qué dispositivos y navegadores web están usando y cuándo generalmente visitan tu sitio web. Asimilá, en el agregado, quién es tu audiencia, y buscá valores atípicos para ver cómo podría crecer.", "VisitorsCategoryHelp2": "Además de la información general sobre tus visitantes, también podés usar el %1$sregistro de visitas%2$s para ver qué ocurrió con cada visita individual.", "VisitorsOverviewHelp": "El pantallazo de los visitantes te ayuda a entender la popularidad de tu sitio web. Lo hace ofreciendo gráficos que muestran cuántas visitas está recibiendo tu sitio sobre un período seleccionado y el nivel promedio de compromiso con las funciones claves, como las búsquedas y las descargas.", - "DevicesSubcategoryHelp": "La sección de dispositivos te ayuda a entender la tecnología que tus visitantes están usando para acceder a tu sitio web. Vas a ver informes sobre el tipo de dispositivo y modelos específicos para habilitarte a optimizar tu sitio para los dispositivos más populares.", - "SoftwareSubcategoryHelp": "La sección de software muestra los sistemas operativos, navehadores web y plugins que tus visitantes están usando para acceder al sitio, así podés optimizarlo para asegurarte de que es totalmente compatible con las configuraciones más populares.", - "EngagementSubcategoryHelp1": "La sección de compromiso ofrece informes que ayudan a cuantificar cuántos visitantes nuevos y habitués tenés. También podés revisar informes que delimitan el tiempo promedio y número de páginas por visitas, así como el número de veces que un visitante estuvo en tu sitio y la cantidad más común de días entre visitas.", - "EngagementSubcategoryHelp2": "Esto te puede ayudar a optimizar la frecuencia de visitas y su alta interacción, además de maximizar tu alcance.", - "PeriodHasOnlyRawData": "Parece que todavía no se procesaron informes para este período. ¿Querés saber lo que está pasando ahora? Revisá el %1$sregistro de visitas%2$s o elegí un período de fechas diferentes hasta que se generen los informes." + "WebAnalyticsReports": "Informes de análisis web", + "YouAreUsingTheLatestVersion": "¡Estás usando la última versión de Matomo!", + "YourDonationWillHelp": "Tu donación ayudará directamente a crear nuevas funciones y mejoras en esta plataforma de análisis web de código abierto. Esto significa que la comunidad siempre se beneficiará de una herramienta que protege la privacidad y que te permite tener el control de tus datos." } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/es.json b/plugins/CoreHome/lang/es.json index 2cce146f21..11c0bbc03a 100644 --- a/plugins/CoreHome/lang/es.json +++ b/plugins/CoreHome/lang/es.json @@ -24,7 +24,7 @@ "DataTableShowDimensions": "Dimensiones están combinadas %s Mostrarlas separadamente", "DateInvalid": "La combinación de fecha y periodo seleccionados es inválido. Por favor escoja una fecha válida en el selector de fechas.", "Default": "predeterminado", - "DonateCall1": "Matomo siempre será gratis, pero eso no significa que no nos cueste nada hacerlo.", + "DonateCall1": "Matomo siempre será gratis, pero eso no significa que no nos cueste nada hacerlo.", "DonateCall2": "Matomo necesita su apoyo para crecer y prosperar.", "DonateCall3": "Si sientes que Matomo ha supuesto un valor añadido para tu negocio o emprendimiento, %1$spor favor, considera hacer una donación%2$s o %3$sadquirir una funcionalidad premium%4$s. Cada centavo ayudará.", "EndShortcut": "Fin", diff --git a/plugins/CoreHome/lang/fi.json b/plugins/CoreHome/lang/fi.json index 55e3c31d43..f56c47d625 100644 --- a/plugins/CoreHome/lang/fi.json +++ b/plugins/CoreHome/lang/fi.json @@ -1,31 +1,41 @@ { "CoreHome": { + "AdblockIsMaybeUsed": "Jos käytät mainostenestoa (ad blocker), poista se käytöstä tällä sivulla, jotta Matomo toimii ongelmitta.", + "AddTotalsRowDataTable": "Tämä raportti ei näytä yhtenvetoriviä %s Näytä yhteenvetorivi", "CategoryNoData": "Tässä kategoriassa ei ole tietoja. Kokeile linkkiä \"Kaikki esiintymät\".", - "ChangeVisualization": "Vaihda visualisaatio", + "ChangeCurrentWebsite": "Valitse sivusto, nyt valittuna %s", "ChangePeriod": "Vaihda aikaväliä", + "ChangeVisualization": "Vaihda visualisaatio", "CheckForUpdates": "Tarkista päivitykset", "CheckPiwikOut": "Tutustu Matomoon!", + "ChooseX": "Valitse %1$s", + "ClickRowToExpandOrContract": "Klikkaa tätä riviä avataksesi tai sulkeaksesi alataulukon.", "ClickToEditX": "Muokkaa %s klikkaamalla", "ClickToSeeFullInformation": "Klikkaa nähdäksesi lisätietoja", "CloseSearch": "Sulje haku", "CloseWidgetDirections": "Voit sulkea tämän widget-käyttöliittymän klikkaamalla \"X\"-ikonia käyttöliittymän yläreunassa.", - "ChooseX": "Valitse %1$s", + "CssDidntLoad": "Selaimesi ei saanut ladattua tämän sivun tyyliä.", + "CustomLimit": "Muokattu rajaus", "DataForThisReportHasBeenPurged": "Tämän raportin data on yli %s kuukautta vanhaa ja on poistettu.", "DataTableExcludeAggregateRows": "Yhdistetyt rivit ovat näkyvillä %s Piilota", - "DataTableIncludeAggregateRows": "Yhdistetyt rivit on piilotettu %s Näytä", "DataTableHowToSearch": "Hae painamalla enter tai klikkaamalla hakukuvaketta", + "DataTableIncludeAggregateRows": "Yhdistetyt rivit on piilotettu %s Näytä", "Default": "oletus", "DonateCall1": "Matomo on sinulle aina ilmainen, mutta tämä ei tarkoita sitä, että sen luominen olisi ilmaista meille.", "DonateCall2": "Matomo tarvitsee sinun tukeasi kasvaakseen ja menestyäkseen.", "DonateCall3": "Jos Matomosta on ollut merkittävää hyötyä liiketoiminnallesi, %1$sharkitse lahjoittamista%2$s tai %3$spremium-toimintojen ostamista%4$s. Jokainen euro auttaa.", + "EndDate": "Lopetuspäivä", "EndShortcut": "Loppuun", "EnterZenMode": "Siirry Zen-tilaan (piilota valikot)", - "ExitZenMode": "Poistu Zen-tilasta (näytä valikot)", + "ExceptionNotAllowlistedIP": "Et voi käyttää tätä Matomo-instanssia, koska IP-osoitteesi %s ei ole sallittu.", "ExcludeRowsWithLowPopulation": "Kaikki rivit näytetään %s Piilota vajaat rivit", + "ExitZenMode": "Poistu Zen-tilasta (näytä valikot)", + "ExpandSubtables": "Avaa alataulut", + "ExportFormat": "Vientimuoto", "ExternalHelp": "Apua (aukeaa uudessa ikkunassa)", "FlattenDataTable": "Tämä raportti on hierarkinen %s Muuta tasaiseksi", + "FlattenReport": "Litistä raportti", "FormatMetrics": "Muotoile mittarit", - "ShowExportUrl": "Näytä vienti-URL", "HideExportUrl": "Piilota vienti-URL", "HomeShortcut": "Alkuun", "IncludeRowsWithLowPopulation": "Vajaat rivit on piilotettu %s Näytä kaikki rivit", @@ -34,74 +44,68 @@ "InjectedHostNonSuperUserWarning": "%1$sKlikkaa tästä avataksesi Matomo turvallisesti%2$s ja poistaaksesi tämä varoitus. Voit myös ottaa yhteyttä Matomon ylläpitäjään ja ilmoittaa ongelmasta (%3$sklikkaa tästä lähettääksesi sähköpostia%4$s).", "InjectedHostSuperUserWarning": "Matomo saattaa olla väärin asennettu (esim. jos Matomo on hiljattain siirretty uuteen serveriin tai URL:ään). Voit joko %1$sklikata tästä ja lisätä %2$s ja lisätä päteväksi Matomo isäntänimeksi (jos luotat siihen)%3$s, tai %4$sklikata tästä ja %5$s siirtyäksesi Matomoon turvallisesti%6$s.", "InjectedHostWarningIntro": "Käytät Matomoa osoitteesta %1$s, mutta Matomo on konfiguroitu ajettavaksi tässä osoitteessa: %2$s.", - "JavascriptDisabled": "JavaScript on oltava käytössä, jotta Matomoa voi käyttää standardinäkymässä.<br \/>Vaikuttaa kuitenkin siltä, ettei JavaScript ole käytössä tai tuettu selaimessasi.<br \/>Käyttääksesi standardinäkymää, ota JavaScript käyttöön selaimen asetuksista, ja %1$syritä uudelleen%2$s.<br \/>", - "VisitStatusOrdered": "Ostettu", - "VisitStatusOrderedThenAbandoned": "Ostettu, sitten hylätty ostoskori", - "VisitTypeReturning": "Palaava", - "VisitTypeReturningCustomer": "Palaava asiakas", + "JavascriptDisabled": "JavaScript on oltava käytössä, jotta Matomoa voi käyttää standardinäkymässä.<br />Vaikuttaa kuitenkin siltä, ettei JavaScript ole käytössä tai tuettu selaimessasi.<br />Käyttääksesi standardinäkymää, ota JavaScript käyttöön selaimen asetuksista, ja %1$syritä uudelleen%2$s.<br />", + "JsDidntLoad": "Selaimesi ei saanut ladattua tämän sivun skriptejä.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "Johtava avoimen lähdekoodin analytiikka-alusta, joka kunnioittaa yksityisyyttäsi.", + "MacPageDown": "Fn + Nuoli oikealle", + "MacPageUp": "Fn + Nuoli vasemmalle", "MainNavigation": "Päänavigointi", "Menu": "Valikko", + "MenuEntries": "Valikon sisältö", "NoPrivilegesAskPiwikAdmin": "Olet kirjautuneena sisään käyttäjänä '%1$s', mutta sinulla ei ole mitään oikeuksia Matomoon. %2$sPyydä Matomon ylläpitäjää (napsauta avataksesi sähköpostin)%3$s antamaan katseluoikeudet verkkosivustoon.", + "NoSuchPage": "Tätä sivua ei ole olemassa", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Yhden klikkauksen päivitys ei ole saatavilla, sillä Matomoasi ajetaan useilla palvelimilla. Lataa uusin versio jatkaaksesi: %1$s", "OnlyForSuperUserAccess": "Tämä vimpain näkyy ainoastaan käyttäjille, joilla on superkäyttäjän oikeudet.", + "PageDownShortcutDescription": "päästäksesi sivun loppuun", + "PageUpShortcutDescription": "päästäksesi sivun alkuun", "PeriodRange": "Alue", + "PivotBySubtable": "Tämä raportti ei ole käännetty %1$s:n mukaan. Käännetty %2$s:llä.", + "QuickAccessTitle": "Hae %s:llä. Käytä nuolia navigointiin. Oikotie: haku aukeaa painamalla f-näppäintä.", + "QuickLinks": "Pikalinkit", + "ReadMoreOnlineGuide": "Lue lisää tästä aiheesta verkko-oppaasta.", + "RemoveTotalsRowDataTable": "Tämä raportti näyttää yhteenvetorivin%sPoista yhteenvetorivi", "ReportGeneratedOn": "Raportti luotu %s", "ReportGeneratedXAgo": "Raportti luotu %s sitten", + "ReportType": "Raportin tyyppi", + "ReportWithMetadata": "Raportti metadatan kera", + "RowLimit": "Rivejä", + "SearchOnMatomo": "Hae '%1$s' Matomo.orgista", + "SeeAvailableVersions": "Näytä saatavilla olevat versiot", + "Segments": "Segmentit", "SharePiwikLong": "Hei! Löysin juuri hienon vapaan ohjelmiston: Matomon!\n\nMatomolla voit seurata verkkosivustosi vierailijoita ilmaiseksi. Kannattaa tutustua!", "SharePiwikShort": "Matomo! Vapaa ja avoimen lähdekoodin verkkoanalyysi. Hallitse omaa dataasi.", "ShareThis": "Jaa tämä", - "ShortcutsAvailable": "Saatavilla olevat oikotiet", - "ShortcutZenMode": "Zen-tila", - "ShortcutSegmentSelector": "segmentin valinnalle", - "ShortcutWebsiteSelector": "verkkosivun valinnalle", "ShortcutCalendar": "kalenterin avaamiselle", - "ShortcutSearch": "haulle", "ShortcutHelp": "tälle ohjeelle", + "ShortcutSearch": "haulle", + "ShortcutSegmentSelector": "segmentin valinnalle", + "ShortcutWebsiteSelector": "verkkosivun valinnalle", + "ShortcutZenMode": "Zen-tila", + "ShortcutsAvailable": "Saatavilla olevat oikotiet", + "ShowExportUrl": "Näytä vienti-URL", "ShowJSCode": "Näytä lisättävä Javascript-koodi", "SkipToContent": "Siirry sisältöön", + "StandardReport": "Standardiraportti", + "StartDate": "Aloituspäivä", "SubscribeAndBecomePiwikSupporter": "Jatka turvalliselle luottokorttimaksusivulle (Paypal) ryhtyäksesi Matomon tukijaksi!", "SupportPiwik": "Tue Matomoa!", + "SupportUsOn": "Tue meitä", + "SystemSummaryMysqlVersion": "MySQL-versio", + "SystemSummaryNActivatedPlugins": "%d lisäosaa käytössä", + "SystemSummaryNWebsites": "%d verkkosivustoa", + "SystemSummaryPhpVersion": "PHP-versio", + "SystemSummaryPiwikVersion": "Matomo-versio", + "SystemSummaryWidget": "Järjestelmän yhteenveto", "TableNoData": "Ei tietoja tässä taulukossa", "ThereIsNoDataForThisReport": "Tähän raporttiin ei ole tietoja.", "UnFlattenDataTable": "Tämä raportti on tasainen %s Muuta hierarkiseksi", - "RemoveTotalsRowDataTable": "Tämä raportti näyttää yhteenvetorivin%sPoista yhteenvetorivi", - "AddTotalsRowDataTable": "Tämä raportti ei näytä yhtenvetoriviä %s Näytä yhteenvetorivi", + "UndoPivotBySubtable": "Tämä raportti on käännetty %s:llä. Kumoa kääntö", "ViewAllPiwikVideoTutorials": "Näytä kaikki Matomon videokurssit", + "VisitStatusOrdered": "Ostettu", + "VisitStatusOrderedThenAbandoned": "Ostettu, sitten hylätty ostoskori", + "VisitTypeReturning": "Palaava", + "VisitTypeReturningCustomer": "Palaava asiakas", "WebAnalyticsReports": "Raportit", - "YouAreUsingTheLatestVersion": "Käytössäsi on Matomon uusin versio!", - "ClickRowToExpandOrContract": "Klikkaa tätä riviä avataksesi tai sulkeaksesi alataulukon.", - "UndoPivotBySubtable": "Tämä raportti on käännetty %s:llä. Kumoa kääntö", - "NoSuchPage": "Tätä sivua ei ole olemassa", - "PageUpShortcutDescription": "päästäksesi sivun alkuun", - "PageDownShortcutDescription": "päästäksesi sivun loppuun", - "PivotBySubtable": "Tämä raportti ei ole käännetty %1$s:n mukaan. Käännetty %2$s:llä.", - "SystemSummaryWidget": "Järjestelmän yhteenveto", - "SystemSummaryNWebsites": "%d verkkosivustoa", - "SystemSummaryNActivatedPlugins": "%d lisäosaa käytössä", - "SystemSummaryPiwikVersion": "Matomo-versio", - "SystemSummaryMysqlVersion": "MySQL-versio", - "SystemSummaryPhpVersion": "PHP-versio", - "QuickAccessTitle": "Hae %s:llä. Käytä nuolia navigointiin. Oikotie: haku aukeaa painamalla f-näppäintä.", - "MenuEntries": "Valikon sisältö", - "Segments": "Segmentit", - "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Yhden klikkauksen päivitys ei ole saatavilla, sillä Matomoasi ajetaan useilla palvelimilla. Lataa uusin versio jatkaaksesi: %1$s", - "CssDidntLoad": "Selaimesi ei saanut ladattua tämän sivun tyyliä.", - "JsDidntLoad": "Selaimesi ei saanut ladattua tämän sivun skriptejä.", - "AdblockIsMaybeUsed": "Jos käytät mainostenestoa (ad blocker), poista se käytöstä tällä sivulla, jotta Matomo toimii ongelmitta.", - "ChangeCurrentWebsite": "Valitse sivusto, nyt valittuna %s", - "LeadingAnalyticsPlatformRespectsYourPrivacy": "Johtava avoimen lähdekoodin analytiikka-alusta, joka kunnioittaa yksityisyyttäsi.", - "MacPageUp": "Fn + Nuoli vasemmalle", - "MacPageDown": "Fn + Nuoli oikealle", - "ReportType": "Raportin tyyppi", - "RowLimit": "Rivejä", - "CustomLimit": "Muokattu rajaus", - "ExportFormat": "Vientimuoto", - "ExpandSubtables": "Avaa alataulut", - "StandardReport": "Standardiraportti", - "FlattenReport": "Litistä raportti", - "ReportWithMetadata": "Raportti metadatan kera", - "ReadMoreOnlineGuide": "Lue lisää tästä aiheesta verkko-oppaasta.", - "SeeAvailableVersions": "Näytä saatavilla olevat versiot", - "QuickLinks": "Pikalinkit", - "SearchOnMatomo": "Hae '%1$s' Matomo.orgista" + "YouAreUsingTheLatestVersion": "Käytössäsi on Matomon uusin versio!" } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/fr.json b/plugins/CoreHome/lang/fr.json index 3ffcdfa13d..88c2350c15 100644 --- a/plugins/CoreHome/lang/fr.json +++ b/plugins/CoreHome/lang/fr.json @@ -9,13 +9,14 @@ "CheckForUpdates": "Vérifier les mises à jour", "CheckPiwikOut": "Vérifiez sur Matomo !", "ChooseX": "Choisir %1$s", - "ClickRowToExpandOrContract": "Cliquez sur cette rangée pour afficher ou masquer le sous-tableau", + "ClickRowToExpandOrContract": "Cliquez sur cette rangée pour afficher ou masquer le sous-tableau.", "ClickToEditX": "Cliquer pour éditer %s", "ClickToSeeFullInformation": "Cliquer pour voir le détail de l'information", "CloseSearch": "Recherche précise", "CloseWidgetDirections": "Vous pouvez fermer ce gadget en cliquant sur l'icône en forme de \"X\" en haut du gadget.", "CssDidntLoad": "Votre navigateur n'a pas été en mesure de charger le style de la page.", "CustomLimit": "Limite personnalisée", + "DataForThisReportHasBeenDisabled": "La segmentation est actuellement désactivée pour ce rapport. Veuillez consulter %1$sthis FAQ%2$s pour plus de détails.", "DataForThisReportHasBeenPurged": "Les données pour ce rapport ont plus de %s mois et ont été purgées.", "DataTableCombineDimensions": "Les dimensions sont affichées séparément %s Combiner les dimensions", "DataTableExcludeAggregateRows": "Les lignes agrégées sont affichées %s Les cacher", @@ -28,6 +29,7 @@ "DonateCall1": "Matomo ne vous coûtera jamais rien à utiliser, mais cela ne veut pas dire que ça ne nous coûte rien pour le réaliser.", "DonateCall2": "Matomo a besoin de votre support pour continuer croître et prospérer.", "DonateCall3": "SI vous pensez que Matomo a ajouté une valeur significative à votre entreprise ou projet, %1$spensez à faire un don%2$s ou %3$sachetez des fonctionnalités premium%4$s. Chaque centime sera le bienvenu.", + "EndDate": "Date de fin", "EndShortcut": "Fin", "EngagementSubcategoryHelp1": "La page \"Engagement\" fournit des rapports pour quantifier la part des nouveaux visiteurs et des visiteurs connus. Vous pouvez également consulter les rapports qui ventilent la durée moyenne et le nombre de pages par visite, ainsi que le nombre de fois qu'un visiteur est venu sur votre site et le nombre de jours le plus fréquent entre deux visites.", "EngagementSubcategoryHelp2": "Cela peut vous aider à optimiser la fréquence et l'interaction des visites, tout en maximisant votre portée.", @@ -37,8 +39,8 @@ "ExitZenMode": "Quitter le mode Zen (afficher les menus)", "ExpandSubtables": "Élargir les sous-tables", "ExportFormat": "Format d'export", - "ExportTooltip": "Remarque : pour utiliser l'URL d'export générée, vous devez spécifier un jeton d'authentification d'application. Vous pouvez configurer ces jetons dans Administration -> Sécurité -> Jetons d'authentification.", - "ExportTooltipWithLink": "Remarque : pour utiliser l'URL d'export générée, vous devez spécifier un jeton d'authentification d'application. Vous pouvez configurer ces jetons dans %1$s[Administration -> Sécurité -> Jetons d'authentification]%2$s. Remplacez %3$s dans l'URL d'export par votre jeton. Attention : ne partagez jamais l'URL contenant votre jeton avec quelqu'un d'autre.", + "ExportTooltip": "Remarque : pour utiliser l'URL d'export générée, vous devez spécifier un jeton d'authentification d'application. Vous pouvez configurer ces jetons dans Administration -> Sécurité -> Jetons d'authentification.", + "ExportTooltipWithLink": "Remarque : pour utiliser l'URL d'export générée, vous devez spécifier un jeton d'authentification d'application. Vous pouvez configurer ces jetons dans %1$s[Administration -> Sécurité -> Jetons d'authentification]%2$s. Remplacez %3$s dans l'URL d'export par votre jeton. Attention : ne partagez jamais l'URL contenant votre jeton avec quelqu'un d'autre.", "ExternalHelp": "Aide (nouvel onglet)", "FlattenDataTable": "Le rapport est hiérarchique %s L'aplatir", "FlattenReport": "Aplatir le rapport", @@ -51,7 +53,7 @@ "InjectedHostNonSuperUserWarning": "%1$sCliquez ici pour accéder à Matomo de manière sécurisé%2$s et supprimer cette alerte. Vous pouvez aussi contacter votre administrateur Matomo and l'avertir de ce problème (%3$sCliquez ici pour envoyer un message%4$s).", "InjectedHostSuperUserWarning": "Matomo est probablement mal configuré (par exemple, si Matomo a récemment été déplacé vers un nouveau serveur ou une nouvelle URL). Vous pouvez ou %1$scliquer ici et l'ajouter %2$s en tant que nom d'hôte Matomo valide (si vous lui faites confiance)%3$s, ou %4$s cliquer ici et accéder %5$s à Matomo de manière sécurisée%6$s.", "InjectedHostWarningIntro": "Vous accédez maintenant à Matomo depuis %1$s, mais Matomo a été configuré pour s'exécuter à cette adresse : %2$s.", - "JavascriptDisabled": "JavaScript doit être activé pour que vous puissiez utiliser Matomo de manière basique.<br />Cependant, il semble que JasvaScript ne soit pas supporté ou soit désactivé sur votre navigateur.<br />Pour utiliser l'interface basique, activez JavaScript en modifiant les options de votre navigateur, ensuite %1$sessayez encore%2$s.<br />", + "JavascriptDisabled": "JavaScript doit être activé pour que vous puissiez utiliser Matomo de manière standard.<br>Cependant, il semble que JasvaScript ne soit pas supporté ou soit désactivé sur votre navigateur.<br>Pour utiliser l'interface standard, activez JavaScript en modifiant les options de votre navigateur, ensuite %1$sessayez encore%2$s.<br>", "JsDidntLoad": "Votre navigateur n'a pas été en mesure de charger les scripts de la page.", "LeadingAnalyticsPlatformRespectsYourPrivacy": "La première plateforme d'analyses statistiques libre qui respecte votre vie privée.", "MacPageDown": "Fn + flèche Droite", @@ -77,7 +79,7 @@ "ReportGeneratedXAgo": "Rapport généré il y a %s", "ReportType": "Type de rapport", "ReportWithMetadata": "Rapport avec métadonnées", - "ReportingCategoryHelpPrefix": "Comment la page de rapport \"%1$s > %2$s\" m'a-t-elle aidée ?", + "ReportingCategoryHelpPrefix": "Comment la page de rapport \"%1$s > %2$s\" m'a-t-elle aidée ?", "RowLimit": "Limite de rang", "SearchOnMatomo": "Rechercher '%1$s' sur Matomo.org", "SeeAvailableVersions": "Voir les versions disponibles", @@ -97,6 +99,7 @@ "SkipToContent": "Passer au contenu", "SoftwareSubcategoryHelp": "La page \"Logiciel\" affiche les systèmes d'exploitation, les navigateurs et les modules complémentaires de vos visiteurs, vous permettant d'optimiser votre site pour s'assurer d'être pleinement compatible avec les configurations les plus populaires.", "StandardReport": "Rapport standard", + "StartDate": "Date de début", "SubscribeAndBecomePiwikSupporter": "Procéder à un paiement par carte de crédit sécurisé (Paypal) pour devenir un bienfaiteur de Matomo !", "SupportPiwik": "Supporter Matomo !", "SupportUsOn": "Soutenez-nous sur", diff --git a/plugins/CoreHome/lang/ga.json b/plugins/CoreHome/lang/ga.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/plugins/CoreHome/lang/ga.json @@ -0,0 +1 @@ +{} diff --git a/plugins/CoreHome/lang/hi.json b/plugins/CoreHome/lang/hi.json index 52aa7e356d..21b90c82ab 100644 --- a/plugins/CoreHome/lang/hi.json +++ b/plugins/CoreHome/lang/hi.json @@ -1,17 +1,27 @@ { "CoreHome": { "CategoryNoData": "इस श्रेणी में कोई डेटा नहीं. \"सभी लोगों को शामिल\" करने का प्रयास करें.", + "ChangePeriod": "अवधि बदलें", + "ChangeVisualization": "विज़ुअलाइज़ेशन बदलें", "CheckForUpdates": "अद्यतन देखें", "CheckPiwikOut": "Matomo जाँच करें!", + "ChooseX": "%1$s चुनें", "ClickToEditX": "%s को संपादित करने के लिए क्लिक करें", + "ClickToSeeFullInformation": "पूरी जानकारी देखने के लिए क्लिक करें", + "CloseSearch": "खोज बंद करें", "CloseWidgetDirections": "आप विजेट के शीर्ष पर 'X' आइकन पर क्लिक करके इस विजेट बंद कर सकते हैं.", "DataForThisReportHasBeenPurged": "इस रिपोर्ट के लिए डेटा %s महीनोंकी तुलना में अधिक पुराना है और शुद्ध किया गया है.", "DataTableExcludeAggregateRows": "कुल पंक्तियों %s को दिखाया जाता है उन्हें छुपाने", + "DataTableHowToSearch": "Enter दबाएँ या खोज करने के लिए खोज चिह्न क्लिक करें", "DataTableIncludeAggregateRows": "कुल पंक्तियों को छिपा रहे हैं, %s उन्हें दिखाओ", + "DateInvalid": "दिया गया दिनांक और अवधि संयोजन अमान्य है। कृपया दिनांक चयनकर्ता में एक मान्य दिनांक चुनें।", "Default": "डिफ़ॉल्ट", "DonateCall1": "Matomo उपयोग करने के लिए आपके कुछ भी खर्च नहीं होंगे, लेकिन यह मतलब नहीं बनाने के लिए कोई खर्च नहीं लगता है.", "DonateCall2": "Matomo के बढ़ने और फूलने के लिए आपके निरंतर समर्थन की जरूरत है.", + "EndShortcut": "समाप्ति", + "EnterZenMode": "ज़ेन मोड में प्रवेश करें (मेन्यू छुपाएं)", "ExcludeRowsWithLowPopulation": "सभी पंक्तियों %s को दिखाया जाता है कम आबादी बाहर निकालें", + "ExitZenMode": "ज़ेन मोड से बाहर निकलें (मेन्यू दिखाएँ)", "ExternalHelp": "सहायता (नए टैब में खुलती है)", "FlattenDataTable": "रिपोर्ट श्रेणीबद्ध %s है यह फ्लैट बनाओ है", "IncludeRowsWithLowPopulation": "कम आबादी के साथ पंक्तियाँ छिपे %s हुए हैं, सभी पंक्तियों दिखाएँ", @@ -29,12 +39,12 @@ "ShowJSCode": "सम्मिलित करने के लिए जावास्क्रिप्ट कोड दिखाएँ", "SubscribeAndBecomePiwikSupporter": "एक Matomo समर्थक बनने के लिए एक सुरक्षित क्रेडिट कार्ड भुगतान पृष्ठ (पेपैल) के लिए आगे बढ़ें!", "SupportPiwik": "पिविक को अपना सहयोग दें।", + "SystemSummaryPhpVersion": "PHP संस्करण", "TableNoData": "इस तालिका के लिए कोई डेटा नहीं है .", "ThereIsNoDataForThisReport": "इस रिपोर्ट के लिए कोई डाटा नहीं है.", "UnFlattenDataTable": "रिपोर्ट फ्लैट %s है इसे श्रेणीबद्ध करें", "ViewAllPiwikVideoTutorials": "सभी Matomo वीडियो ट्यूटोरियल देखें", "WebAnalyticsReports": "वेब विश्लेषिकी रिपोर्टें", - "YouAreUsingTheLatestVersion": "आप Matomo का नवीनतम संस्करण का उपयोग कर रहे हैं!", - "SystemSummaryPhpVersion": "PHP संस्करण" + "YouAreUsingTheLatestVersion": "आप Matomo का नवीनतम संस्करण का उपयोग कर रहे हैं!" } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/id.json b/plugins/CoreHome/lang/id.json index 33527e8628..2f83b6813e 100644 --- a/plugins/CoreHome/lang/id.json +++ b/plugins/CoreHome/lang/id.json @@ -1,44 +1,132 @@ { "CoreHome": { + "AdblockIsMaybeUsed": "Jika Anda menggunakan pemblokir iklan, harap nonaktifkan untuk situs ini untuk memastikan Matomo berfungsi tanpa masalah.", + "AddTotalsRowDataTable": "Laporan tidak menampilkan baris total %s Tampilkan baris total", "CategoryNoData": "Tak ada data untuk kategori ini. Coba untuk \"Masukkan seluruh populasi\".", + "ChangeCurrentWebsite": "Pilih situs web, situs web yang saat ini dipilih: %s", + "ChangePeriod": "Ubah periode", "ChangeVisualization": "Ubah visualisasi", "CheckForUpdates": "Periksa pembaruan", "CheckPiwikOut": "Periksa Matomo!", + "ChooseX": "Pilih %1$s", + "ClickRowToExpandOrContract": "Klik baris ini untuk memperluas atau mengontrak subtabel.", "ClickToEditX": "Klik untuk mengubah %s", "ClickToSeeFullInformation": "Klik untuk melihat informasi lengkap", - "CloseWidgetDirections": "Anda dapat menutup gawit ini dengan mengeklik ikon 'X' di atas gawit.", - "ChooseX": "Pilih %1$s", + "CloseSearch": "Tutup pencarian", + "CloseWidgetDirections": "Anda dapat menutup widget ini dengan mengklik ikon 'X' di bagian atas widget.", + "CssDidntLoad": "Peramban Anda tidak dapat memuat gaya halaman ini.", + "CustomLimit": "Batas khusus", + "DataForThisReportHasBeenDisabled": "Segmentasi untuk laporan ini saat ini dinonaktifkan. Silakan periksa %1$sFAQ ini%2$s untuk detail selengkapnya.", "DataForThisReportHasBeenPurged": "Data untuk laporan ini telah berumur lebih dari %s bulan dan telah dibersihkan.", - "DataTableExcludeAggregateRows": "Keseluruhan baris ditampilkan %s Sembunyikan sekarang", - "DataTableIncludeAggregateRows": "Keseluruhan baris tersembunyi %s Tampilkan sekarang", + "DataTableCombineDimensions": "Dimensi ditampilkan secara terpisah %s Tampilkan dimensi gabungan", + "DataTableExcludeAggregateRows": "Baris agregat ditampilkan %s Sembunyikan", + "DataTableHowToSearch": "Tekan enter atau klik ikon pencarian untuk mencari", + "DataTableIncludeAggregateRows": "Baris agregat disembunyikan %s Perlihatkan", + "DataTableShowDimensions": "Dimensi digabungkan %s Tampilkan dimensi secara terpisah", + "DateInvalid": "Kombinasi tanggal dan periode yang diberikan tidak valid. Harap pilih tanggal yang valid di pemilih tanggal.", "Default": "asali", - "DonateCall1": "Matomo akan selalu tidak membebani Anda biaya, tapi bukan berarti bahwa biaya tidak berarti bagi kami.", + "DevicesSubcategoryHelp": "Bagian Perangkat membantu Anda memahami teknologi yang digunakan oleh pengunjung untuk mengakses situs. Anda akan melihat laporan tentang jenis perangkat dan model tertentu untuk memungkinkan Anda mengoptimalkan situs Anda untuk perangkat yang paling populer.", + "DonateCall1": "Anda tidak perlu mengeluarkan biaya apa pun untuk memakai Matomo, tetapi bukan berarti kami tidak mengeluarkan biaya apa pun untuk membuatnya.", "DonateCall2": "Matomo membutuhkan bantuan berkelanjutan Anda untuk tumbuh dan berkembang.", - "ExcludeRowsWithLowPopulation": "Seluruh baris telah ditampilkan %s Populasi rendah dikecualikan", - "FlattenDataTable": "Laporan ditampilkan berurutan %s Buat tetap", - "IncludeRowsWithLowPopulation": "Baris dengan populasi rendah telah tersembunyi %s Tampilkan seluruh baris", - "InjectedHostEmailBody": "Halo, saya mencoba mengakses Matomo hari ini dan menemukan peringatan nama inang tidak dikenal.", - "InjectedHostEmailSubject": "Matomo telah diakses menggunakan nama inang tidak dikenal: %s", + "DonateCall3": "Jika Anda merasa bahwa Matomo telah memberi nilai signifikan bagi bisnis atau usaha Anda, %1$sharap pertimbangkan untuk menyumbang%2$s atau %3$smembeli fitur premium%4$s. Setiap sen akan sangat membantu.", + "EndDate": "Tanggal Akhir", + "EndShortcut": "Akhir", + "EngagementSubcategoryHelp1": "Bagian Keterlibatan memberikan laporan yang membantu menghitung jumlah pengunjung baru dan pengunjun yang kembali. Anda juga dapat meninjau laporan yang memecah waktu rata-rata dan jumlah halaman per kunjungan, serta frekuensi pengunjung yang mengunjungi situs Anda dan jumlah hari kunjungan.", + "EngagementSubcategoryHelp2": "Ini dapat membantu Anda untuk mengoptimalkan frekuensi dan tingkat interaksi kunjungan demi memaksimalkan jangkauan Anda.", + "EnterZenMode": "Masuk ke mode Zen (sembunyikan menu)", + "ExceptionNotAllowlistedIP": "Anda tidak dapat menggunakan Matomo karena IP Anda %s tidak diperbolehkan.", + "ExcludeRowsWithLowPopulation": "Semua baris ditampilkan %s Kecualikan populasi yang rendah", + "ExitZenMode": "Keluar dari mode Zen (tampilkan menu)", + "ExpandSubtables": "Perluas subtabel", + "ExportFormat": "Format ekspor", + "ExportTooltip": "Catatan: Untuk menggunakan URL ekspor yang dihasilkan, Anda harus menentukan autentikasi token aplikasi. Anda dapat mengonfigurasi token ini di Admin -> Keamanan -> Token Auths.", + "ExportTooltipWithLink": "Catatan: Untuk menggunakan URL ekspor yang dihasilkan, Anda harus menentukan autentikasi token aplikasi. Anda dapat mengonfigurasi token ini di %1$s[Admin -> Keamanan -> Auths Tokens]%2$s. Ganti %3$s di URL Ekspor dengan token Auth Anda. Peringatan: Jangan pernah membagikan URL yang berisi token asli kepada orang lain.", + "ExternalHelp": "Bantuan (terbuka di tab baru)", + "FlattenDataTable": "Laporan ini hierarkis %s Tampilkan secara datar", + "FlattenReport": "Ratakan laporan", + "FormatMetrics": "Format metrik", + "HideExportUrl": "Sembunyikan URL Ekspor", + "HomeShortcut": "Beranda", + "IncludeRowsWithLowPopulation": "Baris dengan populasi rendah disembunyikan %s Tampilkan semua baris", + "InjectedHostEmailBody": "Halo, saya mencoba mengakses Matomo hari ini dan menemukan peringatan nama host yang tidak dikenal.", + "InjectedHostEmailSubject": "Matomo diakses dengan nama host yang tidak diketahui: %s", "InjectedHostNonSuperUserWarning": "%1$sKlik di sini untuk mengkases Matomo secara aman%2$s dan menghapus peringatan ini. Anda juga dapat menghubungi pengelola Matomo Anda dan memberi tahu tentang permasalahan ini (%3$sklik di sini untuk surel%4$s).", - "InjectedHostSuperUserWarning": "Matomo mungkin salah konfigurasi (sebagai contoh, bila Matomo baru saja dipindah ke peladen atau URL baru). Anda dapat memilih %1$sklik di sini dan menambah%2$s sebagai nama inang Matomo sahih (bila Anda mempercayai ini)%3$s, atau %4$sklik di sini dan menuju %5$s akses Matomo secara aman%6$s.", + "InjectedHostSuperUserWarning": "Matomo mungkin salah dikonfigurasi (misalnya, jika Matomo baru saja dipindahkan ke server atau URL baru). Anda dapat %1$sklik di sini dan menambahkan %2$s sebagai nama host Matomo yang valid (jika Anda memercayainya)%3$s atau %4$sklik di sini dan pergi ke %5$s untuk mengakses Matomo dengan aman%6$s.", "InjectedHostWarningIntro": "Sekarang Anda mengakses Matomo dari %1$s, tetapi Matomo telah diatur untuk berjalan di alamat ini: %2$s.", + "JavascriptDisabled": "JavaScript harus diaktifkan agar Anda dapat menggunakan Matomo dalam tampilan standar.<br>Namun, tampaknya JavaScript dinonaktifkan atau tidak didukung oleh peramban Anda.<br>Untuk menggunakan tampilan standar, aktifkan JavaScript dengan mengubah opsi peramban Anda , lalu %1$scoba lagi%2$s.<br>", + "JsDidntLoad": "Peramban Anda tidak dapat memuat skrip halaman ini.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "Platform analitik terbuka terkemuka yang menghormati privasi Anda.", + "MacPageDown": "Fn + Panah kanan", + "MacPageUp": "Fn + Panah kiri", + "MainNavigation": "Navigasi utama", "Menu": "Menu", + "MenuEntries": "Entri menu", "NoPrivilegesAskPiwikAdmin": "Anda masuk sebagai '%1$s' tetapi sepertinya Anda tidak memiliki izin apapun di Matomo. %2$s Tanyakan kepada pengelola Matomo Anda (klik untuk kirim surel)%3$s untuk memberikan akses 'Lihat' ke situs.", + "NoSuchPage": "Halaman ini tidak ada", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Pembaruan sekali klik tidak tersedia karena Anda menggunakan Matomo dengan banyak server. Silakan unduh versi terbaru dari %1$s untuk melanjutkan.", + "OnlyForSuperUserAccess": "Widget ini ditampilkan di dasbor bawaan hanya untuk pengguna yang memiliki akses Pengguna Super.", + "PageDownShortcutDescription": "untuk sampai ke bagian bawah halaman", + "PageUpShortcutDescription": "untuk sampai ke bagian atas halaman", + "PeriodHasOnlyRawData": "Sepertinya laporan untuk periode ini belum diproses. Apakah Anda ingin melihat apa yang terjadi sekarang? Lihat %1$sLog kunjungan%2$s atau pilih periode tanggal yang berbeda hingga laporan dibuat.", "PeriodRange": "Rentang", + "PivotBySubtable": "Laporan ini tidak dipivot %1$s Dipivot berdasarkan %2$s", + "Profilable": "Dapat diprofilkan", + "QuickAccessTitle": "Telusuri %s. Gunakan tombol panah untuk menavigasi hasil pencarian. Pintasan: Tekan 'f' untuk mencari.", + "QuickLinks": "Tautan Cepat", + "ReadMoreOnlineGuide": "Baca lebih lanjut tentang topik ini di panduan daring.", + "RemoveTotalsRowDataTable": "Laporan menunjukkan baris total %s Hapus baris total", "ReportGeneratedOn": "Laporan dibuat dalam %s", "ReportGeneratedXAgo": "Laporan dibuat %s lalu", - "SharePiwikShort": "Matomo! Analisis ramatraya sumber terbuka dan gratis. Miliki sendiri data Anda.", - "ShareThis": "Bagi ini", + "ReportType": "Tipe laporan", + "ReportWithMetadata": "Laporan dengan metadata", + "ReportingCategoryHelpPrefix": "Bagaimana halaman pelaporan \"%1$s > %2$s\" membantu saya?", + "RowLimit": "Batas baris", + "SearchOnMatomo": "Cari '%1$s' di Matomo.org", + "SeeAvailableVersions": "Lihat Versi yang Tersedia", + "Segments": "Segmen", + "SharePiwikLong": "Hai! Saya baru saja menemukan perangkat lunak gratis yang hebat yaitu Matomo!\n\nMatomo memungkinkan Anda untuk melacak pengunjung situs web Anda secara gratis. Anda benar-benar harus mengeceknya!", + "SharePiwikShort": "Matomo! Analisis web gratis/libre. Miliki data Anda.", + "ShareThis": "Bagikan ini", + "ShortcutCalendar": "untuk membuka kalender (d singkatan dari Tanggal)", + "ShortcutHelp": "untuk menampilkan bantuan ini", + "ShortcutSearch": "untuk membuka pencarian (f singkatan dari Cari)", + "ShortcutSegmentSelector": "untuk membuka pemilih Segmen", + "ShortcutWebsiteSelector": "untuk membuka pemilih Situs Web", + "ShortcutZenMode": "untuk mode Zen", + "ShortcutsAvailable": "Pintasan yang tersedia", + "ShowExportUrl": "Tampilkan URL Ekspor", "ShowJSCode": "Tampilkan kode JavaScript untuk disisipkan", "SkipToContent": "Lewati ke konten", - "SubscribeAndBecomePiwikSupporter": "Meneruskan ke halaman pembayaran aman kartu kredit (Paypal) untuk to menjadi pendukung Matomo!", - "SupportPiwik": "Dukung!", + "SoftwareSubcategoryHelp": "Bagian Perangkat Lunak menunjukkan sistem operasi, peramban, dan plugin yang digunakan oleh pengunjung Anda untuk mengakses situs sehingga Anda dapat mengoptimalkan situs untuk memastikannya kompatibel sepenuhnya dengan konfigurasi yang paling populer.", + "StandardReport": "Laporan standar", + "StartDate": "Tanggal Awal", + "SubscribeAndBecomePiwikSupporter": "Lanjutkan ke halaman pembayaran kartu kredit yang aman (Paypal) untuk menjadi Pendukung Matomo!", + "SupportPiwik": "Dukung Matomo!", + "SupportUsOn": "Dukung kami di", + "SystemSummaryMysqlVersion": "Versi MySQL", + "SystemSummaryNActivatedPlugins": "%d plugin yang diaktifkan", + "SystemSummaryNSegments": "%1$d segmen", + "SystemSummaryNSegmentsWithBreakdown": "%1$d segmen (%2$s telah diproses sebelumnya, %3$s diproses secara waktu nyata)", + "SystemSummaryNWebsites": "%d situs web", + "SystemSummaryPhpVersion": "Versi PHP", + "SystemSummaryPiwikVersion": "Versi Matomo", + "SystemSummaryWidget": "Ringkasan Sistem", + "TableNoData": "Tidak ada data untuk tabel ini.", + "TechDeprecationWarning": "Mulai dari versi Matomo %1$s, Matomo akan mengakhiri dukungan untuk %2$s. Untuk informasi lebih lanjut %3$slihat postingan blog kami.%4$s", + "ThanksFromAllOfUs": "Terima kasih dari kami semua di Matomo!", "ThereIsNoDataForThisReport": "Tidak ada data untuk laporan ini.", - "UnFlattenDataTable": "Laporan ditampilkan tetap %s Buat berurutan", + "UnFlattenDataTable": "Laporan ditampilkan secara datar %s Buat berurutan", + "UndoPivotBySubtable": "Laporan ini telah dipivot %s Batalkan pivot", "ViewAllPiwikVideoTutorials": "Tampilkan seluruh Video Tutorial Matomo", + "VisitStatusOrdered": "Dipesan", + "VisitStatusOrderedThenAbandoned": "Dipesan lalu Keranjang Ditinggalkan", + "VisitTypeReturning": "Kembali", + "VisitTypeReturningCustomer": "Pelanggan yang Kembali", + "VisitorsCategoryHelp1": "Halaman Pengunjung memberi tahu Anda banyak hal tentang siapa pengunjung Anda. Hal-hal seperti dari mana pengunjung Anda berasal, perangkat dan peramban apa yang mereka gunakan, dan kapan mereka biasanya mengunjungi situs web Anda. Pahami secara keseluruhan siapa audiens Anda dan cari anomali untuk melihat bagaimana audiens Anda bisa tumbuh.", + "VisitorsCategoryHelp2": "Selain informasi umum tentang pengunjung, Anda juga dapat menggunakan %1$sLog Kunjungan%2$s untuk melihat apa yang terjadi di setiap kunjungan individu.", + "VisitorsOverviewHelp": "Ikhtisar Pengunjung membantu Anda dalam memahami popularitas situs Anda. Ini dilakukan dengan menyediakan bagan yang menunjukkan berapa banyak kunjungan yang diterima situs Anda selama periode yang dipilih dan tingkat keterlibatan rata-rata untuk fitur utama, seperti pencarian dan unduhan.", "WebAnalyticsReports": "Laporan Analisis Web", - "YouAreUsingTheLatestVersion": "Anda menggunakan versi termutakhir Matomo!", - "SystemSummaryPhpVersion": "Versi PHP", - "SearchOnMatomo": "Cari '%1$s' pada Matomo.org" + "YouAreUsingTheLatestVersion": "Anda menggunakan versi Matomo terbaru!", + "YourDonationWillHelp": "Donasi Anda secara langsung akan membantu mendanai fitur dan peningkatan baru untuk platform analitik sumber terbuka ini. Ini berarti komunitas akan selalu mendapat manfaat dari alat yang melindungi privasi dan memungkinkan Anda untuk tetap mengontrol data Anda." } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/it.json b/plugins/CoreHome/lang/it.json index 27d6ab8436..e75aab914d 100644 --- a/plugins/CoreHome/lang/it.json +++ b/plugins/CoreHome/lang/it.json @@ -16,9 +16,10 @@ "CloseWidgetDirections": "Potete chiudere questo widget cliccando sull'icona 'X' nella parte alta del widget stesso.", "CssDidntLoad": "Il tuo browser non ha potuto caricare lo stile di questa pagina.", "CustomLimit": "Limite personalizzato", + "DataForThisReportHasBeenDisabled": "La segmentazione é disabilitata al momento per questo documento. Per maggiori dettagli controllate %1$s la sezione Domande Frequenti%2$s perfavore.", "DataForThisReportHasBeenPurged": "I dati di questo report hanno più di un mese %s e sono stati eliminati.", "DataTableCombineDimensions": "Le dimensioni sono separate %s Mostra le dimensioni combinate", - "DataTableExcludeAggregateRows": "Le righe di aggregazione vengono visualizzate %s Nascondile", + "DataTableExcludeAggregateRows": "Le righe di aggregazione sono visibili. %s Nascondile", "DataTableHowToSearch": "Premi Invio o clicca sull'icona per cercare", "DataTableIncludeAggregateRows": "Le righe di aggregazione sono nascoste %s Visualizzale", "DataTableShowDimensions": "Le dimensioni sono combinate %s Mostra le dimensioni separatamente", @@ -28,6 +29,7 @@ "DonateCall1": "Matomo non costerà mai nulla a voi per il suo utilizzo, ma ciò non significa che non costi nulla a noi svilupparlo.", "DonateCall2": "Matomo ha bisogno del vostro costante supporto per crescere e prosperare.", "DonateCall3": "Se ritieni che Matomo abbia portato alla tua attività un significativo valore aggiunto, %1$sconsidera di fare una donazione%2$s o di %3$sacquistare una funzionalità premium%4$s. Anche gli spiccioli aiutano.", + "EndDate": "Data di Fine", "EndShortcut": "Fine", "EngagementSubcategoryHelp1": "La sezione Engagement fornisce dei report che aiutano a quantificare il numero di visitatori nuovi e di ritorno che ricevi. Puoi anche esaminare i report che dettagliano il tempo medio e il numero di pagine per visita, nonché il numero di volte in cui un visitatore è stato sul tuo sito e il numero abituale di giorni che intercorrono tra le visite.", "EngagementSubcategoryHelp2": "Questo può aiutarti a ottimizzare la frequenza e le visite ad alta interazione oltre a massimizzare la tua copertura.", @@ -37,8 +39,8 @@ "ExitZenMode": "Esci dalla modalità Zen (mostra i menù)", "ExpandSubtables": "Espandi sottotabelle", "ExportFormat": "Esporta formato", - "ExportTooltip": "Nota: per utilizzare l'URL di esportazione generato, sarà necessario specificare un token auth dell'applicazione. Puoi configurare questi token in Admin -> Sicurezza -> Token Auth.", - "ExportTooltipWithLink": "Nota: per utilizzare l'URL di esportazione generato, sarà necessario specificare un token auth dell'applicazione. È possibile configurare questi token in %1$s[Admin -> Sicurezza-> Token Auth]%2$s. Sostituisci %3$s nell'URL di esportazione con il tuo token auth. Attenzione: non condividere mai con nessun altro l'URL con il token reale.", + "ExportTooltip": "Nota: per utilizzare l'URL di esportazione generato, sarà necessario specificare un token auth dell'applicazione. Puoi configurare questi token in Admin -> Sicurezza -> Token Auth.", + "ExportTooltipWithLink": "Nota: per utilizzare l'URL di esportazione generato, sarà necessario specificare un token auth dell'applicazione. È possibile configurare questi token in %1$s[Admin -> Sicurezza-> Token Auth]%2$s. Sostituisci %3$s nell'URL di esportazione con il tuo token auth. Attenzione: non condividere mai con nessun altro l'URL con il token reale.", "ExternalHelp": "Aiuto (apri in una nuova scheda)", "FlattenDataTable": "Il report è gerarchico %s Rendilo piatto", "FlattenReport": "Report piatto", @@ -51,7 +53,7 @@ "InjectedHostNonSuperUserWarning": "%1$sClicca qui per accedere a Matomo in maniera sicura%2$s e rimuovere questo avvertimento. Puoi anche voler contattare il tuo amministratore di Matomo per avvisare di questo problema (%3$sclicca qui per inviare un'email%4$s).", "InjectedHostSuperUserWarning": "Matomo può essere configurato in modo errato (ad esempio, se Matomo è stato recentemente spostato in un nuovo server o URL). È possibile anche %1$s cliccare qui e aggiungere %2$s come hostname valido per Matomo (se ti fidi di esso)%3$s, o %4$scliccare qui e andare a %5$s per accedere in modo sicuro a Matomo%6$s.", "InjectedHostWarningIntro": "Stai accedendo a Matomo da %1$s ma Matomo è stato configurato per girare a questo indirizzo: %2$s.", - "JavascriptDisabled": "Perché tu possa usare Matomo in visualizzazione standard, JavaScript deve essere abilitato. <br />Comunque sembra che JavaScript sia disabilitato o non supportato dal tuo browser.<br /> Per usare la visualizzazione standard, abilita JavaScript cambiando le opzioni del tuo browser, poi %1$sprova ancora%2$s.<br />", + "JavascriptDisabled": "Perché tu possa usare Matomo in visualizzazione standard, JavaScript deve essere abilitato. <br>Comunque sembra che JavaScript sia disabilitato o non supportato dal tuo browser.<br> Per usare la visualizzazione standard, abilita JavaScript cambiando le opzioni del tuo browser, poi %1$sprova ancora%2$s.<br>", "JsDidntLoad": "Il tuo browser non ha potuto caricare gli script di questa pagina.", "LeadingAnalyticsPlatformRespectsYourPrivacy": "La piattaforma gratuita di analisi web che rispetta la tua privacy.", "MacPageDown": "Fn + Freccia a destra", @@ -77,7 +79,7 @@ "ReportGeneratedXAgo": "Report generato %s fa", "ReportType": "Tipo di report", "ReportWithMetadata": "Report con metadati", - "ReportingCategoryHelpPrefix": "In che modo la pagina dei report \"%1$s > %2$s\" può aiutarmi?", + "ReportingCategoryHelpPrefix": "In che modo la pagina dei report \"%1$s > %2$s\" può aiutarmi?", "RowLimit": "Limite riga", "SearchOnMatomo": "Cerca '%1$s' su matomo.org", "SeeAvailableVersions": "Vedi le Versioni Disponibili", @@ -97,6 +99,7 @@ "SkipToContent": "Vai al contenuto", "SoftwareSubcategoryHelp": "La sezione Software mostra i sistemi operativi, i browser e i plugin che i tuoi visitatori stanno utilizzando per accedere al sito, in modo da poterlo ottimizzare per assicurarti che sia completamente compatibile con le configurazioni più diffuse.", "StandardReport": "Report standard", + "StartDate": "Data di Inizio", "SubscribeAndBecomePiwikSupporter": "Procedi su una pagina sicura di pagamento con carta di credito (Paypal) per diventare un Sostenitore di Matomo!", "SupportPiwik": "Sostieni Matomo!", "SupportUsOn": "Sostienici su", diff --git a/plugins/CoreHome/lang/ja.json b/plugins/CoreHome/lang/ja.json index a7b9cf41b1..dfb5534296 100644 --- a/plugins/CoreHome/lang/ja.json +++ b/plugins/CoreHome/lang/ja.json @@ -16,6 +16,7 @@ "CloseWidgetDirections": "このウィジェットを閉じるには、ウィジェットの上部にある ' × ' アイコンをクリックします。", "CssDidntLoad": "お使いのブラウザではこのページのスタイルを読み込めませんでした。", "CustomLimit": "カスタム制限", + "DataForThisReportHasBeenDisabled": "現在、このレポートではセグメンテーションが無効になっています。 詳細については、%1$sこのFAQ%2$sを確認してください。", "DataForThisReportHasBeenPurged": "このレポートのデータは、%sヶ月以上経過しており、パージされています。", "DataTableCombineDimensions": "ディメンションは %s で別々に表示されています。組み合わせたディメンションを表示", "DataTableExcludeAggregateRows": "%s で表示している集計行を非表示にする", @@ -28,6 +29,7 @@ "DonateCall1": "Matomo は無料でご利用いただけますが、 Matomo の制作に費用がかかっていないと言う意味ではありません。", "DonateCall2": "Matomo の成長と発展には、みなさんの継続的なご支援が必要です。", "DonateCall3": "Matomo がビジネスや努力に重大な付加価値を感じる場合は、%3$sプレミアム機能を購入%4$sまたは%1$s寄付する%2$sことをご検討ください。 すべての寄付金が助けになるでしょう。", + "EndDate": "終了日", "EndShortcut": "終了", "EngagementSubcategoryHelp1": "エンゲージメントセクションには、新規ビジターとリピーターの数を定量化するのに役立つレポートがあります。 また、ビジットあたりの平均時間とページ数、ビジターがサイトにアクセスした回数、およびビジット間の最も一般的な日数を分類したレポートを確認することもできます。", "EngagementSubcategoryHelp2": "これにより、リーチを最大化するだけでなく、ビジットの頻度とインタラクションの多いビジットを最適化することができます。", @@ -97,6 +99,7 @@ "SkipToContent": "コンテンツへスキップ", "SoftwareSubcategoryHelp": "ソフトウェアセクションには、ビジターがサイトにアクセスするために使用しているオペレーティングシステム、ブラウザ、プラグインが表示されます。これにより、サイトを最適化して、最も一般的な構成と完全に互換性を持たせることができます。", "StandardReport": "標準レポート", + "StartDate": "開始日", "SubscribeAndBecomePiwikSupporter": "Matomo サポーターになるには、安全なクレジットカード決済 ( Paypal ) ページにお進みください !", "SupportPiwik": "Matomo をサポート!", "SupportUsOn": "で私たちをサポート", diff --git a/plugins/CoreHome/lang/nb.json b/plugins/CoreHome/lang/nb.json index 0195d940d3..5b482aced5 100644 --- a/plugins/CoreHome/lang/nb.json +++ b/plugins/CoreHome/lang/nb.json @@ -1,8 +1,10 @@ { "CoreHome": { "AdblockIsMaybeUsed": "Hvis du bruker en ad-blocker, vennligst deaktiver den for dette nettstedet for å forsikre deg om at Matomo fungerer som det skal.", + "AddTotalsRowDataTable": "Rapporten viser ikke totalt antall rader %s Vis totalt antall", "CategoryNoData": "Ingen data i denne kategorien. Prøv å velge «Inkluder hele populasjonen».", "ChangeCurrentWebsite": "Velg et nettsted. Nettstedet som nå er valgt er: %s", + "ChangePeriod": "Endre periode", "ChangeVisualization": "Endre visualisering", "CheckForUpdates": "Se etter oppdateringer", "CheckPiwikOut": "Sjekk ut Matomo!", @@ -12,52 +14,119 @@ "ClickToSeeFullInformation": "Klikk her for å se mer informasjon", "CloseSearch": "Lukk søk", "CloseWidgetDirections": "Du kan lukke dette elementet ved å klikke på X-ikonet over widgeten.", + "CssDidntLoad": "Nettleseren din kunne ikke laste inn sidestilen.", + "CustomLimit": "Egendefinert grense", + "DataForThisReportHasBeenDisabled": "Inndeling er avskrudd for denne rapporten. Sjekk %1$softe stilte spørsmål%2$s for flere detaljer.", "DataForThisReportHasBeenPurged": "Dataene for denne rapporten er mer enn %s måneder gamle og har blitt fjernet.", + "DataTableCombineDimensions": "Dimensjoner vises for seg selv %s Vis dimensjoner sammenslått", "DataTableExcludeAggregateRows": "Aggregerte rader vises %s Skjul dem", "DataTableHowToSearch": "Trykk enter eller klikk på søkeikonet for å søke", "DataTableIncludeAggregateRows": "Aggregerte rader er skjult %s Vis dem", + "DataTableShowDimensions": "Dimensjoner er kombinert %s Vis dimensjoner separert", + "DateInvalid": "Angitt kombinasjon av dato og periode er ugyldig. Velg en gyldig dato i datovelgeren.", "Default": "standard", + "DevicesSubcategoryHelp": "Enhetsdelen hjelper deg å forstå teknologien dine besøkende bruker for å besøke nettsiden din. Du vil finne rapporter om hvilken type enhet og spesifikke modeller for å skru på og optimisere din side for de mest populære enhetene.", "DonateCall1": "Det vil aldri koste noe å bruke Matomo, men det betyr ikke at det ikke koster oss noe å lage.", "DonateCall2": "Matomo trenger din fortsatte støtte for å vokse og blomstre.", + "DonateCall3": "Hvis u synes Matomo har gitt din virksomhet økt verdi kan du %1$sdonere%2$s eller %3$skjøpe en premiumsfunksjon%4$s. Hvert øre bidrar.", + "EndDate": "Sluttdato", + "EndShortcut": "Slutt", + "EngagementSubcategoryHelp1": "Interaksjonsdelen gir deg rapporter som hjelper deg å anslå hvor mange nye og tilbakevendende besøk du får. Du kan også gjennomse rapporter som gir gjennomsnittlig tid og antall sider per besøk, sågar også antall ganger en besøkende har vært på siden din, og hvor lenge det vanligvis går mellom avlagt besøk.", + "EngagementSubcategoryHelp2": "Dette kan hjelpe deg å optimalisere for frekvens og høy-interaksjonsbesøk i tillegg til å maksimere din rekkevidde.", + "EnterZenMode": "Gå inn i Zen-modus (skjul menyene)", + "ExceptionNotAllowlistedIP": "Du kan ikke bruke denne Matomo-installasjonen fordi din IP (%s) ikke tillates.", "ExcludeRowsWithLowPopulation": "All rader vises %s Ekskluder lav populasjon", + "ExitZenMode": "Avslutt Zen-modus (vis menyene)", + "ExpandSubtables": "Fold ut undertabeller", + "ExportFormat": "Eksportformat", + "ExportTooltip": "Merk: for å bruke generert eksportnettadresse må du angi en programsymbolidentitetsbekreftelse. Du kan sette opp disse symbolene i Administrasjon → Sikkerhet → Symbolidentitetsbekreftelser.", + "ExportTooltipWithLink": "Merk: For å bruke en generert eksportnettadresse må du angi en programsymbolidentitetsbekreftelse. Du kan sette opp disse symbolene i %1$s[Administrasjon → Sikkerhet → Identitetbekreftelsessymboler]%2$s. Erstatt %3$s i eksportnettadressen med ditt identitetbekreftelsessymbol. Advarsel: Aldri del nettadressen som har det virkelige symbolet med noen andre.", "ExternalHelp": "Hjelp (åpnes i ny fane)", "FlattenDataTable": "Rapporten er hierarkisk %s Gjør den flat", + "FlattenReport": "Fold sammen rapport", + "FormatMetrics": "Formater målinger", + "HideExportUrl": "Skjul eksport-nettadresse", + "HomeShortcut": "Hjem", "IncludeRowsWithLowPopulation": "Rader med lav populasjon er skjult %s Vis alle rader", "InjectedHostEmailBody": "Hei, jeg prøvde å få tilgang til Matomo i dag og ble møtt av «ukjent vertsnavn»-advarselen.", "InjectedHostEmailSubject": "Matomo ble åpnet med et ukjent vertsnavn: %s", "InjectedHostNonSuperUserWarning": "%1$sKlikk her for å få sikker tilgang til Matomo%2$s og for å fjerne denne advarselen. Du vil kanskje også kontakte din Matomo-administrator for å varsle dem om dette problemet (%3$sklikk her for å sende e-post%4$s).", "InjectedHostSuperUserWarning": "Matomo kan være feilkonfigurert (for eksempel hvis Matomo nylig var flyttet til en ny tjener eller ny URL). Du kan enten %1$sklikke her og legge til %2$s som et gyldig Matomo-vertsnavn (hvis du stoler på det)%3$s eller %4$sklikk her og gå til %5$s for sikker tilgang til Matomo%6$s.", "InjectedHostWarningIntro": "Du har tilgang til Matomo fra %1$s, men Matomo er konfigurert til å kjøre på adressen: %2$s.", + "JavascriptDisabled": "JavaScript må skrus på for at du skal kunne bruke Matomo i forvalgt visning.<br>Dog ser det ut til at det enten er avslått eller ustøttet i din nettleser.<br>For å bruke forvalgt visning kan du skru på JavaScript ved å endre dine nettleservalg, og så %1$sprøve igjen%2$s.<br>", + "JsDidntLoad": "Nettleseren din kunne ikke laste inn skript fra denne siden.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "Den ledende åpne analyseplattformen som respekterer personvernet.", + "MacPageDown": "Fn+høyrepil", + "MacPageUp": "Fn+venstrepil", "MainNavigation": "Hovednavigasjon", "Menu": "Meny", "MenuEntries": "Menyvalg", "NoPrivilegesAskPiwikAdmin": "Du er logget inn som «%1$s», men det ser ut til at du ikke har noen rettigheter satt i Matomo. %2$s Be din Matomo-administrator (klikk for å sende e-post)%3$s å gi deg «vis»-tilgang til et nettsted.", "NoSuchPage": "Denne siden finnes ikke", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Énklikksoppdateringen er ikke tilgjengelig siden du bruker Matomo med flere tjenere. Last ned siste versjon fra %1$s for å fortsette.", "OnlyForSuperUserAccess": "Denne widgeten vises kun i standardoversikten for brukere som har superbruker-tilgang.", + "PageDownShortcutDescription": "for å komme til bunnen av siden", + "PageUpShortcutDescription": "for å komme til toppen av siden", + "PeriodHasOnlyRawData": "Det ser ut til at rapporter for denne perioden ikke har blitt behandlet enda. Ønsker du å finne ut hva som skjer nå? Sjekk ut %1$sbesøksloggen%2$s eller velg et annet datofølge til rapportene er generert.", "PeriodRange": "Periode", "PivotBySubtable": "Denne rapporten er ikke pivotert %1$s Pivot etter %2$s", + "Profilable": "Profilerbar", "QuickAccessTitle": "Søk etter %s. Bruk piltastene for å navigere i søkeresultatene. Snarvei: trykk «f» for å søke.", + "QuickLinks": "Hurtiglenker", + "ReadMoreOnlineGuide": "Les mer om dette emnet i den nettbaserte veiledningen.", + "RemoveTotalsRowDataTable": "Rapporten viser totalt antall rader %s Fjern total", "ReportGeneratedOn": "Rapport generert %s", "ReportGeneratedXAgo": "Rapport generert for %s siden", + "ReportType": "Rapporttype", + "ReportWithMetadata": "Rapport med metadata", + "ReportingCategoryHelpPrefix": "Hvordan hjelper «%1$s > %2$s»-rapportsiden meg?", + "RowLimit": "Radgrense", + "SearchOnMatomo": "Søk etter «%1$s» på Matomo.org", + "SeeAvailableVersions": "Vis tilgjengelige versjoner", "Segments": "Segmenter", + "SharePiwikLong": "Hei. Du bør prøve den frie programvaren Matomo.\n\nDen lar deg spore besøk på nettisden din.", "SharePiwikShort": "Matomo! Gratis og åpen kildekode for nettstatistikk. Du eier dataene.", "ShareThis": "Del dette", + "ShortcutCalendar": "for å åpne kalenderen (d står for dato)", + "ShortcutHelp": "for å vise denne hjelpen", + "ShortcutSearch": "for å åpne søket (f står for finn)", + "ShortcutSegmentSelector": "for å åpne segmentvelger", + "ShortcutWebsiteSelector": "for å åpne nettsidevelger", + "ShortcutZenMode": "for Zen-modus", + "ShortcutsAvailable": "Tilgjengelige snarveier", + "ShowExportUrl": "Vis eksport-nettadresse", "ShowJSCode": "Vis JavaScript-koden til å sette inn på din nettside", "SkipToContent": "Hopp til innhold", + "SoftwareSubcategoryHelp": "Programvaredelen viser operativsystemene, nettleserne og programtilleggene dine besøkende bruker for å besøke siden, slik at du kan optimalisere den for å sikre at den er kompatibel med de mest populære oppsettene.", + "StandardReport": "Forvalgt rapport", + "StartDate": "Startdato", "SubscribeAndBecomePiwikSupporter": "Fortsett til en sikker betalingsside for kredittkort (Paypal) for å bli en Matomo-støttespiller!", "SupportPiwik": "Støtt Matomo!", + "SupportUsOn": "Støtt oss på", "SystemSummaryMysqlVersion": "MySQL-versjon", "SystemSummaryNActivatedPlugins": "%d aktiverte utvidelser", + "SystemSummaryNSegments": "%1$d segmenter", + "SystemSummaryNSegmentsWithBreakdown": "%1$d segmenter (%2$s forhåndsbehandlet, %3$s behandlet i sanntid)", "SystemSummaryNWebsites": "%d nettsteder", "SystemSummaryPhpVersion": "PHP-versjon", "SystemSummaryPiwikVersion": "Matomo-versjon", "SystemSummaryWidget": "Systemsammendrag", "TableNoData": "Ingen data for denne tabellen.", + "TechDeprecationWarning": "Fra Matomo versjon %1$s vil støtten for %2$s slutte. Mer info er å finne i %3$sdenne bloggposten%4$s.", + "ThanksFromAllOfUs": "Takk til deg fra alle oss i Matomo.", "ThereIsNoDataForThisReport": "Det finnes ingen data for denne rapporten.", "UnFlattenDataTable": "Rapporten er flat %s Gjør den hierarkisk", "UndoPivotBySubtable": "Denne rapporten er pivotert %s Angre pivot", "ViewAllPiwikVideoTutorials": "Se alle opplæringsvideoene for Matomo", + "VisitStatusOrdered": "Bestilt", + "VisitStatusOrderedThenAbandoned": "Bestilt, men forlot handlekurven", + "VisitTypeReturning": "Tilbakevendende", + "VisitTypeReturningCustomer": "Tidligere kunde", + "VisitorsCategoryHelp1": "Besøkssiden forteller deg noe om hvem dine besøkende er. Hvor de besøkte fra, hvilke enheter og nettlesere de brukte, og når de vanligvis besøker nettsiden din. Du kan i de store tallene forstå hvem publikumet ditt består av, og se etter avvik for å finne ut hvordan du kan øke besøkstallene.", + "VisitorsCategoryHelp2": "I tillegg til generell info om dine besøkende, kan du også bruke %1$sbesøksloggen%2$s for å finne ut hva som skjedde for hvert enkelte besøk.", + "VisitorsOverviewHelp": "Besøksoversikten hjelper deg å forstå hvor populær nettsiden din er. Diagrammer som viser hvor mange besøk den mottar over en valgt periode og gjennomsnittlig interaksjonsnivå for nøkkelaktiviteter tilbys, som f.eks. søk og nedlastninger.", "WebAnalyticsReports": "Nettstatistikkrapporter", - "YouAreUsingTheLatestVersion": "Du bruker den nyeste versjonen av Matomo!" + "YouAreUsingTheLatestVersion": "Du bruker den nyeste versjonen av Matomo!", + "YourDonationWillHelp": "Donasjonen din går direkte til utvikling av nye funksjoner og forbedringer i denne frie analyseplattformen. Dette betyr at gemenskapen alltid nyter godt av et verktøy som hegner om personvernet og lar deg kontrollere din data." } } diff --git a/plugins/CoreHome/lang/nl.json b/plugins/CoreHome/lang/nl.json index b63338dfdb..e4d8c849a8 100644 --- a/plugins/CoreHome/lang/nl.json +++ b/plugins/CoreHome/lang/nl.json @@ -1,33 +1,38 @@ { "CoreHome": { + "AdblockIsMaybeUsed": "Als je gebruik maakt van een reclame blokker, schakel deze a.u.b. uit zodat je zeker weet dat Matomo werkt zonder problemen.", "CategoryNoData": "Geen data in deze categorie. Probeer \"Toon alle data\".", + "ChangeCurrentWebsite": "Kies een website, huidig geselecteerde website: %s", + "ChangePeriod": "Wijzig tijdsspanne", "ChangeVisualization": "Verander visualisatie", - "ChangePeriod": "Wijzigingsperiode", "CheckForUpdates": "Controleer op updates", "CheckPiwikOut": "Bekijk Matomo eens!", + "ChooseX": "Kies %1$s", + "ClickRowToExpandOrContract": "Klik deze regel om de tabel te openen of te sluiten.", "ClickToEditX": "Klik om %s te bewerken", "ClickToSeeFullInformation": "Klik om de volledige informatie te zien", "CloseSearch": "Sluit zoeken", "CloseWidgetDirections": "U kunt deze widget sluiten door op het 'X'-icoon te klikken aan de bovenkant van de widget.", - "ChooseX": "Kies %1$s", + "CssDidntLoad": "De browser kan de style van deze pagina niet laden.", "DataForThisReportHasBeenPurged": "De data voor dit rapport was meer dan %s maanden oud en is reeds opgeschoond.", + "DataTableCombineDimensions": "Dimensies worden afzonderlijk weergegeven %s Toon dimensies gecombineerd", "DataTableExcludeAggregateRows": "Geagregeerde rijen worden getoond %s Verberg ze", - "DataTableIncludeAggregateRows": "Geagregeerde rijen zijn verborgen %s Toon ze", "DataTableHowToSearch": "Druk op enter of klik op het zoek icoon om te zoeken.", + "DataTableIncludeAggregateRows": "Geagregeerde rijen zijn verborgen %s Toon ze", "DataTableShowDimensions": "Dimensies zijn gecombineerd %s Toon dimensies apart", - "DataTableCombineDimensions": "Dimensies worden afzonderlijk weergegeven %s Toon dimensies gecombineerd", "Default": "standaard", "DonateCall1": "Matomo zal altijd gratis zijn om te gebruiken, maar dat wil niet zeggen dat het niks kost om te maken.", "DonateCall2": "Matomo heeft uw voortdurende steun nodig om te groeien en te bloeien.", "DonateCall3": "Als u het gevoel heeft dat Matomo van toegevoegde waarde is voor uw bedrijf of inspanningen, %1$soverweeg dan te doneren %2$s of %3$skoop een premium-functie%4$s. Elke cent helpt.", "EndShortcut": "Einde", "EnterZenMode": "Activeer Zen-modus (verberg menu's)", - "ExitZenMode": "Deactiveer Zen-modus (toon menu's)", "ExcludeRowsWithLowPopulation": "Alle rijen worden getoond %s Verberg de rijen met een lage populatie", + "ExitZenMode": "Deactiveer Zen-modus (toon menu's)", + "ExportFormat": "Export formaat", "ExternalHelp": "Help (opent in een nieuw tabblad)", "FlattenDataTable": "De rapportweergave is hierarchisch %s Maak het vlak", + "FlattenReport": "Rapport afvlakken", "FormatMetrics": "Waarden opmaken", - "ShowExportUrl": "Toon Export URL", "HideExportUrl": "Verberg Export URL", "HomeShortcut": "Home", "IncludeRowsWithLowPopulation": "Rijen met een lage populatie zijn verborgen %s Laat alle rijen zien", @@ -36,66 +41,61 @@ "InjectedHostNonSuperUserWarning": "%1$sKlik hier om Matomo veilig te benaderen%2$s en deze waarschuwing te verwijderen. Je verwittigt best ook je Matomo beheerder en meld hen dit probleem (%3$sKlik hier om te emailen%4$s).", "InjectedHostSuperUserWarning": "Matomo is waarschijnlijk verkeerd geconfigureerd (bijv. Matomo werd verplaatst naar een nieuwe server of URL). %1$sKlik hier en voeg %2$s toe als een toegestane Matomo hostnaam indien je die vertrouwd%3$s, of %4$sklik hier en ga naar %5$s om Matomo veilig te banaderen%6$s.", "InjectedHostWarningIntro": "Je bezoekt nu Matomo van %1$s, maar Matomo is geconfigureerd om op dit adres te draaien: %2$s.", - "VisitStatusOrdered": "Besteld", - "VisitStatusOrderedThenAbandoned": "Besteld, daarna winkelwagen achtergelaten", - "VisitTypeReturning": "Terugkerend", - "VisitTypeReturningCustomer": "Terugkerende klant", + "JsDidntLoad": "De browser kan het script van deze website niet laden.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "Het leidende open analytics platform dat privacy respecteerd.", + "MacPageDown": "Fn + Pijl naar rechts", + "MacPageUp": "Fn + Pijl naar links", "MainNavigation": "Hoofdnavigatie", "Menu": "Menu", + "MenuEntries": "Menu-items", "NoPrivilegesAskPiwikAdmin": "U bent aangemeld as '%1$s'. Maar het lijkt er op dat u geen rechten hebt op Matomo te bezoeken. %2$sVraag aan uw webmaster (klik hier voor e-mail)%3$s of hij u de juiste rechten wilt geven om de statistieken te bekijken.", + "NoSuchPage": "Deze pagina bestaat niet", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "De één-klik update is niet beschikbaar wanneer Matomo is geïnstalleerd over meerdere servers. Download de laatste versie van Matomo via %1$s om verder te gaan.", "OnlyForSuperUserAccess": "Het widget wordt alleen getoond in het standaard dashbord aan gebruikers met Super User toegang.", + "PageDownShortcutDescription": "om onderaan de pagina te komen", + "PageUpShortcutDescription": "om bovenaan de pagina te komen", "PeriodRange": "Bereik", + "PivotBySubtable": "Dit rapport wordt niet als een draaitabel getoond, %1$s maak een draaitabel op basis van %2$s", + "QuickAccessTitle": "Zoeken naar %s. Gebruik de pijltjestoetsen om door de zoekopdrachten te navigeren. Shortcut: Druk 'f' om te zoeken.", + "ReadMoreOnlineGuide": "Lees meer over dit onderwerp in de online handleiding.", "ReportGeneratedOn": "Rapport gegenereerd op %s", "ReportGeneratedXAgo": "Rapport %s geleden gegenereerd", + "ReportType": "Rapport type", + "ReportWithMetadata": "Rapport met metadata", + "RowLimit": "Rij limiet", + "SeeAvailableVersions": "Zie Beschikbare Versies", + "Segments": "Segmenten", "SharePiwikShort": "Matomo! Gratis en open source web analyse. Beheer je data.", "ShareThis": "Deel dit", - "ShortcutsAvailable": "Beschikbare snelkoppelingen", - "ShortcutZenMode": "voor Zen mode", - "ShortcutSegmentSelector": "om de Segment selector te openen", - "ShortcutWebsiteSelector": "om de Website selector te openen", "ShortcutCalendar": "kalender openen (d staat voor Datum)", - "ShortcutSearch": "zoekveld openen (f staat voor Find)", "ShortcutHelp": "om deze help te tonen", + "ShortcutSearch": "zoekveld openen (f staat voor Find)", + "ShortcutSegmentSelector": "om de Segment selector te openen", + "ShortcutWebsiteSelector": "om de Website selector te openen", + "ShortcutZenMode": "voor Zen mode", + "ShortcutsAvailable": "Beschikbare snelkoppelingen", + "ShowExportUrl": "Toon Export URL", "ShowJSCode": "Toon de in te voegen JavaScript code", "SkipToContent": "Ga naar de inhoud", + "StandardReport": "Standaard rapport", "SubscribeAndBecomePiwikSupporter": "Ga verder naar een veilige kredietkaart betaalpagina (Paypal) en wordt een Matomo Supporter!", "SupportPiwik": "Ondersteun Matomo!", + "SystemSummaryMysqlVersion": "MySQL-versie", + "SystemSummaryNActivatedPlugins": "%d geactiveerde plugins", + "SystemSummaryNWebsites": "%d websites", + "SystemSummaryPhpVersion": "PHP-versie", + "SystemSummaryPiwikVersion": "Matomo-versie", + "SystemSummaryWidget": "Systeem samenvatting", "TableNoData": "Geen gegevens voor deze tabel.", "ThereIsNoDataForThisReport": "Er zijn geen gegevens voor dit rapport.", "UnFlattenDataTable": "De rapportweergave is vlak %s Maak het hierarchisch", + "UndoPivotBySubtable": "Dit rapport wordt als een draaitabel getoond, %s schakel de draaitabel uit.", "ViewAllPiwikVideoTutorials": "Bekijk alle Matomo Video Tutorials", + "VisitStatusOrdered": "Besteld", + "VisitStatusOrderedThenAbandoned": "Besteld, daarna winkelwagen achtergelaten", + "VisitTypeReturning": "Terugkerend", + "VisitTypeReturningCustomer": "Terugkerende klant", "WebAnalyticsReports": "Web Analyse rapporten", - "YouAreUsingTheLatestVersion": "Je gebruikt de laatste versie van Matomo!", - "ClickRowToExpandOrContract": "Klik deze regel om de tabel te openen of te sluiten.", - "UndoPivotBySubtable": "Dit rapport wordt als een draaitabel getoond, %s schakel de draaitabel uit.", - "NoSuchPage": "Deze pagina bestaat niet", - "PageUpShortcutDescription": "om bovenaan de pagina te komen", - "PageDownShortcutDescription": "om onderaan de pagina te komen", - "PivotBySubtable": "Dit rapport wordt niet als een draaitabel getoond, %1$s maak een draaitabel op basis van %2$s", - "SystemSummaryWidget": "Systeem samenvatting", - "SystemSummaryNWebsites": "%d websites", - "SystemSummaryNActivatedPlugins": "%d geactiveerde plugins", - "SystemSummaryPiwikVersion": "Matomo-versie", - "SystemSummaryMysqlVersion": "MySQL-versie", - "SystemSummaryPhpVersion": "PHP-versie", - "QuickAccessTitle": "Zoeken naar %s. Gebruik de pijltjestoetsen om door de zoekopdrachten te navigeren. Shortcut: Druk 'f' om te zoeken.", - "MenuEntries": "Menu-items", - "Segments": "Segmenten", - "OneClickUpdateNotPossibleAsMultiServerEnvironment": "De één-klik update is niet beschikbaar wanneer Matomo is geïnstalleerd over meerdere servers. Download de laatste versie van Matomo via %1$s om verder te gaan.", - "CssDidntLoad": "De browser kan de style van deze pagina niet laden.", - "JsDidntLoad": "De browser kan het script van deze website niet laden.", - "AdblockIsMaybeUsed": "Als je gebruik maakt van een reclame blokker, schakel deze a.u.b. uit zodat je zeker weet dat Matomo werkt zonder problemen.", - "ChangeCurrentWebsite": "Kies een website, huidig geselecteerde website: %s", - "LeadingAnalyticsPlatformRespectsYourPrivacy": "Het leidende open analytics platform dat privacy respecteerd.", - "MacPageUp": "Fn + Pijl naar links", - "MacPageDown": "Fn + Pijl naar rechts", - "ReportType": "Rapport type", - "RowLimit": "Rij limiet", - "ExportFormat": "Export formaat", - "StandardReport": "Standaard rapport", - "FlattenReport": "Rapport afvlakken", - "ReportWithMetadata": "Rapport met metadata", - "ReadMoreOnlineGuide": "Lees meer over dit onderwerp in de online handleiding.", - "SeeAvailableVersions": "Zie Beschikbare Versies" + "YouAreUsingTheLatestVersion": "Je gebruikt de laatste versie van Matomo!" } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/pt-br.json b/plugins/CoreHome/lang/pt-br.json index 1cfe00e68e..09c750bcaf 100644 --- a/plugins/CoreHome/lang/pt-br.json +++ b/plugins/CoreHome/lang/pt-br.json @@ -16,6 +16,7 @@ "CloseWidgetDirections": "Você pode fechar esta ferramenta clicando no ícone \"X\" na parte superior do widget.", "CssDidntLoad": "Seu navegador não conseguiu carregar o estilo desta página.", "CustomLimit": "Limite personalizado", + "DataForThisReportHasBeenDisabled": "A segmentação está atualmente desabilitada para este relatório. Verifique %1$sesta FAQ%2$s para obter mais detalhes.", "DataForThisReportHasBeenPurged": "Os dados para este relatório possuem mais de %s meses e foram excluídos.", "DataTableCombineDimensions": "Dimensões são mostradas separadamente %s Mostrar dimensões combinadas", "DataTableExcludeAggregateRows": "As linhas agregadas encontram-se visíveis %s Oculte-as", @@ -28,6 +29,7 @@ "DonateCall1": "Matomo sempre custará nada para usar, mas isso não significa que não nos custa nada para fazê-lo.", "DonateCall2": "Matomo precisa do seu apoio continuado para crescer e prosperar.", "DonateCall3": "Se você sentir que Matomo tem acrescentado valor significativo para seu negócio ou empreendimento, %1$sconsidere doar para o projeto%2$s ou %3$s comprar um recurso premium%4$s. Cada centavo vai ajudar.", + "EndDate": "Data Final", "EndShortcut": "Fim", "EngagementSubcategoryHelp1": "A seção Engajamento fornece relatórios que ajudam a quantificar quantos visitantes novos e recorrentes você recebe. Você também pode revisar relatórios que detalham o tempo médio e o número de páginas por visita, bem como o número de vezes que um visitante acessou seu site e o número mais comum de dias entre as visitas.", "EngagementSubcategoryHelp2": "Isso pode ajudá-lo a otimizar a frequência e as visitas de alta interação, além de maximizar seu alcance.", @@ -97,6 +99,7 @@ "SkipToContent": "Ir para o conteúdo", "SoftwareSubcategoryHelp": "A seção Software mostra os sistemas operacionais, navegadores e plugins que seus visitantes estão usando para acessar o site para que você possa otimizá-lo e garantir que seja totalmente compatível com as configurações mais populares.", "StandardReport": "Relatório padrão", + "StartDate": "Data Inicial", "SubscribeAndBecomePiwikSupporter": "Proceder a uma página de pagamento seguro através de cartão de crédito (Paypal) para se tornar um apoiador do Matomo!", "SupportPiwik": "Apóie o Matomo!", "SupportUsOn": "Apoie-nos em", diff --git a/plugins/CoreHome/lang/sl.json b/plugins/CoreHome/lang/sl.json index 8dbf266514..9d06b1c116 100644 --- a/plugins/CoreHome/lang/sl.json +++ b/plugins/CoreHome/lang/sl.json @@ -1,8 +1,30 @@ { "CoreHome": { "CategoryNoData": "V tej kategoriji ni podatkov. Poizkusite \"Vključiti celotno populacijo\".", + "ChangePeriod": "Spremeni obdobje", + "ChangeVisualization": "Spremenite način prikazovanja", "CheckForUpdates": "Preveri za posodobitve", + "CheckPiwikOut": "Preverite Matomo!", + "ChooseX": "Izberite %1$s", + "ClickToEditX": "Kliknite za urejanje %s", + "ClickToSeeFullInformation": "Kliknite za ogled vseh informacij", + "CloseSearch": "Zapri iskanje", + "CloseWidgetDirections": "Ta pripomoček lahko zaprete s klikom na ikono 'X' na vrhu pripomočka.", + "DataForThisReportHasBeenPurged": "Podatki za to poročilo so stari več kot %s mesecev in so bili očiščeni.", + "DataTableCombineDimensions": "Mere so prikazane ločeno %s Prikaži kombinirane dimenzije", + "DataTableExcludeAggregateRows": "Prikazane so združene vrstice %s Skrij jih", + "DataTableHowToSearch": "Pritisnite enter ali kliknite na ikono za iskanje", + "DataTableIncludeAggregateRows": "Skrite so združene vrstice %s Prikaži jih", + "DataTableShowDimensions": "Mere so kombinirane %s Prikaži mere ločeno", + "DateInvalid": "Navedena kombinacija datuma in obdobja je neveljavna. Prosimo, izberite veljaven datum v izbirniku datumov.", "Default": "privzeto", + "DonateCall1": "Uporaba Matoma je brezplačna, vendar to ne pomeni, da nas izdelava nič ne stane.", + "DonateCall2": "Matomo potrebuje vašo stalno podporo, da raste in uspeva.", + "DonateCall3": "Če menite, da je Matomo vašemu podjetju ali prizadevanju dodal pomembno vrednost, %1$s prosimo, razmislite o donaciji %2$s ali %3$s nakupu vrhunske funkcije%4$s. Vsak peni bo pomagal.", + "EndShortcut": "Konec", + "EnterZenMode": "Vstopite v način Zen (skrij menije)", + "ExceptionNotAllowlistedIP": "Tega Matoma ne morete uporabljati, ker vaš IP %s ni dovoljen.", + "ExitZenMode": "Zapustite način Zen (prikažite menije)", "NoPrivilegesAskPiwikAdmin": "Vpisani ste kot '%1$s', vendar v Matomo-u nimate nastavljenih nobenih pooblastil. %2$s Poprosite vašega Matomo administratorja (klik za email)%3$s naj vam da pooblastila za ogled določene(ih) strani.", "PeriodRange": "Razpon", "ReportGeneratedOn": "Poročilo ustvarjano na %s", @@ -10,4 +32,4 @@ "ShowJSCode": "Prikaži JavaScript kodo za vstavljanje", "ThereIsNoDataForThisReport": "Za to poročilo ni podatkov." } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/sq.json b/plugins/CoreHome/lang/sq.json index 685d25f200..fffd17c8fe 100644 --- a/plugins/CoreHome/lang/sq.json +++ b/plugins/CoreHome/lang/sq.json @@ -1,128 +1,132 @@ { "CoreHome": { - "CategoryNoData": "Pa të dhëna për këtë kategori. Provoni të \"Përfshini tërë popullatën\".", - "ChangeVisualization": "Ndryshoni vizualizimin", + "AdblockIsMaybeUsed": "Në rast se përdorni ndonjë bllokues reklamash, ju lutemi, çaktivizojeni për këtë sajt, që të siguroni punën pa probleme të Matomo-s.", + "AddTotalsRowDataTable": "Raporti s’shfaq rreshtin e tërësoreve %s Shfaqe rreshtin e tërësoreve", + "CategoryNoData": "Pa të dhëna për këtë kategori. Provoni të “Përfshini tërë popullatën”.", + "ChangeCurrentWebsite": "Zgjidhni një sajt, sajti i përzgjedhur tani: %s", "ChangePeriod": "Ndryshoni periudhën", + "ChangeVisualization": "Ndryshoni vizualizimin", "CheckForUpdates": "Kontrollo për përditësime", "CheckPiwikOut": "Provojeni Matomo-s!", + "ChooseX": "Zgjidhni %1$s", + "ClickRowToExpandOrContract": "Që të zgjeroni ose tkurrni nëntabelën, klikoni mbi këtë rresht.", "ClickToEditX": "Klikoni që të përpunoni %s", "ClickToSeeFullInformation": "Klikoni që të shihni të dhënat e plota", "CloseSearch": "Mbylle kërkimin", - "CloseWidgetDirections": "Këtë widget mund ta mbyllni duke klikuar mbi ikonën 'X' në krye të widget-it.", - "ChooseX": "Zgjidhni %1$s", - "DataForThisReportHasBeenPurged": "Të dhënat e këtij raporti janë më të vjetra se %s muaj dhe u pastruan.", - "DataTableExcludeAggregateRows": "Grumbulli i rreshtave është i shfaqur %s Fshihini", - "DataTableIncludeAggregateRows": "Grumbulli i rreshtave është i fshehur %s Shfaqini", - "DataTableHowToSearch": "Shtypni tastin Enter ose klikoni ikonën e kërkimit që të kërkoni", - "DataTableShowDimensions": "Përmasat janë të ndërthurura %s Shfaqi përmasat ndarazi", + "CloseWidgetDirections": "Këtë “widget” mund ta mbyllni duke klikuar mbi ikonën 'X' në krye të widget-it.", + "CssDidntLoad": "Shfletuesi juaj s’qe në gjendje të ngarkonte stilin e kësaj faqeje.", + "CustomLimit": "Kufi vetjak", + "DataForThisReportHasBeenDisabled": "Segmentimi është aktualisht i çaktivizuar për këtë raport. Për më tepër hollësi, ju lutemi, shihni %1$skëto PBR%2$s.", + "DataForThisReportHasBeenPurged": "Të dhënat e këtij raporti janë më të vjetra se %s muaj dhe u spastruan.", "DataTableCombineDimensions": "Përmasat janë shfaqur ndarazi %s Shfaqi përmasat të ndërthurura", + "DataTableExcludeAggregateRows": "Shfaqen rreshtat përmbledhur %s Fshihi", + "DataTableHowToSearch": "Që të kërkoni, shtypni tastin Enter, ose klikoni ikonën e kërkimit", + "DataTableIncludeAggregateRows": "Rreshtat e përmbledhur janë të fshehur %s Shfaqi", + "DataTableShowDimensions": "Përmasat janë të ndërthurura %s Shfaqi përmasat ndarazi", "DateInvalid": "Kombinimi dhënë për datë dhe periudhë është i pavlefshëm. Ju lutemi, zgjidhni një datë të vlefshme te përzgjedhësi i datave.", "Default": "parazgjedhje", - "DonateCall1": "Përdorimi i Matomo-a s’do t’ju kushtojë kurrë një dysh, por kjo s’do të thotë që neve nuk na kushton krijimi i tij.", - "DonateCall2": "Matomo lyp përkrahjen tuaj që të rritet dhe lulëzojë.", - "DonateCall3": "Nëse jeni të mendimit se Matomo ka sjellë një shtim të vyer të biznesit apo në përpjekjet tuaja, %1$sju lutemi, shihni mundësinë e dhurimit%2$s ose %3$sblerjes së paketës me pagesë%4$s. Çdo qindarkë do të na ndihmonte.", - "EndShortcut": "Fund", + "DevicesSubcategoryHelp": "Ndarja Pajisje ju ndihmon të njihni teknologjinë që vizitorët përdorin në sajtin tuaj. Do të shihni raporte mbi llojin e pajisjes dhe modele specifike, që t’ju bëjnë të mundur ta optimizoni sajtin për shumicën e pajisjeve popullore.", + "DonateCall1": "Përdorimi i Matomo-a s’do t’ju kushtojë kurrë një dysh, por kjo s’do të thotë që neve s’na kushton krijimi i tij.", + "DonateCall2": "Që të rritet dhe lulëzojë, Matomo lyp përkrahjen tuaj.", + "DonateCall3": "Nëse jeni të mendimit se Matomo ka sjellë një shtim të vyer në biznesin apo në përpjekjet tuaja, %1$sju lutemi, shihni mundësinë e dhurimit%2$s, ose %3$sblerjes së paketës me pagesë%4$s. Çdo qindarkë do të na ndihmonte.", + "EndDate": "Datë Përfundimi", + "EndShortcut": "Përfundim", + "EngagementSubcategoryHelp1": "Ndarja Angazhim ju furnizon raporte që ndihmojnë të kini një ide mbi sasinë e vizitave të reja dhe të rikthyerish që përfiton sajti juaj. Mund të shqyrtoni edhe raporte që japin kohën mesatare dhe numrin e faqeve sipas vizitash, si dhe numrin e herëve që një vizitor ka qenë në sajtin tuaj dhe numrin më të zakonshëm të ditëve mes vizitash.", + "EngagementSubcategoryHelp2": "Kjo mund t’ju ndihmojë të bëni optimizim për shpeshti dhe vizita me shkallë të lartë ndërveprimi, përveç se për të kapur maksimumin e shtrirjes tuaj.", "EnterZenMode": "Kalo nën mënyrën Zen (fshihi menutë)", - "ExitZenMode": "Dil nga mënyra Zen (shfaqi menutë)", - "ExceptionNotAllowlistedIP": "S’mund të përdorni këtë instancë të Matomo-s, ngaqë nuk lejohet IP-ja juaj %s.", + "ExceptionNotAllowlistedIP": "S’mund të përdorni këtë instancë të Matomo-s, ngaqë IP-ja juaj %s s’është e lejuar.", "ExcludeRowsWithLowPopulation": "Po shfaqen krejt rreshtat %s Përjashtoni popullatat e ulëta", + "ExitZenMode": "Dil nga mënyra Zen (shfaqi menutë)", + "ExpandSubtables": "Zgjeroji nëntabelat", + "ExportFormat": "Format eksportimi", + "ExportTooltip": "Shënim: Për të përdorur URL-në e prodhuar për eksportim, do t’ju duhet të specifikoni një aplikacion mirëfilltësimi token-ësh. Këta token-ë mund t’i formësoni te Përgjegjës -> Siguri -> Token-ë Mirëfilltësimi.", + "ExportTooltipWithLink": "Shënim: Për të përdorur URL-në e prodhuar për eksportim, do t’ju duhet të specifikoni një aplikacion mirëfilltësimi token-ësh. Këta token-ë mund t’i formësoni te %1$s[Përgjegjës -> Siguri -> Token-ë Mirëfilltësimi]%2$s. Zëvendësoni %3$s te URL Eksportimi me token-in tuaj të Mirëfilltësimit. Kujdes: Mos ia jepni kujt tjetër URL-në me token-in real.", "ExternalHelp": "Ndihmë (hapet në skedë të re)", - "FlattenDataTable": "Raporti është hierarkik %s Bëjeni të sheshtë", + "FlattenDataTable": "Raporti është hierarkik %s Bëje të sheshtë", + "FlattenReport": "Raport i sheshtë", "FormatMetrics": "Statistika formatesh", - "ShowExportUrl": "Shfaq URL Eksportimi", "HideExportUrl": "Fshihe URL-në e Eksportimit", "HomeShortcut": "Kreu", - "SupportUsOn": "Na përkrahni në", "IncludeRowsWithLowPopulation": "Janë fshehur rreshta me popullatë të ulët %s Shfaqi krejt rreshtat", "InjectedHostEmailBody": "Tungjatjeta, provova të hyj në Matomo sot dhe ndesha sinjalizimin për strehëemër të panjohur.", "InjectedHostEmailSubject": "Te Matomo u hy me një strehëemër të panjohur: %s", "InjectedHostNonSuperUserWarning": "%1$sKlikoni këtu që të hyni te Matomo pa rrezik%2$s dhe që të hiqet ky sinjalizim. Mund të doni edhe të lidheni me përgjegjësin e instalimit tuaj të Matomo-s dhe t’ia bëni të ditur këtë problem (%3$sklikoni këtu që t’ia dërgoni me email%4$s).", "InjectedHostSuperUserWarning": "Matomo mund të jetë i keqformësuar (për shembull, në rast se Matomo tani së fundi u kalua në një shërbyes të ri ose URL të re). Mundeni ose %1$stë klikoni këtu dhe ta shtoni %2$s si një strehëemër të vlefshëm Matomo (nëse i zini besë)%3$s, ose %4$stë klikoni këtu dhe të kaloni te %5$s për hyrje të parrezik në Matomo%6$s.", "InjectedHostWarningIntro": "Po hyni në Matomo që prej %1$s, por Matomo qe formësuar të xhirojë në këtë adresë: %2$s.", - "JavascriptDisabled": "Që të mund të përdorni Matomo-n në parjen standarde duhet të aktivizohet JavaScript-i.<br \/>Por ja që duket se ose JavaScript-i është i çaktivizuar, ose nuk mbulohet nga shfletuesi juaj.<br \/>Që të përdorni parjen standarde, aktivizoni JavaScript-in duke ndryshuar mundësitë përkatëse te shfletuesi juaj, mandej %1$sriprovoni%2$s.<br \/>", - "VisitStatusOrdered": "Të porositura", - "VisitStatusOrderedThenAbandoned": "Shportë e të Porositurave mandej të Braktisura", - "VisitTypeReturning": "I rikthyer", - "VisitTypeReturningCustomer": "Klient i Rikthyer", + "JavascriptDisabled": "Që të mund të përdorni Matomo-n në parjen standarde, duhet të aktivizohet JavaScript-i.<br>Por ja që duket se ose JavaScript-i është i çaktivizuar, ose nuk mbulohet nga shfletuesi juaj.<br>Që të përdorni parjen standarde, aktivizoni JavaScript-in duke ndryshuar mundësitë përkatëse te shfletuesi juaj, mandej %1$sriprovoni%2$s.<br>", + "JsDidntLoad": "Shfletuesi juaj s’qe në gjendje të ngarkonte programthet e kësaj faqeje.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "Platforma kryesuese e analizave të hapura që respekton privatësinë tuaj.", + "MacPageDown": "Fn+tasti shigjetë Djathtas", + "MacPageUp": "Fn+tasti shigjetë Majtas", "MainNavigation": "Lëvizja kryesore", - "YourDonationWillHelp": "Dhurimi juaj do të ndihmojë drejtpërsëdrejti për financim veçorish të reja dhe përmirësime të kësaj platforme statistikash dhe analizimesh me burim të hapët. Kjo do të thotë që bashkësia do të përfitojë përherë nga një mjet që mbron privatësinë dhe ju lejon të jeni në kontroll të të dhënave tuaja.", - "ThanksFromAllOfUs": "Faleminderit prej krejt nesh në Matomo!", "Menu": "Menu", - "NoPrivilegesAskPiwikAdmin": "Jeni i futur si '%1$s' por duket se s’keni leje të rregulluara për ju në Matomo. %2$s Kërkojini administratorit tuaj te Matomo (klikoni që t’i dërgoni email)%3$s që t’ju japë të drejta 'parjesh' te një sajt.", - "OnlyForSuperUserAccess": "Ky widget u shfaqet te pulti parazgjedhje vetëm përdoruesve që kanë hyrje si Superpërdorues.", + "MenuEntries": "Zëra menuje", + "NoPrivilegesAskPiwikAdmin": "Jeni i futur si '%1$s', por duket se s’keni leje të rregulluara për ju në Matomo. %2$s Kërkojini administratorit tuaj te Matomo (klikoni që t’i dërgoni email)%3$s që t’ju japë të drejta 'parjesh' te një sajt.", + "NoSuchPage": "Kjo faqe s’ekziston", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "S’kryeni dot përditësim me një klikim, ngaqë po e përdorni Matomo-n me disa shërbyes. Ju lutemi, që të mund të vazhdohet, shkarkoni versionin më të ri prej %1$s.", + "OnlyForSuperUserAccess": "Ky “widget” u shfaqet te pulti parazgjedhje vetëm përdoruesve që kanë hyrje si Superpërdorues.", + "PageDownShortcutDescription": "që të shkohet në fund të faqes", + "PageUpShortcutDescription": "që të shkohet në krye të faqes", + "PeriodHasOnlyRawData": "Duket sikur raportet për këtë periudhë s’janë përpunuar ende. Doni të shihni ç’po ndodh tani? Shihni %1$sRegjistër vizitash%2$s, ose zgjidhni një periudhë tjetër datash, deri sa të prodhohen raportet.", "PeriodRange": "Interval", + "PivotBySubtable": "Ky raport s’është rrotulluar %1$s Rrotullojeni sipas %2$s", + "Profilable": "E profilizueshme", + "QuickAccessTitle": "Kërkoni për %s. Përdorni tastet shigjetë që të lëvizni nëpër përfundimet e kërkimit. Shkurtore tastiere: Shtypni tastin 'f' që të kërkohet.", + "QuickLinks": "Lidhje të Shpejta", + "ReadMoreOnlineGuide": "Lexoni më tepër rreth kësaj teme te udhërrëfyesi në internet.", + "RemoveTotalsRowDataTable": "Raporti shfaq rreshtin e tërësoreve %s Hiqe rreshtin e tërësoreve", "ReportGeneratedOn": "Raport i prodhuar më %s", "ReportGeneratedXAgo": "Raport i prodhuar %s më parë", + "ReportType": "Lloj raport", + "ReportWithMetadata": "Raport me tejtëdhëna", + "ReportingCategoryHelpPrefix": "Si më ndihmon faqja e raportimeve “%1$s > %2$s”?", + "RowLimit": "Kufi i papërpunuar", + "SearchOnMatomo": "Kërkoni për '%1$s' te Matomo.org", + "SeeAvailableVersions": "Shihni Versione të Gatshëm", + "Segments": "Segmente", "SharePiwikLong": "Njatjeta! Sapo gjeta një program të lirë shumë të mirë: Matomo!\n\nMatomo do t’ju lejojë të ndiqni falas vizitorët në sajtin tuaj. Duhet ta provoni medoemos!", - "SharePiwikShort": "Matomo! Analiza web të lira\/libre. Jini zot i të dhënave tuaja.", + "SharePiwikShort": "Matomo! Analiza web të lira/libre. Jini zot i të dhënave tuaja.", "ShareThis": "Ndajeni me të tjerët këtë", - "ShortcutsAvailable": "Shkurtore të gatshme", - "ShortcutZenMode": "për mënyrën Zen", - "ShortcutSegmentSelector": "për hapje përzgjedhësi Segmentesh", - "ShortcutWebsiteSelector": "për hapje përzgjedhësi Sajtesh", "ShortcutCalendar": "për hapje kalendarësh (d nënkupton Datë)", - "ShortcutSearch": "për hapje kërkimesh (g nënkupton Gjej)", "ShortcutHelp": "për shfaqjen e kësaj ndihme", + "ShortcutSearch": "për hapje kërkimesh (f nënkupton Find, pra Gjej në shqip)", + "ShortcutSegmentSelector": "për hapje përzgjedhësi Segmentesh", + "ShortcutWebsiteSelector": "për hapje përzgjedhësi Sajtesh", + "ShortcutZenMode": "për mënyrën Zen", + "ShortcutsAvailable": "Shkurtore të gatshme", + "ShowExportUrl": "Shfaq URL Eksportimi", "ShowJSCode": "Shfaqe kodin JavaScript që duhet futur", "SkipToContent": "Kalo te lënda", - "SubscribeAndBecomePiwikSupporter": "Vazhdoni te një faqe e sigurt pagesash me kartë krediti (Paypal) që të bëheni një Përkrahës i Matomo-s!", + "SoftwareSubcategoryHelp": "Ndarja Software ju shfaq sistemet operative, shfletues dhe shtojca që vizitorët tuaj përdorin për sajtin, që të mund ta optimizoni sajtin tuaj për të garantuar se është plotësisht i përputhshëm me formësimet më popullore.", + "StandardReport": "Raport standard", + "StartDate": "Datë Fillimi", + "SubscribeAndBecomePiwikSupporter": "Vazhdoni te një faqe e sigurt pagesash me kartë krediti (Paypal), që të bëheni një Përkrahës i Matomo-s!", "SupportPiwik": "Përkrahni Matomo-n!", - "TableNoData": "S’ka të dhëna për këtë tabelë.", - "ThereIsNoDataForThisReport": "Nuk ka të dhëna për këtë raport.", - "UnFlattenDataTable": "Raporti është i sheshtë %s Bëjeni hierarkik", - "RemoveTotalsRowDataTable": "Raporti shfaq rreshtin e tërësoreve %s Hiqe rreshtin e tërësoreve", - "AddTotalsRowDataTable": "Raporti s’shfaq rreshtin e tërësoreve %s Shfaqe rreshtin e tërësoreve", - "ViewAllPiwikVideoTutorials": "Shihini krejt Përkujdesoret Video për Matomo-n", - "WebAnalyticsReports": "Raporte Analizash Web", - "YouAreUsingTheLatestVersion": "Po përdorni versionin më të ri të Matomo-s!", - "ClickRowToExpandOrContract": "Klikoni mbi këtë rresht që të zgjeroni ose tkurrni nëntabelën.", - "UndoPivotBySubtable": "Ky raport është rrotulluar %s Zhbëjeni rrotullimin", - "NoSuchPage": "Kjo faqe s’ekziston", - "PageUpShortcutDescription": "që të shkohet në krye të faqes", - "PageDownShortcutDescription": "që të shkohet në fund të faqes", - "PivotBySubtable": "Ky raport s’është rrotulluar %1$s Rrotullojeni sipas %2$s", - "SystemSummaryWidget": "Përmbledhje Sistemi", - "SystemSummaryNWebsites": "%d sajte", + "SupportUsOn": "Na përkrahni në", + "SystemSummaryMysqlVersion": "Version MySQL-je", + "SystemSummaryNActivatedPlugins": "%d shtojca të aktivizuara", "SystemSummaryNSegments": "%1$d segmente", "SystemSummaryNSegmentsWithBreakdown": "%1$d segmente (%2$s të parapërpunuar, %3$s të përpunuar aty për aty)", - "SystemSummaryNActivatedPlugins": "%d shtojca të aktivizuara", - "SystemSummaryPiwikVersion": "Version Matomo", - "SystemSummaryMysqlVersion": "Version MySQL-je", + "SystemSummaryNWebsites": "%d sajte", "SystemSummaryPhpVersion": "Version PHP-je", - "QuickAccessTitle": "Kërkoni për %s. Përdorni tastet shigjetë që të lëvizni nëpër përfundimet e kërkimit. Shkurtore tastiere: Shtypni 'f' që të kërkohet.", - "MenuEntries": "Zëra menuje", - "Segments": "Segmente", - "OneClickUpdateNotPossibleAsMultiServerEnvironment": "S’kryeni dot përditësim me një klikim, ngaqë po e përdorni Matomo-n me disa shërbyes. Ju lutemi, që të mund të vazhdohet, shkarkoni versionin më të ri prej %1$s.", - "CssDidntLoad": "Shfletuesi juaj s’qe në gjendje të ngarkonte stilin e kësaj faqeje.", - "JsDidntLoad": "Shfletuesi juaj s’qe në gjendje të ngarkonte programthet e kësaj faqeje.", - "AdblockIsMaybeUsed": "Në rast se përdorni ndonjë bllokues reklamash, ju lutemi, çaktivizojeni për këtë sajt, që të siguroni punën pa probleme të Matomo-s.", - "ChangeCurrentWebsite": "Zgjidhni një sajt, sajti i përzgjedhur tani: %s", - "LeadingAnalyticsPlatformRespectsYourPrivacy": "Platforma kryesuese e analizave të hapura që respekton privatësinë tuaj.", - "MacPageUp": "Fn+shigjeta Majtas", - "MacPageDown": "Fn+shigjeta Djathtas", - "ReportType": "Lloj raport", - "RowLimit": "Kufi i papërpunuar", - "CustomLimit": "Kufi vetjak", - "ExportFormat": "Format eksportimi", - "ExportTooltip": "Shënim: Për të përdorur URL-në e prodhuar për eksport, do t’ju duhet të specifikoni një aplikacion mirëfilltësimi token-ësh. Këta token-ë mund t’i formësoni te Përgjegjës -> Siguri -> Token-ë Mirëfilltësimi.", - "ExportTooltipWithLink": "Shënim: Për të përdorur URL-në e prodhuar për eksport, do t’ju duhet të specifikoni një aplikacion mirëfilltësimi token-ësh. Këta token-ë mund t’i formësoni te %1$s[Përgjegjës -> Siguri -> Token-ë Mirëfilltësimi]%2$s. Zëvendësoni %3$s ite URL Eksporti ,e token-in tuaj të Mirëfilltësimit. Kujdes: Mos ia jepni kujt tjetër URL-në me token-in real.", - "ExpandSubtables": "Zgjeroji nëntabelat", - "StandardReport": "Raport standard", - "FlattenReport": "Raport i sheshtë", - "ReportWithMetadata": "Raport me tejtëdhëna", - "ReadMoreOnlineGuide": "Lexoni më tepër rreth kësaj teme te udhërrëfyesi në internet.", - "SeeAvailableVersions": "Shihni Versione të Gatshëm", - "QuickLinks": "Lidhje të Shpejta", - "Profilable": "E profilizueshme", - "SearchOnMatomo": "Kërkoni për '%1$s' te Matomo.org", - "ReportingCategoryHelpPrefix": "Si më ndihmon faqja e raportimeve \"%1$s > %2$s\"?", - "VisitorsCategoryHelp1": "Faqet Vizitorë ju tregojnë gjëra rreth se cilët janë vizitorët tuaj. Gjëra të tilla si nga vijnë vizitorët tuaj, çfarë pajisjesh dhe shfletuesish përdorin dhe kur e vizitojnë, përgjithësisht, sajtin tuaj. Të kuptoni, përmbledhtas, cili është publiku juaj, dhe të kërkoni për veçanti, për të parë se si mund të shtohet publiku juaj.", + "SystemSummaryPiwikVersion": "Version Matomo", + "SystemSummaryWidget": "Përmbledhje Sistemi", + "TableNoData": "S’ka të dhëna për këtë tabelë.", + "TechDeprecationWarning": "Duke filluar me versionin Matomo %1$s, Matomo-ja do të reshtë së mbuluari %2$s. Për më tepër hollësi, %3$sshihni postimin tonë në blog.%4$s", + "ThanksFromAllOfUs": "Faleminderit prej krejt nesh në Matomo!", + "ThereIsNoDataForThisReport": "S’ka të dhëna për këtë raport.", + "UnFlattenDataTable": "Raporti është i sheshtë %s Bëje hierarkik", + "UndoPivotBySubtable": "Ky raport është rrotulluar %s Zhbëje rrotullimin", + "ViewAllPiwikVideoTutorials": "Shihini krejt Përkujdesoret Video për Matomo-n", + "VisitStatusOrdered": "Të porositura", + "VisitStatusOrderedThenAbandoned": "Shportë e të Porositurave, mandej të Braktisura", + "VisitTypeReturning": "I rikthyer", + "VisitTypeReturningCustomer": "Klient i Rikthyer", + "VisitorsCategoryHelp1": "Faqet Vizitorë ju tregojnë gjëra rreth se cilët janë vizitorët tuaj. Gjëra të tilla si nga vijnë vizitorët tuaj, çfarë pajisjesh dhe shfletuesish përdorin dhe kur e vizitojnë, përgjithësisht, sajtin tuaj. Të kuptoni, përmbledhtas, cili është publiku juaj dhe të kërkoni për veçanti, për të parë se si mund të shtohet publiku juaj.", "VisitorsCategoryHelp2": "Përveç informacionit të përgjithshëm rreth vizitorëve tuaj, mund të përdorni edhe %1$sRegjistër Vizitash%2$s, që të shihni ç’ndodhi gjatë çdo vizite individuale.", - "VisitorsOverviewHelp": "Përmbledhja mbi Vizitorët ju ndihmon të kuptoni popullaritetin e sajtit tuaj. Kjo bëhet duke dhënë grafikë që shfaqin sa vizita ka sajti juaj gjatë një periudhe të caktuar dhe shkallën mesatare të angazhimit për veçori bazë, bie fjala, kërkime dhe shkarkime.", - "DevicesSubcategoryHelp": "Ndarja Pajisje ju ndihmon të njihni teknologjinë që vizitorët tuaj përdorin në sajtin tuaj. Do të shihni raporte mbi llojin e pajisjes dhe modele specifike, që t’ju bëjnë të mundur ta optimizoni sajtin për shumicën e pajisjeve popullore.", - "SoftwareSubcategoryHelp": "Ndarja Software ju shfaq sistemet operative, shfletues dhe shtojca që vizitorët tuaj përdorin për sajtin, që të mund ta optimizoni sajtin tuaj për të garantuar se është plotësisht i përputhshëm me formësimet më popullore.", - "EngagementSubcategoryHelp1": "Ndarja Angazhim ju furnizon raporte që ndihmojnë të kini një ide mbi sasinë e vizitave të reja dhe të rikthyerish që përfiton sajti juaj. Mund të shqyrtoni edhe raporte që japin kohën mesatare dhe numrin e faqeve sipas vizitash, si dhe numrin e herëve që një vizitor ka qenë në sajtin tuaj dhe numrin më të zakonshëm të ditëve mes vizitash.", - "EngagementSubcategoryHelp2": "Kjo mund t’ju ndihmojë të bëni optimizim për shpeshti dhe vizita me shkallë të lartë ndërveprimi, përveç se për të kapur maksimumin e shtrirjes tuaj.", - "PeriodHasOnlyRawData": "Duket sikur raportet për këtë periudhë s’janë përpunuar ende. Doni të shihni ç’po ndodh tani? Shihni %1$sRegjistër vizitash%2$s ose zgjidhni një periudhë tjetër datash, deri sa të prodhohen raportet." + "VisitorsOverviewHelp": "Përmbledhja mbi Vizitorët ju ndihmon të kuptoni popullaritetin e sajtit tuaj. Këtë e bën duke dhënë grafikë që shfaqin sa vizita ka sajti juaj gjatë një periudhe të caktuar dhe shkallën mesatare të angazhimit për veçori bazë, bie fjala, kërkime dhe shkarkime.", + "WebAnalyticsReports": "Raporte Analizash Web", + "YouAreUsingTheLatestVersion": "Po përdorni versionin më të ri të Matomo-s!", + "YourDonationWillHelp": "Dhurimi juaj do të ndihmojë drejtpërsëdrejti për financim veçorish të reja dhe përmirësime të kësaj platforme statistikash dhe analizimesh me burim të hapët. Kjo do të thotë se bashkësia do të përfitojë përherë nga një mjet që mbron privatësinë dhe ju lejon të jeni në kontroll të të dhënave tuaja." } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/sr.json b/plugins/CoreHome/lang/sr.json index 38791a6731..08cb829642 100644 --- a/plugins/CoreHome/lang/sr.json +++ b/plugins/CoreHome/lang/sr.json @@ -1,18 +1,22 @@ { "CoreHome": { + "AdblockIsMaybeUsed": "Ukoliko koristite bloker reklama, molimo vas da ga isključite na ovom sajtu kako biste bili sigurni da Matomo radi bez ikakvih problema.", "CategoryNoData": "Nema podataka u ovoj kategoriji. Probajte sa \"Uključi celu populaciju\".", + "ChangeCurrentWebsite": "Izaberite sajt, trenutno izabrani sajt je %s", + "ChangePeriod": "период промене", "ChangeVisualization": "Promenite način prikaza", "CheckForUpdates": "Proveri da li se pojavila nova verzija", "CheckPiwikOut": "Proverite!", + "ChooseX": "Izaberite %1$s", + "ClickRowToExpandOrContract": "Kliknite ovaj red kako biste proširili ili skupili tabelu.", "ClickToEditX": "Kliknite kako biste izmenili %s", "ClickToSeeFullInformation": "Kliknite ovde za više informacija", "CloseSearch": "Zatvori pretragu", "CloseWidgetDirections": "Možete zatvoriti ovaj vidžet tako što ćete kliknuti na sličicu 'X' na vrhu.", - "ChooseX": "Izaberite %1$s", "DataForThisReportHasBeenPurged": "Podaci za ovaj izveštaj su više od %s meseci stari te su obrisani.", "DataTableExcludeAggregateRows": "Zbirni redovi su prikazani %s Sakrij ih", - "DataTableIncludeAggregateRows": "Zbirni redovi su sakriveni %s Prikaži ih", "DataTableHowToSearch": "Pritisnite Enter ili kliknite na sličicu kako biste pokrenuli pretragu", + "DataTableIncludeAggregateRows": "Zbirni redovi su sakriveni %s Prikaži ih", "Default": "podrazumevano", "DonateCall1": "Matomo vas nikada neće ništa koštati ali to ne znači da nas Matomo ništa ne košta dok ga pravimo.", "DonateCall2": "Matomou je potrebna vaša stalna podrška kako bi rastao i napredovao.", @@ -21,46 +25,43 @@ "ExternalHelp": "Pomoć (otvara se u novom tabu)", "FlattenDataTable": "Izveštaj je u hijerarhiji %s Poravnaj ga", "IncludeRowsWithLowPopulation": "Redovi sa slabom populacijom su sakriveni %s Prikaži sve redove", - "InjectedHostEmailBody": "Pozdrav. Pokušao\\\/la sam da pristupim Matomo-u danas i dobio\\\/la upozorenje o nepoznatom nazivu hosta.", + "InjectedHostEmailBody": "Pozdrav. Pokušao\\/la sam da pristupim Matomo-u danas i dobio\\/la upozorenje o nepoznatom nazivu hosta.", "InjectedHostEmailSubject": "Matomo-u je pristupljeno sa nepoznatim nazivom hosta: %s", "InjectedHostNonSuperUserWarning": "%1$sKliknite ovde kako biste pristupili Matomo-u bezbedno%2$s i uklonili ovo upozorenje. Takođe možete kontaktirati administratora i obavestiti ga o ovom upozorenju (%3$skliknite ovde kako biste poslali poruku%4$s).", "InjectedHostSuperUserWarning": "Matomo možda nije podešen kako treba (na primer, premešten je na novi server ili URL). Možete ili da %1$skliknete ovde i dodate %2$s kao validan naziv hosta (ukoliko mu verijete)%3$s, ili da %4$skliknete ovde i %5$s pristupite bezbedno Matomo-u%6$s.", "InjectedHostWarningIntro": "Sada pristupate Matomo-u sa %1$s, ali je Matomo podešen da radi sa ove adrese: %2$s.", + "LeadingAnalyticsPlatformRespectsYourPrivacy": "Vodeća otvorena analitička platforma koja poštuje vašu privatnost.", "MainNavigation": "Glavna navigacija", "Menu": "Meni", + "MenuEntries": "Stavke menija", "NoPrivilegesAskPiwikAdmin": "Prijavljeni ste kao '%1$s' ali izgleda da nemate postavljena nikakva ovlašćenja. %2$s Tražite od Matomo administratora (kliknite za poruku)%3$s da vam dozvoli 'prikaz' na sajtu.", + "NoSuchPage": "Ova stranica ne postoji", + "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Nadogradnja jednim klikom nije moguća zato što koristite Matomo na više servera. Molimo vas da preuzmete poslednju verziju sa %1$s kako biste nastavili.", "OnlyForSuperUserAccess": "Ovaj vidžet se prikazuje na podrazumevanoj konzoli samo superkorisnicima.", "PeriodRange": "Period", + "PivotBySubtable": "Ovaj izveštaj nije pivotiran %1$s Pivotiraj sa %2$s", + "QuickAccessTitle": "Pretraga za %s. Koristite tastere sa strelicama kako biste se kretali kroz rezultate pretrage. Prečica: pritisnite 'f' za pretragu.", "ReportGeneratedOn": "Izveštaj generisan %s", "ReportGeneratedXAgo": "Izveštaj generisan pre %s", + "Segments": "Segmenti", "SharePiwikShort": "Matomo! Besplatna web analitika otvorenog koda. Budite vlasnici svojih podataka.", "ShareThis": "Podeli", "ShowJSCode": "Prikaži JavaScript kod", "SkipToContent": "Pređi na sadržaj", "SubscribeAndBecomePiwikSupporter": "Nastavite ka stranici za sigurno plaćanje (Paypal) kako biste postali Matomo suporter!", "SupportPiwik": "Podržite Matomo!", + "SystemSummaryMysqlVersion": "Verzija MySQL-a", + "SystemSummaryNActivatedPlugins": "%d aktiviranih dodataka", + "SystemSummaryNWebsites": "%d sajtova", + "SystemSummaryPhpVersion": "Verzija PHP-a", + "SystemSummaryPiwikVersion": "Verzija Matomo-a", + "SystemSummaryWidget": "Sumarno", "TableNoData": "Nema podataka za ovu tabelu.", "ThereIsNoDataForThisReport": "Nema podataka za ovaj izveštaj.", "UnFlattenDataTable": "Izveštaj je ravan %s Prikaži hijerarhiju", + "UndoPivotBySubtable": "Ovaj izveštaj je pivotiran %s Otkaži pivot", "ViewAllPiwikVideoTutorials": "Prikaži sve Matomo video tutorijale", "WebAnalyticsReports": "Izveštaj web analitike", - "YouAreUsingTheLatestVersion": "Koristite poslednju verziju Matomo-a", - "ClickRowToExpandOrContract": "Kliknite ovaj red kako biste proširili ili skupili tabelu.", - "UndoPivotBySubtable": "Ovaj izveštaj je pivotiran %s Otkaži pivot", - "NoSuchPage": "Ova stranica ne postoji", - "PivotBySubtable": "Ovaj izveštaj nije pivotiran %1$s Pivotiraj sa %2$s", - "SystemSummaryWidget": "Sumarno", - "SystemSummaryNWebsites": "%d sajtova", - "SystemSummaryNActivatedPlugins": "%d aktiviranih dodataka", - "SystemSummaryPiwikVersion": "Verzija Matomo-a", - "SystemSummaryMysqlVersion": "Verzija MySQL-a", - "SystemSummaryPhpVersion": "Verzija PHP-a", - "QuickAccessTitle": "Pretraga za %s. Koristite tastere sa strelicama kako biste se kretali kroz rezultate pretrage. Prečica: pritisnite 'f' za pretragu.", - "MenuEntries": "Stavke menija", - "Segments": "Segmenti", - "OneClickUpdateNotPossibleAsMultiServerEnvironment": "Nadogradnja jednim klikom nije moguća zato što koristite Matomo na više servera. Molimo vas da preuzmete poslednju verziju sa %1$s kako biste nastavili.", - "AdblockIsMaybeUsed": "Ukoliko koristite bloker reklama, molimo vas da ga isključite na ovom sajtu kako biste bili sigurni da Matomo radi bez ikakvih problema.", - "ChangeCurrentWebsite": "Izaberite sajt, trenutno izabrani sajt je %s", - "LeadingAnalyticsPlatformRespectsYourPrivacy": "Vodeća otvorena analitička platforma koja poštuje vašu privatnost." + "YouAreUsingTheLatestVersion": "Koristite poslednju verziju Matomo-a" } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/sv.json b/plugins/CoreHome/lang/sv.json index 47d8086d3d..3dffcf2d35 100644 --- a/plugins/CoreHome/lang/sv.json +++ b/plugins/CoreHome/lang/sv.json @@ -16,6 +16,7 @@ "CloseWidgetDirections": "Du kan stänga widgeten genom att klicka på (X) på widgetens topp.", "CssDidntLoad": "Din webbläsare kunde inte läsa in stilen på den här sidan.", "CustomLimit": "Anpassad begränsning", + "DataForThisReportHasBeenDisabled": "Segmentering är för närvarande nerstängt för den här rapporten. Vänligen kolla %1$sden här FAQ'en%2$s för mer detaljer.", "DataForThisReportHasBeenPurged": "Data för denna rapport är mer än %s månader gammal och har tagits bort.", "DataTableCombineDimensions": "Dimensioner som visas separerade %s Visa dimensioner kombinerade", "DataTableExcludeAggregateRows": "Aggregerade rader dolda %s Dölj dem", @@ -28,6 +29,7 @@ "DonateCall1": "Matomo kommer alltid vara gratis att använda men det innebär inte att det inte kostar något att skapa den.", "DonateCall2": "Matomo behöver ditt fortsatta stöd för att växa och frodas.", "DonateCall3": "Om du tycker att Matomo bidragit till din verksamhet är vi tacksamma om du överväger att %1$sdonera%2$s eller %3$sköpa premiumfunktioner%4$s. Varje öre bidrar.", + "EndDate": "Slutdatum", "EndShortcut": "Slut", "EngagementSubcategoryHelp1": "Avsnittet Engagemang ger rapporter som hjälper till att kvantifiera hur många nya och återkommande besökare du får. Du kan också granska rapporter som tar upp genomsnittlig tid och antal sidvisningar per besök, liksom antalet gånger en besökare har varit på din webbplats och det vanligaste antalet dagar mellan besök.", "EngagementSubcategoryHelp2": "Detta kan hjälpa dig att optimera för besök med hög frekvens och interaktion utöver att maximera din räckvidd.", @@ -65,13 +67,14 @@ "OnlyForSuperUserAccess": "Denna widget visas bara för superanvändare i standardkontrollpanelen.", "PageDownShortcutDescription": "för att komma till botten av sidan", "PageUpShortcutDescription": "för att komma till toppen av sidan", + "PeriodHasOnlyRawData": "Det verkar som att rapporterna för den här perioden inte har behandlats än. Vill du se vad som händer nu? Kolla in %1$sBesöksloggen%2$s eller välj en annorlunda datum-period tills det att rapporterna är genererade.", "PeriodRange": "Intervall", "PivotBySubtable": "Denna rapport är inte pivoterad %1$s Pivotera med %2$s", "Profilable": "Profilabel", "QuickAccessTitle": "Sök efter %s. Använd piltangenterna för att navigera i sökresultatet. Genväg: Tryck på 'f' för att söka.", "QuickLinks": "Snabblänkar", "ReadMoreOnlineGuide": "Läs mer om ämnet i onlineguiden.", - "RemoveTotalsRowDataTable": "Rapporten visar totalt antal rader 1%s Ta bort totalt antal rader", + "RemoveTotalsRowDataTable": "Rapporten visar totalt antal rader %s Ta bort totalt antal rader", "ReportGeneratedOn": "Rapporten genererades på %s", "ReportGeneratedXAgo": "Rapporten genererades för %s sen", "ReportType": "Rapporttyp", @@ -96,18 +99,20 @@ "SkipToContent": "Hoppa till innehåll", "SoftwareSubcategoryHelp": "Avsnittet Programvara visar de operativsystem, webbläsare och plugins som dina besökare använder för att besöka webbplatsen så att du kan optimera din webbplats för att säkerställa att den är helt kompatibel med de mest populära konfigurationerna..", "StandardReport": "Standardrapport", + "StartDate": "Startdatum", "SubscribeAndBecomePiwikSupporter": "Fortsätt till en säker kortbetalningssida (Paypal) för att bli en Matomo-Supporter!", "SupportPiwik": "Stöd Matomo!", "SupportUsOn": "Stöd oss på", "SystemSummaryMysqlVersion": "MySQL version", "SystemSummaryNActivatedPlugins": "%d aktiverade plugins", "SystemSummaryNSegments": "%1$d segment", - "SystemSummaryNSegmentsWithBreakdown": "%1$dsegment (%2$sförbehandlade, %3$sbearbetade i realtid)", + "SystemSummaryNSegmentsWithBreakdown": "%1$d segment (%2$s förbehandlade, %3$s bearbetade i realtid)", "SystemSummaryNWebsites": "%d webbplatser", "SystemSummaryPhpVersion": "PHP version", "SystemSummaryPiwikVersion": "Matomo version", "SystemSummaryWidget": "Systemsammanfattning", "TableNoData": "Det finns ingen data för den här tabellen-", + "TechDeprecationWarning": "Från och med version %1$s av Matomo så kommer Matomo att upphöra sin support för %2$s. För mer information, %3$släs vårat blogg-inlägg.%4$s", "ThanksFromAllOfUs": "Tack från oss alla på Matomo!", "ThereIsNoDataForThisReport": "Det finns ingen data för denna rapport.", "UnFlattenDataTable": "Rapporten är plan %s Gör den hierarkisk", diff --git a/plugins/CoreHome/lang/ta.json b/plugins/CoreHome/lang/ta.json index 4193a4e4a4..78b4409578 100644 --- a/plugins/CoreHome/lang/ta.json +++ b/plugins/CoreHome/lang/ta.json @@ -2,14 +2,18 @@ "CoreHome": { "CheckForUpdates": "புதிய பதிப்புகளை சரிபார்க்கவும்", "CheckPiwikOut": "பிவிக் வெளியேறலை செய்ய சரியிடுக", + "ChooseX": "%1$s ஐத் தேர்ந்தெடுக்கவும்", "ClickToEditX": "%sஐத் திருத்த கிளிக் செய்க", "ClickToSeeFullInformation": "முழு தகவலைக் காண கிளிக் செய்க", "CloseSearch": "தேடலை மூடு", "CloseWidgetDirections": "விட்ஜெட்டின் மேல்பகுதியில் உள்ள 'X' படவுருவை க்ளிக் செய்வதன் மூலம் இந்த விட்ஜெட்டை நீங்கள் மூட முடியும்", - "ChooseX": "%1$s ஐத் தேர்ந்தெடுக்கவும்", + "DataForThisReportHasBeenPurged": "இந்த அறிக்கைக்கான தரவு %sஐ மாதங்களைத் தாண்டியுள்ளது. மேலும், அது நீக்கப்பட்டுள்ளது.", "Default": "தவறுதல்", "DonateCall1": "பிவிக் எப்போதும் உங்களுக்கு எந்தவித செலவும் இல்லாமல் கிடைகிறது, ஆனால் பிவிக்-ஐ உருவாக்க எங்களுக்கு செலவாகாமல் இருப்பதில்லை.", "DonateCall2": "Matomo செழித்து வளர உங்கள் தொடர்ந்த ஆதரவு தேவைப்படுகிறது.", + "EndShortcut": "முடிவுறு", + "EnterZenMode": "ஜென் மோடிற்குள் நுழை (மெனுவை மறைக்கவும்)", + "ExitZenMode": "ஜென் மோடை விட்டும் வெளியேறு (மெனுவை காட்டவும்)", "InjectedHostEmailBody": "வணக்கம், நான் இன்று Matomo அணுக முயற்சிசெய்யும் போது அறியப்படாத புரவலன்பெயர் எச்சரிக்கையை எதிர்கொண்டேன்.", "InjectedHostEmailSubject": "Matomo தெரியாத இந்த புரவலன் பேரில் இருந்து அணுகப்பட்டுள்ளது: %s", "InjectedHostWarningIntro": "நீங்கள் இப்போது பிவிக்கை %1$s -ல் இருந்து இயக்குகிறீர்கள், ஆனால் பிவிக்கானது %2$s -முகவரியிலிருந்து இயங்க கட்டமைக்கப்பட்டுள்ளது.", @@ -27,4 +31,4 @@ "WebAnalyticsReports": "இணைய பகுப்பாய்வு அறிக்கைகள்", "YouAreUsingTheLatestVersion": "நீங்கள் Matomo அண்மைய புதிய பதிப்பை பயன்படுத்துகிறீர்கள்" } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/th.json b/plugins/CoreHome/lang/th.json index aa39061cb4..8b9e748fdc 100644 --- a/plugins/CoreHome/lang/th.json +++ b/plugins/CoreHome/lang/th.json @@ -1,6 +1,7 @@ { "CoreHome": { "CategoryNoData": "ไม่มีข้อมูลในประเภทนี้ พยายาม \"รวมประชากรทั้งหมด\"", + "ChangeVisualization": "เปลี่ยน มุมมอง", "CheckForUpdates": "ตรวจสอบชุดอัพเดท", "Default": "ค่าเริ่มต้น", "ShowJSCode": "แสดงรหัส JavaScript เมื่อต้องการแทรก", @@ -10,4 +11,4 @@ "WebAnalyticsReports": "รายงานการวิเคราะห์เว็บไซต์", "YouAreUsingTheLatestVersion": "คุณกำลังใช้งานรุ่นล่าสุดของ Matomo!" } -}
\ No newline at end of file +} diff --git a/plugins/CoreHome/lang/tr.json b/plugins/CoreHome/lang/tr.json index 88fff41282..c9821f099a 100644 --- a/plugins/CoreHome/lang/tr.json +++ b/plugins/CoreHome/lang/tr.json @@ -16,6 +16,7 @@ "CloseWidgetDirections": "Üst kısımdaki 'X' simgesine tıklayarak bu pano bileşenini kapatabilirsiniz.", "CssDidntLoad": "Tarayıcınız bu sayfanın biçemini yükleyemedi.", "CustomLimit": "Özel sayı", + "DataForThisReportHasBeenDisabled": "Şu anda bu rapor için dilimlere ayırma devre dışı bırakılmış. Ayrıntılı bilgi almak için %1$sbu SSS%2$s bölümüne bakabilirsiniz.", "DataForThisReportHasBeenPurged": "Bu raporda bulunan veriler %s ay öncesine ait olduğundan atıldı.", "DataTableCombineDimensions": "Boyutlar ayrı görüntüleniyor %s Boyutları birleştirerek görüntüle", "DataTableExcludeAggregateRows": "Tüm satırlar görüntüleniyor %s Gizle", @@ -28,6 +29,7 @@ "DonateCall1": "Matomo her zaman ücretsiz kullanılabilecek ancak bu durum geliştirmenin ücretsiz olduğu anlamına gelmiyor.", "DonateCall2": "Gelişip ilerleyebilmesi için Matomo projesi sürekli desteğinize gerek duyuyor.", "DonateCall3": "Matomo uygulamasının işinize önemli bir katkı sağladığını düşünüyorsanız, %1$slütfen düzenli bağış yapmayı%2$s ya da %3$sbir özellik satın almayı%4$s düşünün. Her kuruşun yardımı olur.", + "EndDate": "Bitiş tarihi", "EndShortcut": "Son", "EngagementSubcategoryHelp1": "Bağlılık arttırma bölümü, yeni ve geri gelen ziyaretçilerin ölçülmesini sağlayan raporlar içerir. Ayrıca raporlara, ortalama ziyaret süresi ve ziyaret edilen sayfa sayısı yanında bir ziyaretçinin siteyi kaç kez ziyaret ettiği ve ziyaretler arasındaki genellikle kaç gün olduğu gibi çeşitli kırılımlara göre bakabilirsiniz.", "EngagementSubcategoryHelp2": "Bunlar ziyaretlerin sıklığını ve etkileşim oranını arttırarak erişimi iyileştirmeye yardımcı olabilir.", @@ -97,6 +99,7 @@ "SkipToContent": "İçeriğe geç", "SoftwareSubcategoryHelp": "Yazılım bölümü, ziyaretçilerin siteye erişmek için kullandığı işletim sistemlerini, tarayıcıları ve eklentileri içerir. Böylece site yaygın kullanılan yazılımlarla tam olarak uyumlu olacak şekilde iyileştirilebilir.", "StandardReport": "Standart rapor", + "StartDate": "Başlangıç tarihi", "SubscribeAndBecomePiwikSupporter": "Matomo destekçisi olmak için güvenli bir kredi kartı ödeme sayfası (Paypal) açın!", "SupportPiwik": "Matomo uygulamasını destekleyin!", "SupportUsOn": "Şuradan destek olun", diff --git a/plugins/CoreHome/lang/zh-cn.json b/plugins/CoreHome/lang/zh-cn.json index 0d6993cd54..48a9fe758b 100644 --- a/plugins/CoreHome/lang/zh-cn.json +++ b/plugins/CoreHome/lang/zh-cn.json @@ -16,6 +16,7 @@ "CloseWidgetDirections": "点击右上角的 'X' 图标可关闭这个小窗口。", "CssDidntLoad": "您的浏览器无法加载此页面的样式。", "CustomLimit": "自定义限制", + "DataForThisReportHasBeenDisabled": "此报告当前已禁用分段。有关详细信息,请查看%1$s此常见问题解答%2$s。", "DataForThisReportHasBeenPurged": "本报表数据超过 %s 个月已被清空。", "DataTableCombineDimensions": "尺寸单独显示%s显示组合尺寸", "DataTableExcludeAggregateRows": "汇总行已显示 %s 隐藏汇总", @@ -28,6 +29,7 @@ "DonateCall1": "Matomo 对您来说可以免费使用,但对我们来说并非零成本。", "DonateCall2": "Matomo 的茁壮成长离不开您的支持。", "DonateCall3": "如果你觉得Matomo对你的商业有价值的话,%1$s请考虑资助%2$s 或者 %3$s购买会员%4$s。任何一分都会有帮助。", + "EndDate": "结束日期", "EndShortcut": "结束", "EngagementSubcategoryHelp1": "参与部分提供的报告帮助你量化了得到的新访客和回访访客的数量。你还可以查看报告,其中细分了每次访问的平均时间和页面数,以及访客访问你的网站的次数和最常见的访问间隔天数。", "EngagementSubcategoryHelp2": "这可以帮助你优化频率和高互动访问,此外还可以最大限度地提高你的影响力。", @@ -97,6 +99,7 @@ "SkipToContent": "跳过,查看内容", "SoftwareSubcategoryHelp": "软件部分展示了您的访问者在访问网站时使用的操作系统、浏览器和插件,以便您可以优化您的网站,以确保它与最流行的配置完全兼容。", "StandardReport": "标准报告", + "StartDate": "开始日期", "SubscribeAndBecomePiwikSupporter": "进入安全的信用卡付款页面 (Paypal) 支持 Matomo !", "SupportPiwik": "支持 Matomo!", "SupportUsOn": "支持我们", diff --git a/plugins/CoreHome/lang/zh-tw.json b/plugins/CoreHome/lang/zh-tw.json index 639a915e5f..9816695681 100644 --- a/plugins/CoreHome/lang/zh-tw.json +++ b/plugins/CoreHome/lang/zh-tw.json @@ -16,6 +16,7 @@ "CloseWidgetDirections": "你可以點擊小工具上方的「X」來關閉它。", "CssDidntLoad": "你的瀏覽器無法載入此頁面的樣式。", "CustomLimit": "自訂限制", + "DataForThisReportHasBeenDisabled": "區隔在此報表上已停用。請參閱%1$s此 FAQ%2$s 瞭解詳情。", "DataForThisReportHasBeenPurged": "這份報表中的資料已經超過 %s 個月因此已被清除。", "DataTableCombineDimensions": "目前顯示個別的維度 %s 顯示綜合的維度", "DataTableExcludeAggregateRows": "合計列已顯示 %s 點擊隱藏", @@ -24,10 +25,14 @@ "DataTableShowDimensions": "目前顯示綜合的維度 %s 分別顯示各個維度", "DateInvalid": "指定的日期與期間組合無效。請至日期工具內選擇另一個有效的日期。", "Default": "預設", + "DevicesSubcategoryHelp": "「設備」部分幫助你瞭解訪問者用於訪問你網站的技術。你將看到有關裝置類型和型號的報表,以便你的網站能針對最受歡迎的裝置作出優化。", "DonateCall1": "使用 Matomo 永遠不花你任何一毛錢,但那不表示我們開發不需要花到半毛錢。", "DonateCall2": "Matomo 需要你的持續支持以成長茁壯。", "DonateCall3": "如果你覺得 Matomo 為你的事業或是奮鬥過程中增添了非凡的價值,%1$s請考慮捐助%2$s或是%3$s購買高級功能%4$s。每一分錢都是幫助。", + "EndDate": "結束日期", "EndShortcut": "End 鍵", + "EngagementSubcategoryHelp1": "「參與」部分提供的報表有助於量化你獲得的新訪客和回頭客之數量。你還可以查閱細分每次訪問的平均時間和頁數的報告,以及訪問者訪問你網站的次數以及一般隔多少天會再次訪問。", + "EngagementSubcategoryHelp2": "這可以幫助你針對頻次和高互動的來訪作出優化,同時最大限度地擴大覆蓋面。", "EnterZenMode": "進入勿擾模式(隱藏選單)", "ExceptionNotAllowlistedIP": "你無法使用此 Matomo,因為你的 IP %s 未被允許。", "ExcludeRowsWithLowPopulation": "已顯示所有列 %s 排除較低人數", @@ -35,6 +40,7 @@ "ExpandSubtables": "展開子表格", "ExportFormat": "匯出格式", "ExportTooltip": "注意:要使用產生的導出URL,您需要指定一個app token授權。您可以在Admin -> Security -> Token Auths配置這些授權。", + "ExportTooltipWithLink": "注意:要使用生成的導出網址,你需要指明一個應用授權權杖。你可以在%1$s[管理 -> 安全 -> 授權權杖]%2$s中配置這些授權權杖。以你的授權權杖替換導出網址中的 %3$s。警告:切勿共享帶有真實授權權杖的網址予他人。", "ExternalHelp": "幫助(在新分頁中開啟)", "FlattenDataTable": "報表目前已分層 %s 平面化顯示", "FlattenReport": "平滑化報表", @@ -47,7 +53,7 @@ "InjectedHostNonSuperUserWarning": "%1$s點擊這裡以安全的存取 Matomo%2$s 並移除這個警告。你也可能想要聯絡你的 Matomo 管理員並提醒他們這個問題(%3$s點此寄信%4$s)。", "InjectedHostSuperUserWarning": "Matomo 可能設定錯誤(例如 Matomo 剛從其他伺服器或網址移動)。你可以%1$s點此新增 %2$s 為 Matomo 有效域名%3$s(如果你信任它),或是%4$s點此訪問 %5$s 來安全的存取 Matomo%6$s。", "InjectedHostWarningIntro": "你現在正從 %1$s 訪問 Matomo,但 Matomo 設定中的網址已經變更為 %2$s。", - "JavascriptDisabled": "使用 Matomo 的標準檢視時必須啟用 JavaScript。<br />然而,你的瀏覽器似乎已停用或不支援 JavaScript。<br />若要使用標準檢視,請變更你的瀏覽器選項並啟用 JavaScript,然後%1$s重試一次%2$s。<br />", + "JavascriptDisabled": "使用 Matomo 的標準檢視時必須啟用 JavaScript。<br>然而,你的瀏覽器似乎已停用或不支援 JavaScript。<br>若要使用標準檢視,請變更你的瀏覽器選項並啟用 JavaScript,然後%1$s重試一次%2$s。<br>", "JsDidntLoad": "你的瀏覽器無法載入此頁面的程式碼。", "LeadingAnalyticsPlatformRespectsYourPrivacy": "尊重你隱私的開放式分析平台領導。", "MacPageDown": "Fn + → 鍵", @@ -61,6 +67,7 @@ "OnlyForSuperUserAccess": "這個小工具只顯示於擁有超級使用者權限使用者的預設展示板。", "PageDownShortcutDescription": "前往網頁最下方", "PageUpShortcutDescription": "回到網頁最上方", + "PeriodHasOnlyRawData": "似乎這一時段的報表尚未處理完成。想看看現在的狀況嗎?查看%1$s訪問紀錄%2$s或選擇不同的時段,直到有生成的報告。", "PeriodRange": "範圍", "PivotBySubtable": "此報表尚未圖形化 %1$s 以 %2$s 圖形化", "Profilable": "可紀錄的", @@ -72,7 +79,7 @@ "ReportGeneratedXAgo": "報表產生於 %s 之前", "ReportType": "報表類型", "ReportWithMetadata": "含中繼資料報表", - "ReportingCategoryHelpPrefix": "「%1$s > %2$s 」報告頁如何協助我?", + "ReportingCategoryHelpPrefix": "「%1$s > %2$s 」報告頁如何協助我?", "RowLimit": "行數限制", "SearchOnMatomo": "在 Matomo.org 上搜尋「%1$s」", "SeeAvailableVersions": "查看可用版本", @@ -90,10 +97,12 @@ "ShowExportUrl": "顯示匯出網址", "ShowJSCode": "顯示要插入的 JavaScript 程式碼", "SkipToContent": "跳到內容", + "SoftwareSubcategoryHelp": "「軟體」部分顯示訪問者用於訪問網站的作業系統、瀏覽器和外掛程式,以便你可以優化你的網站,確保其與最流行的配置完全相容。", "StandardReport": "標準報表", + "StartDate": "開始日期", "SubscribeAndBecomePiwikSupporter": "繼續到安全的信用卡付款網頁(Paypal)來成為 Matomo 的支持者!", "SupportPiwik": "支持 Matomo!", - "SupportUsOn": "贊助我們:", + "SupportUsOn": "贊助我們", "SystemSummaryMysqlVersion": "MySQL 版本", "SystemSummaryNActivatedPlugins": "%d 個外掛已啟用", "SystemSummaryNSegments": "%1$d 個區隔", @@ -103,6 +112,7 @@ "SystemSummaryPiwikVersion": "Matomo 版本", "SystemSummaryWidget": "系統摘要", "TableNoData": "此表格中無資料。", + "TechDeprecationWarning": "自 Matomo %1$s 版本起,Matomo 將停止支援 %2$s。更多資訊請%3$s看我們的部落格文章。%4$s", "ThanksFromAllOfUs": "Matomo 全體成員感謝你!", "ThereIsNoDataForThisReport": "此報表無資料。", "UnFlattenDataTable": "報表目前已平面化 %s 分層顯示", @@ -112,6 +122,9 @@ "VisitStatusOrderedThenAbandoned": "已下訂並棄用的購物車", "VisitTypeReturning": "回訪", "VisitTypeReturningCustomer": "回訪顧客", + "VisitorsCategoryHelp1": "「訪問者」頁面會告訴你有關訪問者的資訊。例如,訪問者來自哪裡,他們使用什麼設備和瀏覽器以及他們通常何時訪問你的網站。從總體上瞭解你的受眾是誰,並尋找異常值以瞭解你的受眾如何增長。", + "VisitorsCategoryHelp2": "除了有關訪問者的一般資訊外,你還可以使用%1$s訪問紀錄%2$s查看每次訪問的過程。", + "VisitorsOverviewHelp": "「訪問者總覽」幫助你瞭解網站的受歡迎程度。以圖表顯示你的網站在選定時段內獲得的訪問量,以及關鍵功能(如搜尋和下載)的平均參與程度。", "WebAnalyticsReports": "網站分析報表", "YouAreUsingTheLatestVersion": "你正在使用 Matomo 的最新版本!", "YourDonationWillHelp": "你的捐款會直接用於建立新功能、和改善此自由開源的分析平台。由此,社群都能助益於這個能保障隱私、且使你真正擁有個人資料的工具。" diff --git a/plugins/CoreHome/stylesheets/layout.less b/plugins/CoreHome/stylesheets/layout.less index dd1a8b6fd0..07da8e2668 100644 --- a/plugins/CoreHome/stylesheets/layout.less +++ b/plugins/CoreHome/stylesheets/layout.less @@ -365,6 +365,9 @@ nav { .item .icon-arrow-right:before { content: "\e63b"; } + .menu-icon { + padding-right: 13px; + } } .collapsible { @@ -419,13 +422,17 @@ nav { input { height: 33px; font-size: 11px; - padding: 10px 12px 10px 10px; + padding: 10px 12px 10px 30px; border: 0; margin: 0; box-sizing: border-box; border-radius: 2px !important; box-shadow: none!important; } + + input::placeholder { + color: #a9a9a9; + } } .piwikTopControl { diff --git a/plugins/CoreHome/stylesheets/vue-transitions.less b/plugins/CoreHome/stylesheets/vue-transitions.less index cdfef3e1ea..d9bd4cf49e 100644 --- a/plugins/CoreHome/stylesheets/vue-transitions.less +++ b/plugins/CoreHome/stylesheets/vue-transitions.less @@ -13,4 +13,12 @@ .slow-fade-out-leave-to { opacity: 0; -}
\ No newline at end of file +} + +.fade-out-enter-active { + transition: opacity 0.4s ease; +} + +.fade-out-enter-from { + opacity: 1; +} diff --git a/plugins/CoreHome/stylesheets/zen-mode.less b/plugins/CoreHome/stylesheets/zen-mode.less index 9cad06cd87..781a1c01bc 100644 --- a/plugins/CoreHome/stylesheets/zen-mode.less +++ b/plugins/CoreHome/stylesheets/zen-mode.less @@ -10,6 +10,10 @@ #root #secondNavBar + .pageWrap { margin-left: 0; } + + .bannerHeader { + display: none; + } } #content:not(.admin), .widget, .ui-widget { diff --git a/plugins/CoreHome/templates/_adblockDetect.twig b/plugins/CoreHome/templates/_adblockDetect.twig index f60d2ac0e3..22d02e8c2f 100644 --- a/plugins/CoreHome/templates/_adblockDetect.twig +++ b/plugins/CoreHome/templates/_adblockDetect.twig @@ -1,42 +1,44 @@ <div id="bottomAd" style="font-size: 2px;"> </div> <script type="text/javascript"> - if ('undefined' === (typeof hasBlockedContent) || hasBlockedContent !== false) { - {# if hasBlockedContent was "false" most likely nothing was blocked #} - (function () { - {# most likely jQuery is not available, have to use vanilla JS here #} - var body = document.getElementsByTagName('body'); + window.addEventListener('DOMContentLoaded', function () { + if ('undefined' === (typeof hasBlockedContent) || hasBlockedContent !== false) { + {# if hasBlockedContent was "false" most likely nothing was blocked #} + (function () { + {# most likely jQuery is not available, have to use vanilla JS here #} + var body = document.getElementsByTagName('body'); - if (!body || !body[0]) { - return; - } + if (!body || !body[0]) { + return; + } - var bottomAd = document.getElementById('bottomAd'); - var wasMostLikelyCausedByAdblock = false; + var bottomAd = document.getElementById('bottomAd'); + var wasMostLikelyCausedByAdblock = false; - if (!bottomAd) { - wasMostLikelyCausedByAdblock = true; - } else if (bottomAd.style && bottomAd.style.display === 'none') { - wasMostLikelyCausedByAdblock = true; - } else if ('undefined' !== (typeof bottomAd.clientHeight) && bottomAd.clientHeight === 0) { - wasMostLikelyCausedByAdblock = true; - } + if (!bottomAd) { + wasMostLikelyCausedByAdblock = true; + } else if (bottomAd.style && bottomAd.style.display === 'none') { + wasMostLikelyCausedByAdblock = true; + } else if ('undefined' !== (typeof bottomAd.clientHeight) && bottomAd.clientHeight === 0) { + wasMostLikelyCausedByAdblock = true; + } - if (wasMostLikelyCausedByAdblock) { - var shouldGetHiddenElement = document.getElementById("should-get-hidden"); - var warning = document.createElement('p'); - warning.innerText = '{{ 'CoreHome_AdblockIsMaybeUsed'|translate|e('js') }}'; + if (wasMostLikelyCausedByAdblock) { + var shouldGetHiddenElement = document.getElementById("should-get-hidden"); + var warning = document.createElement('p'); + warning.innerText = '{{ 'CoreHome_AdblockIsMaybeUsed'|translate|e('js') }}'; - if (shouldGetHiddenElement) { - shouldGetHiddenElement.appendChild(warning); - } else { - body[0].insertBefore(warning, body[0].firstChild); - warning.style.color = 'red'; - warning.style.fontWeight = 'bold'; - warning.style.marginLeft = '16px'; - warning.style.marginBottom = '16px'; - warning.style.fontSize = '20px'; + if (shouldGetHiddenElement) { + shouldGetHiddenElement.appendChild(warning); + } else { + body[0].insertBefore(warning, body[0].firstChild); + warning.style.color = 'red'; + warning.style.fontWeight = 'bold'; + warning.style.marginLeft = '16px'; + warning.style.marginBottom = '16px'; + warning.style.fontSize = '20px'; + } } - } - })(); - } + })(); + } + }); </script>
\ No newline at end of file diff --git a/plugins/CoreHome/templates/_dataTable.twig b/plugins/CoreHome/templates/_dataTable.twig index f9abda1fc2..4ba518a511 100644 --- a/plugins/CoreHome/templates/_dataTable.twig +++ b/plugins/CoreHome/templates/_dataTable.twig @@ -13,7 +13,7 @@ {% if properties.title %} <h2 class="card-title" {% if properties.title_edit_entity_url %}edit-url="{{ properties.title_edit_entity_url }}"{% endif %} - {% if reportLastUpdatedMessage is defined and reportLastUpdatedMessage %}report-generated="{{ reportLastUpdatedMessage|raw }}"{% endif %} + report-generated="{% if reportLastUpdatedMessage is defined %}{{ reportLastUpdatedMessage|raw }}{% endif %}" piwik-enriched-headline >{{ properties.title }}</h2> {% endif %} @@ -59,6 +59,8 @@ <div class="pk-emptyDataTable"> {% if showReportDataWasPurgedMessage is defined and showReportDataWasPurgedMessage %} {{ 'CoreHome_DataForThisReportHasBeenPurged'|translate(deleteReportsOlderThan) }} + {% elseif showPluginArchiveDisabled is defined and showPluginArchiveDisabled%} + {{ 'CoreHome_DataForThisReportHasBeenDisabled'|translate('<a target="_blank" href="'~'https://matomo.org/faq/how-to-disable-archiving-the-segment-reports-for-specific-plugins' ~'">', '</a>')|raw }} {% elseif properties.no_data_message %} {{ properties.no_data_message|raw }} {% else %} @@ -73,7 +75,7 @@ {% include "@CoreHome/_dataTableFooter.twig" %} {% endif %} - {% include "@CoreHome/_dataTableJS.twig" %} + {% include "@CoreHome/_dataTableJS.twig" with { reportId: properties.report_id } %} {% endif %} </div> </div> diff --git a/plugins/CoreHome/templates/_dataTableJS.twig b/plugins/CoreHome/templates/_dataTableJS.twig index 975dca4b3b..7d671c398a 100644 --- a/plugins/CoreHome/templates/_dataTableJS.twig +++ b/plugins/CoreHome/templates/_dataTableJS.twig @@ -1,5 +1,5 @@ <script type="text/javascript" defer="defer"> $(document).ready(function () { - require('piwik/UI/DataTable').initNewDataTables(); + require('piwik/UI/DataTable').initNewDataTables({{ reportId|json_encode|raw }}); }); </script> diff --git a/plugins/CoreHome/templates/_topBar.twig b/plugins/CoreHome/templates/_topBar.twig index febe664681..961c6d6b8a 100644 --- a/plugins/CoreHome/templates/_topBar.twig +++ b/plugins/CoreHome/templates/_topBar.twig @@ -13,6 +13,8 @@ {{ menu._html|raw }} {% else %} <a {% if menu._tooltip is defined %}title="{{ menu._tooltip }}"{% endif %} + {% if menu._attribute is defined %}{{ menu._attribute }}{% endif %} + {% if menu._onclick is defined %}onClick="{{ menu._onclick }}"{% endif %} {% if menu._url.module is defined %} id="topmenu-{{ menu._url.module|lower }}" href="index.php{{ menu._url|urlRewriteWithParameters }}" diff --git a/plugins/CoreHome/tests/Integration/ChangesTest.php b/plugins/CoreHome/tests/Integration/ChangesTest.php new file mode 100644 index 0000000000..3c22ad03f3 --- /dev/null +++ b/plugins/CoreHome/tests/Integration/ChangesTest.php @@ -0,0 +1,50 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\Plugins\CoreHome\tests\Integration; + +use Piwik\Tests\Fixtures\CreateChanges; +use Piwik\Tests\Framework\TestCase\IntegrationTestCase; +use Piwik\Changes\Model as ChangesModel; + +/** + * @group CoreHome + * @group CoreHomeTest + * @group CoreHomeChanges + */ +class ChangesTest extends IntegrationTestCase +{ + + /** + * @var CreateChanges + */ + public static $fixture; + + public function test_CoreHomeChanges_ShouldSortChangeListMostRecentFirst() + { + $json = '{"idchange":5,"plugin_name":"CoreHome","version":"4.6.0b5","title":"New feature x added","description":"Now you can do a with b like this","link_name":"For more information go here","link":"https:\/\/www.matomo.org"}'; + $changesModel = new ChangesModel(); + $changes = $changesModel->getChangeItems(); + $r = reset($changes); + unset($r['created_time']); + $this->assertEquals($json, json_encode($r, true)); + } + + public function test_CoreHomeChanges_ShouldAllowChangeItemAddWithoutLink() + { + $json = '{"idchange":4,"plugin_name":"CoreHome","version":"4.5.0","title":"New feature y added","description":"Now you can do c with d like this","link_name":null,"link":null}'; + $changesModel = new ChangesModel(); + $changes = $changesModel->getChangeItems(); + $r = $changes[1]; + unset($r['created_time']); + $this->assertEquals($json, json_encode($r, true)); + } + +} + +ChangesTest::$fixture = new CreateChanges(); diff --git a/plugins/CoreHome/tests/Integration/Column/UserIdTest.php b/plugins/CoreHome/tests/Integration/Column/UserIdTest.php index 848d933f5a..da1fd47ee9 100644 --- a/plugins/CoreHome/tests/Integration/Column/UserIdTest.php +++ b/plugins/CoreHome/tests/Integration/Column/UserIdTest.php @@ -9,8 +9,6 @@ namespace Piwik\Plugins\CoreHome\tests\Integration\Column; use Piwik\Cache; -use Piwik\DataAccess\ArchiveTableCreator; -use Piwik\Db; use Piwik\Metrics; use Piwik\Plugins\CoreHome\Columns\UserId; use Piwik\Tests\Framework\Fixture; diff --git a/plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php b/plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php index acbf850dde..f0fc25024c 100644 --- a/plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php +++ b/plugins/CoreHome/tests/Integration/Column/VisitLastActionTimeTest.php @@ -8,23 +8,14 @@ namespace Piwik\Plugins\CoreHome\tests\Integration\Column; -use Piwik\Cache; use Piwik\Common; -use Piwik\DataAccess\ArchiveTableCreator; use Piwik\Date; -use Piwik\Db; -use Piwik\Metrics; -use Piwik\Plugins\CoreHome\Columns\UserId; use Piwik\Plugins\CoreHome\Columns\VisitLastActionTime; -use Piwik\Plugins\CoreHome\Tracker\LogTable\Visit; use Piwik\Tests\Framework\Fixture; -use Piwik\Tests\Framework\Mock\FakeAccess; use Piwik\Tests\Framework\TestCase\IntegrationTestCase; -use Piwik\DataTable; use Piwik\Tracker\Request; use Piwik\Tracker\Visit\VisitProperties; use Piwik\Tracker\Visitor; -use Piwik\Tracker\VisitorRecognizer; /** * @group CoreHome diff --git a/plugins/CoreHome/tests/UI/Changes_spec.js b/plugins/CoreHome/tests/UI/Changes_spec.js new file mode 100644 index 0000000000..0ba2a77924 --- /dev/null +++ b/plugins/CoreHome/tests/UI/Changes_spec.js @@ -0,0 +1,29 @@ +/*! + * Matomo - free/libre analytics platform + * + * Dashboard screenshot tests. + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +describe('Changes', function () { + this.timeout(0); + + this.fixture = "Piwik\\Tests\\Fixtures\\CreateChanges"; + + var url = "?module=CoreAdminHome&action=home&idSite=1&period=day&date=yesterday"; + + it('should show changes', async function () { + await page.goto(url); + await page.waitForNetworkIdle(); + + await page.click('.right > li:nth-child(5) > a:nth-child(1)'); + await page.waitForNetworkIdle(); + + var elem = await page.waitForSelector('#Piwik_Popover'); + + expect(await elem.screenshot()).to.matchImage('show_popover'); + }); + +}); diff --git a/plugins/CoreHome/tests/UI/SingleMetricView_spec.js b/plugins/CoreHome/tests/UI/SingleMetricView_spec.js index 93b1959894..d0722973b7 100644 --- a/plugins/CoreHome/tests/UI/SingleMetricView_spec.js +++ b/plugins/CoreHome/tests/UI/SingleMetricView_spec.js @@ -38,7 +38,7 @@ describe('SingleMetricView', function () { $('#dashboardWidgetsArea #widgetCoreVisualizationssingleMetricViewcolumn .jqplot-seriespicker').trigger('mouseenter'); }); await page.webpage.evaluate(function(){ - $('#dashboardWidgetsArea .jqplot-seriespicker-popover label:contains(Revenue)').click(); + $('#dashboardWidgetsArea .jqplot-seriespicker-popover label:contains(Revenue):eq(0)').click(); }); await page.waitForNetworkIdle(); await page.waitForTimeout(250); @@ -53,7 +53,7 @@ describe('SingleMetricView', function () { }); await page.waitForTimeout(250); await page.evaluate(function(){ - $('#dashboardWidgetsArea .jqplot-seriespicker-popover label:contains(_x)').click() + $('#dashboardWidgetsArea .jqplot-seriespicker-popover label:contains(_x):eq(0)').click() }); await page.waitForNetworkIdle(); await page.waitForTimeout(250); @@ -69,7 +69,7 @@ describe('SingleMetricView', function () { }); await page.waitForTimeout(250); await page.evaluate(function(){ - $('#dashboardWidgetsArea #widgetCoreVisualizationssingleMetricViewcolumn .jqplot-seriespicker-popover label:contains(Revenue)').click() + $('#dashboardWidgetsArea #widgetCoreVisualizationssingleMetricViewcolumn .jqplot-seriespicker-popover label:contains(Revenue):eq(0)').click() }); await page.waitForNetworkIdle(); await page.waitForTimeout(250); diff --git a/plugins/CoreHome/tests/UI/expected-screenshots/Changes_show_popover.png b/plugins/CoreHome/tests/UI/expected-screenshots/Changes_show_popover.png new file mode 100644 index 0000000000..bd5f69163c --- /dev/null +++ b/plugins/CoreHome/tests/UI/expected-screenshots/Changes_show_popover.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f844aa8ae955f79da1581be5763ba61d01774043be2b5856df5f3b7894dbc24c +size 72788 diff --git a/plugins/CoreHome/tests/UI/expected-screenshots/ShowChanges_view.png b/plugins/CoreHome/tests/UI/expected-screenshots/ShowChanges_view.png new file mode 100644 index 0000000000..7843fcffbc --- /dev/null +++ b/plugins/CoreHome/tests/UI/expected-screenshots/ShowChanges_view.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5391866af7ca6c0522d75dbbfcc1b798ad234728ab7d1f8dcb7b13d2040fbdbd +size 42705 diff --git a/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_formatted_metric.png b/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_formatted_metric.png index 26ce8b42b5..6f6a0b3397 100644 --- a/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_formatted_metric.png +++ b/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_formatted_metric.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fb9305159cdcbf107a6747b315cba146214a1f73f404c200aa37d6734706ccc2 -size 6485 +oid sha256:f52ffb459eaad6bf566e3f837974b82f02ef104a484d16149b3e8f204f6a220f +size 6302 diff --git a/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_goal_metric.png b/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_goal_metric.png index e6cdfa9a26..668b981e43 100644 --- a/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_goal_metric.png +++ b/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_goal_metric.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:33bbb2c1fe617afaf7dc2216e981057698abe7679814ca3d4a729517b7859b33 -size 8952 +oid sha256:d7eae513738ddda333cabbf469c1acadb3ac3bc4f7ed80caa0520b0a73b23dfb +size 9002 diff --git a/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_loaded.png b/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_loaded.png index 9dcc86fc15..2d0189601c 100644 --- a/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_loaded.png +++ b/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_loaded.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:da10b7861b5b8208164116aebb716bb8d6028701544c7430bf172d9b328fbe74 -size 4741 +oid sha256:e8d3f4bcf5e2b039f91160466eb94f26f54f24d57d03188cce70132795789609 +size 4646 diff --git a/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_range.png b/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_range.png index f685b2dc05..97a4a0938c 100644 --- a/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_range.png +++ b/plugins/CoreHome/tests/UI/expected-screenshots/SingleMetricView_range.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9cbbbee4066bb4ae19015e8398353d512f42d943cd27a375554218f865581738 -size 5059 +oid sha256:307d7efaa78defa78c7162bae0e51beb7d8d963db529ab5f4a95153f339c2fd3 +size 4844 diff --git a/plugins/CoreHome/tests/Unit/EvolutionMetricTest.php b/plugins/CoreHome/tests/Unit/EvolutionMetricTest.php new file mode 100644 index 0000000000..7929eba0e4 --- /dev/null +++ b/plugins/CoreHome/tests/Unit/EvolutionMetricTest.php @@ -0,0 +1,62 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Plugins\CoreHome\tests\Unit; + +use PHPUnit\Framework\TestCase; +use Piwik\DataTable; +use Piwik\DataTable\Row; +use Piwik\Date; +use Piwik\Plugins\CoreHome\Columns\Metrics\EvolutionMetric; + +/** + * @group CoreHome + * @group CoreHomeTest + * @group EvolutionMetric + */ +class EvolutionMetricTest extends TestCase +{ + public function test_shouldDoProportionalComparision_ifCurrentPeriodIncomplete() + { + $currentData = new DataTable(); + $cPeriod = new \Piwik\Period\Week(Date::factory('2021-10-10')); + $currentData->setMetadata('period', $cPeriod); + + // If the archived date meta data value exists on the row then it will be used + // as the current date for calculation purposes, we can use this to consistently test the + // ratio calculation by supplying a fixed set of dates that should result in a 0.5 ratio + + $row = new Row(); + $row->setMetadata(DataTable::ARCHIVED_DATE_METADATA_NAME, '2021-10-07 00:00:00'); + + $pastData = new DataTable(); + $sPeriod = new \Piwik\Period\Week(Date::factory('2021-10-03')); + $pastData->setMetadata('period', $sPeriod); + + $ratio = EvolutionMetric::getRatio($currentData, $pastData, $row); + + $this->assertEquals(0.429, $ratio); + } + + public function test_shouldNotDoProportionalComparision_ifCurrentPeriodComplete() + { + $currentData = new DataTable(); + $cPeriod = new \Piwik\Period\Week(Date::factory('2021-10-10')); + $currentData->setMetadata('period', $cPeriod); + + $pastData = new DataTable(); + $sPeriod = new \Piwik\Period\Week(Date::factory('2021-10-03')); + $pastData->setMetadata('period', $sPeriod); + + $ratio = EvolutionMetric::getRatio($currentData, $pastData, new Row()); + + $this->assertEquals(1, $ratio); + } + +} diff --git a/plugins/CoreHome/vue/dist/CoreHome.umd.js b/plugins/CoreHome/vue/dist/CoreHome.umd.js index 36e4c542d9..3032d70e23 100644 --- a/plugins/CoreHome/vue/dist/CoreHome.umd.js +++ b/plugins/CoreHome/vue/dist/CoreHome.umd.js @@ -128,11 +128,22 @@ module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__; __webpack_require__.r(__webpack_exports__); // EXPORTS +__webpack_require__.d(__webpack_exports__, "createVueApp", function() { return /* reexport */ createVueApp; }); +__webpack_require__.d(__webpack_exports__, "useExternalPluginComponent", function() { return /* reexport */ useExternalPluginComponent; }); +__webpack_require__.d(__webpack_exports__, "DirectiveUtilities", function() { return /* reexport */ directiveUtilities; }); +__webpack_require__.d(__webpack_exports__, "debounce", function() { return /* reexport */ debounce; }); +__webpack_require__.d(__webpack_exports__, "getFormattedEvolution", function() { return /* reexport */ getFormattedEvolution; }); __webpack_require__.d(__webpack_exports__, "createAngularJsAdapter", function() { return /* reexport */ createAngularJsAdapter; }); +__webpack_require__.d(__webpack_exports__, "transformAngularJsBoolAttr", function() { return /* reexport */ transformAngularJsBoolAttr; }); +__webpack_require__.d(__webpack_exports__, "transformAngularJsIntAttr", function() { return /* reexport */ transformAngularJsIntAttr; }); +__webpack_require__.d(__webpack_exports__, "removeAngularJsSpecificProperties", function() { return /* reexport */ removeAngularJsSpecificProperties; }); +__webpack_require__.d(__webpack_exports__, "clone", function() { return /* reexport */ clone; }); +__webpack_require__.d(__webpack_exports__, "cloneThenApply", function() { return /* reexport */ cloneThenApply; }); __webpack_require__.d(__webpack_exports__, "activityIndicatorAdapter", function() { return /* reexport */ ActivityIndicator_adapter; }); __webpack_require__.d(__webpack_exports__, "ActivityIndicator", function() { return /* reexport */ ActivityIndicator; }); __webpack_require__.d(__webpack_exports__, "translate", function() { return /* reexport */ translate; }); -__webpack_require__.d(__webpack_exports__, "alertAdapter", function() { return /* reexport */ Alert_adapter; }); +__webpack_require__.d(__webpack_exports__, "translateOrDefault", function() { return /* reexport */ translateOrDefault; }); +__webpack_require__.d(__webpack_exports__, "Alert", function() { return /* reexport */ Alert; }); __webpack_require__.d(__webpack_exports__, "AjaxHelper", function() { return /* reexport */ AjaxHelper_AjaxHelper; }); __webpack_require__.d(__webpack_exports__, "setCookie", function() { return /* reexport */ setCookie; }); __webpack_require__.d(__webpack_exports__, "getCookie", function() { return /* reexport */ getCookie; }); @@ -149,22 +160,49 @@ __webpack_require__.d(__webpack_exports__, "format", function() { return /* reex __webpack_require__.d(__webpack_exports__, "getToday", function() { return /* reexport */ getToday; }); __webpack_require__.d(__webpack_exports__, "parseDate", function() { return /* reexport */ parseDate; }); __webpack_require__.d(__webpack_exports__, "todayIsInRange", function() { return /* reexport */ todayIsInRange; }); -__webpack_require__.d(__webpack_exports__, "Dropdown", function() { return /* reexport */ DropdownMenu; }); +__webpack_require__.d(__webpack_exports__, "DropdownMenu", function() { return /* reexport */ DropdownMenu; }); __webpack_require__.d(__webpack_exports__, "FocusAnywhereButHere", function() { return /* reexport */ FocusAnywhereButHere; }); __webpack_require__.d(__webpack_exports__, "FocusIf", function() { return /* reexport */ FocusIf; }); +__webpack_require__.d(__webpack_exports__, "Tooltips", function() { return /* reexport */ Tooltips; }); __webpack_require__.d(__webpack_exports__, "MatomoDialog", function() { return /* reexport */ MatomoDialog; }); __webpack_require__.d(__webpack_exports__, "ExpandOnClick", function() { return /* reexport */ ExpandOnClick; }); __webpack_require__.d(__webpack_exports__, "ExpandOnHover", function() { return /* reexport */ ExpandOnHover; }); +__webpack_require__.d(__webpack_exports__, "ShowSensitiveData", function() { return /* reexport */ ShowSensitiveData; }); +__webpack_require__.d(__webpack_exports__, "DropdownButton", function() { return /* reexport */ DropdownButton; }); +__webpack_require__.d(__webpack_exports__, "SelectOnFocus", function() { return /* reexport */ SelectOnFocus; }); +__webpack_require__.d(__webpack_exports__, "SideNav", function() { return /* reexport */ SideNav; }); __webpack_require__.d(__webpack_exports__, "EnrichedHeadline", function() { return /* reexport */ EnrichedHeadline; }); __webpack_require__.d(__webpack_exports__, "ContentBlock", function() { return /* reexport */ ContentBlock; }); __webpack_require__.d(__webpack_exports__, "Comparisons", function() { return /* reexport */ Comparisons; }); -__webpack_require__.d(__webpack_exports__, "Menudropdown", function() { return /* reexport */ Menudropdown; }); +__webpack_require__.d(__webpack_exports__, "MenuItemsDropdown", function() { return /* reexport */ MenuItemsDropdown; }); __webpack_require__.d(__webpack_exports__, "DatePicker", function() { return /* reexport */ DatePicker; }); __webpack_require__.d(__webpack_exports__, "DateRangePicker", function() { return /* reexport */ DateRangePicker; }); __webpack_require__.d(__webpack_exports__, "PeriodDatePicker", function() { return /* reexport */ PeriodDatePicker; }); __webpack_require__.d(__webpack_exports__, "Notification", function() { return /* reexport */ Notification; }); __webpack_require__.d(__webpack_exports__, "NotificationGroup", function() { return /* reexport */ Notification_NotificationGroup; }); __webpack_require__.d(__webpack_exports__, "NotificationsStore", function() { return /* reexport */ Notifications_store; }); +__webpack_require__.d(__webpack_exports__, "SitesStore", function() { return /* reexport */ SiteSelector_SitesStore; }); +__webpack_require__.d(__webpack_exports__, "SiteSelector", function() { return /* reexport */ SiteSelector; }); +__webpack_require__.d(__webpack_exports__, "QuickAccess", function() { return /* reexport */ QuickAccess; }); +__webpack_require__.d(__webpack_exports__, "FieldArray", function() { return /* reexport */ FieldArray; }); +__webpack_require__.d(__webpack_exports__, "MultiPairField", function() { return /* reexport */ MultiPairField; }); +__webpack_require__.d(__webpack_exports__, "PeriodSelector", function() { return /* reexport */ PeriodSelector; }); +__webpack_require__.d(__webpack_exports__, "ReportingMenu", function() { return /* reexport */ ReportingMenu; }); +__webpack_require__.d(__webpack_exports__, "ReportingMenuStore", function() { return /* reexport */ ReportingMenu_store; }); +__webpack_require__.d(__webpack_exports__, "ReportingPagesStore", function() { return /* reexport */ ReportingPages_store; }); +__webpack_require__.d(__webpack_exports__, "ReportMetadataStore", function() { return /* reexport */ ReportMetadata_store; }); +__webpack_require__.d(__webpack_exports__, "WidgetsStore", function() { return /* reexport */ Widgets_store; }); +__webpack_require__.d(__webpack_exports__, "WidgetLoader", function() { return /* reexport */ WidgetLoader; }); +__webpack_require__.d(__webpack_exports__, "WidgetContainer", function() { return /* reexport */ WidgetContainer; }); +__webpack_require__.d(__webpack_exports__, "WidgetByDimensionContainer", function() { return /* reexport */ WidgetByDimensionContainer; }); +__webpack_require__.d(__webpack_exports__, "Widget", function() { return /* reexport */ Widget_Widget; }); +__webpack_require__.d(__webpack_exports__, "ReportingPage", function() { return /* reexport */ ReportingPage; }); +__webpack_require__.d(__webpack_exports__, "ReportExport", function() { return /* reexport */ ReportExport; }); +__webpack_require__.d(__webpack_exports__, "Sparkline", function() { return /* reexport */ Sparkline; }); +__webpack_require__.d(__webpack_exports__, "Progressbar", function() { return /* reexport */ Progressbar; }); +__webpack_require__.d(__webpack_exports__, "ContentIntro", function() { return /* reexport */ ContentIntro; }); +__webpack_require__.d(__webpack_exports__, "ContentTable", function() { return /* reexport */ ContentTable; }); +__webpack_require__.d(__webpack_exports__, "AjaxForm", function() { return /* reexport */ AjaxForm; }); // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js // This file is imported into lib/wc client bundles. @@ -329,7 +367,7 @@ Matomo_piwik.updateDateInTitle = function updateDateInTitle(date, period) { if (originalTitle.indexOf(Matomo_piwik.siteName) === 0) { var dateString = " - ".concat(Periods_Periods.parse(period, date).getPrettyString(), " "); - document.title = "".concat(Matomo_piwik.siteName).concat(dateString).concat(originalTitle.substr(Matomo_piwik.siteName.length)); + document.title = "".concat(Matomo_piwik.siteName).concat(dateString).concat(originalTitle.slice(Matomo_piwik.siteName.length)); } }; @@ -387,18 +425,33 @@ var Matomo = Matomo_piwik; * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ function translate(translationStringId) { + if (!translationStringId) { + return ''; + } + for (var _len = arguments.length, values = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { values[_key - 1] = arguments[_key]; } var pkArgs = values; // handle variadic args AND single array of values (to match _pk_translate signature) - if (values.length === 1 && values[0] && values[0] instanceof Array) { + if (values.length === 1 && values[0] && Array.isArray(values[0])) { pkArgs = values[0]; } return window._pk_translate(translationStringId, pkArgs); // eslint-disable-line } +function translateOrDefault(translationStringIdOrText) { + if (!translationStringIdOrText || !window.piwik_translations[translationStringIdOrText]) { + return translationStringIdOrText; + } + + for (var _len2 = arguments.length, values = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { + values[_key2 - 1] = arguments[_key2]; + } + + return translate.apply(void 0, [translationStringIdOrText].concat(values)); +} // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Periods/utilities.ts /*! * Matomo - free/libre analytics platform @@ -543,6 +596,11 @@ var Range_RangePeriod = /*#__PURE__*/function () { value: function containsToday() { return todayIsInRange(this.getDateRange()); } + }, { + key: "getDayCount", + value: function getDayCount() { + return Math.ceil((this.endDate.getTime() - this.startDate.getTime()) / (1000 * 3600 * 24)) + 1; + } }], [{ key: "getLastNRange", value: function getLastNRange(childPeriodType, strAmount, strEndDate) { @@ -1018,9 +1076,17 @@ Periods_Periods.addCustomPeriod('year', Year_YearPeriod); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.ts -function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function MatomoUrl_slicedToArray(arr, i) { return MatomoUrl_arrayWithHoles(arr) || MatomoUrl_iterableToArrayLimit(arr, i) || MatomoUrl_unsupportedIterableToArray(arr, i) || MatomoUrl_nonIterableRest(); } + +function MatomoUrl_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function MatomoUrl_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return MatomoUrl_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return MatomoUrl_arrayLikeToArray(o, minLen); } + +function MatomoUrl_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } -function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { MatomoUrl_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function MatomoUrl_iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function MatomoUrl_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function MatomoUrl_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } @@ -1068,15 +1134,15 @@ var MatomoUrl_MatomoUrl = /*#__PURE__*/function () { MatomoUrl_defineProperty(this, "hashQuery", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])('')); MatomoUrl_defineProperty(this, "urlParsed", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(MatomoUrl_broadcast.getValuesFromUrl("?".concat(_this.urlQuery.value), true)); + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_this.parse(_this.urlQuery.value)); })); MatomoUrl_defineProperty(this, "hashParsed", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(MatomoUrl_broadcast.getValuesFromUrl("?".concat(_this.hashQuery.value), true)); + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_this.parse(_this.hashQuery.value)); })); MatomoUrl_defineProperty(this, "parsed", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_objectSpread(_objectSpread({}, _this.urlParsed.value), _this.hashParsed.value)); + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(Object.assign(Object.assign({}, _this.urlParsed.value), _this.hashParsed.value)); })); this.setUrlQuery(window.location.search); @@ -1095,11 +1161,59 @@ var MatomoUrl_MatomoUrl = /*#__PURE__*/function () { } MatomoUrl_createClass(MatomoUrl, [{ + key: "updateHashToUrl", + value: function updateHashToUrl(url) { + var $location = Matomo_Matomo.helper.getAngularDependency('$location'); + $location.url(url); + } + }, { key: "updateHash", value: function updateHash(params) { - var serializedParams = typeof params !== 'string' ? this.stringify(params) : params; + var modifiedParams = this.getFinalHashParams(params); + var serializedParams = this.stringify(modifiedParams); var $location = Matomo_Matomo.helper.getAngularDependency('$location'); $location.search(serializedParams); + var $timeout = Matomo_Matomo.helper.getAngularDependency('$timeout'); + $timeout(); + } + }, { + key: "updateUrl", + value: function updateUrl(params) { + var hashParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var serializedParams = typeof params !== 'string' ? this.stringify(params) : params; + var modifiedHashParams = Object.keys(hashParams).length ? this.getFinalHashParams(hashParams, params) : {}; + var serializedHashParams = this.stringify(modifiedHashParams); + var url = "?".concat(serializedParams); + + if (serializedHashParams.length) { + url = "".concat(url, "#?").concat(serializedHashParams); + } + + window.broadcast.propagateNewPage('', undefined, undefined, undefined, url); + } + }, { + key: "getFinalHashParams", + value: function getFinalHashParams(params) { + var urlParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var paramsObj = typeof params !== 'string' ? params : this.parse(params); + var urlParamsObj = typeof params !== 'string' ? urlParams : this.parse(urlParams); + return Object.assign({ + // these params must always be present in the hash + period: urlParamsObj.period || this.parsed.value.period, + date: urlParamsObj.date || this.parsed.value.date, + segment: urlParamsObj.segment || this.parsed.value.segment + }, paramsObj); + } // if we're in an embedded context, loads an entire new URL, otherwise updates the hash + + }, { + key: "updateLocation", + value: function updateLocation(params) { + if (Matomo_Matomo.helper.isAngularRenderingThePage()) { + this.updateHash(params); + return; + } + + this.updateUrl(params); } }, { key: "getSearchParam", @@ -1118,10 +1232,24 @@ var MatomoUrl_MatomoUrl = /*#__PURE__*/function () { return window.broadcast.getValueFromUrl(paramName, window.location.search); } }, { + key: "parse", + value: function parse(query) { + return MatomoUrl_broadcast.getValuesFromUrl("?".concat(query), true); + } + }, { key: "stringify", value: function stringify(search) { - // TODO: using $ since URLSearchParams does not handle array params the way Matomo uses them - return $.param(search).replace(/%5B%5D/g, '[]'); + var searchWithoutEmpty = Object.fromEntries(Object.entries(search).filter(function (_ref) { + var _ref2 = MatomoUrl_slicedToArray(_ref, 2), + value = _ref2[1]; + + return value !== '' && value !== null && value !== undefined; + })); // TODO: using $ since URLSearchParams does not handle array params the way Matomo uses them + + return $.param(searchWithoutEmpty).replace(/%5B%5D/g, '[]') // some browsers treat URLs w/ date=a,b differently from date=a%2Cb, causing multiple + // entries to show up in the browser history. this has a compounding effect w/ angular.js, + // which when the back button is pressed to effectively abort the back navigation. + .replace(/%2C/g, ','); } }, { key: "updatePeriodParamsFromUrl", @@ -1186,8 +1314,11 @@ function piwikUrl() { return model; } -piwikUrl.$inject = []; -angular.module('piwikApp.service').service('piwikUrl', piwikUrl); +window.angular.module('piwikApp.service').service('piwikUrl', piwikUrl); // make sure $location is initialized early + +window.angular.module('piwikApp.service').run(['$location', function () { + return null; +}]); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts /*! * Matomo - free/libre analytics platform @@ -1212,9 +1343,8 @@ function initPiwikService(piwik, $rootScope) { args[_key - 1] = arguments[_key]; } - Matomo_Matomo.postEvent.apply(Matomo_Matomo, [name].concat(args)); // can't always get the result. it's not really used in angularjs though, so it should be ok. - - return null; + Matomo_Matomo.postEventNoEmit.apply(Matomo_Matomo, [name].concat(args)); + return this.$oldEmit.apply(this, [name].concat(args)); // eslint-disable-line }; $rootScope.$oldBroadcast = $rootScope.$broadcast; // eslint-disable-line @@ -1225,7 +1355,7 @@ function initPiwikService(piwik, $rootScope) { } Matomo_Matomo.postEventNoEmit.apply(Matomo_Matomo, [name].concat(args)); - return $rootScope.$oldBroadcast.apply($rootScope, [name].concat(args)); // eslint-disable-line + return this.$oldBroadcast.apply(this, [name].concat(args)); // eslint-disable-line }; $rootScope.$on('$locationChangeSuccess', piwik.updatePeriodParamsFromUrl); @@ -1234,11 +1364,19 @@ function initPiwikService(piwik, $rootScope) { initPiwikService.$inject = ['piwik', '$rootScope']; window.angular.module('piwikApp.service').run(initPiwikService); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts -function AjaxHelper_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } -function AjaxHelper_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { AjaxHelper_ownKeys(Object(source), true).forEach(function (key) { AjaxHelper_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { AjaxHelper_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function AjaxHelper_toConsumableArray(arr) { return AjaxHelper_arrayWithoutHoles(arr) || AjaxHelper_iterableToArray(arr) || AjaxHelper_unsupportedIterableToArray(arr) || AjaxHelper_nonIterableSpread(); } -function AjaxHelper_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function AjaxHelper_nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function AjaxHelper_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return AjaxHelper_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return AjaxHelper_arrayLikeToArray(o, minLen); } + +function AjaxHelper_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } + +function AjaxHelper_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return AjaxHelper_arrayLikeToArray(arr); } + +function AjaxHelper_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } function AjaxHelper_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } @@ -1246,6 +1384,28 @@ function AjaxHelper_createClass(Constructor, protoProps, staticProps) { if (prot function AjaxHelper_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function AjaxHelper_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } + +function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } + +function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } + +function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } + +function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } + +function _construct(Parent, args, Class) { if (_isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } + +function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } + +function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } + +function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } + +function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } + /*! * Matomo - free/libre analytics platform * @@ -1315,6 +1475,20 @@ function defaultErrorCallback(deferred, status) { loadingError.show(); } } + +var ApiResponseError = /*#__PURE__*/function (_Error) { + _inherits(ApiResponseError, _Error); + + var _super = _createSuper(ApiResponseError); + + function ApiResponseError() { + AjaxHelper_classCallCheck(this, ApiResponseError); + + return _super.apply(this, arguments); + } + + return ApiResponseError; +}( /*#__PURE__*/_wrapNativeSuper(Error)); /** * Global ajax helper to handle requests within Matomo */ @@ -1348,10 +1522,16 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { AjaxHelper_defineProperty(this, "errorElement", '#ajaxError'); + AjaxHelper_defineProperty(this, "headers", void 0); + AjaxHelper_defineProperty(this, "requestHandle", null); + AjaxHelper_defineProperty(this, "abortController", null); + AjaxHelper_defineProperty(this, "defaultParams", ['idSite', 'period', 'date', 'segment']); + AjaxHelper_defineProperty(this, "resolveWithHelper", false); + this.errorCallback = defaultErrorCallback; } /** @@ -1378,6 +1558,10 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { return; } + if (typeof value === 'boolean') { + value = value ? 1 : 0; + } + if (type.toLowerCase() === 'get') { _this.getParams[key] = value; } else if (type.toLowerCase() === 'post') { @@ -1581,14 +1765,44 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { this.requestHandle = this.buildAjaxCall(); window.globalAjaxQueue.push(this.requestHandle); - return new Promise(function (resolve, reject) { - _this2.requestHandle.then(resolve).fail(function (xhr) { - if (xhr.statusText !== 'abort') { - console.log("Warning: the ".concat($.param(_this2.getParams), " request failed!")); - reject(xhr); + var $timeout = null; + + try { + $timeout = Matomo_Matomo.helper.getAngularDependency('$timeout'); + } catch (e) {// ignore + } + + if (this.abortController) { + this.abortController.signal.addEventListener('abort', function () { + if (_this2.requestHandle) { + _this2.requestHandle.abort(); + } + }); + } + + var result = new Promise(function (resolve, reject) { + _this2.requestHandle.then(function (data) { + if (_this2.resolveWithHelper) { + // NOTE: we can't resolve w/ the jquery xhr, because it's a promise, and will + // just result in following the promise chain back to 'data' + resolve(_this2); // casting hack here + } else { + resolve(data); // ignoring textStatus/jqXHR + } + }).fail(function (xhr) { + if (xhr.statusText === 'abort') { + return; + } + + console.log("Warning: the ".concat($.param(_this2.getParams), " request failed!")); + reject(xhr); + }).done(function () { + if ($timeout) { + $timeout(); // trigger digest } }); }); + return result; } /** * Aborts the current request if it is (still) running @@ -1638,6 +1852,7 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { url: url, dataType: this.format || 'json', complete: this.completeCallback, + headers: this.headers ? this.headers : undefined, error: function errorCallback() { window.globalAjaxQueue.active -= 1; @@ -1664,7 +1879,9 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { type = null; } - if (response.message) { + var isLoggedIn = !document.querySelector('#login_form'); + + if (response.message && isLoggedIn) { var UI = window['require']('piwik/UI'); // eslint-disable-line var notification = new UI.Notification(); @@ -1725,9 +1942,7 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { key: "mixinDefaultPostParams", value: function mixinDefaultPostParams(params) { var defaultParams = this.getDefaultPostParams(); - - var mergedParams = AjaxHelper_objectSpread(AjaxHelper_objectSpread({}, defaultParams), params); - + var mergedParams = Object.assign(Object.assign({}, defaultParams), params); return mergedParams; } /** @@ -1766,6 +1981,11 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { return params; } + }, { + key: "getRequestHandle", + value: function getRequestHandle() { + return this.requestHandle; + } }], [{ key: "fetch", value: @@ -1827,10 +2047,15 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { */ /** + * Extra headers to add to the request. + */ + + /** * Handle for current request */ // helper method entry point - function fetch(params) { + function fetch( // eslint-disable-line + params) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var helper = new AjaxHelper(); @@ -1838,17 +2063,109 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { helper.withTokenInUrl(); } - helper.setFormat('json'); - helper.addParams(AjaxHelper_objectSpread({ - module: 'API', - format: 'json' - }, params), 'get'); + if (options.errorElement) { + helper.setErrorElement(options.errorElement); + } + + if (options.redirectOnSuccess) { + helper.redirectOnSuccess(options.redirectOnSuccess !== true ? options.redirectOnSuccess : undefined); + } + + helper.setFormat(options.format || 'json'); + + if (Array.isArray(params)) { + helper.setBulkRequests.apply(helper, AjaxHelper_toConsumableArray(params)); + } else { + helper.addParams(Object.assign(Object.assign({ + module: 'API', + format: options.format || 'json' + }, params), {}, { + // ajax helper does not encode the segment parameter assuming it is already encoded. this is + // probably for pre-angularjs code, so we don't want to do this now, but just treat segment + // as a normal query parameter input (so it will have double encoded values in input params + // object, then naturally triple encoded in the URL after a $.param call), however we need + // to support any existing uses of the old code, so instead we do a manual encode here. new + // code that uses .fetch() will not need to pre-encode the parameter, while old code + // can pre-encode it. + segment: params.segment ? encodeURIComponent(params.segment) : undefined + }), 'get'); + } if (options.postParams) { helper.addParams(options.postParams, 'post'); } - return helper.send(); + if (options.headers) { + helper.headers = options.headers; + } + + var createErrorNotification = true; + + if (typeof options.createErrorNotification !== 'undefined' && !options.createErrorNotification) { + helper.useCallbackInCaseOfError(); + helper.setErrorCallback(null); + createErrorNotification = false; + } + + if (options.abortController) { + helper.abortController = options.abortController; + } + + if (options.returnResponseObject) { + helper.resolveWithHelper = true; + } + + return helper.send().then(function (result) { + var data = result instanceof AjaxHelper ? result.requestHandle.responseJSON : result; // check for error if not using default notification behavior + + if (data.result === 'error') { + throw new ApiResponseError(data.message); + } + + return result; + }).catch(function (xhr) { + if (createErrorNotification) { + throw xhr; + } + + var message = 'Something went wrong'; + + if (xhr.status === 504) { + message = 'Request was prossibly aborted'; + } + + throw new Error(message); + }); + } // eslint-disable-next-line @typescript-eslint/no-explicit-any + + }, { + key: "post", + value: function post(params) { + var postParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + return AjaxHelper.fetch(params, Object.assign(Object.assign({}, options), {}, { + postParams: postParams + })); + } // eslint-disable-next-line @typescript-eslint/no-explicit-any + + }, { + key: "oneAtATime", + value: function oneAtATime(method, options) { + var abortController = null; + return function (params, postParams) { + if (abortController) { + abortController.abort(); + } + + abortController = new AbortController(); + return AjaxHelper.post(Object.assign(Object.assign({}, params), {}, { + method: method + }), postParams, Object.assign(Object.assign({}, options), {}, { + abortController: abortController + })).finally(function () { + abortController = null; + }); + }; } }]); @@ -1861,10 +2178,480 @@ var AjaxHelper_AjaxHelper = /*#__PURE__*/function () { window.ajaxHelper = AjaxHelper_AjaxHelper; function ajaxQueue() { - return globalAjaxQueue; + return window.globalAjaxQueue; +} + +window.angular.module('piwikApp.service').service('globalAjaxQueue', ajaxQueue); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PopoverHandler/PopoverHandler.ts +function PopoverHandler_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function PopoverHandler_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function PopoverHandler_createClass(Constructor, protoProps, staticProps) { if (protoProps) PopoverHandler_defineProperties(Constructor.prototype, protoProps); if (staticProps) PopoverHandler_defineProperties(Constructor, staticProps); return Constructor; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +var PopoverHandler_window = window, + PopoverHandler_$ = PopoverHandler_window.$; + +var PopoverHandler_PopoverHandler = /*#__PURE__*/function () { + function PopoverHandler() { + PopoverHandler_classCallCheck(this, PopoverHandler); + + this.setup(); + } + + PopoverHandler_createClass(PopoverHandler, [{ + key: "setup", + value: function setup() { + var _this = this; + + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () { + return src_MatomoUrl_MatomoUrl.parsed.value.popover; + }, function () { + return _this.onPopoverParamChanged(); + }); + + if (src_MatomoUrl_MatomoUrl.parsed.value.popover) { + this.onPopoverParamChangedInitial(); + } + } // don't initiate the handler until the page had a chance to render, + // since some rowactions depend on what's been loaded. + + }, { + key: "onPopoverParamChangedInitial", + value: function onPopoverParamChangedInitial() { + var _this2 = this; + + PopoverHandler_$(function () { + setTimeout(function () { + _this2.openOrClose(); + }); + }); + } + }, { + key: "onPopoverParamChanged", + value: function onPopoverParamChanged() { + var _this3 = this; + + // make sure all popover handles were registered + PopoverHandler_$(function () { + _this3.openOrClose(); + }); + } + }, { + key: "openOrClose", + value: function openOrClose() { + this.close(); // should be rather done by routing + + var popoverParam = src_MatomoUrl_MatomoUrl.parsed.value.popover; + + if (popoverParam) { + this.open(popoverParam); + } else { + // the URL should only be set to an empty popover if there are no popovers in the stack. + // to avoid avoid any strange inconsistent states, we reset the popover stack here. + window.broadcast.resetPopoverStack(); + } + } + }, { + key: "close", + value: function close() { + window.Piwik_Popover.close(); + } + }, { + key: "open", + value: function open(thePopoverParam) { + // in case the $ was encoded (e.g. when using copy&paste on urls in some browsers) + var popoverParam = decodeURIComponent(thePopoverParam); // revert special encoding from broadcast.propagateNewPopoverParameter() + + popoverParam = popoverParam.replace(/\$/g, '%'); + popoverParam = decodeURIComponent(popoverParam); + var popoverParamParts = popoverParam.split(':'); + var handlerName = popoverParamParts[0]; + popoverParamParts.shift(); + var param = popoverParamParts.join(':'); + + if (typeof window.broadcast.popoverHandlers[handlerName] !== 'undefined' && !window.broadcast.isLoginPage()) { + window.broadcast.popoverHandlers[handlerName](param); + } + } + }]); + + return PopoverHandler; +}(); + +/* harmony default export */ var src_PopoverHandler_PopoverHandler = (new PopoverHandler_PopoverHandler()); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Alert/Alert.vue?vue&type=template&id=c3863ae2 +function Alertvue_type_template_id_c3863ae2_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + + +function Alertvue_type_template_id_c3863ae2_render(_ctx, _cache, $props, $setup, $data, $options) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["alert", Alertvue_type_template_id_c3863ae2_defineProperty({}, "alert-".concat(_ctx.severity), true)]) + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")], 2); } +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Alert/Alert.vue?vue&type=template&id=c3863ae2 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Alert/Alert.vue?vue&type=script&lang=ts -angular.module('piwikApp.service').service('globalAjaxQueue', ajaxQueue); +/* harmony default export */ var Alertvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + severity: { + type: String, + required: true + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Alert/Alert.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Alert/Alert.vue + + + +Alertvue_type_script_lang_ts.render = Alertvue_type_template_id_c3863ae2_render + +/* harmony default export */ var Alert = (Alertvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/createVueApp.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +function createVueApp() { + var app = external_commonjs_vue_commonjs2_vue_root_Vue_["createApp"].apply(void 0, arguments); + app.config.globalProperties.$sanitize = window.vueSanitize; + app.config.globalProperties.translate = translate; + app.config.globalProperties.translateOrDefault = translateOrDefault; + return app; +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/createAngularJsAdapter.ts +function createAngularJsAdapter_slicedToArray(arr, i) { return createAngularJsAdapter_arrayWithHoles(arr) || createAngularJsAdapter_iterableToArrayLimit(arr, i) || createAngularJsAdapter_unsupportedIterableToArray(arr, i) || createAngularJsAdapter_nonIterableRest(); } + +function createAngularJsAdapter_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function createAngularJsAdapter_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return createAngularJsAdapter_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return createAngularJsAdapter_arrayLikeToArray(o, minLen); } + +function createAngularJsAdapter_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function createAngularJsAdapter_iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function createAngularJsAdapter_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + +function createAngularJsAdapter_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { createAngularJsAdapter_typeof = function _typeof(obj) { return typeof obj; }; } else { createAngularJsAdapter_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return createAngularJsAdapter_typeof(obj); } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/* eslint-disable @typescript-eslint/no-explicit-any */ + + + +var transcludeCounter = 0; + +function toKebabCase(arg) { + return arg.substring(0, 1).toLowerCase() + arg.substring(1).replace(/[A-Z]/g, function (s) { + return "-".concat(s.toLowerCase()); + }); +} + +function toAngularJsCamelCase(arg) { + return arg.substring(0, 1).toLowerCase() + arg.substring(1).replace(/-([a-z])/g, function (s, p) { + return p.toUpperCase(); + }); +} + +function removeAngularJsSpecificProperties(newValue) { + if (createAngularJsAdapter_typeof(newValue) === 'object' && newValue !== null && Object.getPrototypeOf(newValue) === Object.prototype) { + return Object.fromEntries(Object.entries(newValue).filter(function (pair) { + return !/^\$/.test(pair[0]); + })); + } + + return newValue; +} +function createAngularJsAdapter(options) { + var component = options.component, + require = options.require, + _options$scope = options.scope, + scope = _options$scope === void 0 ? {} : _options$scope, + _options$events = options.events, + events = _options$events === void 0 ? {} : _options$events, + $inject = options.$inject, + directiveName = options.directiveName, + transclude = options.transclude, + mountPointFactory = options.mountPointFactory, + postCreate = options.postCreate, + noScope = options.noScope, + _options$restrict = options.restrict, + restrict = _options$restrict === void 0 ? 'A' : _options$restrict, + priority = options.priority, + replace = options.replace; + var currentTranscludeCounter = transcludeCounter; + + if (transclude) { + transcludeCounter += 1; + } + + var vueToAngular = {}; + var angularJsScope = {}; + Object.entries(scope).forEach(function (_ref) { + var _ref2 = createAngularJsAdapter_slicedToArray(_ref, 2), + scopeVarName = _ref2[0], + info = _ref2[1]; + + if (!info.vue) { + info.vue = scopeVarName; + } + + if (info.angularJsBind) { + angularJsScope[scopeVarName] = info.angularJsBind; + } + + vueToAngular[info.vue] = scopeVarName; + }); + + function angularJsAdapter() { + for (var _len = arguments.length, injectedServices = new Array(_len), _key = 0; _key < _len; _key++) { + injectedServices[_key] = arguments[_key]; + } + + var adapter = { + restrict: restrict, + require: require, + priority: priority, + scope: noScope ? undefined : angularJsScope, + compile: function angularJsAdapterCompile() { + return { + post: function angularJsAdapterLink(ngScope, ngElement, ngAttrs, ngController) { + var transcludeClone = transclude ? ngElement.find("[ng-transclude][counter=".concat(currentTranscludeCounter, "]")) : null; // build the root vue template + + var rootVueTemplate = '<root-component'; + Object.entries(events).forEach(function (info) { + var _info = createAngularJsAdapter_slicedToArray(info, 1), + eventName = _info[0]; + + rootVueTemplate += " @".concat(toKebabCase(eventName), "=\"onEventHandler('").concat(eventName, "', $event)\""); + }); + Object.entries(scope).forEach(function (_ref3) { + var _ref4 = createAngularJsAdapter_slicedToArray(_ref3, 2), + info = _ref4[1]; + + if (info.angularJsBind === '&' || info.angularJsBind === '&?') { + var eventName = toKebabCase(info.vue); + + if (!events[info.vue]) { + // pass through scope & w/o a custom event handler + rootVueTemplate += " @".concat(eventName, "=\"onEventHandler('").concat(info.vue, "', $event)\""); + } + } else { + rootVueTemplate += " :".concat(toKebabCase(info.vue), "=\"").concat(info.vue, "\""); + } + }); + rootVueTemplate += '>'; + + if (transclude) { + rootVueTemplate += '<div ref="transcludeTarget"/>'; + } + + rootVueTemplate += '</root-component>'; // build the vue app + + var app = createVueApp({ + template: rootVueTemplate, + data: function data() { + var _this = this; + + var initialData = {}; + Object.entries(scope).forEach(function (_ref5) { + var _ref6 = createAngularJsAdapter_slicedToArray(_ref5, 2), + scopeVarName = _ref6[0], + info = _ref6[1]; + + var value = removeAngularJsSpecificProperties(ngScope[scopeVarName]); + + if (typeof value === 'undefined' && typeof info.default !== 'undefined') { + value = info.default instanceof Function ? info.default.apply(info, [ngScope, ngElement, ngAttrs].concat(injectedServices)) : info.default; + } + + if (info.transform) { + value = info.transform.apply(info, [value, _this, ngScope, ngElement, ngAttrs, ngController].concat(injectedServices)); + } + + initialData[info.vue] = value; + }); + return initialData; + }, + setup: function setup() { + if (transclude) { + var transcludeTarget = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(null); + return { + transcludeTarget: transcludeTarget + }; + } + + return undefined; + }, + methods: { + onEventHandler: function onEventHandler(name, $event) { + var scopePropertyName = toAngularJsCamelCase(name); + scopePropertyName = vueToAngular[scopePropertyName] || scopePropertyName; + + if (ngScope[scopePropertyName]) { + ngScope[scopePropertyName]($event); + } + + if (events[name]) { + events[name].apply(events, [$event, this, ngScope, ngElement, ngAttrs, ngController].concat(injectedServices)); + } + } + } + }); + app.component('root-component', component); // mount the app + + var mountPoint = mountPointFactory ? mountPointFactory.apply(void 0, [ngScope, ngElement, ngAttrs].concat(injectedServices)) : ngElement[0]; + var vm = app.mount(mountPoint); // setup watches to bind between angularjs + vue + + Object.entries(scope).forEach(function (_ref7) { + var _ref8 = createAngularJsAdapter_slicedToArray(_ref7, 2), + scopeVarName = _ref8[0], + info = _ref8[1]; + + if (!info.angularJsBind || info.angularJsBind === '&' || info.angularJsBind === '&?') { + return; + } + + ngScope.$watch(scopeVarName, function (newValue, oldValue) { + if (newValue === oldValue && JSON.stringify(vm[info.vue]) === JSON.stringify(newValue)) { + return; // initial + } + + var newValueFinal = removeAngularJsSpecificProperties(newValue); + + if (typeof info.default !== 'undefined' && typeof newValue === 'undefined') { + newValueFinal = info.default instanceof Function ? info.default.apply(info, [ngScope, ngElement, ngAttrs].concat(injectedServices)) : info.default; + } + + if (info.transform) { + newValueFinal = info.transform.apply(info, [newValueFinal, vm, ngScope, ngElement, ngAttrs, ngController].concat(injectedServices)); + } + + vm[info.vue] = newValueFinal; + }, info.deepWatch); + }); + + if (transclude && transcludeClone) { + $(vm.transcludeTarget).append(transcludeClone); + } + + if (postCreate) { + postCreate.apply(void 0, [vm, ngScope, ngElement, ngAttrs, ngController].concat(injectedServices)); + } // specifying replace: true on the directive does nothing w/ vue inside, so + // handle it here. + + + if (replace) { + // transfer attributes from angularjs element that are not in scope to + // mount point element + Array.from(ngElement[0].attributes).forEach(function (attr) { + if (scope[attr.nodeName]) { + return; + } + + if (mountPoint.firstElementChild) { + mountPoint.firstElementChild.setAttribute(attr.nodeName, attr.nodeValue); + } + }); + ngElement.replaceWith(window.$(mountPoint).children()); + } + + ngElement.on('$destroy', function () { + app.unmount(); + }); + } + }; + } + }; + + if (transclude) { + adapter.transclude = true; + adapter.template = "<div ng-transclude counter=\"".concat(currentTranscludeCounter, "\"/>"); + } + + return adapter; + } + + angularJsAdapter.$inject = $inject || []; + window.angular.module('piwikApp').directive(directiveName, angularJsAdapter); + return angularJsAdapter; +} +function transformAngularJsBoolAttr(v) { + if (typeof v === 'undefined') { + return undefined; + } + + if (v === 'true') { + return true; + } + + return !!v && v > 0 && v !== '0'; +} +function transformAngularJsIntAttr(v) { + if (typeof v === 'undefined') { + return undefined; + } + + if (v === null) { + return null; + } + + return parseInt(v, 10); +} // utility function for service adapters + +function clone(p) { + if (typeof p === 'undefined') { + return p; + } + + return JSON.parse(JSON.stringify(p)); +} +function cloneThenApply(p) { + var result = clone(p); + Matomo_Matomo.helper.getAngularDependency('$rootScope').$applyAsync(); + return result; +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Alert/Alert.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var Alert_adapter = (createAngularJsAdapter({ + component: Alert, + scope: { + severity: { + vue: 'severity', + angularJsBind: '@piwikAlert' + } + }, + directiveName: 'piwikAlert', + transclude: true +})); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.ts /*! * Matomo - free/libre analytics platform @@ -1894,6 +2681,7 @@ angular.module('piwikApp.service').service('globalAjaxQueue', ajaxQueue); * </li> * </ul> */ + /* harmony default export */ var DropdownMenu = ({ mounted: function mounted(element, binding) { var options = {}; @@ -1901,16 +2689,26 @@ angular.module('piwikApp.service').service('globalAjaxQueue', ajaxQueue); var isSubmenu = !!$(element).parent().closest('.dropdown-content').length; if (isSubmenu) { + var _binding$value; + options = { hover: true }; $(element).addClass('submenu'); - $(binding.value.activates).addClass('submenu-dropdown-content'); // if a submenu is used, the dropdown will never scroll + $(((_binding$value = binding.value) === null || _binding$value === void 0 ? void 0 : _binding$value.activates) || $(element).data('target')).addClass('submenu-dropdown-content'); // if a submenu is used, the dropdown will never scroll $(element).parents('.dropdown-content').addClass('submenu-container'); } $(element).dropdown(options); + }, + updated: function updated(element) { + // classes can be overwritten when elements bind to :class, nextTick + using + // updated avoids this problem (and doing in both mounted and updated avoids a temporary + // state where the classes aren't added) + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () { + $(element).addClass('matomo-dropdown-menu'); + }); } }); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.adapter.ts @@ -1943,7 +2741,7 @@ function piwikDropdownMenu($timeout) { } piwikDropdownMenu.$inject = ['$timeout']; -angular.module('piwikApp').directive('piwikDropdownMenu', piwikDropdownMenu); +window.angular.module('piwikApp').directive('piwikDropdownMenu', piwikDropdownMenu); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.ts /*! * Matomo - free/libre analytics platform @@ -2062,8 +2860,7 @@ function piwikFocusAnywhereButHere() { }; } -piwikFocusAnywhereButHere.$inject = []; -angular.module('piwikApp.directive').directive('piwikFocusAnywhereButHere', piwikFocusAnywhereButHere); +window.angular.module('piwikApp.directive').directive('piwikFocusAnywhereButHere', piwikFocusAnywhereButHere); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusIf/FocusIf.ts /*! * Matomo - free/libre analytics platform @@ -2129,7 +2926,23 @@ function piwikFocusIf() { }; } -angular.module('piwikApp.directive').directive('piwikFocusIf', piwikFocusIf); +window.angular.module('piwikApp.directive').directive('piwikFocusIf', piwikFocusIf); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/directiveUtilities.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function getRef(expander, binding) { + var _binding$instance; + + return expander instanceof HTMLElement ? expander : (_binding$instance = binding.instance) === null || _binding$instance === void 0 ? void 0 : _binding$instance.$refs[expander]; +} + +/* harmony default export */ var directiveUtilities = ({ + getRef: getRef +}); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.ts /*! * Matomo - free/libre analytics platform @@ -2139,6 +2952,7 @@ angular.module('piwikApp.directive').directive('piwikFocusIf', piwikFocusIf); */ + function onExpand(element) { element.classList.toggle('expanded'); var positionElement = element.querySelector('.dropdown.positionInViewport'); @@ -2180,6 +2994,8 @@ function ExpandOnClick_onEscapeHandler(element, binding, event) { } var ExpandOnClick_doc = document.documentElement; +var ExpandOnClick_window = window, + ExpandOnClick_$ = ExpandOnClick_window.$; /** * Usage (in a component): * @@ -2198,14 +3014,25 @@ var ExpandOnClick_doc = document.documentElement; binding.value.onMouseDown = ExpandOnClick_onMouseDown.bind(null, binding); binding.value.onClickOutsideElement = ExpandOnClick_onClickOutsideElement.bind(null, el, binding); binding.value.onScroll = ExpandOnClick_onScroll.bind(null, binding); - binding.value.expander.addEventListener('click', binding.value.onExpand); + setTimeout(function () { + var expander = directiveUtilities.getRef(binding.value.expander, binding); + + if (expander) { + ExpandOnClick_$(expander).on('click', binding.value.onExpand); + } + }); ExpandOnClick_doc.addEventListener('keyup', binding.value.onEscapeHandler); ExpandOnClick_doc.addEventListener('mousedown', binding.value.onMouseDown); ExpandOnClick_doc.addEventListener('mouseup', binding.value.onClickOutsideElement); ExpandOnClick_doc.addEventListener('scroll', binding.value.onScroll); }, unmounted: function unmounted(el, binding) { - binding.value.expander.removeEventListener('click', binding.value.onExpand); + var expander = directiveUtilities.getRef(binding.value.expander, binding); + + if (expander) { + ExpandOnClick_$(expander).off('click', binding.value.onExpand); + } + ExpandOnClick_doc.removeEventListener('keyup', binding.value.onEscapeHandler); ExpandOnClick_doc.removeEventListener('mousedown', binding.value.onMouseDown); ExpandOnClick_doc.removeEventListener('mouseup', binding.value.onClickOutsideElement); @@ -2240,8 +3067,7 @@ function piwikExpandOnClick() { } }; } -piwikExpandOnClick.$inject = []; -angular.module('piwikApp').directive('piwikExpandOnClick', piwikExpandOnClick); +window.angular.module('piwikApp').directive('piwikExpandOnClick', piwikExpandOnClick); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.ts /*! * Matomo - free/libre analytics platform @@ -2251,6 +3077,7 @@ angular.module('piwikApp').directive('piwikExpandOnClick', piwikExpandOnClick); */ + function onMouseEnter(element) { element.classList.add('expanded'); var positionElement = element.querySelector('.dropdown.positionInViewport'); @@ -2292,13 +3119,24 @@ var ExpandOnHover_doc = document.documentElement; binding.value.onMouseLeave = onMouseLeave.bind(null, el); binding.value.onClickOutsideElement = ExpandOnHover_onClickOutsideElement.bind(null, el); binding.value.onEscapeHandler = ExpandOnHover_onEscapeHandler.bind(null, el); - binding.value.expander.addEventListener('mouseenter', binding.value.onMouseEnter); + setTimeout(function () { + var expander = directiveUtilities.getRef(binding.value.expander, binding); + + if (expander) { + expander.addEventListener('mouseenter', binding.value.onMouseEnter); + } + }); el.addEventListener('mouseleave', binding.value.onMouseLeave); ExpandOnHover_doc.addEventListener('keyup', binding.value.onEscapeHandler); ExpandOnHover_doc.addEventListener('mouseup', binding.value.onClickOutsideElement); }, unmounted: function unmounted(el, binding) { - binding.value.expander.removeEventListener('mouseenter', binding.value.onMouseEnter); + var expander = directiveUtilities.getRef(binding.value.expander, binding); + + if (expander) { + expander.removeEventListener('mouseenter', binding.value.onMouseEnter); + } + el.removeEventListener('mouseleave', binding.value.onMouseLeave); document.removeEventListener('keyup', binding.value.onEscapeHandler); document.removeEventListener('mouseup', binding.value.onClickOutsideElement); @@ -2334,19 +3172,311 @@ function piwikExpandOnHover() { }; } -piwikExpandOnHover.$inject = []; -angular.module('piwikApp').directive('piwikExpandOnHover', piwikExpandOnHover); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=template&id=7aba656e +window.angular.module('piwikApp').directive('piwikExpandOnHover', piwikExpandOnHover); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +var ShowSensitiveData_window = window, + ShowSensitiveData_$ = ShowSensitiveData_window.$; +/** + * Handles visibility of sensitive data. By default data will be shown replaced with stars (*) + * On click on the element the full data will be shown + * + * Configuration attributes: + * data-show-characters number of characters to show in clear text (defaults to 6) + * data-click-element-selector selector for element that will show the full data on click + * (defaults to element) + * + * Example: + * <div v-show-sensitive-date="some text"></div> + */ + +/* harmony default export */ var ShowSensitiveData = ({ + mounted: function mounted(el, binding) { + var element = ShowSensitiveData_$(el); + var sensitiveData = binding.value.sensitiveData; + var showCharacters = binding.value.showCharacters || 6; + var clickElement = binding.value.clickElementSelector || element; + var protectedData = ''; + + if (showCharacters > 0) { + protectedData += sensitiveData.slice(0, showCharacters); + } + + protectedData += sensitiveData.slice(showCharacters).replace(/./g, '*'); + element.html(protectedData); + + function onClickHandler() { + element.html(sensitiveData); + ShowSensitiveData_$(clickElement).css({ + cursor: '' + }); + ShowSensitiveData_$(clickElement).tooltip('destroy'); + } + + ShowSensitiveData_$(clickElement).tooltip({ + content: translate('CoreHome_ClickToSeeFullInformation'), + items: '*', + track: true + }); + ShowSensitiveData_$(clickElement).one('click', onClickHandler); + ShowSensitiveData_$(clickElement).css({ + cursor: 'pointer' + }); + } +}); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +function piwikShowSensitiveData() { + return { + restrict: 'A', + link: function piwikShowSensitiveDataLink(scope, element, attr) { + var binding = { + instance: null, + value: { + sensitiveData: attr.piwikShowSensitiveData || (attr.text ? attr.text() : ''), + showCharacters: attr.showCharacters ? parseInt(attr.showCharacters, 10) : undefined, + clickElementSelector: attr.clickElementSelector + }, + oldValue: null, + modifiers: {}, + dir: {} + }; + ShowSensitiveData.mounted(element[0], binding); + } + }; +} +window.angular.module('piwikApp').directive('piwikShowSensitiveData', piwikShowSensitiveData); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DropdownButton/DropdownButton.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +var DropdownButton_window = window, + DropdownButton_$ = DropdownButton_window.$; +/* harmony default export */ var DropdownButton = ({ + mounted: function mounted(el) { + var element = DropdownButton_$(el); // BC for materializecss 0.97 => 1.0 + + if (!element.attr('data-target') && element.attr('data-activates')) { + element.attr('data-target', element.attr('data-activates')); + } + + var target = element.attr('data-target'); + + if (target && DropdownButton_$("#".concat(target)).length) { + element.dropdown({ + inDuration: 300, + outDuration: 225, + constrainWidth: false, + // hover: true, // Activate on hover + belowOrigin: true // Displays dropdown below the button + + }); + } + } +}); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DropdownButton/DropdownButton.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +function piwikDropdownButton() { + return { + restrict: 'C', + link: function piwikDropdownButtonLink(scope, element) { + DropdownButton.mounted(element[0]); + } + }; +} +window.angular.module('piwikApp').directive('dropdownButton', piwikDropdownButton); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function onFocusHandler(binding, event) { + if (binding.value.focusedElement !== event.target) { + binding.value.focusedElement = event.target; + window.angular.element(event.target).select(); + } +} + +function SelectOnFocus_onClickHandler(event) { + // .select() + focus and blur seems to not work on pre elements + var range = document.createRange(); + range.selectNode(event.target); + var selection = window.getSelection(); + + if (selection && selection.rangeCount > 0) { + selection.removeAllRanges(); + } + + if (selection) { + selection.addRange(range); + } +} + +function onBlurHandler(binding) { + delete binding.value.focusedElement; +} + +/* harmony default export */ var SelectOnFocus = ({ + mounted: function mounted(el, binding) { + var tagName = el.tagName.toLowerCase(); + binding.value.elementSupportsSelect = tagName === 'textarea'; + + if (binding.value.elementSupportsSelect) { + binding.value.onFocusHandler = onFocusHandler.bind(null, binding); + binding.value.onBlurHandler = onBlurHandler.bind(null, binding); + el.addEventListener('focus', binding.value.onFocusHandler); + el.addEventListener('blur', binding.value.onBlurHandler); + } else { + binding.value.onClickHandler = SelectOnFocus_onClickHandler; + el.addEventListener('click', binding.value.onClickHandler); + } + }, + unmounted: function unmounted(el, binding) { + if (binding.value.elementSupportsSelect) { + el.removeEventListener('focus', binding.value.onFocusHandler); + el.removeEventListener('blur', binding.value.onBlurHandler); + } else { + el.removeEventListener('click', binding.value.onClickHandler); + } + } +}); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +function piwikSelectOnFocus() { + return { + restrict: 'A', + link: function piwikSelectOnFocusLink(scope, element) { + var binding = { + instance: null, + value: {}, + oldValue: null, + modifiers: {}, + dir: {} + }; + SelectOnFocus.mounted(element[0], binding); + element.on('$destroy', function () { + return SelectOnFocus.unmounted(element[0], binding); + }); + } + }; +} +window.angular.module('piwikApp').directive('piwikSelectOnFocus', piwikSelectOnFocus); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SideNav/SideNav.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +var initialized = false; +/** + * Will activate the materialize side nav feature once rendered. We use this directive as + * it makes sure the actual left menu is rendered at the time we init the side nav. + * + * Has to be set on a collaapsible element + * + * Example: + * <div class="collapsible" v-side-nav="nav .activateLeftMenu">...</div> + */ + +/* harmony default export */ var SideNav = ({ + mounted: function mounted(el, binding) { + if (!binding.value.activator) { + return; + } + + setTimeout(function () { + if (!initialized) { + initialized = true; + var sideNavActivator = directiveUtilities.getRef(binding.value.activator, binding); + + if (sideNavActivator) { + window.$(sideNavActivator).show(); + var targetSelector = sideNavActivator.getAttribute('data-target'); // @ts-ignore + + window.$("#".concat(targetSelector)).sidenav({ + closeOnClick: true + }); + } + } + + if (el.classList.contains('collapsible')) { + window.$(el).collapsible(); + } + }); + } +}); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SideNav/SideNav.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +function piwikSideNav($timeout) { + return { + restrict: 'A', + priority: 10, + link: function linkPiwikSideNav(scope, element, attr) { + var binding = { + instance: null, + value: { + activator: $(attr.piwikSideNav)[0] + }, + oldValue: null, + modifiers: {}, + dir: {} + }; + $timeout(function () { + SideNav.mounted(element[0], binding); + }); + } + }; +} +piwikSideNav.$inject = ['$timeout']; +window.angular.module('piwikApp.directive').directive('piwikSideNav', piwikSideNav); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=template&id=00aba563 var _hoisted_1 = { ref: "root" }; -function MatomoDialogvue_type_template_id_7aba656e_render(_ctx, _cache, $props, $setup, $data, $options) { +function MatomoDialogvue_type_template_id_00aba563_render(_ctx, _cache, $props, $setup, $data, $options) { return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")], 512)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.modelValue]]); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=template&id=7aba656e +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=template&id=00aba563 -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=script&lang=ts /* harmony default export */ var MatomoDialogvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ @@ -2371,7 +3501,7 @@ function MatomoDialogvue_type_template_id_7aba656e_render(_ctx, _cache, $props, required: false } }, - emits: ['yes', 'no', 'closeEnd', 'close', 'update:modelValue'], + emits: ['yes', 'no', 'closeEnd', 'close', 'validation', 'update:modelValue'], activated: function activated() { this.$emit('update:modelValue', false); }, @@ -2416,229 +3546,9 @@ function MatomoDialogvue_type_template_id_7aba656e_render(_ctx, _cache, $props, -MatomoDialogvue_type_script_lang_ts.render = MatomoDialogvue_type_template_id_7aba656e_render +MatomoDialogvue_type_script_lang_ts.render = MatomoDialogvue_type_template_id_00aba563_render /* harmony default export */ var MatomoDialog = (MatomoDialogvue_type_script_lang_ts); -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/createAngularJsAdapter.ts -function createAngularJsAdapter_slicedToArray(arr, i) { return createAngularJsAdapter_arrayWithHoles(arr) || createAngularJsAdapter_iterableToArrayLimit(arr, i) || createAngularJsAdapter_unsupportedIterableToArray(arr, i) || createAngularJsAdapter_nonIterableRest(); } - -function createAngularJsAdapter_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } - -function createAngularJsAdapter_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return createAngularJsAdapter_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return createAngularJsAdapter_arrayLikeToArray(o, minLen); } - -function createAngularJsAdapter_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } - -function createAngularJsAdapter_iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } - -function createAngularJsAdapter_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } - -/*! - * Matomo - free/libre analytics platform - * - * @link https://matomo.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ - - -var transcludeCounter = 0; - -function toKebabCase(arg) { - return arg.substring(0, 1).toLowerCase() + arg.substring(1).replace(/[A-Z]/g, function (s) { - return "-".concat(s.toLowerCase()); - }); -} - -function toAngularJsCamelCase(arg) { - return arg.substring(0, 1).toLowerCase() + arg.substring(1).replace(/-([a-z])/g, function (s, p) { - return p.toUpperCase(); - }); -} - -function createAngularJsAdapter(options) { - var component = options.component, - _options$scope = options.scope, - scope = _options$scope === void 0 ? {} : _options$scope, - _options$events = options.events, - events = _options$events === void 0 ? {} : _options$events, - $inject = options.$inject, - directiveName = options.directiveName, - transclude = options.transclude, - mountPointFactory = options.mountPointFactory, - postCreate = options.postCreate, - noScope = options.noScope, - _options$restrict = options.restrict, - restrict = _options$restrict === void 0 ? 'A' : _options$restrict; - var currentTranscludeCounter = transcludeCounter; - - if (transclude) { - transcludeCounter += 1; - } - - var angularJsScope = {}; - Object.entries(scope).forEach(function (_ref) { - var _ref2 = createAngularJsAdapter_slicedToArray(_ref, 2), - scopeVarName = _ref2[0], - info = _ref2[1]; - - if (!info.vue) { - info.vue = scopeVarName; - } - - if (info.angularJsBind) { - angularJsScope[scopeVarName] = info.angularJsBind; - } - }); - - function angularJsAdapter() { - for (var _len = arguments.length, injectedServices = new Array(_len), _key = 0; _key < _len; _key++) { - injectedServices[_key] = arguments[_key]; - } - - var adapter = { - restrict: restrict, - scope: noScope ? undefined : angularJsScope, - compile: function angularJsAdapterCompile() { - return { - post: function angularJsAdapterLink(ngScope, ngElement, ngAttrs) { - var clone = transclude ? ngElement.find("[ng-transclude][counter=".concat(currentTranscludeCounter, "]")) : null; // build the root vue template - - var rootVueTemplate = '<root-component'; - Object.entries(events).forEach(function (info) { - var _info = createAngularJsAdapter_slicedToArray(info, 1), - eventName = _info[0]; - - rootVueTemplate += " @".concat(eventName, "=\"onEventHandler('").concat(eventName, "', $event)\""); - }); - Object.entries(scope).forEach(function (_ref3) { - var _ref4 = createAngularJsAdapter_slicedToArray(_ref3, 2), - key = _ref4[0], - info = _ref4[1]; - - if (info.angularJsBind === '&') { - var eventName = toKebabCase(key); - - if (!events[eventName]) { - // pass through scope & w/o a custom event handler - rootVueTemplate += " @".concat(eventName, "=\"onEventHandler('").concat(eventName, "', $event)\""); - } - } else { - rootVueTemplate += " :".concat(info.vue, "=\"").concat(info.vue, "\""); - } - }); - rootVueTemplate += '>'; - - if (transclude) { - rootVueTemplate += '<div ref="transcludeTarget"/>'; - } - - rootVueTemplate += '</root-component>'; // build the vue app - - var app = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createApp"])({ - template: rootVueTemplate, - data: function data() { - var initialData = {}; - Object.entries(scope).forEach(function (_ref5) { - var _ref6 = createAngularJsAdapter_slicedToArray(_ref5, 2), - scopeVarName = _ref6[0], - info = _ref6[1]; - - var value = ngScope[scopeVarName]; - - if (typeof value === 'undefined' && typeof info.default !== 'undefined') { - value = info.default instanceof Function ? info.default.apply(info, [ngScope, ngElement, ngAttrs].concat(injectedServices)) : info.default; - } - - if (info.transform) { - value = info.transform(value); - } - - initialData[info.vue] = value; - }); - return initialData; - }, - setup: function setup() { - if (transclude) { - var transcludeTarget = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(null); - return { - transcludeTarget: transcludeTarget - }; - } - - return undefined; - }, - methods: { - onEventHandler: function onEventHandler(name, $event) { - var scopePropertyName = toAngularJsCamelCase(name); - - if (ngScope[scopePropertyName]) { - ngScope[scopePropertyName]($event); - } - - if (events[name]) { - events[name].apply(events, [$event, ngScope, ngElement, ngAttrs].concat(injectedServices)); - } - } - } - }); - app.config.globalProperties.$sanitize = window.vueSanitize; - app.config.globalProperties.translate = translate; - app.component('root-component', component); // mount the app - - var mountPoint = mountPointFactory ? mountPointFactory.apply(void 0, [ngScope, ngElement, ngAttrs].concat(injectedServices)) : ngElement[0]; - var vm = app.mount(mountPoint); // setup watches to bind between angularjs + vue - - Object.entries(scope).forEach(function (_ref7) { - var _ref8 = createAngularJsAdapter_slicedToArray(_ref7, 2), - scopeVarName = _ref8[0], - info = _ref8[1]; - - if (!info.angularJsBind || info.angularJsBind === '&') { - return; - } - - ngScope.$watch(scopeVarName, function (newValue) { - var newValueFinal = newValue; - - if (typeof info.default !== 'undefined' && typeof newValue === 'undefined') { - newValueFinal = info.default instanceof Function ? info.default.apply(info, [ngScope, ngElement, ngAttrs].concat(injectedServices)) : info.default; - } - - if (info.transform) { - newValueFinal = info.transform(newValueFinal); - } - - vm[scopeVarName] = newValueFinal; - }); - }); - - if (transclude) { - $(vm.transcludeTarget).append(clone); - } - - if (postCreate) { - postCreate.apply(void 0, [vm, ngScope, ngElement, ngAttrs].concat(injectedServices)); - } - - ngElement.on('$destroy', function () { - app.unmount(); - }); - } - }; - } - }; - - if (transclude) { - adapter.transclude = true; - adapter.template = "<div ng-transclude counter=\"".concat(currentTranscludeCounter, "\"/>"); - } - - return adapter; - } - - angularJsAdapter.$inject = $inject || []; - angular.module('piwikApp').directive(directiveName, angularJsAdapter); - return angularJsAdapter; -} // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts /*! * Matomo - free/libre analytics platform @@ -2662,7 +3572,7 @@ function createAngularJsAdapter(options) { } }, events: { - yes: function yes($event, scope, element, attrs) { + yes: function yes($event, vm, scope, element, attrs) { if (attrs.yes) { scope.$eval(attrs.yes); setTimeout(function () { @@ -2670,7 +3580,7 @@ function createAngularJsAdapter(options) { }, 0); } }, - no: function no($event, scope, element, attrs) { + no: function no($event, vm, scope, element, attrs) { if (attrs.no) { scope.$eval(attrs.no); setTimeout(function () { @@ -2678,7 +3588,7 @@ function createAngularJsAdapter(options) { }, 0); } }, - validation: function validation($event, scope, element, attrs) { + validation: function validation($event, vm, scope, element, attrs) { if (attrs.no) { scope.$eval(attrs.no); setTimeout(function () { @@ -2686,7 +3596,7 @@ function createAngularJsAdapter(options) { }, 0); } }, - close: function close($event, scope, element, attrs) { + close: function close($event, vm, scope, element, attrs) { if (attrs.close) { scope.$eval(attrs.close); setTimeout(function () { @@ -2694,7 +3604,7 @@ function createAngularJsAdapter(options) { }, 0); } }, - 'update:modelValue': function updateModelValue(newValue, scope, element, attrs, $parse) { + 'update:modelValue': function updateModelValue(newValue, vm, scope, element, attrs, controller, $parse) { setTimeout(function () { scope.$apply($parse(attrs.piwikDialog).assign(scope, newValue)); }, 0); @@ -2717,9 +3627,9 @@ function createAngularJsAdapter(options) { }, noScope: true })); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue?vue&type=template&id=5653b0bd +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue?vue&type=template&id=7b85675d -var EnrichedHeadlinevue_type_template_id_5653b0bd_hoisted_1 = { +var EnrichedHeadlinevue_type_template_id_7b85675d_hoisted_1 = { key: 0, class: "title", tabindex: "6" @@ -2749,8 +3659,9 @@ var _hoisted_11 = { class: "inlineHelp" }; var _hoisted_12 = ["innerHTML"]; -var _hoisted_13 = ["href"]; -function EnrichedHeadlinevue_type_template_id_5653b0bd_render(_ctx, _cache, $props, $setup, $data, $options) { +var _hoisted_13 = ["innerHTML"]; +var _hoisted_14 = ["href"]; +function EnrichedHeadlinevue_type_template_id_7b85675d_render(_ctx, _cache, $props, $setup, $data, $options) { var _component_RateFeature = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("RateFeature"); return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { @@ -2762,7 +3673,7 @@ function EnrichedHeadlinevue_type_template_id_5653b0bd_render(_ctx, _cache, $pro return _ctx.showIcons = false; }), ref: "root" - }, [!_ctx.editUrl ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", EnrichedHeadlinevue_type_template_id_5653b0bd_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.editUrl ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { + }, [!_ctx.editUrl ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", EnrichedHeadlinevue_type_template_id_7b85675d_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.editUrl ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { key: 1, class: "title", href: _ctx.editUrl, @@ -2787,32 +3698,54 @@ function EnrichedHeadlinevue_type_template_id_5653b0bd_render(_ctx, _cache, $pro title: _ctx.actualFeatureName }, null, 8, ["title"])])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showIcons || _ctx.showInlineHelp]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_11, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { innerHTML: _ctx.$sanitize(_ctx.actualInlineHelp) - }, null, 8, _hoisted_12), _ctx.helpUrl ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { + }, null, 8, _hoisted_12), _ctx.reportGenerated != '' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", { key: 0, + class: "helpDate", + innerHTML: _ctx.$sanitize(_ctx.reportGenerated) + }, null, 8, _hoisted_13)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.helpUrl ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { + key: 1, rel: "noreferrer noopener", target: "_blank", class: "readMore", href: _ctx.helpUrl - }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_MoreDetails')), 9, _hoisted_13)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showInlineHelp]])], 544); + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_MoreDetails')), 9, _hoisted_14)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showInlineHelp]])], 544); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue?vue&type=template&id=5653b0bd +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue?vue&type=template&id=7b85675d -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/useExternalPluginComponent.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +/* eslint-disable @typescript-eslint/no-explicit-any */ - // working around a cycle in dependencies (CoreHome depends on Feedback, Feedback depends on -// CoreHome) -// TODO: may need a generic solution at some point, but it's bad practice to have -// cyclic dependencies like this. it worked before because it was individual files -// dependening on each other, not whole plugins. - -var RateFeature = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineAsyncComponent"])(function () { - return new Promise(function (resolve) { - window.$(document).ready(function () { - resolve(window.Feedback.RateFeature); // eslint-disable-line +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +function useExternalPluginComponent(plugin, component) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineAsyncComponent"])(function () { + return new Promise(function (resolve) { + window.$(document).ready(function () { + if (window[plugin]) { + resolve(window[plugin][component]); + } else { + // @ts-ignore + resolve(null); // plugin not loaded + } + }); }); }); -}); +} +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue?vue&type=script&lang=ts + + + + // working around a cycle in dependencies (CoreHome depends on Feedback, Feedback depends on +// CoreHome) + +var RateFeature = useExternalPluginComponent('Feedback', 'RateFeature'); /** * Usage: * @@ -2885,20 +3818,24 @@ var RateFeature = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineAs setTimeout(function () { if (!_this.actualInlineHelp) { + var _root$parentElement; + var helpNode = root.querySelector('.title .inlineHelp'); - if (!helpNode && root.parentElement.nextElementSibling) { + if (!helpNode && (_root$parentElement = root.parentElement) !== null && _root$parentElement !== void 0 && _root$parentElement.nextElementSibling) { // hack for reports :( helpNode = root.parentElement.nextElementSibling.querySelector('.reportDocumentation'); } if (helpNode) { + var _helpNode$getAttribut; + // hackish solution to get binded html of p tag within the help node // at this point the ng-bind-html is not yet converted into html when report is not // initially loaded. Using $compile doesn't work. So get and set it manually - var helpDocs = helpNode.getAttribute('data-content').trim(); + var helpDocs = (_helpNode$getAttribut = helpNode.getAttribute('data-content')) === null || _helpNode$getAttribut === void 0 ? void 0 : _helpNode$getAttribut.trim(); - if (helpDocs.length) { + if (helpDocs && helpDocs.length) { _this.actualInlineHelp = "<p>".concat(helpDocs, "</p>"); setTimeout(function () { return helpNode.remove(); @@ -2908,17 +3845,23 @@ var RateFeature = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineAs } if (!_this.actualFeatureName) { - _this.actualFeatureName = root.querySelector('.title').textContent; + var _root$querySelector; + + _this.actualFeatureName = (_root$querySelector = root.querySelector('.title')) === null || _root$querySelector === void 0 ? void 0 : _root$querySelector.textContent; } - if (_this.reportGenerated && Periods_Periods.parse(Matomo_Matomo.period, Matomo_Matomo.currentDateString).containsToday()) { - window.$(root.querySelector('.report-generated')).tooltip({ - track: true, - content: _this.reportGenerated, - items: 'div', - show: false, - hide: false - }); + if (Matomo_Matomo.period && Matomo_Matomo.currentDateString) { + var currentPeriod = Periods_Periods.parse(Matomo_Matomo.period, Matomo_Matomo.currentDateString); + + if (_this.reportGenerated && currentPeriod.containsToday()) { + window.$(root.querySelector('.report-generated')).tooltip({ + track: true, + content: _this.reportGenerated, + items: 'div', + show: false, + hide: false + }); + } } }); } @@ -2929,7 +3872,7 @@ var RateFeature = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineAs -EnrichedHeadlinevue_type_script_lang_ts.render = EnrichedHeadlinevue_type_template_id_5653b0bd_render +EnrichedHeadlinevue_type_script_lang_ts.render = EnrichedHeadlinevue_type_template_id_7b85675d_render /* harmony default export */ var EnrichedHeadline = (EnrichedHeadlinevue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.adapter.ts @@ -2963,30 +3906,30 @@ EnrichedHeadlinevue_type_script_lang_ts.render = EnrichedHeadlinevue_type_templa directiveName: 'piwikEnrichedHeadline', transclude: true })); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue?vue&type=template&id=09ef9e02 +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue?vue&type=template&id=3f4d113e -var ContentBlockvue_type_template_id_09ef9e02_hoisted_1 = { +var ContentBlockvue_type_template_id_3f4d113e_hoisted_1 = { class: "card", ref: "root" }; -var ContentBlockvue_type_template_id_09ef9e02_hoisted_2 = { +var ContentBlockvue_type_template_id_3f4d113e_hoisted_2 = { class: "card-content" }; -var ContentBlockvue_type_template_id_09ef9e02_hoisted_3 = { +var ContentBlockvue_type_template_id_3f4d113e_hoisted_3 = { key: 0, class: "card-title" }; -var ContentBlockvue_type_template_id_09ef9e02_hoisted_4 = { +var ContentBlockvue_type_template_id_3f4d113e_hoisted_4 = { key: 1, class: "card-title" }; -var ContentBlockvue_type_template_id_09ef9e02_hoisted_5 = { +var ContentBlockvue_type_template_id_3f4d113e_hoisted_5 = { ref: "content" }; -function ContentBlockvue_type_template_id_09ef9e02_render(_ctx, _cache, $props, $setup, $data, $options) { +function ContentBlockvue_type_template_id_3f4d113e_render(_ctx, _cache, $props, $setup, $data, $options) { var _component_EnrichedHeadline = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("EnrichedHeadline"); - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ContentBlockvue_type_template_id_09ef9e02_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ContentBlockvue_type_template_id_09ef9e02_hoisted_2, [_ctx.contentTitle && !_ctx.actualFeature && !_ctx.helpUrl && !_ctx.actualHelpText ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("h2", ContentBlockvue_type_template_id_09ef9e02_hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.contentTitle), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.contentTitle && (_ctx.actualFeature || _ctx.helpUrl || _ctx.actualHelpText) ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("h2", ContentBlockvue_type_template_id_09ef9e02_hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_EnrichedHeadline, { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ContentBlockvue_type_template_id_3f4d113e_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ContentBlockvue_type_template_id_3f4d113e_hoisted_2, [_ctx.contentTitle && !_ctx.actualFeature && !_ctx.helpUrl && !_ctx.actualHelpText ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("h2", ContentBlockvue_type_template_id_3f4d113e_hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.contentTitle), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.contentTitle && (_ctx.actualFeature || _ctx.helpUrl || _ctx.actualHelpText) ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("h2", ContentBlockvue_type_template_id_3f4d113e_hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_EnrichedHeadline, { "feature-name": _ctx.actualFeature, "help-url": _ctx.helpUrl, "inline-help": _ctx.actualHelpText @@ -2995,14 +3938,16 @@ function ContentBlockvue_type_template_id_09ef9e02_render(_ctx, _cache, $props, return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.contentTitle), 1)]; }), _: 1 - }, 8, ["feature-name", "help-url", "inline-help"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ContentBlockvue_type_template_id_09ef9e02_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")], 512)])], 512); + }, 8, ["feature-name", "help-url", "inline-help"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ContentBlockvue_type_template_id_3f4d113e_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")], 512)])], 512); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue?vue&type=template&id=09ef9e02 +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue?vue&type=template&id=3f4d113e -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue?vue&type=script&lang=ts var adminContent = null; +var ContentBlockvue_type_script_lang_ts_window = window, + ContentBlockvue_type_script_lang_ts_$ = ContentBlockvue_type_script_lang_ts_window.$; /* harmony default export */ var ContentBlockvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ props: { contentTitle: String, @@ -3031,14 +3976,13 @@ var adminContent = null; mounted: function mounted() { var _this = this; - var _this$$refs = this.$refs, - root = _this$$refs.root, - content = _this$$refs.content; + var root = this.$refs.root; + var content = this.$refs.content; - if (this.anchor) { + if (this.anchor && root && root.parentElement) { var anchorElement = document.createElement('a'); anchorElement.id = this.anchor; - root.parentElement.prepend(anchorElement); + ContentBlockvue_type_script_lang_ts_$(root.parentElement).prepend(anchorElement); } setTimeout(function () { @@ -3050,7 +3994,7 @@ var adminContent = null; } }, 0); - if (this.actualFeature && (this.actualFeature === true || this.actualFeature === 'true')) { + if (this.actualFeature && this.actualFeature === 'true') { this.actualFeature = this.contentTitle; } @@ -3059,7 +4003,7 @@ var adminContent = null; adminContent = document.querySelector('#content.admin'); } - var contentTopPosition; + var contentTopPosition = null; if (adminContent) { contentTopPosition = adminContent.offsetTop; @@ -3075,7 +4019,7 @@ var adminContent = null; if (topThis - contentTopPosition < 17) { // we make sure to display the first card with no margin-top to have it on same as line as // navigation - root.style.marginTop = 0; + root.style.marginTop = '0'; } } } @@ -3086,7 +4030,7 @@ var adminContent = null; -ContentBlockvue_type_script_lang_ts.render = ContentBlockvue_type_template_id_09ef9e02_render +ContentBlockvue_type_script_lang_ts.render = ContentBlockvue_type_template_id_3f4d113e_render /* harmony default export */ var ContentBlock = (ContentBlockvue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.adapter.ts @@ -3186,10 +4130,6 @@ function Comparisons_store_arrayWithoutHoles(arr) { if (Array.isArray(arr)) retu function Comparisons_store_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } -function Comparisons_store_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } - -function Comparisons_store_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { Comparisons_store_ownKeys(Object(source), true).forEach(function (key) { Comparisons_store_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { Comparisons_store_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } - function Comparisons_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function Comparisons_store_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } @@ -3219,7 +4159,7 @@ function wrapArray(values) { return []; } - return values instanceof Array ? values : [values]; + return Array.isArray(values) ? values : [values]; } var Comparisons_store_ComparisonsStore = /*#__PURE__*/function () { @@ -3353,7 +4293,7 @@ var Comparisons_store_ComparisonsStore = /*#__PURE__*/function () { _this2.getSegmentComparisons().forEach(function (segmentComp) { seriesInfo.push({ index: seriesIndex, - params: Comparisons_store_objectSpread(Comparisons_store_objectSpread({}, segmentComp.params), periodComp.params), + params: Object.assign(Object.assign({}, segmentComp.params), periodComp.params), color: _this2.colors["series".concat(seriesIndex)] }); seriesIndex += 1; @@ -3429,33 +4369,8 @@ var Comparisons_store_ComparisonsStore = /*#__PURE__*/function () { compareDates: compareDates }; // change the page w/ these new param values - if (Matomo_Matomo.helper.isAngularRenderingThePage()) { - var search = src_MatomoUrl_MatomoUrl.hashParsed.value; - - var newSearch = Comparisons_store_objectSpread(Comparisons_store_objectSpread(Comparisons_store_objectSpread({}, search), compareParams), extraParams); - - delete newSearch['compareSegments[]']; - delete newSearch['comparePeriods[]']; - delete newSearch['compareDates[]']; - - if (JSON.stringify(newSearch) !== JSON.stringify(search)) { - src_MatomoUrl_MatomoUrl.updateHash(newSearch); - } - - return; - } - - var paramsToRemove = []; - ['compareSegments', 'comparePeriods', 'compareDates'].forEach(function (name) { - if (!compareParams[name].length) { - paramsToRemove.push(name); - } - }); // angular is not rendering the page (ie, we are in the embedded dashboard) or we need to change - // the segment - - var url = src_MatomoUrl_MatomoUrl.stringify(extraParams); - var strHash = src_MatomoUrl_MatomoUrl.stringify(compareParams); - window.broadcast.propagateNewPage(url, undefined, strHash, paramsToRemove); + var baseParams = Matomo_Matomo.helper.isAngularRenderingThePage() ? src_MatomoUrl_MatomoUrl.hashParsed.value : src_MatomoUrl_MatomoUrl.urlParsed.value; + src_MatomoUrl_MatomoUrl.updateLocation(Object.assign(Object.assign(Object.assign({}, baseParams), compareParams), extraParams)); } }, { key: "getAllSeriesColors", @@ -3483,9 +4398,14 @@ var Comparisons_store_ComparisonsStore = /*#__PURE__*/function () { value: function loadComparisonsDisabledFor() { var _this3 = this; - var matomoModule = src_MatomoUrl_MatomoUrl.parsed.value.module; + var matomoModule = src_MatomoUrl_MatomoUrl.parsed.value.module; // check if body id #installation exist - if (matomoModule === 'CoreUpdater' || matomoModule === 'Installation') { + if (window.piwik.installation) { + this.privateState.comparisonsDisabledFor = []; + return; + } + + if (matomoModule === 'CoreUpdater' || matomoModule === 'Installation' || matomoModule === 'Overlay' || window.piwik.isPagesComparisonApiDisabled) { this.privateState.comparisonsDisabledFor = []; return; } @@ -3582,43 +4502,45 @@ var Comparisons_store_ComparisonsStore = /*#__PURE__*/function () { // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.store.instance.ts /* harmony default export */ var Comparisons_store_instance = (new Comparisons_store_ComparisonsStore()); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=template&id=1b8ecdd2 +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=template&id=d1a096d8 -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_1 = { +var Comparisonsvue_type_template_id_d1a096d8_hoisted_1 = { key: 0, ref: "root", class: "matomo-comparisons" }; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_2 = { +var Comparisonsvue_type_template_id_d1a096d8_hoisted_2 = { class: "comparison-type" }; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_3 = ["title"]; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_4 = ["href"]; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_5 = ["title"]; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_6 = { +var Comparisonsvue_type_template_id_d1a096d8_hoisted_3 = ["title"]; +var Comparisonsvue_type_template_id_d1a096d8_hoisted_4 = ["href"]; +var Comparisonsvue_type_template_id_d1a096d8_hoisted_5 = ["title"]; +var Comparisonsvue_type_template_id_d1a096d8_hoisted_6 = { class: "comparison-period-label" }; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_7 = ["onClick"]; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_8 = ["title"]; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_9 = { +var Comparisonsvue_type_template_id_d1a096d8_hoisted_7 = ["onClick"]; +var Comparisonsvue_type_template_id_d1a096d8_hoisted_8 = ["title"]; +var Comparisonsvue_type_template_id_d1a096d8_hoisted_9 = { class: "loadingPiwik", style: { "display": "none" } }; -var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_10 = ["alt"]; -function Comparisonsvue_type_template_id_1b8ecdd2_render(_ctx, _cache, $props, $setup, $data, $options) { - return _ctx.isComparing ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Comparisonsvue_type_template_id_1b8ecdd2_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h3", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Comparisons')), 1), (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.segmentComparisons, function (comparison, $index) { +var Comparisonsvue_type_template_id_d1a096d8_hoisted_10 = ["alt"]; +function Comparisonsvue_type_template_id_d1a096d8_render(_ctx, _cache, $props, $setup, $data, $options) { + var _directive_tooltips = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("tooltips"); + + return _ctx.isComparing ? Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Comparisonsvue_type_template_id_d1a096d8_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h3", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Comparisons')), 1), (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.segmentComparisons, function (comparison, $index) { return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { class: "comparison card", key: comparison.index - }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Comparisonsvue_type_template_id_1b8ecdd2_hoisted_2, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Segment')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Comparisonsvue_type_template_id_d1a096d8_hoisted_2, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Segment')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { class: "title", title: comparison.title + '<br/>' + decodeURIComponent(comparison.params.segment) }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { target: "_blank", href: _ctx.getUrlToSegment(comparison.params.segment) - }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(comparison.title), 9, Comparisonsvue_type_template_id_1b8ecdd2_hoisted_4)], 8, Comparisonsvue_type_template_id_1b8ecdd2_hoisted_3), (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.periodComparisons, function (periodComparison) { + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(comparison.title), 9, Comparisonsvue_type_template_id_d1a096d8_hoisted_4)], 8, Comparisonsvue_type_template_id_d1a096d8_hoisted_3), (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.periodComparisons, function (periodComparison) { return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { class: "comparison-period", key: periodComparison.index, @@ -3628,7 +4550,7 @@ function Comparisonsvue_type_template_id_1b8ecdd2_render(_ctx, _cache, $props, $ style: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeStyle"])({ 'background-color': _ctx.getSeriesColor(comparison, periodComparison) }) - }, null, 4), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", Comparisonsvue_type_template_id_1b8ecdd2_hoisted_6, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(periodComparison.title) + " (" + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.getComparisonPeriodType(periodComparison)) + ") ", 1)], 8, Comparisonsvue_type_template_id_1b8ecdd2_hoisted_5); + }, null, 4), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", Comparisonsvue_type_template_id_d1a096d8_hoisted_6, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(periodComparison.title) + " (" + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.getComparisonPeriodType(periodComparison)) + ") ", 1)], 8, Comparisonsvue_type_template_id_d1a096d8_hoisted_5); }), 128)), _ctx.segmentComparisons.length > 1 ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { key: 0, class: "remove-button", @@ -3638,20 +4560,66 @@ function Comparisonsvue_type_template_id_1b8ecdd2_render(_ctx, _cache, $props, $ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { class: "icon icon-close", title: _ctx.translate('General_ClickToRemoveComp') - }, null, 8, Comparisonsvue_type_template_id_1b8ecdd2_hoisted_8)], 8, Comparisonsvue_type_template_id_1b8ecdd2_hoisted_7)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]); - }), 128)), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Comparisonsvue_type_template_id_1b8ecdd2_hoisted_9, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { + }, null, 8, Comparisonsvue_type_template_id_d1a096d8_hoisted_8)], 8, Comparisonsvue_type_template_id_d1a096d8_hoisted_7)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]); + }), 128)), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Comparisonsvue_type_template_id_d1a096d8_hoisted_9, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { src: "plugins/Morpheus/images/loading-blue.gif", alt: _ctx.translate('General_LoadingData') - }, null, 8, Comparisonsvue_type_template_id_1b8ecdd2_hoisted_10), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_LoadingData')), 1)])], 512)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true); + }, null, 8, Comparisonsvue_type_template_id_d1a096d8_hoisted_10), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_LoadingData')), 1)])], 512)), [[_directive_tooltips, { + duration: 200, + delay: 200, + content: _ctx.transformTooltipContent + }]]) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=template&id=1b8ecdd2 +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=template&id=d1a096d8 -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=script&lang=ts -function Comparisonsvue_type_script_lang_ts_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Tooltips/Tooltips.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +var Tooltips_window = window, + Tooltips_$ = Tooltips_window.$; -function Comparisonsvue_type_script_lang_ts_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { Comparisonsvue_type_script_lang_ts_ownKeys(Object(source), true).forEach(function (key) { Comparisonsvue_type_script_lang_ts_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { Comparisonsvue_type_script_lang_ts_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } +function defaultContentTransform() { + var title = Tooltips_$(this).attr('title') || ''; + return window.vueSanitize(title.replace(/\n/g, '<br />')); +} -function Comparisonsvue_type_script_lang_ts_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function setupTooltips(el, binding) { + var _binding$value, _binding$value2, _binding$value3; + + Tooltips_$(el).tooltip({ + track: true, + content: ((_binding$value = binding.value) === null || _binding$value === void 0 ? void 0 : _binding$value.content) || defaultContentTransform, + show: { + delay: ((_binding$value2 = binding.value) === null || _binding$value2 === void 0 ? void 0 : _binding$value2.delay) || 700, + duration: ((_binding$value3 = binding.value) === null || _binding$value3 === void 0 ? void 0 : _binding$value3.duration) || 200 + }, + hide: false + }); +} + +/* harmony default export */ var Tooltips = ({ + mounted: function mounted(el, binding) { + setTimeout(function () { + return setupTooltips(el, binding); + }); + }, + updated: function updated(el, binding) { + setTimeout(function () { + return setupTooltips(el, binding); + }); + }, + beforeUnmount: function beforeUnmount(el) { + try { + window.$(el).tooltip('destroy'); + } catch (e) {// ignore + } + } +}); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=script&lang=ts @@ -3661,6 +4629,9 @@ function Comparisonsvue_type_script_lang_ts_defineProperty(obj, key, value) { if /* harmony default export */ var Comparisonsvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ props: {}, + directives: { + Tooltips: Tooltips + }, data: function data() { return { comparisonTooltips: null @@ -3679,11 +4650,23 @@ function Comparisonsvue_type_script_lang_ts_defineProperty(obj, key, value) { if return Comparisons_store_instance.getPeriodComparisons(); }); var getSeriesColor = Comparisons_store_instance.getSeriesColor.bind(Comparisons_store_instance); + + function transformTooltipContent() { + var title = window.$(this).attr('title'); + + if (!title) { + return title; + } + + return window.vueSanitize(title.replace(/\n/g, '<br />')); + } + return { isComparing: isComparing, segmentComparisons: segmentComparisons, periodComparisons: periodComparisons, - getSeriesColor: getSeriesColor + getSeriesColor: getSeriesColor, + transformTooltipContent: transformTooltipContent }; }, methods: { @@ -3713,30 +4696,13 @@ function Comparisonsvue_type_script_lang_ts_defineProperty(obj, key, value) { if return (this.comparisonTooltips[periodComparison.index] || {})[segmentComparison.index]; }, getUrlToSegment: function getUrlToSegment(segment) { - var hash = Comparisonsvue_type_script_lang_ts_objectSpread({}, src_MatomoUrl_MatomoUrl.hashParsed.value); - + var hash = Object.assign({}, src_MatomoUrl_MatomoUrl.hashParsed.value); delete hash.comparePeriods; delete hash.compareDates; delete hash.compareSegments; hash.segment = segment; return "".concat(window.location.search, "#?").concat(src_MatomoUrl_MatomoUrl.stringify(hash)); }, - setUpTooltips: function setUpTooltips() { - var _window = window, - $ = _window.$; - $(this.$refs.root).tooltip({ - track: true, - content: function transformTooltipContent() { - var title = $(this).attr('title'); - return window.vueSanitize(title.replace(/\n/g, '<br />')); - }, - show: { - delay: 200, - duration: 200 - }, - hide: false - }); - }, onComparisonsChanged: function onComparisonsChanged() { var _this = this; @@ -3794,29 +4760,13 @@ function Comparisonsvue_type_script_lang_ts_defineProperty(obj, key, value) { if return tooltip; } }, - updated: function updated() { - var _this2 = this; - - setTimeout(function () { - return _this2.setUpTooltips(); - }); - }, mounted: function mounted() { - var _this3 = this; + var _this2 = this; Matomo_Matomo.on('piwikComparisonsChanged', function () { - _this3.onComparisonsChanged(); + _this2.onComparisonsChanged(); }); this.onComparisonsChanged(); - setTimeout(function () { - return _this3.setUpTooltips(); - }); - }, - beforeUnmount: function beforeUnmount() { - try { - window.$(this.refs.root).tooltip('destroy'); - } catch (e) {// ignore - } } })); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=script&lang=ts @@ -3825,7 +4775,7 @@ function Comparisonsvue_type_script_lang_ts_defineProperty(obj, key, value) { if -Comparisonsvue_type_script_lang_ts.render = Comparisonsvue_type_template_id_1b8ecdd2_render +Comparisonsvue_type_script_lang_ts.render = Comparisonsvue_type_template_id_d1a096d8_render /* harmony default export */ var Comparisons = (Comparisonsvue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts @@ -3843,42 +4793,41 @@ function ComparisonFactory() { return Comparisons_store_instance; } -ComparisonFactory.$inject = []; -angular.module('piwikApp.service').factory('piwikComparisonsService', ComparisonFactory); +window.angular.module('piwikApp.service').factory('piwikComparisonsService', ComparisonFactory); /* harmony default export */ var Comparisons_adapter = (createAngularJsAdapter({ component: Comparisons, directiveName: 'piwikComparisons', restrict: 'E' })); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue?vue&type=template&id=0349d645 +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue?vue&type=template&id=ee5932cc -var Menudropdownvue_type_template_id_0349d645_hoisted_1 = { +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_1 = { ref: "root", class: "menuDropdown" }; -var Menudropdownvue_type_template_id_0349d645_hoisted_2 = ["title"]; -var Menudropdownvue_type_template_id_0349d645_hoisted_3 = ["innerHTML"]; +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_2 = ["title"]; +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_3 = ["innerHTML"]; -var Menudropdownvue_type_template_id_0349d645_hoisted_4 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_4 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { class: "icon-arrow-bottom" }, null, -1); -var Menudropdownvue_type_template_id_0349d645_hoisted_5 = { +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_5 = { class: "items" }; -var Menudropdownvue_type_template_id_0349d645_hoisted_6 = { +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_6 = { key: 0, class: "search" }; -var Menudropdownvue_type_template_id_0349d645_hoisted_7 = ["placeholder"]; -var Menudropdownvue_type_template_id_0349d645_hoisted_8 = ["title"]; -var Menudropdownvue_type_template_id_0349d645_hoisted_9 = ["title"]; -function Menudropdownvue_type_template_id_0349d645_render(_ctx, _cache, $props, $setup, $data, $options) { +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_7 = ["placeholder"]; +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_8 = ["title"]; +var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_9 = ["title"]; +function MenuItemsDropdownvue_type_template_id_ee5932cc_render(_ctx, _cache, $props, $setup, $data, $options) { var _directive_focus_if = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("focus-if"); var _directive_focus_anywhere_but_here = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("focus-anywhere-but-here"); - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Menudropdownvue_type_template_id_0349d645_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { class: "title", onClick: _cache[0] || (_cache[0] = function ($event) { return _ctx.showItems = !_ctx.showItems; @@ -3886,7 +4835,7 @@ function Menudropdownvue_type_template_id_0349d645_render(_ctx, _cache, $props, title: _ctx.tooltip }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { innerHTML: _ctx.$sanitize(this.actualMenuTitle) - }, null, 8, Menudropdownvue_type_template_id_0349d645_hoisted_3), Menudropdownvue_type_template_id_0349d645_hoisted_4], 8, Menudropdownvue_type_template_id_0349d645_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Menudropdownvue_type_template_id_0349d645_hoisted_5, [_ctx.showSearch && _ctx.showItems ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Menudropdownvue_type_template_id_0349d645_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + }, null, 8, MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_3), MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_4], 8, MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_5, [_ctx.showSearch && _ctx.showItems ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { type: "text", "onUpdate:modelValue": _cache[1] || (_cache[1] = function ($event) { return _ctx.searchTerm = $event; @@ -3895,11 +4844,11 @@ function Menudropdownvue_type_template_id_0349d645_render(_ctx, _cache, $props, return _ctx.onSearchTermKeydown($event); }), placeholder: _ctx.translate('General_Search') - }, null, 40, Menudropdownvue_type_template_id_0349d645_hoisted_7), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.searchTerm], [_directive_focus_if, {}, _ctx.showItems]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { + }, null, 40, MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_7), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.searchTerm], [_directive_focus_if, {}, _ctx.showItems]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { class: "search_ico", src: "plugins/Morpheus/images/search_ico.png", title: _ctx.translate('General_Search') - }, null, 8, Menudropdownvue_type_template_id_0349d645_hoisted_8), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !_ctx.searchTerm]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { + }, null, 8, MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_8), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !_ctx.searchTerm]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { onClick: _cache[3] || (_cache[3] = function ($event) { _ctx.searchTerm = ''; @@ -3908,7 +4857,7 @@ function Menudropdownvue_type_template_id_0349d645_render(_ctx, _cache, $props, class: "reset", src: "plugins/CoreHome/images/reset_search.png", title: _ctx.translate('General_Clear') - }, null, 8, Menudropdownvue_type_template_id_0349d645_hoisted_9), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.searchTerm]])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { + }, null, 8, MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_9), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.searchTerm]])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { onClick: _cache[4] || (_cache[4] = function ($event) { return _ctx.selectItem($event); }) @@ -3916,20 +4865,20 @@ function Menudropdownvue_type_template_id_0349d645_render(_ctx, _cache, $props, blur: _ctx.lostFocus }]]); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue?vue&type=template&id=0349d645 +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue?vue&type=template&id=ee5932cc -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue?vue&type=script&lang=ts -var Menudropdownvue_type_script_lang_ts_window = window, - Menudropdownvue_type_script_lang_ts_$ = Menudropdownvue_type_script_lang_ts_window.$; -/* harmony default export */ var Menudropdownvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ +var MenuItemsDropdownvue_type_script_lang_ts_window = window, + MenuItemsDropdownvue_type_script_lang_ts_$ = MenuItemsDropdownvue_type_script_lang_ts_window.$; +/* harmony default export */ var MenuItemsDropdownvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ props: { menuTitle: String, tooltip: String, showSearch: Boolean, - menuTitleChangeOnClick: String + menuTitleChangeOnClick: Boolean }, directives: { FocusAnywhereButHere: FocusAnywhereButHere, @@ -3959,14 +4908,14 @@ var Menudropdownvue_type_script_lang_ts_window = window, return; } - if (this.menuTitleChangeOnClick !== false) { - this.actualMenuTitle = event.target.textContent.replace(/[\u0000-\u2666]/g, function (c) { + if (this.menuTitleChangeOnClick) { + this.actualMenuTitle = (event.target.textContent || '').replace(/[\u0000-\u2666]/g, function (c) { return "&#".concat(c.charCodeAt(0), ";"); }); // eslint-disable-line } this.showItems = false; - Menudropdownvue_type_script_lang_ts_$(this.$slots.default()).find('.item').removeClass('active'); + MenuItemsDropdownvue_type_script_lang_ts_$(this.$slots.default()[0].el).find('.item').removeClass('active'); targetClasses.add('active'); this.$emit('afterSelect'); }, @@ -3979,8 +4928,8 @@ var Menudropdownvue_type_script_lang_ts_window = window, }, searchItems: function searchItems(unprocessedSearchTerm) { var searchTerm = unprocessedSearchTerm.toLowerCase(); - Menudropdownvue_type_script_lang_ts_$(this.$refs.root).find('.item').each(function (index, node) { - var $node = Menudropdownvue_type_script_lang_ts_$(node); + MenuItemsDropdownvue_type_script_lang_ts_$(this.$refs.root).find('.item').each(function (index, node) { + var $node = MenuItemsDropdownvue_type_script_lang_ts_$(node); if ($node.text().toLowerCase().indexOf(searchTerm) === -1) { $node.hide(); @@ -3991,16 +4940,16 @@ var Menudropdownvue_type_script_lang_ts_window = window, } } })); -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue?vue&type=script&lang=ts -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue -Menudropdownvue_type_script_lang_ts.render = Menudropdownvue_type_template_id_0349d645_render +MenuItemsDropdownvue_type_script_lang_ts.render = MenuItemsDropdownvue_type_template_id_ee5932cc_render -/* harmony default export */ var Menudropdown = (Menudropdownvue_type_script_lang_ts); -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.adapter.ts +/* harmony default export */ var MenuItemsDropdown = (MenuItemsDropdownvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.adapter.ts /*! * Matomo - free/libre analytics platform * @@ -4009,8 +4958,8 @@ Menudropdownvue_type_script_lang_ts.render = Menudropdownvue_type_template_id_03 */ -/* harmony default export */ var Menudropdown_adapter = (createAngularJsAdapter({ - component: Menudropdown, +/* harmony default export */ var MenuItemsDropdown_adapter = (createAngularJsAdapter({ + component: MenuItemsDropdown, scope: { menuTitle: { angularJsBind: '@' @@ -4028,30 +4977,24 @@ Menudropdownvue_type_script_lang_ts.render = Menudropdownvue_type_template_id_03 directiveName: 'piwikMenudropdown', transclude: true, events: { - 'after-select': function afterSelect($event, scope) { + 'after-select': function afterSelect($event, vm, scope) { setTimeout(function () { scope.$apply(); }, 0); } } })); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=template&id=c8c462d2 +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=template&id=589729fc -var DatePickervue_type_template_id_c8c462d2_hoisted_1 = { +var DatePickervue_type_template_id_589729fc_hoisted_1 = { ref: "root" }; -function DatePickervue_type_template_id_c8c462d2_render(_ctx, _cache, $props, $setup, $data, $options) { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", DatePickervue_type_template_id_c8c462d2_hoisted_1, null, 512); +function DatePickervue_type_template_id_589729fc_render(_ctx, _cache, $props, $setup, $data, $options) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", DatePickervue_type_template_id_589729fc_hoisted_1, null, 512); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=template&id=c8c462d2 - -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=script&lang=ts -function DatePickervue_type_script_lang_ts_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } - -function DatePickervue_type_script_lang_ts_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { DatePickervue_type_script_lang_ts_ownKeys(Object(source), true).forEach(function (key) { DatePickervue_type_script_lang_ts_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { DatePickervue_type_script_lang_ts_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } - -function DatePickervue_type_script_lang_ts_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=template&id=589729fc +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=script&lang=ts @@ -4144,18 +5087,20 @@ var DatePickervue_type_script_lang_ts_window = window, } function viewDateChanged() { - var date = props.viewDate; - - if (!date) { + if (!props.viewDate) { return false; } - if (!(date instanceof Date)) { + var date; + + if (typeof props.viewDate === 'string') { try { - date = parseDate(date); + date = parseDate(props.viewDate); } catch (e) { return false; } + } else { + date = props.viewDate; } var element = DatePickervue_type_script_lang_ts_$(root.value); // only change the datepicker date if the date is outside of the current month/year. @@ -4201,7 +5146,11 @@ var DatePickervue_type_script_lang_ts_window = window, function enableDisableMonthDropdown() { var element = DatePickervue_type_script_lang_ts_$(root.value); - element.find('.ui-datepicker-month').attr('disabled', props.disableMonthDropdown); + var monthPicker = element.find('.ui-datepicker-month')[0]; + + if (monthPicker) { + monthPicker.disabled = props.disableMonthDropdown; + } } function handleOtherMonthClick() { @@ -4233,23 +5182,34 @@ var DatePickervue_type_script_lang_ts_window = window, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () { - return DatePickervue_type_script_lang_ts_objectSpread({}, props); + return Object.assign({}, props); }, function (newProps, oldProps) { var redraw = false; - ['selectedDateStart', 'selectedDateEnd', 'highlightedDateStart', 'highlightedDateEnd'].forEach(function (propName) { + [function (x) { + return x.selectedDateStart; + }, function (x) { + return x.selectedDateEnd; + }, function (x) { + return x.highlightedDateStart; + }, function (x) { + return x.highlightedDateEnd; + }].forEach(function (selector) { if (redraw) { return; } - if (!newProps[propName] && oldProps[propName]) { + var newProp = selector(newProps); + var oldProp = selector(oldProps); + + if (!newProp && oldProp) { redraw = true; } - if (newProps[propName] && !oldProps[propName]) { + if (newProp && !oldProp) { redraw = true; } - if (newProps[propName] && oldProps[propName] && newProps[propName].getTime() !== oldProps[propName].getTime()) { + if (newProp && oldProp && newProp.getTime() !== oldProp.getTime()) { redraw = true; } }); @@ -4262,7 +5222,7 @@ var DatePickervue_type_script_lang_ts_window = window, stepMonthsChanged(); } - if (newProps.enableDisableMonthDropdown !== oldProps.enableDisableMonthDropdown) { + if (newProps.disableMonthDropdown !== oldProps.disableMonthDropdown) { enableDisableMonthDropdown(); } // redraw when selected/highlighted dates change @@ -4274,8 +5234,7 @@ var DatePickervue_type_script_lang_ts_window = window, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["onMounted"])(function () { var element = DatePickervue_type_script_lang_ts_$(root.value); var customOptions = props.options || {}; - - var datePickerOptions = DatePickervue_type_script_lang_ts_objectSpread(DatePickervue_type_script_lang_ts_objectSpread(DatePickervue_type_script_lang_ts_objectSpread({}, Matomo_Matomo.getBaseDatePickerOptions()), customOptions), {}, { + var datePickerOptions = Object.assign(Object.assign(Object.assign({}, Matomo_Matomo.getBaseDatePickerOptions()), customOptions), {}, { onChangeMonthYear: function onChangeMonthYear() { // datepicker renders the HTML after this hook is called, so we use setTimeout // to run some code after the render. @@ -4284,7 +5243,6 @@ var DatePickervue_type_script_lang_ts_window = window, }); } }); - element.datepicker(datePickerOptions); element.on('mouseover', 'tbody td a', function (event) { // this event is triggered when a user clicks a date as well. in that case, @@ -4316,9 +5274,7 @@ var DatePickervue_type_script_lang_ts_window = window, return context.emit('cellHoverLeave'); }); // make sure whitespace is clickable when the period makes it appropriate - element.on('click', 'tbody td.ui-datepicker-other-month', function () { - return handleOtherMonthClick(); - }); // NOTE: using a selector w/ .on() doesn't seem to work for some reason... + element.on('click', 'tbody td.ui-datepicker-other-month', handleOtherMonthClick); // NOTE: using a selector w/ .on() doesn't seem to work for some reason... element.on('click', function (e) { e.preventDefault(); @@ -4362,7 +5318,7 @@ var DatePickervue_type_script_lang_ts_window = window, -DatePickervue_type_script_lang_ts.render = DatePickervue_type_template_id_c8c462d2_render +DatePickervue_type_script_lang_ts.render = DatePickervue_type_template_id_589729fc_render /* harmony default export */ var DatePicker = (DatePickervue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts @@ -4413,30 +5369,30 @@ DatePickervue_type_script_lang_ts.render = DatePickervue_type_template_id_c8c462 }, directiveName: 'piwikDatePicker', events: { - 'cell-hover': function cellHover(event, scope, element, attrs, $timeout) { + 'cell-hover': function cellHover(event, vm, scope, element, attrs, controller, $timeout) { $timeout(); // trigger new digest }, - 'cell-hover-leave': function cellHoverLeave(event, scope, element, attrs, $timeout) { + 'cell-hover-leave': function cellHoverLeave(event, vm, scope, element, attrs, controller, $timeout) { $timeout(); // trigger new digest }, - 'date-select': function dateSelect(event, scope, element, attrs, $timeout) { + 'date-select': function dateSelect(event, vm, scope, element, attrs, controller, $timeout) { $timeout(); // trigger new digest } }, $inject: ['$timeout'] })); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue?vue&type=template&id=d9f4b538 +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue?vue&type=template&id=7bf842c2 -var DateRangePickervue_type_template_id_d9f4b538_hoisted_1 = { +var DateRangePickervue_type_template_id_7bf842c2_hoisted_1 = { id: "calendarRangeFrom" }; -var DateRangePickervue_type_template_id_d9f4b538_hoisted_2 = { +var DateRangePickervue_type_template_id_7bf842c2_hoisted_2 = { id: "calendarRangeTo" }; -function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $props, $setup, $data, $options) { +function DateRangePickervue_type_template_id_7bf842c2_render(_ctx, _cache, $props, $setup, $data, $options) { var _component_DatePicker = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("DatePicker"); - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", DateRangePickervue_type_template_id_d9f4b538_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h6", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_DateRangeFrom')) + " ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", DateRangePickervue_type_template_id_7bf842c2_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h6", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_DateRangeFrom')) + " ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { type: "text", id: "inputCalendarFrom", name: "inputCalendarFrom", @@ -4444,7 +5400,7 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) { return _ctx.startDateText = $event; }), - onChange: _cache[1] || (_cache[1] = function ($event) { + onKeydown: _cache[1] || (_cache[1] = function ($event) { return _ctx.onRangeInputChanged('from', $event); }), onKeyup: _cache[2] || (_cache[2] = function ($event) { @@ -4466,7 +5422,7 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop onCellHoverLeave: _cache[5] || (_cache[5] = function ($event) { return _ctx.fromPickerHighlightedDates = [null, null]; }) - }, null, 8, ["view-date", "selected-date-start", "selected-date-end", "highlighted-date-start", "highlighted-date-end"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", DateRangePickervue_type_template_id_d9f4b538_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h6", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_DateRangeTo')) + " ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + }, null, 8, ["view-date", "selected-date-start", "selected-date-end", "highlighted-date-start", "highlighted-date-end"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", DateRangePickervue_type_template_id_7bf842c2_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h6", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_DateRangeTo')) + " ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { type: "text", id: "inputCalendarTo", name: "inputCalendarTo", @@ -4474,7 +5430,7 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop "onUpdate:modelValue": _cache[6] || (_cache[6] = function ($event) { return _ctx.endDateText = $event; }), - onChange: _cache[7] || (_cache[7] = function ($event) { + onKeydown: _cache[7] || (_cache[7] = function ($event) { return _ctx.onRangeInputChanged('to', $event); }), onKeyup: _cache[8] || (_cache[8] = function ($event) { @@ -4496,14 +5452,15 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop onCellHoverLeave: _cache[11] || (_cache[11] = function ($event) { return _ctx.toPickerHighlightedDates = [null, null]; }) - }, null, 8, ["view-date", "selected-date-start", "selected-date-end", "highlighted-date-start", "highlighted-date-end"])])], 64); + }, null, 8, ["view-date", "selected-date-start", "selected-date-end", "highlighted-date-start", "highlighted-date-end"])])]); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue?vue&type=template&id=d9f4b538 +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue?vue&type=template&id=7bf842c2 -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue?vue&type=script&lang=ts +var DATE_FORMAT = 'YYYY-MM-DD'; /* harmony default export */ var DateRangePickervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ props: { startDate: String, @@ -4516,14 +5473,18 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop var startDate = null; try { - startDate = parseDate(this.startDate); + if (this.startDate) { + startDate = parseDate(this.startDate); + } } catch (e) {// ignore } var endDate = null; try { - endDate = parseDate(this.endDate); + if (this.endDate) { + endDate = parseDate(this.endDate); + } } catch (e) {// ignore } @@ -4533,7 +5494,9 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop fromPickerHighlightedDates: [null, null], toPickerHighlightedDates: [null, null], startDateText: this.startDate, - endDateText: this.endDate + endDateText: this.endDate, + startDateInvalid: false, + endDateInvalid: false }; }, emits: ['rangeChange', 'submit'], @@ -4560,11 +5523,15 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop this.rangeChanged(); }, onRangeInputChanged: function onRangeInputChanged(source, event) { - if (source === 'from') { - this.setStartRangeDateFromStr(event.target.value); - } else { - this.setEndRangeDateFromStr(event.target.value); - } + var _this = this; + + setTimeout(function () { + if (source === 'from') { + _this.setStartRangeDateFromStr(event.target.value); + } else { + _this.setEndRangeDateFromStr(event.target.value); + } + }); }, getNewHighlightedDates: function getNewHighlightedDates(date, $cell) { if ($cell.hasClass('ui-datepicker-unselectable')) { @@ -4584,39 +5551,43 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop }); }, setStartRangeDateFromStr: function setStartRangeDateFromStr(dateStr) { - var startDateParsed; + this.startDateInvalid = true; + var startDateParsed = null; try { - startDateParsed = parseDate(dateStr); - } catch (e) { - this.startDateText = this.startDate; + if (dateStr && dateStr.length === DATE_FORMAT.length) { + startDateParsed = parseDate(dateStr); + } + } catch (e) {// ignore } if (startDateParsed) { this.fromPickerSelectedDates = [startDateParsed, startDateParsed]; + this.startDateInvalid = false; + this.rangeChanged(); } - - this.rangeChanged(); }, setEndRangeDateFromStr: function setEndRangeDateFromStr(dateStr) { - var endDateParsed; + this.endDateInvalid = true; + var endDateParsed = null; try { - endDateParsed = parseDate(dateStr); - } catch (e) { - this.endDateText = this.endDate; + if (dateStr && dateStr.length === DATE_FORMAT.length) { + endDateParsed = parseDate(dateStr); + } + } catch (e) {// ignore } if (endDateParsed) { this.toPickerSelectedDates = [endDateParsed, endDateParsed]; + this.endDateInvalid = false; + this.rangeChanged(); } - - this.rangeChanged(); }, rangeChanged: function rangeChanged() { this.$emit('rangeChange', { - start: format(this.fromPickerSelectedDates[0]), - end: format(this.toPickerSelectedDates[0]) + start: this.fromPickerSelectedDates[0] ? format(this.fromPickerSelectedDates[0]) : null, + end: this.toPickerSelectedDates[0] ? format(this.toPickerSelectedDates[0]) : null }); } } @@ -4627,7 +5598,7 @@ function DateRangePickervue_type_template_id_d9f4b538_render(_ctx, _cache, $prop -DateRangePickervue_type_script_lang_ts.render = DateRangePickervue_type_template_id_d9f4b538_render +DateRangePickervue_type_script_lang_ts.render = DateRangePickervue_type_template_id_7bf842c2_render /* harmony default export */ var DateRangePicker = (DateRangePickervue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.adapter.ts @@ -4658,9 +5629,9 @@ DateRangePickervue_type_script_lang_ts.render = DateRangePickervue_type_template directiveName: 'piwikDateRangePicker', restrict: 'E' })); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue?vue&type=template&id=0fe3c4e7 +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue?vue&type=template&id=6d1fa14c -function PeriodDatePickervue_type_template_id_0fe3c4e7_render(_ctx, _cache, $props, $setup, $data, $options) { +function PeriodDatePickervue_type_template_id_6d1fa14c_render(_ctx, _cache, $props, $setup, $data, $options) { var _component_DatePicker = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("DatePicker"); return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_DatePicker, { @@ -4682,18 +5653,21 @@ function PeriodDatePickervue_type_template_id_0fe3c4e7_render(_ctx, _cache, $pro }) }, null, 8, ["selected-date-start", "selected-date-end", "highlighted-date-start", "highlighted-date-end", "view-date", "step-months", "disable-month-dropdown"]); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue?vue&type=template&id=0fe3c4e7 +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue?vue&type=template&id=6d1fa14c -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue?vue&type=script&lang=ts -var piwikMinDate = new Date(Matomo_Matomo.minDateYear, Matomo_Matomo.minDateMonth - 1, Matomo_Matomo.minDateDay); +var PeriodDatePickervue_type_script_lang_ts_piwikMinDate = new Date(Matomo_Matomo.minDateYear, Matomo_Matomo.minDateMonth - 1, Matomo_Matomo.minDateDay); var piwikMaxDate = new Date(Matomo_Matomo.maxDateYear, Matomo_Matomo.maxDateMonth - 1, Matomo_Matomo.maxDateDay); /* harmony default export */ var PeriodDatePickervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ props: { - period: String, + period: { + type: String, + required: true + }, date: [String, Date] }, components: { @@ -4708,13 +5682,13 @@ var piwikMaxDate = new Date(Matomo_Matomo.maxDateYear, Matomo_Matomo.maxDateMont function getBoundedDateRange(date) { var dates = Periods_Periods.get(props.period).parse(date).getDateRange(); // make sure highlighted date range is within min/max date range - dates[0] = piwikMinDate < dates[0] ? dates[0] : piwikMinDate; + dates[0] = PeriodDatePickervue_type_script_lang_ts_piwikMinDate < dates[0] ? dates[0] : PeriodDatePickervue_type_script_lang_ts_piwikMinDate; dates[1] = piwikMaxDate > dates[1] ? dates[1] : piwikMaxDate; return dates; } function onHoverNormalCell(cellDate, $cell) { - var isOutOfMinMaxDateRange = cellDate < piwikMinDate || cellDate > piwikMaxDate; // don't highlight anything if the period is month or day, and we're hovering over calendar + var isOutOfMinMaxDateRange = cellDate < PeriodDatePickervue_type_script_lang_ts_piwikMinDate || cellDate > piwikMaxDate; // don't highlight anything if the period is month or day, and we're hovering over calendar // whitespace. since there are no dates, it's doesn't make sense what you're selecting. var shouldNotHighlightFromWhitespace = $cell.hasClass('ui-datepicker-other-month') && (props.period === 'month' || props.period === 'day'); @@ -4740,10 +5714,12 @@ var piwikMaxDate = new Date(Matomo_Matomo.maxDateYear, Matomo_Matomo.maxDateMont function onChanges() { if (!props.period || !props.date) { selectedDates.value = [null, null]; + viewDate.value = null; return; } selectedDates.value = getBoundedDateRange(props.date); + viewDate.value = parseDate(props.date); } Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(props, onChanges); @@ -4764,7 +5740,7 @@ var piwikMaxDate = new Date(Matomo_Matomo.maxDateYear, Matomo_Matomo.maxDateMont -PeriodDatePickervue_type_script_lang_ts.render = PeriodDatePickervue_type_template_id_0fe3c4e7_render +PeriodDatePickervue_type_script_lang_ts.render = PeriodDatePickervue_type_template_id_6d1fa14c_render /* harmony default export */ var PeriodDatePicker = (PeriodDatePickervue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.adapter.ts @@ -4792,49 +5768,625 @@ PeriodDatePickervue_type_script_lang_ts.render = PeriodDatePickervue_type_templa directiveName: 'piwikPeriodDatePicker', restrict: 'E' })); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=template&id=6af4d064 +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue?vue&type=template&id=48e19035 -var ActivityIndicatorvue_type_template_id_6af4d064_hoisted_1 = { - class: "loadingPiwik" +var SiteSelectorvue_type_template_id_48e19035_hoisted_1 = ["value", "name"]; +var SiteSelectorvue_type_template_id_48e19035_hoisted_2 = ["title"]; +var SiteSelectorvue_type_template_id_48e19035_hoisted_3 = ["textContent"]; +var SiteSelectorvue_type_template_id_48e19035_hoisted_4 = { + key: 1, + class: "placeholder" +}; +var SiteSelectorvue_type_template_id_48e19035_hoisted_5 = { + class: "dropdown" }; +var SiteSelectorvue_type_template_id_48e19035_hoisted_6 = { + class: "custom_select_search" +}; +var SiteSelectorvue_type_template_id_48e19035_hoisted_7 = ["placeholder"]; +var SiteSelectorvue_type_template_id_48e19035_hoisted_8 = { + key: 0 +}; +var SiteSelectorvue_type_template_id_48e19035_hoisted_9 = { + class: "custom_select_container" +}; +var SiteSelectorvue_type_template_id_48e19035_hoisted_10 = ["onClick"]; +var SiteSelectorvue_type_template_id_48e19035_hoisted_11 = ["innerHTML", "href", "title"]; +var SiteSelectorvue_type_template_id_48e19035_hoisted_12 = { + class: "ui-autocomplete ui-front ui-menu ui-widget ui-widget-content ui-corner-all\n siteSelect" +}; +var SiteSelectorvue_type_template_id_48e19035_hoisted_13 = { + class: "ui-menu-item" +}; +var SiteSelectorvue_type_template_id_48e19035_hoisted_14 = { + class: "ui-corner-all", + tabindex: "-1" +}; +var _hoisted_15 = { + key: 1 +}; +function SiteSelectorvue_type_template_id_48e19035_render(_ctx, _cache, $props, $setup, $data, $options) { + var _ctx$modelValue, _ctx$modelValue2, _ctx$modelValue3, _ctx$modelValue4; -var ActivityIndicatorvue_type_template_id_6af4d064_hoisted_2 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { - src: "plugins/Morpheus/images/loading-blue.gif", - alt: "" -}, null, -1); + var _component_AllSitesLink = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("AllSitesLink"); + + var _directive_focus_if = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("focus-if"); -function ActivityIndicatorvue_type_template_id_6af4d064_render(_ctx, _cache, $props, $setup, $data, $options) { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ActivityIndicatorvue_type_template_id_6af4d064_hoisted_1, [ActivityIndicatorvue_type_template_id_6af4d064_hoisted_2, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.loadingMessage), 1)], 512)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.loading]]); + var _directive_focus_anywhere_but_here = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("focus-anywhere-but-here"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["siteSelector piwikSelector borderedControl", { + 'expanded': _ctx.showSitesList, + 'disabled': !_ctx.hasMultipleSites + }]) + }, [_ctx.name ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("input", { + key: 0, + type: "hidden", + value: (_ctx$modelValue = _ctx.modelValue) === null || _ctx$modelValue === void 0 ? void 0 : _ctx$modelValue.id, + name: _ctx.name + }, null, 8, SiteSelectorvue_type_template_id_48e19035_hoisted_1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + ref: "selectorLink", + onClick: _cache[0] || (_cache[0] = function () { + return _ctx.onClickSelector && _ctx.onClickSelector.apply(_ctx, arguments); + }), + onKeydown: _cache[1] || (_cache[1] = function ($event) { + return _ctx.onPressEnter($event); + }), + href: "javascript:void(0)", + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])([{ + 'loading': _ctx.isLoading + }, "title"]), + tabindex: "4", + title: _ctx.selectorLinkTitle + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["icon icon-arrow-bottom", { + 'iconHidden': _ctx.isLoading, + 'collapsed': !_ctx.showSitesList + }]) + }, null, 2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, [(_ctx$modelValue2 = _ctx.modelValue) !== null && _ctx$modelValue2 !== void 0 && _ctx$modelValue2.name || !_ctx.placeholder ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", { + key: 0, + textContent: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(((_ctx$modelValue3 = _ctx.modelValue) === null || _ctx$modelValue3 === void 0 ? void 0 : _ctx$modelValue3.name) || _ctx.firstSiteName) + }, null, 8, SiteSelectorvue_type_template_id_48e19035_hoisted_3)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !((_ctx$modelValue4 = _ctx.modelValue) !== null && _ctx$modelValue4 !== void 0 && _ctx$modelValue4.name) && _ctx.placeholder ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", SiteSelectorvue_type_template_id_48e19035_hoisted_4, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.placeholder), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])], 42, SiteSelectorvue_type_template_id_48e19035_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", SiteSelectorvue_type_template_id_48e19035_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", SiteSelectorvue_type_template_id_48e19035_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + type: "text", + onClick: _cache[2] || (_cache[2] = function ($event) { + _ctx.searchTerm = ''; + + _ctx.loadInitialSites(); + }), + "onUpdate:modelValue": _cache[3] || (_cache[3] = function ($event) { + return _ctx.searchTerm = $event; + }), + tabindex: "4", + class: "websiteSearch inp browser-default", + placeholder: _ctx.translate('General_Search') + }, null, 8, SiteSelectorvue_type_template_id_48e19035_hoisted_7), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.searchTerm], [_directive_focus_if, {}, _ctx.shouldFocusOnSearch]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { + title: "Clear", + onClick: _cache[4] || (_cache[4] = function ($event) { + _ctx.searchTerm = ''; + + _ctx.loadInitialSites(); + }), + class: "reset", + src: "plugins/CoreHome/images/reset_search.png" + }, null, 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.searchTerm]])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.autocompleteMinSites <= _ctx.sites.length || _ctx.searchTerm]]), _ctx.allSitesLocation === 'top' && _ctx.showAllSitesItem ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", SiteSelectorvue_type_template_id_48e19035_hoisted_8, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_AllSitesLink, { + href: _ctx.urlAllSites, + "all-sites-text": _ctx.allSitesText, + onClick: _cache[5] || (_cache[5] = function ($event) { + return _ctx.onAllSitesClick($event); + }) + }, null, 8, ["href", "all-sites-text"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", SiteSelectorvue_type_template_id_48e19035_hoisted_9, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", { + class: "custom_select_ul_list", + onClick: _cache[7] || (_cache[7] = function ($event) { + return _ctx.showSitesList = false; + }) + }, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.sites, function (site, index) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", { + onClick: function onClick($event) { + return _ctx.switchSite(Object.assign(Object.assign({}, site), {}, { + id: site.idsite + }), $event); + }, + key: index + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + onClick: _cache[6] || (_cache[6] = function ($event) { + return $event.preventDefault(); + }), + innerHTML: _ctx.$sanitize(_ctx.getMatchedSiteName(site.name)), + tabindex: "4", + href: _ctx.getUrlForSiteId(site.idsite), + title: site.name + }, null, 8, SiteSelectorvue_type_template_id_48e19035_hoisted_11)], 8, SiteSelectorvue_type_template_id_48e19035_hoisted_10)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !(!_ctx.showSelectedSite && _ctx.activeSiteId === site.idsite)]]); + }), 128))]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", SiteSelectorvue_type_template_id_48e19035_hoisted_12, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("li", SiteSelectorvue_type_template_id_48e19035_hoisted_13, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", SiteSelectorvue_type_template_id_48e19035_hoisted_14, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('SitesManager_NotFound') + ' ' + _ctx.searchTerm), 1)])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !_ctx.sites.length && _ctx.searchTerm]])]), _ctx.allSitesLocation === 'bottom' && _ctx.showAllSitesItem ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_15, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_AllSitesLink, { + href: _ctx.urlAllSites, + "all-sites-text": _ctx.allSitesText, + onClick: _cache[8] || (_cache[8] = function ($event) { + return _ctx.onAllSitesClick($event); + }) + }, null, 8, ["href", "all-sites-text"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showSitesList]])], 2)), [[_directive_focus_anywhere_but_here, { + blur: _ctx.onBlur + }]]); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=template&id=6af4d064 +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue?vue&type=template&id=48e19035 -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue?vue&type=template&id=45607d28 +var AllSitesLinkvue_type_template_id_45607d28_hoisted_1 = ["innerHTML", "href"]; +function AllSitesLinkvue_type_template_id_45607d28_render(_ctx, _cache, $props, $setup, $data, $options) { + var _this = this; -/* harmony default export */ var ActivityIndicatorvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + onClick: _cache[1] || (_cache[1] = function ($event) { + return _this.onClick($event); + }), + class: "custom_select_all" + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + onClick: _cache[0] || (_cache[0] = function ($event) { + return $event.preventDefault(); + }), + innerHTML: _ctx.$sanitize(_ctx.allSitesText), + tabindex: "4", + href: _ctx.href + }, null, 8, AllSitesLinkvue_type_template_id_45607d28_hoisted_1)]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue?vue&type=template&id=45607d28 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue?vue&type=script&lang=ts + +/* harmony default export */ var AllSitesLinkvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ props: { - loading: { + href: String, + allSitesText: String + }, + emits: ['click'], + methods: { + onClick: function onClick(event) { + this.$emit('click', event); + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue + + + +AllSitesLinkvue_type_script_lang_ts.render = AllSitesLinkvue_type_template_id_45607d28_render + +/* harmony default export */ var AllSitesLink = (AllSitesLinkvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/SitesStore.ts +function SitesStore_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function SitesStore_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function SitesStore_createClass(Constructor, protoProps, staticProps) { if (protoProps) SitesStore_defineProperties(Constructor.prototype, protoProps); if (staticProps) SitesStore_defineProperties(Constructor, staticProps); return Constructor; } + +function SitesStore_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + + +var SitesStore_SitesStore = /*#__PURE__*/function () { + function SitesStore() { + var _this = this; + + SitesStore_classCallCheck(this, SitesStore); + + SitesStore_defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({ + initialSites: [], + isInitialized: false + })); + + SitesStore_defineProperty(this, "currentRequestAbort", null); + + SitesStore_defineProperty(this, "limitRequest", void 0); + + SitesStore_defineProperty(this, "initialSites", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_this.state.initialSites); + })); + } + + SitesStore_createClass(SitesStore, [{ + key: "loadInitialSites", + value: function loadInitialSites() { + var _this2 = this; + + if (this.state.isInitialized) { + return Promise.resolve(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(this.state.initialSites)); + } + + return this.searchSite('%').then(function (sites) { + _this2.state.isInitialized = true; + + if (sites !== null) { + _this2.state.initialSites = sites; + } + + return sites; + }); + } + }, { + key: "loadSite", + value: function loadSite(idSite) { + if (idSite === 'all') { + src_MatomoUrl_MatomoUrl.updateUrl(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.urlParsed.value), {}, { + module: 'MultiSites', + action: 'index', + date: src_MatomoUrl_MatomoUrl.parsed.value.date, + period: src_MatomoUrl_MatomoUrl.parsed.value.period + })); + } else { + src_MatomoUrl_MatomoUrl.updateUrl(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.urlParsed.value), {}, { + segment: '', + idSite: idSite + }), Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.hashParsed.value), {}, { + segment: '', + idSite: idSite + })); + } + } + }, { + key: "searchSite", + value: function searchSite(term) { + var _this3 = this; + + var onlySitesWithAdminAccess = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!term) { + return this.loadInitialSites(); + } + + if (this.currentRequestAbort) { + this.currentRequestAbort.abort(); + } + + if (!this.limitRequest) { + this.limitRequest = AjaxHelper_AjaxHelper.fetch({ + method: 'SitesManager.getNumWebsitesToDisplayPerPage' + }); + } + + return this.limitRequest.then(function (response) { + var limit = response.value; + var methodToCall = 'SitesManager.getPatternMatchSites'; + + if (onlySitesWithAdminAccess) { + methodToCall = 'SitesManager.getSitesWithAdminAccess'; + } + + _this3.currentRequestAbort = new AbortController(); + return AjaxHelper_AjaxHelper.fetch({ + method: methodToCall, + limit: limit, + pattern: term + }, { + abortController: _this3.currentRequestAbort + }); + }).then(function (response) { + if (response) { + return _this3.processWebsitesList(response); + } + + return null; + }).finally(function () { + _this3.currentRequestAbort = null; + }); + } + }, { + key: "processWebsitesList", + value: function processWebsitesList(response) { + var sites = response; + + if (!sites || !sites.length) { + return []; + } + + sites = sites.map(function (s) { + return Object.assign(Object.assign({}, s), {}, { + name: s.group ? "[".concat(s.group, "] ").concat(s.name) : s.name + }); + }); + sites.sort(function (lhs, rhs) { + if (lhs.name.toLowerCase() < rhs.name.toLowerCase()) { + return -1; + } + + return lhs.name.toLowerCase() > rhs.name.toLowerCase() ? 1 : 0; + }); + return sites; + } + }]); + + return SitesStore; +}(); + +/* harmony default export */ var SiteSelector_SitesStore = (new SitesStore_SitesStore()); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/debounce.ts +var DEFAULT_DEBOUNCE_DELAY = 300; +function debounce(fn) { + var delayInMs = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DEFAULT_DEBOUNCE_DELAY; + var timeout; + return function wrapper() { + var _this = this; + + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + if (timeout) { + clearTimeout(timeout); + } + + timeout = setTimeout(function () { + fn.call.apply(fn, [_this].concat(args)); + }, delayInMs); + }; +} +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue?vue&type=script&lang=ts + + + + + + + + + +/* harmony default export */ var SiteSelectorvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + modelValue: { + type: Object, + default: function _default(props) { + if (props.modelValue) { + return props.modelValue; + } + + return Matomo_Matomo.idSite ? { + id: Matomo_Matomo.idSite, + name: Matomo_Matomo.helper.htmlDecode(Matomo_Matomo.siteName) + } : undefined; + } + }, + showSelectedSite: { type: Boolean, - required: true, default: false }, - loadingMessage: { + showAllSitesItem: { + type: Boolean, + default: true + }, + switchSiteOnSelect: { + type: Boolean, + default: true + }, + onlySitesWithAdminAccess: { + type: Boolean, + default: false + }, + name: { type: String, - required: false, - default: translate('General_LoadingData') + default: '' + }, + allSitesText: { + type: String, + default: translate('General_MultiSitesSummary') + }, + allSitesLocation: { + type: String, + default: 'bottom' + }, + placeholder: String + }, + emits: ['update:modelValue', 'blur'], + components: { + AllSitesLink: AllSitesLink + }, + directives: { + FocusAnywhereButHere: FocusAnywhereButHere, + FocusIf: FocusIf + }, + watch: { + searchTerm: function searchTerm() { + this.onSearchTermChanged(); + } + }, + data: function data() { + return { + searchTerm: '', + activeSiteId: "".concat(Matomo_Matomo.idSite), + showSitesList: false, + isLoading: false, + sites: [], + autocompleteMinSites: parseInt(Matomo_Matomo.config.autocomplete_min_sites, 10) + }; + }, + created: function created() { + this.searchSite = debounce(this.searchSite); + }, + mounted: function mounted() { + var _this = this; + + window.initTopControls(); + this.loadInitialSites().then(function () { + if ((!_this.modelValue || !_this.modelValue.id) && !_this.hasMultipleSites && _this.sites[0]) { + _this.$emit('update:modelValue', { + id: _this.sites[0].idsite, + name: _this.sites[0].name + }); + } + }); + var shortcutTitle = translate('CoreHome_ShortcutWebsiteSelector'); + Matomo_Matomo.helper.registerShortcut('w', shortcutTitle, function (event) { + if (event.altKey) { + return; + } + + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; // IE + } + + var selectorLink = _this.$refs.selectorLink; + + if (selectorLink) { + selectorLink.click(); + selectorLink.focus(); + } + }); + }, + computed: { + shouldFocusOnSearch: function shouldFocusOnSearch() { + return this.showSitesList && this.autocompleteMinSites <= this.sites.length || this.searchTerm; + }, + selectorLinkTitle: function selectorLinkTitle() { + var _this$modelValue; + + return this.hasMultipleSites ? translate('CoreHome_ChangeCurrentWebsite', ((_this$modelValue = this.modelValue) === null || _this$modelValue === void 0 ? void 0 : _this$modelValue.name) || this.firstSiteName) : ''; + }, + hasMultipleSites: function hasMultipleSites() { + return SiteSelector_SitesStore.initialSites.value && SiteSelector_SitesStore.initialSites.value.length > 1; + }, + firstSiteName: function firstSiteName() { + var initialSites = SiteSelector_SitesStore.initialSites.value; + return initialSites && initialSites.length > 0 ? initialSites[0].name : ''; + }, + urlAllSites: function urlAllSites() { + var newQuery = src_MatomoUrl_MatomoUrl.stringify(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.urlParsed.value), {}, { + module: 'MultiSites', + action: 'index', + date: src_MatomoUrl_MatomoUrl.parsed.value.date, + period: src_MatomoUrl_MatomoUrl.parsed.value.period + })); + return "?".concat(newQuery); + } + }, + methods: { + onSearchTermChanged: function onSearchTermChanged() { + if (!this.searchTerm) { + this.isLoading = false; + this.loadInitialSites(); + } else { + this.isLoading = true; + this.searchSite(this.searchTerm); + } + }, + onAllSitesClick: function onAllSitesClick(event) { + this.switchSite({ + id: 'all', + name: this.$props.allSitesText + }, event); + this.showSitesList = false; + }, + switchSite: function switchSite(site, event) { + // for Mac OS cmd key needs to be pressed, ctrl key on other systems + var controlKey = navigator.userAgent.indexOf('Mac OS X') !== -1 ? event.metaKey : event.ctrlKey; + + if (event && controlKey && event.target && event.target.href) { + window.open(event.target.href, '_blank'); + return; + } + + this.$emit('update:modelValue', { + id: site.id, + name: site.name + }); + + if (!this.switchSiteOnSelect || this.activeSiteId === site.id) { + return; + } + + SiteSelector_SitesStore.loadSite(site.id); + }, + onBlur: function onBlur() { + this.showSitesList = false; + this.$emit('blur'); + }, + onClickSelector: function onClickSelector() { + if (this.hasMultipleSites) { + this.showSitesList = !this.showSitesList; + + if (!this.isLoading && !this.searchTerm) { + this.loadInitialSites(); + } + } + }, + onPressEnter: function onPressEnter(event) { + if (event.key !== 'Enter') { + return; + } + + event.preventDefault(); + this.showSitesList = !this.showSitesList; + + if (this.showSitesList && !this.isLoading) { + this.loadInitialSites(); + } + }, + getMatchedSiteName: function getMatchedSiteName(siteName) { + var index = siteName.toUpperCase().indexOf(this.searchTerm.toUpperCase()); + + if (index === -1 || this.isLoading // only highlight when we know the displayed results are for a search + ) { + return Matomo_Matomo.helper.htmlEntities(siteName); + } + + var previousPart = Matomo_Matomo.helper.htmlEntities(siteName.substring(0, index)); + var lastPart = Matomo_Matomo.helper.htmlEntities(siteName.substring(index + this.searchTerm.length)); + return "".concat(previousPart, "<span class=\"autocompleteMatched\">").concat(this.searchTerm, "</span>").concat(lastPart); + }, + loadInitialSites: function loadInitialSites() { + var _this2 = this; + + return SiteSelector_SitesStore.loadInitialSites().then(function (sites) { + _this2.sites = sites || []; + }); + }, + searchSite: function searchSite(term) { + var _this3 = this; + + this.isLoading = true; + SiteSelector_SitesStore.searchSite(term, this.onlySitesWithAdminAccess).then(function (sites) { + if (term !== _this3.searchTerm) { + return; // search term changed in the meantime + } + + if (sites) { + _this3.sites = sites; + } + }).finally(function () { + _this3.isLoading = false; + }); + }, + getUrlForSiteId: function getUrlForSiteId(idSite) { + var newQuery = src_MatomoUrl_MatomoUrl.stringify(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.urlParsed.value), {}, { + segment: '', + idSite: idSite + })); + var newHash = src_MatomoUrl_MatomoUrl.stringify(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.hashParsed.value), {}, { + segment: '', + idSite: idSite + })); + return "?".concat(newQuery, "#?").concat(newHash); } } })); -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue?vue&type=script&lang=ts -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue -ActivityIndicatorvue_type_script_lang_ts.render = ActivityIndicatorvue_type_template_id_6af4d064_render +SiteSelectorvue_type_script_lang_ts.render = SiteSelectorvue_type_template_id_48e19035_render -/* harmony default export */ var ActivityIndicator = (ActivityIndicatorvue_type_script_lang_ts); -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts +/* harmony default export */ var SiteSelector = (SiteSelectorvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/SiteSelector.adapter.ts /*! * Matomo - free/libre analytics platform * @@ -4844,55 +6396,787 @@ ActivityIndicatorvue_type_script_lang_ts.render = ActivityIndicatorvue_type_temp -/* harmony default export */ var ActivityIndicator_adapter = (createAngularJsAdapter({ - component: ActivityIndicator, + +/* harmony default export */ var SiteSelector_adapter = (createAngularJsAdapter({ + component: SiteSelector, + require: '?ngModel', scope: { - loading: { - vue: 'loading', - angularJsBind: '<' + showSelectedSite: { + angularJsBind: '=' }, - loadingMessage: { - vue: 'loadingMessage', - angularJsBind: '<', - default: function _default() { - return translate('General_LoadingData'); + showAllSitesItem: { + angularJsBind: '=' + }, + switchSiteOnSelect: { + angularJsBind: '=' + }, + onlySitesWithAdminAccess: { + angularJsBind: '=' + }, + name: { + angularJsBind: '@' + }, + allSitesText: { + angularJsBind: '@' + }, + allSitesLocation: { + angularJsBind: '@' + }, + placeholder: { + angularJsBind: '@' + }, + modelValue: { + default: function _default(scope, element, attrs) { + if (attrs.siteid && attrs.sitename) { + return { + id: attrs.siteid, + name: Matomo_Matomo.helper.htmlDecode(attrs.sitename) + }; + } + + if (Matomo_Matomo.idSite) { + return { + id: Matomo_Matomo.idSite, + name: Matomo_Matomo.helper.htmlDecode(Matomo_Matomo.siteName) + }; + } + + return undefined; } } }, - $inject: [], - directiveName: 'piwikActivityIndicator' + $inject: ['$timeout'], + directiveName: 'piwikSiteselector', + events: { + 'update:modelValue': function updateModelValue(newValue, vm, scope, element, attrs, ngModel, $timeout) { + if (newValue && !vm.modelValue || !newValue && vm.modelValue || newValue.id !== vm.modelValue.id) { + $timeout(function () { + scope.value = newValue; + element.attr('siteid', newValue.id); + element.trigger('change', newValue); + + if (ngModel) { + ngModel.$setViewValue(newValue); + ngModel.$render(); // not called automatically by the digest + } + }); + } + }, + blur: function blur(event, vm, scope) { + setTimeout(function () { + return scope.$apply(); + }); + } + }, + postCreate: function postCreate(vm, scope, element, attrs, controller) { + var ngModel = controller; + scope.$watch('value', function (newVal) { + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () { + if (newVal !== vm.modelValue) { + vm.modelValue = newVal; + } + }); + }); + + if (attrs.siteid && attrs.sitename) { + vm.modelValue = { + id: attrs.siteid, + name: Matomo_Matomo.helper.htmlDecode(attrs.sitename) + }; + } else if (Matomo_Matomo.idSite) { + vm.modelValue = { + id: Matomo_Matomo.idSite, + name: Matomo_Matomo.helper.htmlDecode(Matomo_Matomo.siteName) + }; + } // setup ng-model mapping + + + if (ngModel) { + ngModel.$setViewValue(vm.modelValue); + + ngModel.$render = function () { + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () { + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () { + if (window.angular.isString(ngModel.$viewValue)) { + vm.modelValue = JSON.parse(ngModel.$viewValue); + } else { + vm.modelValue = ngModel.$viewValue; + } + }); + }); + }; + } + } })); -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Alert/Alert.vue?vue&type=template&id=c3863ae2 -function Alertvue_type_template_id_c3863ae2_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/SitesStore.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ -function Alertvue_type_template_id_c3863ae2_render(_ctx, _cache, $props, $setup, $data, $options) { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { - class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["alert", Alertvue_type_template_id_c3863ae2_defineProperty({}, "alert-".concat(_ctx.severity), true)]) - }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")], 2); + +function siteSelectorModelAdapter() { + return { + get initialSites() { + return SiteSelector_SitesStore.initialSites.value; + }, + + loadSite: SiteSelector_SitesStore.loadSite.bind(SiteSelector_SitesStore), + loadInitialSites: function loadInitialSites() { + return cloneThenApply(SiteSelector_SitesStore.loadInitialSites()); + }, + searchSite: function searchSite() { + return cloneThenApply(SiteSelector_SitesStore.searchSite.apply(SiteSelector_SitesStore, arguments)); + } + }; } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Alert/Alert.vue?vue&type=template&id=c3863ae2 -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Alert/Alert.vue?vue&type=script&lang=ts +window.angular.module('piwikApp.service').factory('siteSelectorModel', siteSelectorModelAdapter); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue?vue&type=template&id=21ce66fa -/* harmony default export */ var Alertvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ +var QuickAccessvue_type_template_id_21ce66fa_hoisted_1 = { + ref: "root", + class: "quickAccessInside" +}; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_2 = ["title", "placeholder"]; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_3 = { + class: "dropdown" +}; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_4 = { + class: "no-result" +}; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_5 = ["onClick"]; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_6 = ["onMouseenter", "onClick"]; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_7 = { + class: "quickAccessMatomoSearch" +}; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_8 = ["onMouseenter", "onClick"]; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_9 = ["textContent"]; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_10 = { + class: "quick-access-category helpCategory" +}; +var QuickAccessvue_type_template_id_21ce66fa_hoisted_11 = ["href"]; +function QuickAccessvue_type_template_id_21ce66fa_render(_ctx, _cache, $props, $setup, $data, $options) { + var _directive_focus_if = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("focus-if"); + + var _directive_focus_anywhere_but_here = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("focus-anywhere-but-here"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", QuickAccessvue_type_template_id_21ce66fa_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: "icon-search", + onMouseenter: _cache[0] || (_cache[0] = function ($event) { + return _ctx.searchActive = true; + }) + }, null, 32), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + class: "s", + onKeydown: _cache[1] || (_cache[1] = function ($event) { + return _ctx.onKeypress($event); + }), + onFocus: _cache[2] || (_cache[2] = function ($event) { + return _ctx.searchActive = true; + }), + "onUpdate:modelValue": _cache[3] || (_cache[3] = function ($event) { + return _ctx.searchTerm = $event; + }), + type: "text", + tabindex: "2", + title: _ctx.quickAccessTitle, + placeholder: _ctx.translate('General_Search'), + ref: "input" + }, null, 40, QuickAccessvue_type_template_id_21ce66fa_hoisted_2), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.searchTerm], [_directive_focus_if, {}, _ctx.searchActive]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", QuickAccessvue_type_template_id_21ce66fa_hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("li", QuickAccessvue_type_template_id_21ce66fa_hoisted_4, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_SearchNoResults')), 1)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !(_ctx.numMenuItems > 0 || _ctx.sites.length)]]), (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.menuItems, function (subcategory) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("ul", { + key: subcategory.title + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("li", { + class: "quick-access-category", + onClick: function onClick($event) { + _ctx.searchTerm = subcategory.title; + + _ctx.searchMenu(_ctx.searchTerm); + } + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(subcategory.title), 9, QuickAccessvue_type_template_id_21ce66fa_hoisted_5), (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(subcategory.items, function (submenuEntry) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["result", { + selected: submenuEntry.menuIndex === _ctx.searchIndex + }]), + onMouseenter: function onMouseenter($event) { + return _ctx.searchIndex = submenuEntry.menuIndex; + }, + onClick: function onClick($event) { + return _ctx.selectMenuItem(submenuEntry.index); + }, + key: submenuEntry.index + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(submenuEntry.name.trim()), 1)], 42, QuickAccessvue_type_template_id_21ce66fa_hoisted_6); + }), 128))]); + }), 128)), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", QuickAccessvue_type_template_id_21ce66fa_hoisted_7, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("li", { + class: "quick-access-category websiteCategory" + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('SitesManager_Sites')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.hasSitesSelector && _ctx.sites.length || _ctx.isLoading]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("li", { + class: "no-result" + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('MultiSites_LoadingWebsites')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.hasSitesSelector && _ctx.isLoading]]), (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.sites, function (site, index) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["result", { + selected: _ctx.numMenuItems + index === _ctx.searchIndex + }]), + onMouseenter: function onMouseenter($event) { + return _ctx.searchIndex = _ctx.numMenuItems + index; + }, + onClick: function onClick($event) { + return _ctx.selectSite(site.idsite); + }, + key: site.idsite + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + textContent: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(site.name) + }, null, 8, QuickAccessvue_type_template_id_21ce66fa_hoisted_9)], 42, QuickAccessvue_type_template_id_21ce66fa_hoisted_8)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.hasSitesSelector && !_ctx.isLoading]]); + }), 128))]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("li", QuickAccessvue_type_template_id_21ce66fa_hoisted_10, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_HelpResources')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("li", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])([{ + selected: _ctx.searchIndex === 'help' + }, "quick-access-help"]), + onMouseenter: _cache[4] || (_cache[4] = function ($event) { + return _ctx.searchIndex = 'help'; + }) + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + href: "https://matomo.org?mtm_campaign=App_Help&mtm_source=Matomo_App&mtm_keyword=QuickSearch&s=".concat(encodeURIComponent(_ctx.searchTerm)), + target: "_blank" + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('CoreHome_SearchOnMatomo', _ctx.searchTerm)), 9, QuickAccessvue_type_template_id_21ce66fa_hoisted_11)], 34)])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.searchTerm && _ctx.searchActive]])], 512)), [[_directive_focus_anywhere_but_here, { + blur: _ctx.onBlur + }]]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue?vue&type=template&id=21ce66fa + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue?vue&type=script&lang=ts + + + + + + + + +function isElementInViewport(element) { + var rect = element.getBoundingClientRect(); + var $window = window.$(window); + return rect.top >= 0 && rect.left >= 0 && rect.bottom <= $window.height() && rect.right <= $window.width(); +} + +function scrollFirstElementIntoView(element) { + if (element && element.scrollIntoView) { + // make sure search is visible + element.scrollIntoView(); + } +} + +/* harmony default export */ var QuickAccessvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + directives: { + FocusAnywhereButHere: FocusAnywhereButHere, + FocusIf: FocusIf + }, + watch: { + searchActive: function searchActive(newValue) { + var root = this.$refs.root; + + if (!root || !root.parentElement) { + return; + } + + var classes = root.parentElement.classList; + classes.toggle('active', newValue); + classes.toggle('expanded', newValue); + } + }, + mounted: function mounted() { + var _this = this; + + var root = this.$refs.root; // TODO: temporary, remove after angularjs is removed. + // this is currently needed since angularjs will render a div, then vue will render a div + // within it, but the top controls and CSS expect to have certain CSS classes in the root + // element. + // same applies to above watch for searchActive() + + if (root && root.parentElement) { + root.parentElement.classList.add('quick-access', 'piwikSelector'); + } + + if (typeof window.initTopControls !== 'undefined' && window.initTopControls) { + window.initTopControls(); + } + + Matomo_Matomo.helper.registerShortcut('f', translate('CoreHome_ShortcutSearch'), function (event) { + if (event.altKey) { + return; + } + + event.preventDefault(); + scrollFirstElementIntoView(_this.$refs.root); + + _this.activateSearch(); + }); + }, + data: function data() { + var hasSegmentSelector = !!document.querySelector('.segmentEditorPanel'); + return { + menuItems: [], + numMenuItems: 0, + searchActive: false, + searchTerm: '', + searchIndex: 0, + menuIndexCounter: -1, + topMenuItems: null, + leftMenuItems: null, + segmentItems: null, + hasSegmentSelector: hasSegmentSelector, + sites: [], + isLoading: false + }; + }, + created: function created() { + this.searchMenu = debounce(this.searchMenu.bind(this)); + }, + computed: { + hasSitesSelector: function hasSitesSelector() { + return !!document.querySelector('.top_controls [piwik-siteselector]'); + }, + quickAccessTitle: function quickAccessTitle() { + var searchAreasTitle = ''; + var searchAreas = [translate('CoreHome_MenuEntries')]; + + if (this.hasSegmentSelector) { + searchAreas.push(translate('CoreHome_Segments')); + } + + if (this.hasSitesSelector) { + searchAreas.push(translate('SitesManager_Sites')); + } + + while (searchAreas.length) { + searchAreasTitle += searchAreas.shift(); + + if (searchAreas.length >= 2) { + searchAreasTitle += ', '; + } else if (searchAreas.length === 1) { + searchAreasTitle += " ".concat(translate('General_And'), " "); + } + } + + return translate('CoreHome_QuickAccessTitle', searchAreasTitle); + } + }, + emits: ['itemSelected', 'blur'], + methods: { + onKeypress: function onKeypress(event) { + var _this2 = this; + + var areSearchResultsDisplayed = this.searchTerm && this.searchActive; + var isTabKey = event.which === 9; + var isEscKey = event.which === 27; + + if (event.which === 38) { + this.highlightPreviousItem(); + event.preventDefault(); + } else if (event.which === 40) { + this.highlightNextItem(); + event.preventDefault(); + } else if (event.which === 13) { + this.clickQuickAccessMenuItem(); + } else if (isTabKey && areSearchResultsDisplayed) { + this.deactivateSearch(); + } else if (isEscKey && areSearchResultsDisplayed) { + this.deactivateSearch(); + } else { + setTimeout(function () { + _this2.searchActive = true; + + _this2.searchMenu(_this2.searchTerm); + }); + } + }, + highlightPreviousItem: function highlightPreviousItem() { + if (this.searchIndex - 1 < 0) { + this.searchIndex = 0; + } else { + this.searchIndex -= 1; + } + + this.makeSureSelectedItemIsInViewport(); + }, + highlightNextItem: function highlightNextItem() { + var numTotal = this.$refs.root.querySelectorAll('li.result').length; + + if (numTotal <= this.searchIndex + 1) { + this.searchIndex = numTotal - 1; + } else { + this.searchIndex += 1; + } + + this.makeSureSelectedItemIsInViewport(); + }, + clickQuickAccessMenuItem: function clickQuickAccessMenuItem() { + var _this3 = this; + + var selectedMenuElement = this.getCurrentlySelectedElement(); + + if (selectedMenuElement) { + setTimeout(function () { + selectedMenuElement.click(); + + _this3.$emit('itemSelected', selectedMenuElement); + }, 20); + } + }, + deactivateSearch: function deactivateSearch() { + this.searchTerm = ''; + this.searchActive = false; + + if (this.$refs.input) { + this.$refs.input.blur(); + } + }, + makeSureSelectedItemIsInViewport: function makeSureSelectedItemIsInViewport() { + var element = this.getCurrentlySelectedElement(); + + if (element && !isElementInViewport(element)) { + scrollFirstElementIntoView(element); + } + }, + getCurrentlySelectedElement: function getCurrentlySelectedElement() { + var results = this.$refs.root.querySelectorAll('li.result'); + + if (results && results.length && results.item(this.searchIndex)) { + return results.item(this.searchIndex); + } + + return undefined; + }, + searchMenu: function searchMenu(unprocessedSearchTerm) { + var _this4 = this; + + var searchTerm = unprocessedSearchTerm.toLowerCase(); + var index = -1; + var menuItemsIndex = {}; + var menuItems = []; + + var moveToCategory = function moveToCategory(theSubmenuItem) { + // force rerender of element to prevent weird side effects + var submenuItem = Object.assign({}, theSubmenuItem); // needed for proper highlighting with arrow keys + + index += 1; + submenuItem.menuIndex = index; + var category = submenuItem.category; + + if (!(category in menuItemsIndex)) { + menuItems.push({ + title: category, + items: [] + }); + menuItemsIndex[category] = menuItems.length - 1; + } + + var indexOfCategory = menuItemsIndex[category]; + menuItems[indexOfCategory].items.push(submenuItem); + }; + + this.resetSearchIndex(); + + if (this.hasSitesSelector) { + this.isLoading = true; + SiteSelector_SitesStore.searchSite(searchTerm).then(function (sites) { + if (sites) { + _this4.sites = sites; + } + }).finally(function () { + _this4.isLoading = false; + }); + } + + var menuItemMatches = function menuItemMatches(i) { + return i.name.toLowerCase().indexOf(searchTerm) !== -1 || i.category.toLowerCase().indexOf(searchTerm) !== -1; + }; // get the menu items on first search since this component can be mounted + // before the menus are + + + if (this.topMenuItems === null) { + this.topMenuItems = this.getTopMenuItems(); + } + + if (this.leftMenuItems === null) { + this.leftMenuItems = this.getLeftMenuItems(); + } + + if (this.segmentItems === null) { + this.segmentItems = this.getSegmentItems(); + } + + var topMenuItems = this.topMenuItems.filter(menuItemMatches); + var leftMenuItems = this.leftMenuItems.filter(menuItemMatches); + var segmentItems = this.segmentItems.filter(menuItemMatches); + topMenuItems.forEach(moveToCategory); + leftMenuItems.forEach(moveToCategory); + segmentItems.forEach(moveToCategory); + this.numMenuItems = topMenuItems.length + leftMenuItems.length + segmentItems.length; + this.menuItems = menuItems; + }, + resetSearchIndex: function resetSearchIndex() { + this.searchIndex = 0; + this.makeSureSelectedItemIsInViewport(); + }, + selectSite: function selectSite(idSite) { + SiteSelector_SitesStore.loadSite(idSite); + }, + selectMenuItem: function selectMenuItem(index) { + var target = document.querySelector("[quick_access='".concat(index, "']")); + + if (target) { + this.deactivateSearch(); + var href = target.getAttribute('href'); + + if (href && href.length > 10 && target && target.click) { + try { + target.click(); + } catch (e) { + window.$(target).click(); + } + } else { + // not sure why jquery is used here and above, but only sometimes. keeping for BC. + window.$(target).click(); + } + } + }, + onBlur: function onBlur() { + this.searchActive = false; + this.$emit('blur'); + }, + activateSearch: function activateSearch() { + this.searchActive = true; + }, + getTopMenuItems: function getTopMenuItems() { + var _this5 = this; + + var category = translate('CoreHome_Menu'); + var topMenuItems = []; + document.querySelectorAll('nav .sidenav li > a').forEach(function (element) { + var _element$textContent; + + var text = (_element$textContent = element.textContent) === null || _element$textContent === void 0 ? void 0 : _element$textContent.trim(); + + if (!text) { + var _element$getAttribute; + + text = (_element$getAttribute = element.getAttribute('title')) === null || _element$getAttribute === void 0 ? void 0 : _element$getAttribute.trim(); // possibly a icon, use title instead + } + + if (text) { + topMenuItems.push({ + name: text, + index: _this5.menuIndexCounter += 1, + category: category + }); + element.setAttribute('quick_access', "".concat(_this5.menuIndexCounter)); + } + }); + return topMenuItems; + }, + getLeftMenuItems: function getLeftMenuItems() { + var _this6 = this; + + var leftMenuItems = []; + document.querySelectorAll('#secondNavBar .menuTab').forEach(function (element) { + var _categoryElement$; + + var categoryElement = window.$(element).find('> .item'); + var category = ((_categoryElement$ = categoryElement[0]) === null || _categoryElement$ === void 0 ? void 0 : _categoryElement$.innerText.trim()) || ''; + + if (category && category.lastIndexOf('\n') !== -1) { + // remove "\n\nMenu" + category = category.slice(0, category.lastIndexOf('\n')).trim(); + } + + window.$(element).find('li .item').each(function (i, subElement) { + var _subElement$textConte; + + var text = (_subElement$textConte = subElement.textContent) === null || _subElement$textConte === void 0 ? void 0 : _subElement$textConte.trim(); + + if (text) { + leftMenuItems.push({ + name: text, + category: category, + index: _this6.menuIndexCounter += 1 + }); + subElement.setAttribute('quick_access', "".concat(_this6.menuIndexCounter)); + } + }); + }); + return leftMenuItems; + }, + getSegmentItems: function getSegmentItems() { + var _this7 = this; + + if (!this.hasSegmentSelector) { + return []; + } + + var category = translate('CoreHome_Segments'); + var segmentItems = []; + document.querySelectorAll('.segmentList [data-idsegment]').forEach(function (element) { + var _element$querySelecto, _element$querySelecto2; + + var text = (_element$querySelecto = element.querySelector('.segname')) === null || _element$querySelecto === void 0 ? void 0 : (_element$querySelecto2 = _element$querySelecto.textContent) === null || _element$querySelecto2 === void 0 ? void 0 : _element$querySelecto2.trim(); + + if (text) { + segmentItems.push({ + name: text, + category: category, + index: _this7.menuIndexCounter += 1 + }); + element.setAttribute('quick_access', "".concat(_this7.menuIndexCounter)); + } + }); + return segmentItems; + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue + + + +QuickAccessvue_type_script_lang_ts.render = QuickAccessvue_type_template_id_21ce66fa_render + +/* harmony default export */ var QuickAccess = (QuickAccessvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/QuickAccess/QuickAccess.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var QuickAccess_adapter = (createAngularJsAdapter({ + component: QuickAccess, + directiveName: 'piwikQuickAccess', + events: { + itemSelected: function itemSelected(event, vm, scope, elem, attrs, controller, $timeout) { + $timeout(); + }, + blur: function blur(event, vm, scope) { + setTimeout(function () { + return scope.$apply(); + }); + } + } +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/FieldArray/FieldArray.vue?vue&type=template&id=66b76384 +function FieldArrayvue_type_template_id_66b76384_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + + +var FieldArrayvue_type_template_id_66b76384_hoisted_1 = { + class: "fieldArray form-group" +}; +var FieldArrayvue_type_template_id_66b76384_hoisted_2 = { + key: 0, + class: "fieldUiControl" +}; +var FieldArrayvue_type_template_id_66b76384_hoisted_3 = ["onClick", "title"]; +function FieldArrayvue_type_template_id_66b76384_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FieldArrayvue_type_template_id_66b76384_hoisted_1, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.modelValue, function (item, index) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["fieldArrayTable multiple valign-wrapper", FieldArrayvue_type_template_id_66b76384_defineProperty({}, "fieldArrayTable".concat(index), true)]), + key: index + }, [_ctx.field.uiControl ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FieldArrayvue_type_template_id_66b76384_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + "full-width": true, + "model-value": item, + options: _ctx.field.availableValues, + "onUpdate:modelValue": function onUpdateModelValue($event) { + return _ctx.onEntryChange($event, index); + }, + placeholder: ' ', + uicontrol: _ctx.field.uiControl, + title: _ctx.field.title, + name: "".concat(_ctx.name, "-").concat(index), + "template-file": _ctx.field.templateFile, + component: _ctx.field.component + }, null, 8, ["model-value", "options", "onUpdate:modelValue", "uicontrol", "title", "name", "template-file", "component"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + onClick: function onClick($event) { + return _ctx.removeEntry(index); + }, + class: "icon-minus valign", + title: _ctx.translate('General_Remove') + }, null, 8, FieldArrayvue_type_template_id_66b76384_hoisted_3), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], index + 1 !== _ctx.modelValue.length]])], 2); + }), 128))]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FieldArray/FieldArray.vue?vue&type=template&id=66b76384 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/FieldArray/FieldArray.vue?vue&type=script&lang=ts +function FieldArrayvue_type_script_lang_ts_toConsumableArray(arr) { return FieldArrayvue_type_script_lang_ts_arrayWithoutHoles(arr) || FieldArrayvue_type_script_lang_ts_iterableToArray(arr) || FieldArrayvue_type_script_lang_ts_unsupportedIterableToArray(arr) || FieldArrayvue_type_script_lang_ts_nonIterableSpread(); } + +function FieldArrayvue_type_script_lang_ts_nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function FieldArrayvue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return FieldArrayvue_type_script_lang_ts_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return FieldArrayvue_type_script_lang_ts_arrayLikeToArray(o, minLen); } + +function FieldArrayvue_type_script_lang_ts_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } + +function FieldArrayvue_type_script_lang_ts_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return FieldArrayvue_type_script_lang_ts_arrayLikeToArray(arr); } + +function FieldArrayvue_type_script_lang_ts_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + + + // async since this is a a recursive component + +var Field = useExternalPluginComponent('CorePluginsAdmin', 'Field'); +/* harmony default export */ var FieldArrayvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ props: { - severity: { - type: String, - required: true + modelValue: Array, + name: String, + field: Object + }, + components: { + Field: Field + }, + emits: ['update:modelValue'], + watch: { + modelValue: function modelValue(newValue) { + this.checkEmptyModelValue(newValue); + } + }, + mounted: function mounted() { + this.checkEmptyModelValue(this.modelValue); + }, + methods: { + checkEmptyModelValue: function checkEmptyModelValue(newValue) { + // make sure there is always an empty new value + if (!newValue || !newValue.length || newValue.slice(-1)[0] !== '') { + this.$emit('update:modelValue', [].concat(FieldArrayvue_type_script_lang_ts_toConsumableArray(newValue || []), [''])); + } + }, + onEntryChange: function onEntryChange(newValue, index) { + var newArrayValue = FieldArrayvue_type_script_lang_ts_toConsumableArray(this.modelValue || []); + + newArrayValue[index] = newValue; + this.$emit('update:modelValue', newArrayValue); + }, + removeEntry: function removeEntry(index) { + if (index > -1 && this.modelValue) { + var newValue = this.modelValue.filter(function (x, i) { + return i !== index; + }); + this.$emit('update:modelValue', newValue); + } } } })); -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Alert/Alert.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FieldArray/FieldArray.vue?vue&type=script&lang=ts -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Alert/Alert.vue +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FieldArray/FieldArray.vue -Alertvue_type_script_lang_ts.render = Alertvue_type_template_id_c3863ae2_render +FieldArrayvue_type_script_lang_ts.render = FieldArrayvue_type_template_id_66b76384_render -/* harmony default export */ var Alert = (Alertvue_type_script_lang_ts); -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Alert/Alert.adapter.ts +/* harmony default export */ var FieldArray = (FieldArrayvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FieldArray/FieldArray.adapter.ts /*! * Matomo - free/libre analytics platform * @@ -4901,78 +7185,1109 @@ Alertvue_type_script_lang_ts.render = Alertvue_type_template_id_c3863ae2_render */ -/* harmony default export */ var Alert_adapter = (createAngularJsAdapter({ - component: Alert, +/* harmony default export */ var FieldArray_adapter = (createAngularJsAdapter({ + component: FieldArray, + require: '?ngModel', scope: { - severity: { - vue: 'severity', - angularJsBind: '@piwikAlert' + name: { + angularJsBind: '=' + }, + field: { + angularJsBind: '=' } }, - directiveName: 'piwikAlert', - transclude: true + directiveName: 'matomoFieldArray', + events: { + 'update:modelValue': function updateModelValue(newValue, vm, scope, element, attrs, ngModel) { + if (newValue !== vm.modelValue) { + element.trigger('change', newValue); + + if (ngModel) { + ngModel.$setViewValue(newValue); + } + } + } + }, + postCreate: function postCreate(vm, scope, element, attrs, controller) { + var ngModel = controller; // setup ng-model mapping + + if (ngModel) { + ngModel.$setViewValue(vm.modelValue); + + ngModel.$render = function () { + if (window.angular.isString(ngModel.$viewValue)) { + vm.modelValue = JSON.parse(ngModel.$viewValue); + } else { + vm.modelValue = ngModel.$viewValue; + } + }; + } + } })); -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/CookieHelper/CookieHelper.ts -/* - * General utils for managing cookies in Typescript. +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue?vue&type=template&id=b0d1c4e2 +function MultiPairFieldvue_type_template_id_b0d1c4e2_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + + +var MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_1 = { + class: "multiPairField form-group" +}; +var MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_2 = { + key: 1, + class: "fieldUiControl fieldUiControl2" +}; +var MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_3 = { + key: 2, + class: "fieldUiControl fieldUiControl3" +}; +var MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_4 = { + key: 3, + class: "fieldUiControl fieldUiControl4" +}; +var MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_5 = ["onClick", "title"]; +function MultiPairFieldvue_type_template_id_b0d1c4e2_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_1, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.modelValue, function (item, index) { + var _ref; + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["multiPairFieldTable multiple valign-wrapper", (_ref = {}, MultiPairFieldvue_type_template_id_b0d1c4e2_defineProperty(_ref, "multiPairFieldTable".concat(index), true), MultiPairFieldvue_type_template_id_b0d1c4e2_defineProperty(_ref, "has".concat(_ctx.fieldCount, "Fields"), true), _ref)]), + key: index + }, [_ctx.field1 ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + key: 0, + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["fieldUiControl fieldUiControl1", { + hasMultiFields: _ctx.field1.type && _ctx.field2.type + }]) + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + "full-width": true, + modelValue: item[_ctx.field1.key], + "onUpdate:modelValue": [function ($event) { + return item[_ctx.field1.key] = $event; + }, function ($event) { + return _ctx.onEntryChange(index, _ctx.field1.key, $event); + }], + options: _ctx.field1.availableValues, + placeholder: ' ', + uicontrol: _ctx.field1.uiControl, + name: "".concat(_ctx.name, "-p1-").concat(index), + title: _ctx.field1.title, + "template-file": _ctx.field1.templateFile, + component: _ctx.field1.component + }, null, 8, ["modelValue", "onUpdate:modelValue", "options", "uicontrol", "name", "title", "template-file", "component"])], 2)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.field2 ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + "full-width": true, + options: _ctx.field2.availableValues, + "onUpdate:modelValue": [function ($event) { + return _ctx.onEntryChange(index, _ctx.field2.key, $event); + }, function ($event) { + return item[_ctx.field2.key] = $event; + }], + modelValue: item[_ctx.field2.key], + placeholder: ' ', + uicontrol: _ctx.field2.uiControl, + name: "".concat(_ctx.name, "-p2-").concat(index), + title: _ctx.field2.title, + "template-file": _ctx.field2.templateFile, + component: _ctx.field2.component + }, null, 8, ["options", "onUpdate:modelValue", "modelValue", "uicontrol", "name", "title", "template-file", "component"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.field3 ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + "full-width": true, + options: _ctx.field3.availableValues, + "onUpdate:modelValue": [function ($event) { + return _ctx.onEntryChange(index, _ctx.field3.key, $event); + }, function ($event) { + return item[_ctx.field3.key] = $event; + }], + modelValue: item[_ctx.field3.key], + placeholder: ' ', + uicontrol: _ctx.field3.uiControl, + title: _ctx.field3.title, + "template-file": _ctx.field3.templateFile, + component: _ctx.field3.component + }, null, 8, ["options", "onUpdate:modelValue", "modelValue", "uicontrol", "title", "template-file", "component"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.field4 ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + "full-width": true, + options: _ctx.field4.availableValues, + "onUpdate:modelValue": [function ($event) { + return _ctx.onEntryChange(index, _ctx.field4.key, $event); + }, function ($event) { + return item[_ctx.field4.key] = $event; + }], + modelValue: item[_ctx.field4.key], + placeholder: ' ', + uicontrol: _ctx.field4.uiControl, + title: _ctx.field4.title, + "template-file": _ctx.field4.templateFile, + component: _ctx.field4.component + }, null, 8, ["options", "onUpdate:modelValue", "modelValue", "uicontrol", "title", "template-file", "component"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + onClick: function onClick($event) { + return _ctx.removeEntry(index); + }, + class: "icon-minus valign", + title: _ctx.translate('General_Remove') + }, null, 8, MultiPairFieldvue_type_template_id_b0d1c4e2_hoisted_5), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], index + 1 !== _ctx.modelValue.length]])], 2); + }), 128))]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue?vue&type=template&id=b0d1c4e2 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue?vue&type=script&lang=ts +function MultiPairFieldvue_type_script_lang_ts_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function MultiPairFieldvue_type_script_lang_ts_toConsumableArray(arr) { return MultiPairFieldvue_type_script_lang_ts_arrayWithoutHoles(arr) || MultiPairFieldvue_type_script_lang_ts_iterableToArray(arr) || MultiPairFieldvue_type_script_lang_ts_unsupportedIterableToArray(arr) || MultiPairFieldvue_type_script_lang_ts_nonIterableSpread(); } + +function MultiPairFieldvue_type_script_lang_ts_nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function MultiPairFieldvue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return MultiPairFieldvue_type_script_lang_ts_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return MultiPairFieldvue_type_script_lang_ts_arrayLikeToArray(o, minLen); } + +function MultiPairFieldvue_type_script_lang_ts_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } + +function MultiPairFieldvue_type_script_lang_ts_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return MultiPairFieldvue_type_script_lang_ts_arrayLikeToArray(arr); } + +function MultiPairFieldvue_type_script_lang_ts_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + + + // async since this is a a recursive component + +var MultiPairFieldvue_type_script_lang_ts_Field = useExternalPluginComponent('CorePluginsAdmin', 'Field'); +/* harmony default export */ var MultiPairFieldvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + modelValue: Array, + name: String, + field1: Object, + field2: Object, + field3: Object, + field4: Object + }, + components: { + Field: MultiPairFieldvue_type_script_lang_ts_Field + }, + computed: { + fieldCount: function fieldCount() { + if (this.field1 && this.field2 && this.field3 && this.field4) { + return 4; + } + + if (this.field1 && this.field2 && this.field3) { + return 3; + } + + if (this.field1 && this.field2) { + return 2; + } + + if (this.field1) { + return 1; + } + + return 0; + } + }, + emits: ['update:modelValue'], + watch: { + modelValue: function modelValue(newValue) { + this.checkEmptyModelValue(newValue); + } + }, + mounted: function mounted() { + this.checkEmptyModelValue(this.modelValue); + }, + methods: { + checkEmptyModelValue: function checkEmptyModelValue(newValue) { + // make sure there is always an empty new value + if (!newValue || !newValue.length || this.isEmptyValue(newValue.slice(-1)[0])) { + this.$emit('update:modelValue', [].concat(MultiPairFieldvue_type_script_lang_ts_toConsumableArray(newValue || []), [this.makeEmptyValue()])); + } + }, + onEntryChange: function onEntryChange(index, key, newValue) { + var newWholeValue = MultiPairFieldvue_type_script_lang_ts_toConsumableArray(this.modelValue); + + newWholeValue[index] = Object.assign(Object.assign({}, newWholeValue[index]), {}, MultiPairFieldvue_type_script_lang_ts_defineProperty({}, key, newValue)); + this.$emit('update:modelValue', newWholeValue); + }, + removeEntry: function removeEntry(index) { + if (index > -1 && this.modelValue) { + var newValue = this.modelValue.filter(function (x, i) { + return i !== index; + }); + this.$emit('update:modelValue', newValue); + } + }, + isEmptyValue: function isEmptyValue(value) { + var fieldCount = this.fieldCount; + + if (fieldCount === 4) { + if (!value[this.field1.key] && !value[this.field2.key] && !value[this.field3.key] && !value[this.field4.key]) { + return false; + } + } else if (fieldCount === 3) { + if (!value[this.field1.key] && !value[this.field2.key] && !value[this.field3.key]) { + return false; + } + } else if (fieldCount === 2) { + if (!value[this.field1.key] && !value[this.field2.key]) { + return false; + } + } else if (fieldCount === 1) { + if (!value[this.field1.key]) { + return false; + } + } + + return true; + }, + makeEmptyValue: function makeEmptyValue() { + var result = {}; + + if (this.field1 && this.field1.key) { + result[this.field1.key] = ''; + } + + if (this.field2 && this.field2.key) { + result[this.field2.key] = ''; + } + + if (this.field3 && this.field3.key) { + result[this.field3.key] = ''; + } + + if (this.field4 && this.field4.key) { + result[this.field4.key] = ''; + } + + return result; + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue + + + +MultiPairFieldvue_type_script_lang_ts.render = MultiPairFieldvue_type_template_id_b0d1c4e2_render + +/* harmony default export */ var MultiPairField = (MultiPairFieldvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MultiPairField/MultiPairField.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -function setCookie(name, val, seconds) { - var date = new Date(); // set default day to 3 days - if (!seconds) { - // eslint-disable-next-line no-param-reassign - seconds = 3 * 24 * 60 * 1000; - } // Set it expire in n days +/* harmony default export */ var MultiPairField_adapter = (createAngularJsAdapter({ + component: MultiPairField, + require: '?ngModel', + scope: { + name: { + angularJsBind: '=' + }, + field1: { + angularJsBind: '=' + }, + field2: { + angularJsBind: '=' + }, + field3: { + angularJsBind: '=' + }, + field4: { + angularJsBind: '=' + } + }, + directiveName: 'matomoMultiPairField', + events: { + 'update:modelValue': function updateModelValue(newValue, vm, scope, element, attrs, ngModel) { + if (newValue !== vm.modelValue) { + element.trigger('change', newValue); + + if (ngModel) { + ngModel.$setViewValue(newValue); + } + } + } + }, + postCreate: function postCreate(vm, scope, element, attrs, controller) { + var ngModel = controller; // setup ng-model mapping - date.setTime(date.getTime() + seconds); // Set it + if (ngModel) { + ngModel.$setViewValue(vm.modelValue); - document.cookie = "".concat(name, "=").concat(val, "; expires=").concat(date.toUTCString(), "; path=/"); -} // eslint-disable-next-line consistent-return,@typescript-eslint/explicit-module-boundary-types + ngModel.$render = function () { + if (window.angular.isString(ngModel.$viewValue)) { + vm.modelValue = JSON.parse(ngModel.$viewValue); + } else { + vm.modelValue = ngModel.$viewValue; + } + }; + } + } +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue?vue&type=template&id=0115e905 -function getCookie(name) { - var value = "; ".concat(document.cookie); - var parts = value.split("; ".concat(name, "=")); // if cookie not exist return null - // eslint-disable-next-line eqeqeq +var PeriodSelectorvue_type_template_id_0115e905_hoisted_1 = { + ref: "root", + class: "periodSelector piwikSelector" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_2 = ["title"]; - if (parts.length == 2) { - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - var data = parts.pop().split(';').shift(); +var PeriodSelectorvue_type_template_id_0115e905_hoisted_3 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: "icon icon-calendar" +}, null, -1); - if (typeof data !== 'undefined') { - return data; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_4 = { + id: "periodMore", + class: "dropdown" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_5 = { + class: "flex" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_6 = { + key: 0, + class: "period-date" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_7 = { + class: "period-type" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_8 = { + id: "otherPeriods" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_9 = ["onDblclick", "title"]; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_10 = ["id", "checked", "onChange", "onDblclick"]; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_11 = { + key: 0, + class: "compare-checkbox" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_12 = { + id: "comparePeriodToDropdown" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_13 = { + key: 1, + class: "compare-date-range" +}; +var PeriodSelectorvue_type_template_id_0115e905_hoisted_14 = { + id: "comparePeriodStartDate" +}; + +var PeriodSelectorvue_type_template_id_0115e905_hoisted_15 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: "compare-dates-separator" +}, null, -1); + +var _hoisted_16 = { + id: "comparePeriodEndDate" +}; +var _hoisted_17 = { + class: "apply-button-container" +}; +var _hoisted_18 = ["disabled", "value"]; +var _hoisted_19 = { + key: 2, + id: "ajaxLoadingCalendar" +}; +var _hoisted_20 = { + class: "loadingSegment" +}; +function PeriodSelectorvue_type_template_id_0115e905_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_DateRangePicker = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("DateRangePicker"); + + var _component_PeriodDatePicker = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("PeriodDatePicker"); + + var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field"); + + var _component_ActivityIndicator = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ActivityIndicator"); + + var _directive_expand_on_click = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("expand-on-click"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + ref: "title", + id: "date", + class: "title", + tabindex: "-1", + title: _ctx.translate('General_ChooseDate', _ctx.currentlyViewingText) + }, [PeriodSelectorvue_type_template_id_0115e905_hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.currentlyViewingText), 1)], 8, PeriodSelectorvue_type_template_id_0115e905_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_DateRangePicker, { + class: "period-range", + "start-date": _ctx.startRangeDate, + "end-date": _ctx.endRangeDate, + onRangeChange: _cache[0] || (_cache[0] = function ($event) { + return _ctx.onRangeChange($event.start, $event.end); + }), + onSubmit: _cache[1] || (_cache[1] = function ($event) { + return _ctx.onApplyClicked(); + }) + }, null, 8, ["start-date", "end-date"]), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.selectedPeriod === 'range']]), _ctx.selectedPeriod !== 'range' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_PeriodDatePicker, { + id: "datepicker", + period: _ctx.selectedPeriod, + date: _ctx.periodValue === _ctx.selectedPeriod ? _ctx.dateValue : null, + onSelect: _cache[2] || (_cache[2] = function ($event) { + return _ctx.setPiwikPeriodAndDate(_ctx.selectedPeriod, $event.date); + }) + }, null, 8, ["period", "date"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_7, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h6", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Period')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_8, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.periodsFiltered, function (period) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", { + key: period + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])({ + 'selected-period-label': period === _ctx.selectedPeriod + }), + onDblclick: function onDblclick($event) { + return _ctx.changeViewedPeriod(period); + }, + title: period === _ctx.periodValue ? '' : _ctx.translate('General_DoubleClickToChangePeriod') + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + type: "radio", + name: "period", + id: "period_id_".concat(period), + "onUpdate:modelValue": _cache[3] || (_cache[3] = function ($event) { + return _ctx.selectedPeriod = $event; + }), + checked: _ctx.selectedPeriod === period, + onChange: function onChange($event) { + return _ctx.selectedPeriod = period; + }, + onDblclick: function onDblclick($event) { + return _ctx.changeViewedPeriod(period); + } + }, null, 40, PeriodSelectorvue_type_template_id_0115e905_hoisted_10), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelRadio"], _ctx.selectedPeriod]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.getPeriodDisplayText(period)), 1)], 42, PeriodSelectorvue_type_template_id_0115e905_hoisted_9)]); + }), 128))])])]), _ctx.isComparisonEnabled ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_11, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + id: "comparePeriodTo", + type: "checkbox", + "onUpdate:modelValue": _cache[4] || (_cache[4] = function ($event) { + return _ctx.isComparing = $event; + }) + }, null, 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelCheckbox"], _ctx.isComparing]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_CompareTo')), 1)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_12, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + modelValue: _ctx.comparePeriodType, + "onUpdate:modelValue": _cache[5] || (_cache[5] = function ($event) { + return _ctx.comparePeriodType = $event; + }), + style: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeStyle"])({ + 'visibility': _ctx.isComparing ? 'visible' : 'hidden' + }), + name: 'comparePeriodToDropdown', + uicontrol: 'select', + options: _ctx.comparePeriodDropdownOptions, + "full-width": true, + disabled: !_ctx.isComparing + }, null, 8, ["modelValue", "style", "options", "disabled"])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.isComparing && _ctx.comparePeriodType === 'custom' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_13, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PeriodSelectorvue_type_template_id_0115e905_hoisted_14, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + modelValue: _ctx.compareStartDate, + "onUpdate:modelValue": _cache[6] || (_cache[6] = function ($event) { + return _ctx.compareStartDate = $event; + }), + name: 'comparePeriodStartDate', + uicontrol: 'text', + "full-width": true, + title: _ctx.translate('CoreHome_StartDate'), + placeholder: 'YYYY-MM-DD' + }, null, 8, ["modelValue", "title"])])]), PeriodSelectorvue_type_template_id_0115e905_hoisted_15, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_16, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + modelValue: _ctx.compareEndDate, + "onUpdate:modelValue": _cache[7] || (_cache[7] = function ($event) { + return _ctx.compareEndDate = $event; + }), + name: 'comparePeriodEndDate', + uicontrol: 'text', + "full-width": true, + title: _ctx.translate('CoreHome_EndDate'), + placeholder: 'YYYY-MM-DD' + }, null, 8, ["modelValue", "title"])])])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_17, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", { + type: "submit", + id: "calendarApply", + class: "btn", + onClick: _cache[8] || (_cache[8] = function ($event) { + return _ctx.onApplyClicked(); + }), + disabled: !_ctx.isApplyEnabled(), + value: _ctx.translate('General_Apply') + }, null, 8, _hoisted_18)]), _ctx.isLoadingNewPage ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_19, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, { + loading: true + }), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_20, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('SegmentEditor_LoadingSegmentedDataMayTakeSomeTime')), 1)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])], 512)), [[_directive_expand_on_click, { + expander: 'title' + }]]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue?vue&type=template&id=0115e905 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=template&id=7c5fe406 + +var ActivityIndicatorvue_type_template_id_7c5fe406_hoisted_1 = { + class: "loadingPiwik" +}; + +var ActivityIndicatorvue_type_template_id_7c5fe406_hoisted_2 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { + src: "plugins/Morpheus/images/loading-blue.gif", + alt: "" +}, null, -1); + +function ActivityIndicatorvue_type_template_id_7c5fe406_render(_ctx, _cache, $props, $setup, $data, $options) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ActivityIndicatorvue_type_template_id_7c5fe406_hoisted_1, [ActivityIndicatorvue_type_template_id_7c5fe406_hoisted_2, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.loadingMessage), 1)], 512)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.loading]]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=template&id=7c5fe406 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=script&lang=ts + + +/* harmony default export */ var ActivityIndicatorvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + loading: { + type: Boolean, + required: true, + default: false + }, + loadingMessage: { + type: String, + required: false, + default: translate('General_LoadingData') } } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue - return null; -} // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -function deleteCookie(name) { - var date = new Date(); // Set it expire in -1 days - date.setTime(date.getTime() + -1 * 24 * 60 * 60 * 1000); // Set it +ActivityIndicatorvue_type_script_lang_ts.render = ActivityIndicatorvue_type_template_id_7c5fe406_render - document.cookie = "".concat(name, "=; expires=").concat(date.toUTCString(), "; path=/"); +/* harmony default export */ var ActivityIndicator = (ActivityIndicatorvue_type_script_lang_ts); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue?vue&type=script&lang=ts +function PeriodSelectorvue_type_script_lang_ts_slicedToArray(arr, i) { return PeriodSelectorvue_type_script_lang_ts_arrayWithHoles(arr) || PeriodSelectorvue_type_script_lang_ts_iterableToArrayLimit(arr, i) || PeriodSelectorvue_type_script_lang_ts_unsupportedIterableToArray(arr, i) || PeriodSelectorvue_type_script_lang_ts_nonIterableRest(); } + +function PeriodSelectorvue_type_script_lang_ts_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function PeriodSelectorvue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return PeriodSelectorvue_type_script_lang_ts_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return PeriodSelectorvue_type_script_lang_ts_arrayLikeToArray(o, minLen); } + +function PeriodSelectorvue_type_script_lang_ts_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function PeriodSelectorvue_type_script_lang_ts_iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function PeriodSelectorvue_type_script_lang_ts_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + + + + + + + + + + + + +var PeriodSelectorvue_type_script_lang_ts_Field = useExternalPluginComponent('CorePluginsAdmin', 'Field'); +var NBSP = Matomo_Matomo.helper.htmlDecode(' '); +var COMPARE_PERIOD_OPTIONS = [{ + key: 'custom', + value: translate('General_Custom') +}, { + key: 'previousPeriod', + value: translate('General_PreviousPeriod').replace(/\s+/, NBSP) +}, { + key: 'previousYear', + value: translate('General_PreviousYear').replace(/\s+/, NBSP) +}]; +var PeriodSelectorvue_type_script_lang_ts_piwikMinDate = new Date(Matomo_Matomo.minDateYear, Matomo_Matomo.minDateMonth - 1, Matomo_Matomo.minDateDay); +var PeriodSelectorvue_type_script_lang_ts_piwikMaxDate = new Date(Matomo_Matomo.maxDateYear, Matomo_Matomo.maxDateMonth - 1, Matomo_Matomo.maxDateDay); + +function isValidDate(d) { + if (Object.prototype.toString.call(d) !== '[object Date]') { + return false; + } + + return !Number.isNaN(d.getTime()); } -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=template&id=e3d12348 -var Notificationvue_type_template_id_e3d12348_hoisted_1 = { +/* harmony default export */ var PeriodSelectorvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + periods: Array + }, + components: { + DateRangePicker: DateRangePicker, + PeriodDatePicker: PeriodDatePicker, + Field: PeriodSelectorvue_type_script_lang_ts_Field, + ActivityIndicator: ActivityIndicator + }, + directives: { + ExpandOnClick: ExpandOnClick + }, + data: function data() { + var selectedPeriod = src_MatomoUrl_MatomoUrl.parsed.value.period; + return { + comparePeriodDropdownOptions: COMPARE_PERIOD_OPTIONS, + periodValue: selectedPeriod, + dateValue: null, + selectedPeriod: selectedPeriod, + startRangeDate: null, + endRangeDate: null, + isRangeValid: null, + isLoadingNewPage: false, + isComparing: null, + comparePeriodType: 'previousPeriod', + compareStartDate: '', + compareEndDate: '' + }; + }, + mounted: function mounted() { + var _this = this; + + Matomo_Matomo.on('hidePeriodSelector', function () { + window.$(_this.$refs.root).hide(); + }); // some widgets might hide the period selector using the event above, so ensure it's + // shown again when switching the page + + Matomo_Matomo.on('piwikPageChange', function () { + window.$(_this.$refs.root).show(); + }); + this.updateSelectedValuesFromHash(); + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () { + return src_MatomoUrl_MatomoUrl.parsed.value; + }, this.updateSelectedValuesFromHash); + this.isComparing = Comparisons_store_instance.isComparingPeriods(); + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () { + return Comparisons_store_instance.isComparingPeriods(); + }, function (newVal) { + _this.isComparing = newVal; + }); + window.initTopControls(); // must be called when a top control changes width + + this.handleZIndexPositionRelativeCompareDropdownIssue(); + }, + computed: { + currentlyViewingText: function currentlyViewingText() { + var date; + + if (this.periodValue === 'range') { + if (!this.startRangeDate || !this.endRangeDate) { + return translate('General_Error'); + } + + date = "".concat(this.startRangeDate, ",").concat(this.endRangeDate); + } else { + if (!this.dateValue) { + return translate('General_Error'); + } + + date = format(this.dateValue); + } + + try { + return Periods_Periods.parse(this.periodValue, date).getPrettyString(); + } catch (e) { + return translate('General_Error'); + } + }, + isComparisonEnabled: function isComparisonEnabled() { + return Comparisons_store_instance.isComparisonEnabled(); + }, + periodsFiltered: function periodsFiltered() { + return (this.periods || []).filter(function (periodLabel) { + return Periods_Periods.isRecognizedPeriod(periodLabel); + }); + }, + selectedComparisonParams: function selectedComparisonParams() { + if (!this.isComparing) { + return {}; + } + + if (this.comparePeriodType === 'custom') { + return { + comparePeriods: ['range'], + compareDates: ["".concat(this.compareStartDate, ",").concat(this.compareEndDate)] + }; + } + + if (this.comparePeriodType === 'previousPeriod') { + return { + comparePeriods: [this.selectedPeriod], + compareDates: [this.previousPeriodDateToSelectedPeriod] + }; + } + + if (this.comparePeriodType === 'previousYear') { + var dateStr = this.selectedPeriod === 'range' ? "".concat(this.startRangeDate, ",").concat(this.endRangeDate) : format(this.dateValue); + var currentDateRange = Periods_Periods.parse(this.selectedPeriod, dateStr).getDateRange(); + currentDateRange[0].setFullYear(currentDateRange[0].getFullYear() - 1); + currentDateRange[1].setFullYear(currentDateRange[1].getFullYear() - 1); + + if (this.selectedPeriod === 'range') { + return { + comparePeriods: ['range'], + compareDates: ["".concat(format(currentDateRange[0]), ",").concat(format(currentDateRange[1]))] + }; + } + + return { + comparePeriods: [this.selectedPeriod], + compareDates: [format(currentDateRange[0])] + }; + } + + console.warn("Unknown compare period type: ".concat(this.comparePeriodType)); + return {}; + }, + previousPeriodDateToSelectedPeriod: function previousPeriodDateToSelectedPeriod() { + if (this.selectedPeriod === 'range') { + var currentStartRange = parseDate(this.startRangeDate); + var currentEndRange = parseDate(this.endRangeDate); + var newEndDate = Range_RangePeriod.getLastNRange('day', 2, currentStartRange).startDate; + var rangeSize = Math.floor((currentEndRange.valueOf() - currentStartRange.valueOf()) / 86400000); + var newRange = Range_RangePeriod.getLastNRange('day', 1 + rangeSize, newEndDate); + return "".concat(format(newRange.startDate), ",").concat(format(newRange.endDate)); + } + + var newStartDate = Range_RangePeriod.getLastNRange(this.selectedPeriod, 2, this.dateValue).startDate; + return format(newStartDate); + }, + selectedDateString: function selectedDateString() { + if (this.selectedPeriod === 'range') { + var dateFrom = this.startRangeDate; + var dateTo = this.endRangeDate; + var oDateFrom = parseDate(dateFrom); + var oDateTo = parseDate(dateTo); + + if (!isValidDate(oDateFrom) || !isValidDate(oDateTo) || oDateFrom > oDateTo) { + // TODO: use a notification instead? + window.$('#alert').find('h2').text(translate('General_InvalidDateRange')); + Matomo_Matomo.helper.modalConfirm('#alert', {}); + return null; + } + + return "".concat(dateFrom, ",").concat(dateTo); + } + + return format(this.dateValue); + } + }, + methods: { + handleZIndexPositionRelativeCompareDropdownIssue: function handleZIndexPositionRelativeCompareDropdownIssue() { + var $element = window.$(this.$refs.root); + $element.on('focus', '#comparePeriodToDropdown .select-dropdown', function () { + $element.addClass('compare-dropdown-open'); + }).on('blur', '#comparePeriodToDropdown .select-dropdown', function () { + $element.removeClass('compare-dropdown-open'); + }); + }, + changeViewedPeriod: function changeViewedPeriod(period) { + // only change period if it's different from what's being shown currently + if (period === this.periodValue) { + return; + } // can't just change to a range period, w/o setting two new dates + + + if (period === 'range') { + return; + } + + this.setPiwikPeriodAndDate(period, this.dateValue); + }, + setPiwikPeriodAndDate: function setPiwikPeriodAndDate(period, date) { + this.periodValue = period; + this.selectedPeriod = period; + this.dateValue = date; + var currentDateString = format(date); + this.setRangeStartEndFromPeriod(period, currentDateString); + this.propagateNewUrlParams(currentDateString, this.selectedPeriod); + window.initTopControls(); + }, + propagateNewUrlParams: function propagateNewUrlParams(date, period) { + var compareParams = this.selectedComparisonParams; + var baseParams; + + if (Matomo_Matomo.helper.isAngularRenderingThePage()) { + this.closePeriodSelector(); + baseParams = src_MatomoUrl_MatomoUrl.hashParsed.value; + } else { + this.isLoadingNewPage = true; + baseParams = src_MatomoUrl_MatomoUrl.parsed.value; + } // get params without comparePeriods/compareSegments/compareDates + + + var paramsWithoutCompare = Object.assign({}, baseParams); + delete paramsWithoutCompare.comparePeriods; + delete paramsWithoutCompare.compareDates; + src_MatomoUrl_MatomoUrl.updateLocation(Object.assign(Object.assign({}, paramsWithoutCompare), {}, { + date: date, + period: period + }, compareParams)); + }, + onApplyClicked: function onApplyClicked() { + if (this.selectedPeriod === 'range') { + var dateString = this.selectedDateString; + + if (!dateString) { + return; + } + + this.periodValue = 'range'; + this.propagateNewUrlParams(dateString, 'range'); + return; + } + + this.setPiwikPeriodAndDate(this.selectedPeriod, this.dateValue); + }, + updateSelectedValuesFromHash: function updateSelectedValuesFromHash() { + var date = src_MatomoUrl_MatomoUrl.parsed.value.date; + var period = src_MatomoUrl_MatomoUrl.parsed.value.period; + this.periodValue = period; + this.selectedPeriod = period; + this.dateValue = null; + this.startRangeDate = null; + this.endRangeDate = null; + + try { + Periods_Periods.parse(period, date); + } catch (e) { + return; + } + + if (period === 'range') { + var periodObj = Periods_Periods.get(period).parse(date); + + var _periodObj$getDateRan = periodObj.getDateRange(), + _periodObj$getDateRan2 = PeriodSelectorvue_type_script_lang_ts_slicedToArray(_periodObj$getDateRan, 2), + startDate = _periodObj$getDateRan2[0], + endDate = _periodObj$getDateRan2[1]; + + this.dateValue = startDate; + this.startRangeDate = format(startDate); + this.endRangeDate = format(endDate); + } else { + this.dateValue = parseDate(date); + this.setRangeStartEndFromPeriod(period, date); + } + }, + setRangeStartEndFromPeriod: function setRangeStartEndFromPeriod(period, dateStr) { + var dateRange = Periods_Periods.parse(period, dateStr).getDateRange(); + this.startRangeDate = format(dateRange[0] < PeriodSelectorvue_type_script_lang_ts_piwikMinDate ? PeriodSelectorvue_type_script_lang_ts_piwikMinDate : dateRange[0]); + this.endRangeDate = format(dateRange[1] > PeriodSelectorvue_type_script_lang_ts_piwikMaxDate ? PeriodSelectorvue_type_script_lang_ts_piwikMaxDate : dateRange[1]); + }, + getPeriodDisplayText: function getPeriodDisplayText(periodLabel) { + return Periods_Periods.get(periodLabel).getDisplayText(); + }, + onRangeChange: function onRangeChange(start, end) { + if (!start || !end) { + this.isRangeValid = false; + return; + } + + this.isRangeValid = true; + this.startRangeDate = start; + this.endRangeDate = end; + }, + isApplyEnabled: function isApplyEnabled() { + if (this.selectedPeriod === 'range' && !this.isRangeValid) { + return false; + } + + if (this.isComparing && this.comparePeriodType === 'custom' && !this.isCompareRangeValid()) { + return false; + } + + return true; + }, + closePeriodSelector: function closePeriodSelector() { + this.$refs.root.classList.remove('expanded'); + }, + isCompareRangeValid: function isCompareRangeValid() { + try { + parseDate(this.compareStartDate); + } catch (e) { + return false; + } + + try { + parseDate(this.compareEndDate); + } catch (e) { + return false; + } + + return true; + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue + + + +PeriodSelectorvue_type_script_lang_ts.render = PeriodSelectorvue_type_template_id_0115e905_render + +/* harmony default export */ var PeriodSelector = (PeriodSelectorvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var PeriodSelector_adapter = (createAngularJsAdapter({ + component: PeriodSelector, + scope: { + periods: { + angularJsBind: '<' + } + }, + directiveName: 'piwikPeriodSelector' +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue?vue&type=template&id=0f6008b2 + +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_1 = { + class: "reportingMenu" +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_2 = ["aria-label"]; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_3 = ["onClick"]; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_4 = { + class: "hidden" +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_5 = { + role: "menu" +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_6 = ["href", "onClick", "title"]; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_7 = ["href", "onClick"]; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_8 = ["onClick"]; + +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_9 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: "icon-help" +}, null, -1); + +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_10 = [ReportingMenuvue_type_template_id_0f6008b2_hoisted_9]; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_11 = { + id: "mobile-left-menu", + class: "sidenav hide-on-large-only" +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_12 = { + class: "collapsible collapsible-accordion" +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_13 = { + class: "collapsible-header" +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_14 = { + class: "collapsible-body" +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_15 = { + key: 0 +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_16 = ["onClick", "href"]; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_17 = { + key: 1 +}; +var ReportingMenuvue_type_template_id_0f6008b2_hoisted_18 = ["onClick", "href"]; +function ReportingMenuvue_type_template_id_0f6008b2_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_MenuItemsDropdown = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("MenuItemsDropdown"); + + var _directive_side_nav = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("side-nav"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ReportingMenuvue_type_template_id_0f6008b2_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", { + class: "navbar hide-on-med-and-down", + role: "menu", + "aria-label": _ctx.translate('CoreHome_MainNavigation') + }, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.menu, function (category) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["menuTab", { + 'active': category.id === _ctx.activeCategory + }]), + role: "menuitem", + key: category.id + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + class: "item", + tabindex: "5", + href: "", + onClick: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withModifiers"])(function ($event) { + return _ctx.loadCategory(category); + }, ["prevent"]) + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])("menu-icon ".concat(category.icon ? category.icon : 'icon-arrow-right')) + }, null, 2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(category.name) + " ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", ReportingMenuvue_type_template_id_0f6008b2_hoisted_4, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('CoreHome_Menu')), 1)], 8, ReportingMenuvue_type_template_id_0f6008b2_hoisted_3), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", ReportingMenuvue_type_template_id_0f6008b2_hoisted_5, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(category.subcategories, function (subcategory) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", { + role: "menuitem", + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])({ + 'active': (subcategory.id === _ctx.displayedSubcategory || subcategory.isGroup && _ctx.activeSubsubcategory === _ctx.displayedSubcategory) && category.id === _ctx.displayedCategory + }), + key: subcategory.id + }, [subcategory.isGroup ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_MenuItemsDropdown, { + key: 0, + "show-search": true, + "menu-title": _ctx.htmlEntities(subcategory.name) + }, { + default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () { + return [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(subcategory.subcategories, function (subcat) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["item", { + active: subcat.id === _ctx.activeSubsubcategory && subcategory.id === _ctx.displayedSubcategory && category.id === _ctx.displayedCategory + }]), + tabindex: "5", + href: "#?".concat(_ctx.makeUrl(category, subcat)), + onClick: function onClick($event) { + return _ctx.loadSubcategory(category, subcat, $event); + }, + title: subcat.tooltip, + key: subcat.id + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(subcat.name), 11, ReportingMenuvue_type_template_id_0f6008b2_hoisted_6); + }), 128))]; + }), + _: 2 + }, 1032, ["menu-title"])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !subcategory.isGroup ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { + key: 1, + href: "#?".concat(_ctx.makeUrl(category, subcategory)), + class: "item", + onClick: function onClick($event) { + return _ctx.loadSubcategory(category, subcategory, $event); + } + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(subcategory.name), 9, ReportingMenuvue_type_template_id_0f6008b2_hoisted_7)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), subcategory.help ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { + key: 2, + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["item-help-icon", { + active: _ctx.helpShownCategory && _ctx.helpShownCategory.subcategory === subcategory.id && _ctx.helpShownCategory.category === category.id && subcategory.help + }]), + tabindex: "5", + href: "javascript:", + onClick: function onClick($event) { + return _ctx.showHelp(category, subcategory, $event); + } + }, ReportingMenuvue_type_template_id_0f6008b2_hoisted_10, 10, ReportingMenuvue_type_template_id_0f6008b2_hoisted_8)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 2); + }), 128))])], 2); + }), 128))], 8, ReportingMenuvue_type_template_id_0f6008b2_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", ReportingMenuvue_type_template_id_0f6008b2_hoisted_11, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.menu, function (category) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", { + class: "no-padding", + key: category.id + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", ReportingMenuvue_type_template_id_0f6008b2_hoisted_12, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("li", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", ReportingMenuvue_type_template_id_0f6008b2_hoisted_13, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("i", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(category.icon ? category.icon : 'icon-arrow-bottom') + }, null, 2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(category.name), 1)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportingMenuvue_type_template_id_0f6008b2_hoisted_14, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", null, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(category.subcategories, function (subcategory) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", { + key: subcategory.id + }, [subcategory.isGroup ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", ReportingMenuvue_type_template_id_0f6008b2_hoisted_15, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(subcategory.subcategories, function (subcat) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", { + onClick: function onClick($event) { + return _ctx.loadSubcategory(category, subcat); + }, + href: "#?".concat(_ctx.makeUrl(category, subcat)), + key: subcat.id + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(subcat.name), 9, ReportingMenuvue_type_template_id_0f6008b2_hoisted_16); + }), 128))])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !subcategory.isGroup ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", ReportingMenuvue_type_template_id_0f6008b2_hoisted_17, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + onClick: function onClick($event) { + return _ctx.loadSubcategory(category, subcategory); + }, + href: "#?".concat(_ctx.makeUrl(category, subcategory)) + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(subcategory.name), 9, ReportingMenuvue_type_template_id_0f6008b2_hoisted_18)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]); + }), 128))])])])], 512), [[_directive_side_nav, { + activator: _ctx.sideNavActivator + }]])]); + }), 128))])]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue?vue&type=template&id=0f6008b2 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=template&id=52166f8a + +var Notificationvue_type_template_id_52166f8a_hoisted_1 = { key: 0 }; -var Notificationvue_type_template_id_e3d12348_hoisted_2 = ["data-notification-instance-id"]; -var Notificationvue_type_template_id_e3d12348_hoisted_3 = { +var Notificationvue_type_template_id_52166f8a_hoisted_2 = ["data-notification-instance-id"]; +var Notificationvue_type_template_id_52166f8a_hoisted_3 = { key: 1 }; -var Notificationvue_type_template_id_e3d12348_hoisted_4 = { +var Notificationvue_type_template_id_52166f8a_hoisted_4 = { class: "notification-body" }; -var Notificationvue_type_template_id_e3d12348_hoisted_5 = ["innerHTML"]; -var Notificationvue_type_template_id_e3d12348_hoisted_6 = { +var Notificationvue_type_template_id_52166f8a_hoisted_5 = ["innerHTML"]; +var Notificationvue_type_template_id_52166f8a_hoisted_6 = { key: 1 }; -function Notificationvue_type_template_id_e3d12348_render(_ctx, _cache, $props, $setup, $data, $options) { +function Notificationvue_type_template_id_52166f8a_render(_ctx, _cache, $props, $setup, $data, $options) { return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Transition"], { name: _ctx.type === 'toast' ? 'slow-fade-out' : undefined, onAfterLeave: _cache[1] || (_cache[1] = function ($event) { @@ -4980,7 +8295,7 @@ function Notificationvue_type_template_id_e3d12348_render(_ctx, _cache, $props, }) }, { default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () { - return [!_ctx.deleted ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Notificationvue_type_template_id_e3d12348_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Transition"], { + return [!_ctx.deleted ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Notificationvue_type_template_id_52166f8a_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Transition"], { name: _ctx.type === 'toast' ? 'toast-slide-up' : undefined, appear: "" }, { @@ -5003,10 +8318,10 @@ function Notificationvue_type_template_id_e3d12348_render(_ctx, _cache, $props, onClick: _cache[0] || (_cache[0] = function ($event) { return _ctx.closeNotification($event); }) - }, " × ")) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.title ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("strong", Notificationvue_type_template_id_e3d12348_hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.title), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Notificationvue_type_template_id_e3d12348_hoisted_4, [_ctx.message ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + }, " × ")) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.title ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("strong", Notificationvue_type_template_id_52166f8a_hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.title), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Notificationvue_type_template_id_52166f8a_hoisted_4, [_ctx.message ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { key: 0, innerHTML: _ctx.$sanitize(_ctx.message) - }, null, 8, Notificationvue_type_template_id_e3d12348_hoisted_5)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !_ctx.message ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Notificationvue_type_template_id_e3d12348_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])], 14, Notificationvue_type_template_id_e3d12348_hoisted_2)]; + }, null, 8, Notificationvue_type_template_id_52166f8a_hoisted_5)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !_ctx.message ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Notificationvue_type_template_id_52166f8a_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])], 14, Notificationvue_type_template_id_52166f8a_hoisted_2)]; }), _: 3 }, 8, ["name"])])]; @@ -5017,9 +8332,9 @@ function Notificationvue_type_template_id_e3d12348_render(_ctx, _cache, $props, _: 3 }, 8, ["name"]); } -// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=template&id=e3d12348 +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=template&id=52166f8a -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=script&lang=ts var Notificationvue_type_script_lang_ts_window = window, @@ -5114,13 +8429,13 @@ var Notificationvue_type_script_lang_ts_window = window, return; } - AjaxHelper_AjaxHelper.fetch({ + AjaxHelper_AjaxHelper.post({ module: 'CoreHome', action: 'markNotificationAsRead' }, { - postParams: { - notificationId: this.notificationId - } + notificationId: this.notificationId + }, { + withTokenInUrl: true }); } } @@ -5131,7 +8446,7 @@ var Notificationvue_type_script_lang_ts_window = window, -Notificationvue_type_script_lang_ts.render = Notificationvue_type_template_id_e3d12348_render +Notificationvue_type_script_lang_ts.render = Notificationvue_type_template_id_52166f8a_render /* harmony default export */ var Notification = (Notificationvue_type_script_lang_ts); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.adapter.ts @@ -5160,9 +8475,7 @@ Notificationvue_type_script_lang_ts.render = Notificationvue_type_template_id_e3 }, noclear: { angularJsBind: '@?', - transform: function transform(v) { - return !!v; - } + transform: transformAngularJsBoolAttr }, toastLength: { angularJsBind: '@?' @@ -5172,10 +8485,6 @@ Notificationvue_type_script_lang_ts.render = Notificationvue_type_template_id_e3 transclude: true })); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notifications.store.ts -function Notifications_store_ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } - -function Notifications_store_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { Notifications_store_ownKeys(Object(source), true).forEach(function (key) { Notifications_store_defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { Notifications_store_ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } - function Notifications_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function Notifications_store_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } @@ -5194,6 +8503,8 @@ function Notifications_store_defineProperty(obj, key, value) { if (key in obj) { +var Notifications_store_window = window, + Notifications_store_$ = Notifications_store_window.$; var Notifications_store_NotificationsStore = /*#__PURE__*/function () { function NotificationsStore() { @@ -5209,7 +8520,7 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { Notifications_store_createClass(NotificationsStore, [{ key: "state", get: function get() { - return this.privateState; + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(this.privateState); } }, { key: "appendNotification", @@ -5249,15 +8560,15 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { value: function parseNotificationDivs() { var _this = this; - var $notificationNodes = $('[data-role="notification"]'); + var $notificationNodes = Notifications_store_$('[data-role="notification"]'); var notificationsToShow = []; $notificationNodes.each(function (index, notificationNode) { - var $notificationNode = $(notificationNode); + var $notificationNode = Notifications_store_$(notificationNode); var attributes = $notificationNode.data(); var message = $notificationNode.html(); if (message) { - notificationsToShow.push(Notifications_store_objectSpread(Notifications_store_objectSpread({}, attributes), {}, { + notificationsToShow.push(Object.assign(Object.assign({}, attributes), {}, { message: message, animate: false })); @@ -5284,7 +8595,7 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { key: "show", value: function show(notification) { this.checkMessage(notification.message); - var addMethod = this.appendNotification; + var addMethod = notification.prepend ? this.prependNotification : this.appendNotification; var notificationPosition = '#notificationContainer'; if (notification.placeat) { @@ -5293,17 +8604,22 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { // If a modal is open, we want to make sure the error message is visible and therefore // show it within the opened modal var modalSelector = '.modal.open .modal-content'; + var modal = document.querySelector(modalSelector); + + if (modal) { + if (!modal.querySelector('#modalNotificationContainer')) { + Notifications_store_$(modal).prepend('<div id="modalNotificationContainer"/>'); + } - if (document.querySelector(modalSelector)) { - notificationPosition = modalSelector; + notificationPosition = "".concat(modalSelector, " #modalNotificationContainer"); addMethod = this.prependNotification; } } - var group = notification.group || (notification.placeat ? notification.placeat.toString() : ''); + var group = notification.group || (notificationPosition ? notificationPosition.toString() : ''); this.initializeNotificationContainer(notificationPosition, group); var notificationInstanceId = (this.nextNotificationId += 1).toString(); - addMethod.call(this, Notifications_store_objectSpread(Notifications_store_objectSpread({}, notification), {}, { + addMethod.call(this, Object.assign(Object.assign({}, notification), {}, { noclear: !!notification.noclear, group: group, notificationId: notification.id, @@ -5331,9 +8647,9 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { key: "toast", value: function toast(notification) { this.checkMessage(notification.message); - var $placeat = $(notification.placeat); + var $placeat = notification.placeat ? Notifications_store_$(notification.placeat) : undefined; - if (!$placeat.length) { + if (!$placeat || !$placeat.length) { throw new Error('A valid selector is required for the placeat option when using Notification.toast().'); } @@ -5343,9 +8659,9 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { toastElement.style.left = "".concat($placeat.offset().left, "px"); toastElement.style.zIndex = '1000'; document.body.appendChild(toastElement); - var app = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createApp"])({ + var app = createVueApp({ render: function render() { - return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(Notification, Notifications_store_objectSpread(Notifications_store_objectSpread({}, notification), {}, { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(Notification, Object.assign(Object.assign({}, notification), {}, { notificationId: notification.id, type: 'toast', onClosed: function onClosed() { @@ -5354,14 +8670,16 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { })); } }); - app.config.globalProperties.$sanitize = window.vueSanitize; - app.config.globalProperties.translate = translate; app.mount(toastElement); } }, { key: "initializeNotificationContainer", value: function initializeNotificationContainer(notificationPosition, group) { - var $container = window.$(notificationPosition); + if (!notificationPosition) { + return; + } + + var $container = Notifications_store_$(notificationPosition); if ($container.children('.notification-group').length) { return; @@ -5371,7 +8689,7 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { var NotificationGroup = window.CoreHome.NotificationGroup; // eslint-disable-line - var app = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createApp"])({ + var app = createVueApp({ template: '<NotificationGroup :group="group"></NotificationGroup>', data: function data() { return { @@ -5379,8 +8697,6 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { }; } }); - app.config.globalProperties.$sanitize = window.vueSanitize; - app.config.globalProperties.translate = translate; app.component('NotificationGroup', NotificationGroup); app.mount($container[0]); } @@ -5399,7 +8715,7 @@ var Notifications_store_NotificationsStore = /*#__PURE__*/function () { var Notifications_store_instance = new Notifications_store_NotificationsStore(); /* harmony default export */ var Notifications_store = (Notifications_store_instance); // parse notifications on dom load -$(function () { +Notifications_store_$(function () { return Notifications_store_instance.parseNotificationDivs(); }); // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notifications.store.adapter.ts @@ -5410,7 +8726,7 @@ $(function () { * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -angular.module('piwikApp').factory('notifications', function () { +window.angular.module('piwikApp').factory('notifications', function () { return Notifications_store; }); // CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Notification/NotificationGroup.vue?vue&type=template&id=672051da @@ -5451,7 +8767,7 @@ function NotificationGroupvue_type_template_id_672051da_render(_ctx, _cache, $pr } // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/NotificationGroup.vue?vue&type=template&id=672051da -// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/@vue/cli-plugin-typescript/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-3!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Notification/NotificationGroup.vue?vue&type=script&lang=ts +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Notification/NotificationGroup.vue?vue&type=script&lang=ts @@ -5502,6 +8818,3357 @@ NotificationGroupvue_type_script_lang_ts.render = NotificationGroupvue_type_temp +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.ts +function ReportingPages_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function ReportingPages_store_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function ReportingPages_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) ReportingPages_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) ReportingPages_store_defineProperties(Constructor, staticProps); return Constructor; } + +function ReportingPages_store_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +var ReportingPages_store_ReportingPagesStore = /*#__PURE__*/function () { + function ReportingPagesStore() { + var _this = this; + + ReportingPages_store_classCallCheck(this, ReportingPagesStore); + + ReportingPages_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({ + pages: [] + })); + + ReportingPages_store_defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_this.privateState); + })); + + ReportingPages_store_defineProperty(this, "fetchAllPagesPromise", void 0); + + ReportingPages_store_defineProperty(this, "pages", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.state.value.pages; + })); + } + + ReportingPages_store_createClass(ReportingPagesStore, [{ + key: "findPageInCategory", + value: function findPageInCategory(categoryId) { + // happens when user switches between sites, in this case check if the same category exists and + // if so, select first entry from that category + return this.pages.value.find(function (p) { + return p && p.category && p.category.id === categoryId && p.subcategory && p.subcategory.id; + }); + } + }, { + key: "findPage", + value: function findPage(categoryId, subcategoryId) { + return this.pages.value.find(function (p) { + return p && p.category && p.subcategory && p.category.id === categoryId && "".concat(p.subcategory.id) === subcategoryId; + }); + } + }, { + key: "reloadAllPages", + value: function reloadAllPages() { + delete this.fetchAllPagesPromise; + return this.getAllPages(); + } + }, { + key: "getAllPages", + value: function getAllPages() { + var _this2 = this; + + if (!this.fetchAllPagesPromise) { + this.fetchAllPagesPromise = AjaxHelper_AjaxHelper.fetch({ + method: 'API.getReportPagesMetadata', + filter_limit: '-1' + }).then(function (response) { + _this2.privateState.pages = response; + return _this2.pages.value; + }); + } + + return this.fetchAllPagesPromise.then(function () { + return _this2.pages.value; + }); + } + }]); + + return ReportingPagesStore; +}(); +/* harmony default export */ var ReportingPages_store = (new ReportingPages_store_ReportingPagesStore()); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Orderable.ts +function Orderable_toConsumableArray(arr) { return Orderable_arrayWithoutHoles(arr) || Orderable_iterableToArray(arr) || Orderable_unsupportedIterableToArray(arr) || Orderable_nonIterableSpread(); } + +function Orderable_nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function Orderable_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return Orderable_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return Orderable_arrayLikeToArray(o, minLen); } + +function Orderable_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } + +function Orderable_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return Orderable_arrayLikeToArray(arr); } + +function Orderable_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function sortOrderables(menu) { + var result = Orderable_toConsumableArray(menu || []); + + result.sort(function (lhs, rhs) { + if (lhs.order < rhs.order) { + return -1; + } + + if (lhs.order > rhs.order) { + return 1; + } + + return 0; + }); + return result; +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/Category.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function getCategoryChildren(category) { + var container = category; + + if (container.subcategories) { + return container.subcategories; + } + + return []; +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/Subcategory.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function getSubcategoryChildren(subcategory) { + var container = subcategory; + + if (container.subcategories) { + return container.subcategories; + } + + return []; +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.ts +function ReportingMenu_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function ReportingMenu_store_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function ReportingMenu_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) ReportingMenu_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) ReportingMenu_store_defineProperties(Constructor, staticProps); return Constructor; } + +function ReportingMenu_store_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + + + + + + +function isNumeric(text) { + var n = parseFloat(text); + return !Number.isNaN(n) && Number.isFinite(n); +} + +var ReportingMenu_store_ReportingMenuStore = /*#__PURE__*/function () { + function ReportingMenuStore() { + var _this = this; + + ReportingMenu_store_classCallCheck(this, ReportingMenuStore); + + ReportingMenu_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({ + activeCategoryId: null, + activeSubcategoryId: null, + activeSubsubcategoryId: null + })); + + ReportingMenu_store_defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_this.privateState); + })); + + ReportingMenu_store_defineProperty(this, "activeCategory", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.state.value.activeCategoryId || src_MatomoUrl_MatomoUrl.parsed.value.category; + })); + + ReportingMenu_store_defineProperty(this, "activeSubcategory", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.state.value.activeSubcategoryId || src_MatomoUrl_MatomoUrl.parsed.value.subcategory; + })); + + ReportingMenu_store_defineProperty(this, "activeSubsubcategory", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + var manuallySetId = _this.state.value.activeSubsubcategoryId; + + if (manuallySetId) { + return manuallySetId; + } // default to activeSubcategory if the activeSubcategory is part of a group + + + var foundCategory = _this.findSubcategory(_this.activeCategory.value, _this.activeSubcategory.value); + + if (foundCategory.subsubcategory && foundCategory.subsubcategory.id === _this.activeSubcategory.value) { + return foundCategory.subsubcategory.id; + } + + return null; + })); + + ReportingMenu_store_defineProperty(this, "menu", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.buildMenuFromPages(); + })); + } + + ReportingMenu_store_createClass(ReportingMenuStore, [{ + key: "fetchMenuItems", + value: function fetchMenuItems() { + var _this2 = this; + + return ReportingPages_store.getAllPages().then(function () { + return _this2.menu.value; + }); + } + }, { + key: "reloadMenuItems", + value: function reloadMenuItems() { + var _this3 = this; + + return ReportingPages_store.reloadAllPages().then(function () { + return _this3.menu.value; + }); + } + }, { + key: "findSubcategory", + value: function findSubcategory(categoryId, subcategoryId) { + var foundCategory = undefined; + var foundSubcategory = undefined; + var foundSubSubcategory = undefined; + this.menu.value.forEach(function (category) { + if (category.id !== categoryId) { + return; + } + + (getCategoryChildren(category) || []).forEach(function (subcategory) { + if (subcategory.id === subcategoryId) { + foundCategory = category; + foundSubcategory = subcategory; + } + + if (subcategory.isGroup) { + (getSubcategoryChildren(subcategory) || []).forEach(function (subcat) { + if (subcat.id === subcategoryId) { + foundCategory = category; + foundSubcategory = subcategory; + foundSubSubcategory = subcat; + } + }); + } + }); + }); + return { + category: foundCategory, + subcategory: foundSubcategory, + subsubcategory: foundSubSubcategory + }; + } + }, { + key: "buildMenuFromPages", + value: function buildMenuFromPages() { + var menu = []; + var displayedCategory = src_MatomoUrl_MatomoUrl.parsed.value.category; + var displayedSubcategory = src_MatomoUrl_MatomoUrl.parsed.value.subcategory; + var pages = ReportingPages_store.pages.value; + var categoriesHandled = {}; + pages.forEach(function (page) { + var category = Object.assign({}, page.category); + var categoryId = category.id; + var isCategoryDisplayed = categoryId === displayedCategory; + + if (categoriesHandled[categoryId]) { + return; + } + + categoriesHandled[categoryId] = true; + category.subcategories = []; + var categoryGroups = null; + var pagesWithCategory = pages.filter(function (p) { + return p.category.id === categoryId; + }); + pagesWithCategory.forEach(function (p) { + var subcategory = Object.assign({}, p.subcategory); + var isSubcategoryDisplayed = subcategory.id === displayedSubcategory && isCategoryDisplayed; + + if (p.widgets && p.widgets[0] && isNumeric(p.subcategory.id)) { + // we handle a goal or something like it + if (!categoryGroups) { + categoryGroups = Object.assign({}, subcategory); + categoryGroups.name = translate('CoreHome_ChooseX', [category.name]); + categoryGroups.isGroup = true; + categoryGroups.subcategories = []; + categoryGroups.order = 10; + } + + if (isSubcategoryDisplayed) { + categoryGroups.name = subcategory.name; + } + + var entityId = page.subcategory.id; + subcategory.tooltip = "".concat(subcategory.name, " (id = ").concat(entityId, ")"); + categoryGroups.subcategories.push(subcategory); + return; + } + + category.subcategories.push(subcategory); + }); + + if (categoryGroups && categoryGroups.subcategories && categoryGroups.subcategories.length <= 5) { + categoryGroups.subcategories.forEach(function (sub) { + return category.subcategories.push(sub); + }); + } else if (categoryGroups) { + category.subcategories.push(categoryGroups); + } + + category.subcategories = sortOrderables(getCategoryChildren(category)); + menu.push(category); + }); + return sortOrderables(menu); + } + }, { + key: "toggleCategory", + value: function toggleCategory(category) { + this.privateState.activeSubcategoryId = null; + this.privateState.activeSubsubcategoryId = null; + + if (this.privateState.activeCategoryId === category.id) { + this.privateState.activeCategoryId = null; + return false; + } + + this.privateState.activeCategoryId = category.id; + return true; + } + }, { + key: "enterSubcategory", + value: function enterSubcategory(category, subcategory, subsubcategory) { + if (!category || !subcategory) { + return; + } + + this.privateState.activeCategoryId = category.id; + this.privateState.activeSubcategoryId = subcategory.id; + + if (subsubcategory) { + this.privateState.activeSubsubcategoryId = subsubcategory.id; + } + } + }]); + + return ReportingMenuStore; +}(); +/* harmony default export */ var ReportingMenu_store = (new ReportingMenu_store_ReportingMenuStore()); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Widget/Widgets.store.ts +function Widgets_store_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { Widgets_store_typeof = function _typeof(obj) { return typeof obj; }; } else { Widgets_store_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return Widgets_store_typeof(obj); } + +function Widgets_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function Widgets_store_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function Widgets_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) Widgets_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) Widgets_store_defineProperties(Constructor, staticProps); return Constructor; } + +function Widgets_store_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +function getWidgetChildren(widget) { + var container = widget; + + if (container.widgets) { + return container.widgets; + } + + return []; +} + +var Widgets_store_WidgetsStore = /*#__PURE__*/function () { + function WidgetsStore() { + var _this = this; + + Widgets_store_classCallCheck(this, WidgetsStore); + + Widgets_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({ + isFetchedFirstTime: false, + categorizedWidgets: {} + })); + + Widgets_store_defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + if (!_this.privateState.isFetchedFirstTime) { + // initiating a side effect in a computed property seems wrong, but it needs to be + // executed after knowing a user's logged in and it will succeed. + _this.fetchAvailableWidgets(); + } + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_this.privateState); + })); + + Widgets_store_defineProperty(this, "widgets", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.state.value.categorizedWidgets; + })); + } + + Widgets_store_createClass(WidgetsStore, [{ + key: "fetchAvailableWidgets", + value: function fetchAvailableWidgets() { + var _this2 = this; + + // if there's no idSite, don't make the request since it will just fail + if (!src_MatomoUrl_MatomoUrl.parsed.value.idSite) { + return Promise.resolve(this.widgets.value); + } + + this.privateState.isFetchedFirstTime = true; + return new Promise(function (resolve, reject) { + try { + window.widgetsHelper.getAvailableWidgets(function (widgets) { + var casted = widgets; + _this2.privateState.categorizedWidgets = casted; + resolve(_this2.widgets.value); + }); + } catch (e) { + reject(e); + } + }); + } + }, { + key: "reloadAvailableWidgets", + value: function reloadAvailableWidgets() { + if (Widgets_store_typeof(window.widgetsHelper) === 'object' && window.widgetsHelper.availableWidgets) { + // lets also update widgetslist so will be easier to update list of available widgets in + // dashboard selector immediately + delete window.widgetsHelper.availableWidgets; + } + + return this.fetchAvailableWidgets(); + } + }]); + + return WidgetsStore; +}(); + +/* harmony default export */ var Widgets_store = (new Widgets_store_WidgetsStore()); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue?vue&type=script&lang=ts + + + + + + + + + +var REPORTING_HELP_NOTIFICATION_ID = 'reportingmenu-help'; +/* harmony default export */ var ReportingMenuvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + components: { + MenuItemsDropdown: MenuItemsDropdown + }, + directives: { + SideNav: SideNav + }, + props: {}, + data: function data() { + return { + showSubcategoryHelpOnLoad: null, + initialLoad: true, + helpShownCategory: null + }; + }, + computed: { + sideNavActivator: function sideNavActivator() { + return document.querySelector('nav .activateLeftMenu'); + }, + menu: function menu() { + return ReportingMenu_store.menu.value; + }, + activeCategory: function activeCategory() { + return ReportingMenu_store.activeCategory.value; + }, + activeSubcategory: function activeSubcategory() { + return ReportingMenu_store.activeSubcategory.value; + }, + activeSubsubcategory: function activeSubsubcategory() { + return ReportingMenu_store.activeSubsubcategory.value; + }, + displayedCategory: function displayedCategory() { + return src_MatomoUrl_MatomoUrl.parsed.value.category; + }, + displayedSubcategory: function displayedSubcategory() { + return src_MatomoUrl_MatomoUrl.parsed.value.subcategory; + } + }, + created: function created() { + var _this = this; + + ReportingMenu_store.fetchMenuItems().then(function (menu) { + if (!src_MatomoUrl_MatomoUrl.parsed.value.subcategory) { + var categoryToLoad = menu[0]; + var subcategoryToLoad = categoryToLoad.subcategories[0]; // load first, initial page if no subcategory is present + + ReportingMenu_store.enterSubcategory(categoryToLoad, subcategoryToLoad); + + _this.propagateUrlChange(categoryToLoad, subcategoryToLoad); + } + }); + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () { + return src_MatomoUrl_MatomoUrl.parsed.value; + }, function (query) { + var found = ReportingMenu_store.findSubcategory(query.category, query.subcategory); + ReportingMenu_store.enterSubcategory(found.category, found.subcategory, found.subsubcategory); + }); + Matomo_Matomo.on('piwikPageChange', function () { + if (!_this.initialLoad) { + window.globalAjaxQueue.abort(); + } + + _this.helpShownCategory = null; + + if (_this.showSubcategoryHelpOnLoad) { + _this.showHelp(_this.showSubcategoryHelpOnLoad.category, _this.showSubcategoryHelpOnLoad.subcategory); + + _this.showSubcategoryHelpOnLoad = null; + } + + window.$('#loadingError').hide(); + _this.initialLoad = false; + }); + Matomo_Matomo.on('updateReportingMenu', function () { + ReportingMenu_store.reloadMenuItems().then(function () { + var category = src_MatomoUrl_MatomoUrl.parsed.value.category; + var subcategory = src_MatomoUrl_MatomoUrl.parsed.value.subcategory; // we need to make sure to select same categories again + + if (category && subcategory) { + var found = ReportingMenu_store.findSubcategory(category, subcategory); + + if (found.category) { + ReportingMenu_store.enterSubcategory(found.category, found.subcategory, found.subsubcategory); + } + } + }); + Widgets_store.reloadAvailableWidgets(); + }); + }, + methods: { + propagateUrlChange: function propagateUrlChange(category, subcategory) { + var queryParams = src_MatomoUrl_MatomoUrl.parsed.value; + + if (queryParams.category === category.id && queryParams.subcategory === subcategory.id) { + // we need to manually trigger change as URL would not change and therefore page would not + // be reloaded + this.loadSubcategory(category, subcategory); + } else { + src_MatomoUrl_MatomoUrl.updateHash(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.hashParsed.value), {}, { + category: category.id, + subcategory: subcategory.id + })); + } + }, + loadCategory: function loadCategory(category) { + Notifications_store.remove(REPORTING_HELP_NOTIFICATION_ID); + var isActive = ReportingMenu_store.toggleCategory(category); + + if (isActive && category.subcategories && category.subcategories.length === 1) { + this.helpShownCategory = null; + var subcategory = category.subcategories[0]; + this.propagateUrlChange(category, subcategory); + } + }, + loadSubcategory: function loadSubcategory(category, subcategory, event) { + if (event && (event.shiftKey || event.ctrlKey || event.metaKey)) { + return; + } + + Notifications_store.remove(REPORTING_HELP_NOTIFICATION_ID); + + if (subcategory && subcategory.id === this.activeSubcategory) { + this.helpShownCategory = null; // this menu item is already active, a location change success would not be triggered, + // instead trigger an event (after the URL changes) + + setTimeout(function () { + Matomo_Matomo.postEvent('loadPage', category.id, subcategory.id); + }); + } + }, + makeUrl: function makeUrl(category, subcategory) { + var _MatomoUrl$parsed$val = src_MatomoUrl_MatomoUrl.parsed.value, + idSite = _MatomoUrl$parsed$val.idSite, + period = _MatomoUrl$parsed$val.period, + date = _MatomoUrl$parsed$val.date, + segment = _MatomoUrl$parsed$val.segment, + comparePeriods = _MatomoUrl$parsed$val.comparePeriods, + compareDates = _MatomoUrl$parsed$val.compareDates, + compareSegments = _MatomoUrl$parsed$val.compareSegments; + return src_MatomoUrl_MatomoUrl.stringify({ + idSite: idSite, + period: period, + date: date, + segment: segment, + comparePeriods: comparePeriods, + compareDates: compareDates, + compareSegments: compareSegments, + category: category.id, + subcategory: subcategory.id + }); + }, + htmlEntities: function htmlEntities(v) { + return Matomo_Matomo.helper.htmlEntities(v); + }, + showHelp: function showHelp(category, subcategory, event) { + var parsedUrl = src_MatomoUrl_MatomoUrl.parsed.value; + var currentCategory = parsedUrl.category; + var currentSubcategory = parsedUrl.subcategory; + + if ((currentCategory !== category.id || currentSubcategory !== subcategory.id) && event) { + this.showSubcategoryHelpOnLoad = { + category: category, + subcategory: subcategory + }; + src_MatomoUrl_MatomoUrl.updateHash(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.hashParsed.value), {}, { + category: category.id, + subcategory: subcategory.id + })); + return; + } + + if (this.helpShownCategory && category.id === this.helpShownCategory.category && subcategory.id === this.helpShownCategory.subcategory) { + Notifications_store.remove(REPORTING_HELP_NOTIFICATION_ID); + this.helpShownCategory = null; + return; + } + + var prefixText = translate('CoreHome_ReportingCategoryHelpPrefix', category.name, subcategory.name); + var prefix = "<strong>".concat(prefixText, "</strong><br/>"); + Notifications_store.show({ + context: 'info', + id: REPORTING_HELP_NOTIFICATION_ID, + type: 'help', + noclear: true, + class: 'help-notification', + message: prefix + subcategory.help, + placeat: '#notificationContainer', + prepend: true + }); + this.helpShownCategory = { + category: category.id, + subcategory: subcategory.id + }; + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue + + + +ReportingMenuvue_type_script_lang_ts.render = ReportingMenuvue_type_template_id_0f6008b2_render + +/* harmony default export */ var ReportingMenu = (ReportingMenuvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var ReportingMenu_adapter = (createAngularJsAdapter({ + component: ReportingMenu, + directiveName: 'piwikReportingMenu' +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + // removed boolean active property from objects in vue so we can keep the store immutable, but, +// angularjs version should still have them + +function addActiveMenuItems(menu) { + menu.forEach(function (category) { + if (category.id === ReportingMenu_store.activeCategory.value) { + category.active = true; + (category.subcategories || []).forEach(function (subcat) { + if (subcat.id === ReportingMenu_store.activeSubcategory.value) { + subcat.active = true; + (subcat.subcategories || []).forEach(function (subsubcat) { + if (subsubcat.id === ReportingMenu_store.activeSubsubcategory.value) { + subsubcat.active = true; + } + }); + } + }); + } + }); + return menu; +} + +function reportingMenuModelAdapter() { + return { + get menu() { + return ReportingMenu_store.menu.value; + }, + + findSubcategory: ReportingMenu_store.findSubcategory.bind(ReportingMenu_store), + reloadMenuItems: function reloadMenuItems() { + return ReportingMenu_store.reloadMenuItems().then(function (p) { + return addActiveMenuItems(cloneThenApply(p)); + }); + }, + fetchMenuItems: function fetchMenuItems() { + return ReportingMenu_store.fetchMenuItems().then(function (p) { + return addActiveMenuItems(cloneThenApply(p)); + }); + } + }; +} + +window.angular.module('piwikApp.service').factory('reportingMenuModel', reportingMenuModelAdapter); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + +function reportingPagesModelAdapter() { + return { + get pages() { + return ReportingPages_store.pages.value; + }, + + findPageInCategory: function findPageInCategory() { + return clone(ReportingPages_store.findPageInCategory.apply(ReportingPages_store, arguments)); + }, + findPage: function findPage() { + return clone(ReportingPages_store.findPage.apply(ReportingPages_store, arguments)); + }, + reloadAllPages: function reloadAllPages() { + return ReportingPages_store.reloadAllPages().then(function (p) { + return cloneThenApply(p); + }); + }, + getAllPages: function getAllPages() { + return ReportingPages_store.getAllPages().then(function (p) { + return cloneThenApply(p); + }); + } + }; +} + +window.angular.module('piwikApp.service').factory('reportingPagesModel', reportingPagesModelAdapter); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.ts +function ReportMetadata_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function ReportMetadata_store_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function ReportMetadata_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) ReportMetadata_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) ReportMetadata_store_defineProperties(Constructor, staticProps); return Constructor; } + +function ReportMetadata_store_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + + +var ReportMetadata_store_ReportMetadataStore = /*#__PURE__*/function () { + function ReportMetadataStore() { + var _this = this; + + ReportMetadata_store_classCallCheck(this, ReportMetadataStore); + + ReportMetadata_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({ + reports: [] + })); + + ReportMetadata_store_defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(this.privateState)); + + ReportMetadata_store_defineProperty(this, "reports", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.state.reports; + })); + + ReportMetadata_store_defineProperty(this, "reportsPromise", void 0); + } + + ReportMetadata_store_createClass(ReportMetadataStore, [{ + key: "findReport", + value: // TODO: it used to return an empty array when nothing was found, will that be an issue? + function findReport(reportModule, reportAction) { + return this.reports.value.find(function (r) { + return r.module === reportModule && r.action === reportAction; + }); + } + }, { + key: "fetchReportMetadata", + value: function fetchReportMetadata() { + var _this2 = this; + + if (!this.reportsPromise) { + this.reportsPromise = AjaxHelper_AjaxHelper.fetch({ + method: 'API.getReportMetadata', + filter_limit: '-1', + idSite: Matomo_Matomo.idSite || src_MatomoUrl_MatomoUrl.parsed.value.idSite + }).then(function (response) { + _this2.privateState.reports = response; + return response; + }); + } + + return this.reportsPromise.then(function () { + return _this2.reports.value; + }); + } + }]); + + return ReportMetadataStore; +}(); +/* harmony default export */ var ReportMetadata_store = (new ReportMetadata_store_ReportMetadataStore()); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +window.angular.module('piwikApp.service').factory('reportMetadataModel', function () { + return { + get reports() { + return ReportMetadata_store.reports.value; + }, + + findReport: ReportMetadata_store.findReport.bind(ReportMetadata_store), + fetchReportMetadata: function fetchReportMetadata() { + return ReportMetadata_store.fetchReportMetadata().then(function (m) { + return cloneThenApply(m); + }); + } + }; +}); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue?vue&type=template&id=2dfca834 + +var WidgetLoadervue_type_template_id_2dfca834_hoisted_1 = { + key: 0 +}; +var WidgetLoadervue_type_template_id_2dfca834_hoisted_2 = { + class: "notification system notification-error" +}; +var WidgetLoadervue_type_template_id_2dfca834_hoisted_3 = { + key: 0, + rel: "noreferrer noopener", + target: "_blank", + href: "https://matomo.org/faq/troubleshooting/faq_19489/" +}; +var WidgetLoadervue_type_template_id_2dfca834_hoisted_4 = { + class: "theWidgetContent", + ref: "widgetContent" +}; +function WidgetLoadervue_type_template_id_2dfca834_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_ActivityIndicator = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ActivityIndicator"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, { + "loading-message": _ctx.loadingMessage, + loading: _ctx.loading + }, null, 8, ["loading-message", "loading"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [_ctx.widgetName ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("h2", WidgetLoadervue_type_template_id_2dfca834_hoisted_1, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.widgetName), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", WidgetLoadervue_type_template_id_2dfca834_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ErrorRequest', '', '')) + " ", 1), _ctx.hasErrorFaqLink ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", WidgetLoadervue_type_template_id_2dfca834_hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ErrorRequestFaqLink')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.loadingFailed]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", WidgetLoadervue_type_template_id_2dfca834_hoisted_4, null, 512)]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue?vue&type=template&id=2dfca834 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue?vue&type=script&lang=ts + + + + + + + + +/** + * Loads any custom widget or URL based on the given parameters. + * + * The currently active idSite, period, date and segment (if needed) is automatically + * appended to the parameters. If this widget is removed from the DOM and requests are in + * progress, these requests will be aborted. A loading message or an error message on failure + * is shown as well. It's kinda similar to ng-include but there it is not possible to + * listen to HTTP errors etc. + * + * Example: + * <WidgetLoader :widget-params="{module: '', action: '', ...}"/> + */ + +/* harmony default export */ var WidgetLoadervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + widgetParams: Object, + widgetName: String + }, + components: { + ActivityIndicator: ActivityIndicator + }, + data: function data() { + return { + loading: false, + loadingFailed: false, + changeCounter: 0, + currentScope: null, + lastWidgetAbortController: null + }; + }, + watch: { + widgetParams: function widgetParams(parameters) { + if (parameters) { + this.loadWidgetUrl(parameters, this.changeCounter += 1); + } + } + }, + computed: { + loadingMessage: function loadingMessage() { + if (!this.widgetName) { + return translate('General_LoadingData'); + } + + return translate('General_LoadingPopover', this.widgetName); + }, + hasErrorFaqLink: function hasErrorFaqLink() { + var isGeneralSettingsAdminEnabled = Matomo_Matomo.config.enable_general_settings_admin; + var isPluginsAdminEnabled = Matomo_Matomo.config.enable_plugins_admin; + return Matomo_Matomo.hasSuperUserAccess && (isGeneralSettingsAdminEnabled || isPluginsAdminEnabled); + } + }, + mounted: function mounted() { + if (this.widgetParams) { + this.loadWidgetUrl(this.widgetParams, this.changeCounter += 1); + } + }, + beforeUnmount: function beforeUnmount() { + this.cleanupLastWidgetContent(); + }, + methods: { + abortHttpRequestIfNeeded: function abortHttpRequestIfNeeded() { + if (this.lastWidgetAbortController) { + this.lastWidgetAbortController.abort(); + this.lastWidgetAbortController = null; + } + }, + cleanupLastWidgetContent: function cleanupLastWidgetContent() { + var widgetContent = this.$refs.widgetContent; + Matomo_Matomo.helper.destroyVueComponent(widgetContent); + + if (this.currentScope) { + this.currentScope.$destroy(); + } + + if (widgetContent) { + widgetContent.innerHTML = ''; + } + }, + getWidgetUrl: function getWidgetUrl(parameters) { + var urlParams = src_MatomoUrl_MatomoUrl.parsed.value; + var fullParameters = Object.assign({}, parameters || {}); + var paramsToForward = Object.keys(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.hashParsed.value), {}, { + idSite: '', + period: '', + date: '', + segment: '', + widget: '' + })); + paramsToForward.forEach(function (key) { + if (key === 'category' || key === 'subcategory') { + return; + } + + if (!(key in fullParameters)) { + fullParameters[key] = urlParams[key]; + } + }); + + if (Comparisons_store_instance.isComparisonEnabled()) { + fullParameters = Object.assign(Object.assign({}, fullParameters), {}, { + comparePeriods: urlParams.comparePeriods, + compareDates: urlParams.compareDates, + compareSegments: urlParams.compareSegments + }); + } + + if (!parameters || !('showtitle' in parameters)) { + fullParameters.showtitle = '1'; + } + + if (Matomo_Matomo.shouldPropagateTokenAuth && urlParams.token_auth) { + if (!Matomo_Matomo.broadcast.isWidgetizeRequestWithoutSession()) { + fullParameters.force_api_session = '1'; + } + + fullParameters.token_auth = urlParams.token_auth; + } + + fullParameters.random = Math.floor(Math.random() * 10000); + return fullParameters; + }, + loadWidgetUrl: function loadWidgetUrl(parameters, thisChangeId) { + var _this = this; + + this.loading = true; + this.abortHttpRequestIfNeeded(); + this.cleanupLastWidgetContent(); + this.lastWidgetAbortController = new AbortController(); + AjaxHelper_AjaxHelper.fetch(this.getWidgetUrl(parameters), { + format: 'html', + headers: { + 'X-Requested-With': 'XMLHttpRequest' + }, + abortController: this.lastWidgetAbortController + }).then(function (response) { + if (thisChangeId !== _this.changeCounter || !response || typeof response !== 'string') { + // another widget was requested meanwhile, ignore this response + return; + } + + _this.lastWidgetAbortController = null; + _this.loading = false; + _this.loadingFailed = false; + var widgetContent = _this.$refs.widgetContent; + window.$(widgetContent).html(response); + var $content = window.$(widgetContent).children(); + + if (_this.widgetName) { + // we need to respect the widget title, which overwrites a possibly set report title + var $title = $content.find('> .card-content .card-title'); + + if (!$title.length) { + $title = $content.find('> h2'); + } + + if ($title.length) { + // required to use htmlEntities since it also escapes '{{' format items + $title.html(Matomo_Matomo.helper.htmlEntities(_this.widgetName)); + } + } + + var $rootScope = Matomo_Matomo.helper.getAngularDependency('$rootScope'); + var scope = $rootScope.$new(); + _this.currentScope = scope; // compile angularjs first since it will modify all dom nodes, breaking vue bindings + // if they are present + + Matomo_Matomo.helper.compileAngularComponents($content, { + scope: scope + }); + Matomo_Matomo.helper.compileVueEntryComponents($content); + Notifications_store.parseNotificationDivs(); + setTimeout(function () { + Matomo_Matomo.postEvent('widget:loaded', { + parameters: parameters, + element: $content + }); + }); + }).catch(function (response) { + if (thisChangeId !== _this.changeCounter) { + // another widget was requested meanwhile, ignore this response + return; + } + + _this.lastWidgetAbortController = null; + + _this.cleanupLastWidgetContent(); + + _this.loading = false; + + if (response.xhrStatus === 'abort') { + return; + } + + _this.loadingFailed = true; + }); + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue + + + +WidgetLoadervue_type_script_lang_ts.render = WidgetLoadervue_type_template_id_2dfca834_render + +/* harmony default export */ var WidgetLoader = (WidgetLoadervue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var WidgetLoader_adapter = (createAngularJsAdapter({ + component: WidgetLoader, + scope: { + piwikWidgetLoader: { + vue: 'widgetParams', + angularJsBind: '=' + }, + widgetName: { + angularJsBind: '@' + } + }, + directiveName: 'piwikWidgetLoader' +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue?vue&type=template&id=41745e0f + +function WidgetContainervue_type_template_id_41745e0f_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_Widget = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Widget"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", null, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.actualContainer, function (widget, index) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + key: index + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Widget, { + widget: widget, + "prevent-recursion": true + }, null, 8, ["widget"])])]); + }), 128))]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue?vue&type=template&id=41745e0f + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue?vue&type=script&lang=ts +function WidgetContainervue_type_script_lang_ts_toConsumableArray(arr) { return WidgetContainervue_type_script_lang_ts_arrayWithoutHoles(arr) || WidgetContainervue_type_script_lang_ts_iterableToArray(arr) || WidgetContainervue_type_script_lang_ts_unsupportedIterableToArray(arr) || WidgetContainervue_type_script_lang_ts_nonIterableSpread(); } + +function WidgetContainervue_type_script_lang_ts_nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function WidgetContainervue_type_script_lang_ts_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } + +function WidgetContainervue_type_script_lang_ts_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return WidgetContainervue_type_script_lang_ts_arrayLikeToArray(arr); } + +function WidgetContainervue_type_script_lang_ts_slicedToArray(arr, i) { return WidgetContainervue_type_script_lang_ts_arrayWithHoles(arr) || WidgetContainervue_type_script_lang_ts_iterableToArrayLimit(arr, i) || WidgetContainervue_type_script_lang_ts_unsupportedIterableToArray(arr, i) || WidgetContainervue_type_script_lang_ts_nonIterableRest(); } + +function WidgetContainervue_type_script_lang_ts_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function WidgetContainervue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return WidgetContainervue_type_script_lang_ts_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return WidgetContainervue_type_script_lang_ts_arrayLikeToArray(o, minLen); } + +function WidgetContainervue_type_script_lang_ts_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function WidgetContainervue_type_script_lang_ts_iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function WidgetContainervue_type_script_lang_ts_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + + + // since we're recursing, don't import the plugin directly + +var Widget = useExternalPluginComponent('CoreHome', 'Widget'); +/* harmony default export */ var WidgetContainervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + container: { + type: Array, + required: true + } + }, + components: { + Widget: Widget + }, + computed: { + actualContainer: function actualContainer() { + var _container$, _widget$parameters, _widget$parameters2; + + var container = this.container; + + if (!(container !== null && container !== void 0 && (_container$ = container[0]) !== null && _container$ !== void 0 && _container$.parameters)) { + return container; + } + + var _container = WidgetContainervue_type_script_lang_ts_slicedToArray(container, 1), + widget = _container[0]; + + var isWidgetized = ((_widget$parameters = widget.parameters) === null || _widget$parameters === void 0 ? void 0 : _widget$parameters.widget) === '1' || ((_widget$parameters2 = widget.parameters) === null || _widget$parameters2 === void 0 ? void 0 : _widget$parameters2.widget) === 1; + var isGraphEvolution = isWidgetized && widget.viewDataTable === 'graphEvolution'; // we hide the first title for Visits Overview with Graph and Goal Overview + + var firstWidget = isGraphEvolution ? Object.assign(Object.assign({}, widget), {}, { + parameters: Object.assign(Object.assign({}, widget.parameters), {}, { + showtitle: '0' + }) + }) : widget; + return [firstWidget].concat(WidgetContainervue_type_script_lang_ts_toConsumableArray(container.slice(1))); + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue + + + +WidgetContainervue_type_script_lang_ts.render = WidgetContainervue_type_template_id_41745e0f_render + +/* harmony default export */ var WidgetContainer = (WidgetContainervue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var WidgetContainer_adapter = (createAngularJsAdapter({ + component: WidgetContainer, + scope: { + container: { + angularJsBind: '=piwikWidgetContainer' + } + }, + directiveName: 'piwikWidgetContainer' +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue?vue&type=template&id=3681f928 + +var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_1 = { + class: "reportsByDimensionView" +}; +var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_2 = { + class: "entityList" +}; +var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_3 = { + class: "listCircle" +}; +var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_4 = ["onClick"]; +var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_5 = { + class: "dimension" +}; +var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_6 = { + class: "reportContainer" +}; + +var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_7 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { + class: "clear" +}, null, -1); + +function WidgetByDimensionContainervue_type_template_id_3681f928_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_WidgetLoader = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("WidgetLoader"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_2, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.widgetsByCategory, function (category) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + class: "dimensionCategory", + key: category.name + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(category.name) + " ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_3, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(category.widgets, function (widget) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", { + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["reportDimension", { + activeDimension: _ctx.selectedWidget.uniqueId === widget.uniqueId + }]), + key: widget.uniqueId, + onClick: function onClick($event) { + return _ctx.selectWidget(widget); + } + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_5, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(widget.name), 1)], 10, WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_4); + }), 128))])]); + }), 128))]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_6, [_ctx.selectedWidget.parameters ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_WidgetLoader, { + key: 0, + "widget-params": _ctx.selectedWidget.parameters, + class: "dimensionReport" + }, null, 8, ["widget-params"])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]), WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_7]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue?vue&type=template&id=3681f928 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue?vue&type=script&lang=ts +function WidgetByDimensionContainervue_type_script_lang_ts_slicedToArray(arr, i) { return WidgetByDimensionContainervue_type_script_lang_ts_arrayWithHoles(arr) || WidgetByDimensionContainervue_type_script_lang_ts_iterableToArrayLimit(arr, i) || WidgetByDimensionContainervue_type_script_lang_ts_unsupportedIterableToArray(arr, i) || WidgetByDimensionContainervue_type_script_lang_ts_nonIterableRest(); } + +function WidgetByDimensionContainervue_type_script_lang_ts_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function WidgetByDimensionContainervue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return WidgetByDimensionContainervue_type_script_lang_ts_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return WidgetByDimensionContainervue_type_script_lang_ts_arrayLikeToArray(o, minLen); } + +function WidgetByDimensionContainervue_type_script_lang_ts_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function WidgetByDimensionContainervue_type_script_lang_ts_iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function WidgetByDimensionContainervue_type_script_lang_ts_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + + + + +/* harmony default export */ var WidgetByDimensionContainervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + widgets: Array + }, + components: { + WidgetLoader: WidgetLoader + }, + data: function data() { + return { + selectedWidget: null + }; + }, + created: function created() { + var _this$widgetsSorted = WidgetByDimensionContainervue_type_script_lang_ts_slicedToArray(this.widgetsSorted, 1); + + this.selectedWidget = _this$widgetsSorted[0]; + }, + computed: { + widgetsSorted: function widgetsSorted() { + return sortOrderables(this.widgets); + }, + widgetsByCategory: function widgetsByCategory() { + var byCategory = {}; + this.widgetsSorted.forEach(function (widget) { + var _widget$subcategory; + + var category = (_widget$subcategory = widget.subcategory) === null || _widget$subcategory === void 0 ? void 0 : _widget$subcategory.name; + + if (!category) { + return; + } + + if (!byCategory[category]) { + byCategory[category] = { + name: category, + order: widget.order, + widgets: [] + }; + } + + byCategory[category].widgets.push(widget); + }); + return sortOrderables(Object.values(byCategory)); + } + }, + methods: { + selectWidget: function selectWidget(widget) { + // we copy to force rerender if selecting same widget + this.selectedWidget = Object.assign({}, widget); + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue + + + +WidgetByDimensionContainervue_type_script_lang_ts.render = WidgetByDimensionContainervue_type_template_id_3681f928_render + +/* harmony default export */ var WidgetByDimensionContainer = (WidgetByDimensionContainervue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var WidgetByDimensionContainer_adapter = (createAngularJsAdapter({ + component: WidgetByDimensionContainer, + scope: { + widgets: { + angularJsBind: '=piwikWidgetByDimensionContainer', + transform: function transform(v) { + return v.widgets; + } + } + }, + directiveName: 'piwikWidgetByDimensionContainer' +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Widget/Widget.vue?vue&type=template&id=23f53472 + +var Widgetvue_type_template_id_23f53472_hoisted_1 = ["id"]; +var Widgetvue_type_template_id_23f53472_hoisted_2 = { + key: 1 +}; +var Widgetvue_type_template_id_23f53472_hoisted_3 = { + key: 2 +}; +function Widgetvue_type_template_id_23f53472_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_WidgetLoader = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("WidgetLoader"); + + var _component_WidgetContainer = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("WidgetContainer"); + + var _component_WidgetByDimensionContainer = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("WidgetByDimensionContainer"); + + var _directive_tooltips = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("tooltips"); + + return _ctx.actualWidget ? Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])((Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + key: 0, + class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["matomo-widget", { + 'isFirstWidgetInPage': _ctx.actualWidget.isFirstInPage + }]), + id: _ctx.actualWidget.uniqueId + }, [!_ctx.actualWidget.isContainer && _ctx.actualWidget.parameters ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_WidgetLoader, { + key: 0, + "widget-params": _ctx.actualWidget.parameters, + "widget-name": _ctx.actualWidget.name + }, null, 8, ["widget-params", "widget-name"])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.actualWidget.isContainer && _ctx.actualWidget.layout !== 'ByDimension' && !this.preventRecursion ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Widgetvue_type_template_id_23f53472_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_WidgetContainer, { + container: _ctx.actualWidget.widgets + }, null, 8, ["container"])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.actualWidget.isContainer && _ctx.actualWidget.layout === 'ByDimension' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Widgetvue_type_template_id_23f53472_hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_WidgetByDimensionContainer, { + widgets: _ctx.actualWidget.widgets + }, null, 8, ["widgets"])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 10, Widgetvue_type_template_id_23f53472_hoisted_1)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showWidget], [_directive_tooltips, { + content: _ctx.tooltipContent + }]]) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Widget/Widget.vue?vue&type=template&id=23f53472 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Widget/Widget.vue?vue&type=script&lang=ts + + + + + + + + + +function findContainer(widgetsByCategory, containerId) { + var widget = undefined; + Object.values(widgetsByCategory || {}).some(function (widgets) { + widget = widgets.find(function (w) { + var _w$parameters; + + return w && w.isContainer && ((_w$parameters = w.parameters) === null || _w$parameters === void 0 ? void 0 : _w$parameters.containerId) === containerId; + }); + return widget; + }); + return widget; +} +/** + * Renders any kind of widget. If you have a widget and you want to have it rendered, use this + * directive. It will display a name on top and the actual widget below. It can handle any kind + * of widget, no matter whether it is a regular widget or a container. + * + * @param {Object} piwikWidget A widget object as returned by the WidgetMetadata API. + * @param {Object} piwikWidget.middlewareParameters If present, we will request a URL using the + * given parameters and only if this URL + * returns a JSON `true` the widget will be + * shown. Otherwise the widget won't be shown. + * @param {String} containerId If you do not have a widget object but a containerId we will find + * the correct widget object based on the given containerId. Be aware + * that we might not find the widget if it is for example not + * available for the current user or period/date. + * @param {Boolean} widgetized true if the widget is widgetized (eg in Dashboard or exported). + * In this case we will add a URL parameter widget=1 to all widgets. + * Eg sparklines will be then displayed one after another + * (vertically aligned) instead of two next to each other. + * + * Example: + * <Widget :widget="widget"></Widget> + * // in this case we will find the correct widget automatically + * <Widget :containerid="widgetGoalsOverview"></Widget> + * // disables rating feature, no initial headline + * <Widget :widget="widget" :widetized="true"></Widget> + */ + + +/* harmony default export */ var Widgetvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + widget: Object, + widgetized: Boolean, + containerid: String, + preventRecursion: Boolean + }, + components: { + WidgetLoader: WidgetLoader, + WidgetContainer: WidgetContainer, + WidgetByDimensionContainer: WidgetByDimensionContainer + }, + directives: { + Tooltips: Tooltips + }, + data: function data() { + return { + showWidget: false + }; + }, + setup: function setup() { + function tooltipContent() { + var $this = window.$(this); + + if ($this.attr('piwik-field') === '' || $this.hasClass('matomo-form-field')) { + // do not show it for form fields + return ''; + } + + var title = window.$(this).attr('title') || ''; + return window.vueSanitize(title.replace(/\n/g, '<br />')); + } + + return { + tooltipContent: tooltipContent + }; + }, + created: function created() { + var _this = this; + + var actualWidget = this.actualWidget; + + if (actualWidget && actualWidget.middlewareParameters) { + var params = actualWidget.middlewareParameters; + AjaxHelper_AjaxHelper.fetch(params).then(function (response) { + _this.showWidget = !!response; + }); + } else { + this.showWidget = true; + } + }, + computed: { + allWidgets: function allWidgets() { + return Widgets_store.widgets.value; + }, + actualWidget: function actualWidget() { + var _this2 = this; + + var widget = this.widget; + + if (widget) { + var result = Object.assign({}, widget); + + if (widget && widget.isReport && !widget.documentation) { + var report = ReportMetadata_store.findReport(widget.module, widget.action); + + if (report && report.documentation) { + result.documentation = report.documentation; + } + } + + return widget; + } + + if (this.containerid) { + var containerWidget = findContainer(this.allWidgets, this.containerid); + + if (containerWidget) { + var _result = Object.assign({}, containerWidget); + + if (this.widgetized) { + _result.isFirstInPage = true; + _result.parameters = Object.assign(Object.assign({}, _result.parameters), {}, { + widget: '1' + }); + var widgets = getWidgetChildren(_result); + + if (widgets) { + _result.widgets = widgets.map(function (w) { + return Object.assign(Object.assign({}, w), {}, { + parameters: Object.assign(Object.assign({}, w.parameters), {}, { + widget: '1', + containerId: _this2.containerid + }) + }); + }); + } + } + + return _result; + } + } + + return null; + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Widget/Widget.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Widget/Widget.vue + + + +Widgetvue_type_script_lang_ts.render = Widgetvue_type_template_id_23f53472_render + +/* harmony default export */ var Widget_Widget = (Widgetvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Widget/Widget.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var Widget_adapter = (createAngularJsAdapter({ + component: Widget_Widget, + scope: { + widget: { + angularJsBind: '=?piwikWidget' + }, + widgetized: { + angularJsBind: '=?' + }, + containerid: { + angularJsBind: '@' + } + }, + directiveName: 'piwikWidget' +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue?vue&type=template&id=28b6d8b8 + +var ReportingPagevue_type_template_id_28b6d8b8_hoisted_1 = { + class: "reporting-page" +}; +var ReportingPagevue_type_template_id_28b6d8b8_hoisted_2 = { + key: 1, + class: "col s12 l6 leftWidgetColumn" +}; +var ReportingPagevue_type_template_id_28b6d8b8_hoisted_3 = { + key: 2, + class: "col s12 l6 rightWidgetColumn" +}; +function ReportingPagevue_type_template_id_28b6d8b8_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_ActivityIndicator = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ActivityIndicator"); + + var _component_Widget = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Widget"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ReportingPagevue_type_template_id_28b6d8b8_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, { + loading: _ctx.loading + }, null, 8, ["loading"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('CoreHome_NoSuchPage')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.hasNoPage]]), (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(_ctx.widgets, function (widget) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", { + class: "row", + key: widget.uniqueId + }, [!widget.group ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Widget, { + key: 0, + class: "col s12 fullWidgetColumn", + widget: widget + }, null, 8, ["widget"])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), widget.group ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ReportingPagevue_type_template_id_28b6d8b8_hoisted_2, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(widget.left, function (widgetInGroup) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Widget, { + widget: widgetInGroup, + key: widgetInGroup.uniqueId + }, null, 8, ["widget"]); + }), 128))])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), widget.group ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ReportingPagevue_type_template_id_28b6d8b8_hoisted_3, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderList"])(widget.right, function (widgetInGroup) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Widget, { + widget: widgetInGroup, + key: widgetInGroup.uniqueId + }, null, 8, ["widget"]); + }), 128))])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]); + }), 128))]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue?vue&type=template&id=28b6d8b8 + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.ts +function ReportingPage_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function ReportingPage_store_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } + +function ReportingPage_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) ReportingPage_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) ReportingPage_store_defineProperties(Constructor, staticProps); return Constructor; } + +function ReportingPage_store_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +function ReportingPage_store_toConsumableArray(arr) { return ReportingPage_store_arrayWithoutHoles(arr) || ReportingPage_store_iterableToArray(arr) || ReportingPage_store_unsupportedIterableToArray(arr) || ReportingPage_store_nonIterableSpread(); } + +function ReportingPage_store_nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function ReportingPage_store_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return ReportingPage_store_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return ReportingPage_store_arrayLikeToArray(o, minLen); } + +function ReportingPage_store_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } + +function ReportingPage_store_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return ReportingPage_store_arrayLikeToArray(arr); } + +function ReportingPage_store_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + + + + +function shouldBeRenderedWithFullWidth(widget) { + // rather controller logic + if (widget.isContainer && widget.layout && widget.layout === 'ByDimension' || widget.viewDataTable === 'bydimension') { + return true; + } + + if (widget.isWide) { + return true; + } + + return widget.viewDataTable && (widget.viewDataTable === 'tableAllColumns' || widget.viewDataTable === 'sparklines' || widget.viewDataTable === 'graphEvolution'); +} + +function markWidgetsInFirstRowOfPage(widgets) { + if (widgets && widgets[0]) { + var newWidgets = ReportingPage_store_toConsumableArray(widgets); + + var groupedWidgets = widgets[0]; + + if (groupedWidgets.group) { + newWidgets[0] = Object.assign(Object.assign({}, newWidgets[0]), {}, { + left: markWidgetsInFirstRowOfPage(groupedWidgets.left || []), + right: markWidgetsInFirstRowOfPage(groupedWidgets.right || []) + }); + } else { + newWidgets[0] = Object.assign(Object.assign({}, newWidgets[0]), {}, { + isFirstInPage: true + }); + } + + return newWidgets; + } + + return widgets; +} + +var ReportingPage_store_ReportingPageStore = /*#__PURE__*/function () { + function ReportingPageStore() { + var _this = this; + + ReportingPage_store_classCallCheck(this, ReportingPageStore); + + ReportingPage_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({})); + + ReportingPage_store_defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(_this.privateState); + })); + + ReportingPage_store_defineProperty(this, "page", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + return _this.state.value.page; + })); + + ReportingPage_store_defineProperty(this, "widgets", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () { + var page = _this.page.value; + + if (!page) { + return []; + } + + var widgets = []; + var reportsToIgnore = {}; + + var isIgnoredReport = function isIgnoredReport(widget) { + return widget.isReport && reportsToIgnore["".concat(widget.module, ".").concat(widget.action)]; + }; + + var getRelatedReports = function getRelatedReports(widget) { + if (!widget.isReport) { + return []; + } + + var report = ReportMetadata_store.findReport(widget.module, widget.action); + + if (!report || !report.relatedReports) { + return []; + } + + return report.relatedReports; + }; + + (page.widgets || []).forEach(function (widget) { + if (isIgnoredReport(widget)) { + return; + } + + getRelatedReports(widget).forEach(function (report) { + reportsToIgnore["".concat(report.module, ".").concat(report.action)] = true; + }); + widgets.push(widget); + }); + widgets = sortOrderables(widgets); + + if (widgets.length === 1) { + // if there is only one widget, we always display it full width + return markWidgetsInFirstRowOfPage(widgets); + } + + var groupedWidgets = []; + + for (var i = 0; i < widgets.length; i += 1) { + var widget = widgets[i]; + + if (shouldBeRenderedWithFullWidth(widget) || widgets[i + 1] && shouldBeRenderedWithFullWidth(widgets[i + 1])) { + groupedWidgets.push(Object.assign(Object.assign({}, widget), {}, { + widgets: sortOrderables(getWidgetChildren(widget)) + })); + } else { + var counter = 0; + var left = [widget]; + var right = []; + + while (widgets[i + 1] && !shouldBeRenderedWithFullWidth(widgets[i + 1])) { + i += 1; + counter += 1; + + if (counter % 2 === 0) { + left.push(widgets[i]); + } else { + right.push(widgets[i]); + } + } + + groupedWidgets.push({ + group: true, + left: left, + right: right + }); + } + } + + var sortedWidgets = markWidgetsInFirstRowOfPage(groupedWidgets); + return sortedWidgets; + })); + } + + ReportingPage_store_createClass(ReportingPageStore, [{ + key: "fetchPage", + value: function fetchPage(category, subcategory) { + var _this2 = this; + + this.resetPage(); + return Promise.all([ReportingPages_store.getAllPages(), ReportMetadata_store.fetchReportMetadata()]).then(function () { + _this2.privateState.page = ReportingPages_store.findPage(category, subcategory); + return _this2.page.value; + }); + } + }, { + key: "resetPage", + value: function resetPage() { + this.privateState.page = undefined; + } + }]); + + return ReportingPageStore; +}(); +/* harmony default export */ var ReportingPage_store = (new ReportingPage_store_ReportingPageStore()); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue?vue&type=script&lang=ts + + + + + + + + + + + + +function showOnlyRawDataNotification() { + var params = 'category=General_Visitors&subcategory=Live_VisitorLog'; + var url = window.broadcast.buildReportingUrl(params); + Notifications_store.show({ + id: 'onlyRawData', + animate: false, + context: 'info', + message: translate('CoreHome_PeriodHasOnlyRawData', "<a href=\"".concat(url, "\">"), '</a>'), + type: 'transient' + }); +} + +function hideOnlyRawDataNoticifation() { + Notifications_store.remove('onlyRawData'); +} + +/* harmony default export */ var ReportingPagevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + components: { + ActivityIndicator: ActivityIndicator, + Widget: Widget_Widget + }, + data: function data() { + return { + loading: false, + hasRawData: false, + hasNoVisits: false, + dateLastChecked: null, + hasNoPage: false + }; + }, + created: function created() { + var _this = this; + + ReportingPage_store.resetPage(); + this.loading = true; // we only set loading on initial load + + this.renderInitialPage(); + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () { + return src_MatomoUrl_MatomoUrl.parsed.value; + }, function (newValue, oldValue) { + if (newValue.category === oldValue.category && newValue.subcategory === oldValue.subcategory && newValue.period === oldValue.period && newValue.date === oldValue.date && newValue.segment === oldValue.segment && JSON.stringify(newValue.compareDates) === JSON.stringify(oldValue.compareDates) && JSON.stringify(newValue.comparePeriods) === JSON.stringify(oldValue.comparePeriods) && JSON.stringify(newValue.compareSegments) === JSON.stringify(oldValue.compareSegments) && JSON.stringify(newValue.columns || '') === JSON.stringify(oldValue.columns || '')) { + // this page is already loaded + return; + } + + if (newValue.date !== oldValue.date || newValue.period !== oldValue.period) { + hideOnlyRawDataNoticifation(); + _this.dateLastChecked = null; + _this.hasRawData = false; + _this.hasNoVisits = false; + } + + _this.renderPage(newValue.category, newValue.subcategory); + }); + Matomo_Matomo.on('loadPage', function (category, subcategory) { + _this.renderPage(category, subcategory); + }); + }, + computed: { + widgets: function widgets() { + return ReportingPage_store.widgets.value; + } + }, + methods: { + renderPage: function renderPage(category, subcategory) { + var _this2 = this; + + if (!category || !subcategory) { + ReportingPage_store.resetPage(); + this.loading = false; + return; + } + + var parsedUrl = src_MatomoUrl_MatomoUrl.parsed.value; + var currentPeriod = parsedUrl.period; + var currentDate = parsedUrl.date; + + try { + Periods_Periods.parse(currentPeriod, currentDate); + } catch (e) { + Notifications_store.show({ + id: 'invalidDate', + animate: false, + context: 'error', + message: translate('CoreHome_DateInvalid'), + type: 'transient' + }); + ReportingPage_store.resetPage(); + this.loading = false; + return; + } + + Notifications_store.remove('invalidDate'); + Matomo_Matomo.postEvent('piwikPageChange', {}); + Notifications_store.clearTransientNotifications(); + + if (Periods_Periods.parse(currentPeriod, currentDate).containsToday()) { + this.showOnlyRawDataMessageIfRequired(); + } + + var params = { + category: category, + subcategory: subcategory + }; + Matomo_Matomo.postEvent('ReportingPage.loadPage', params); + + if (params.promise) { + this.loading = true; + Promise.resolve(params.promise).finally(function () { + _this2.loading = false; + }); + return; + } + + ReportingPage_store.fetchPage(category, subcategory).then(function () { + var hasNoPage = !ReportingPage_store.page.value; + + if (hasNoPage) { + var page = ReportingPages_store.findPageInCategory(category); + + if (page && page.subcategory) { + src_MatomoUrl_MatomoUrl.updateHash(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.hashParsed.value), {}, { + subcategory: page.subcategory.id + })); + return; + } + } + + _this2.hasNoPage = hasNoPage; + _this2.loading = false; + }); + }, + renderInitialPage: function renderInitialPage() { + var parsed = src_MatomoUrl_MatomoUrl.parsed.value; + this.renderPage(parsed.category, parsed.subcategory); + }, + showOnlyRawDataMessageIfRequired: function showOnlyRawDataMessageIfRequired() { + var _this3 = this; + + if (this.hasRawData && this.hasNoVisits) { + showOnlyRawDataNotification(); + } + + var parsedUrl = src_MatomoUrl_MatomoUrl.parsed.value; + var segment = parsedUrl.segment; + + if (segment) { + hideOnlyRawDataNoticifation(); + return; + } + + var subcategoryExceptions = ['Live_VisitorLog', 'General_RealTime', 'UserCountryMap_RealTimeMap', 'MediaAnalytics_TypeAudienceLog', 'MediaAnalytics_TypeRealTime', 'FormAnalytics_TypeRealTime', 'Goals_AddNewGoal']; + var categoryExceptions = ['HeatmapSessionRecording_Heatmaps', 'HeatmapSessionRecording_SessionRecordings', 'Marketplace_Marketplace']; + var subcategory = parsedUrl.subcategory; + var category = parsedUrl.category; + + if (subcategoryExceptions.indexOf(subcategory) !== -1 || categoryExceptions.indexOf(category) !== -1 || subcategory.toLowerCase().indexOf('manage') !== -1) { + hideOnlyRawDataNoticifation(); + return; + } + + var minuteInMilliseconds = 60000; + + if (this.dateLastChecked && new Date().valueOf() - this.dateLastChecked.valueOf() < minuteInMilliseconds) { + return; + } + + AjaxHelper_AjaxHelper.fetch({ + method: 'VisitsSummary.getVisits' + }).then(function (json) { + _this3.dateLastChecked = new Date(); + + if (json.value > 0) { + _this3.hasNoVisits = false; + hideOnlyRawDataNoticifation(); + return undefined; + } + + _this3.hasNoVisits = true; + + if (_this3.hasRawData) { + showOnlyRawDataNotification(); + return undefined; + } + + return AjaxHelper_AjaxHelper.fetch({ + method: 'Live.getLastVisitsDetails', + filter_limit: 1, + doNotFetchActions: 1 + }); + }).then(function (lastVisits) { + if (!lastVisits || lastVisits.length === 0) { + _this3.hasRawData = false; + hideOnlyRawDataNoticifation(); + return; + } + + _this3.hasRawData = true; + showOnlyRawDataNotification(); + }); + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue + + + +ReportingPagevue_type_script_lang_ts.render = ReportingPagevue_type_template_id_28b6d8b8_render + +/* harmony default export */ var ReportingPage = (ReportingPagevue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var ReportingPage_adapter = (createAngularJsAdapter({ + component: ReportingPage, + directiveName: 'piwikReportingPage' +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue?vue&type=template&id=3d203950 + +var ReportExportPopovervue_type_template_id_3d203950_hoisted_1 = { + class: "report-export-popover row", + id: "reportExport" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_2 = { + class: "col l6" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_3 = { + name: "format" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_4 = { + name: "option_flat" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_5 = { + name: "option_expanded" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_6 = { + name: "option_format_metrics" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_7 = { + class: "col l6" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_8 = { + name: "filter_type" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_9 = { + class: "filter_limit" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_10 = { + name: "filter_limit_all" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_11 = { + key: 0, + name: "filter_limit" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_12 = { + key: 1, + name: "filter_limit" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_13 = { + class: "col l12" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_14 = ["value"]; + +var ReportExportPopovervue_type_template_id_3d203950_hoisted_15 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])("\n "); + +var ReportExportPopovervue_type_template_id_3d203950_hoisted_16 = [ReportExportPopovervue_type_template_id_3d203950_hoisted_15]; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_17 = ["innerHTML"]; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_18 = { + class: "col l12" +}; +var ReportExportPopovervue_type_template_id_3d203950_hoisted_19 = ["href", "title"]; +function ReportExportPopovervue_type_template_id_3d203950_render(_ctx, _cache, $props, $setup, $data, $options) { + var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field"); + + var _directive_select_on_focus = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("select-on-focus"); + + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: 'radio', + name: 'format', + title: _ctx.translate('CoreHome_ExportFormat'), + modelValue: _ctx.reportFormat, + "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) { + return _ctx.reportFormat = $event; + }), + "full-width": true, + options: _ctx.availableReportFormats[_ctx.reportType] + }, null, 8, ["title", "modelValue", "options"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: 'checkbox', + name: 'option_flat', + title: _ctx.translate('CoreHome_FlattenReport'), + modelValue: _ctx.optionFlat, + "onUpdate:modelValue": _cache[1] || (_cache[1] = function ($event) { + return _ctx.optionFlat = $event; + }) + }, null, 8, ["title", "modelValue"]), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.hasSubtables]])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: 'checkbox', + name: 'option_expanded', + title: _ctx.translate('CoreHome_ExpandSubtables'), + modelValue: _ctx.optionExpanded, + "onUpdate:modelValue": _cache[2] || (_cache[2] = function ($event) { + return _ctx.optionExpanded = $event; + }) + }, null, 8, ["title", "modelValue"]), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.hasSubtables && !_ctx.optionFlat]])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: 'checkbox', + name: 'option_format_metrics', + title: _ctx.translate('CoreHome_FormatMetrics'), + modelValue: _ctx.optionFormatMetrics, + "onUpdate:modelValue": _cache[3] || (_cache[3] = function ($event) { + return _ctx.optionFormatMetrics = $event; + }) + }, null, 8, ["title", "modelValue"])])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_7, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_8, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: 'radio', + name: 'filter_type', + title: _ctx.translate('CoreHome_ReportType'), + modelValue: _ctx.reportType, + "onUpdate:modelValue": _cache[4] || (_cache[4] = function ($event) { + return _ctx.reportType = $event; + }), + "full-width": true, + options: _ctx.availableReportTypes + }, null, 8, ["title", "modelValue", "options"])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_9, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_10, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: 'radio', + name: 'filter_limit_all', + title: _ctx.translate('CoreHome_RowLimit'), + modelValue: _ctx.reportLimitAll, + "onUpdate:modelValue": _cache[5] || (_cache[5] = function ($event) { + return _ctx.reportLimitAll = $event; + }), + "full-width": true, + options: _ctx.limitAllOptions + }, null, 8, ["title", "modelValue", "options"])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !_ctx.maxFilterLimit || _ctx.maxFilterLimit <= 0]]), _ctx.reportLimitAll === 'no' && _ctx.maxFilterLimit <= 0 ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_11, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: 'number', + name: "filter_limit", + min: 1, + modelValue: _ctx.reportLimit, + "onUpdate:modelValue": _cache[6] || (_cache[6] = function ($event) { + return _ctx.reportLimit = $event; + }), + "full-width": true + }, null, 8, ["modelValue"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.reportLimitAll === 'no' && _ctx.maxFilterLimit > 0 ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_12, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, { + uicontrol: 'number', + name: 'filter_limit', + min: 1, + max: _ctx.maxFilterLimit, + modelValue: _ctx.reportLimit, + "onUpdate:modelValue": _cache[7] || (_cache[7] = function ($event) { + return _ctx.reportLimit = $event; + }), + value: _ctx.reportLimit, + "full-width": true, + title: _ctx.filterLimitTooltip + }, null, 8, ["max", "modelValue", "value", "title"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_13, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("textarea", { + readonly: "", + class: "exportFullUrl", + value: _ctx.exportLinkWithoutToken + }, ReportExportPopovervue_type_template_id_3d203950_hoisted_16, 8, ReportExportPopovervue_type_template_id_3d203950_hoisted_14), [[_directive_select_on_focus, {}]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { + class: "tooltip", + innerHTML: _ctx.$sanitize(_ctx.translate('CoreHome_ExportTooltipWithLink', '<a target=_blank href=\'?module=UsersManager&action=userSecurity\'>', '</a>', 'ENTER_YOUR_TOKEN_AUTH_HERE')) + }, null, 8, ReportExportPopovervue_type_template_id_3d203950_hoisted_17)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showUrl]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", ReportExportPopovervue_type_template_id_3d203950_hoisted_18, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + class: "btn", + href: _ctx.exportLink, + target: "_new", + title: _ctx.translate('CoreHome_ExportTooltip') + }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Export')), 9, ReportExportPopovervue_type_template_id_3d203950_hoisted_19), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", { + href: "javascript:", + onClick: _cache[8] || (_cache[8] = function ($event) { + return _ctx.showUrl = !_ctx.showUrl; + }), + class: "toggle-export-url" + }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('CoreHome_ShowExportUrl')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !_ctx.showUrl]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('CoreHome_HideExportUrl')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showUrl]])])])]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue?vue&type=template&id=3d203950 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue?vue&type=script&lang=ts +function ReportExportPopovervue_type_script_lang_ts_slicedToArray(arr, i) { return ReportExportPopovervue_type_script_lang_ts_arrayWithHoles(arr) || ReportExportPopovervue_type_script_lang_ts_iterableToArrayLimit(arr, i) || ReportExportPopovervue_type_script_lang_ts_unsupportedIterableToArray(arr, i) || ReportExportPopovervue_type_script_lang_ts_nonIterableRest(); } + +function ReportExportPopovervue_type_script_lang_ts_nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } + +function ReportExportPopovervue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return ReportExportPopovervue_type_script_lang_ts_arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return ReportExportPopovervue_type_script_lang_ts_arrayLikeToArray(o, minLen); } + +function ReportExportPopovervue_type_script_lang_ts_arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } + +function ReportExportPopovervue_type_script_lang_ts_iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } + +function ReportExportPopovervue_type_script_lang_ts_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } + + + + + + + +var ReportExportPopovervue_type_script_lang_ts_Field = useExternalPluginComponent('CorePluginsAdmin', 'Field'); +/* harmony default export */ var ReportExportPopovervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + components: { + Field: ReportExportPopovervue_type_script_lang_ts_Field + }, + directives: { + SelectOnFocus: SelectOnFocus + }, + props: { + hasSubtables: Boolean, + availableReportTypes: Object, + availableReportFormats: { + type: Object, + required: true + }, + maxFilterLimit: Number, + limitAllOptions: Object, + dataTable: { + type: Object, + required: true + }, + requestParams: [Object, String], + apiMethod: { + type: String, + required: true + }, + initialReportType: { + type: String, + default: 'default' + }, + initialReportLimit: { + type: [String, Number], + default: 100 + }, + initialReportLimitAll: { + type: String, + default: 'yes' + }, + initialOptionFlat: { + type: Boolean, + default: false + }, + initialOptionExpanded: { + type: Boolean, + default: true + }, + initialOptionFormatMetrics: { + type: Boolean, + default: false + }, + initialReportFormat: { + type: String, + default: 'XML' + } + }, + data: function data() { + return { + showUrl: false, + reportFormat: this.initialReportFormat, + optionFlat: this.initialOptionFlat, + optionExpanded: this.initialOptionExpanded, + optionFormatMetrics: this.initialOptionFormatMetrics, + reportType: this.initialReportType, + reportLimitAll: this.initialReportLimitAll, + reportLimit: typeof this.initialReportLimit === 'string' ? parseInt(this.initialReportLimit, 10) : this.initialReportLimit + }; + }, + watch: { + reportType: function reportType(newVal) { + if (!this.availableReportFormats[newVal][this.reportFormat]) { + this.reportFormat = 'XML'; + } + }, + reportLimit: function reportLimit(newVal, oldVal) { + if (this.maxFilterLimit && this.maxFilterLimit > 0 && newVal > this.maxFilterLimit) { + this.reportLimit = oldVal; + } + } + }, + computed: { + filterLimitTooltip: function filterLimitTooltip() { + var rowLimit = translate('CoreHome_RowLimit'); + var computedMetricMax = this.maxFilterLimit ? translate('General_ComputedMetricMax', this.maxFilterLimit.toString()) : ''; + return "".concat(rowLimit, " (").concat(computedMetricMax, ")"); + }, + exportLink: function exportLink() { + return this.getExportLink(true); + }, + exportLinkWithoutToken: function exportLinkWithoutToken() { + return this.getExportLink(false); + } + }, + methods: { + getExportLink: function getExportLink() { + var withToken = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var reportFormat = this.reportFormat, + apiMethod = this.apiMethod, + reportType = this.reportType; + var dataTable = this.dataTable; + + if (!reportFormat) { + return undefined; + } + + var requestParams = {}; + var limit = this.reportLimitAll === 'yes' ? -1 : this.reportLimit; + + if (this.requestParams && typeof this.requestParams === 'string') { + requestParams = JSON.parse(this.requestParams); + } + + var _dataTable$param = dataTable.param, + segment = _dataTable$param.segment, + label = _dataTable$param.label, + idGoal = _dataTable$param.idGoal, + idDimension = _dataTable$param.idDimension, + idSite = _dataTable$param.idSite; + var _dataTable$param2 = dataTable.param, + date = _dataTable$param2.date, + period = _dataTable$param2.period; + + if (reportFormat === 'RSS') { + date = 'last10'; + } + + if (typeof dataTable.param.dateUsedInGraph !== 'undefined') { + date = dataTable.param.dateUsedInGraph; + } + + var formatsUseDayNotRange = Matomo_Matomo.config.datatable_export_range_as_day.toLowerCase(); + + if (formatsUseDayNotRange.indexOf(reportFormat.toLowerCase()) !== -1 && dataTable.param.period === 'range') { + period = 'day'; + } // Below evolution graph, show daily exports + + + if (dataTable.param.period === 'range' && dataTable.param.viewDataTable === 'graphEvolution') { + period = 'day'; + } + + var exportUrlParams = { + module: 'API', + format: reportFormat, + idSite: idSite, + period: period, + date: date + }; + + if (reportType === 'processed') { + exportUrlParams.method = 'API.getProcessedReport'; + + var _apiMethod$split = apiMethod.split('.'); + + var _apiMethod$split2 = ReportExportPopovervue_type_script_lang_ts_slicedToArray(_apiMethod$split, 2); + + exportUrlParams.apiModule = _apiMethod$split2[0]; + exportUrlParams.apiAction = _apiMethod$split2[1]; + } else { + exportUrlParams.method = apiMethod; + } + + if (dataTable.param.compareDates && dataTable.param.compareDates.length) { + exportUrlParams.compareDates = dataTable.param.compareDates; + exportUrlParams.compare = '1'; + } + + if (dataTable.param.comparePeriods && dataTable.param.comparePeriods.length) { + exportUrlParams.comparePeriods = dataTable.param.comparePeriods; + exportUrlParams.compare = '1'; + } + + if (dataTable.param.compareSegments && dataTable.param.compareSegments.length) { + exportUrlParams.compareSegments = dataTable.param.compareSegments; + exportUrlParams.compare = '1'; + } + + if (typeof dataTable.param.filter_pattern !== 'undefined') { + exportUrlParams.filter_pattern = dataTable.param.filter_pattern; + } + + if (typeof dataTable.param.filter_pattern_recursive !== 'undefined') { + exportUrlParams.filter_pattern_recursive = dataTable.param.filter_pattern_recursive; + } + + if (window.$.isPlainObject(requestParams)) { + Object.entries(requestParams).forEach(function (_ref) { + var _ref2 = ReportExportPopovervue_type_script_lang_ts_slicedToArray(_ref, 2), + index = _ref2[0], + param = _ref2[1]; + + var value = param; + + if (value === true) { + value = 1; + } else if (value === false) { + value = 0; + } + + exportUrlParams[index] = value; + }); + } + + if (this.optionFlat) { + exportUrlParams.flat = 1; + + if (typeof dataTable.param.include_aggregate_rows !== 'undefined' && dataTable.param.include_aggregate_rows === '1') { + exportUrlParams.include_aggregate_rows = 1; + } + } + + if (!this.optionFlat && this.optionExpanded) { + exportUrlParams.expanded = 1; + } + + if (this.optionFormatMetrics) { + exportUrlParams.format_metrics = 1; + } + + if (dataTable.param.pivotBy) { + exportUrlParams.pivotBy = dataTable.param.pivotBy; + exportUrlParams.pivotByColumnLimit = 20; + + if (dataTable.props.pivot_by_column) { + exportUrlParams.pivotByColumn = dataTable.props.pivot_by_column; + } + } + + if (reportFormat === 'CSV' || reportFormat === 'TSV' || reportFormat === 'RSS') { + exportUrlParams.translateColumnNames = 1; + exportUrlParams.language = Matomo_Matomo.language; + } + + if (typeof segment !== 'undefined') { + exportUrlParams.segment = decodeURIComponent(segment); + } // Export Goals specific reports + + + if (typeof idGoal !== 'undefined' && idGoal !== '-1') { + exportUrlParams.idGoal = idGoal; + } // Export Dimension specific reports + + + if (typeof idDimension !== 'undefined' && idDimension !== '-1') { + exportUrlParams.idDimension = idDimension; + } + + if (label) { + var labelParts = label.split(','); + + if (labelParts.length > 1) { + exportUrlParams.label = labelParts; + } else { + var _labelParts = ReportExportPopovervue_type_script_lang_ts_slicedToArray(labelParts, 1); + + exportUrlParams.label = _labelParts[0]; + } + } + + exportUrlParams.token_auth = 'ENTER_YOUR_TOKEN_AUTH_HERE'; + + if (withToken === true) { + exportUrlParams.token_auth = Matomo_Matomo.token_auth; + exportUrlParams.force_api_session = 1; + } + + exportUrlParams.filter_limit = limit; + var prefix = window.location.href.split('?')[0]; + return "".concat(prefix, "?").concat(src_MatomoUrl_MatomoUrl.stringify(exportUrlParams)); + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue + + + +ReportExportPopovervue_type_script_lang_ts.render = ReportExportPopovervue_type_template_id_3d203950_render + +/* harmony default export */ var ReportExportPopover = (ReportExportPopovervue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportExport/ReportExport.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + + + +var ReportExport_window = window, + ReportExport_$ = ReportExport_window.$; +/* harmony default export */ var ReportExport = ({ + mounted: function mounted(el, binding) { + el.addEventListener('click', function () { + var popoverParamBackup = src_MatomoUrl_MatomoUrl.hashParsed.value.popover; + var dataTable = ReportExport_$(el).closest('[data-report]').data('uiControlObject'); + var popover = window.Piwik_Popover.showLoading('Export'); + var formats = binding.value.reportFormats; + var reportLimit = dataTable.param.filter_limit; + + if (binding.value.maxFilterLimit > 0) { + reportLimit = Math.min(reportLimit, binding.value.maxFilterLimit); + } + + var optionFlat = dataTable.param.flat === true || dataTable.param.flat === 1 || dataTable.param.flat === '1'; + var props = { + initialReportType: 'default', + initialReportLimit: reportLimit > 0 ? reportLimit : 100, + initialReportLimitAll: reportLimit === -1 ? 'yes' : 'no', + initialOptionFlat: optionFlat, + initialOptionExpanded: true, + initialOptionFormatMetrics: false, + hasSubtables: optionFlat || dataTable.numberOfSubtables > 0, + availableReportFormats: { + default: formats, + processed: { + XML: formats.XML, + JSON: formats.JSON + } + }, + availableReportTypes: { + default: translate('CoreHome_StandardReport'), + processed: translate('CoreHome_ReportWithMetadata') + }, + limitAllOptions: { + yes: translate('General_All'), + no: translate('CoreHome_CustomLimit') + }, + maxFilterLimit: binding.value.maxFilterLimit, + dataTable: dataTable, + requestParams: binding.value.requestParams, + apiMethod: binding.value.apiMethod + }; + var app = createVueApp({ + template: "\n <popover v-bind=\"bind\"/>", + data: function data() { + return { + bind: props + }; + } + }); + app.component('popover', ReportExportPopover); + var mountPoint = document.createElement('div'); + app.mount(mountPoint); + var reportTitle = binding.value.reportTitle; + window.Piwik_Popover.setTitle("".concat(translate('General_Export'), " ").concat(Matomo_Matomo.helper.htmlEntities(reportTitle))); + window.Piwik_Popover.setContent(mountPoint); + window.Piwik_Popover.onClose(function () { + app.unmount(); + + if (popoverParamBackup !== '') { + setTimeout(function () { + src_MatomoUrl_MatomoUrl.updateHash(Object.assign(Object.assign({}, src_MatomoUrl_MatomoUrl.hashParsed.value), {}, { + popover: popoverParamBackup + })); + + if (binding.value.onClose) { + binding.value.onClose(); + } + }, 100); + } + }); + setTimeout(function () { + popover.dialog(); + ReportExport_$('.exportFullUrl, .btn', popover).tooltip({ + track: true, + show: false, + hide: false + }); + }, 100); + }); + } +}); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportExport/ReportExport.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +function piwikReportExport($timeout) { + return { + restrict: 'A', + scope: { + reportTitle: '@', + requestParams: '@', + reportFormats: '@', + apiMethod: '@', + maxFilterLimit: '@' + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + link: function piwikReportExportLink(scope, element) { + var binding = { + instance: null, + value: { + reportTitle: scope.reportTitle, + requestParams: scope.requestParams, + reportFormats: typeof scope.reportFormats === 'string' ? JSON.parse(scope.reportFormats) : scope.reportFormats, + apiMethod: scope.apiMethod, + maxFilterLimit: parseInt(scope.maxFilterLimit, 10), + onClose: function onClose() { + $timeout(function () { + window.angular.element(document).injector().get('$rootScope').$apply(); + }, 10); + } + }, + oldValue: null, + modifiers: {}, + dir: {} + }; + ReportExport.mounted(element[0], binding); + } + }; +} +piwikReportExport.$inject = ['$timeout']; +window.angular.module('piwikApp').directive('piwikReportExport', piwikReportExport); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Sparkline/Sparkline.vue?vue&type=template&id=693cd955 + +var Sparklinevue_type_template_id_693cd955_hoisted_1 = ["src"]; +function Sparklinevue_type_template_id_693cd955_render(_ctx, _cache, $props, $setup, $data, $options) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("img", { + src: _ctx.sparklineUrl + }, null, 8, Sparklinevue_type_template_id_693cd955_hoisted_1); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Sparkline/Sparkline.vue?vue&type=template&id=693cd955 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Sparkline/Sparkline.vue?vue&type=script&lang=ts + + + + + + +/* harmony default export */ var Sparklinevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + seriesIndices: Array, + params: Object + }, + data: function data() { + return { + isWidget: false + }; + }, + mounted: function mounted() { + this.isWidget = !!this.$el.closest('[widgetId]'); + }, + computed: { + sparklineUrl: function sparklineUrl() { + var seriesIndices = this.seriesIndices, + params = this.params; + var sparklineColors = Matomo_Matomo.getSparklineColors(); + + if (seriesIndices) { + sparklineColors.lineColor = sparklineColors.lineColor.filter(function (c, index) { + return seriesIndices.indexOf(index) !== -1; + }); + } + + var colors = JSON.stringify(sparklineColors); + var defaultParams = { + forceView: '1', + viewDataTable: 'sparkline', + widget: this.isWidget ? '1' : '0', + showtitle: '1', + colors: colors, + random: Date.now(), + date: this.defaultDate + }; + var helper = new AjaxHelper_AjaxHelper(); + var urlParams = helper.mixinDefaultGetParams(Object.assign(Object.assign({}, defaultParams), params)); // Append the token_auth to the URL if it was set (eg. embed dashboard) + + var token_auth = src_MatomoUrl_MatomoUrl.parsed.value.token_auth; + + if (token_auth && token_auth.length && Matomo_Matomo.shouldPropagateTokenAuth) { + urlParams.token_auth = token_auth; + } + + return "?".concat(src_MatomoUrl_MatomoUrl.stringify(urlParams)); + }, + defaultDate: function defaultDate() { + if (Matomo_Matomo.period === 'range') { + return "".concat(Matomo_Matomo.startDateString, ",").concat(Matomo_Matomo.endDateString); + } + + var dateRange = Range_RangePeriod.getLastNRange(Matomo_Matomo.period, 30, Matomo_Matomo.currentDateString).getDateRange(); + var piwikMinDate = new Date(Matomo_Matomo.minDateYear, Matomo_Matomo.minDateMonth - 1, Matomo_Matomo.minDateDay); + + if (dateRange[0] < piwikMinDate) { + dateRange[0] = piwikMinDate; + } + + var startDateStr = format(dateRange[0]); + var endDateStr = format(dateRange[1]); + return "".concat(startDateStr, ",").concat(endDateStr); + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Sparkline/Sparkline.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Sparkline/Sparkline.vue + + + +Sparklinevue_type_script_lang_ts.render = Sparklinevue_type_template_id_693cd955_render + +/* harmony default export */ var Sparkline = (Sparklinevue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Sparkline/Sparkline.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var Sparkline_adapter = (createAngularJsAdapter({ + component: Sparkline, + scope: { + seriesIndices: { + angularJsBind: '<' + }, + params: { + angularJsBind: '<' + } + }, + directiveName: 'piwikSparkline', + restrict: 'E' +})); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Progressbar/Progressbar.vue?vue&type=template&id=0048ddd7 + +var Progressbarvue_type_template_id_0048ddd7_hoisted_1 = { + class: "progressbar" +}; +var Progressbarvue_type_template_id_0048ddd7_hoisted_2 = { + class: "progress" +}; + +var Progressbarvue_type_template_id_0048ddd7_hoisted_3 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("img", { + src: "plugins/Morpheus/images/loading-blue.gif", + style: { + "margin-right": "3.5px" + } +}, null, -1); + +var Progressbarvue_type_template_id_0048ddd7_hoisted_4 = ["innerHTML"]; +function Progressbarvue_type_template_id_0048ddd7_render(_ctx, _cache, $props, $setup, $data, $options) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", Progressbarvue_type_template_id_0048ddd7_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", Progressbarvue_type_template_id_0048ddd7_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", { + class: "determinate", + style: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeStyle"])([{ + "width": "0" + }, { + width: "".concat(_ctx.actualProgress, "%") + }]) + }, null, 4)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, [Progressbarvue_type_template_id_0048ddd7_hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", { + class: "label", + innerHTML: _ctx.$sanitize(_ctx.label) + }, null, 8, Progressbarvue_type_template_id_0048ddd7_hoisted_4)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !!_ctx.label]])]); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Progressbar/Progressbar.vue?vue&type=template&id=0048ddd7 + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/Progressbar/Progressbar.vue?vue&type=script&lang=ts + +/* harmony default export */ var Progressbarvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + progress: { + type: Number, + required: true + }, + label: String + }, + computed: { + actualProgress: function actualProgress() { + if (this.progress > 100) { + return 100; + } + + if (this.progress < 0) { + return 0; + } + + return this.progress; + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Progressbar/Progressbar.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Progressbar/Progressbar.vue + + + +Progressbarvue_type_script_lang_ts.render = Progressbarvue_type_template_id_0048ddd7_render + +/* harmony default export */ var Progressbar = (Progressbarvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Progressbar/Progressbar.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +/* harmony default export */ var Progressbar_adapter = (createAngularJsAdapter({ + component: Progressbar, + scope: { + progress: { + angularJsBind: '=' + }, + label: { + angularJsBind: '=' + } + }, + directiveName: 'piwikProgressbar' +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentIntro/ContentIntro.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/* harmony default export */ var ContentIntro = ({ + mounted: function mounted(el) { + el.classList.add('piwik-content-intro'); + }, + updated: function updated(el) { + // classes can be overwritten when elements bind to :class, nextTick + using + // updated avoids this problem (and doing in both mounted and updated avoids a temporary + // state where the classes aren't added) + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () { + el.classList.add('piwik-content-intro'); + }); + } +}); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentIntro/ContentIntro.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +function piwikContentIntro() { + return { + restrict: 'A', + link: function piwikContentIntroLink(scope, element) { + ContentIntro.mounted(element[0]); + } + }; +} +window.angular.module('piwikApp').directive('piwikContentIntro', piwikContentIntro); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentTable/ContentTable.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/* harmony default export */ var ContentTable = ({ + mounted: function mounted(el) { + el.classList.add('card', 'card-table', 'entityTable'); + }, + updated: function updated(el) { + // classes can be overwritten when elements bind to :class, nextTick + using + // updated avoids this problem (and doing in both mounted and updated avoids a temporary + // state where the classes aren't added) + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () { + el.classList.add('card', 'card-table', 'entityTable'); + }); + } +}); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentTable/ContentTable.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +function piwikContentTable() { + return { + restrict: 'A', + link: function piwikContentTableLink(scope, element) { + ContentTable.mounted(element[0]); + } + }; +} +window.angular.module('piwikApp').directive('piwikContentTable', piwikContentTable); +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-babel/node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/@vue/cli-plugin-babel/node_modules/thread-loader/dist/cjs.js!./node_modules/babel-loader/lib!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist/templateLoader.js??ref--6!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue?vue&type=template&id=00d5220c + +var AjaxFormvue_type_template_id_00d5220c_hoisted_1 = { + ref: "root" +}; +function AjaxFormvue_type_template_id_00d5220c_render(_ctx, _cache, $props, $setup, $data, $options) { + return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", AjaxFormvue_type_template_id_00d5220c_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default", { + formData: _ctx.formData, + submitApiMethod: _ctx.submitApiMethod, + sendJsonPayload: _ctx.sendJsonPayload, + noErrorNotification: _ctx.noErrorNotification, + noSuccessNotification: _ctx.noSuccessNotification, + submitForm: _ctx.submitForm, + isSubmitting: _ctx.isSubmitting, + successfulPostResponse: _ctx.successfulPostResponse, + errorPostResponse: _ctx.errorPostResponse + })], 512); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue?vue&type=template&id=00d5220c + +// CONCATENATED MODULE: ./node_modules/@vue/cli-plugin-typescript/node_modules/cache-loader/dist/cjs.js??ref--14-0!./node_modules/babel-loader/lib!./node_modules/@vue/cli-plugin-typescript/node_modules/ts-loader??ref--14-2!./node_modules/@vue/cli-service/node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/@vue/cli-service/node_modules/vue-loader-v16/dist??ref--0-1!./plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue?vue&type=script&lang=ts + + + + +var AjaxFormvue_type_script_lang_ts_window = window, + AjaxFormvue_type_script_lang_ts_$ = AjaxFormvue_type_script_lang_ts_window.$; +/** + * Example usage: + * + * <AjaxForm :form-data="myData" ...> + * <template v-slot:default="ajaxForm"> + * <Field v-model="myData.something" .../> + * <SaveButton @confirm="ajaxForm.submitForm()" :saving="ajaxForm.isSubmitting"/> + * </template> + * </AjaxForm> + * + * Data does not flow upwards in any way. :form-data is used for submitForm(), and the + * containing component binds to properties of the object in controls to fill the object. + */ + +/* harmony default export */ var AjaxFormvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({ + props: { + formData: { + type: Object, + required: true + }, + submitApiMethod: { + type: String, + required: true + }, + sendJsonPayload: Boolean, + noErrorNotification: Boolean, + noSuccessNotification: Boolean + }, + data: function data() { + return { + isSubmitting: false, + successfulPostResponse: null, + errorPostResponse: null + }; + }, + emits: ['update:modelValue'], + mounted: function mounted() { + var _this = this; + + // on submit call controller submit method + AjaxFormvue_type_script_lang_ts_$(this.$refs.root).on('click', 'input[type=submit]', function () { + _this.submitForm(); + }); + }, + methods: { + submitForm: function submitForm() { + var _this2 = this; + + this.successfulPostResponse = null; + this.errorPostResponse = null; + var postParams = this.formData; + + if (this.sendJsonPayload) { + postParams = { + data: JSON.stringify(this.formData) + }; + } + + this.isSubmitting = true; + AjaxHelper_AjaxHelper.post({ + module: 'API', + method: this.submitApiMethod + }, postParams, { + createErrorNotification: !this.noErrorNotification + }).then(function (response) { + _this2.successfulPostResponse = response; + + if (!_this2.noSuccessNotification) { + var notificationInstanceId = Notifications_store.show({ + message: translate('General_YourChangesHaveBeenSaved'), + context: 'success', + type: 'toast', + id: 'ajaxHelper' + }); + Notifications_store.scrollToNotification(notificationInstanceId); + } + }).catch(function (error) { + _this2.errorPostResponse = error.message; + }).finally(function () { + _this2.isSubmitting = false; + }); + } + } +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue?vue&type=script&lang=ts + +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue + + + +AjaxFormvue_type_script_lang_ts.render = AjaxFormvue_type_template_id_00d5220c_render + +/* harmony default export */ var AjaxForm = (AjaxFormvue_type_script_lang_ts); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/AjaxForm/AjaxForm.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + +var AjaxForm_adapter_window = window, + AjaxForm_adapter_$ = AjaxForm_adapter_window.$; +/** + * AngularJS directive that manages an AJAX form. + * + * This directive will detect inputs & selects defined within an element and when a + * submit button is clicked, will post data from the inputs & selects to a Piwik API method. + * + * When the POST request is finished the result will, by default, be displayed as a + * notification. + * + * This directive accepts the following attributes: + * + * - **submit-api-method**: **required** The Piwik API method that handles the POST request. + * - **send-json-payload**: Whether to send the data as a form encoded URL or to send it as JSON. + * If sending as JSON, the payload will still be a form encoded value, + * but will contain a JSON object like `{data: {...form data...}}`. + * + * This is for forms with lots of fields where having the same number + * of parameters in an API method would not be desired. + * - **no-error-notification**: If true, does not display an error notification if the AJAX post + * fails. + * - **no-success-notification**: If true, does not display an error notification if the AJAX + * results in success. + * + * **Custom Success/Error Handling** + * + * On success/failure, the response will be stored in controller scope. Child elements of a + * piwik-ajax-form element can access this data, and thus, can customize what happens when + * a form submit succeeds/fails. + * + * See the ajax-form.controller.js file for more info. + * + * Usage: + * + * <div piwik-ajax-form + * submit-api-method="'MyPlugin.myFormSaveMethod'" + * send-json-payload="true" + * ng-model="myFormData"> + * + * <h2>My Form</h2> + * <input name="myOption" value="myDefaultValue" type="text" /> + * <input name="myOtherOption" type="checkbox" checked="checked" /> + * <input type="submit" value="Submit" ng-disabled="ajaxForm.isSubmitting" /> + * + * <div piwik-notification context='error' ng-show="errorPostResponse">ERROR!</div> + * </div> + * @deprecated + */ + +function piwikAjaxForm($parse) { + return { + restrict: 'A', + scope: { + submitApiMethod: '=', + sendJsonPayload: '=', + noErrorNotification: '=', + noSuccessNotification: '=', + useCustomDataBinding: '=' + }, + require: '?ngModel', + transclude: true, + compile: function piwikAjaxFormCompile(compileElement, compileAttrs) { + compileAttrs.noErrorNotification = !!compileAttrs.noErrorNotification; // eslint-disable-next-line @typescript-eslint/no-explicit-any + + return function piwikAjaxFormLink(scope, element, attrs, ngModel, transclude) { + if (!scope.submitApiMethod) { + throw new Error('submitApiMethod is required'); + } + + scope.ajaxForm = {}; + scope.ajaxForm.submitApiMethod = scope.submitApiMethod; + scope.ajaxForm.sendJsonPayload = scope.sendJsonPayload; + scope.ajaxForm.noErrorNotification = scope.noErrorNotification; + scope.ajaxForm.noSuccessNotification = scope.noSuccessNotification; + scope.ajaxForm.data = {}; // if a model is supplied, initiate form data w/ model value + + if (ngModel) { + // probably redundant, but I cannot find another way to get the ng model value here + var ngModelGetter = $parse(attrs.ngModel); + scope.ajaxForm.data = ngModelGetter(scope.$parent); + } + + var specialBindDirective = { + mounted: function mounted(el, binding) { + scope.ajaxForm.submitForm = binding.value.submitForm; + } + }; + var rootTemplate = "\n <AjaxForm\n :form-data=\"data\"\n :submit-api-method=\"submitApiMethod\"\n :send-json-payload=\"sendJsonPayload\"\n :no-error-notification=\"noErrorNotification\"\n :no-success-notification=\"noSuccessNotification\"\n >\n <template v-slot:default=\"ajaxFormVue\">\n <div\n ref=\"transcludeTarget\"\n v-special-bind-directive=\"{ submitForm: ajaxFormVue.submitForm }\"\n />\n </template>\n </AjaxForm>"; + var app = createVueApp({ + template: rootTemplate, + data: function data() { + return scope.ajaxForm; + }, + setup: function setup() { + var transcludeTarget = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(null); + return { + transcludeTarget: transcludeTarget + }; + } + }); + app.component('AjaxForm', AjaxForm); + app.directive('SpecialBindDirective', specialBindDirective); + var vm = app.mount(element[0]); + element.on('$destroy', function () { + app.unmount(); + }); + + function setFormValueFromInput(inputElement, skipScopeApply) { + var name = AjaxForm_adapter_$(inputElement).attr('name'); + var val; + + if (AjaxForm_adapter_$(inputElement).attr('type') === 'checkbox') { + val = AjaxForm_adapter_$(inputElement).is(':checked'); + } else { + val = AjaxForm_adapter_$(inputElement).val(); + } + + scope.ajaxForm.data[name] = val; + + if (!skipScopeApply) { + setTimeout(function () { + scope.$apply(); + }, 0); + } + } // on change of any input, change appropriate value in model, but only if requested + + + if (!scope.useCustomDataBinding) { + element.on('change', 'input,select', function (event) { + setFormValueFromInput(event.target); + }); + } // make sure child elements can access this directive's scope + // eslint-disable-next-line @typescript-eslint/no-explicit-any + + + transclude(scope, function (clone, transcludeScope) { + if (!transcludeScope.useCustomDataBinding) { + var $inputs = clone.find('input,select').not('[type=submit]'); // initialize form data to input values (include <select>s + + $inputs.each(function inputEach() { + setFormValueFromInput(this, true); + }); + } // eslint-disable-next-line @typescript-eslint/no-explicit-any + + + AjaxForm_adapter_$(vm.transcludeTarget).append(clone); + }); + }; + } + }; +} + +piwikAjaxForm.$inject = ['$parse']; +window.angular.module('piwikApp').directive('piwikAjaxForm', piwikAjaxForm); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/getFormattedEvolution.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + +function calculateEvolution(currentValue, pastValue) { + var pastValueParsed = parseInt(pastValue, 10); + var currentValueParsed = parseInt(currentValue, 10) - pastValueParsed; + var evolution; + + if (currentValueParsed === 0 || Number.isNaN(currentValueParsed)) { + evolution = 0; + } else if (pastValueParsed === 0 || Number.isNaN(pastValueParsed)) { + evolution = 100; + } else { + evolution = currentValueParsed / pastValueParsed * 100; + } + + return evolution; +} + +function formatEvolution(evolution) { + return "".concat(evolution > 0 ? Matomo_Matomo.numbers.symbolPlus : '').concat(Math.round(evolution), "}%"); +} + +function getFormattedEvolution(currentValue, pastValue) { + var evolution = calculateEvolution(currentValue, pastValue); + return formatEvolution(evolution); +} +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + + + +/* harmony default export */ var ActivityIndicator_adapter = (createAngularJsAdapter({ + component: ActivityIndicator, + scope: { + loading: { + vue: 'loading', + angularJsBind: '<' + }, + loadingMessage: { + vue: 'loadingMessage', + angularJsBind: '<', + default: function _default() { + return translate('General_LoadingData'); + } + } + }, + $inject: [], + directiveName: 'piwikActivityIndicator' +})); +// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/CookieHelper/CookieHelper.ts +/* + * General utils for managing cookies in Typescript. + */ +// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types +function setCookie(name, val, seconds) { + var date = new Date(); // set default day to 3 days + + if (!seconds) { + // eslint-disable-next-line no-param-reassign + seconds = 3 * 24 * 60 * 1000; + } // Set it expire in n days + + + date.setTime(date.getTime() + seconds); // Set it + + document.cookie = "".concat(name, "=").concat(val, "; expires=").concat(date.toUTCString(), "; path=/"); +} // eslint-disable-next-line consistent-return,@typescript-eslint/explicit-module-boundary-types + +function getCookie(name) { + var value = "; ".concat(document.cookie); + var parts = value.split("; ".concat(name, "=")); // if cookie not exist return null + // eslint-disable-next-line eqeqeq + + if (parts.length == 2) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + var data = parts.pop().split(';').shift(); + + if (typeof data !== 'undefined') { + return data; + } + } + + return null; +} // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types + +function deleteCookie(name) { + var date = new Date(); // Set it expire in -1 days + + date.setTime(date.getTime() + -1 * 24 * 60 * 60 * 1000); // Set it + + document.cookie = "".concat(name, "=; expires=").concat(date.toUTCString(), "; path=/"); +} // CONCATENATED MODULE: ./plugins/CoreHome/vue/src/index.ts /*! * Matomo - free/libre analytics platform @@ -5556,6 +12223,65 @@ NotificationGroupvue_type_script_lang_ts.render = NotificationGroupvue_type_temp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js diff --git a/plugins/CoreHome/vue/dist/CoreHome.umd.min.js b/plugins/CoreHome/vue/dist/CoreHome.umd.min.js index 4b0e64d200..c4f4956925 100644 --- a/plugins/CoreHome/vue/dist/CoreHome.umd.min.js +++ b/plugins/CoreHome/vue/dist/CoreHome.umd.min.js @@ -1,275 +1,566 @@ -(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("vue")):"function"===typeof define&&define.amd?define([],t):"object"===typeof exports?exports["CoreHome"]=t(require("vue")):e["CoreHome"]=t(e["Vue"])})("undefined"!==typeof self?self:this,(function(e){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="plugins/CoreHome/vue/dist/",n(n.s="fae3")}({2342:function(e,t,n){"use strict"; +(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("vue")):"function"===typeof define&&define.amd?define([],t):"object"===typeof exports?exports["CoreHome"]=t(require("vue")):e["CoreHome"]=t(e["Vue"])})("undefined"!==typeof self?self:this,(function(e){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="plugins/CoreHome/vue/dist/",n(n.s="fae3")}({2342:function(e,t,n){"use strict"; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */window.hasBlockedContent=!1},"8bbf":function(t,n){t.exports=e},fae3:function(e,t,n){"use strict";if(n.r(t),n.d(t,"createAngularJsAdapter",(function(){return wt})),n.d(t,"activityIndicatorAdapter",(function(){return yr})),n.d(t,"ActivityIndicator",(function(){return br})),n.d(t,"translate",(function(){return C})),n.d(t,"alertAdapter",(function(){return Dr})),n.d(t,"AjaxHelper",(function(){return Ne})),n.d(t,"setCookie",(function(){return Cr})),n.d(t,"getCookie",(function(){return Sr})),n.d(t,"deleteCookie",(function(){return Pr})),n.d(t,"MatomoUrl",(function(){return ke})),n.d(t,"Matomo",(function(){return D})),n.d(t,"Periods",(function(){return p})),n.d(t,"Day",(function(){return z})),n.d(t,"Week",(function(){return X})),n.d(t,"Month",(function(){return re})),n.d(t,"Year",(function(){return se})),n.d(t,"Range",(function(){return R})),n.d(t,"format",(function(){return S})),n.d(t,"getToday",(function(){return P})),n.d(t,"parseDate",(function(){return E})),n.d(t,"todayIsInRange",(function(){return T})),n.d(t,"Dropdown",(function(){return Be})),n.d(t,"FocusAnywhereButHere",(function(){return Re})),n.d(t,"FocusIf",(function(){return Je})),n.d(t,"MatomoDialog",(function(){return ut})),n.d(t,"ExpandOnClick",(function(){return Xe})),n.d(t,"ExpandOnHover",(function(){return ot})),n.d(t,"EnrichedHeadline",(function(){return Mt})),n.d(t,"ContentBlock",(function(){return qt})),n.d(t,"Comparisons",(function(){return Nn})),n.d(t,"Menudropdown",(function(){return zn})),n.d(t,"DatePicker",(function(){return rr})),n.d(t,"DateRangePicker",(function(){return sr})),n.d(t,"PeriodDatePicker",(function(){return fr})),n.d(t,"Notification",(function(){return Fr})),n.d(t,"NotificationGroup",(function(){return Xr})),n.d(t,"NotificationsStore",(function(){return zr})),"undefined"!==typeof window){var r=window.document.currentScript,a=r&&r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);a&&(n.p=a[1])}n("2342");var o=n("8bbf");function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function c(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function s(e,t,n){return t&&c(e.prototype,t),n&&c(e,n),e}function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} + */window.hasBlockedContent=!1},"8bbf":function(t,n){t.exports=e},fae3:function(e,t,n){"use strict";if(n.r(t),n.d(t,"createVueApp",(function(){return dt})),n.d(t,"useExternalPluginComponent",(function(){return $n})),n.d(t,"DirectiveUtilities",(function(){return $t})),n.d(t,"debounce",(function(){return Gi})),n.d(t,"getFormattedEvolution",(function(){return Eu})),n.d(t,"createAngularJsAdapter",(function(){return kt})),n.d(t,"transformAngularJsBoolAttr",(function(){return St})),n.d(t,"transformAngularJsIntAttr",(function(){return Ct})),n.d(t,"removeAngularJsSpecificProperties",(function(){return jt})),n.d(t,"clone",(function(){return Et})),n.d(t,"cloneThenApply",(function(){return Dt})),n.d(t,"activityIndicatorAdapter",(function(){return Du})),n.d(t,"ActivityIndicator",(function(){return go})),n.d(t,"translate",(function(){return C})),n.d(t,"translateOrDefault",(function(){return E})),n.d(t,"Alert",(function(){return ut})),n.d(t,"AjaxHelper",(function(){return Ze})),n.d(t,"setCookie",(function(){return Pu})),n.d(t,"getCookie",(function(){return Vu})),n.d(t,"deleteCookie",(function(){return Nu})),n.d(t,"MatomoUrl",(function(){return Ee})),n.d(t,"Matomo",(function(){return S})),n.d(t,"Periods",(function(){return p})),n.d(t,"Day",(function(){return z})),n.d(t,"Week",(function(){return Z})),n.d(t,"Month",(function(){return ie})),n.d(t,"Year",(function(){return se})),n.d(t,"Range",(function(){return H})),n.d(t,"format",(function(){return D})),n.d(t,"getToday",(function(){return P})),n.d(t,"parseDate",(function(){return V})),n.d(t,"todayIsInRange",(function(){return N})),n.d(t,"DropdownMenu",(function(){return Pt})),n.d(t,"FocusAnywhereButHere",(function(){return Bt})),n.d(t,"FocusIf",(function(){return Rt})),n.d(t,"Tooltips",(function(){return Rr})),n.d(t,"MatomoDialog",(function(){return Cn})),n.d(t,"ExpandOnClick",(function(){return Qt})),n.d(t,"ExpandOnHover",(function(){return rn})),n.d(t,"ShowSensitiveData",(function(){return cn})),n.d(t,"DropdownButton",(function(){return pn})),n.d(t,"SelectOnFocus",(function(){return vn})),n.d(t,"SideNav",(function(){return wn})),n.d(t,"EnrichedHeadline",(function(){return qn})),n.d(t,"ContentBlock",(function(){return tr})),n.d(t,"Comparisons",(function(){return _r})),n.d(t,"MenuItemsDropdown",(function(){return ti})),n.d(t,"DatePicker",(function(){return ci})),n.d(t,"DateRangePicker",(function(){return fi})),n.d(t,"PeriodDatePicker",(function(){return yi})),n.d(t,"Notification",(function(){return ol})),n.d(t,"NotificationGroup",(function(){return wl})),n.d(t,"NotificationsStore",(function(){return hl})),n.d(t,"SitesStore",(function(){return Wi})),n.d(t,"SiteSelector",(function(){return Yi})),n.d(t,"QuickAccess",(function(){return pa})),n.d(t,"FieldArray",(function(){return Ea})),n.d(t,"MultiPairField",(function(){return Ua})),n.d(t,"PeriodSelector",(function(){return No})),n.d(t,"ReportingMenu",(function(){return Zl})),n.d(t,"ReportingMenuStore",(function(){return Hl})),n.d(t,"ReportingPagesStore",(function(){return El})),n.d(t,"ReportMetadataStore",(function(){return cc})),n.d(t,"WidgetsStore",(function(){return Ql})),n.d(t,"WidgetLoader",(function(){return hc})),n.d(t,"WidgetContainer",(function(){return Vc})),n.d(t,"WidgetByDimensionContainer",(function(){return Wc})),n.d(t,"Widget",(function(){return Xc})),n.d(t,"ReportingPage",(function(){return ws})),n.d(t,"ReportExport",(function(){return Xs})),n.d(t,"Sparkline",(function(){return ru})),n.d(t,"Progressbar",(function(){return uu})),n.d(t,"ContentIntro",(function(){return du})),n.d(t,"ContentTable",(function(){return mu})),n.d(t,"AjaxForm",(function(){return wu})),"undefined"!==typeof window){var r=window.document.currentScript,i=r&&r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);i&&(n.p=i[1])}n("2342");var a=n("8bbf");function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function l(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function c(e,t,n){return t&&l(e.prototype,t),n&&l(e,n),e}function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var u,d=function(){function e(){i(this,e),l(this,"periods",{}),l(this,"periodOrder",[])}return s(e,[{key:"addCustomPeriod",value:function(e,t){if(this.periods[e])throw new Error('The "'.concat(e,'" period already exists! It cannot be overridden.'));this.periods[e]=t,this.periodOrder.push(e)}},{key:"getAllLabels",value:function(){return Array().concat(this.periodOrder)}},{key:"get",value:function(e){var t=this.periods[e];if(!t)throw new Error("Invalid period label: ".concat(e));return t}},{key:"parse",value:function(e,t){return this.get(e).parse(t)}},{key:"isRecognizedPeriod",value:function(e){return!!this.periods[e]}}]),e}(),p=new d;function f(e){return g(e)||v(e)||h(e)||m()}function m(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function h(e,t){if(e){if("string"===typeof e)return b(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?b(e,t):void 0}}function v(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function g(e){if(Array.isArray(e))return b(e)}function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r} + */var u,d=function(){function e(){o(this,e),s(this,"periods",{}),s(this,"periodOrder",[])}return c(e,[{key:"addCustomPeriod",value:function(e,t){if(this.periods[e])throw new Error('The "'.concat(e,'" period already exists! It cannot be overridden.'));this.periods[e]=t,this.periodOrder.push(e)}},{key:"getAllLabels",value:function(){return Array().concat(this.periodOrder)}},{key:"get",value:function(e){var t=this.periods[e];if(!t)throw new Error("Invalid period label: ".concat(e));return t}},{key:"parse",value:function(e,t){return this.get(e).parse(t)}},{key:"isRecognizedPeriod",value:function(e){return!!this.periods[e]}}]),e}(),p=new d;function m(e){return v(e)||g(e)||h(e)||f()}function f(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function h(e,t){if(e){if("string"===typeof e)return b(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?b(e,t):void 0}}function g(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function v(e){if(Array.isArray(e))return b(e)}function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var y=window,w=y.piwik,k=y.broadcast,O=y.piwikHelper;w.helper=O,w.broadcast=k,w.updateDateInTitle=function(e,t){if($(".top_controls #periodString").length&&(u=u||document.title,0===u.indexOf(w.siteName))){var n=" - ".concat(p.parse(t,e).getPrettyString()," ");document.title="".concat(w.siteName).concat(n).concat(u.substr(w.siteName.length))}},w.hasUserCapability=function(e){return window.angular.isArray(w.userCapabilities)&&-1!==w.userCapabilities.indexOf(e)},w.on=function(e,t){function n(e){t.apply(void 0,f(e.detail))}t.wrapper=n,window.addEventListener(e,n)},w.off=function(e,t){t.wrapper&&window.removeEventListener(e,t.wrapper)},w.postEventNoEmit=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];var a=new CustomEvent(e,{detail:n});window.dispatchEvent(a)},w.postEvent=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];w.postEventNoEmit.apply(w,[e].concat(n)),window.angular.element((function(){var t=w.helper.getAngularDependency("$rootScope");t.$oldEmit.apply(t,[e].concat(n))}))};var j=w,D=j; + */var y=window,w=y.piwik,O=y.broadcast,j=y.piwikHelper;w.helper=j,w.broadcast=O,w.updateDateInTitle=function(e,t){if($(".top_controls #periodString").length&&(u=u||document.title,0===u.indexOf(w.siteName))){var n=" - ".concat(p.parse(t,e).getPrettyString()," ");document.title="".concat(w.siteName).concat(n).concat(u.slice(w.siteName.length))}},w.hasUserCapability=function(e){return window.angular.isArray(w.userCapabilities)&&-1!==w.userCapabilities.indexOf(e)},w.on=function(e,t){function n(e){t.apply(void 0,m(e.detail))}t.wrapper=n,window.addEventListener(e,n)},w.off=function(e,t){t.wrapper&&window.removeEventListener(e,t.wrapper)},w.postEventNoEmit=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];var i=new CustomEvent(e,{detail:n});window.dispatchEvent(i)},w.postEvent=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];w.postEventNoEmit.apply(w,[e].concat(n)),window.angular.element((function(){var t=w.helper.getAngularDependency("$rootScope");t.$oldEmit.apply(t,[e].concat(n))}))};var k=w,S=k; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function C(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];var a=n;return 1===n.length&&n[0]&&n[0]instanceof Array&&(a=n[0]),window._pk_translate(e,a)} +function C(e){if(!e)return"";for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];var i=n;return 1===n.length&&n[0]&&Array.isArray(n[0])&&(i=n[0]),window._pk_translate(e,i)}function E(e){if(!e||!window.piwik_translations[e])return e;for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return C.apply(void 0,[e].concat(n))} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function S(e){return $.datepicker.formatDate("yy-mm-dd",e)}function P(){var e=new Date(Date.now());return e.setTime(e.getTime()+60*e.getTimezoneOffset()*1e3),e.setHours(e.getHours()+(window.piwik.timezoneOffset||0)/3600),e.setHours(0),e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0),e}function E(e){if(e instanceof Date)return e;var t=decodeURIComponent(e).trim();if(""===t)throw new Error("Invalid date, empty string.");if("today"===t||"now"===t)return P();if("yesterday"===t||"yesterdaySameTime"===t){var n=P();return n.setDate(n.getDate()-1),n}if(t.match(/last[ -]?week/i)){var r=P();return r.setDate(r.getDate()-7),r}if(t.match(/last[ -]?month/i)){var a=P();return a.setDate(1),a.setMonth(a.getMonth()-1),a}if(t.match(/last[ -]?year/i)){var o=P();return o.setFullYear(o.getFullYear()-1),o}return $.datepicker.parseDate("yy-mm-dd",t)}function T(e){return 2===e.length&&(P()>=e[0]&&P()<=e[1])}function x(e,t){return A(e)||H(e,t)||N(e,t)||I()}function I(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function N(e,t){if(e){if("string"===typeof e)return B(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?B(e,t):void 0}}function B(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function H(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,c=!1;try{for(n=n.call(e);!(i=(r=n.next()).done);i=!0)if(o.push(r.value),t&&o.length===t)break}catch(s){c=!0,a=s}finally{try{i||null==n["return"]||n["return"]()}finally{if(c)throw a}}return o}}function A(e){if(Array.isArray(e))return e}function M(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function F(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function V(e,t,n){return t&&F(e.prototype,t),n&&F(e,n),e}function L(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} + */function D(e){return $.datepicker.formatDate("yy-mm-dd",e)}function P(){var e=new Date(Date.now());return e.setTime(e.getTime()+60*e.getTimezoneOffset()*1e3),e.setHours(e.getHours()+(window.piwik.timezoneOffset||0)/3600),e.setHours(0),e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0),e}function V(e){if(e instanceof Date)return e;var t=decodeURIComponent(e).trim();if(""===t)throw new Error("Invalid date, empty string.");if("today"===t||"now"===t)return P();if("yesterday"===t||"yesterdaySameTime"===t){var n=P();return n.setDate(n.getDate()-1),n}if(t.match(/last[ -]?week/i)){var r=P();return r.setDate(r.getDate()-7),r}if(t.match(/last[ -]?month/i)){var i=P();return i.setDate(1),i.setMonth(i.getMonth()-1),i}if(t.match(/last[ -]?year/i)){var a=P();return a.setFullYear(a.getFullYear()-1),a}return $.datepicker.parseDate("yy-mm-dd",t)}function N(e){return 2===e.length&&(P()>=e[0]&&P()<=e[1])}function T(e,t){return M(e)||B(e,t)||I(e,t)||A()}function A(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function I(e,t){if(e){if("string"===typeof e)return x(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?x(e,t):void 0}}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function B(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a=[],o=!0,l=!1;try{for(n=n.call(e);!(o=(r=n.next()).done);o=!0)if(a.push(r.value),t&&a.length===t)break}catch(c){l=!0,i=c}finally{try{o||null==n["return"]||n["return"]()}finally{if(l)throw i}}return a}}function M(e){if(Array.isArray(e))return e}function L(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function R(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function F(e,t,n){return t&&R(e.prototype,t),n&&R(e,n),e}function _(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var R=function(){function e(t,n,r){M(this,e),L(this,"startDate",void 0),L(this,"endDate",void 0),L(this,"childPeriodType",void 0),this.startDate=t,this.endDate=n,this.childPeriodType=r}return V(e,[{key:"getPrettyString",value:function(){var e=S(this.startDate),t=S(this.endDate);return C("General_DateRangeFromTo",[e,t])}},{key:"getDateRange",value:function(){return[this.startDate,this.endDate]}},{key:"containsToday",value:function(){return T(this.getDateRange())}}],[{key:"getLastNRange",value:function(t,n,r){var a=Math.max(parseInt(n.toString(),10)-1,0);if(Number.isNaN(a))throw new Error("Invalid range strAmount");var o=r?E(r):P(),i=new Date(o.getTime());if("day"===t)i.setDate(i.getDate()-a);else if("week"===t)i.setDate(i.getDate()-7*a);else if("month"===t)i.setDate(1),i.setMonth(i.getMonth()-a);else{if("year"!==t)throw new Error("Unknown period type '".concat(t,"'."));i.setFullYear(i.getFullYear()-a)}if("day"!==t){var c=p.periods[t].parse(i),s=p.periods[t].parse(o),l=c.getDateRange(),u=x(l,1);i=u[0];var d=s.getDateRange(),f=x(d,2);o=f[1]}var m=new Date(1991,7,6);if(i.getTime()-m.getTime()<0)switch(t){case"year":i=new Date(1992,0,1);break;case"month":i=new Date(1991,8,1);break;case"week":i=new Date(1991,8,12);break;case"day":default:i=m;break}return new e(i,o,t)}},{key:"getLastNRangeChild",value:function(t,n,r){var a=n?E(n):P(),o=new Date(a.getTime()),i=new Date(a.getTime());if("day"===t)o.setDate(o.getDate()-r),i.setDate(i.getDate()-r);else if("week"===t)o.setDate(o.getDate()-7*r),i.setDate(i.getDate()-7*r);else if("month"===t)o.setDate(1),o.setMonth(o.getMonth()-r),i.setDate(1),i.setMonth(i.getMonth()-r);else{if("year"!==t)throw new Error("Unknown period type '".concat(t,"'."));o.setFullYear(o.getFullYear()-r),i.setFullYear(i.getFullYear()-r)}if("day"!==t){var c=p.periods[t].parse(o),s=p.periods[t].parse(i),l=c.getDateRange(),u=x(l,1);o=u[0];var d=s.getDateRange(),f=x(d,2);i=f[1]}var m=new Date(1991,7,6);if(o.getTime()-m.getTime()<0)switch(t){case"year":o=new Date(1992,0,1);break;case"month":o=new Date(1991,8,1);break;case"week":o=new Date(1991,8,12);break;case"day":default:o=m;break}return new e(o,i,t)}},{key:"parse",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"day";if(/^previous/.test(t)){var r=e.getLastNRange(n,"2").startDate;return e.getLastNRange(n,t.substring(8),r)}if(/^last/.test(t))return e.getLastNRange(n,t.substring(4));var a=decodeURIComponent(t).split(",");return new e(E(a[0]),E(a[1]),n)}},{key:"getDisplayText",value:function(){return C("General_DateRangeInPeriodList")}}]),e}();function U(){return{getAllLabels:p.getAllLabels.bind(p),isRecognizedPeriod:p.isRecognizedPeriod.bind(p),get:p.get.bind(p),parse:p.parse.bind(p),parseDate:E,format:S,RangePeriod:R,todayIsInRange:T}}function _(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function J(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function G(e,t,n){return t&&J(e.prototype,t),n&&J(e,n),e}function q(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} + */var H=function(){function e(t,n,r){L(this,e),_(this,"startDate",void 0),_(this,"endDate",void 0),_(this,"childPeriodType",void 0),this.startDate=t,this.endDate=n,this.childPeriodType=r}return F(e,[{key:"getPrettyString",value:function(){var e=D(this.startDate),t=D(this.endDate);return C("General_DateRangeFromTo",[e,t])}},{key:"getDateRange",value:function(){return[this.startDate,this.endDate]}},{key:"containsToday",value:function(){return N(this.getDateRange())}},{key:"getDayCount",value:function(){return Math.ceil((this.endDate.getTime()-this.startDate.getTime())/864e5)+1}}],[{key:"getLastNRange",value:function(t,n,r){var i=Math.max(parseInt(n.toString(),10)-1,0);if(Number.isNaN(i))throw new Error("Invalid range strAmount");var a=r?V(r):P(),o=new Date(a.getTime());if("day"===t)o.setDate(o.getDate()-i);else if("week"===t)o.setDate(o.getDate()-7*i);else if("month"===t)o.setDate(1),o.setMonth(o.getMonth()-i);else{if("year"!==t)throw new Error("Unknown period type '".concat(t,"'."));o.setFullYear(o.getFullYear()-i)}if("day"!==t){var l=p.periods[t].parse(o),c=p.periods[t].parse(a),s=l.getDateRange(),u=T(s,1);o=u[0];var d=c.getDateRange(),m=T(d,2);a=m[1]}var f=new Date(1991,7,6);if(o.getTime()-f.getTime()<0)switch(t){case"year":o=new Date(1992,0,1);break;case"month":o=new Date(1991,8,1);break;case"week":o=new Date(1991,8,12);break;case"day":default:o=f;break}return new e(o,a,t)}},{key:"getLastNRangeChild",value:function(t,n,r){var i=n?V(n):P(),a=new Date(i.getTime()),o=new Date(i.getTime());if("day"===t)a.setDate(a.getDate()-r),o.setDate(o.getDate()-r);else if("week"===t)a.setDate(a.getDate()-7*r),o.setDate(o.getDate()-7*r);else if("month"===t)a.setDate(1),a.setMonth(a.getMonth()-r),o.setDate(1),o.setMonth(o.getMonth()-r);else{if("year"!==t)throw new Error("Unknown period type '".concat(t,"'."));a.setFullYear(a.getFullYear()-r),o.setFullYear(o.getFullYear()-r)}if("day"!==t){var l=p.periods[t].parse(a),c=p.periods[t].parse(o),s=l.getDateRange(),u=T(s,1);a=u[0];var d=c.getDateRange(),m=T(d,2);o=m[1]}var f=new Date(1991,7,6);if(a.getTime()-f.getTime()<0)switch(t){case"year":a=new Date(1992,0,1);break;case"month":a=new Date(1991,8,1);break;case"week":a=new Date(1991,8,12);break;case"day":default:a=f;break}return new e(a,o,t)}},{key:"parse",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"day";if(/^previous/.test(t)){var r=e.getLastNRange(n,"2").startDate;return e.getLastNRange(n,t.substring(8),r)}if(/^last/.test(t))return e.getLastNRange(n,t.substring(4));var i=decodeURIComponent(t).split(",");return new e(V(i[0]),V(i[1]),n)}},{key:"getDisplayText",value:function(){return C("General_DateRangeInPeriodList")}}]),e}();function U(){return{getAllLabels:p.getAllLabels.bind(p),isRecognizedPeriod:p.isRecognizedPeriod.bind(p),get:p.get.bind(p),parse:p.parse.bind(p),parseDate:V,format:D,RangePeriod:H,todayIsInRange:N}}function q(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function W(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function J(e,t,n){return t&&W(e.prototype,t),n&&W(e,n),e}function G(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */p.addCustomPeriod("range",R), + */p.addCustomPeriod("range",H), /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -window.piwik.addCustomPeriod=p.addCustomPeriod.bind(p),window.angular.module("piwikApp.service").factory("piwikPeriods",U);var z=function(){function e(t){_(this,e),q(this,"dateInPeriod",void 0),this.dateInPeriod=t}return G(e,[{key:"getPrettyString",value:function(){return S(this.dateInPeriod)}},{key:"getDateRange",value:function(){return[new Date(this.dateInPeriod.getTime()),new Date(this.dateInPeriod.getTime())]}},{key:"containsToday",value:function(){return T(this.getDateRange())}}],[{key:"parse",value:function(t){return new e(E(t))}},{key:"getDisplayText",value:function(){return C("Intl_PeriodDay")}}]),e}();function Q(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Y(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function W(e,t,n){return t&&Y(e.prototype,t),n&&Y(e,n),e}function K(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} +window.piwik.addCustomPeriod=p.addCustomPeriod.bind(p),window.angular.module("piwikApp.service").factory("piwikPeriods",U);var z=function(){function e(t){q(this,e),G(this,"dateInPeriod",void 0),this.dateInPeriod=t}return J(e,[{key:"getPrettyString",value:function(){return D(this.dateInPeriod)}},{key:"getDateRange",value:function(){return[new Date(this.dateInPeriod.getTime()),new Date(this.dateInPeriod.getTime())]}},{key:"containsToday",value:function(){return N(this.getDateRange())}}],[{key:"parse",value:function(t){return new e(V(t))}},{key:"getDisplayText",value:function(){return C("Intl_PeriodDay")}}]),e}();function Y(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Q(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function K(e,t,n){return t&&Q(e.prototype,t),n&&Q(e,n),e}function X(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */p.addCustomPeriod("day",z);var X=function(){function e(t){Q(this,e),K(this,"dateInPeriod",void 0),this.dateInPeriod=t}return W(e,[{key:"getPrettyString",value:function(){var e=this.getDateRange(),t=S(e[0]),n=S(e[1]);return C("General_DateRangeFromTo",[t,n])}},{key:"getDateRange",value:function(){var e=(this.dateInPeriod.getDay()+6)%7,t=new Date(this.dateInPeriod.getTime());t.setDate(this.dateInPeriod.getDate()-e);var n=new Date(t.getTime());return n.setDate(t.getDate()+6),[t,n]}},{key:"containsToday",value:function(){return T(this.getDateRange())}}],[{key:"parse",value:function(t){return new e(E(t))}},{key:"getDisplayText",value:function(){return C("Intl_PeriodWeek")}}]),e}();function Z(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function ee(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function te(e,t,n){return t&&ee(e.prototype,t),n&&ee(e,n),e}function ne(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} + */p.addCustomPeriod("day",z);var Z=function(){function e(t){Y(this,e),X(this,"dateInPeriod",void 0),this.dateInPeriod=t}return K(e,[{key:"getPrettyString",value:function(){var e=this.getDateRange(),t=D(e[0]),n=D(e[1]);return C("General_DateRangeFromTo",[t,n])}},{key:"getDateRange",value:function(){var e=(this.dateInPeriod.getDay()+6)%7,t=new Date(this.dateInPeriod.getTime());t.setDate(this.dateInPeriod.getDate()-e);var n=new Date(t.getTime());return n.setDate(t.getDate()+6),[t,n]}},{key:"containsToday",value:function(){return N(this.getDateRange())}}],[{key:"parse",value:function(t){return new e(V(t))}},{key:"getDisplayText",value:function(){return C("Intl_PeriodWeek")}}]),e}();function ee(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function te(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function ne(e,t,n){return t&&te(e.prototype,t),n&&te(e,n),e}function re(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */p.addCustomPeriod("week",X);var re=function(){function e(t){Z(this,e),ne(this,"dateInPeriod",void 0),this.dateInPeriod=t}return te(e,[{key:"getPrettyString",value:function(){var e=C("Intl_Month_Long_StandAlone_".concat(this.dateInPeriod.getMonth()+1));return"".concat(e," ").concat(this.dateInPeriod.getFullYear())}},{key:"getDateRange",value:function(){var e=new Date(this.dateInPeriod.getTime());e.setDate(1);var t=new Date(this.dateInPeriod.getTime());return t.setDate(1),t.setMonth(t.getMonth()+1),t.setDate(0),[e,t]}},{key:"containsToday",value:function(){return T(this.getDateRange())}}],[{key:"parse",value:function(t){return new e(E(t))}},{key:"getDisplayText",value:function(){return C("Intl_PeriodMonth")}}]),e}();function ae(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function oe(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function ie(e,t,n){return t&&oe(e.prototype,t),n&&oe(e,n),e}function ce(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} + */p.addCustomPeriod("week",Z);var ie=function(){function e(t){ee(this,e),re(this,"dateInPeriod",void 0),this.dateInPeriod=t}return ne(e,[{key:"getPrettyString",value:function(){var e=C("Intl_Month_Long_StandAlone_".concat(this.dateInPeriod.getMonth()+1));return"".concat(e," ").concat(this.dateInPeriod.getFullYear())}},{key:"getDateRange",value:function(){var e=new Date(this.dateInPeriod.getTime());e.setDate(1);var t=new Date(this.dateInPeriod.getTime());return t.setDate(1),t.setMonth(t.getMonth()+1),t.setDate(0),[e,t]}},{key:"containsToday",value:function(){return N(this.getDateRange())}}],[{key:"parse",value:function(t){return new e(V(t))}},{key:"getDisplayText",value:function(){return C("Intl_PeriodMonth")}}]),e}();function ae(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function oe(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function le(e,t,n){return t&&oe(e.prototype,t),n&&oe(e,n),e}function ce(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */p.addCustomPeriod("month",re);var se=function(){function e(t){ae(this,e),ce(this,"dateInPeriod",void 0),this.dateInPeriod=t}return ie(e,[{key:"getPrettyString",value:function(){return this.dateInPeriod.getFullYear().toString()}},{key:"getDateRange",value:function(){var e=new Date(this.dateInPeriod.getTime());e.setMonth(0),e.setDate(1);var t=new Date(this.dateInPeriod.getTime());return t.setMonth(12),t.setDate(0),[e,t]}},{key:"containsToday",value:function(){return T(this.getDateRange())}}],[{key:"parse",value:function(t){return new e(E(t))}},{key:"getDisplayText",value:function(){return C("Intl_PeriodYear")}}]),e}(); + */p.addCustomPeriod("month",ie);var se=function(){function e(t){ae(this,e),ce(this,"dateInPeriod",void 0),this.dateInPeriod=t}return le(e,[{key:"getPrettyString",value:function(){return this.dateInPeriod.getFullYear().toString()}},{key:"getDateRange",value:function(){var e=new Date(this.dateInPeriod.getTime());e.setMonth(0),e.setDate(1);var t=new Date(this.dateInPeriod.getTime());return t.setMonth(12),t.setDate(0),[e,t]}},{key:"containsToday",value:function(){return N(this.getDateRange())}}],[{key:"parse",value:function(t){return new e(V(t))}},{key:"getDisplayText",value:function(){return C("Intl_PeriodYear")}}]),e}(); /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function le(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function ue(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?le(Object(n),!0).forEach((function(t){me(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):le(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function de(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function pe(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function fe(e,t,n){return t&&pe(e.prototype,t),n&&pe(e,n),e}function me(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} +function ue(e,t){return he(e)||fe(e,t)||pe(e,t)||de()}function de(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function pe(e,t){if(e){if("string"===typeof e)return me(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?me(e,t):void 0}}function me(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function fe(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a=[],o=!0,l=!1;try{for(n=n.call(e);!(o=(r=n.next()).done);o=!0)if(a.push(r.value),t&&a.length===t)break}catch(c){l=!0,i=c}finally{try{o||null==n["return"]||n["return"]()}finally{if(l)throw i}}return a}}function he(e){if(Array.isArray(e))return e}function ge(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function ve(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function be(e,t,n){return t&&ve(e.prototype,t),n&&ve(e,n),e}function ye(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */p.addCustomPeriod("year",se);var he=window,ve=he.piwik,ge=he.broadcast;function be(e,t){try{return p.parse(e,t),!0}catch(n){return!1}}var ye=function(){function e(){var t=this;de(this,e),me(this,"urlQuery",Object(o["ref"])("")),me(this,"hashQuery",Object(o["ref"])("")),me(this,"urlParsed",Object(o["computed"])((function(){return Object(o["readonly"])(ge.getValuesFromUrl("?".concat(t.urlQuery.value),!0))}))),me(this,"hashParsed",Object(o["computed"])((function(){return Object(o["readonly"])(ge.getValuesFromUrl("?".concat(t.hashQuery.value),!0))}))),me(this,"parsed",Object(o["computed"])((function(){return Object(o["readonly"])(ue(ue({},t.urlParsed.value),t.hashParsed.value))}))),this.setUrlQuery(window.location.search),this.setHashQuery(window.location.hash),D.on("$locationChangeSuccess",(function(e){var n=new URL(e);t.setUrlQuery(n.search.replace(/^\?/,"")),t.setHashQuery(n.hash.replace(/^#/,""))})),this.updatePeriodParamsFromUrl()}return fe(e,[{key:"updateHash",value:function(e){var t="string"!==typeof e?this.stringify(e):e,n=D.helper.getAngularDependency("$location");n.search(t)}},{key:"getSearchParam",value:function(e){var t=window.location.href.split("#"),n=new RegExp("".concat(e,"(\\[]|=)"));if(t&&t[1]&&n.test(decodeURIComponent(t[1]))){var r=window.broadcast.getValueFromHash(e,window.location.href);if(r||"date"!==e&&"period"!==e&&"idSite"!==e)return r}return window.broadcast.getValueFromUrl(e,window.location.search)}},{key:"stringify",value:function(e){return $.param(e).replace(/%5B%5D/g,"[]")}},{key:"updatePeriodParamsFromUrl",value:function(){var e=this.getSearchParam("date"),t=this.getSearchParam("period");if(be(t,e)&&(ve.period!==t||ve.currentDateString!==e)){ve.period=t;var n=p.parse(t,e).getDateRange();ve.startDateString=S(n[0]),ve.endDateString=S(n[1]),ve.updateDateInTitle(e,t),"range"===ve.period&&(e="".concat(ve.startDateString,",").concat(ve.endDateString)),ve.currentDateString=e}}},{key:"setUrlQuery",value:function(e){this.urlQuery.value=e.replace(/^\?/,"")}},{key:"setHashQuery",value:function(e){this.hashQuery.value=e.replace(/^[#/?]+/,"")}}]),e}(),we=new ye,ke=we; + */p.addCustomPeriod("year",se);var we=window,Oe=we.piwik,je=we.broadcast;function ke(e,t){try{return p.parse(e,t),!0}catch(n){return!1}}var Se=function(){function e(){var t=this;ge(this,e),ye(this,"urlQuery",Object(a["ref"])("")),ye(this,"hashQuery",Object(a["ref"])("")),ye(this,"urlParsed",Object(a["computed"])((function(){return Object(a["readonly"])(t.parse(t.urlQuery.value))}))),ye(this,"hashParsed",Object(a["computed"])((function(){return Object(a["readonly"])(t.parse(t.hashQuery.value))}))),ye(this,"parsed",Object(a["computed"])((function(){return Object(a["readonly"])(Object.assign(Object.assign({},t.urlParsed.value),t.hashParsed.value))}))),this.setUrlQuery(window.location.search),this.setHashQuery(window.location.hash),S.on("$locationChangeSuccess",(function(e){var n=new URL(e);t.setUrlQuery(n.search.replace(/^\?/,"")),t.setHashQuery(n.hash.replace(/^#/,""))})),this.updatePeriodParamsFromUrl()}return be(e,[{key:"updateHashToUrl",value:function(e){var t=S.helper.getAngularDependency("$location");t.url(e)}},{key:"updateHash",value:function(e){var t=this.getFinalHashParams(e),n=this.stringify(t),r=S.helper.getAngularDependency("$location");r.search(n);var i=S.helper.getAngularDependency("$timeout");i()}},{key:"updateUrl",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n="string"!==typeof e?this.stringify(e):e,r=Object.keys(t).length?this.getFinalHashParams(t,e):{},i=this.stringify(r),a="?".concat(n);i.length&&(a="".concat(a,"#?").concat(i)),window.broadcast.propagateNewPage("",void 0,void 0,void 0,a)}},{key:"getFinalHashParams",value:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n="string"!==typeof e?e:this.parse(e),r="string"!==typeof e?t:this.parse(t);return Object.assign({period:r.period||this.parsed.value.period,date:r.date||this.parsed.value.date,segment:r.segment||this.parsed.value.segment},n)}},{key:"updateLocation",value:function(e){S.helper.isAngularRenderingThePage()?this.updateHash(e):this.updateUrl(e)}},{key:"getSearchParam",value:function(e){var t=window.location.href.split("#"),n=new RegExp("".concat(e,"(\\[]|=)"));if(t&&t[1]&&n.test(decodeURIComponent(t[1]))){var r=window.broadcast.getValueFromHash(e,window.location.href);if(r||"date"!==e&&"period"!==e&&"idSite"!==e)return r}return window.broadcast.getValueFromUrl(e,window.location.search)}},{key:"parse",value:function(e){return je.getValuesFromUrl("?".concat(e),!0)}},{key:"stringify",value:function(e){var t=Object.fromEntries(Object.entries(e).filter((function(e){var t=ue(e,2),n=t[1];return""!==n&&null!==n&&void 0!==n})));return $.param(t).replace(/%5B%5D/g,"[]").replace(/%2C/g,",")}},{key:"updatePeriodParamsFromUrl",value:function(){var e=this.getSearchParam("date"),t=this.getSearchParam("period");if(ke(t,e)&&(Oe.period!==t||Oe.currentDateString!==e)){Oe.period=t;var n=p.parse(t,e).getDateRange();Oe.startDateString=D(n[0]),Oe.endDateString=D(n[1]),Oe.updateDateInTitle(e,t),"range"===Oe.period&&(e="".concat(Oe.startDateString,",").concat(Oe.endDateString)),Oe.currentDateString=e}}},{key:"setUrlQuery",value:function(e){this.urlQuery.value=e.replace(/^\?/,"")}},{key:"setHashQuery",value:function(e){this.hashQuery.value=e.replace(/^[#/?]+/,"")}}]),e}(),Ce=new Se,Ee=Ce; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function Oe(){var e={getSearchParam:ke.getSearchParam.bind(ke)};return e} +function De(){var e={getSearchParam:Ee.getSearchParam.bind(Ee)};return e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function je(){return D}function De(e,t){t.$oldEmit=t.$emit,t.$emit=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return D.postEvent.apply(D,[e].concat(n)),null},t.$oldBroadcast=t.$broadcast,t.$broadcast=function(e){for(var n=arguments.length,r=new Array(n>1?n-1:0),a=1;a<n;a++)r[a-1]=arguments[a];return D.postEventNoEmit.apply(D,[e].concat(r)),t.$oldBroadcast.apply(t,[e].concat(r))},t.$on("$locationChangeSuccess",e.updatePeriodParamsFromUrl)}function Ce(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Se(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Ce(Object(n),!0).forEach((function(t){xe(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Ce(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Pe(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Ee(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function Te(e,t,n){return t&&Ee(e.prototype,t),n&&Ee(e,n),e}function xe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} +function Pe(){return S}function Ve(e,t){t.$oldEmit=t.$emit,t.$emit=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return S.postEventNoEmit.apply(S,[e].concat(n)),this.$oldEmit.apply(this,[e].concat(n))},t.$oldBroadcast=t.$broadcast,t.$broadcast=function(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r<t;r++)n[r-1]=arguments[r];return S.postEventNoEmit.apply(S,[e].concat(n)),this.$oldBroadcast.apply(this,[e].concat(n))},t.$on("$locationChangeSuccess",e.updatePeriodParamsFromUrl)}function Ne(e){return Ne="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ne(e)}function Te(e){return Be(e)||xe(e)||Ie(e)||Ae()}function Ae(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function Ie(e,t){if(e){if("string"===typeof e)return Me(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Me(e,t):void 0}}function xe(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function Be(e){if(Array.isArray(e))return Me(e)}function Me(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function Le(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function Re(e,t,n){return t&&Le(e.prototype,t),n&&Le(e,n),e}function Fe(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function _e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function $e(e,t){if("function"!==typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&Ye(e,t)}function He(e){var t=Ge();return function(){var n,r=Qe(e);if(t){var i=Qe(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return Ue(this,n)}}function Ue(e,t){if(t&&("object"===Ne(t)||"function"===typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return qe(e)}function qe(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function We(e){var t="function"===typeof Map?new Map:void 0;return We=function(e){if(null===e||!ze(e))return e;if("function"!==typeof e)throw new TypeError("Super expression must either be null or a function");if("undefined"!==typeof t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return Je(e,arguments,Qe(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),Ye(n,e)},We(e)}function Je(e,t,n){return Je=Ge()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=Function.bind.apply(e,r),a=new i;return n&&Ye(a,n.prototype),a},Je.apply(null,arguments)}function Ge(){if("undefined"===typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"===typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}function ze(e){return-1!==Function.toString.call(e).indexOf("[native code]")}function Ye(e,t){return Ye=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},Ye(e,t)}function Qe(e){return Qe=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},Qe(e)} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function Ie(e,t){if("abort"!==t)if("undefined"!==typeof Piwik_Popover){var n=$("#loadingError");Piwik_Popover.isOpen()&&e&&500===e.status?e&&500===e.status&&$(document.body).html(piwikHelper.escape(e.responseText)):n.show()}else console.log("Request failed: ".concat(e.responseText))}ve.updatePeriodParamsFromUrl=we.updatePeriodParamsFromUrl.bind(we),Oe.$inject=[],angular.module("piwikApp.service").service("piwikUrl",Oe),window.angular.module("piwikApp.service").service("piwik",je),De.$inject=["piwik","$rootScope"],window.angular.module("piwikApp.service").run(De),window.globalAjaxQueue=[],window.globalAjaxQueue.active=0,window.globalAjaxQueue.clean=function(){for(var e=this.length;e>=0;e-=1)this[e]&&4!==this[e].readyState||this.splice(e,1)},window.globalAjaxQueue.push=function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return this.active+=n.length,this.clean(),(e=Array.prototype.push).call.apply(e,[this].concat(n))},window.globalAjaxQueue.abort=function(){this.forEach((function(e){return e&&e.abort&&e.abort()})),this.splice(0,this.length),this.active=0};var Ne=function(){function e(){Pe(this,e),xe(this,"format","json"),xe(this,"timeout",null),xe(this,"callback",null),xe(this,"useRegularCallbackInCaseOfError",!1),xe(this,"errorCallback",void 0),xe(this,"withToken",!1),xe(this,"completeCallback",void 0),xe(this,"getParams",{}),xe(this,"getUrl","?"),xe(this,"postParams",{}),xe(this,"loadingElement",null),xe(this,"errorElement","#ajaxError"),xe(this,"requestHandle",null),xe(this,"defaultParams",["idSite","period","date","segment"]),this.errorCallback=Ie}return Te(e,[{key:"addParams",value:function(e,t){var n=this,r="string"===typeof e?window.broadcast.getValuesFromUrl(e):e,a=["compareSegments","comparePeriods","compareDates"];Object.keys(r).forEach((function(e){var o=r[e];(-1===a.indexOf(e)||o)&&("get"===t.toLowerCase()?n.getParams[e]=o:"post"===t.toLowerCase()&&(n.postParams[e]=o))}))}},{key:"withTokenInUrl",value:function(){this.withToken=!0}},{key:"setUrl",value:function(e){this.addParams(broadcast.getValuesFromUrl(e),"GET")}},{key:"setBulkRequests",value:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r=t.map((function(e){return"string"===typeof e?e:$.param(e)}));this.addParams({module:"API",method:"API.getBulkRequest",urls:r,format:"json"},"post")}},{key:"setTimeout",value:function(e){this.timeout=e}},{key:"setCallback",value:function(e){this.callback=e}},{key:"useCallbackInCaseOfError",value:function(){this.useRegularCallbackInCaseOfError=!0}},{key:"redirectOnSuccess",value:function(e){this.setCallback((function(){piwikHelper.redirect(e)}))}},{key:"setErrorCallback",value:function(e){this.errorCallback=e}},{key:"setCompleteCallback",value:function(e){this.completeCallback=e}},{key:"setFormat",value:function(e){this.format=e}},{key:"setLoadingElement",value:function(e){this.loadingElement=e||"#ajaxLoadingDiv"}},{key:"setErrorElement",value:function(e){e&&(this.errorElement=e)}},{key:"useGETDefaultParameter",value:function(e){if(e&&this.defaultParams)for(var t=0;t<this.defaultParams.length;t+=1)if(this.defaultParams[t]===e)return!0;return!1}},{key:"removeDefaultParameter",value:function(e){if(e&&this.defaultParams)for(var t=0;t<this.defaultParams.length;t+=1)this.defaultParams[t]===e&&this.defaultParams.splice(t,1)}},{key:"send",value:function(){var e=this;return $(this.errorElement).length&&$(this.errorElement).hide(),this.loadingElement&&$(this.loadingElement).fadeIn(),this.requestHandle=this.buildAjaxCall(),window.globalAjaxQueue.push(this.requestHandle),new Promise((function(t,n){e.requestHandle.then(t).fail((function(t){"abort"!==t.statusText&&(console.log("Warning: the ".concat($.param(e.getParams)," request failed!")),n(t))}))}))}},{key:"abort",value:function(){this.requestHandle&&"function"===typeof this.requestHandle.abort&&(this.requestHandle.abort(),this.requestHandle=null)}},{key:"buildAjaxCall",value:function(){var e=this,t=this,n=this.mixinDefaultGetParams(this.getParams),r=this.getUrl;"?"!==r[r.length-1]&&(r+="&"),n.segment&&(r="".concat(r,"segment=").concat(n.segment,"&"),delete n.segment),n.date&&(r="".concat(r,"date=").concat(decodeURIComponent(n.date.toString()),"&"),delete n.date),r+=$.param(n);var a={type:"POST",async:!0,url:r,dataType:this.format||"json",complete:this.completeCallback,error:function(){if(window.globalAjaxQueue.active-=1,t.errorCallback){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.errorCallback.apply(this,n)}},success:function(t,n,r){if(e.loadingElement&&$(e.loadingElement).hide(),t&&"error"===t.result&&!e.useRegularCallbackInCaseOfError){var a=null,o="toast";if($(e.errorElement).length&&t.message&&($(e.errorElement).show(),a=e.errorElement,o=null),t.message){var i=window["require"]("piwik/UI"),c=new i.Notification;c.show(t.message,{placeat:a,context:"error",type:o,id:"ajaxHelper"}),c.scrollToNotification()}}else e.callback&&e.callback(t,n,r);window.globalAjaxQueue.active-=1,D.ajaxRequestFinished&&D.ajaxRequestFinished()},data:this.mixinDefaultPostParams(this.postParams),timeout:null!==this.timeout?this.timeout:void 0};return $.ajax(a)}},{key:"isRequestToApiMethod",value:function(){return this.getParams&&"API"===this.getParams.module&&this.getParams.method||this.postParams&&"API"===this.postParams.module&&this.postParams.method}},{key:"isWidgetizedRequest",value:function(){return"Widgetize"===broadcast.getValueFromUrl("module")}},{key:"getDefaultPostParams",value:function(){return this.withToken||this.isRequestToApiMethod()||D.shouldPropagateTokenAuth?{token_auth:D.token_auth,force_api_session:broadcast.isWidgetizeRequestWithoutSession()?0:1}:{}}},{key:"mixinDefaultPostParams",value:function(e){var t=this.getDefaultPostParams(),n=Se(Se({},t),e);return n}},{key:"mixinDefaultGetParams",value:function(e){var t=this,n=ke.getSearchParam("segment"),r={idSite:D.idSite?D.idSite.toString():broadcast.getValueFromUrl("idSite"),period:D.period||broadcast.getValueFromUrl("period"),segment:n},a=e;return a.token_auth&&(a.token_auth=null,delete a.token_auth),Object.keys(r).forEach((function(e){t.useGETDefaultParameter(e)&&!a[e]&&!t.postParams[e]&&r[e]&&(a[e]=r[e])})),!this.useGETDefaultParameter("date")||a.date||this.postParams.date||(a.date=D.currentDateString),a}}],[{key:"fetch",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=new e;return n.withTokenInUrl&&r.withTokenInUrl(),r.setFormat("json"),r.addParams(Se({module:"API",format:"json"},t),"get"),n.postParams&&r.addParams(n.postParams,"post"),r.send()}}]),e}();function $e(){return globalAjaxQueue}window.ajaxHelper=Ne,angular.module("piwikApp.service").service("globalAjaxQueue",$e); + */function Ke(e,t){if("abort"!==t)if("undefined"!==typeof Piwik_Popover){var n=$("#loadingError");Piwik_Popover.isOpen()&&e&&500===e.status?e&&500===e.status&&$(document.body).html(piwikHelper.escape(e.responseText)):n.show()}else console.log("Request failed: ".concat(e.responseText))}Oe.updatePeriodParamsFromUrl=Ce.updatePeriodParamsFromUrl.bind(Ce),window.angular.module("piwikApp.service").service("piwikUrl",De),window.angular.module("piwikApp.service").run(["$location",function(){return null}]),window.angular.module("piwikApp.service").service("piwik",Pe),Ve.$inject=["piwik","$rootScope"],window.angular.module("piwikApp.service").run(Ve),window.globalAjaxQueue=[],window.globalAjaxQueue.active=0,window.globalAjaxQueue.clean=function(){for(var e=this.length;e>=0;e-=1)this[e]&&4!==this[e].readyState||this.splice(e,1)},window.globalAjaxQueue.push=function(){for(var e,t=arguments.length,n=new Array(t),r=0;r<t;r++)n[r]=arguments[r];return this.active+=n.length,this.clean(),(e=Array.prototype.push).call.apply(e,[this].concat(n))},window.globalAjaxQueue.abort=function(){this.forEach((function(e){return e&&e.abort&&e.abort()})),this.splice(0,this.length),this.active=0};var Xe=function(e){$e(n,e);var t=He(n);function n(){return _e(this,n),t.apply(this,arguments)}return n}(We(Error)),Ze=function(){function e(){_e(this,e),Fe(this,"format","json"),Fe(this,"timeout",null),Fe(this,"callback",null),Fe(this,"useRegularCallbackInCaseOfError",!1),Fe(this,"errorCallback",void 0),Fe(this,"withToken",!1),Fe(this,"completeCallback",void 0),Fe(this,"getParams",{}),Fe(this,"getUrl","?"),Fe(this,"postParams",{}),Fe(this,"loadingElement",null),Fe(this,"errorElement","#ajaxError"),Fe(this,"headers",void 0),Fe(this,"requestHandle",null),Fe(this,"abortController",null),Fe(this,"defaultParams",["idSite","period","date","segment"]),Fe(this,"resolveWithHelper",!1),this.errorCallback=Ke}return Re(e,[{key:"addParams",value:function(e,t){var n=this,r="string"===typeof e?window.broadcast.getValuesFromUrl(e):e,i=["compareSegments","comparePeriods","compareDates"];Object.keys(r).forEach((function(e){var a=r[e];(-1===i.indexOf(e)||a)&&("boolean"===typeof a&&(a=a?1:0),"get"===t.toLowerCase()?n.getParams[e]=a:"post"===t.toLowerCase()&&(n.postParams[e]=a))}))}},{key:"withTokenInUrl",value:function(){this.withToken=!0}},{key:"setUrl",value:function(e){this.addParams(broadcast.getValuesFromUrl(e),"GET")}},{key:"setBulkRequests",value:function(){for(var e=arguments.length,t=new Array(e),n=0;n<e;n++)t[n]=arguments[n];var r=t.map((function(e){return"string"===typeof e?e:$.param(e)}));this.addParams({module:"API",method:"API.getBulkRequest",urls:r,format:"json"},"post")}},{key:"setTimeout",value:function(e){this.timeout=e}},{key:"setCallback",value:function(e){this.callback=e}},{key:"useCallbackInCaseOfError",value:function(){this.useRegularCallbackInCaseOfError=!0}},{key:"redirectOnSuccess",value:function(e){this.setCallback((function(){piwikHelper.redirect(e)}))}},{key:"setErrorCallback",value:function(e){this.errorCallback=e}},{key:"setCompleteCallback",value:function(e){this.completeCallback=e}},{key:"setFormat",value:function(e){this.format=e}},{key:"setLoadingElement",value:function(e){this.loadingElement=e||"#ajaxLoadingDiv"}},{key:"setErrorElement",value:function(e){e&&(this.errorElement=e)}},{key:"useGETDefaultParameter",value:function(e){if(e&&this.defaultParams)for(var t=0;t<this.defaultParams.length;t+=1)if(this.defaultParams[t]===e)return!0;return!1}},{key:"removeDefaultParameter",value:function(e){if(e&&this.defaultParams)for(var t=0;t<this.defaultParams.length;t+=1)this.defaultParams[t]===e&&this.defaultParams.splice(t,1)}},{key:"send",value:function(){var e=this;$(this.errorElement).length&&$(this.errorElement).hide(),this.loadingElement&&$(this.loadingElement).fadeIn(),this.requestHandle=this.buildAjaxCall(),window.globalAjaxQueue.push(this.requestHandle);var t=null;try{t=S.helper.getAngularDependency("$timeout")}catch(r){}this.abortController&&this.abortController.signal.addEventListener("abort",(function(){e.requestHandle&&e.requestHandle.abort()}));var n=new Promise((function(n,r){e.requestHandle.then((function(t){e.resolveWithHelper?n(e):n(t)})).fail((function(t){"abort"!==t.statusText&&(console.log("Warning: the ".concat($.param(e.getParams)," request failed!")),r(t))})).done((function(){t&&t()}))}));return n}},{key:"abort",value:function(){this.requestHandle&&"function"===typeof this.requestHandle.abort&&(this.requestHandle.abort(),this.requestHandle=null)}},{key:"buildAjaxCall",value:function(){var e=this,t=this,n=this.mixinDefaultGetParams(this.getParams),r=this.getUrl;"?"!==r[r.length-1]&&(r+="&"),n.segment&&(r="".concat(r,"segment=").concat(n.segment,"&"),delete n.segment),n.date&&(r="".concat(r,"date=").concat(decodeURIComponent(n.date.toString()),"&"),delete n.date),r+=$.param(n);var i={type:"POST",async:!0,url:r,dataType:this.format||"json",complete:this.completeCallback,headers:this.headers?this.headers:void 0,error:function(){if(window.globalAjaxQueue.active-=1,t.errorCallback){for(var e=arguments.length,n=new Array(e),r=0;r<e;r++)n[r]=arguments[r];t.errorCallback.apply(this,n)}},success:function(t,n,r){if(e.loadingElement&&$(e.loadingElement).hide(),t&&"error"===t.result&&!e.useRegularCallbackInCaseOfError){var i=null,a="toast";$(e.errorElement).length&&t.message&&($(e.errorElement).show(),i=e.errorElement,a=null);var o=!document.querySelector("#login_form");if(t.message&&o){var l=window["require"]("piwik/UI"),c=new l.Notification;c.show(t.message,{placeat:i,context:"error",type:a,id:"ajaxHelper"}),c.scrollToNotification()}}else e.callback&&e.callback(t,n,r);window.globalAjaxQueue.active-=1,S.ajaxRequestFinished&&S.ajaxRequestFinished()},data:this.mixinDefaultPostParams(this.postParams),timeout:null!==this.timeout?this.timeout:void 0};return $.ajax(i)}},{key:"isRequestToApiMethod",value:function(){return this.getParams&&"API"===this.getParams.module&&this.getParams.method||this.postParams&&"API"===this.postParams.module&&this.postParams.method}},{key:"isWidgetizedRequest",value:function(){return"Widgetize"===broadcast.getValueFromUrl("module")}},{key:"getDefaultPostParams",value:function(){return this.withToken||this.isRequestToApiMethod()||S.shouldPropagateTokenAuth?{token_auth:S.token_auth,force_api_session:broadcast.isWidgetizeRequestWithoutSession()?0:1}:{}}},{key:"mixinDefaultPostParams",value:function(e){var t=this.getDefaultPostParams(),n=Object.assign(Object.assign({},t),e);return n}},{key:"mixinDefaultGetParams",value:function(e){var t=this,n=Ee.getSearchParam("segment"),r={idSite:S.idSite?S.idSite.toString():broadcast.getValueFromUrl("idSite"),period:S.period||broadcast.getValueFromUrl("period"),segment:n},i=e;return i.token_auth&&(i.token_auth=null,delete i.token_auth),Object.keys(r).forEach((function(e){t.useGETDefaultParameter(e)&&!i[e]&&!t.postParams[e]&&r[e]&&(i[e]=r[e])})),!this.useGETDefaultParameter("date")||i.date||this.postParams.date||(i.date=S.currentDateString),i}},{key:"getRequestHandle",value:function(){return this.requestHandle}}],[{key:"fetch",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=new e;n.withTokenInUrl&&r.withTokenInUrl(),n.errorElement&&r.setErrorElement(n.errorElement),n.redirectOnSuccess&&r.redirectOnSuccess(!0!==n.redirectOnSuccess?n.redirectOnSuccess:void 0),r.setFormat(n.format||"json"),Array.isArray(t)?r.setBulkRequests.apply(r,Te(t)):r.addParams(Object.assign(Object.assign({module:"API",format:n.format||"json"},t),{},{segment:t.segment?encodeURIComponent(t.segment):void 0}),"get"),n.postParams&&r.addParams(n.postParams,"post"),n.headers&&(r.headers=n.headers);var i=!0;return"undefined"===typeof n.createErrorNotification||n.createErrorNotification||(r.useCallbackInCaseOfError(),r.setErrorCallback(null),i=!1),n.abortController&&(r.abortController=n.abortController),n.returnResponseObject&&(r.resolveWithHelper=!0),r.send().then((function(t){var n=t instanceof e?t.requestHandle.responseJSON:t;if("error"===n.result)throw new Xe(n.message);return t})).catch((function(e){if(i)throw e;var t="Something went wrong";throw 504===e.status&&(t="Request was prossibly aborted"),new Error(t)}))}},{key:"post",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return e.fetch(t,Object.assign(Object.assign({},r),{},{postParams:n}))}},{key:"oneAtATime",value:function(t,n){var r=null;return function(i,a){return r&&r.abort(),r=new AbortController,e.post(Object.assign(Object.assign({},i),{},{method:t}),a,Object.assign(Object.assign({},n),{},{abortController:r})).finally((function(){r=null}))}}}]),e}();function et(){return window.globalAjaxQueue}function tt(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function nt(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function rt(e,t,n){return t&&nt(e.prototype,t),n&&nt(e,n),e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var Be={mounted:function(e,t){var n={};$(e).addClass("matomo-dropdown-menu");var r=!!$(e).parent().closest(".dropdown-content").length;r&&(n={hover:!0},$(e).addClass("submenu"),$(t.value.activates).addClass("submenu-dropdown-content"),$(e).parents(".dropdown-content").addClass("submenu-container")),$(e).dropdown(n)}}; + */window.ajaxHelper=Ze,window.angular.module("piwikApp.service").service("globalAjaxQueue",et);var it=window,at=it.$,ot=function(){function e(){tt(this,e),this.setup()}return rt(e,[{key:"setup",value:function(){var e=this;Object(a["watch"])((function(){return Ee.parsed.value.popover}),(function(){return e.onPopoverParamChanged()})),Ee.parsed.value.popover&&this.onPopoverParamChangedInitial()}},{key:"onPopoverParamChangedInitial",value:function(){var e=this;at((function(){setTimeout((function(){e.openOrClose()}))}))}},{key:"onPopoverParamChanged",value:function(){var e=this;at((function(){e.openOrClose()}))}},{key:"openOrClose",value:function(){this.close();var e=Ee.parsed.value.popover;e?this.open(e):window.broadcast.resetPopoverStack()}},{key:"close",value:function(){window.Piwik_Popover.close()}},{key:"open",value:function(e){var t=decodeURIComponent(e);t=t.replace(/\$/g,"%"),t=decodeURIComponent(t);var n=t.split(":"),r=n[0];n.shift();var i=n.join(":");"undefined"===typeof window.broadcast.popoverHandlers[r]||window.broadcast.isLoginPage()||window.broadcast.popoverHandlers[r](i)}}]),e}();new ot;function lt(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ct(e,t,n,r,i,o){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:Object(a["normalizeClass"])(["alert",lt({},"alert-".concat(e.severity),!0)])},[Object(a["renderSlot"])(e.$slots,"default")],2)}var st=Object(a["defineComponent"])({props:{severity:{type:String,required:!0}}});st.render=ct;var ut=st; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function He(e){return{restrict:"A",link:function(t,n,r){var a={instance:null,value:{activates:$("#".concat(r.activates))[0]},oldValue:null,modifiers:{},dir:{}};e((function(){Be.mounted(n[0],a)}))}}} + */function dt(){var e=a["createApp"].apply(void 0,arguments);return e.config.globalProperties.$sanitize=window.vueSanitize,e.config.globalProperties.translate=C,e.config.globalProperties.translateOrDefault=E,e}function pt(e,t){return vt(e)||gt(e,t)||ft(e,t)||mt()}function mt(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ft(e,t){if(e){if("string"===typeof e)return ht(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?ht(e,t):void 0}}function ht(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function gt(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a=[],o=!0,l=!1;try{for(n=n.call(e);!(o=(r=n.next()).done);o=!0)if(a.push(r.value),t&&a.length===t)break}catch(c){l=!0,i=c}finally{try{o||null==n["return"]||n["return"]()}finally{if(l)throw i}}return a}}function vt(e){if(Array.isArray(e))return e}function bt(e){return bt="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},bt(e)} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var yt=0;function wt(e){return e.substring(0,1).toLowerCase()+e.substring(1).replace(/[A-Z]/g,(function(e){return"-".concat(e.toLowerCase())}))}function Ot(e){return e.substring(0,1).toLowerCase()+e.substring(1).replace(/-([a-z])/g,(function(e,t){return t.toUpperCase()}))}function jt(e){return"object"===bt(e)&&null!==e&&Object.getPrototypeOf(e)===Object.prototype?Object.fromEntries(Object.entries(e).filter((function(e){return!/^\$/.test(e[0])}))):e}function kt(e){var t=e.component,n=e.require,r=e.scope,i=void 0===r?{}:r,o=e.events,l=void 0===o?{}:o,c=e.$inject,s=e.directiveName,u=e.transclude,d=e.mountPointFactory,p=e.postCreate,m=e.noScope,f=e.restrict,h=void 0===f?"A":f,g=e.priority,v=e.replace,b=yt;u&&(yt+=1);var y={},w={};function O(){for(var e=arguments.length,r=new Array(e),o=0;o<e;o++)r[o]=arguments[o];var c={restrict:h,require:n,priority:g,scope:m?void 0:w,compile:function(){return{post:function(e,n,o,c){var s=u?n.find("[ng-transclude][counter=".concat(b,"]")):null,m="<root-component";Object.entries(l).forEach((function(e){var t=pt(e,1),n=t[0];m+=" @".concat(wt(n),"=\"onEventHandler('").concat(n,"', $event)\"")})),Object.entries(i).forEach((function(e){var t=pt(e,2),n=t[1];if("&"===n.angularJsBind||"&?"===n.angularJsBind){var r=wt(n.vue);l[n.vue]||(m+=" @".concat(r,"=\"onEventHandler('").concat(n.vue,"', $event)\""))}else m+=" :".concat(wt(n.vue),'="').concat(n.vue,'"')})),m+=">",u&&(m+='<div ref="transcludeTarget"/>'),m+="</root-component>";var f=dt({template:m,data:function(){var t=this,a={};return Object.entries(i).forEach((function(i){var l=pt(i,2),s=l[0],u=l[1],d=jt(e[s]);"undefined"===typeof d&&"undefined"!==typeof u.default&&(d=u.default instanceof Function?u.default.apply(u,[e,n,o].concat(r)):u.default),u.transform&&(d=u.transform.apply(u,[d,t,e,n,o,c].concat(r))),a[u.vue]=d})),a},setup:function(){if(u){var e=Object(a["ref"])(null);return{transcludeTarget:e}}},methods:{onEventHandler:function(t,i){var a=Ot(t);a=y[a]||a,e[a]&&e[a](i),l[t]&&l[t].apply(l,[i,this,e,n,o,c].concat(r))}}});f.component("root-component",t);var h=d?d.apply(void 0,[e,n,o].concat(r)):n[0],g=f.mount(h);Object.entries(i).forEach((function(t){var i=pt(t,2),a=i[0],l=i[1];l.angularJsBind&&"&"!==l.angularJsBind&&"&?"!==l.angularJsBind&&e.$watch(a,(function(t,i){if(t!==i||JSON.stringify(g[l.vue])!==JSON.stringify(t)){var a=jt(t);"undefined"!==typeof l.default&&"undefined"===typeof t&&(a=l.default instanceof Function?l.default.apply(l,[e,n,o].concat(r)):l.default),l.transform&&(a=l.transform.apply(l,[a,g,e,n,o,c].concat(r))),g[l.vue]=a}}),l.deepWatch)})),u&&s&&$(g.transcludeTarget).append(s),p&&p.apply(void 0,[g,e,n,o,c].concat(r)),v&&(Array.from(n[0].attributes).forEach((function(e){i[e.nodeName]||h.firstElementChild&&h.firstElementChild.setAttribute(e.nodeName,e.nodeValue)})),n.replaceWith(window.$(h).children())),n.on("$destroy",(function(){f.unmount()}))}}}};return u&&(c.transclude=!0,c.template='<div ng-transclude counter="'.concat(b,'"/>')),c}return Object.entries(i).forEach((function(e){var t=pt(e,2),n=t[0],r=t[1];r.vue||(r.vue=n),r.angularJsBind&&(w[n]=r.angularJsBind),y[r.vue]=n})),O.$inject=c||[],window.angular.module("piwikApp").directive(s,O),O}function St(e){if("undefined"!==typeof e)return"true"===e||!!e&&e>0&&"0"!==e}function Ct(e){if("undefined"!==typeof e)return null===e?null:parseInt(e,10)}function Et(e){return"undefined"===typeof e?e:JSON.parse(JSON.stringify(e))}function Dt(e){var t=Et(e);return S.helper.getAngularDependency("$rootScope").$applyAsync(),t} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */kt({component:ut,scope:{severity:{vue:"severity",angularJsBind:"@piwikAlert"}},directiveName:"piwikAlert",transclude:!0}); +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var Pt={mounted:function(e,t){var n={};$(e).addClass("matomo-dropdown-menu");var r,i=!!$(e).parent().closest(".dropdown-content").length;i&&(n={hover:!0},$(e).addClass("submenu"),$((null===(r=t.value)||void 0===r?void 0:r.activates)||$(e).data("target")).addClass("submenu-dropdown-content"),$(e).parents(".dropdown-content").addClass("submenu-container"));$(e).dropdown(n)},updated:function(e){Object(a["nextTick"])((function(){$(e).addClass("matomo-dropdown-menu")}))}}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function Vt(e){return{restrict:"A",link:function(t,n,r){var i={instance:null,value:{activates:$("#".concat(r.activates))[0]},oldValue:null,modifiers:{},dir:{}};e((function(){Pt.mounted(n[0],i)}))}}} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function Nt(e,t,n){var r=t.value.isMouseDown&&t.value.hasScrolled;t.value.isMouseDown=!1,t.value.hasScrolled=!1,r||e.contains(n.target)||t.value&&t.value.blur()}function Tt(e,t){t.value.hasScrolled=!0}function At(e,t){t.value.isMouseDown=!0,t.value.hasScrolled=!1}function It(e,t,n){27===n.which&&setTimeout((function(){t.value.isMouseDown=!1,t.value.hasScrolled=!1,t.value.blur&&t.value.blur()}),0)}Vt.$inject=["$timeout"],window.angular.module("piwikApp").directive("piwikDropdownMenu",Vt);var xt=document.documentElement,Bt={mounted:function(e,t){t.value.isMouseDown=!1,t.value.hasScrolled=!1,t.value.onEscapeHandler=It.bind(null,e,t),t.value.onMouseDown=At.bind(null,e,t),t.value.onClickOutsideElement=Nt.bind(null,e,t),t.value.onScroll=Tt.bind(null,e,t),xt.addEventListener("keyup",t.value.onEscapeHandler),xt.addEventListener("mousedown",t.value.onMouseDown),xt.addEventListener("mouseup",t.value.onClickOutsideElement),xt.addEventListener("scroll",t.value.onScroll)},unmounted:function(e,t){xt.removeEventListener("keyup",t.value.onEscapeHandler),xt.removeEventListener("mousedown",t.value.onMouseDown),xt.removeEventListener("mouseup",t.value.onClickOutsideElement),xt.removeEventListener("scroll",t.value.onScroll)}}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function Mt(){return{restrict:"A",link:function(e,t,n){var r={instance:null,value:{blur:function(){setTimeout((function(){e.$apply(n.piwikFocusAnywhereButHere)}),0)}},oldValue:null,modifiers:{},dir:{}};Bt.mounted(t[0],r),t.on("$destroy",(function(){return Bt.unmounted(t[0],r)}))}}} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function Ae(e,t,n){var r=t.value.isMouseDown&&t.value.hasScrolled;t.value.isMouseDown=!1,t.value.hasScrolled=!1,r||e.contains(n.target)||t.value&&t.value.blur()}function Me(e,t){t.value.hasScrolled=!0}function Fe(e,t){t.value.isMouseDown=!0,t.value.hasScrolled=!1}function Ve(e,t,n){27===n.which&&setTimeout((function(){t.value.isMouseDown=!1,t.value.hasScrolled=!1,t.value.blur&&t.value.blur()}),0)}He.$inject=["$timeout"],angular.module("piwikApp").directive("piwikDropdownMenu",He);var Le=document.documentElement,Re={mounted:function(e,t){t.value.isMouseDown=!1,t.value.hasScrolled=!1,t.value.onEscapeHandler=Ve.bind(null,e,t),t.value.onMouseDown=Fe.bind(null,e,t),t.value.onClickOutsideElement=Ae.bind(null,e,t),t.value.onScroll=Me.bind(null,e,t),Le.addEventListener("keyup",t.value.onEscapeHandler),Le.addEventListener("mousedown",t.value.onMouseDown),Le.addEventListener("mouseup",t.value.onClickOutsideElement),Le.addEventListener("scroll",t.value.onScroll)},unmounted:function(e,t){Le.removeEventListener("keyup",t.value.onEscapeHandler),Le.removeEventListener("mousedown",t.value.onMouseDown),Le.removeEventListener("mouseup",t.value.onClickOutsideElement),Le.removeEventListener("scroll",t.value.onScroll)}}; +function Lt(e,t){t.arg&&setTimeout((function(){e.focus(),t.value.afterFocus&&t.value.afterFocus()}),5)}window.angular.module("piwikApp.directive").directive("piwikFocusAnywhereButHere",Mt);var Rt={mounted:function(e,t){Lt(e,t)},updated:function(e,t){Lt(e,t)}}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function Ft(){return{restrict:"A",link:function(e,t,n){e.$watch(n.piwikFocusIf,(function(n){var r={instance:null,arg:n?"1":void 0,value:{afterFocus:function(){return e.$apply()}},oldValue:null,modifiers:{},dir:{}};Rt.updated(t[0],r)}))}}} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function Ue(){return{restrict:"A",link:function(e,t,n){var r={instance:null,value:{blur:function(){setTimeout((function(){e.$apply(n.piwikFocusAnywhereButHere)}),0)}},oldValue:null,modifiers:{},dir:{}};Re.mounted(t[0],r),t.on("$destroy",(function(){return Re.unmounted(t[0],r)}))}}} +function _t(e,t){var n;return e instanceof HTMLElement?e:null===(n=t.instance)||void 0===n?void 0:n.$refs[e]}window.angular.module("piwikApp.directive").directive("piwikFocusIf",Ft);var $t={getRef:_t}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function Ht(e){e.classList.toggle("expanded");var t=e.querySelector(".dropdown.positionInViewport");t&&S.helper.setMarginLeftToBeInViewport(t)}function Ut(e,t,n){var r=t.value.isMouseDown&&t.value.hasScrolled;t.value.isMouseDown=!1,t.value.hasScrolled=!1,r||e.contains(n.target)||e.classList.remove("expanded")}function qt(e){e.value.hasScrolled=!0}function Wt(e){e.value.isMouseDown=!0,e.value.hasScrolled=!1}function Jt(e,t,n){27===n.which&&(t.value.isMouseDown=!1,t.value.hasScrolled=!1,e.classList.remove("expanded"))}var Gt=document.documentElement,zt=window,Yt=zt.$,Qt={mounted:function(e,t){t.value.isMouseDown=!1,t.value.hasScrolled=!1,t.value.onExpand=Ht.bind(null,e),t.value.onEscapeHandler=Jt.bind(null,e,t),t.value.onMouseDown=Wt.bind(null,t),t.value.onClickOutsideElement=Ut.bind(null,e,t),t.value.onScroll=qt.bind(null,t),setTimeout((function(){var e=$t.getRef(t.value.expander,t);e&&Yt(e).on("click",t.value.onExpand)})),Gt.addEventListener("keyup",t.value.onEscapeHandler),Gt.addEventListener("mousedown",t.value.onMouseDown),Gt.addEventListener("mouseup",t.value.onClickOutsideElement),Gt.addEventListener("scroll",t.value.onScroll)},unmounted:function(e,t){var n=$t.getRef(t.value.expander,t);n&&Yt(n).off("click",t.value.onExpand),Gt.removeEventListener("keyup",t.value.onEscapeHandler),Gt.removeEventListener("mousedown",t.value.onMouseDown),Gt.removeEventListener("mouseup",t.value.onClickOutsideElement),Gt.removeEventListener("scroll",t.value.onScroll)}}; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function _e(e,t){t.arg&&setTimeout((function(){e.focus(),t.value.afterFocus&&t.value.afterFocus()}),5)}Ue.$inject=[],angular.module("piwikApp.directive").directive("piwikFocusAnywhereButHere",Ue);var Je={mounted:function(e,t){_e(e,t)},updated:function(e,t){_e(e,t)}}; +function Kt(){return{restrict:"A",link:function(e,t){var n={instance:null,value:{expander:t.find(".title").first()[0]},oldValue:null,modifiers:{},dir:{}};Qt.mounted(t[0],n),t.on("$destroy",(function(){return Qt.unmounted(t[0],n)}))}}} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function Ge(){return{restrict:"A",link:function(e,t,n){e.$watch(n.piwikFocusIf,(function(n){var r={instance:null,arg:n?"1":void 0,value:{afterFocus:function(){return e.$apply()}},oldValue:null,modifiers:{},dir:{}};Je.updated(t[0],r)}))}}} + */ +function Xt(e){e.classList.add("expanded");var t=e.querySelector(".dropdown.positionInViewport");t&&S.helper.setMarginLeftToBeInViewport(t)}function Zt(e){e.classList.remove("expanded")}function en(e,t){e.contains(t.target)||e.classList.remove("expanded")}function tn(e,t){27===t.which&&e.classList.remove("expanded")}window.angular.module("piwikApp").directive("piwikExpandOnClick",Kt);var nn=document.documentElement,rn={mounted:function(e,t){t.value.onMouseEnter=Xt.bind(null,e),t.value.onMouseLeave=Zt.bind(null,e),t.value.onClickOutsideElement=en.bind(null,e),t.value.onEscapeHandler=tn.bind(null,e),setTimeout((function(){var e=$t.getRef(t.value.expander,t);e&&e.addEventListener("mouseenter",t.value.onMouseEnter)})),e.addEventListener("mouseleave",t.value.onMouseLeave),nn.addEventListener("keyup",t.value.onEscapeHandler),nn.addEventListener("mouseup",t.value.onClickOutsideElement)},unmounted:function(e,t){var n=$t.getRef(t.value.expander,t);n&&n.removeEventListener("mouseenter",t.value.onMouseEnter),e.removeEventListener("mouseleave",t.value.onMouseLeave),document.removeEventListener("keyup",t.value.onEscapeHandler),document.removeEventListener("mouseup",t.value.onClickOutsideElement)}}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function an(){return{restrict:"A",link:function(e,t){var n={instance:null,value:{expander:t.find(".title").first()[0]},oldValue:null,modifiers:{},dir:{}};rn.mounted(t[0],n),t.on("$destroy",(function(){return rn.unmounted(t[0],n)}))}}}window.angular.module("piwikApp").directive("piwikExpandOnHover",an); +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +var on=window,ln=on.$,cn={mounted:function(e,t){var n=ln(e),r=t.value.sensitiveData,i=t.value.showCharacters||6,a=t.value.clickElementSelector||n,o="";function l(){n.html(r),ln(a).css({cursor:""}),ln(a).tooltip("destroy")}i>0&&(o+=r.slice(0,i)),o+=r.slice(i).replace(/./g,"*"),n.html(o),ln(a).tooltip({content:C("CoreHome_ClickToSeeFullInformation"),items:"*",track:!0}),ln(a).one("click",l),ln(a).css({cursor:"pointer"})}}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function sn(){return{restrict:"A",link:function(e,t,n){var r={instance:null,value:{sensitiveData:n.piwikShowSensitiveData||(n.text?n.text():""),showCharacters:n.showCharacters?parseInt(n.showCharacters,10):void 0,clickElementSelector:n.clickElementSelector},oldValue:null,modifiers:{},dir:{}};cn.mounted(t[0],r)}}}window.angular.module("piwikApp").directive("piwikShowSensitiveData",sn); /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function qe(e){e.classList.toggle("expanded");var t=e.querySelector(".dropdown.positionInViewport");t&&D.helper.setMarginLeftToBeInViewport(t)}function ze(e,t,n){var r=t.value.isMouseDown&&t.value.hasScrolled;t.value.isMouseDown=!1,t.value.hasScrolled=!1,r||e.contains(n.target)||e.classList.remove("expanded")}function Qe(e){e.value.hasScrolled=!0}function Ye(e){e.value.isMouseDown=!0,e.value.hasScrolled=!1}function We(e,t,n){27===n.which&&(t.value.isMouseDown=!1,t.value.hasScrolled=!1,e.classList.remove("expanded"))}angular.module("piwikApp.directive").directive("piwikFocusIf",Ge);var Ke=document.documentElement,Xe={mounted:function(e,t){t.value.isMouseDown=!1,t.value.hasScrolled=!1,t.value.onExpand=qe.bind(null,e),t.value.onEscapeHandler=We.bind(null,e,t),t.value.onMouseDown=Ye.bind(null,t),t.value.onClickOutsideElement=ze.bind(null,e,t),t.value.onScroll=Qe.bind(null,t),t.value.expander.addEventListener("click",t.value.onExpand),Ke.addEventListener("keyup",t.value.onEscapeHandler),Ke.addEventListener("mousedown",t.value.onMouseDown),Ke.addEventListener("mouseup",t.value.onClickOutsideElement),Ke.addEventListener("scroll",t.value.onScroll)},unmounted:function(e,t){t.value.expander.removeEventListener("click",t.value.onExpand),Ke.removeEventListener("keyup",t.value.onEscapeHandler),Ke.removeEventListener("mousedown",t.value.onMouseDown),Ke.removeEventListener("mouseup",t.value.onClickOutsideElement),Ke.removeEventListener("scroll",t.value.onScroll)}}; +var un=window,dn=un.$,pn={mounted:function(e){var t=dn(e);!t.attr("data-target")&&t.attr("data-activates")&&t.attr("data-target",t.attr("data-activates"));var n=t.attr("data-target");n&&dn("#".concat(n)).length&&t.dropdown({inDuration:300,outDuration:225,constrainWidth:!1,belowOrigin:!0})}}; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function Ze(){return{restrict:"A",link:function(e,t){var n={instance:null,value:{expander:t.find(".title").first()[0]},oldValue:null,modifiers:{},dir:{}};Xe.mounted(t[0],n),t.on("$destroy",(function(){return Xe.unmounted(t[0],n)}))}}} +function mn(){return{restrict:"C",link:function(e,t){pn.mounted(t[0])}}} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function fn(e,t){e.value.focusedElement!==t.target&&(e.value.focusedElement=t.target,window.angular.element(t.target).select())}function hn(e){var t=document.createRange();t.selectNode(e.target);var n=window.getSelection();n&&n.rangeCount>0&&n.removeAllRanges(),n&&n.addRange(t)}function gn(e){delete e.value.focusedElement}window.angular.module("piwikApp").directive("dropdownButton",mn);var vn={mounted:function(e,t){var n=e.tagName.toLowerCase();t.value.elementSupportsSelect="textarea"===n,t.value.elementSupportsSelect?(t.value.onFocusHandler=fn.bind(null,t),t.value.onBlurHandler=gn.bind(null,t),e.addEventListener("focus",t.value.onFocusHandler),e.addEventListener("blur",t.value.onBlurHandler)):(t.value.onClickHandler=hn,e.addEventListener("click",t.value.onClickHandler))},unmounted:function(e,t){t.value.elementSupportsSelect?(e.removeEventListener("focus",t.value.onFocusHandler),e.removeEventListener("blur",t.value.onBlurHandler)):e.removeEventListener("click",t.value.onClickHandler)}}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function bn(){return{restrict:"A",link:function(e,t){var n={instance:null,value:{},oldValue:null,modifiers:{},dir:{}};vn.mounted(t[0],n),t.on("$destroy",(function(){return vn.unmounted(t[0],n)}))}}}window.angular.module("piwikApp").directive("piwikSelectOnFocus",bn); +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +var yn=!1,wn={mounted:function(e,t){t.value.activator&&setTimeout((function(){if(!yn){yn=!0;var n=$t.getRef(t.value.activator,t);if(n){window.$(n).show();var r=n.getAttribute("data-target");window.$("#".concat(r)).sidenav({closeOnClick:!0})}}e.classList.contains("collapsible")&&window.$(e).collapsible()}))}}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function On(e){return{restrict:"A",priority:10,link:function(t,n,r){var i={instance:null,value:{activator:$(r.piwikSideNav)[0]},oldValue:null,modifiers:{},dir:{}};e((function(){wn.mounted(n[0],i)}))}}}On.$inject=["$timeout"],window.angular.module("piwikApp.directive").directive("piwikSideNav",On);var jn={ref:"root"};function kn(e,t,n,r,i,o){return Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",jn,[Object(a["renderSlot"])(e.$slots,"default")],512)),[[a["vShow"],e.modelValue]])}var Sn=Object(a["defineComponent"])({props:{modelValue:{type:Boolean,required:!0},element:{type:HTMLElement,required:!1}},emits:["yes","no","closeEnd","close","validation","update:modelValue"],activated:function(){this.$emit("update:modelValue",!1)},watch:{modelValue:function(e,t){var n=this;if(e){var r=this.element||this.$refs.root.firstElementChild;S.helper.modalConfirm(r,{yes:function(){n.$emit("yes")},no:function(){n.$emit("no")},validation:function(){n.$emit("validation")}},{onCloseEnd:function(){n.element||n.$refs.root.appendChild(r),n.$emit("update:modelValue",!1),n.$emit("closeEnd")}})}else!1===e&&!0===t&&this.$emit("close")}}});Sn.render=kn;var Cn=Sn,En=(kt({component:Cn,scope:{show:{vue:"modelValue",default:!1},element:{default:function(e,t){return t[0]}}},events:{yes:function(e,t,n,r,i){i.yes&&(n.$eval(i.yes),setTimeout((function(){n.$apply()}),0))},no:function(e,t,n,r,i){i.no&&(n.$eval(i.no),setTimeout((function(){n.$apply()}),0))},validation:function(e,t,n,r,i){i.no&&(n.$eval(i.no),setTimeout((function(){n.$apply()}),0))},close:function(e,t,n,r,i){i.close&&(n.$eval(i.close),setTimeout((function(){n.$apply()}),0))},"update:modelValue":function(e,t,n,r,i,a,o){setTimeout((function(){n.$apply(o(i.piwikDialog).assign(n,e))}),0)}},$inject:["$parse"],directiveName:"piwikDialog",transclude:!0,mountPointFactory:function(e,t){var n=$('<div class="vue-placeholder"/>');return n.appendTo(t),n[0]},postCreate:function(e,t,n,r){t.$watch(r.piwikDialog,(function(t,n){n!==t&&(e.modelValue=t||!1)}))},noScope:!0}),{key:0,class:"title",tabindex:"6"}),Dn=["href","title"],Pn={class:"iconsBar"},Vn=["href","title"],Nn=Object(a["createElementVNode"])("span",{class:"icon-help"},null,-1),Tn=[Nn],An=["title"],In=Object(a["createElementVNode"])("span",{class:"icon-info"},null,-1),xn=[In],Bn={class:"ratingIcons"},Mn={class:"inlineHelp"},Ln=["innerHTML"],Rn=["innerHTML"],Fn=["href"]; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function _n(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("RateFeature");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"enrichedHeadline",onMouseenter:t[1]||(t[1]=function(t){return e.showIcons=!0}),onMouseleave:t[2]||(t[2]=function(t){return e.showIcons=!1}),ref:"root"},[e.editUrl?Object(a["createCommentVNode"])("",!0):(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",En,[Object(a["renderSlot"])(e.$slots,"default")])),e.editUrl?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:1,class:"title",href:e.editUrl,title:e.translate("CoreHome_ClickToEditX",e.$sanitize(e.actualFeatureName))},[Object(a["renderSlot"])(e.$slots,"default")],8,Dn)):Object(a["createCommentVNode"])("",!0),Object(a["withDirectives"])(Object(a["createElementVNode"])("span",Pn,[e.helpUrl&&!e.actualInlineHelp?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:0,rel:"noreferrer noopener",target:"_blank",class:"helpIcon",href:e.helpUrl,title:e.translate("CoreHome_ExternalHelp")},Tn,8,Vn)):Object(a["createCommentVNode"])("",!0),e.actualInlineHelp?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:1,onClick:t[0]||(t[0]=function(t){return e.showInlineHelp=!e.showInlineHelp}),class:Object(a["normalizeClass"])(["helpIcon",{active:e.showInlineHelp}]),title:e.translate(e.reportGenerated?"General_HelpReport":"General_Help")},xn,10,An)):Object(a["createCommentVNode"])("",!0),Object(a["createElementVNode"])("div",Bn,[Object(a["createVNode"])(l,{title:e.actualFeatureName},null,8,["title"])])],512),[[a["vShow"],e.showIcons||e.showInlineHelp]]),Object(a["withDirectives"])(Object(a["createElementVNode"])("div",Mn,[Object(a["createElementVNode"])("div",{innerHTML:e.$sanitize(e.actualInlineHelp)},null,8,Ln),""!=e.reportGenerated?(Object(a["openBlock"])(),Object(a["createElementBlock"])("span",{key:0,class:"helpDate",innerHTML:e.$sanitize(e.reportGenerated)},null,8,Rn)):Object(a["createCommentVNode"])("",!0),e.helpUrl?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:1,rel:"noreferrer noopener",target:"_blank",class:"readMore",href:e.helpUrl},Object(a["toDisplayString"])(e.translate("General_MoreDetails")),9,Fn)):Object(a["createCommentVNode"])("",!0)],512),[[a["vShow"],e.showInlineHelp]])],544)} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function $n(e,t){return Object(a["defineAsyncComponent"])((function(){return new Promise((function(n){window.$(document).ready((function(){window[e]?n(window[e][t]):n(null)}))}))}))}var Hn=$n("Feedback","RateFeature"),Un=Object(a["defineComponent"])({props:{helpUrl:{type:String,default:""},editUrl:{type:String,default:""},reportGenerated:String,featureName:String,inlineHelp:String},components:{RateFeature:Hn},data:function(){return{showIcons:!1,showInlineHelp:!1,actualFeatureName:this.featureName,actualInlineHelp:this.inlineHelp}},watch:{inlineHelp:function(e){this.actualInlineHelp=e},featureName:function(e){this.actualFeatureName=e}},mounted:function(){var e=this,t=this.$refs.root;setTimeout((function(){if(!e.actualInlineHelp){var n,r=t.querySelector(".title .inlineHelp");if(!r&&null!==(n=t.parentElement)&&void 0!==n&&n.nextElementSibling&&(r=t.parentElement.nextElementSibling.querySelector(".reportDocumentation")),r){var i,a=null===(i=r.getAttribute("data-content"))||void 0===i?void 0:i.trim();a&&a.length&&(e.actualInlineHelp="<p>".concat(a,"</p>"),setTimeout((function(){return r.remove()}),0))}}var o;e.actualFeatureName||(e.actualFeatureName=null===(o=t.querySelector(".title"))||void 0===o?void 0:o.textContent);if(S.period&&S.currentDateString){var l=p.parse(S.period,S.currentDateString);e.reportGenerated&&l.containsToday()&&window.$(t.querySelector(".report-generated")).tooltip({track:!0,content:e.reportGenerated,items:"div",show:!1,hide:!1})}}))}});Un.render=_n;var qn=Un,Wn=(kt({component:qn,scope:{helpUrl:{angularJsBind:"@"},editUrl:{angularJsBind:"@"},reportGenerated:{angularJsBind:"@?"},featureName:{angularJsBind:"@"},inlineHelp:{angularJsBind:"@?"}},directiveName:"piwikEnrichedHeadline",transclude:!0}),{class:"card",ref:"root"}),Jn={class:"card-content"},Gn={key:0,class:"card-title"},zn={key:1,class:"card-title"},Yn={ref:"content"}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function Qn(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("EnrichedHeadline");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Wn,[Object(a["createElementVNode"])("div",Jn,[!e.contentTitle||e.actualFeature||e.helpUrl||e.actualHelpText?Object(a["createCommentVNode"])("",!0):(Object(a["openBlock"])(),Object(a["createElementBlock"])("h2",Gn,Object(a["toDisplayString"])(e.contentTitle),1)),e.contentTitle&&(e.actualFeature||e.helpUrl||e.actualHelpText)?(Object(a["openBlock"])(),Object(a["createElementBlock"])("h2",zn,[Object(a["createVNode"])(l,{"feature-name":e.actualFeature,"help-url":e.helpUrl,"inline-help":e.actualHelpText},{default:Object(a["withCtx"])((function(){return[Object(a["createTextVNode"])(Object(a["toDisplayString"])(e.contentTitle),1)]})),_:1},8,["feature-name","help-url","inline-help"])])):Object(a["createCommentVNode"])("",!0),Object(a["createElementVNode"])("div",Yn,[Object(a["renderSlot"])(e.$slots,"default")],512)])],512)}var Kn=null,Xn=window,Zn=Xn.$,er=Object(a["defineComponent"])({props:{contentTitle:String,feature:String,helpUrl:String,helpText:String,anchor:String},components:{EnrichedHeadline:qn},data:function(){return{actualFeature:this.feature,actualHelpText:this.helpText}},watch:{feature:function(e){this.actualFeature=e},helpText:function(e){this.actualHelpText=e}},mounted:function(){var e=this,t=this.$refs.root,n=this.$refs.content;if(this.anchor&&t&&t.parentElement){var r=document.createElement("a");r.id=this.anchor,Zn(t.parentElement).prepend(r)}setTimeout((function(){var t=n.querySelector(".contentHelp");t&&(e.actualHelpText=t.innerHTML,t.remove())}),0),this.actualFeature&&"true"===this.actualFeature&&(this.actualFeature=this.contentTitle),null===Kn&&(Kn=document.querySelector("#content.admin"));var i=null;if(Kn&&(i=Kn.offsetTop),i||0===i){var a=t.closest("[piwik-widget-loader]"),o=a?a.offsetTop:t.offsetTop;o-i<17&&(t.style.marginTop="0")}}});er.render=Qn;var tr=er; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */kt({component:tr,scope:{contentTitle:{angularJsBind:"@"},feature:{angularJsBind:"@"},helpUrl:{angularJsBind:"@"},helpText:{angularJsBind:"@"},anchor:{angularJsBind:"@?"}},directiveName:"piwikContentBlock",transclude:!0});function nr(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function rr(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function ir(e,t,n){return t&&rr(e.prototype,t),n&&rr(e,n),e}function ar(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var or=function(){function e(){var t=this;nr(this,e),ar(this,"segmentState",Object(a["reactive"])({availableSegments:[]})),S.on("piwikSegmentationInited",(function(){return t.setSegmentState()}))}return ir(e,[{key:"state",get:function(){return Object(a["readonly"])(this.segmentState)}},{key:"setSegmentState",value:function(){try{var e=$(".segmentEditorPanel").data("uiControlObject");this.segmentState.availableSegments=e.impl.availableSegments||[]}catch(t){}}}]),e}(),lr=new or;function cr(e){return pr(e)||dr(e)||ur(e)||sr()}function sr(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ur(e,t){if(e){if("string"===typeof e)return mr(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?mr(e,t):void 0}}function dr(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function pr(e){if(Array.isArray(e))return mr(e)}function mr(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function fr(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function hr(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function gr(e,t,n){return t&&hr(e.prototype,t),n&&hr(e,n),e}function vr(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var br=8,yr=3;function wr(e){return e?Array.isArray(e)?e:[e]:[]}var Or=function(){function e(){var t=this;fr(this,e),vr(this,"privateState",Object(a["reactive"])({comparisonsDisabledFor:[]})),vr(this,"state",Object(a["readonly"])(this.privateState)),vr(this,"colors",{}),vr(this,"segmentComparisons",Object(a["computed"])((function(){return t.parseSegmentComparisons()}))),vr(this,"periodComparisons",Object(a["computed"])((function(){return t.parsePeriodComparisons()}))),vr(this,"isEnabled",Object(a["computed"])((function(){return t.checkEnabledForCurrentPage()}))),this.loadComparisonsDisabledFor(),$((function(){t.colors=t.getAllSeriesColors()})),Object(a["watch"])((function(){return t.getComparisons()}),(function(){return S.postEvent("piwikComparisonsChanged")}),{deep:!0})}return gr(e,[{key:"getComparisons",value:function(){return this.getSegmentComparisons().concat(this.getPeriodComparisons())}},{key:"isComparing",value:function(){return this.isComparisonEnabled()&&(this.segmentComparisons.value.length>1||this.periodComparisons.value.length>1)}},{key:"isComparingPeriods",value:function(){return this.getPeriodComparisons().length>1}},{key:"getSegmentComparisons",value:function(){return this.isComparisonEnabled()?this.segmentComparisons.value:[]}},{key:"getPeriodComparisons",value:function(){return this.isComparisonEnabled()?this.periodComparisons.value:[]}},{key:"getSeriesColor",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=this.getComparisonSeriesIndex(t.index,e.index)%br;if(0===n)return this.colors["series".concat(r)];var i=n%yr;return this.colors["series".concat(r,"-shade").concat(i)]}},{key:"getSeriesColorName",value:function(e,t){var n="series".concat(e%br);return t>0&&(n+="-shade".concat(t%yr)),n}},{key:"isComparisonEnabled",value:function(){return this.isEnabled.value}},{key:"getIndividualComparisonRowIndices",value:function(e){var t=this.getSegmentComparisons().length,n=e%t,r=Math.floor(e/t);return{segmentIndex:n,periodIndex:r}}},{key:"getComparisonSeriesIndex",value:function(e,t){var n=this.getSegmentComparisons().length;return e*n+t}},{key:"getAllComparisonSeries",value:function(){var e=this,t=[],n=0;return this.getPeriodComparisons().forEach((function(r){e.getSegmentComparisons().forEach((function(i){t.push({index:n,params:Object.assign(Object.assign({},i.params),r.params),color:e.colors["series".concat(n)]}),n+=1}))})),t}},{key:"removeSegmentComparison",value:function(e){if(!this.isComparisonEnabled())throw new Error("Comparison disabled.");var t=cr(this.segmentComparisons.value);t.splice(e,1);var n={};0===e&&(n.segment=t[0].params.segment),this.updateQueryParamsFromComparisons(t,this.periodComparisons.value,n)}},{key:"addSegmentComparison",value:function(e){if(!this.isComparisonEnabled())throw new Error("Comparison disabled.");var t=this.segmentComparisons.value.concat([{params:e,index:-1,title:""}]);this.updateQueryParamsFromComparisons(t,this.periodComparisons.value)}},{key:"updateQueryParamsFromComparisons",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r={},i={},a=!1,o=!1;e.forEach((function(e){a?r[e.params.segment]=!0:a=!0})),t.forEach((function(e){o?i["".concat(e.params.period,"|").concat(e.params.date)]=!0:o=!0}));var l=[],c=[];Object.keys(i).forEach((function(e){var t=e.split("|");l.push(t[0]),c.push(t[1])}));var s={compareSegments:Object.keys(r),comparePeriods:l,compareDates:c},u=S.helper.isAngularRenderingThePage()?Ee.hashParsed.value:Ee.urlParsed.value;Ee.updateLocation(Object.assign(Object.assign(Object.assign({},u),s),n))}},{key:"getAllSeriesColors",value:function(){var e=S.ColorManager;if(!e)return[];for(var t=[],n=0;n<br;n+=1){t.push("series".concat(n));for(var r=0;r<yr;r+=1)t.push("series".concat(n,"-shade").concat(r))}return e.getColors("comparison-series-color",t)}},{key:"loadComparisonsDisabledFor",value:function(){var e=this,t=Ee.parsed.value.module;window.piwik.installation||"CoreUpdater"===t||"Installation"===t||"Overlay"===t||window.piwik.isPagesComparisonApiDisabled?this.privateState.comparisonsDisabledFor=[]:Ze.fetch({module:"API",method:"API.getPagesComparisonsDisabledFor"}).then((function(t){e.privateState.comparisonsDisabledFor=t}))}},{key:"parseSegmentComparisons",value:function(){var e=lr.state.availableSegments,t=cr(wr(Ee.parsed.value.compareSegments));t.unshift(Ee.parsed.value.segment||"");var n=[];return t.forEach((function(t,r){var i;e.forEach((function(e){e.definition!==t&&e.definition!==decodeURIComponent(t)&&decodeURIComponent(e.definition)!==t||(i=e)}));var a=i?i.name:C("General_Unknown");""===t.trim()&&(a=C("SegmentEditor_DefaultAllVisits")),n.push({params:{segment:t},title:S.helper.htmlDecode(a),index:r})})),n}},{key:"parsePeriodComparisons",value:function(){var e=cr(wr(Ee.parsed.value.comparePeriods)),t=cr(wr(Ee.parsed.value.compareDates));e.unshift(Ee.parsed.value.period),t.unshift(Ee.parsed.value.date);for(var n=[],r=0;r<Math.min(t.length,e.length);r+=1){var i=void 0;try{i=p.parse(e[r],t[r]).getPrettyString()}catch(a){i=C("General_Error")}n.push({params:{date:t[r],period:e[r]},title:i,index:r})}return n}},{key:"checkEnabledForCurrentPage",value:function(){var e=Ee.parsed.value.category||Ee.parsed.value.module,t=Ee.parsed.value.subcategory||Ee.parsed.value.action,n="".concat(e,".").concat(t),r=-1===this.privateState.comparisonsDisabledFor.indexOf(n)&&-1===this.privateState.comparisonsDisabledFor.indexOf("".concat(e,".*"));return document.documentElement.classList.toggle("comparisonsDisabled",!r),r}}]),e}(),jr=new Or,kr={key:0,ref:"root",class:"matomo-comparisons"},Sr={class:"comparison-type"},Cr=["title"],Er=["href"],Dr=["title"],Pr={class:"comparison-period-label"},Vr=["onClick"],Nr=["title"],Tr={class:"loadingPiwik",style:{display:"none"}},Ar=["alt"];function Ir(e,t,n,r,i,o){var l=Object(a["resolveDirective"])("tooltips");return e.isComparing?Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",kr,[Object(a["createElementVNode"])("h3",null,Object(a["toDisplayString"])(e.translate("General_Comparisons")),1),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.segmentComparisons,(function(t,n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"comparison card",key:t.index},[Object(a["createElementVNode"])("div",Sr,Object(a["toDisplayString"])(e.translate("General_Segment")),1),Object(a["createElementVNode"])("div",{class:"title",title:t.title+"<br/>"+decodeURIComponent(t.params.segment)},[Object(a["createElementVNode"])("a",{target:"_blank",href:e.getUrlToSegment(t.params.segment)},Object(a["toDisplayString"])(t.title),9,Er)],8,Cr),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.periodComparisons,(function(n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"comparison-period",key:n.index,title:e.getComparisonTooltip(t,n)},[Object(a["createElementVNode"])("span",{class:"comparison-dot",style:Object(a["normalizeStyle"])({"background-color":e.getSeriesColor(t,n)})},null,4),Object(a["createElementVNode"])("span",Pr,Object(a["toDisplayString"])(n.title)+" ("+Object(a["toDisplayString"])(e.getComparisonPeriodType(n))+") ",1)],8,Dr)})),128)),e.segmentComparisons.length>1?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:0,class:"remove-button",onClick:function(t){return e.removeSegmentComparison(n)}},[Object(a["createElementVNode"])("span",{class:"icon icon-close",title:e.translate("General_ClickToRemoveComp")},null,8,Nr)],8,Vr)):Object(a["createCommentVNode"])("",!0)])})),128)),Object(a["createElementVNode"])("div",Tr,[Object(a["createElementVNode"])("img",{src:"plugins/Morpheus/images/loading-blue.gif",alt:e.translate("General_LoadingData")},null,8,Ar),Object(a["createTextVNode"])(" "+Object(a["toDisplayString"])(e.translate("General_LoadingData")),1)])],512)),[[l,{duration:200,delay:200,content:e.transformTooltipContent}]]):Object(a["createCommentVNode"])("",!0)} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var xr=window,Br=xr.$;function Mr(){var e=Br(this).attr("title")||"";return window.vueSanitize(e.replace(/\n/g,"<br />"))}function Lr(e,t){var n,r,i;Br(e).tooltip({track:!0,content:(null===(n=t.value)||void 0===n?void 0:n.content)||Mr,show:{delay:(null===(r=t.value)||void 0===r?void 0:r.delay)||700,duration:(null===(i=t.value)||void 0===i?void 0:i.duration)||200},hide:!1})}var Rr={mounted:function(e,t){setTimeout((function(){return Lr(e,t)}))},updated:function(e,t){setTimeout((function(){return Lr(e,t)}))},beforeUnmount:function(e){try{window.$(e).tooltip("destroy")}catch(t){}}},Fr=Object(a["defineComponent"])({props:{},directives:{Tooltips:Rr},data:function(){return{comparisonTooltips:null}},setup:function(){var e=Object(a["computed"])((function(){return jr.isComparing()})),t=Object(a["computed"])((function(){return jr.getSegmentComparisons()})),n=Object(a["computed"])((function(){return jr.getPeriodComparisons()})),r=jr.getSeriesColor.bind(jr);function i(){var e=window.$(this).attr("title");return e?window.vueSanitize(e.replace(/\n/g,"<br />")):e}return{isComparing:e,segmentComparisons:t,periodComparisons:n,getSeriesColor:r,transformTooltipContent:i}},methods:{comparisonHasSegment:function(e){return"undefined"!==typeof e.params.segment},removeSegmentComparison:function(e){window.$(this.$refs.root).tooltip("destroy"),jr.removeSegmentComparison(e)},getComparisonPeriodType:function(e){var t=e.params.period;if("range"===t)return C("CoreHome_PeriodRange");var n=C("Intl_Period".concat(t.substring(0,1).toUpperCase()).concat(t.substring(1)));return n.substring(0,1).toUpperCase()+n.substring(1)},getComparisonTooltip:function(e,t){if(this.comparisonTooltips&&Object.keys(this.comparisonTooltips).length)return(this.comparisonTooltips[t.index]||{})[e.index]},getUrlToSegment:function(e){var t=Object.assign({},Ee.hashParsed.value);return delete t.comparePeriods,delete t.compareDates,delete t.compareSegments,t.segment=e,"".concat(window.location.search,"#?").concat(Ee.stringify(t))},onComparisonsChanged:function(){var e=this;if(this.comparisonTooltips=null,jr.isComparing()){var t=jr.getPeriodComparisons(),n=jr.getSegmentComparisons();Ze.fetch({method:"API.getProcessedReport",apiModule:"VisitsSummary",apiAction:"get",compare:"1",compareSegments:Ee.getSearchParam("compareSegments"),comparePeriods:Ee.getSearchParam("comparePeriods"),compareDates:Ee.getSearchParam("compareDates"),format_metrics:"1"}).then((function(r){e.comparisonTooltips={},t.forEach((function(t){e.comparisonTooltips[t.index]={},n.forEach((function(n){var i=e.generateComparisonTooltip(r,t,n);e.comparisonTooltips[t.index][n.index]=i}))}))}))}},generateComparisonTooltip:function(e,t,n){if(!e.reportData.comparisons)return"";var r=jr.getComparisonSeriesIndex(t.index,0),i=e.reportData.comparisons[r],a=jr.getComparisonSeriesIndex(t.index,n.index),o=e.reportData.comparisons[a],l=e.reportData.comparisons[n.index],c='<div class="comparison-card-tooltip">',s=(o.nb_visits/i.nb_visits*100).toFixed(2);return s="".concat(s,"%"),c+=C("General_ComparisonCardTooltip1",["'".concat(o.compareSegmentPretty,"'"),o.comparePeriodPretty,s,o.nb_visits.toString(),i.nb_visits.toString()]),t.index>0&&(c+="<br/><br/>",c+=C("General_ComparisonCardTooltip2",[o.nb_visits_change.toString(),l.compareSegmentPretty,l.comparePeriodPretty])),c+="</div>",c}},mounted:function(){var e=this;S.on("piwikComparisonsChanged",(function(){e.onComparisonsChanged()})),this.onComparisonsChanged()}});Fr.render=Ir;var _r=Fr; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function $r(){return jr}window.angular.module("piwikApp.service").factory("piwikComparisonsService",$r);kt({component:_r,directiveName:"piwikComparisons",restrict:"E"});var Hr={ref:"root",class:"menuDropdown"},Ur=["title"],qr=["innerHTML"],Wr=Object(a["createElementVNode"])("span",{class:"icon-arrow-bottom"},null,-1),Jr={class:"items"},Gr={key:0,class:"search"},zr=["placeholder"],Yr=["title"],Qr=["title"];function Kr(e,t,n,r,i,o){var l=Object(a["resolveDirective"])("focus-if"),c=Object(a["resolveDirective"])("focus-anywhere-but-here");return Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Hr,[Object(a["createElementVNode"])("span",{class:"title",onClick:t[0]||(t[0]=function(t){return e.showItems=!e.showItems}),title:e.tooltip},[Object(a["createElementVNode"])("span",{innerHTML:e.$sanitize(this.actualMenuTitle)},null,8,qr),Wr],8,Ur),Object(a["withDirectives"])(Object(a["createElementVNode"])("div",Jr,[e.showSearch&&e.showItems?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Gr,[Object(a["withDirectives"])(Object(a["createElementVNode"])("input",{type:"text","onUpdate:modelValue":t[1]||(t[1]=function(t){return e.searchTerm=t}),onKeydown:t[2]||(t[2]=function(t){return e.onSearchTermKeydown(t)}),placeholder:e.translate("General_Search")},null,40,zr),[[a["vModelText"],e.searchTerm],[l,{},e.showItems]]),Object(a["withDirectives"])(Object(a["createElementVNode"])("img",{class:"search_ico",src:"plugins/Morpheus/images/search_ico.png",title:e.translate("General_Search")},null,8,Yr),[[a["vShow"],!e.searchTerm]]),Object(a["withDirectives"])(Object(a["createElementVNode"])("img",{onClick:t[3]||(t[3]=function(t){e.searchTerm="",e.searchItems("")}),class:"reset",src:"plugins/CoreHome/images/reset_search.png",title:e.translate("General_Clear")},null,8,Qr),[[a["vShow"],e.searchTerm]])])):Object(a["createCommentVNode"])("",!0),Object(a["createElementVNode"])("div",{onClick:t[4]||(t[4]=function(t){return e.selectItem(t)})},[Object(a["renderSlot"])(e.$slots,"default")])],512),[[a["vShow"],e.showItems]])],512)),[[c,{blur:e.lostFocus}]])}var Xr=window,Zr=Xr.$,ei=Object(a["defineComponent"])({props:{menuTitle:String,tooltip:String,showSearch:Boolean,menuTitleChangeOnClick:Boolean},directives:{FocusAnywhereButHere:Bt,FocusIf:Rt},emits:["afterSelect"],watch:{menuTitle:function(){this.actualMenuTitle=this.menuTitle}},data:function(){return{showItems:!1,searchTerm:"",actualMenuTitle:this.menuTitle}},methods:{lostFocus:function(){this.showItems=!1},selectItem:function(e){var t=e.target.classList;!t.contains("item")||t.contains("disabled")||t.contains("separator")||(this.menuTitleChangeOnClick&&(this.actualMenuTitle=(e.target.textContent||"").replace(/[\u0000-\u2666]/g,(function(e){return"&#".concat(e.charCodeAt(0),";")}))),this.showItems=!1,Zr(this.$slots.default()[0].el).find(".item").removeClass("active"),t.add("active"),this.$emit("afterSelect"))},onSearchTermKeydown:function(){var e=this;setTimeout((function(){e.searchItems(e.searchTerm)}))},searchItems:function(e){var t=e.toLowerCase();Zr(this.$refs.root).find(".item").each((function(e,n){var r=Zr(n);-1===r.text().toLowerCase().indexOf(t)?r.hide():r.show()}))}}});ei.render=Kr;var ti=ei,ni=(kt({component:ti,scope:{menuTitle:{angularJsBind:"@"},tooltip:{angularJsBind:"@"},showSearch:{angularJsBind:"="},menuTitleChangeOnClick:{angularJsBind:"="}},directiveName:"piwikMenudropdown",transclude:!0,events:{"after-select":function(e,t,n){setTimeout((function(){n.$apply()}),0)}}}),{ref:"root"}); +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function ri(e,t,n,r,i,o){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",ni,null,512)}var ii=1,ai=window,oi=ai.$,li=Object(a["defineComponent"])({props:{selectedDateStart:Date,selectedDateEnd:Date,highlightedDateStart:Date,highlightedDateEnd:Date,viewDate:[String,Date],stepMonths:Number,disableMonthDropdown:Boolean,options:Object},emits:["cellHover","cellHoverLeave","dateSelect"],setup:function(e,t){var n=Object(a["ref"])(null);function r(t,n){var r=t.children("a");if(e.selectedDateStart&&e.selectedDateEnd&&n>=e.selectedDateStart&&n<=e.selectedDateEnd?t.addClass("ui-datepicker-current-period"):t.removeClass("ui-datepicker-current-period"),e.highlightedDateStart&&e.highlightedDateEnd&&n>=e.highlightedDateStart&&n<=e.highlightedDateEnd){var i=r.length?r:t;i.addClass("ui-state-hover")}else t.removeClass("ui-state-hover"),r.removeClass("ui-state-hover")}function i(e,t,n){if(e.hasClass("ui-datepicker-other-month"))return o(e,t,n);var r=parseInt(e.children("a,span").text(),10);return new Date(n,t,r)}function o(e,t,n){var r,a=e.parent(),o=a.children("td");if(a.is(":first-child")){var l=a.children("td:not(.ui-datepicker-other-month)").first();return r=i(l,t,n),r.setDate(o.index(e)-o.index(l)+1),r}var c=a.children("td:not(.ui-datepicker-other-month)").last();return r=i(c,t,n),r.setDate(r.getDate()+o.index(e)-o.index(c)),r}function l(){var e=oi(n.value),t=e.find("td[data-month]"),r=parseInt(t.attr("data-month"),10),i=parseInt(t.attr("data-year"),10);return[r,i]}function c(){var e=oi(n.value),t=e.find(".ui-datepicker-calendar"),a=l(),o=t.find("td"),c=o.first(),s=i(c,a[0],a[1]);o.each((function(){r(oi(this),s),s.setDate(s.getDate()+1)}))}function s(){if(!e.viewDate)return!1;var t;if("string"===typeof e.viewDate)try{t=V(e.viewDate)}catch(a){return!1}else t=e.viewDate;var r=oi(n.value),i=l();return(i[0]!==t.getMonth()||i[1]!==t.getFullYear())&&(r.datepicker("setDate",t),!0)}function u(){var e=oi(n.value);e.find("td[data-event]").off("click"),e.find(".ui-state-active").removeClass("ui-state-active"),e.find(".ui-datepicker-current-day").removeClass("ui-datepicker-current-day"),e.find(".ui-datepicker-prev,.ui-datepicker-next").attr("href","")}function d(){var t=oi(n.value),r=e.stepMonths||ii;if(t.datepicker("option","stepMonths")===r)return!1;var i=oi(".ui-datepicker-month",t).val(),a=oi(".ui-datepicker-year",t).val();return t.datepicker("option","stepMonths",r).datepicker("setDate",new Date(a,i)),u(),!0}function p(){var t=oi(n.value),r=t.find(".ui-datepicker-month")[0];r&&(r.disabled=e.disableMonthDropdown)}function m(){if(oi(this).hasClass("ui-state-hover")){var e=oi(this).parent(),t=e.parent();e.is(":first-child")?t.find("a").first().click():t.find("a").last().click()}}function f(){p(),c()}return Object(a["watch"])((function(){return Object.assign({},e)}),(function(e,t){var n=!1;[function(e){return e.selectedDateStart},function(e){return e.selectedDateEnd},function(e){return e.highlightedDateStart},function(e){return e.highlightedDateEnd}].forEach((function(r){if(!n){var i=r(e),a=r(t);!i&&a&&(n=!0),i&&!a&&(n=!0),i&&a&&i.getTime()!==a.getTime()&&(n=!0)}})),e.viewDate!==t.viewDate&&s()&&(n=!0),e.stepMonths!==t.stepMonths&&d(),e.disableMonthDropdown!==t.disableMonthDropdown&&p(),n&&c()})),Object(a["onMounted"])((function(){var r=oi(n.value),a=e.options||{},o=Object.assign(Object.assign(Object.assign({},S.getBaseDatePickerOptions()),a),{},{onChangeMonthYear:function(){setTimeout((function(){u()}))}});r.datepicker(o),r.on("mouseover","tbody td a",(function(e){e.originalEvent&&c()})),r.on("mouseenter","tbody td",(function(){var e=l(),n=oi(this),r=i(n,e[0],e[1]);t.emit("cellHover",{date:r,$cell:n})})),r.on("mouseout","tbody td a",(function(){c()})),r.on("mouseleave","table",(function(){return t.emit("cellHoverLeave")})).on("mouseenter","thead",(function(){return t.emit("cellHoverLeave")})),r.on("click","tbody td.ui-datepicker-other-month",m),r.on("click",(function(e){e.preventDefault();var t=oi(e.target).closest("a");(t.is(".ui-datepicker-next")||t.is(".ui-datepicker-prev"))&&f()})),r.on("click","td[data-month]",(function(e){var n=oi(e.target).closest("td"),r=parseInt(n.attr("data-month"),10),i=parseInt(n.attr("data-year"),10),a=parseInt(n.children("a,span").text(),10);t.emit("dateSelect",{date:new Date(i,r,a)})}));var h=d();s(),p(),h||u(),c()})),{root:n}}});li.render=ri;var ci=li,si=(kt({component:ci,scope:{selectedDateStart:{angularJsBind:"<"},selectedDateEnd:{angularJsBind:"<"},highlightedDateStart:{angularJsBind:"<"},highlightedDateEnd:{angularJsBind:"<"},viewDate:{angularJsBind:"<"},stepMonths:{angularJsBind:"<"},disableMonthDropdown:{angularJsBind:"<"},options:{angularJsBind:"<"},cellHover:{angularJsBind:"&"},cellHoverLeave:{angularJsBind:"&"},dateSelect:{angularJsBind:"&"}},directiveName:"piwikDatePicker",events:{"cell-hover":function(e,t,n,r,i,a,o){o()},"cell-hover-leave":function(e,t,n,r,i,a,o){o()},"date-select":function(e,t,n,r,i,a,o){o()}},$inject:["$timeout"]}),{id:"calendarRangeFrom"}),ui={id:"calendarRangeTo"}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function di(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("DatePicker");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",null,[Object(a["createElementVNode"])("div",si,[Object(a["createElementVNode"])("h6",null,[Object(a["createTextVNode"])(Object(a["toDisplayString"])(e.translate("General_DateRangeFrom"))+" ",1),Object(a["withDirectives"])(Object(a["createElementVNode"])("input",{type:"text",id:"inputCalendarFrom",name:"inputCalendarFrom",class:"browser-default","onUpdate:modelValue":t[0]||(t[0]=function(t){return e.startDateText=t}),onKeydown:t[1]||(t[1]=function(t){return e.onRangeInputChanged("from",t)}),onKeyup:t[2]||(t[2]=function(t){return e.handleEnterPress(t)})},null,544),[[a["vModelText"],e.startDateText]])]),Object(a["createVNode"])(l,{id:"calendarFrom","view-date":e.startDate,"selected-date-start":e.fromPickerSelectedDates[0],"selected-date-end":e.fromPickerSelectedDates[1],"highlighted-date-start":e.fromPickerHighlightedDates[0],"highlighted-date-end":e.fromPickerHighlightedDates[1],onDateSelect:t[3]||(t[3]=function(t){return e.setStartRangeDate(t.date)}),onCellHover:t[4]||(t[4]=function(t){return e.fromPickerHighlightedDates=e.getNewHighlightedDates(t.date,t.$cell)}),onCellHoverLeave:t[5]||(t[5]=function(t){return e.fromPickerHighlightedDates=[null,null]})},null,8,["view-date","selected-date-start","selected-date-end","highlighted-date-start","highlighted-date-end"])]),Object(a["createElementVNode"])("div",ui,[Object(a["createElementVNode"])("h6",null,[Object(a["createTextVNode"])(Object(a["toDisplayString"])(e.translate("General_DateRangeTo"))+" ",1),Object(a["withDirectives"])(Object(a["createElementVNode"])("input",{type:"text",id:"inputCalendarTo",name:"inputCalendarTo",class:"browser-default","onUpdate:modelValue":t[6]||(t[6]=function(t){return e.endDateText=t}),onKeydown:t[7]||(t[7]=function(t){return e.onRangeInputChanged("to",t)}),onKeyup:t[8]||(t[8]=function(t){return e.handleEnterPress(t)})},null,544),[[a["vModelText"],e.endDateText]])]),Object(a["createVNode"])(l,{id:"calendarTo","view-date":e.endDate,"selected-date-start":e.toPickerSelectedDates[0],"selected-date-end":e.toPickerSelectedDates[1],"highlighted-date-start":e.toPickerHighlightedDates[0],"highlighted-date-end":e.toPickerHighlightedDates[1],onDateSelect:t[9]||(t[9]=function(t){return e.setEndRangeDate(t.date)}),onCellHover:t[10]||(t[10]=function(t){return e.toPickerHighlightedDates=e.getNewHighlightedDates(t.date,t.$cell)}),onCellHoverLeave:t[11]||(t[11]=function(t){return e.toPickerHighlightedDates=[null,null]})},null,8,["view-date","selected-date-start","selected-date-end","highlighted-date-start","highlighted-date-end"])])])}var pi="YYYY-MM-DD",mi=Object(a["defineComponent"])({props:{startDate:String,endDate:String},components:{DatePicker:ci},data:function(){var e=null;try{this.startDate&&(e=V(this.startDate))}catch(n){}var t=null;try{this.endDate&&(t=V(this.endDate))}catch(n){}return{fromPickerSelectedDates:[e,e],toPickerSelectedDates:[t,t],fromPickerHighlightedDates:[null,null],toPickerHighlightedDates:[null,null],startDateText:this.startDate,endDateText:this.endDate,startDateInvalid:!1,endDateInvalid:!1}},emits:["rangeChange","submit"],watch:{startDate:function(){this.startDateText=this.startDate,this.setStartRangeDateFromStr(this.startDate)},endDate:function(){this.endDateText=this.endDate,this.setEndRangeDateFromStr(this.endDate)}},mounted:function(){this.rangeChanged()},methods:{setStartRangeDate:function(e){this.fromPickerSelectedDates=[e,e],this.rangeChanged()},setEndRangeDate:function(e){this.toPickerSelectedDates=[e,e],this.rangeChanged()},onRangeInputChanged:function(e,t){var n=this;setTimeout((function(){"from"===e?n.setStartRangeDateFromStr(t.target.value):n.setEndRangeDateFromStr(t.target.value)}))},getNewHighlightedDates:function(e,t){return t.hasClass("ui-datepicker-unselectable")?null:[e,e]},handleEnterPress:function(e){13===e.keyCode&&this.$emit("submit",{start:this.startDate,end:this.endDate})},setStartRangeDateFromStr:function(e){this.startDateInvalid=!0;var t=null;try{e&&e.length===pi.length&&(t=V(e))}catch(n){}t&&(this.fromPickerSelectedDates=[t,t],this.startDateInvalid=!1,this.rangeChanged())},setEndRangeDateFromStr:function(e){this.endDateInvalid=!0;var t=null;try{e&&e.length===pi.length&&(t=V(e))}catch(n){}t&&(this.toPickerSelectedDates=[t,t],this.endDateInvalid=!1,this.rangeChanged())},rangeChanged:function(){this.$emit("rangeChange",{start:this.fromPickerSelectedDates[0]?D(this.fromPickerSelectedDates[0]):null,end:this.toPickerSelectedDates[0]?D(this.toPickerSelectedDates[0]):null})}}});mi.render=di;var fi=mi; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */kt({component:fi,scope:{startDate:{angularJsBind:"<"},endDate:{angularJsBind:"<"},rangeChange:{angularJsBind:"&"},submit:{angularJsBind:"&"}},directiveName:"piwikDateRangePicker",restrict:"E"});function hi(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("DatePicker");return Object(a["openBlock"])(),Object(a["createBlock"])(l,{"selected-date-start":e.selectedDates[0],"selected-date-end":e.selectedDates[1],"highlighted-date-start":e.highlightedDates[0],"highlighted-date-end":e.highlightedDates[1],"view-date":e.viewDate,"step-months":"year"===e.period?12:1,"disable-month-dropdown":"year"===e.period,onCellHover:t[0]||(t[0]=function(t){return e.onHoverNormalCell(t.date,t.$cell)}),onCellHoverLeave:t[1]||(t[1]=function(t){return e.onHoverLeaveNormalCells()}),onDateSelect:t[2]||(t[2]=function(t){return e.onDateSelected(t.date)})},null,8,["selected-date-start","selected-date-end","highlighted-date-start","highlighted-date-end","view-date","step-months","disable-month-dropdown"])}var gi=new Date(S.minDateYear,S.minDateMonth-1,S.minDateDay),vi=new Date(S.maxDateYear,S.maxDateMonth-1,S.maxDateDay),bi=Object(a["defineComponent"])({props:{period:{type:String,required:!0},date:[String,Date]},components:{DatePicker:ci},emits:["select"],setup:function(e,t){var n=Object(a["ref"])(e.date),r=Object(a["ref"])([null,null]),i=Object(a["ref"])([null,null]);function o(t){var n=p.get(e.period).parse(t).getDateRange();return n[0]=gi<n[0]?n[0]:gi,n[1]=vi>n[1]?n[1]:vi,n}function l(t,n){var r=t<gi||t>vi,a=n.hasClass("ui-datepicker-other-month")&&("month"===e.period||"day"===e.period);i.value=r||a?[null,null]:o(t)}function c(){i.value=[null,null]}function s(e){t.emit("select",{date:e})}function u(){if(!e.period||!e.date)return r.value=[null,null],void(n.value=null);r.value=o(e.date),n.value=V(e.date)}return Object(a["watch"])(e,u),u(),{selectedDates:r,highlightedDates:i,viewDate:n,onHoverNormalCell:l,onHoverLeaveNormalCells:c,onDateSelected:s}}});bi.render=hi;var yi=bi,wi=(kt({component:yi,scope:{period:{angularJsBind:"<"},date:{angularJsBind:"<"},select:{angularJsBind:"&"}},directiveName:"piwikPeriodDatePicker",restrict:"E"}),["value","name"]),Oi=["title"],ji=["textContent"],ki={key:1,class:"placeholder"},Si={class:"dropdown"},Ci={class:"custom_select_search"},Ei=["placeholder"],Di={key:0},Pi={class:"custom_select_container"},Vi=["onClick"],Ni=["innerHTML","href","title"],Ti={class:"ui-autocomplete ui-front ui-menu ui-widget ui-widget-content ui-corner-all\n siteSelect"},Ai={class:"ui-menu-item"},Ii={class:"ui-corner-all",tabindex:"-1"},xi={key:1}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function Bi(e,t,n,r,i,o){var l,c,s,u,d=Object(a["resolveComponent"])("AllSitesLink"),p=Object(a["resolveDirective"])("focus-if"),m=Object(a["resolveDirective"])("focus-anywhere-but-here");return Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:Object(a["normalizeClass"])(["siteSelector piwikSelector borderedControl",{expanded:e.showSitesList,disabled:!e.hasMultipleSites}])},[e.name?(Object(a["openBlock"])(),Object(a["createElementBlock"])("input",{key:0,type:"hidden",value:null===(l=e.modelValue)||void 0===l?void 0:l.id,name:e.name},null,8,wi)):Object(a["createCommentVNode"])("",!0),Object(a["createElementVNode"])("a",{ref:"selectorLink",onClick:t[0]||(t[0]=function(){return e.onClickSelector&&e.onClickSelector.apply(e,arguments)}),onKeydown:t[1]||(t[1]=function(t){return e.onPressEnter(t)}),href:"javascript:void(0)",class:Object(a["normalizeClass"])([{loading:e.isLoading},"title"]),tabindex:"4",title:e.selectorLinkTitle},[Object(a["createElementVNode"])("span",{class:Object(a["normalizeClass"])(["icon icon-arrow-bottom",{iconHidden:e.isLoading,collapsed:!e.showSitesList}])},null,2),Object(a["createElementVNode"])("span",null,[null!==(c=e.modelValue)&&void 0!==c&&c.name||!e.placeholder?(Object(a["openBlock"])(),Object(a["createElementBlock"])("span",{key:0,textContent:Object(a["toDisplayString"])((null===(s=e.modelValue)||void 0===s?void 0:s.name)||e.firstSiteName)},null,8,ji)):Object(a["createCommentVNode"])("",!0),null!==(u=e.modelValue)&&void 0!==u&&u.name||!e.placeholder?Object(a["createCommentVNode"])("",!0):(Object(a["openBlock"])(),Object(a["createElementBlock"])("span",ki,Object(a["toDisplayString"])(e.placeholder),1))])],42,Oi),Object(a["withDirectives"])(Object(a["createElementVNode"])("div",Si,[Object(a["withDirectives"])(Object(a["createElementVNode"])("div",Ci,[Object(a["withDirectives"])(Object(a["createElementVNode"])("input",{type:"text",onClick:t[2]||(t[2]=function(t){e.searchTerm="",e.loadInitialSites()}),"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.searchTerm=t}),tabindex:"4",class:"websiteSearch inp browser-default",placeholder:e.translate("General_Search")},null,8,Ei),[[a["vModelText"],e.searchTerm],[p,{},e.shouldFocusOnSearch]]),Object(a["withDirectives"])(Object(a["createElementVNode"])("img",{title:"Clear",onClick:t[4]||(t[4]=function(t){e.searchTerm="",e.loadInitialSites()}),class:"reset",src:"plugins/CoreHome/images/reset_search.png"},null,512),[[a["vShow"],e.searchTerm]])],512),[[a["vShow"],e.autocompleteMinSites<=e.sites.length||e.searchTerm]]),"top"===e.allSitesLocation&&e.showAllSitesItem?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Di,[Object(a["createVNode"])(d,{href:e.urlAllSites,"all-sites-text":e.allSitesText,onClick:t[5]||(t[5]=function(t){return e.onAllSitesClick(t)})},null,8,["href","all-sites-text"])])):Object(a["createCommentVNode"])("",!0),Object(a["createElementVNode"])("div",Pi,[Object(a["createElementVNode"])("ul",{class:"custom_select_ul_list",onClick:t[7]||(t[7]=function(t){return e.showSitesList=!1})},[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.sites,(function(n,r){return Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("li",{onClick:function(t){return e.switchSite(Object.assign(Object.assign({},n),{},{id:n.idsite}),t)},key:r},[Object(a["createElementVNode"])("a",{onClick:t[6]||(t[6]=function(e){return e.preventDefault()}),innerHTML:e.$sanitize(e.getMatchedSiteName(n.name)),tabindex:"4",href:e.getUrlForSiteId(n.idsite),title:n.name},null,8,Ni)],8,Vi)),[[a["vShow"],!(!e.showSelectedSite&&e.activeSiteId===n.idsite)]])})),128))]),Object(a["withDirectives"])(Object(a["createElementVNode"])("ul",Ti,[Object(a["createElementVNode"])("li",Ai,[Object(a["createElementVNode"])("a",Ii,Object(a["toDisplayString"])(e.translate("SitesManager_NotFound")+" "+e.searchTerm),1)])],512),[[a["vShow"],!e.sites.length&&e.searchTerm]])]),"bottom"===e.allSitesLocation&&e.showAllSitesItem?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",xi,[Object(a["createVNode"])(d,{href:e.urlAllSites,"all-sites-text":e.allSitesText,onClick:t[8]||(t[8]=function(t){return e.onAllSitesClick(t)})},null,8,["href","all-sites-text"])])):Object(a["createCommentVNode"])("",!0)],512),[[a["vShow"],e.showSitesList]])],2)),[[m,{blur:e.onBlur}]])}var Mi=["innerHTML","href"];function Li(e,t,n,r,i,o){var l=this;return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{onClick:t[1]||(t[1]=function(e){return l.onClick(e)}),class:"custom_select_all"},[Object(a["createElementVNode"])("a",{onClick:t[0]||(t[0]=function(e){return e.preventDefault()}),innerHTML:e.$sanitize(e.allSitesText),tabindex:"4",href:e.href},null,8,Mi)])}var Ri=Object(a["defineComponent"])({props:{href:String,allSitesText:String},emits:["click"],methods:{onClick:function(e){this.$emit("click",e)}}});Ri.render=Li;var Fi=Ri;function _i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function $i(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function Hi(e,t,n){return t&&$i(e.prototype,t),n&&$i(e,n),e}function Ui(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var qi=function(){function e(){var t=this;_i(this,e),Ui(this,"state",Object(a["reactive"])({initialSites:[],isInitialized:!1})),Ui(this,"currentRequestAbort",null),Ui(this,"limitRequest",void 0),Ui(this,"initialSites",Object(a["computed"])((function(){return Object(a["readonly"])(t.state.initialSites)})))}return Hi(e,[{key:"loadInitialSites",value:function(){var e=this;return this.state.isInitialized?Promise.resolve(Object(a["readonly"])(this.state.initialSites)):this.searchSite("%").then((function(t){return e.state.isInitialized=!0,null!==t&&(e.state.initialSites=t),t}))}},{key:"loadSite",value:function(e){"all"===e?Ee.updateUrl(Object.assign(Object.assign({},Ee.urlParsed.value),{},{module:"MultiSites",action:"index",date:Ee.parsed.value.date,period:Ee.parsed.value.period})):Ee.updateUrl(Object.assign(Object.assign({},Ee.urlParsed.value),{},{segment:"",idSite:e}),Object.assign(Object.assign({},Ee.hashParsed.value),{},{segment:"",idSite:e}))}},{key:"searchSite",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return e?(this.currentRequestAbort&&this.currentRequestAbort.abort(),this.limitRequest||(this.limitRequest=Ze.fetch({method:"SitesManager.getNumWebsitesToDisplayPerPage"})),this.limitRequest.then((function(r){var i=r.value,a="SitesManager.getPatternMatchSites";return n&&(a="SitesManager.getSitesWithAdminAccess"),t.currentRequestAbort=new AbortController,Ze.fetch({method:a,limit:i,pattern:e},{abortController:t.currentRequestAbort})})).then((function(e){return e?t.processWebsitesList(e):null})).finally((function(){t.currentRequestAbort=null}))):this.loadInitialSites()}},{key:"processWebsitesList",value:function(e){var t=e;return t&&t.length?(t=t.map((function(e){return Object.assign(Object.assign({},e),{},{name:e.group?"[".concat(e.group,"] ").concat(e.name):e.name})})),t.sort((function(e,t){return e.name.toLowerCase()<t.name.toLowerCase()?-1:e.name.toLowerCase()>t.name.toLowerCase()?1:0})),t):[]}}]),e}(),Wi=new qi,Ji=300;function Gi(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:Ji;return function(){for(var r=this,i=arguments.length,a=new Array(i),o=0;o<i;o++)a[o]=arguments[o];t&&clearTimeout(t),t=setTimeout((function(){e.call.apply(e,[r].concat(a))}),n)}}var zi=Object(a["defineComponent"])({props:{modelValue:{type:Object,default:function(e){return e.modelValue?e.modelValue:S.idSite?{id:S.idSite,name:S.helper.htmlDecode(S.siteName)}:void 0}},showSelectedSite:{type:Boolean,default:!1},showAllSitesItem:{type:Boolean,default:!0},switchSiteOnSelect:{type:Boolean,default:!0},onlySitesWithAdminAccess:{type:Boolean,default:!1},name:{type:String,default:""},allSitesText:{type:String,default:C("General_MultiSitesSummary")},allSitesLocation:{type:String,default:"bottom"},placeholder:String},emits:["update:modelValue","blur"],components:{AllSitesLink:Fi},directives:{FocusAnywhereButHere:Bt,FocusIf:Rt},watch:{searchTerm:function(){this.onSearchTermChanged()}},data:function(){return{searchTerm:"",activeSiteId:"".concat(S.idSite),showSitesList:!1,isLoading:!1,sites:[],autocompleteMinSites:parseInt(S.config.autocomplete_min_sites,10)}},created:function(){this.searchSite=Gi(this.searchSite)},mounted:function(){var e=this;window.initTopControls(),this.loadInitialSites().then((function(){e.modelValue&&e.modelValue.id||e.hasMultipleSites||!e.sites[0]||e.$emit("update:modelValue",{id:e.sites[0].idsite,name:e.sites[0].name})}));var t=C("CoreHome_ShortcutWebsiteSelector");S.helper.registerShortcut("w",t,(function(t){if(!t.altKey){t.preventDefault?t.preventDefault():t.returnValue=!1;var n=e.$refs.selectorLink;n&&(n.click(),n.focus())}}))},computed:{shouldFocusOnSearch:function(){return this.showSitesList&&this.autocompleteMinSites<=this.sites.length||this.searchTerm},selectorLinkTitle:function(){var e;return this.hasMultipleSites?C("CoreHome_ChangeCurrentWebsite",(null===(e=this.modelValue)||void 0===e?void 0:e.name)||this.firstSiteName):""},hasMultipleSites:function(){return Wi.initialSites.value&&Wi.initialSites.value.length>1},firstSiteName:function(){var e=Wi.initialSites.value;return e&&e.length>0?e[0].name:""},urlAllSites:function(){var e=Ee.stringify(Object.assign(Object.assign({},Ee.urlParsed.value),{},{module:"MultiSites",action:"index",date:Ee.parsed.value.date,period:Ee.parsed.value.period}));return"?".concat(e)}},methods:{onSearchTermChanged:function(){this.searchTerm?(this.isLoading=!0,this.searchSite(this.searchTerm)):(this.isLoading=!1,this.loadInitialSites())},onAllSitesClick:function(e){this.switchSite({id:"all",name:this.$props.allSitesText},e),this.showSitesList=!1},switchSite:function(e,t){var n=-1!==navigator.userAgent.indexOf("Mac OS X")?t.metaKey:t.ctrlKey;t&&n&&t.target&&t.target.href?window.open(t.target.href,"_blank"):(this.$emit("update:modelValue",{id:e.id,name:e.name}),this.switchSiteOnSelect&&this.activeSiteId!==e.id&&Wi.loadSite(e.id))},onBlur:function(){this.showSitesList=!1,this.$emit("blur")},onClickSelector:function(){this.hasMultipleSites&&(this.showSitesList=!this.showSitesList,this.isLoading||this.searchTerm||this.loadInitialSites())},onPressEnter:function(e){"Enter"===e.key&&(e.preventDefault(),this.showSitesList=!this.showSitesList,this.showSitesList&&!this.isLoading&&this.loadInitialSites())},getMatchedSiteName:function(e){var t=e.toUpperCase().indexOf(this.searchTerm.toUpperCase());if(-1===t||this.isLoading)return S.helper.htmlEntities(e);var n=S.helper.htmlEntities(e.substring(0,t)),r=S.helper.htmlEntities(e.substring(t+this.searchTerm.length));return"".concat(n,'<span class="autocompleteMatched">').concat(this.searchTerm,"</span>").concat(r)},loadInitialSites:function(){var e=this;return Wi.loadInitialSites().then((function(t){e.sites=t||[]}))},searchSite:function(e){var t=this;this.isLoading=!0,Wi.searchSite(e,this.onlySitesWithAdminAccess).then((function(n){e===t.searchTerm&&n&&(t.sites=n)})).finally((function(){t.isLoading=!1}))},getUrlForSiteId:function(e){var t=Ee.stringify(Object.assign(Object.assign({},Ee.urlParsed.value),{},{segment:"",idSite:e})),n=Ee.stringify(Object.assign(Object.assign({},Ee.hashParsed.value),{},{segment:"",idSite:e}));return"?".concat(t,"#?").concat(n)}}});zi.render=Bi;var Yi=zi; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */kt({component:Yi,require:"?ngModel",scope:{showSelectedSite:{angularJsBind:"="},showAllSitesItem:{angularJsBind:"="},switchSiteOnSelect:{angularJsBind:"="},onlySitesWithAdminAccess:{angularJsBind:"="},name:{angularJsBind:"@"},allSitesText:{angularJsBind:"@"},allSitesLocation:{angularJsBind:"@"},placeholder:{angularJsBind:"@"},modelValue:{default:function(e,t,n){return n.siteid&&n.sitename?{id:n.siteid,name:S.helper.htmlDecode(n.sitename)}:S.idSite?{id:S.idSite,name:S.helper.htmlDecode(S.siteName)}:void 0}}},$inject:["$timeout"],directiveName:"piwikSiteselector",events:{"update:modelValue":function(e,t,n,r,i,a,o){(e&&!t.modelValue||!e&&t.modelValue||e.id!==t.modelValue.id)&&o((function(){n.value=e,r.attr("siteid",e.id),r.trigger("change",e),a&&(a.$setViewValue(e),a.$render())}))},blur:function(e,t,n){setTimeout((function(){return n.$apply()}))}},postCreate:function(e,t,n,r,i){var o=i;t.$watch("value",(function(t){Object(a["nextTick"])((function(){t!==e.modelValue&&(e.modelValue=t)}))})),r.siteid&&r.sitename?e.modelValue={id:r.siteid,name:S.helper.htmlDecode(r.sitename)}:S.idSite&&(e.modelValue={id:S.idSite,name:S.helper.htmlDecode(S.siteName)}),o&&(o.$setViewValue(e.modelValue),o.$render=function(){Object(a["nextTick"])((function(){Object(a["nextTick"])((function(){window.angular.isString(o.$viewValue)?e.modelValue=JSON.parse(o.$viewValue):e.modelValue=o.$viewValue}))}))})}}); /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function et(e){e.classList.add("expanded");var t=e.querySelector(".dropdown.positionInViewport");t&&D.helper.setMarginLeftToBeInViewport(t)}function tt(e){e.classList.remove("expanded")}function nt(e,t){e.contains(t.target)||e.classList.remove("expanded")}function rt(e,t){27===t.which&&e.classList.remove("expanded")}Ze.$inject=[],angular.module("piwikApp").directive("piwikExpandOnClick",Ze);var at=document.documentElement,ot={mounted:function(e,t){t.value.onMouseEnter=et.bind(null,e),t.value.onMouseLeave=tt.bind(null,e),t.value.onClickOutsideElement=nt.bind(null,e),t.value.onEscapeHandler=rt.bind(null,e),t.value.expander.addEventListener("mouseenter",t.value.onMouseEnter),e.addEventListener("mouseleave",t.value.onMouseLeave),at.addEventListener("keyup",t.value.onEscapeHandler),at.addEventListener("mouseup",t.value.onClickOutsideElement)},unmounted:function(e,t){t.value.expander.removeEventListener("mouseenter",t.value.onMouseEnter),e.removeEventListener("mouseleave",t.value.onMouseLeave),document.removeEventListener("keyup",t.value.onEscapeHandler),document.removeEventListener("mouseup",t.value.onClickOutsideElement)}}; +function Qi(){return{get initialSites(){return Wi.initialSites.value},loadSite:Wi.loadSite.bind(Wi),loadInitialSites:function(){return Dt(Wi.loadInitialSites())},searchSite:function(){return Dt(Wi.searchSite.apply(Wi,arguments))}}}window.angular.module("piwikApp.service").factory("siteSelectorModel",Qi);var Ki={ref:"root",class:"quickAccessInside"},Xi=["title","placeholder"],Zi={class:"dropdown"},ea={class:"no-result"},ta=["onClick"],na=["onMouseenter","onClick"],ra={class:"quickAccessMatomoSearch"},ia=["onMouseenter","onClick"],aa=["textContent"],oa={class:"quick-access-category helpCategory"},la=["href"];function ca(e,t,n,r,i,o){var l=Object(a["resolveDirective"])("focus-if"),c=Object(a["resolveDirective"])("focus-anywhere-but-here");return Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Ki,[Object(a["createElementVNode"])("span",{class:"icon-search",onMouseenter:t[0]||(t[0]=function(t){return e.searchActive=!0})},null,32),Object(a["withDirectives"])(Object(a["createElementVNode"])("input",{class:"s",onKeydown:t[1]||(t[1]=function(t){return e.onKeypress(t)}),onFocus:t[2]||(t[2]=function(t){return e.searchActive=!0}),"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.searchTerm=t}),type:"text",tabindex:"2",title:e.quickAccessTitle,placeholder:e.translate("General_Search"),ref:"input"},null,40,Xi),[[a["vModelText"],e.searchTerm],[l,{},e.searchActive]]),Object(a["withDirectives"])(Object(a["createElementVNode"])("div",Zi,[Object(a["withDirectives"])(Object(a["createElementVNode"])("ul",null,[Object(a["createElementVNode"])("li",ea,Object(a["toDisplayString"])(e.translate("General_SearchNoResults")),1)],512),[[a["vShow"],!(e.numMenuItems>0||e.sites.length)]]),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.menuItems,(function(t){return Object(a["openBlock"])(),Object(a["createElementBlock"])("ul",{key:t.title},[Object(a["createElementVNode"])("li",{class:"quick-access-category",onClick:function(n){e.searchTerm=t.title,e.searchMenu(e.searchTerm)}},Object(a["toDisplayString"])(t.title),9,ta),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(t.items,(function(t){return Object(a["openBlock"])(),Object(a["createElementBlock"])("li",{class:Object(a["normalizeClass"])(["result",{selected:t.menuIndex===e.searchIndex}]),onMouseenter:function(n){return e.searchIndex=t.menuIndex},onClick:function(n){return e.selectMenuItem(t.index)},key:t.index},[Object(a["createElementVNode"])("a",null,Object(a["toDisplayString"])(t.name.trim()),1)],42,na)})),128))])})),128)),Object(a["createElementVNode"])("ul",ra,[Object(a["withDirectives"])(Object(a["createElementVNode"])("li",{class:"quick-access-category websiteCategory"},Object(a["toDisplayString"])(e.translate("SitesManager_Sites")),513),[[a["vShow"],e.hasSitesSelector&&e.sites.length||e.isLoading]]),Object(a["withDirectives"])(Object(a["createElementVNode"])("li",{class:"no-result"},Object(a["toDisplayString"])(e.translate("MultiSites_LoadingWebsites")),513),[[a["vShow"],e.hasSitesSelector&&e.isLoading]]),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.sites,(function(t,n){return Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("li",{class:Object(a["normalizeClass"])(["result",{selected:e.numMenuItems+n===e.searchIndex}]),onMouseenter:function(t){return e.searchIndex=e.numMenuItems+n},onClick:function(n){return e.selectSite(t.idsite)},key:t.idsite},[Object(a["createElementVNode"])("a",{textContent:Object(a["toDisplayString"])(t.name)},null,8,aa)],42,ia)),[[a["vShow"],e.hasSitesSelector&&!e.isLoading]])})),128))]),Object(a["createElementVNode"])("ul",null,[Object(a["createElementVNode"])("li",oa,Object(a["toDisplayString"])(e.translate("General_HelpResources")),1),Object(a["createElementVNode"])("li",{class:Object(a["normalizeClass"])([{selected:"help"===e.searchIndex},"quick-access-help"]),onMouseenter:t[4]||(t[4]=function(t){return e.searchIndex="help"})},[Object(a["createElementVNode"])("a",{href:"https://matomo.org?mtm_campaign=App_Help&mtm_source=Matomo_App&mtm_keyword=QuickSearch&s=".concat(encodeURIComponent(e.searchTerm)),target:"_blank"},Object(a["toDisplayString"])(e.translate("CoreHome_SearchOnMatomo",e.searchTerm)),9,la)],34)])],512),[[a["vShow"],e.searchTerm&&e.searchActive]])],512)),[[c,{blur:e.onBlur}]])}function sa(e){var t=e.getBoundingClientRect(),n=window.$(window);return t.top>=0&&t.left>=0&&t.bottom<=n.height()&&t.right<=n.width()}function ua(e){e&&e.scrollIntoView&&e.scrollIntoView()}var da=Object(a["defineComponent"])({directives:{FocusAnywhereButHere:Bt,FocusIf:Rt},watch:{searchActive:function(e){var t=this.$refs.root;if(t&&t.parentElement){var n=t.parentElement.classList;n.toggle("active",e),n.toggle("expanded",e)}}},mounted:function(){var e=this,t=this.$refs.root;t&&t.parentElement&&t.parentElement.classList.add("quick-access","piwikSelector"),"undefined"!==typeof window.initTopControls&&window.initTopControls&&window.initTopControls(),S.helper.registerShortcut("f",C("CoreHome_ShortcutSearch"),(function(t){t.altKey||(t.preventDefault(),ua(e.$refs.root),e.activateSearch())}))},data:function(){var e=!!document.querySelector(".segmentEditorPanel");return{menuItems:[],numMenuItems:0,searchActive:!1,searchTerm:"",searchIndex:0,menuIndexCounter:-1,topMenuItems:null,leftMenuItems:null,segmentItems:null,hasSegmentSelector:e,sites:[],isLoading:!1}},created:function(){this.searchMenu=Gi(this.searchMenu.bind(this))},computed:{hasSitesSelector:function(){return!!document.querySelector(".top_controls [piwik-siteselector]")},quickAccessTitle:function(){var e="",t=[C("CoreHome_MenuEntries")];this.hasSegmentSelector&&t.push(C("CoreHome_Segments")),this.hasSitesSelector&&t.push(C("SitesManager_Sites"));while(t.length)e+=t.shift(),t.length>=2?e+=", ":1===t.length&&(e+=" ".concat(C("General_And")," "));return C("CoreHome_QuickAccessTitle",e)}},emits:["itemSelected","blur"],methods:{onKeypress:function(e){var t=this,n=this.searchTerm&&this.searchActive,r=9===e.which,i=27===e.which;38===e.which?(this.highlightPreviousItem(),e.preventDefault()):40===e.which?(this.highlightNextItem(),e.preventDefault()):13===e.which?this.clickQuickAccessMenuItem():r&&n||i&&n?this.deactivateSearch():setTimeout((function(){t.searchActive=!0,t.searchMenu(t.searchTerm)}))},highlightPreviousItem:function(){this.searchIndex-1<0?this.searchIndex=0:this.searchIndex-=1,this.makeSureSelectedItemIsInViewport()},highlightNextItem:function(){var e=this.$refs.root.querySelectorAll("li.result").length;e<=this.searchIndex+1?this.searchIndex=e-1:this.searchIndex+=1,this.makeSureSelectedItemIsInViewport()},clickQuickAccessMenuItem:function(){var e=this,t=this.getCurrentlySelectedElement();t&&setTimeout((function(){t.click(),e.$emit("itemSelected",t)}),20)},deactivateSearch:function(){this.searchTerm="",this.searchActive=!1,this.$refs.input&&this.$refs.input.blur()},makeSureSelectedItemIsInViewport:function(){var e=this.getCurrentlySelectedElement();e&&!sa(e)&&ua(e)},getCurrentlySelectedElement:function(){var e=this.$refs.root.querySelectorAll("li.result");if(e&&e.length&&e.item(this.searchIndex))return e.item(this.searchIndex)},searchMenu:function(e){var t=this,n=e.toLowerCase(),r=-1,i={},a=[],o=function(e){var t=Object.assign({},e);r+=1,t.menuIndex=r;var n=t.category;n in i||(a.push({title:n,items:[]}),i[n]=a.length-1);var o=i[n];a[o].items.push(t)};this.resetSearchIndex(),this.hasSitesSelector&&(this.isLoading=!0,Wi.searchSite(n).then((function(e){e&&(t.sites=e)})).finally((function(){t.isLoading=!1})));var l=function(e){return-1!==e.name.toLowerCase().indexOf(n)||-1!==e.category.toLowerCase().indexOf(n)};null===this.topMenuItems&&(this.topMenuItems=this.getTopMenuItems()),null===this.leftMenuItems&&(this.leftMenuItems=this.getLeftMenuItems()),null===this.segmentItems&&(this.segmentItems=this.getSegmentItems());var c=this.topMenuItems.filter(l),s=this.leftMenuItems.filter(l),u=this.segmentItems.filter(l);c.forEach(o),s.forEach(o),u.forEach(o),this.numMenuItems=c.length+s.length+u.length,this.menuItems=a},resetSearchIndex:function(){this.searchIndex=0,this.makeSureSelectedItemIsInViewport()},selectSite:function(e){Wi.loadSite(e)},selectMenuItem:function(e){var t=document.querySelector("[quick_access='".concat(e,"']"));if(t){this.deactivateSearch();var n=t.getAttribute("href");if(n&&n.length>10&&t&&t.click)try{t.click()}catch(r){window.$(t).click()}else window.$(t).click()}},onBlur:function(){this.searchActive=!1,this.$emit("blur")},activateSearch:function(){this.searchActive=!0},getTopMenuItems:function(){var e=this,t=C("CoreHome_Menu"),n=[];return document.querySelectorAll("nav .sidenav li > a").forEach((function(r){var i,a,o=null===(i=r.textContent)||void 0===i?void 0:i.trim();o||(o=null===(a=r.getAttribute("title"))||void 0===a?void 0:a.trim());o&&(n.push({name:o,index:e.menuIndexCounter+=1,category:t}),r.setAttribute("quick_access","".concat(e.menuIndexCounter)))})),n},getLeftMenuItems:function(){var e=this,t=[];return document.querySelectorAll("#secondNavBar .menuTab").forEach((function(n){var r,i=window.$(n).find("> .item"),a=(null===(r=i[0])||void 0===r?void 0:r.innerText.trim())||"";a&&-1!==a.lastIndexOf("\n")&&(a=a.slice(0,a.lastIndexOf("\n")).trim()),window.$(n).find("li .item").each((function(n,r){var i,o=null===(i=r.textContent)||void 0===i?void 0:i.trim();o&&(t.push({name:o,category:a,index:e.menuIndexCounter+=1}),r.setAttribute("quick_access","".concat(e.menuIndexCounter)))}))})),t},getSegmentItems:function(){var e=this;if(!this.hasSegmentSelector)return[];var t=C("CoreHome_Segments"),n=[];return document.querySelectorAll(".segmentList [data-idsegment]").forEach((function(r){var i,a,o=null===(i=r.querySelector(".segname"))||void 0===i||null===(a=i.textContent)||void 0===a?void 0:a.trim();o&&(n.push({name:o,category:t,index:e.menuIndexCounter+=1}),r.setAttribute("quick_access","".concat(e.menuIndexCounter)))})),n}}});da.render=ca;var pa=da; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */kt({component:pa,directiveName:"piwikQuickAccess",events:{itemSelected:function(e,t,n,r,i,a,o){o()},blur:function(e,t,n){setTimeout((function(){return n.$apply()}))}}});function ma(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var fa={class:"fieldArray form-group"},ha={key:0,class:"fieldUiControl"},ga=["onClick","title"];function va(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("Field");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",fa,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.modelValue,(function(t,n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:Object(a["normalizeClass"])(["fieldArrayTable multiple valign-wrapper",ma({},"fieldArrayTable".concat(n),!0)]),key:n},[e.field.uiControl?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",ha,[Object(a["createVNode"])(l,{"full-width":!0,"model-value":t,options:e.field.availableValues,"onUpdate:modelValue":function(t){return e.onEntryChange(t,n)},placeholder:" ",uicontrol:e.field.uiControl,title:e.field.title,name:"".concat(e.name,"-").concat(n),"template-file":e.field.templateFile,component:e.field.component},null,8,["model-value","options","onUpdate:modelValue","uicontrol","title","name","template-file","component"])])):Object(a["createCommentVNode"])("",!0),Object(a["withDirectives"])(Object(a["createElementVNode"])("span",{onClick:function(t){return e.removeEntry(n)},class:"icon-minus valign",title:e.translate("General_Remove")},null,8,ga),[[a["vShow"],n+1!==e.modelValue.length]])],2)})),128))])}function ba(e){return ja(e)||Oa(e)||wa(e)||ya()}function ya(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function wa(e,t){if(e){if("string"===typeof e)return ka(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?ka(e,t):void 0}}function Oa(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function ja(e){if(Array.isArray(e))return ka(e)}function ka(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}var Sa=$n("CorePluginsAdmin","Field"),Ca=Object(a["defineComponent"])({props:{modelValue:Array,name:String,field:Object},components:{Field:Sa},emits:["update:modelValue"],watch:{modelValue:function(e){this.checkEmptyModelValue(e)}},mounted:function(){this.checkEmptyModelValue(this.modelValue)},methods:{checkEmptyModelValue:function(e){e&&e.length&&""===e.slice(-1)[0]||this.$emit("update:modelValue",[].concat(ba(e||[]),[""]))},onEntryChange:function(e,t){var n=ba(this.modelValue||[]);n[t]=e,this.$emit("update:modelValue",n)},removeEntry:function(e){if(e>-1&&this.modelValue){var t=this.modelValue.filter((function(t,n){return n!==e}));this.$emit("update:modelValue",t)}}}});Ca.render=va;var Ea=Ca; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */kt({component:Ea,require:"?ngModel",scope:{name:{angularJsBind:"="},field:{angularJsBind:"="}},directiveName:"matomoFieldArray",events:{"update:modelValue":function(e,t,n,r,i,a){e!==t.modelValue&&(r.trigger("change",e),a&&a.$setViewValue(e))}},postCreate:function(e,t,n,r,i){var a=i;a&&(a.$setViewValue(e.modelValue),a.$render=function(){window.angular.isString(a.$viewValue)?e.modelValue=JSON.parse(a.$viewValue):e.modelValue=a.$viewValue})}});function Da(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Pa={class:"multiPairField form-group"},Va={key:1,class:"fieldUiControl fieldUiControl2"},Na={key:2,class:"fieldUiControl fieldUiControl3"},Ta={key:3,class:"fieldUiControl fieldUiControl4"},Aa=["onClick","title"];function Ia(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("Field");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Pa,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.modelValue,(function(t,n){var r;return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:Object(a["normalizeClass"])(["multiPairFieldTable multiple valign-wrapper",(r={},Da(r,"multiPairFieldTable".concat(n),!0),Da(r,"has".concat(e.fieldCount,"Fields"),!0),r)]),key:n},[e.field1?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{key:0,class:Object(a["normalizeClass"])(["fieldUiControl fieldUiControl1",{hasMultiFields:e.field1.type&&e.field2.type}])},[Object(a["createVNode"])(l,{"full-width":!0,modelValue:t[e.field1.key],"onUpdate:modelValue":[function(n){return t[e.field1.key]=n},function(t){return e.onEntryChange(n,e.field1.key,t)}],options:e.field1.availableValues,placeholder:" ",uicontrol:e.field1.uiControl,name:"".concat(e.name,"-p1-").concat(n),title:e.field1.title,"template-file":e.field1.templateFile,component:e.field1.component},null,8,["modelValue","onUpdate:modelValue","options","uicontrol","name","title","template-file","component"])],2)):Object(a["createCommentVNode"])("",!0),e.field2?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Va,[Object(a["createVNode"])(l,{"full-width":!0,options:e.field2.availableValues,"onUpdate:modelValue":[function(t){return e.onEntryChange(n,e.field2.key,t)},function(n){return t[e.field2.key]=n}],modelValue:t[e.field2.key],placeholder:" ",uicontrol:e.field2.uiControl,name:"".concat(e.name,"-p2-").concat(n),title:e.field2.title,"template-file":e.field2.templateFile,component:e.field2.component},null,8,["options","onUpdate:modelValue","modelValue","uicontrol","name","title","template-file","component"])])):Object(a["createCommentVNode"])("",!0),e.field3?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Na,[Object(a["createVNode"])(l,{"full-width":!0,options:e.field3.availableValues,"onUpdate:modelValue":[function(t){return e.onEntryChange(n,e.field3.key,t)},function(n){return t[e.field3.key]=n}],modelValue:t[e.field3.key],placeholder:" ",uicontrol:e.field3.uiControl,title:e.field3.title,"template-file":e.field3.templateFile,component:e.field3.component},null,8,["options","onUpdate:modelValue","modelValue","uicontrol","title","template-file","component"])])):Object(a["createCommentVNode"])("",!0),e.field4?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Ta,[Object(a["createVNode"])(l,{"full-width":!0,options:e.field4.availableValues,"onUpdate:modelValue":[function(t){return e.onEntryChange(n,e.field4.key,t)},function(n){return t[e.field4.key]=n}],modelValue:t[e.field4.key],placeholder:" ",uicontrol:e.field4.uiControl,title:e.field4.title,"template-file":e.field4.templateFile,component:e.field4.component},null,8,["options","onUpdate:modelValue","modelValue","uicontrol","title","template-file","component"])])):Object(a["createCommentVNode"])("",!0),Object(a["withDirectives"])(Object(a["createElementVNode"])("span",{onClick:function(t){return e.removeEntry(n)},class:"icon-minus valign",title:e.translate("General_Remove")},null,8,Aa),[[a["vShow"],n+1!==e.modelValue.length]])],2)})),128))])}function xa(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function Ba(e){return Fa(e)||Ra(e)||La(e)||Ma()}function Ma(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function La(e,t){if(e){if("string"===typeof e)return _a(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_a(e,t):void 0}}function Ra(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function Fa(e){if(Array.isArray(e))return _a(e)}function _a(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}var $a=$n("CorePluginsAdmin","Field"),Ha=Object(a["defineComponent"])({props:{modelValue:Array,name:String,field1:Object,field2:Object,field3:Object,field4:Object},components:{Field:$a},computed:{fieldCount:function(){return this.field1&&this.field2&&this.field3&&this.field4?4:this.field1&&this.field2&&this.field3?3:this.field1&&this.field2?2:this.field1?1:0}},emits:["update:modelValue"],watch:{modelValue:function(e){this.checkEmptyModelValue(e)}},mounted:function(){this.checkEmptyModelValue(this.modelValue)},methods:{checkEmptyModelValue:function(e){e&&e.length&&!this.isEmptyValue(e.slice(-1)[0])||this.$emit("update:modelValue",[].concat(Ba(e||[]),[this.makeEmptyValue()]))},onEntryChange:function(e,t,n){var r=Ba(this.modelValue);r[e]=Object.assign(Object.assign({},r[e]),{},xa({},t,n)),this.$emit("update:modelValue",r)},removeEntry:function(e){if(e>-1&&this.modelValue){var t=this.modelValue.filter((function(t,n){return n!==e}));this.$emit("update:modelValue",t)}},isEmptyValue:function(e){var t=this.fieldCount;if(4===t){if(!e[this.field1.key]&&!e[this.field2.key]&&!e[this.field3.key]&&!e[this.field4.key])return!1}else if(3===t){if(!e[this.field1.key]&&!e[this.field2.key]&&!e[this.field3.key])return!1}else if(2===t){if(!e[this.field1.key]&&!e[this.field2.key])return!1}else if(1===t&&!e[this.field1.key])return!1;return!0},makeEmptyValue:function(){var e={};return this.field1&&this.field1.key&&(e[this.field1.key]=""),this.field2&&this.field2.key&&(e[this.field2.key]=""),this.field3&&this.field3.key&&(e[this.field3.key]=""),this.field4&&this.field4.key&&(e[this.field4.key]=""),e}}});Ha.render=Ia;var Ua=Ha,qa=(kt({component:Ua,require:"?ngModel",scope:{name:{angularJsBind:"="},field1:{angularJsBind:"="},field2:{angularJsBind:"="},field3:{angularJsBind:"="},field4:{angularJsBind:"="}},directiveName:"matomoMultiPairField",events:{"update:modelValue":function(e,t,n,r,i,a){e!==t.modelValue&&(r.trigger("change",e),a&&a.$setViewValue(e))}},postCreate:function(e,t,n,r,i){var a=i;a&&(a.$setViewValue(e.modelValue),a.$render=function(){window.angular.isString(a.$viewValue)?e.modelValue=JSON.parse(a.$viewValue):e.modelValue=a.$viewValue})}}),{ref:"root",class:"periodSelector piwikSelector"}),Wa=["title"],Ja=Object(a["createElementVNode"])("span",{class:"icon icon-calendar"},null,-1),Ga={id:"periodMore",class:"dropdown"},za={class:"flex"},Ya={key:0,class:"period-date"},Qa={class:"period-type"},Ka={id:"otherPeriods"},Xa=["onDblclick","title"],Za=["id","checked","onChange","onDblclick"],eo={key:0,class:"compare-checkbox"},to={id:"comparePeriodToDropdown"},no={key:1,class:"compare-date-range"},ro={id:"comparePeriodStartDate"},io=Object(a["createElementVNode"])("span",{class:"compare-dates-separator"},null,-1),ao={id:"comparePeriodEndDate"},oo={class:"apply-button-container"},lo=["disabled","value"],co={key:2,id:"ajaxLoadingCalendar"},so={class:"loadingSegment"}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function uo(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("DateRangePicker"),c=Object(a["resolveComponent"])("PeriodDatePicker"),s=Object(a["resolveComponent"])("Field"),u=Object(a["resolveComponent"])("ActivityIndicator"),d=Object(a["resolveDirective"])("expand-on-click");return Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",qa,[Object(a["createElementVNode"])("a",{ref:"title",id:"date",class:"title",tabindex:"-1",title:e.translate("General_ChooseDate",e.currentlyViewingText)},[Ja,Object(a["createTextVNode"])(" "+Object(a["toDisplayString"])(e.currentlyViewingText),1)],8,Wa),Object(a["createElementVNode"])("div",Ga,[Object(a["createElementVNode"])("div",za,[Object(a["createElementVNode"])("div",null,[Object(a["withDirectives"])(Object(a["createVNode"])(l,{class:"period-range","start-date":e.startRangeDate,"end-date":e.endRangeDate,onRangeChange:t[0]||(t[0]=function(t){return e.onRangeChange(t.start,t.end)}),onSubmit:t[1]||(t[1]=function(t){return e.onApplyClicked()})},null,8,["start-date","end-date"]),[[a["vShow"],"range"===e.selectedPeriod]]),"range"!==e.selectedPeriod?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Ya,[Object(a["createVNode"])(c,{id:"datepicker",period:e.selectedPeriod,date:e.periodValue===e.selectedPeriod?e.dateValue:null,onSelect:t[2]||(t[2]=function(t){return e.setPiwikPeriodAndDate(e.selectedPeriod,t.date)})},null,8,["period","date"])])):Object(a["createCommentVNode"])("",!0)]),Object(a["createElementVNode"])("div",Qa,[Object(a["createElementVNode"])("h6",null,Object(a["toDisplayString"])(e.translate("General_Period")),1),Object(a["createElementVNode"])("div",Ka,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.periodsFiltered,(function(n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("p",{key:n},[Object(a["createElementVNode"])("label",{class:Object(a["normalizeClass"])({"selected-period-label":n===e.selectedPeriod}),onDblclick:function(t){return e.changeViewedPeriod(n)},title:n===e.periodValue?"":e.translate("General_DoubleClickToChangePeriod")},[Object(a["withDirectives"])(Object(a["createElementVNode"])("input",{type:"radio",name:"period",id:"period_id_".concat(n),"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.selectedPeriod=t}),checked:e.selectedPeriod===n,onChange:function(t){return e.selectedPeriod=n},onDblclick:function(t){return e.changeViewedPeriod(n)}},null,40,Za),[[a["vModelRadio"],e.selectedPeriod]]),Object(a["createElementVNode"])("span",null,Object(a["toDisplayString"])(e.getPeriodDisplayText(n)),1)],42,Xa)])})),128))])])]),e.isComparisonEnabled?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",eo,[Object(a["createElementVNode"])("label",null,[Object(a["withDirectives"])(Object(a["createElementVNode"])("input",{id:"comparePeriodTo",type:"checkbox","onUpdate:modelValue":t[4]||(t[4]=function(t){return e.isComparing=t})},null,512),[[a["vModelCheckbox"],e.isComparing]]),Object(a["createElementVNode"])("span",null,Object(a["toDisplayString"])(e.translate("General_CompareTo")),1)]),Object(a["createElementVNode"])("div",to,[Object(a["createVNode"])(s,{modelValue:e.comparePeriodType,"onUpdate:modelValue":t[5]||(t[5]=function(t){return e.comparePeriodType=t}),style:Object(a["normalizeStyle"])({visibility:e.isComparing?"visible":"hidden"}),name:"comparePeriodToDropdown",uicontrol:"select",options:e.comparePeriodDropdownOptions,"full-width":!0,disabled:!e.isComparing},null,8,["modelValue","style","options","disabled"])])])):Object(a["createCommentVNode"])("",!0),e.isComparing&&"custom"===e.comparePeriodType?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",no,[Object(a["createElementVNode"])("div",null,[Object(a["createElementVNode"])("div",ro,[Object(a["createElementVNode"])("div",null,[Object(a["createVNode"])(s,{modelValue:e.compareStartDate,"onUpdate:modelValue":t[6]||(t[6]=function(t){return e.compareStartDate=t}),name:"comparePeriodStartDate",uicontrol:"text","full-width":!0,title:e.translate("CoreHome_StartDate"),placeholder:"YYYY-MM-DD"},null,8,["modelValue","title"])])]),io,Object(a["createElementVNode"])("div",ao,[Object(a["createElementVNode"])("div",null,[Object(a["createVNode"])(s,{modelValue:e.compareEndDate,"onUpdate:modelValue":t[7]||(t[7]=function(t){return e.compareEndDate=t}),name:"comparePeriodEndDate",uicontrol:"text","full-width":!0,title:e.translate("CoreHome_EndDate"),placeholder:"YYYY-MM-DD"},null,8,["modelValue","title"])])])])])):Object(a["createCommentVNode"])("",!0),Object(a["createElementVNode"])("div",oo,[Object(a["createElementVNode"])("input",{type:"submit",id:"calendarApply",class:"btn",onClick:t[8]||(t[8]=function(t){return e.onApplyClicked()}),disabled:!e.isApplyEnabled(),value:e.translate("General_Apply")},null,8,lo)]),e.isLoadingNewPage?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",co,[Object(a["createVNode"])(u,{loading:!0}),Object(a["createElementVNode"])("div",so,Object(a["toDisplayString"])(e.translate("SegmentEditor_LoadingSegmentedDataMayTakeSomeTime")),1)])):Object(a["createCommentVNode"])("",!0)])],512)),[[d,{expander:"title"}]])}var po={class:"loadingPiwik"},mo=Object(a["createElementVNode"])("img",{src:"plugins/Morpheus/images/loading-blue.gif",alt:""},null,-1);function fo(e,t,n,r,i,o){return Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",po,[mo,Object(a["createElementVNode"])("span",null,Object(a["toDisplayString"])(e.loadingMessage),1)],512)),[[a["vShow"],e.loading]])}var ho=Object(a["defineComponent"])({props:{loading:{type:Boolean,required:!0,default:!1},loadingMessage:{type:String,required:!1,default:C("General_LoadingData")}}});ho.render=fo;var go=ho;function vo(e,t){return jo(e)||Oo(e,t)||yo(e,t)||bo()}function bo(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function yo(e,t){if(e){if("string"===typeof e)return wo(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?wo(e,t):void 0}}function wo(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function Oo(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a=[],o=!0,l=!1;try{for(n=n.call(e);!(o=(r=n.next()).done);o=!0)if(a.push(r.value),t&&a.length===t)break}catch(c){l=!0,i=c}finally{try{o||null==n["return"]||n["return"]()}finally{if(l)throw i}}return a}}function jo(e){if(Array.isArray(e))return e}var ko=$n("CorePluginsAdmin","Field"),So=S.helper.htmlDecode(" "),Co=[{key:"custom",value:C("General_Custom")},{key:"previousPeriod",value:C("General_PreviousPeriod").replace(/\s+/,So)},{key:"previousYear",value:C("General_PreviousYear").replace(/\s+/,So)}],Eo=new Date(S.minDateYear,S.minDateMonth-1,S.minDateDay),Do=new Date(S.maxDateYear,S.maxDateMonth-1,S.maxDateDay);function Po(e){return"[object Date]"===Object.prototype.toString.call(e)&&!Number.isNaN(e.getTime())}var Vo=Object(a["defineComponent"])({props:{periods:Array},components:{DateRangePicker:fi,PeriodDatePicker:yi,Field:ko,ActivityIndicator:go},directives:{ExpandOnClick:Qt},data:function(){var e=Ee.parsed.value.period;return{comparePeriodDropdownOptions:Co,periodValue:e,dateValue:null,selectedPeriod:e,startRangeDate:null,endRangeDate:null,isRangeValid:null,isLoadingNewPage:!1,isComparing:null,comparePeriodType:"previousPeriod",compareStartDate:"",compareEndDate:""}},mounted:function(){var e=this;S.on("hidePeriodSelector",(function(){window.$(e.$refs.root).hide()})),S.on("piwikPageChange",(function(){window.$(e.$refs.root).show()})),this.updateSelectedValuesFromHash(),Object(a["watch"])((function(){return Ee.parsed.value}),this.updateSelectedValuesFromHash),this.isComparing=jr.isComparingPeriods(),Object(a["watch"])((function(){return jr.isComparingPeriods()}),(function(t){e.isComparing=t})),window.initTopControls(),this.handleZIndexPositionRelativeCompareDropdownIssue()},computed:{currentlyViewingText:function(){var e;if("range"===this.periodValue){if(!this.startRangeDate||!this.endRangeDate)return C("General_Error");e="".concat(this.startRangeDate,",").concat(this.endRangeDate)}else{if(!this.dateValue)return C("General_Error");e=D(this.dateValue)}try{return p.parse(this.periodValue,e).getPrettyString()}catch(t){return C("General_Error")}},isComparisonEnabled:function(){return jr.isComparisonEnabled()},periodsFiltered:function(){return(this.periods||[]).filter((function(e){return p.isRecognizedPeriod(e)}))},selectedComparisonParams:function(){if(!this.isComparing)return{};if("custom"===this.comparePeriodType)return{comparePeriods:["range"],compareDates:["".concat(this.compareStartDate,",").concat(this.compareEndDate)]};if("previousPeriod"===this.comparePeriodType)return{comparePeriods:[this.selectedPeriod],compareDates:[this.previousPeriodDateToSelectedPeriod]};if("previousYear"===this.comparePeriodType){var e="range"===this.selectedPeriod?"".concat(this.startRangeDate,",").concat(this.endRangeDate):D(this.dateValue),t=p.parse(this.selectedPeriod,e).getDateRange();return t[0].setFullYear(t[0].getFullYear()-1),t[1].setFullYear(t[1].getFullYear()-1),"range"===this.selectedPeriod?{comparePeriods:["range"],compareDates:["".concat(D(t[0]),",").concat(D(t[1]))]}:{comparePeriods:[this.selectedPeriod],compareDates:[D(t[0])]}}return console.warn("Unknown compare period type: ".concat(this.comparePeriodType)),{}},previousPeriodDateToSelectedPeriod:function(){if("range"===this.selectedPeriod){var e=V(this.startRangeDate),t=V(this.endRangeDate),n=H.getLastNRange("day",2,e).startDate,r=Math.floor((t.valueOf()-e.valueOf())/864e5),i=H.getLastNRange("day",1+r,n);return"".concat(D(i.startDate),",").concat(D(i.endDate))}var a=H.getLastNRange(this.selectedPeriod,2,this.dateValue).startDate;return D(a)},selectedDateString:function(){if("range"===this.selectedPeriod){var e=this.startRangeDate,t=this.endRangeDate,n=V(e),r=V(t);return!Po(n)||!Po(r)||n>r?(window.$("#alert").find("h2").text(C("General_InvalidDateRange")),S.helper.modalConfirm("#alert",{}),null):"".concat(e,",").concat(t)}return D(this.dateValue)}},methods:{handleZIndexPositionRelativeCompareDropdownIssue:function(){var e=window.$(this.$refs.root);e.on("focus","#comparePeriodToDropdown .select-dropdown",(function(){e.addClass("compare-dropdown-open")})).on("blur","#comparePeriodToDropdown .select-dropdown",(function(){e.removeClass("compare-dropdown-open")}))},changeViewedPeriod:function(e){e!==this.periodValue&&"range"!==e&&this.setPiwikPeriodAndDate(e,this.dateValue)},setPiwikPeriodAndDate:function(e,t){this.periodValue=e,this.selectedPeriod=e,this.dateValue=t;var n=D(t);this.setRangeStartEndFromPeriod(e,n),this.propagateNewUrlParams(n,this.selectedPeriod),window.initTopControls()},propagateNewUrlParams:function(e,t){var n,r=this.selectedComparisonParams;S.helper.isAngularRenderingThePage()?(this.closePeriodSelector(),n=Ee.hashParsed.value):(this.isLoadingNewPage=!0,n=Ee.parsed.value);var i=Object.assign({},n);delete i.comparePeriods,delete i.compareDates,Ee.updateLocation(Object.assign(Object.assign({},i),{},{date:e,period:t},r))},onApplyClicked:function(){if("range"===this.selectedPeriod){var e=this.selectedDateString;if(!e)return;return this.periodValue="range",void this.propagateNewUrlParams(e,"range")}this.setPiwikPeriodAndDate(this.selectedPeriod,this.dateValue)},updateSelectedValuesFromHash:function(){var e=Ee.parsed.value.date,t=Ee.parsed.value.period;this.periodValue=t,this.selectedPeriod=t,this.dateValue=null,this.startRangeDate=null,this.endRangeDate=null;try{p.parse(t,e)}catch(l){return}if("range"===t){var n=p.get(t).parse(e),r=n.getDateRange(),i=vo(r,2),a=i[0],o=i[1];this.dateValue=a,this.startRangeDate=D(a),this.endRangeDate=D(o)}else this.dateValue=V(e),this.setRangeStartEndFromPeriod(t,e)},setRangeStartEndFromPeriod:function(e,t){var n=p.parse(e,t).getDateRange();this.startRangeDate=D(n[0]<Eo?Eo:n[0]),this.endRangeDate=D(n[1]>Do?Do:n[1])},getPeriodDisplayText:function(e){return p.get(e).getDisplayText()},onRangeChange:function(e,t){e&&t?(this.isRangeValid=!0,this.startRangeDate=e,this.endRangeDate=t):this.isRangeValid=!1},isApplyEnabled:function(){return!("range"===this.selectedPeriod&&!this.isRangeValid)&&!(this.isComparing&&"custom"===this.comparePeriodType&&!this.isCompareRangeValid())},closePeriodSelector:function(){this.$refs.root.classList.remove("expanded")},isCompareRangeValid:function(){try{V(this.compareStartDate)}catch(e){return!1}try{V(this.compareEndDate)}catch(e){return!1}return!0}}});Vo.render=uo;var No=Vo,To=(kt({component:No,scope:{periods:{angularJsBind:"<"}},directiveName:"piwikPeriodSelector"}),{class:"reportingMenu"}),Ao=["aria-label"],Io=["onClick"],xo={class:"hidden"},Bo={role:"menu"},Mo=["href","onClick","title"],Lo=["href","onClick"],Ro=["onClick"],Fo=Object(a["createElementVNode"])("span",{class:"icon-help"},null,-1),_o=[Fo],$o={id:"mobile-left-menu",class:"sidenav hide-on-large-only"},Ho={class:"collapsible collapsible-accordion"},Uo={class:"collapsible-header"},qo={class:"collapsible-body"},Wo={key:0},Jo=["onClick","href"],Go={key:1},zo=["onClick","href"]; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function Yo(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("MenuItemsDropdown"),c=Object(a["resolveDirective"])("side-nav");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",To,[Object(a["createElementVNode"])("ul",{class:"navbar hide-on-med-and-down",role:"menu","aria-label":e.translate("CoreHome_MainNavigation")},[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.menu,(function(t){return Object(a["openBlock"])(),Object(a["createElementBlock"])("li",{class:Object(a["normalizeClass"])(["menuTab",{active:t.id===e.activeCategory}]),role:"menuitem",key:t.id},[Object(a["createElementVNode"])("a",{class:"item",tabindex:"5",href:"",onClick:Object(a["withModifiers"])((function(n){return e.loadCategory(t)}),["prevent"])},[Object(a["createElementVNode"])("span",{class:Object(a["normalizeClass"])("menu-icon ".concat(t.icon?t.icon:"icon-arrow-right"))},null,2),Object(a["createTextVNode"])(Object(a["toDisplayString"])(t.name)+" ",1),Object(a["createElementVNode"])("span",xo,Object(a["toDisplayString"])(e.translate("CoreHome_Menu")),1)],8,Io),Object(a["createElementVNode"])("ul",Bo,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(t.subcategories,(function(n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("li",{role:"menuitem",class:Object(a["normalizeClass"])({active:(n.id===e.displayedSubcategory||n.isGroup&&e.activeSubsubcategory===e.displayedSubcategory)&&t.id===e.displayedCategory}),key:n.id},[n.isGroup?(Object(a["openBlock"])(),Object(a["createBlock"])(l,{key:0,"show-search":!0,"menu-title":e.htmlEntities(n.name)},{default:Object(a["withCtx"])((function(){return[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(n.subcategories,(function(r){return Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{class:Object(a["normalizeClass"])(["item",{active:r.id===e.activeSubsubcategory&&n.id===e.displayedSubcategory&&t.id===e.displayedCategory}]),tabindex:"5",href:"#?".concat(e.makeUrl(t,r)),onClick:function(n){return e.loadSubcategory(t,r,n)},title:r.tooltip,key:r.id},Object(a["toDisplayString"])(r.name),11,Mo)})),128))]})),_:2},1032,["menu-title"])):Object(a["createCommentVNode"])("",!0),n.isGroup?Object(a["createCommentVNode"])("",!0):(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:1,href:"#?".concat(e.makeUrl(t,n)),class:"item",onClick:function(r){return e.loadSubcategory(t,n,r)}},Object(a["toDisplayString"])(n.name),9,Lo)),n.help?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{key:2,class:Object(a["normalizeClass"])(["item-help-icon",{active:e.helpShownCategory&&e.helpShownCategory.subcategory===n.id&&e.helpShownCategory.category===t.id&&n.help}]),tabindex:"5",href:"javascript:",onClick:function(r){return e.showHelp(t,n,r)}},_o,10,Ro)):Object(a["createCommentVNode"])("",!0)],2)})),128))])],2)})),128))],8,Ao),Object(a["createElementVNode"])("ul",$o,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.menu,(function(t){return Object(a["openBlock"])(),Object(a["createElementBlock"])("li",{class:"no-padding",key:t.id},[Object(a["withDirectives"])(Object(a["createElementVNode"])("ul",Ho,[Object(a["createElementVNode"])("li",null,[Object(a["createElementVNode"])("a",Uo,[Object(a["createElementVNode"])("i",{class:Object(a["normalizeClass"])(t.icon?t.icon:"icon-arrow-bottom")},null,2),Object(a["createTextVNode"])(Object(a["toDisplayString"])(t.name),1)]),Object(a["createElementVNode"])("div",qo,[Object(a["createElementVNode"])("ul",null,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(t.subcategories,(function(n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("li",{key:n.id},[n.isGroup?(Object(a["openBlock"])(),Object(a["createElementBlock"])("span",Wo,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(n.subcategories,(function(n){return Object(a["openBlock"])(),Object(a["createElementBlock"])("a",{onClick:function(r){return e.loadSubcategory(t,n)},href:"#?".concat(e.makeUrl(t,n)),key:n.id},Object(a["toDisplayString"])(n.name),9,Jo)})),128))])):Object(a["createCommentVNode"])("",!0),n.isGroup?Object(a["createCommentVNode"])("",!0):(Object(a["openBlock"])(),Object(a["createElementBlock"])("span",Go,[Object(a["createElementVNode"])("a",{onClick:function(r){return e.loadSubcategory(t,n)},href:"#?".concat(e.makeUrl(t,n))},Object(a["toDisplayString"])(n.name),9,zo)]))])})),128))])])])],512),[[c,{activator:e.sideNavActivator}]])])})),128))])])}var Qo={key:0},Ko=["data-notification-instance-id"],Xo={key:1},Zo={class:"notification-body"},el=["innerHTML"],tl={key:1};function nl(e,t,n,r,i,o){return Object(a["openBlock"])(),Object(a["createBlock"])(a["Transition"],{name:"toast"===e.type?"slow-fade-out":void 0,onAfterLeave:t[1]||(t[1]=function(t){return e.toastClosed()})},{default:Object(a["withCtx"])((function(){return[e.deleted?Object(a["createCommentVNode"])("",!0):(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Qo,[Object(a["createVNode"])(a["Transition"],{name:"toast"===e.type?"toast-slide-up":void 0,appear:""},{default:Object(a["withCtx"])((function(){return[Object(a["createElementVNode"])("div",null,[Object(a["createVNode"])(a["Transition"],{name:e.animate?"fade-in":void 0,appear:""},{default:Object(a["withCtx"])((function(){return[Object(a["createElementVNode"])("div",{class:Object(a["normalizeClass"])(["notification system",e.cssClasses]),style:Object(a["normalizeStyle"])(e.style),ref:"root","data-notification-instance-id":e.notificationInstanceId},[e.canClose?(Object(a["openBlock"])(),Object(a["createElementBlock"])("button",{key:0,type:"button",class:"close","data-dismiss":"alert",onClick:t[0]||(t[0]=function(t){return e.closeNotification(t)})}," × ")):Object(a["createCommentVNode"])("",!0),e.title?(Object(a["openBlock"])(),Object(a["createElementBlock"])("strong",Xo,Object(a["toDisplayString"])(e.title),1)):Object(a["createCommentVNode"])("",!0),Object(a["createElementVNode"])("div",Zo,[e.message?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{key:0,innerHTML:e.$sanitize(e.message)},null,8,el)):Object(a["createCommentVNode"])("",!0),e.message?Object(a["createCommentVNode"])("",!0):(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",tl,[Object(a["renderSlot"])(e.$slots,"default")]))])],14,Ko)]})),_:3},8,["name"])])]})),_:3},8,["name"])]))]})),_:3},8,["name"])}var rl=window,il=rl.$,al=Object(a["defineComponent"])({props:{notificationId:String,notificationInstanceId:String,title:String,context:String,type:String,noclear:Boolean,toastLength:{type:Number,default:12e3},style:[String,Object],animate:Boolean,message:String,cssClass:String},computed:{cssClasses:function(){var e={};return this.context&&(e["notification-".concat(this.context)]=!0),this.cssClass&&(e[this.cssClass]=!0),e},canClose:function(){return"persistent"===this.type||!this.noclear}},emits:["closed"],data:function(){return{deleted:!1}},mounted:function(){var e=this,t=function(){setTimeout((function(){e.deleted=!0}),e.toastLength)};"toast"===this.type&&t(),this.style&&il(this.$refs.root).css(this.style)},methods:{toastClosed:function(){var e=this;Object(a["nextTick"])((function(){e.$emit("closed")}))},closeNotification:function(e){var t=this;this.canClose&&e&&e.target&&(this.deleted=!0,Object(a["nextTick"])((function(){t.$emit("closed")}))),this.markNotificationAsRead()},markNotificationAsRead:function(){this.notificationId&&Ze.post({module:"CoreHome",action:"markNotificationAsRead"},{notificationId:this.notificationId},{withTokenInUrl:!0})}}});al.render=nl;var ol=al; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */kt({component:ol,scope:{notificationId:{angularJsBind:"@?"},title:{angularJsBind:"@?notificationTitle"},context:{angularJsBind:"@?"},type:{angularJsBind:"@?"},noclear:{angularJsBind:"@?",transform:St},toastLength:{angularJsBind:"@?"}},directiveName:"piwikNotification",transclude:!0});function ll(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function cl(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function sl(e,t,n){return t&&cl(e.prototype,t),n&&cl(e,n),e}function ul(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var dl=window,pl=dl.$,ml=function(){function e(){ll(this,e),ul(this,"privateState",Object(a["reactive"])({notifications:[]})),ul(this,"nextNotificationId",0)}return sl(e,[{key:"state",get:function(){return Object(a["readonly"])(this.privateState)}},{key:"appendNotification",value:function(e){this.checkMessage(e.message),e.id&&this.remove(e.id),this.privateState.notifications.push(e)}},{key:"prependNotification",value:function(e){this.checkMessage(e.message),e.id&&this.remove(e.id),this.privateState.notifications.unshift(e)}},{key:"remove",value:function(e){this.privateState.notifications=this.privateState.notifications.filter((function(t){return t.id!==e}))}},{key:"parseNotificationDivs",value:function(){var e=this,t=pl('[data-role="notification"]'),n=[];t.each((function(e,r){var i=pl(r),a=i.data(),o=i.html();o&&n.push(Object.assign(Object.assign({},a),{},{message:o,animate:!1})),t.remove()})),n.forEach((function(t){return e.show(t)}))}},{key:"clearTransientNotifications",value:function(){this.privateState.notifications=this.privateState.notifications.filter((function(e){return"transient"!==e.type}))}},{key:"show",value:function(e){this.checkMessage(e.message);var t=e.prepend?this.prependNotification:this.appendNotification,n="#notificationContainer";if(e.placeat)n=e.placeat;else{var r=".modal.open .modal-content",i=document.querySelector(r);i&&(i.querySelector("#modalNotificationContainer")||pl(i).prepend('<div id="modalNotificationContainer"/>'),n="".concat(r," #modalNotificationContainer"),t=this.prependNotification)}var a=e.group||(n?n.toString():"");this.initializeNotificationContainer(n,a);var o=(this.nextNotificationId+=1).toString();return t.call(this,Object.assign(Object.assign({},e),{},{noclear:!!e.noclear,group:a,notificationId:e.id,notificationInstanceId:o,type:e.type||"transient"})),o}},{key:"scrollToNotification",value:function(e){setTimeout((function(){var t=document.querySelector("[data-notification-instance-id='".concat(e,"']"));t&&S.helper.lazyScrollTo(t,250)}))}},{key:"toast",value:function(e){this.checkMessage(e.message);var t=e.placeat?pl(e.placeat):void 0;if(!t||!t.length)throw new Error("A valid selector is required for the placeat option when using Notification.toast().");var n=document.createElement("div");n.style.position="absolute",n.style.top="".concat(t.offset().top,"px"),n.style.left="".concat(t.offset().left,"px"),n.style.zIndex="1000",document.body.appendChild(n);var r=dt({render:function(){return Object(a["createVNode"])(ol,Object.assign(Object.assign({},e),{},{notificationId:e.id,type:"toast",onClosed:function(){r.unmount()}}))}});r.mount(n)}},{key:"initializeNotificationContainer",value:function(e,t){if(e){var n=pl(e);if(!n.children(".notification-group").length){var r=window.CoreHome.NotificationGroup,i=dt({template:'<NotificationGroup :group="group"></NotificationGroup>',data:function(){return{group:t}}});i.component("NotificationGroup",r),i.mount(n[0])}}}},{key:"checkMessage",value:function(e){if(!e)throw new Error("No message given, cannot display notification")}}]),e}(),fl=new ml,hl=fl;pl((function(){return fl.parseNotificationDivs()})), /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -function it(){return{restrict:"A",link:function(e,t){var n={instance:null,value:{expander:t.find(".title").first()[0]},oldValue:null,modifiers:{},dir:{}};ot.mounted(t[0],n),t.on("$destroy",(function(){return ot.unmounted(t[0],n)}))}}}it.$inject=[],angular.module("piwikApp").directive("piwikExpandOnHover",it);var ct={ref:"root"};function st(e,t,n,r,a,i){return Object(o["withDirectives"])((Object(o["openBlock"])(),Object(o["createElementBlock"])("div",ct,[Object(o["renderSlot"])(e.$slots,"default")],512)),[[o["vShow"],e.modelValue]])}var lt=Object(o["defineComponent"])({props:{modelValue:{type:Boolean,required:!0},element:{type:HTMLElement,required:!1}},emits:["yes","no","closeEnd","close","update:modelValue"],activated:function(){this.$emit("update:modelValue",!1)},watch:{modelValue:function(e,t){var n=this;if(e){var r=this.element||this.$refs.root.firstElementChild;D.helper.modalConfirm(r,{yes:function(){n.$emit("yes")},no:function(){n.$emit("no")},validation:function(){n.$emit("validation")}},{onCloseEnd:function(){n.element||n.$refs.root.appendChild(r),n.$emit("update:modelValue",!1),n.$emit("closeEnd")}})}else!1===e&&!0===t&&this.$emit("close")}}});lt.render=st;var ut=lt;function dt(e,t){return vt(e)||ht(e,t)||ft(e,t)||pt()}function pt(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ft(e,t){if(e){if("string"===typeof e)return mt(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?mt(e,t):void 0}}function mt(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function ht(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,a,o=[],i=!0,c=!1;try{for(n=n.call(e);!(i=(r=n.next()).done);i=!0)if(o.push(r.value),t&&o.length===t)break}catch(s){c=!0,a=s}finally{try{i||null==n["return"]||n["return"]()}finally{if(c)throw a}}return o}}function vt(e){if(Array.isArray(e))return e} +window.angular.module("piwikApp").factory("notifications",(function(){return hl}));var gl={class:"notification-group"},vl=["innerHTML"];function bl(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("Notification");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",gl,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.notifications,(function(t,n){return Object(a["openBlock"])(),Object(a["createBlock"])(l,{key:t.id||"no-id-".concat(n),"notification-id":t.id,title:t.title,context:t.context,type:t.type,noclear:t.noclear,"toast-length":t.toastLength,style:Object(a["normalizeStyle"])(t.style),animate:t.animate,message:t.message,"notification-instance-id":t.notificationInstanceId,"css-class":t.class,onClosed:function(n){return e.removeNotification(t.id)}},{default:Object(a["withCtx"])((function(){return[Object(a["createElementVNode"])("div",{innerHTML:e.$sanitize(t.message)},null,8,vl)]})),_:2},1032,["notification-id","title","context","type","noclear","toast-length","style","animate","message","notification-instance-id","css-class","onClosed"])})),128))])}var yl=Object(a["defineComponent"])({props:{group:String},components:{Notification:ol},computed:{notifications:function(){var e=this;return hl.state.notifications.filter((function(t){return e.group?e.group===t.group:!t.group}))}},methods:{removeNotification:function(e){hl.remove(e)}}});yl.render=bl;var wl=yl; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var gt=0;function bt(e){return e.substring(0,1).toLowerCase()+e.substring(1).replace(/[A-Z]/g,(function(e){return"-".concat(e.toLowerCase())}))}function yt(e){return e.substring(0,1).toLowerCase()+e.substring(1).replace(/-([a-z])/g,(function(e,t){return t.toUpperCase()}))}function wt(e){var t=e.component,n=e.scope,r=void 0===n?{}:n,a=e.events,i=void 0===a?{}:a,c=e.$inject,s=e.directiveName,l=e.transclude,u=e.mountPointFactory,d=e.postCreate,p=e.noScope,f=e.restrict,m=void 0===f?"A":f,h=gt;l&&(gt+=1);var v={};function g(){for(var e=arguments.length,n=new Array(e),a=0;a<e;a++)n[a]=arguments[a];var c={restrict:m,scope:p?void 0:v,compile:function(){return{post:function(e,a,c){var s=l?a.find("[ng-transclude][counter=".concat(h,"]")):null,p="<root-component";Object.entries(i).forEach((function(e){var t=dt(e,1),n=t[0];p+=" @".concat(n,"=\"onEventHandler('").concat(n,"', $event)\"")})),Object.entries(r).forEach((function(e){var t=dt(e,2),n=t[0],r=t[1];if("&"===r.angularJsBind){var a=bt(n);i[a]||(p+=" @".concat(a,"=\"onEventHandler('").concat(a,"', $event)\""))}else p+=" :".concat(r.vue,'="').concat(r.vue,'"')})),p+=">",l&&(p+='<div ref="transcludeTarget"/>'),p+="</root-component>";var f=Object(o["createApp"])({template:p,data:function(){var t={};return Object.entries(r).forEach((function(r){var o=dt(r,2),i=o[0],s=o[1],l=e[i];"undefined"===typeof l&&"undefined"!==typeof s.default&&(l=s.default instanceof Function?s.default.apply(s,[e,a,c].concat(n)):s.default),s.transform&&(l=s.transform(l)),t[s.vue]=l})),t},setup:function(){if(l){var e=Object(o["ref"])(null);return{transcludeTarget:e}}},methods:{onEventHandler:function(t,r){var o=yt(t);e[o]&&e[o](r),i[t]&&i[t].apply(i,[r,e,a,c].concat(n))}}});f.config.globalProperties.$sanitize=window.vueSanitize,f.config.globalProperties.translate=C,f.component("root-component",t);var m=u?u.apply(void 0,[e,a,c].concat(n)):a[0],v=f.mount(m);Object.entries(r).forEach((function(t){var r=dt(t,2),o=r[0],i=r[1];i.angularJsBind&&"&"!==i.angularJsBind&&e.$watch(o,(function(t){var r=t;"undefined"!==typeof i.default&&"undefined"===typeof t&&(r=i.default instanceof Function?i.default.apply(i,[e,a,c].concat(n)):i.default),i.transform&&(r=i.transform(r)),v[o]=r}))})),l&&$(v.transcludeTarget).append(s),d&&d.apply(void 0,[v,e,a,c].concat(n)),a.on("$destroy",(function(){f.unmount()}))}}}};return l&&(c.transclude=!0,c.template='<div ng-transclude counter="'.concat(h,'"/>')),c}return Object.entries(r).forEach((function(e){var t=dt(e,2),n=t[0],r=t[1];r.vue||(r.vue=n),r.angularJsBind&&(v[n]=r.angularJsBind)})),g.$inject=c||[],angular.module("piwikApp").directive(s,g),g} + */function Ol(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function jl(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function kl(e,t,n){return t&&jl(e.prototype,t),n&&jl(e,n),e}function Sl(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */wt({component:ut,scope:{show:{vue:"modelValue",default:!1},element:{default:function(e,t){return t[0]}}},events:{yes:function(e,t,n,r){r.yes&&(t.$eval(r.yes),setTimeout((function(){t.$apply()}),0))},no:function(e,t,n,r){r.no&&(t.$eval(r.no),setTimeout((function(){t.$apply()}),0))},validation:function(e,t,n,r){r.no&&(t.$eval(r.no),setTimeout((function(){t.$apply()}),0))},close:function(e,t,n,r){r.close&&(t.$eval(r.close),setTimeout((function(){t.$apply()}),0))},"update:modelValue":function(e,t,n,r,a){setTimeout((function(){t.$apply(a(r.piwikDialog).assign(t,e))}),0)}},$inject:["$parse"],directiveName:"piwikDialog",transclude:!0,mountPointFactory:function(e,t){var n=$('<div class="vue-placeholder"/>');return n.appendTo(t),n[0]},postCreate:function(e,t,n,r){t.$watch(r.piwikDialog,(function(t,n){n!==t&&(e.modelValue=t||!1)}))},noScope:!0});var kt={key:0,class:"title",tabindex:"6"},Ot=["href","title"],jt={class:"iconsBar"},Dt=["href","title"],Ct=Object(o["createElementVNode"])("span",{class:"icon-help"},null,-1),St=[Ct],Pt=["title"],Et=Object(o["createElementVNode"])("span",{class:"icon-info"},null,-1),Tt=[Et],xt={class:"ratingIcons"},It={class:"inlineHelp"},Nt=["innerHTML"],$t=["href"];function Bt(e,t,n,r,a,i){var c=Object(o["resolveComponent"])("RateFeature");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",{class:"enrichedHeadline",onMouseenter:t[1]||(t[1]=function(t){return e.showIcons=!0}),onMouseleave:t[2]||(t[2]=function(t){return e.showIcons=!1}),ref:"root"},[e.editUrl?Object(o["createCommentVNode"])("",!0):(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",kt,[Object(o["renderSlot"])(e.$slots,"default")])),e.editUrl?(Object(o["openBlock"])(),Object(o["createElementBlock"])("a",{key:1,class:"title",href:e.editUrl,title:e.translate("CoreHome_ClickToEditX",e.$sanitize(e.actualFeatureName))},[Object(o["renderSlot"])(e.$slots,"default")],8,Ot)):Object(o["createCommentVNode"])("",!0),Object(o["withDirectives"])(Object(o["createElementVNode"])("span",jt,[e.helpUrl&&!e.actualInlineHelp?(Object(o["openBlock"])(),Object(o["createElementBlock"])("a",{key:0,rel:"noreferrer noopener",target:"_blank",class:"helpIcon",href:e.helpUrl,title:e.translate("CoreHome_ExternalHelp")},St,8,Dt)):Object(o["createCommentVNode"])("",!0),e.actualInlineHelp?(Object(o["openBlock"])(),Object(o["createElementBlock"])("a",{key:1,onClick:t[0]||(t[0]=function(t){return e.showInlineHelp=!e.showInlineHelp}),class:Object(o["normalizeClass"])(["helpIcon",{active:e.showInlineHelp}]),title:e.translate(e.reportGenerated?"General_HelpReport":"General_Help")},Tt,10,Pt)):Object(o["createCommentVNode"])("",!0),Object(o["createElementVNode"])("div",xt,[Object(o["createVNode"])(c,{title:e.actualFeatureName},null,8,["title"])])],512),[[o["vShow"],e.showIcons||e.showInlineHelp]]),Object(o["withDirectives"])(Object(o["createElementVNode"])("div",It,[Object(o["createElementVNode"])("div",{innerHTML:e.$sanitize(e.actualInlineHelp)},null,8,Nt),e.helpUrl?(Object(o["openBlock"])(),Object(o["createElementBlock"])("a",{key:0,rel:"noreferrer noopener",target:"_blank",class:"readMore",href:e.helpUrl},Object(o["toDisplayString"])(e.translate("General_MoreDetails")),9,$t)):Object(o["createCommentVNode"])("",!0)],512),[[o["vShow"],e.showInlineHelp]])],544)}var Ht=Object(o["defineAsyncComponent"])((function(){return new Promise((function(e){window.$(document).ready((function(){e(window.Feedback.RateFeature)}))}))})),At=Object(o["defineComponent"])({props:{helpUrl:{type:String,default:""},editUrl:{type:String,default:""},reportGenerated:String,featureName:String,inlineHelp:String},components:{RateFeature:Ht},data:function(){return{showIcons:!1,showInlineHelp:!1,actualFeatureName:this.featureName,actualInlineHelp:this.inlineHelp}},watch:{inlineHelp:function(e){this.actualInlineHelp=e},featureName:function(e){this.actualFeatureName=e}},mounted:function(){var e=this,t=this.$refs.root;setTimeout((function(){if(!e.actualInlineHelp){var n=t.querySelector(".title .inlineHelp");if(!n&&t.parentElement.nextElementSibling&&(n=t.parentElement.nextElementSibling.querySelector(".reportDocumentation")),n){var r=n.getAttribute("data-content").trim();r.length&&(e.actualInlineHelp="<p>".concat(r,"</p>"),setTimeout((function(){return n.remove()}),0))}}e.actualFeatureName||(e.actualFeatureName=t.querySelector(".title").textContent),e.reportGenerated&&p.parse(D.period,D.currentDateString).containsToday()&&window.$(t.querySelector(".report-generated")).tooltip({track:!0,content:e.reportGenerated,items:"div",show:!1,hide:!1})}))}});At.render=Bt;var Mt=At,Ft=(wt({component:Mt,scope:{helpUrl:{angularJsBind:"@"},editUrl:{angularJsBind:"@"},reportGenerated:{angularJsBind:"@?"},featureName:{angularJsBind:"@"},inlineHelp:{angularJsBind:"@?"}},directiveName:"piwikEnrichedHeadline",transclude:!0}),{class:"card",ref:"root"}),Vt={class:"card-content"},Lt={key:0,class:"card-title"},Rt={key:1,class:"card-title"},Ut={ref:"content"}; + */var Cl=function(){function e(){var t=this;Ol(this,e),Sl(this,"privateState",Object(a["reactive"])({pages:[]})),Sl(this,"state",Object(a["computed"])((function(){return Object(a["readonly"])(t.privateState)}))),Sl(this,"fetchAllPagesPromise",void 0),Sl(this,"pages",Object(a["computed"])((function(){return t.state.value.pages})))}return kl(e,[{key:"findPageInCategory",value:function(e){return this.pages.value.find((function(t){return t&&t.category&&t.category.id===e&&t.subcategory&&t.subcategory.id}))}},{key:"findPage",value:function(e,t){return this.pages.value.find((function(n){return n&&n.category&&n.subcategory&&n.category.id===e&&"".concat(n.subcategory.id)===t}))}},{key:"reloadAllPages",value:function(){return delete this.fetchAllPagesPromise,this.getAllPages()}},{key:"getAllPages",value:function(){var e=this;return this.fetchAllPagesPromise||(this.fetchAllPagesPromise=Ze.fetch({method:"API.getReportPagesMetadata",filter_limit:"-1"}).then((function(t){return e.privateState.pages=t,e.pages.value}))),this.fetchAllPagesPromise.then((function(){return e.pages.value}))}}]),e}(),El=new Cl;function Dl(e){return Tl(e)||Nl(e)||Vl(e)||Pl()}function Pl(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function Vl(e,t){if(e){if("string"===typeof e)return Al(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Al(e,t):void 0}}function Nl(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function Tl(e){if(Array.isArray(e))return Al(e)}function Al(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function _t(e,t,n,r,a,i){var c=Object(o["resolveComponent"])("EnrichedHeadline");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",Ft,[Object(o["createElementVNode"])("div",Vt,[!e.contentTitle||e.actualFeature||e.helpUrl||e.actualHelpText?Object(o["createCommentVNode"])("",!0):(Object(o["openBlock"])(),Object(o["createElementBlock"])("h2",Lt,Object(o["toDisplayString"])(e.contentTitle),1)),e.contentTitle&&(e.actualFeature||e.helpUrl||e.actualHelpText)?(Object(o["openBlock"])(),Object(o["createElementBlock"])("h2",Rt,[Object(o["createVNode"])(c,{"feature-name":e.actualFeature,"help-url":e.helpUrl,"inline-help":e.actualHelpText},{default:Object(o["withCtx"])((function(){return[Object(o["createTextVNode"])(Object(o["toDisplayString"])(e.contentTitle),1)]})),_:1},8,["feature-name","help-url","inline-help"])])):Object(o["createCommentVNode"])("",!0),Object(o["createElementVNode"])("div",Ut,[Object(o["renderSlot"])(e.$slots,"default")],512)])],512)}var Jt=null,Gt=Object(o["defineComponent"])({props:{contentTitle:String,feature:String,helpUrl:String,helpText:String,anchor:String},components:{EnrichedHeadline:Mt},data:function(){return{actualFeature:this.feature,actualHelpText:this.helpText}},watch:{feature:function(e){this.actualFeature=e},helpText:function(e){this.actualHelpText=e}},mounted:function(){var e,t=this,n=this.$refs,r=n.root,a=n.content;if(this.anchor){var o=document.createElement("a");o.id=this.anchor,r.parentElement.prepend(o)}if(setTimeout((function(){var e=a.querySelector(".contentHelp");e&&(t.actualHelpText=e.innerHTML,e.remove())}),0),!this.actualFeature||!0!==this.actualFeature&&"true"!==this.actualFeature||(this.actualFeature=this.contentTitle),null===Jt&&(Jt=document.querySelector("#content.admin")),Jt&&(e=Jt.offsetTop),e||0===e){var i=r.closest("[piwik-widget-loader]"),c=i?i.offsetTop:r.offsetTop;c-e<17&&(r.style.marginTop=0)}}});Gt.render=_t;var qt=Gt; + */function Il(e){var t=Dl(e||[]);return t.sort((function(e,t){return e.order<t.order?-1:e.order>t.order?1:0})),t} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */wt({component:qt,scope:{contentTitle:{angularJsBind:"@"},feature:{angularJsBind:"@"},helpUrl:{angularJsBind:"@"},helpText:{angularJsBind:"@"},anchor:{angularJsBind:"@?"}},directiveName:"piwikContentBlock",transclude:!0});function zt(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Qt(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function Yt(e,t,n){return t&&Qt(e.prototype,t),n&&Qt(e,n),e}function Wt(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} + */function xl(e){var t=e;return t.subcategories?t.subcategories:[]} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var Kt=function(){function e(){var t=this;zt(this,e),Wt(this,"segmentState",Object(o["reactive"])({availableSegments:[]})),D.on("piwikSegmentationInited",(function(){return t.setSegmentState()}))}return Yt(e,[{key:"state",get:function(){return Object(o["readonly"])(this.segmentState)}},{key:"setSegmentState",value:function(){try{var e=$(".segmentEditorPanel").data("uiControlObject");this.segmentState.availableSegments=e.impl.availableSegments||[]}catch(t){}}}]),e}(),Xt=new Kt;function Zt(e){return rn(e)||nn(e)||tn(e)||en()}function en(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function tn(e,t){if(e){if("string"===typeof e)return an(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?an(e,t):void 0}}function nn(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function rn(e){if(Array.isArray(e))return an(e)}function an(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function on(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function cn(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?on(Object(n),!0).forEach((function(t){dn(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):on(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function sn(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function ln(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function un(e,t,n){return t&&ln(e.prototype,t),n&&ln(e,n),e}function dn(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} + */function Bl(e){var t=e;return t.subcategories?t.subcategories:[]}function Ml(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Ll(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function Rl(e,t,n){return t&&Ll(e.prototype,t),n&&Ll(e,n),e}function Fl(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var pn=8,fn=3;function mn(e){return e?e instanceof Array?e:[e]:[]}var hn=function(){function e(){var t=this;sn(this,e),dn(this,"privateState",Object(o["reactive"])({comparisonsDisabledFor:[]})),dn(this,"state",Object(o["readonly"])(this.privateState)),dn(this,"colors",{}),dn(this,"segmentComparisons",Object(o["computed"])((function(){return t.parseSegmentComparisons()}))),dn(this,"periodComparisons",Object(o["computed"])((function(){return t.parsePeriodComparisons()}))),dn(this,"isEnabled",Object(o["computed"])((function(){return t.checkEnabledForCurrentPage()}))),this.loadComparisonsDisabledFor(),$((function(){t.colors=t.getAllSeriesColors()})),Object(o["watch"])((function(){return t.getComparisons()}),(function(){return D.postEvent("piwikComparisonsChanged")}),{deep:!0})}return un(e,[{key:"getComparisons",value:function(){return this.getSegmentComparisons().concat(this.getPeriodComparisons())}},{key:"isComparing",value:function(){return this.isComparisonEnabled()&&(this.segmentComparisons.value.length>1||this.periodComparisons.value.length>1)}},{key:"isComparingPeriods",value:function(){return this.getPeriodComparisons().length>1}},{key:"getSegmentComparisons",value:function(){return this.isComparisonEnabled()?this.segmentComparisons.value:[]}},{key:"getPeriodComparisons",value:function(){return this.isComparisonEnabled()?this.periodComparisons.value:[]}},{key:"getSeriesColor",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:0,r=this.getComparisonSeriesIndex(t.index,e.index)%pn;if(0===n)return this.colors["series".concat(r)];var a=n%fn;return this.colors["series".concat(r,"-shade").concat(a)]}},{key:"getSeriesColorName",value:function(e,t){var n="series".concat(e%pn);return t>0&&(n+="-shade".concat(t%fn)),n}},{key:"isComparisonEnabled",value:function(){return this.isEnabled.value}},{key:"getIndividualComparisonRowIndices",value:function(e){var t=this.getSegmentComparisons().length,n=e%t,r=Math.floor(e/t);return{segmentIndex:n,periodIndex:r}}},{key:"getComparisonSeriesIndex",value:function(e,t){var n=this.getSegmentComparisons().length;return e*n+t}},{key:"getAllComparisonSeries",value:function(){var e=this,t=[],n=0;return this.getPeriodComparisons().forEach((function(r){e.getSegmentComparisons().forEach((function(a){t.push({index:n,params:cn(cn({},a.params),r.params),color:e.colors["series".concat(n)]}),n+=1}))})),t}},{key:"removeSegmentComparison",value:function(e){if(!this.isComparisonEnabled())throw new Error("Comparison disabled.");var t=Zt(this.segmentComparisons.value);t.splice(e,1);var n={};0===e&&(n.segment=t[0].params.segment),this.updateQueryParamsFromComparisons(t,this.periodComparisons.value,n)}},{key:"addSegmentComparison",value:function(e){if(!this.isComparisonEnabled())throw new Error("Comparison disabled.");var t=this.segmentComparisons.value.concat([{params:e,index:-1,title:""}]);this.updateQueryParamsFromComparisons(t,this.periodComparisons.value)}},{key:"updateQueryParamsFromComparisons",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r={},a={},o=!1,i=!1;e.forEach((function(e){o?r[e.params.segment]=!0:o=!0})),t.forEach((function(e){i?a["".concat(e.params.period,"|").concat(e.params.date)]=!0:i=!0}));var c=[],s=[];Object.keys(a).forEach((function(e){var t=e.split("|");c.push(t[0]),s.push(t[1])}));var l={compareSegments:Object.keys(r),comparePeriods:c,compareDates:s};if(D.helper.isAngularRenderingThePage()){var u=ke.hashParsed.value,d=cn(cn(cn({},u),l),n);return delete d["compareSegments[]"],delete d["comparePeriods[]"],delete d["compareDates[]"],void(JSON.stringify(d)!==JSON.stringify(u)&&ke.updateHash(d))}var p=[];["compareSegments","comparePeriods","compareDates"].forEach((function(e){l[e].length||p.push(e)}));var f=ke.stringify(n),m=ke.stringify(l);window.broadcast.propagateNewPage(f,void 0,m,p)}},{key:"getAllSeriesColors",value:function(){var e=D.ColorManager;if(!e)return[];for(var t=[],n=0;n<pn;n+=1){t.push("series".concat(n));for(var r=0;r<fn;r+=1)t.push("series".concat(n,"-shade").concat(r))}return e.getColors("comparison-series-color",t)}},{key:"loadComparisonsDisabledFor",value:function(){var e=this,t=ke.parsed.value.module;"CoreUpdater"!==t&&"Installation"!==t?Ne.fetch({module:"API",method:"API.getPagesComparisonsDisabledFor"}).then((function(t){e.privateState.comparisonsDisabledFor=t})):this.privateState.comparisonsDisabledFor=[]}},{key:"parseSegmentComparisons",value:function(){var e=Xt.state.availableSegments,t=Zt(mn(ke.parsed.value.compareSegments));t.unshift(ke.parsed.value.segment||"");var n=[];return t.forEach((function(t,r){var a;e.forEach((function(e){e.definition!==t&&e.definition!==decodeURIComponent(t)&&decodeURIComponent(e.definition)!==t||(a=e)}));var o=a?a.name:C("General_Unknown");""===t.trim()&&(o=C("SegmentEditor_DefaultAllVisits")),n.push({params:{segment:t},title:D.helper.htmlDecode(o),index:r})})),n}},{key:"parsePeriodComparisons",value:function(){var e=Zt(mn(ke.parsed.value.comparePeriods)),t=Zt(mn(ke.parsed.value.compareDates));e.unshift(ke.parsed.value.period),t.unshift(ke.parsed.value.date);for(var n=[],r=0;r<Math.min(t.length,e.length);r+=1){var a=void 0;try{a=p.parse(e[r],t[r]).getPrettyString()}catch(o){a=C("General_Error")}n.push({params:{date:t[r],period:e[r]},title:a,index:r})}return n}},{key:"checkEnabledForCurrentPage",value:function(){var e=ke.parsed.value.category||ke.parsed.value.module,t=ke.parsed.value.subcategory||ke.parsed.value.action,n="".concat(e,".").concat(t),r=-1===this.privateState.comparisonsDisabledFor.indexOf(n)&&-1===this.privateState.comparisonsDisabledFor.indexOf("".concat(e,".*"));return document.documentElement.classList.toggle("comparisonsDisabled",!r),r}}]),e}(),vn=new hn,gn={key:0,ref:"root",class:"matomo-comparisons"},bn={class:"comparison-type"},yn=["title"],wn=["href"],kn=["title"],On={class:"comparison-period-label"},jn=["onClick"],Dn=["title"],Cn={class:"loadingPiwik",style:{display:"none"}},Sn=["alt"];function Pn(e,t,n,r,a,i){return e.isComparing?(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",gn,[Object(o["createElementVNode"])("h3",null,Object(o["toDisplayString"])(e.translate("General_Comparisons")),1),(Object(o["openBlock"])(!0),Object(o["createElementBlock"])(o["Fragment"],null,Object(o["renderList"])(e.segmentComparisons,(function(t,n){return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",{class:"comparison card",key:t.index},[Object(o["createElementVNode"])("div",bn,Object(o["toDisplayString"])(e.translate("General_Segment")),1),Object(o["createElementVNode"])("div",{class:"title",title:t.title+"<br/>"+decodeURIComponent(t.params.segment)},[Object(o["createElementVNode"])("a",{target:"_blank",href:e.getUrlToSegment(t.params.segment)},Object(o["toDisplayString"])(t.title),9,wn)],8,yn),(Object(o["openBlock"])(!0),Object(o["createElementBlock"])(o["Fragment"],null,Object(o["renderList"])(e.periodComparisons,(function(n){return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",{class:"comparison-period",key:n.index,title:e.getComparisonTooltip(t,n)},[Object(o["createElementVNode"])("span",{class:"comparison-dot",style:Object(o["normalizeStyle"])({"background-color":e.getSeriesColor(t,n)})},null,4),Object(o["createElementVNode"])("span",On,Object(o["toDisplayString"])(n.title)+" ("+Object(o["toDisplayString"])(e.getComparisonPeriodType(n))+") ",1)],8,kn)})),128)),e.segmentComparisons.length>1?(Object(o["openBlock"])(),Object(o["createElementBlock"])("a",{key:0,class:"remove-button",onClick:function(t){return e.removeSegmentComparison(n)}},[Object(o["createElementVNode"])("span",{class:"icon icon-close",title:e.translate("General_ClickToRemoveComp")},null,8,Dn)],8,jn)):Object(o["createCommentVNode"])("",!0)])})),128)),Object(o["createElementVNode"])("div",Cn,[Object(o["createElementVNode"])("img",{src:"plugins/Morpheus/images/loading-blue.gif",alt:e.translate("General_LoadingData")},null,8,Sn),Object(o["createTextVNode"])(" "+Object(o["toDisplayString"])(e.translate("General_LoadingData")),1)])],512)):Object(o["createCommentVNode"])("",!0)}function En(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Tn(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?En(Object(n),!0).forEach((function(t){xn(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):En(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function xn(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var In=Object(o["defineComponent"])({props:{},data:function(){return{comparisonTooltips:null}},setup:function(){var e=Object(o["computed"])((function(){return vn.isComparing()})),t=Object(o["computed"])((function(){return vn.getSegmentComparisons()})),n=Object(o["computed"])((function(){return vn.getPeriodComparisons()})),r=vn.getSeriesColor.bind(vn);return{isComparing:e,segmentComparisons:t,periodComparisons:n,getSeriesColor:r}},methods:{comparisonHasSegment:function(e){return"undefined"!==typeof e.params.segment},removeSegmentComparison:function(e){window.$(this.$refs.root).tooltip("destroy"),vn.removeSegmentComparison(e)},getComparisonPeriodType:function(e){var t=e.params.period;if("range"===t)return C("CoreHome_PeriodRange");var n=C("Intl_Period".concat(t.substring(0,1).toUpperCase()).concat(t.substring(1)));return n.substring(0,1).toUpperCase()+n.substring(1)},getComparisonTooltip:function(e,t){if(this.comparisonTooltips&&Object.keys(this.comparisonTooltips).length)return(this.comparisonTooltips[t.index]||{})[e.index]},getUrlToSegment:function(e){var t=Tn({},ke.hashParsed.value);return delete t.comparePeriods,delete t.compareDates,delete t.compareSegments,t.segment=e,"".concat(window.location.search,"#?").concat(ke.stringify(t))},setUpTooltips:function(){var e=window,t=e.$;t(this.$refs.root).tooltip({track:!0,content:function(){var e=t(this).attr("title");return window.vueSanitize(e.replace(/\n/g,"<br />"))},show:{delay:200,duration:200},hide:!1})},onComparisonsChanged:function(){var e=this;if(this.comparisonTooltips=null,vn.isComparing()){var t=vn.getPeriodComparisons(),n=vn.getSegmentComparisons();Ne.fetch({method:"API.getProcessedReport",apiModule:"VisitsSummary",apiAction:"get",compare:"1",compareSegments:ke.getSearchParam("compareSegments"),comparePeriods:ke.getSearchParam("comparePeriods"),compareDates:ke.getSearchParam("compareDates"),format_metrics:"1"}).then((function(r){e.comparisonTooltips={},t.forEach((function(t){e.comparisonTooltips[t.index]={},n.forEach((function(n){var a=e.generateComparisonTooltip(r,t,n);e.comparisonTooltips[t.index][n.index]=a}))}))}))}},generateComparisonTooltip:function(e,t,n){if(!e.reportData.comparisons)return"";var r=vn.getComparisonSeriesIndex(t.index,0),a=e.reportData.comparisons[r],o=vn.getComparisonSeriesIndex(t.index,n.index),i=e.reportData.comparisons[o],c=e.reportData.comparisons[n.index],s='<div class="comparison-card-tooltip">',l=(i.nb_visits/a.nb_visits*100).toFixed(2);return l="".concat(l,"%"),s+=C("General_ComparisonCardTooltip1",["'".concat(i.compareSegmentPretty,"'"),i.comparePeriodPretty,l,i.nb_visits.toString(),a.nb_visits.toString()]),t.index>0&&(s+="<br/><br/>",s+=C("General_ComparisonCardTooltip2",[i.nb_visits_change.toString(),c.compareSegmentPretty,c.comparePeriodPretty])),s+="</div>",s}},updated:function(){var e=this;setTimeout((function(){return e.setUpTooltips()}))},mounted:function(){var e=this;D.on("piwikComparisonsChanged",(function(){e.onComparisonsChanged()})),this.onComparisonsChanged(),setTimeout((function(){return e.setUpTooltips()}))},beforeUnmount:function(){try{window.$(this.refs.root).tooltip("destroy")}catch(e){}}});In.render=Pn;var Nn=In; + */function _l(e){var t=parseFloat(e);return!Number.isNaN(t)&&Number.isFinite(t)}var $l=function(){function e(){var t=this;Ml(this,e),Fl(this,"privateState",Object(a["reactive"])({activeCategoryId:null,activeSubcategoryId:null,activeSubsubcategoryId:null})),Fl(this,"state",Object(a["computed"])((function(){return Object(a["readonly"])(t.privateState)}))),Fl(this,"activeCategory",Object(a["computed"])((function(){return t.state.value.activeCategoryId||Ee.parsed.value.category}))),Fl(this,"activeSubcategory",Object(a["computed"])((function(){return t.state.value.activeSubcategoryId||Ee.parsed.value.subcategory}))),Fl(this,"activeSubsubcategory",Object(a["computed"])((function(){var e=t.state.value.activeSubsubcategoryId;if(e)return e;var n=t.findSubcategory(t.activeCategory.value,t.activeSubcategory.value);return n.subsubcategory&&n.subsubcategory.id===t.activeSubcategory.value?n.subsubcategory.id:null}))),Fl(this,"menu",Object(a["computed"])((function(){return t.buildMenuFromPages()})))}return Rl(e,[{key:"fetchMenuItems",value:function(){var e=this;return El.getAllPages().then((function(){return e.menu.value}))}},{key:"reloadMenuItems",value:function(){var e=this;return El.reloadAllPages().then((function(){return e.menu.value}))}},{key:"findSubcategory",value:function(e,t){var n=void 0,r=void 0,i=void 0;return this.menu.value.forEach((function(a){a.id===e&&(xl(a)||[]).forEach((function(e){e.id===t&&(n=a,r=e),e.isGroup&&(Bl(e)||[]).forEach((function(o){o.id===t&&(n=a,r=e,i=o)}))}))})),{category:n,subcategory:r,subsubcategory:i}}},{key:"buildMenuFromPages",value:function(){var e=[],t=Ee.parsed.value.category,n=Ee.parsed.value.subcategory,r=El.pages.value,i={};return r.forEach((function(a){var o=Object.assign({},a.category),l=o.id,c=l===t;if(!i[l]){i[l]=!0,o.subcategories=[];var s=null,u=r.filter((function(e){return e.category.id===l}));u.forEach((function(e){var t=Object.assign({},e.subcategory),r=t.id===n&&c;if(e.widgets&&e.widgets[0]&&_l(e.subcategory.id)){s||(s=Object.assign({},t),s.name=C("CoreHome_ChooseX",[o.name]),s.isGroup=!0,s.subcategories=[],s.order=10),r&&(s.name=t.name);var i=a.subcategory.id;return t.tooltip="".concat(t.name," (id = ").concat(i,")"),void s.subcategories.push(t)}o.subcategories.push(t)})),s&&s.subcategories&&s.subcategories.length<=5?s.subcategories.forEach((function(e){return o.subcategories.push(e)})):s&&o.subcategories.push(s),o.subcategories=Il(xl(o)),e.push(o)}})),Il(e)}},{key:"toggleCategory",value:function(e){return this.privateState.activeSubcategoryId=null,this.privateState.activeSubsubcategoryId=null,this.privateState.activeCategoryId===e.id?(this.privateState.activeCategoryId=null,!1):(this.privateState.activeCategoryId=e.id,!0)}},{key:"enterSubcategory",value:function(e,t,n){e&&t&&(this.privateState.activeCategoryId=e.id,this.privateState.activeSubcategoryId=t.id,n&&(this.privateState.activeSubsubcategoryId=n.id))}}]),e}(),Hl=new $l;function Ul(e){return Ul="function"===typeof Symbol&&"symbol"===typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"===typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ul(e)}function ql(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Wl(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function Jl(e,t,n){return t&&Wl(e.prototype,t),n&&Wl(e,n),e}function Gl(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function $n(){return vn}$n.$inject=[],angular.module("piwikApp.service").factory("piwikComparisonsService",$n);wt({component:Nn,directiveName:"piwikComparisons",restrict:"E"});var Bn={ref:"root",class:"menuDropdown"},Hn=["title"],An=["innerHTML"],Mn=Object(o["createElementVNode"])("span",{class:"icon-arrow-bottom"},null,-1),Fn={class:"items"},Vn={key:0,class:"search"},Ln=["placeholder"],Rn=["title"],Un=["title"];function _n(e,t,n,r,a,i){var c=Object(o["resolveDirective"])("focus-if"),s=Object(o["resolveDirective"])("focus-anywhere-but-here");return Object(o["withDirectives"])((Object(o["openBlock"])(),Object(o["createElementBlock"])("div",Bn,[Object(o["createElementVNode"])("span",{class:"title",onClick:t[0]||(t[0]=function(t){return e.showItems=!e.showItems}),title:e.tooltip},[Object(o["createElementVNode"])("span",{innerHTML:e.$sanitize(this.actualMenuTitle)},null,8,An),Mn],8,Hn),Object(o["withDirectives"])(Object(o["createElementVNode"])("div",Fn,[e.showSearch&&e.showItems?(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",Vn,[Object(o["withDirectives"])(Object(o["createElementVNode"])("input",{type:"text","onUpdate:modelValue":t[1]||(t[1]=function(t){return e.searchTerm=t}),onKeydown:t[2]||(t[2]=function(t){return e.onSearchTermKeydown(t)}),placeholder:e.translate("General_Search")},null,40,Ln),[[o["vModelText"],e.searchTerm],[c,{},e.showItems]]),Object(o["withDirectives"])(Object(o["createElementVNode"])("img",{class:"search_ico",src:"plugins/Morpheus/images/search_ico.png",title:e.translate("General_Search")},null,8,Rn),[[o["vShow"],!e.searchTerm]]),Object(o["withDirectives"])(Object(o["createElementVNode"])("img",{onClick:t[3]||(t[3]=function(t){e.searchTerm="",e.searchItems("")}),class:"reset",src:"plugins/CoreHome/images/reset_search.png",title:e.translate("General_Clear")},null,8,Un),[[o["vShow"],e.searchTerm]])])):Object(o["createCommentVNode"])("",!0),Object(o["createElementVNode"])("div",{onClick:t[4]||(t[4]=function(t){return e.selectItem(t)})},[Object(o["renderSlot"])(e.$slots,"default")])],512),[[o["vShow"],e.showItems]])],512)),[[s,{blur:e.lostFocus}]])}var Jn=window,Gn=Jn.$,qn=Object(o["defineComponent"])({props:{menuTitle:String,tooltip:String,showSearch:Boolean,menuTitleChangeOnClick:String},directives:{FocusAnywhereButHere:Re,FocusIf:Je},emits:["afterSelect"],watch:{menuTitle:function(){this.actualMenuTitle=this.menuTitle}},data:function(){return{showItems:!1,searchTerm:"",actualMenuTitle:this.menuTitle}},methods:{lostFocus:function(){this.showItems=!1},selectItem:function(e){var t=e.target.classList;!t.contains("item")||t.contains("disabled")||t.contains("separator")||(!1!==this.menuTitleChangeOnClick&&(this.actualMenuTitle=e.target.textContent.replace(/[\u0000-\u2666]/g,(function(e){return"&#".concat(e.charCodeAt(0),";")}))),this.showItems=!1,Gn(this.$slots.default()).find(".item").removeClass("active"),t.add("active"),this.$emit("afterSelect"))},onSearchTermKeydown:function(){var e=this;setTimeout((function(){e.searchItems(e.searchTerm)}))},searchItems:function(e){var t=e.toLowerCase();Gn(this.$refs.root).find(".item").each((function(e,n){var r=Gn(n);-1===r.text().toLowerCase().indexOf(t)?r.hide():r.show()}))}}});qn.render=_n;var zn=qn,Qn=(wt({component:zn,scope:{menuTitle:{angularJsBind:"@"},tooltip:{angularJsBind:"@"},showSearch:{angularJsBind:"="},menuTitleChangeOnClick:{angularJsBind:"="}},directiveName:"piwikMenudropdown",transclude:!0,events:{"after-select":function(e,t){setTimeout((function(){t.$apply()}),0)}}}),{ref:"root"}); + */function zl(e){var t=e;return t.widgets?t.widgets:[]}var Yl=function(){function e(){var t=this;ql(this,e),Gl(this,"privateState",Object(a["reactive"])({isFetchedFirstTime:!1,categorizedWidgets:{}})),Gl(this,"state",Object(a["computed"])((function(){return t.privateState.isFetchedFirstTime||t.fetchAvailableWidgets(),Object(a["readonly"])(t.privateState)}))),Gl(this,"widgets",Object(a["computed"])((function(){return t.state.value.categorizedWidgets})))}return Jl(e,[{key:"fetchAvailableWidgets",value:function(){var e=this;return Ee.parsed.value.idSite?(this.privateState.isFetchedFirstTime=!0,new Promise((function(t,n){try{window.widgetsHelper.getAvailableWidgets((function(n){var r=n;e.privateState.categorizedWidgets=r,t(e.widgets.value)}))}catch(r){n(r)}}))):Promise.resolve(this.widgets.value)}},{key:"reloadAvailableWidgets",value:function(){return"object"===Ul(window.widgetsHelper)&&window.widgetsHelper.availableWidgets&&delete window.widgetsHelper.availableWidgets,this.fetchAvailableWidgets()}}]),e}(),Ql=new Yl,Kl="reportingmenu-help",Xl=Object(a["defineComponent"])({components:{MenuItemsDropdown:ti},directives:{SideNav:wn},props:{},data:function(){return{showSubcategoryHelpOnLoad:null,initialLoad:!0,helpShownCategory:null}},computed:{sideNavActivator:function(){return document.querySelector("nav .activateLeftMenu")},menu:function(){return Hl.menu.value},activeCategory:function(){return Hl.activeCategory.value},activeSubcategory:function(){return Hl.activeSubcategory.value},activeSubsubcategory:function(){return Hl.activeSubsubcategory.value},displayedCategory:function(){return Ee.parsed.value.category},displayedSubcategory:function(){return Ee.parsed.value.subcategory}},created:function(){var e=this;Hl.fetchMenuItems().then((function(t){if(!Ee.parsed.value.subcategory){var n=t[0],r=n.subcategories[0];Hl.enterSubcategory(n,r),e.propagateUrlChange(n,r)}})),Object(a["watch"])((function(){return Ee.parsed.value}),(function(e){var t=Hl.findSubcategory(e.category,e.subcategory);Hl.enterSubcategory(t.category,t.subcategory,t.subsubcategory)})),S.on("piwikPageChange",(function(){e.initialLoad||window.globalAjaxQueue.abort(),e.helpShownCategory=null,e.showSubcategoryHelpOnLoad&&(e.showHelp(e.showSubcategoryHelpOnLoad.category,e.showSubcategoryHelpOnLoad.subcategory),e.showSubcategoryHelpOnLoad=null),window.$("#loadingError").hide(),e.initialLoad=!1})),S.on("updateReportingMenu",(function(){Hl.reloadMenuItems().then((function(){var e=Ee.parsed.value.category,t=Ee.parsed.value.subcategory;if(e&&t){var n=Hl.findSubcategory(e,t);n.category&&Hl.enterSubcategory(n.category,n.subcategory,n.subsubcategory)}})),Ql.reloadAvailableWidgets()}))},methods:{propagateUrlChange:function(e,t){var n=Ee.parsed.value;n.category===e.id&&n.subcategory===t.id?this.loadSubcategory(e,t):Ee.updateHash(Object.assign(Object.assign({},Ee.hashParsed.value),{},{category:e.id,subcategory:t.id}))},loadCategory:function(e){hl.remove(Kl);var t=Hl.toggleCategory(e);if(t&&e.subcategories&&1===e.subcategories.length){this.helpShownCategory=null;var n=e.subcategories[0];this.propagateUrlChange(e,n)}},loadSubcategory:function(e,t,n){n&&(n.shiftKey||n.ctrlKey||n.metaKey)||(hl.remove(Kl),t&&t.id===this.activeSubcategory&&(this.helpShownCategory=null,setTimeout((function(){S.postEvent("loadPage",e.id,t.id)}))))},makeUrl:function(e,t){var n=Ee.parsed.value,r=n.idSite,i=n.period,a=n.date,o=n.segment,l=n.comparePeriods,c=n.compareDates,s=n.compareSegments;return Ee.stringify({idSite:r,period:i,date:a,segment:o,comparePeriods:l,compareDates:c,compareSegments:s,category:e.id,subcategory:t.id})},htmlEntities:function(e){return S.helper.htmlEntities(e)},showHelp:function(e,t,n){var r=Ee.parsed.value,i=r.category,a=r.subcategory;if((i!==e.id||a!==t.id)&&n)return this.showSubcategoryHelpOnLoad={category:e,subcategory:t},void Ee.updateHash(Object.assign(Object.assign({},Ee.hashParsed.value),{},{category:e.id,subcategory:t.id}));if(this.helpShownCategory&&e.id===this.helpShownCategory.category&&t.id===this.helpShownCategory.subcategory)return hl.remove(Kl),void(this.helpShownCategory=null);var o=C("CoreHome_ReportingCategoryHelpPrefix",e.name,t.name),l="<strong>".concat(o,"</strong><br/>");hl.show({context:"info",id:Kl,type:"help",noclear:!0,class:"help-notification",message:l+t.help,placeat:"#notificationContainer",prepend:!0}),this.helpShownCategory={category:e.id,subcategory:t.id}}}});Xl.render=Yo;var Zl=Xl; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function Yn(e,t,n,r,a,i){return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",Qn,null,512)}function Wn(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Kn(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Wn(Object(n),!0).forEach((function(t){Xn(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Wn(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Xn(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var Zn=1,er=window,tr=er.$,nr=Object(o["defineComponent"])({props:{selectedDateStart:Date,selectedDateEnd:Date,highlightedDateStart:Date,highlightedDateEnd:Date,viewDate:[String,Date],stepMonths:Number,disableMonthDropdown:Boolean,options:Object},emits:["cellHover","cellHoverLeave","dateSelect"],setup:function(e,t){var n=Object(o["ref"])(null);function r(t,n){var r=t.children("a");if(e.selectedDateStart&&e.selectedDateEnd&&n>=e.selectedDateStart&&n<=e.selectedDateEnd?t.addClass("ui-datepicker-current-period"):t.removeClass("ui-datepicker-current-period"),e.highlightedDateStart&&e.highlightedDateEnd&&n>=e.highlightedDateStart&&n<=e.highlightedDateEnd){var a=r.length?r:t;a.addClass("ui-state-hover")}else t.removeClass("ui-state-hover"),r.removeClass("ui-state-hover")}function a(e,t,n){if(e.hasClass("ui-datepicker-other-month"))return i(e,t,n);var r=parseInt(e.children("a,span").text(),10);return new Date(n,t,r)}function i(e,t,n){var r,o=e.parent(),i=o.children("td");if(o.is(":first-child")){var c=o.children("td:not(.ui-datepicker-other-month)").first();return r=a(c,t,n),r.setDate(i.index(e)-i.index(c)+1),r}var s=o.children("td:not(.ui-datepicker-other-month)").last();return r=a(s,t,n),r.setDate(r.getDate()+i.index(e)-i.index(s)),r}function c(){var e=tr(n.value),t=e.find("td[data-month]"),r=parseInt(t.attr("data-month"),10),a=parseInt(t.attr("data-year"),10);return[r,a]}function s(){var e=tr(n.value),t=e.find(".ui-datepicker-calendar"),o=c(),i=t.find("td"),s=i.first(),l=a(s,o[0],o[1]);i.each((function(){r(tr(this),l),l.setDate(l.getDate()+1)}))}function l(){var t=e.viewDate;if(!t)return!1;if(!(t instanceof Date))try{t=E(t)}catch(o){return!1}var r=tr(n.value),a=c();return(a[0]!==t.getMonth()||a[1]!==t.getFullYear())&&(r.datepicker("setDate",t),!0)}function u(){var e=tr(n.value);e.find("td[data-event]").off("click"),e.find(".ui-state-active").removeClass("ui-state-active"),e.find(".ui-datepicker-current-day").removeClass("ui-datepicker-current-day"),e.find(".ui-datepicker-prev,.ui-datepicker-next").attr("href","")}function d(){var t=tr(n.value),r=e.stepMonths||Zn;if(t.datepicker("option","stepMonths")===r)return!1;var a=tr(".ui-datepicker-month",t).val(),o=tr(".ui-datepicker-year",t).val();return t.datepicker("option","stepMonths",r).datepicker("setDate",new Date(o,a)),u(),!0}function p(){var t=tr(n.value);t.find(".ui-datepicker-month").attr("disabled",e.disableMonthDropdown)}function f(){if(tr(this).hasClass("ui-state-hover")){var e=tr(this).parent(),t=e.parent();e.is(":first-child")?t.find("a").first().click():t.find("a").last().click()}}function m(){p(),s()}return Object(o["watch"])((function(){return Kn({},e)}),(function(e,t){var n=!1;["selectedDateStart","selectedDateEnd","highlightedDateStart","highlightedDateEnd"].forEach((function(r){n||(!e[r]&&t[r]&&(n=!0),e[r]&&!t[r]&&(n=!0),e[r]&&t[r]&&e[r].getTime()!==t[r].getTime()&&(n=!0))})),e.viewDate!==t.viewDate&&l()&&(n=!0),e.stepMonths!==t.stepMonths&&d(),e.enableDisableMonthDropdown!==t.enableDisableMonthDropdown&&p(),n&&s()})),Object(o["onMounted"])((function(){var r=tr(n.value),o=e.options||{},i=Kn(Kn(Kn({},D.getBaseDatePickerOptions()),o),{},{onChangeMonthYear:function(){setTimeout((function(){u()}))}});r.datepicker(i),r.on("mouseover","tbody td a",(function(e){e.originalEvent&&s()})),r.on("mouseenter","tbody td",(function(){var e=c(),n=tr(this),r=a(n,e[0],e[1]);t.emit("cellHover",{date:r,$cell:n})})),r.on("mouseout","tbody td a",(function(){s()})),r.on("mouseleave","table",(function(){return t.emit("cellHoverLeave")})).on("mouseenter","thead",(function(){return t.emit("cellHoverLeave")})),r.on("click","tbody td.ui-datepicker-other-month",(function(){return f()})),r.on("click",(function(e){e.preventDefault();var t=tr(e.target).closest("a");(t.is(".ui-datepicker-next")||t.is(".ui-datepicker-prev"))&&m()})),r.on("click","td[data-month]",(function(e){var n=tr(e.target).closest("td"),r=parseInt(n.attr("data-month"),10),a=parseInt(n.attr("data-year"),10),o=parseInt(n.children("a,span").text(),10);t.emit("dateSelect",{date:new Date(a,r,o)})}));var h=d();l(),p(),h||u(),s()})),{root:n}}});nr.render=Yn;var rr=nr,ar=(wt({component:rr,scope:{selectedDateStart:{angularJsBind:"<"},selectedDateEnd:{angularJsBind:"<"},highlightedDateStart:{angularJsBind:"<"},highlightedDateEnd:{angularJsBind:"<"},viewDate:{angularJsBind:"<"},stepMonths:{angularJsBind:"<"},disableMonthDropdown:{angularJsBind:"<"},options:{angularJsBind:"<"},cellHover:{angularJsBind:"&"},cellHoverLeave:{angularJsBind:"&"},dateSelect:{angularJsBind:"&"}},directiveName:"piwikDatePicker",events:{"cell-hover":function(e,t,n,r,a){a()},"cell-hover-leave":function(e,t,n,r,a){a()},"date-select":function(e,t,n,r,a){a()}},$inject:["$timeout"]}),{id:"calendarRangeFrom"}),or={id:"calendarRangeTo"}; + */kt({component:Zl,directiveName:"piwikReportingMenu"}); /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function ir(e,t,n,r,a,i){var c=Object(o["resolveComponent"])("DatePicker");return Object(o["openBlock"])(),Object(o["createElementBlock"])(o["Fragment"],null,[Object(o["createElementVNode"])("div",ar,[Object(o["createElementVNode"])("h6",null,[Object(o["createTextVNode"])(Object(o["toDisplayString"])(e.translate("General_DateRangeFrom"))+" ",1),Object(o["withDirectives"])(Object(o["createElementVNode"])("input",{type:"text",id:"inputCalendarFrom",name:"inputCalendarFrom",class:"browser-default","onUpdate:modelValue":t[0]||(t[0]=function(t){return e.startDateText=t}),onChange:t[1]||(t[1]=function(t){return e.onRangeInputChanged("from",t)}),onKeyup:t[2]||(t[2]=function(t){return e.handleEnterPress(t)})},null,544),[[o["vModelText"],e.startDateText]])]),Object(o["createVNode"])(c,{id:"calendarFrom","view-date":e.startDate,"selected-date-start":e.fromPickerSelectedDates[0],"selected-date-end":e.fromPickerSelectedDates[1],"highlighted-date-start":e.fromPickerHighlightedDates[0],"highlighted-date-end":e.fromPickerHighlightedDates[1],onDateSelect:t[3]||(t[3]=function(t){return e.setStartRangeDate(t.date)}),onCellHover:t[4]||(t[4]=function(t){return e.fromPickerHighlightedDates=e.getNewHighlightedDates(t.date,t.$cell)}),onCellHoverLeave:t[5]||(t[5]=function(t){return e.fromPickerHighlightedDates=[null,null]})},null,8,["view-date","selected-date-start","selected-date-end","highlighted-date-start","highlighted-date-end"])]),Object(o["createElementVNode"])("div",or,[Object(o["createElementVNode"])("h6",null,[Object(o["createTextVNode"])(Object(o["toDisplayString"])(e.translate("General_DateRangeTo"))+" ",1),Object(o["withDirectives"])(Object(o["createElementVNode"])("input",{type:"text",id:"inputCalendarTo",name:"inputCalendarTo",class:"browser-default","onUpdate:modelValue":t[6]||(t[6]=function(t){return e.endDateText=t}),onChange:t[7]||(t[7]=function(t){return e.onRangeInputChanged("to",t)}),onKeyup:t[8]||(t[8]=function(t){return e.handleEnterPress(t)})},null,544),[[o["vModelText"],e.endDateText]])]),Object(o["createVNode"])(c,{id:"calendarTo","view-date":e.endDate,"selected-date-start":e.toPickerSelectedDates[0],"selected-date-end":e.toPickerSelectedDates[1],"highlighted-date-start":e.toPickerHighlightedDates[0],"highlighted-date-end":e.toPickerHighlightedDates[1],onDateSelect:t[9]||(t[9]=function(t){return e.setEndRangeDate(t.date)}),onCellHover:t[10]||(t[10]=function(t){return e.toPickerHighlightedDates=e.getNewHighlightedDates(t.date,t.$cell)}),onCellHoverLeave:t[11]||(t[11]=function(t){return e.toPickerHighlightedDates=[null,null]})},null,8,["view-date","selected-date-start","selected-date-end","highlighted-date-start","highlighted-date-end"])])],64)}var cr=Object(o["defineComponent"])({props:{startDate:String,endDate:String},components:{DatePicker:rr},data:function(){var e=null;try{e=E(this.startDate)}catch(n){}var t=null;try{t=E(this.endDate)}catch(n){}return{fromPickerSelectedDates:[e,e],toPickerSelectedDates:[t,t],fromPickerHighlightedDates:[null,null],toPickerHighlightedDates:[null,null],startDateText:this.startDate,endDateText:this.endDate}},emits:["rangeChange","submit"],watch:{startDate:function(){this.startDateText=this.startDate,this.setStartRangeDateFromStr(this.startDate)},endDate:function(){this.endDateText=this.endDate,this.setEndRangeDateFromStr(this.endDate)}},mounted:function(){this.rangeChanged()},methods:{setStartRangeDate:function(e){this.fromPickerSelectedDates=[e,e],this.rangeChanged()},setEndRangeDate:function(e){this.toPickerSelectedDates=[e,e],this.rangeChanged()},onRangeInputChanged:function(e,t){"from"===e?this.setStartRangeDateFromStr(t.target.value):this.setEndRangeDateFromStr(t.target.value)},getNewHighlightedDates:function(e,t){return t.hasClass("ui-datepicker-unselectable")?null:[e,e]},handleEnterPress:function(e){13===e.keyCode&&this.$emit("submit",{start:this.startDate,end:this.endDate})},setStartRangeDateFromStr:function(e){var t;try{t=E(e)}catch(n){this.startDateText=this.startDate}t&&(this.fromPickerSelectedDates=[t,t]),this.rangeChanged()},setEndRangeDateFromStr:function(e){var t;try{t=E(e)}catch(n){this.endDateText=this.endDate}t&&(this.toPickerSelectedDates=[t,t]),this.rangeChanged()},rangeChanged:function(){this.$emit("rangeChange",{start:S(this.fromPickerSelectedDates[0]),end:S(this.toPickerSelectedDates[0])})}}});cr.render=ir;var sr=cr; + */ +function ec(e){return e.forEach((function(e){e.id===Hl.activeCategory.value&&(e.active=!0,(e.subcategories||[]).forEach((function(e){e.id===Hl.activeSubcategory.value&&(e.active=!0,(e.subcategories||[]).forEach((function(e){e.id===Hl.activeSubsubcategory.value&&(e.active=!0)})))})))})),e}function tc(){return{get menu(){return Hl.menu.value},findSubcategory:Hl.findSubcategory.bind(Hl),reloadMenuItems:function(){return Hl.reloadMenuItems().then((function(e){return ec(Dt(e))}))},fetchMenuItems:function(){return Hl.fetchMenuItems().then((function(e){return ec(Dt(e))}))}}} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function nc(){return{get pages(){return El.pages.value},findPageInCategory:function(){return Et(El.findPageInCategory.apply(El,arguments))},findPage:function(){return Et(El.findPage.apply(El,arguments))},reloadAllPages:function(){return El.reloadAllPages().then((function(e){return Dt(e)}))},getAllPages:function(){return El.getAllPages().then((function(e){return Dt(e)}))}}}function rc(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function ic(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function ac(e,t,n){return t&&ic(e.prototype,t),n&&ic(e,n),e}function oc(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */window.angular.module("piwikApp.service").factory("reportingMenuModel",tc),window.angular.module("piwikApp.service").factory("reportingPagesModel",nc);var lc=function(){function e(){var t=this;rc(this,e),oc(this,"privateState",Object(a["reactive"])({reports:[]})),oc(this,"state",Object(a["readonly"])(this.privateState)),oc(this,"reports",Object(a["computed"])((function(){return t.state.reports}))),oc(this,"reportsPromise",void 0)}return ac(e,[{key:"findReport",value:function(e,t){return this.reports.value.find((function(n){return n.module===e&&n.action===t}))}},{key:"fetchReportMetadata",value:function(){var e=this;return this.reportsPromise||(this.reportsPromise=Ze.fetch({method:"API.getReportMetadata",filter_limit:"-1",idSite:S.idSite||Ee.parsed.value.idSite}).then((function(t){return e.privateState.reports=t,t}))),this.reportsPromise.then((function(){return e.reports.value}))}}]),e}(),cc=new lc; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */wt({component:sr,scope:{startDate:{angularJsBind:"<"},endDate:{angularJsBind:"<"},rangeChange:{angularJsBind:"&"},submit:{angularJsBind:"&"}},directiveName:"piwikDateRangePicker",restrict:"E"});function lr(e,t,n,r,a,i){var c=Object(o["resolveComponent"])("DatePicker");return Object(o["openBlock"])(),Object(o["createBlock"])(c,{"selected-date-start":e.selectedDates[0],"selected-date-end":e.selectedDates[1],"highlighted-date-start":e.highlightedDates[0],"highlighted-date-end":e.highlightedDates[1],"view-date":e.viewDate,"step-months":"year"===e.period?12:1,"disable-month-dropdown":"year"===e.period,onCellHover:t[0]||(t[0]=function(t){return e.onHoverNormalCell(t.date,t.$cell)}),onCellHoverLeave:t[1]||(t[1]=function(t){return e.onHoverLeaveNormalCells()}),onDateSelect:t[2]||(t[2]=function(t){return e.onDateSelected(t.date)})},null,8,["selected-date-start","selected-date-end","highlighted-date-start","highlighted-date-end","view-date","step-months","disable-month-dropdown"])}var ur=new Date(D.minDateYear,D.minDateMonth-1,D.minDateDay),dr=new Date(D.maxDateYear,D.maxDateMonth-1,D.maxDateDay),pr=Object(o["defineComponent"])({props:{period:String,date:[String,Date]},components:{DatePicker:rr},emits:["select"],setup:function(e,t){var n=Object(o["ref"])(e.date),r=Object(o["ref"])([null,null]),a=Object(o["ref"])([null,null]);function i(t){var n=p.get(e.period).parse(t).getDateRange();return n[0]=ur<n[0]?n[0]:ur,n[1]=dr>n[1]?n[1]:dr,n}function c(t,n){var r=t<ur||t>dr,o=n.hasClass("ui-datepicker-other-month")&&("month"===e.period||"day"===e.period);a.value=r||o?[null,null]:i(t)}function s(){a.value=[null,null]}function l(e){t.emit("select",{date:e})}function u(){e.period&&e.date?r.value=i(e.date):r.value=[null,null]}return Object(o["watch"])(e,u),u(),{selectedDates:r,highlightedDates:a,viewDate:n,onHoverNormalCell:c,onHoverLeaveNormalCells:s,onDateSelected:l}}});pr.render=lr;var fr=pr,mr=(wt({component:fr,scope:{period:{angularJsBind:"<"},date:{angularJsBind:"<"},select:{angularJsBind:"&"}},directiveName:"piwikPeriodDatePicker",restrict:"E"}),{class:"loadingPiwik"}),hr=Object(o["createElementVNode"])("img",{src:"plugins/Morpheus/images/loading-blue.gif",alt:""},null,-1); + */ +window.angular.module("piwikApp.service").factory("reportMetadataModel",(function(){return{get reports(){return cc.reports.value},findReport:cc.findReport.bind(cc),fetchReportMetadata:function(){return cc.fetchReportMetadata().then((function(e){return Dt(e)}))}}}));var sc={key:0},uc={class:"notification system notification-error"},dc={key:0,rel:"noreferrer noopener",target:"_blank",href:"https://matomo.org/faq/troubleshooting/faq_19489/"},pc={class:"theWidgetContent",ref:"widgetContent"};function mc(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("ActivityIndicator");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",null,[Object(a["createVNode"])(l,{"loading-message":e.loadingMessage,loading:e.loading},null,8,["loading-message","loading"]),Object(a["withDirectives"])(Object(a["createElementVNode"])("div",null,[e.widgetName?(Object(a["openBlock"])(),Object(a["createElementBlock"])("h2",sc,Object(a["toDisplayString"])(e.widgetName),1)):Object(a["createCommentVNode"])("",!0),Object(a["createElementVNode"])("div",uc,[Object(a["createTextVNode"])(Object(a["toDisplayString"])(e.translate("General_ErrorRequest","",""))+" ",1),e.hasErrorFaqLink?(Object(a["openBlock"])(),Object(a["createElementBlock"])("a",dc,Object(a["toDisplayString"])(e.translate("General_ErrorRequestFaqLink")),1)):Object(a["createCommentVNode"])("",!0)])],512),[[a["vShow"],e.loadingFailed]]),Object(a["createElementVNode"])("div",pc,null,512)])}var fc=Object(a["defineComponent"])({props:{widgetParams:Object,widgetName:String},components:{ActivityIndicator:go},data:function(){return{loading:!1,loadingFailed:!1,changeCounter:0,currentScope:null,lastWidgetAbortController:null}},watch:{widgetParams:function(e){e&&this.loadWidgetUrl(e,this.changeCounter+=1)}},computed:{loadingMessage:function(){return this.widgetName?C("General_LoadingPopover",this.widgetName):C("General_LoadingData")},hasErrorFaqLink:function(){var e=S.config.enable_general_settings_admin,t=S.config.enable_plugins_admin;return S.hasSuperUserAccess&&(e||t)}},mounted:function(){this.widgetParams&&this.loadWidgetUrl(this.widgetParams,this.changeCounter+=1)},beforeUnmount:function(){this.cleanupLastWidgetContent()},methods:{abortHttpRequestIfNeeded:function(){this.lastWidgetAbortController&&(this.lastWidgetAbortController.abort(),this.lastWidgetAbortController=null)},cleanupLastWidgetContent:function(){var e=this.$refs.widgetContent;S.helper.destroyVueComponent(e),this.currentScope&&this.currentScope.$destroy(),e&&(e.innerHTML="")},getWidgetUrl:function(e){var t=Ee.parsed.value,n=Object.assign({},e||{}),r=Object.keys(Object.assign(Object.assign({},Ee.hashParsed.value),{},{idSite:"",period:"",date:"",segment:"",widget:""}));return r.forEach((function(e){"category"!==e&&"subcategory"!==e&&(e in n||(n[e]=t[e]))})),jr.isComparisonEnabled()&&(n=Object.assign(Object.assign({},n),{},{comparePeriods:t.comparePeriods,compareDates:t.compareDates,compareSegments:t.compareSegments})),e&&"showtitle"in e||(n.showtitle="1"),S.shouldPropagateTokenAuth&&t.token_auth&&(S.broadcast.isWidgetizeRequestWithoutSession()||(n.force_api_session="1"),n.token_auth=t.token_auth),n.random=Math.floor(1e4*Math.random()),n},loadWidgetUrl:function(e,t){var n=this;this.loading=!0,this.abortHttpRequestIfNeeded(),this.cleanupLastWidgetContent(),this.lastWidgetAbortController=new AbortController,Ze.fetch(this.getWidgetUrl(e),{format:"html",headers:{"X-Requested-With":"XMLHttpRequest"},abortController:this.lastWidgetAbortController}).then((function(r){if(t===n.changeCounter&&r&&"string"===typeof r){n.lastWidgetAbortController=null,n.loading=!1,n.loadingFailed=!1;var i=n.$refs.widgetContent;window.$(i).html(r);var a=window.$(i).children();if(n.widgetName){var o=a.find("> .card-content .card-title");o.length||(o=a.find("> h2")),o.length&&o.html(S.helper.htmlEntities(n.widgetName))}var l=S.helper.getAngularDependency("$rootScope"),c=l.$new();n.currentScope=c,S.helper.compileAngularComponents(a,{scope:c}),S.helper.compileVueEntryComponents(a),hl.parseNotificationDivs(),setTimeout((function(){S.postEvent("widget:loaded",{parameters:e,element:a})}))}})).catch((function(e){t===n.changeCounter&&(n.lastWidgetAbortController=null,n.cleanupLastWidgetContent(),n.loading=!1,"abort"!==e.xhrStatus&&(n.loadingFailed=!0))}))}}});fc.render=mc;var hc=fc; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function vr(e,t,n,r,a,i){return Object(o["withDirectives"])((Object(o["openBlock"])(),Object(o["createElementBlock"])("div",mr,[hr,Object(o["createElementVNode"])("span",null,Object(o["toDisplayString"])(e.loadingMessage),1)],512)),[[o["vShow"],e.loading]])}var gr=Object(o["defineComponent"])({props:{loading:{type:Boolean,required:!0,default:!1},loadingMessage:{type:String,required:!1,default:C("General_LoadingData")}}});gr.render=vr;var br=gr,yr=wt({component:br,scope:{loading:{vue:"loading",angularJsBind:"<"},loadingMessage:{vue:"loadingMessage",angularJsBind:"<",default:function(){return C("General_LoadingData")}}},$inject:[],directiveName:"piwikActivityIndicator"}); + */kt({component:hc,scope:{piwikWidgetLoader:{vue:"widgetParams",angularJsBind:"="},widgetName:{angularJsBind:"@"}},directiveName:"piwikWidgetLoader"});function gc(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("Widget");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",null,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.actualContainer,(function(e,t){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{key:t},[Object(a["createElementVNode"])("div",null,[Object(a["createVNode"])(l,{widget:e,"prevent-recursion":!0},null,8,["widget"])])])})),128))])}function vc(e){return wc(e)||yc(e)||kc(e)||bc()}function bc(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function yc(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function wc(e){if(Array.isArray(e))return Sc(e)}function Oc(e,t){return Ec(e)||Cc(e,t)||kc(e,t)||jc()}function jc(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function kc(e,t){if(e){if("string"===typeof e)return Sc(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Sc(e,t):void 0}}function Sc(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function Cc(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a=[],o=!0,l=!1;try{for(n=n.call(e);!(o=(r=n.next()).done);o=!0)if(a.push(r.value),t&&a.length===t)break}catch(c){l=!0,i=c}finally{try{o||null==n["return"]||n["return"]()}finally{if(l)throw i}}return a}}function Ec(e){if(Array.isArray(e))return e}var Dc=$n("CoreHome","Widget"),Pc=Object(a["defineComponent"])({props:{container:{type:Array,required:!0}},components:{Widget:Dc},computed:{actualContainer:function(){var e,t,n,r=this.container;if(null===r||void 0===r||null===(e=r[0])||void 0===e||!e.parameters)return r;var i=Oc(r,1),a=i[0],o="1"===(null===(t=a.parameters)||void 0===t?void 0:t.widget)||1===(null===(n=a.parameters)||void 0===n?void 0:n.widget),l=o&&"graphEvolution"===a.viewDataTable,c=l?Object.assign(Object.assign({},a),{},{parameters:Object.assign(Object.assign({},a.parameters),{},{showtitle:"0"})}):a;return[c].concat(vc(r.slice(1)))}}});Pc.render=gc;var Vc=Pc,Nc=(kt({component:Vc,scope:{container:{angularJsBind:"=piwikWidgetContainer"}},directiveName:"piwikWidgetContainer"}),{class:"reportsByDimensionView"}),Tc={class:"entityList"},Ac={class:"listCircle"},Ic=["onClick"],xc={class:"dimension"},Bc={class:"reportContainer"},Mc=Object(a["createElementVNode"])("div",{class:"clear"},null,-1); /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function wr(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kr(e,t,n,r,a,i){return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",{class:Object(o["normalizeClass"])(["alert",wr({},"alert-".concat(e.severity),!0)])},[Object(o["renderSlot"])(e.$slots,"default")],2)}var Or=Object(o["defineComponent"])({props:{severity:{type:String,required:!0}}});Or.render=kr;var jr=Or,Dr=wt({component:jr,scope:{severity:{vue:"severity",angularJsBind:"@piwikAlert"}},directiveName:"piwikAlert",transclude:!0}); + */function Lc(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("WidgetLoader");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Nc,[Object(a["createElementVNode"])("div",Tc,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.widgetsByCategory,(function(t){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"dimensionCategory",key:t.name},[Object(a["createTextVNode"])(Object(a["toDisplayString"])(t.name)+" ",1),Object(a["createElementVNode"])("ul",Ac,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(t.widgets,(function(t){return Object(a["openBlock"])(),Object(a["createElementBlock"])("li",{class:Object(a["normalizeClass"])(["reportDimension",{activeDimension:e.selectedWidget.uniqueId===t.uniqueId}]),key:t.uniqueId,onClick:function(n){return e.selectWidget(t)}},[Object(a["createElementVNode"])("span",xc,Object(a["toDisplayString"])(t.name),1)],10,Ic)})),128))])])})),128))]),Object(a["createElementVNode"])("div",Bc,[e.selectedWidget.parameters?(Object(a["openBlock"])(),Object(a["createBlock"])(l,{key:0,"widget-params":e.selectedWidget.parameters,class:"dimensionReport"},null,8,["widget-params"])):Object(a["createCommentVNode"])("",!0)]),Mc])}function Rc(e,t){return Uc(e)||Hc(e,t)||_c(e,t)||Fc()}function Fc(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _c(e,t){if(e){if("string"===typeof e)return $c(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?$c(e,t):void 0}}function $c(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function Hc(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a=[],o=!0,l=!1;try{for(n=n.call(e);!(o=(r=n.next()).done);o=!0)if(a.push(r.value),t&&a.length===t)break}catch(c){l=!0,i=c}finally{try{o||null==n["return"]||n["return"]()}finally{if(l)throw i}}return a}}function Uc(e){if(Array.isArray(e))return e}var qc=Object(a["defineComponent"])({props:{widgets:Array},components:{WidgetLoader:hc},data:function(){return{selectedWidget:null}},created:function(){var e=Rc(this.widgetsSorted,1);this.selectedWidget=e[0]},computed:{widgetsSorted:function(){return Il(this.widgets)},widgetsByCategory:function(){var e={};return this.widgetsSorted.forEach((function(t){var n,r=null===(n=t.subcategory)||void 0===n?void 0:n.name;r&&(e[r]||(e[r]={name:r,order:t.order,widgets:[]}),e[r].widgets.push(t))})),Il(Object.values(e))}},methods:{selectWidget:function(e){this.selectedWidget=Object.assign({},e)}}});qc.render=Lc;var Wc=qc,Jc=(kt({component:Wc,scope:{widgets:{angularJsBind:"=piwikWidgetByDimensionContainer",transform:function(e){return e.widgets}}},directiveName:"piwikWidgetByDimensionContainer"}),["id"]),Gc={key:1},zc={key:2}; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */function Cr(e,t,n){var r=new Date;n||(n=432e4),r.setTime(r.getTime()+n),document.cookie="".concat(e,"=").concat(t,"; expires=").concat(r.toUTCString(),"; path=/")}function Sr(e){var t="; ".concat(document.cookie),n=t.split("; ".concat(e,"="));if(2==n.length){var r=n.pop().split(";").shift();if("undefined"!==typeof r)return r}return null}function Pr(e){var t=new Date;t.setTime(t.getTime()+-864e5),document.cookie="".concat(e,"=; expires=").concat(t.toUTCString(),"; path=/")}var Er={key:0},Tr=["data-notification-instance-id"],xr={key:1},Ir={class:"notification-body"},Nr=["innerHTML"],$r={key:1};function Br(e,t,n,r,a,i){return Object(o["openBlock"])(),Object(o["createBlock"])(o["Transition"],{name:"toast"===e.type?"slow-fade-out":void 0,onAfterLeave:t[1]||(t[1]=function(t){return e.toastClosed()})},{default:Object(o["withCtx"])((function(){return[e.deleted?Object(o["createCommentVNode"])("",!0):(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",Er,[Object(o["createVNode"])(o["Transition"],{name:"toast"===e.type?"toast-slide-up":void 0,appear:""},{default:Object(o["withCtx"])((function(){return[Object(o["createElementVNode"])("div",null,[Object(o["createVNode"])(o["Transition"],{name:e.animate?"fade-in":void 0,appear:""},{default:Object(o["withCtx"])((function(){return[Object(o["createElementVNode"])("div",{class:Object(o["normalizeClass"])(["notification system",e.cssClasses]),style:Object(o["normalizeStyle"])(e.style),ref:"root","data-notification-instance-id":e.notificationInstanceId},[e.canClose?(Object(o["openBlock"])(),Object(o["createElementBlock"])("button",{key:0,type:"button",class:"close","data-dismiss":"alert",onClick:t[0]||(t[0]=function(t){return e.closeNotification(t)})}," × ")):Object(o["createCommentVNode"])("",!0),e.title?(Object(o["openBlock"])(),Object(o["createElementBlock"])("strong",xr,Object(o["toDisplayString"])(e.title),1)):Object(o["createCommentVNode"])("",!0),Object(o["createElementVNode"])("div",Ir,[e.message?(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",{key:0,innerHTML:e.$sanitize(e.message)},null,8,Nr)):Object(o["createCommentVNode"])("",!0),e.message?Object(o["createCommentVNode"])("",!0):(Object(o["openBlock"])(),Object(o["createElementBlock"])("div",$r,[Object(o["renderSlot"])(e.$slots,"default")]))])],14,Tr)]})),_:3},8,["name"])])]})),_:3},8,["name"])]))]})),_:3},8,["name"])}var Hr=window,Ar=Hr.$,Mr=Object(o["defineComponent"])({props:{notificationId:String,notificationInstanceId:String,title:String,context:String,type:String,noclear:Boolean,toastLength:{type:Number,default:12e3},style:[String,Object],animate:Boolean,message:String,cssClass:String},computed:{cssClasses:function(){var e={};return this.context&&(e["notification-".concat(this.context)]=!0),this.cssClass&&(e[this.cssClass]=!0),e},canClose:function(){return"persistent"===this.type||!this.noclear}},emits:["closed"],data:function(){return{deleted:!1}},mounted:function(){var e=this,t=function(){setTimeout((function(){e.deleted=!0}),e.toastLength)};"toast"===this.type&&t(),this.style&&Ar(this.$refs.root).css(this.style)},methods:{toastClosed:function(){var e=this;Object(o["nextTick"])((function(){e.$emit("closed")}))},closeNotification:function(e){var t=this;this.canClose&&e&&e.target&&(this.deleted=!0,Object(o["nextTick"])((function(){t.$emit("closed")}))),this.markNotificationAsRead()},markNotificationAsRead:function(){this.notificationId&&Ne.fetch({module:"CoreHome",action:"markNotificationAsRead"},{postParams:{notificationId:this.notificationId}})}}});Mr.render=Br;var Fr=Mr; + */function Yc(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("WidgetLoader"),c=Object(a["resolveComponent"])("WidgetContainer"),s=Object(a["resolveComponent"])("WidgetByDimensionContainer"),u=Object(a["resolveDirective"])("tooltips");return e.actualWidget?Object(a["withDirectives"])((Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{key:0,class:Object(a["normalizeClass"])(["matomo-widget",{isFirstWidgetInPage:e.actualWidget.isFirstInPage}]),id:e.actualWidget.uniqueId},[!e.actualWidget.isContainer&&e.actualWidget.parameters?(Object(a["openBlock"])(),Object(a["createBlock"])(l,{key:0,"widget-params":e.actualWidget.parameters,"widget-name":e.actualWidget.name},null,8,["widget-params","widget-name"])):Object(a["createCommentVNode"])("",!0),e.actualWidget.isContainer&&"ByDimension"!==e.actualWidget.layout&&!this.preventRecursion?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Gc,[Object(a["createElementVNode"])("div",null,[Object(a["createVNode"])(c,{container:e.actualWidget.widgets},null,8,["container"])])])):Object(a["createCommentVNode"])("",!0),e.actualWidget.isContainer&&"ByDimension"===e.actualWidget.layout?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",zc,[Object(a["createElementVNode"])("div",null,[Object(a["createVNode"])(s,{widgets:e.actualWidget.widgets},null,8,["widgets"])])])):Object(a["createCommentVNode"])("",!0)],10,Jc)),[[a["vShow"],e.showWidget],[u,{content:e.tooltipContent}]]):Object(a["createCommentVNode"])("",!0)}function Qc(e,t){var n=void 0;return Object.values(e||{}).some((function(e){return n=e.find((function(e){var n;return e&&e.isContainer&&(null===(n=e.parameters)||void 0===n?void 0:n.containerId)===t})),n})),n}var Kc=Object(a["defineComponent"])({props:{widget:Object,widgetized:Boolean,containerid:String,preventRecursion:Boolean},components:{WidgetLoader:hc,WidgetContainer:Vc,WidgetByDimensionContainer:Wc},directives:{Tooltips:Rr},data:function(){return{showWidget:!1}},setup:function(){function e(){var e=window.$(this);if(""===e.attr("piwik-field")||e.hasClass("matomo-form-field"))return"";var t=window.$(this).attr("title")||"";return window.vueSanitize(t.replace(/\n/g,"<br />"))}return{tooltipContent:e}},created:function(){var e=this,t=this.actualWidget;if(t&&t.middlewareParameters){var n=t.middlewareParameters;Ze.fetch(n).then((function(t){e.showWidget=!!t}))}else this.showWidget=!0},computed:{allWidgets:function(){return Ql.widgets.value},actualWidget:function(){var e=this,t=this.widget;if(t){var n=Object.assign({},t);if(t&&t.isReport&&!t.documentation){var r=cc.findReport(t.module,t.action);r&&r.documentation&&(n.documentation=r.documentation)}return t}if(this.containerid){var i=Qc(this.allWidgets,this.containerid);if(i){var a=Object.assign({},i);if(this.widgetized){a.isFirstInPage=!0,a.parameters=Object.assign(Object.assign({},a.parameters),{},{widget:"1"});var o=zl(a);o&&(a.widgets=o.map((function(t){return Object.assign(Object.assign({},t),{},{parameters:Object.assign(Object.assign({},t.parameters),{},{widget:"1",containerId:e.containerid})})})))}return a}}return null}}});Kc.render=Yc;var Xc=Kc,Zc=(kt({component:Xc,scope:{widget:{angularJsBind:"=?piwikWidget"},widgetized:{angularJsBind:"=?"},containerid:{angularJsBind:"@"}},directiveName:"piwikWidget"}),{class:"reporting-page"}),es={key:1,class:"col s12 l6 leftWidgetColumn"},ts={key:2,class:"col s12 l6 rightWidgetColumn"}; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */wt({component:Fr,scope:{notificationId:{angularJsBind:"@?"},title:{angularJsBind:"@?notificationTitle"},context:{angularJsBind:"@?"},type:{angularJsBind:"@?"},noclear:{angularJsBind:"@?",transform:function(e){return!!e}},toastLength:{angularJsBind:"@?"}},directiveName:"piwikNotification",transclude:!0});function Vr(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Lr(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?Vr(Object(n),!0).forEach((function(t){Jr(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):Vr(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function Rr(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Ur(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function _r(e,t,n){return t&&Ur(e.prototype,t),n&&Ur(e,n),e}function Jr(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e} + */function ns(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("ActivityIndicator"),c=Object(a["resolveComponent"])("Widget");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Zc,[Object(a["createVNode"])(l,{loading:e.loading},null,8,["loading"]),Object(a["withDirectives"])(Object(a["createElementVNode"])("div",null,Object(a["toDisplayString"])(e.translate("CoreHome_NoSuchPage")),513),[[a["vShow"],e.hasNoPage]]),(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.widgets,(function(e){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",{class:"row",key:e.uniqueId},[e.group?Object(a["createCommentVNode"])("",!0):(Object(a["openBlock"])(),Object(a["createBlock"])(c,{key:0,class:"col s12 fullWidgetColumn",widget:e},null,8,["widget"])),e.group?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",es,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.left,(function(e){return Object(a["openBlock"])(),Object(a["createBlock"])(c,{widget:e,key:e.uniqueId},null,8,["widget"])})),128))])):Object(a["createCommentVNode"])("",!0),e.group?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",ts,[(Object(a["openBlock"])(!0),Object(a["createElementBlock"])(a["Fragment"],null,Object(a["renderList"])(e.right,(function(e){return Object(a["openBlock"])(),Object(a["createBlock"])(c,{widget:e,key:e.uniqueId},null,8,["widget"])})),128))])):Object(a["createCommentVNode"])("",!0)])})),128))])}function rs(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function is(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function as(e,t,n){return t&&is(e.prototype,t),n&&is(e,n),e}function os(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ls(e){return ds(e)||us(e)||ss(e)||cs()}function cs(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ss(e,t){if(e){if("string"===typeof e)return ps(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?ps(e,t):void 0}}function us(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function ds(e){if(Array.isArray(e))return ps(e)}function ps(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r} /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */var Gr=function(){function e(){Rr(this,e),Jr(this,"privateState",Object(o["reactive"])({notifications:[]})),Jr(this,"nextNotificationId",0)}return _r(e,[{key:"state",get:function(){return this.privateState}},{key:"appendNotification",value:function(e){this.checkMessage(e.message),e.id&&this.remove(e.id),this.privateState.notifications.push(e)}},{key:"prependNotification",value:function(e){this.checkMessage(e.message),e.id&&this.remove(e.id),this.privateState.notifications.unshift(e)}},{key:"remove",value:function(e){this.privateState.notifications=this.privateState.notifications.filter((function(t){return t.id!==e}))}},{key:"parseNotificationDivs",value:function(){var e=this,t=$('[data-role="notification"]'),n=[];t.each((function(e,r){var a=$(r),o=a.data(),i=a.html();i&&n.push(Lr(Lr({},o),{},{message:i,animate:!1})),t.remove()})),n.forEach((function(t){return e.show(t)}))}},{key:"clearTransientNotifications",value:function(){this.privateState.notifications=this.privateState.notifications.filter((function(e){return"transient"!==e.type}))}},{key:"show",value:function(e){this.checkMessage(e.message);var t=this.appendNotification,n="#notificationContainer";if(e.placeat)n=e.placeat;else{var r=".modal.open .modal-content";document.querySelector(r)&&(n=r,t=this.prependNotification)}var a=e.group||(e.placeat?e.placeat.toString():"");this.initializeNotificationContainer(n,a);var o=(this.nextNotificationId+=1).toString();return t.call(this,Lr(Lr({},e),{},{noclear:!!e.noclear,group:a,notificationId:e.id,notificationInstanceId:o,type:e.type||"transient"})),o}},{key:"scrollToNotification",value:function(e){setTimeout((function(){var t=document.querySelector("[data-notification-instance-id='".concat(e,"']"));t&&D.helper.lazyScrollTo(t,250)}))}},{key:"toast",value:function(e){this.checkMessage(e.message);var t=$(e.placeat);if(!t.length)throw new Error("A valid selector is required for the placeat option when using Notification.toast().");var n=document.createElement("div");n.style.position="absolute",n.style.top="".concat(t.offset().top,"px"),n.style.left="".concat(t.offset().left,"px"),n.style.zIndex="1000",document.body.appendChild(n);var r=Object(o["createApp"])({render:function(){return Object(o["createVNode"])(Fr,Lr(Lr({},e),{},{notificationId:e.id,type:"toast",onClosed:function(){r.unmount()}}))}});r.config.globalProperties.$sanitize=window.vueSanitize,r.config.globalProperties.translate=C,r.mount(n)}},{key:"initializeNotificationContainer",value:function(e,t){var n=window.$(e);if(!n.children(".notification-group").length){var r=window.CoreHome.NotificationGroup,a=Object(o["createApp"])({template:'<NotificationGroup :group="group"></NotificationGroup>',data:function(){return{group:t}}});a.config.globalProperties.$sanitize=window.vueSanitize,a.config.globalProperties.translate=C,a.component("NotificationGroup",r),a.mount(n[0])}}},{key:"checkMessage",value:function(e){if(!e)throw new Error("No message given, cannot display notification")}}]),e}(),qr=new Gr,zr=qr;$((function(){return qr.parseNotificationDivs()})), + */function ms(e){return!!(e.isContainer&&e.layout&&"ByDimension"===e.layout||"bydimension"===e.viewDataTable)||(!!e.isWide||e.viewDataTable&&("tableAllColumns"===e.viewDataTable||"sparklines"===e.viewDataTable||"graphEvolution"===e.viewDataTable))}function fs(e){if(e&&e[0]){var t=ls(e),n=e[0];return n.group?t[0]=Object.assign(Object.assign({},t[0]),{},{left:fs(n.left||[]),right:fs(n.right||[])}):t[0]=Object.assign(Object.assign({},t[0]),{},{isFirstInPage:!0}),t}return e}var hs=function(){function e(){var t=this;rs(this,e),os(this,"privateState",Object(a["reactive"])({})),os(this,"state",Object(a["computed"])((function(){return Object(a["readonly"])(t.privateState)}))),os(this,"page",Object(a["computed"])((function(){return t.state.value.page}))),os(this,"widgets",Object(a["computed"])((function(){var e=t.page.value;if(!e)return[];var n=[],r={},i=function(e){return e.isReport&&r["".concat(e.module,".").concat(e.action)]},a=function(e){if(!e.isReport)return[];var t=cc.findReport(e.module,e.action);return t&&t.relatedReports?t.relatedReports:[]};if((e.widgets||[]).forEach((function(e){i(e)||(a(e).forEach((function(e){r["".concat(e.module,".").concat(e.action)]=!0})),n.push(e))})),n=Il(n),1===n.length)return fs(n);for(var o=[],l=0;l<n.length;l+=1){var c=n[l];if(ms(c)||n[l+1]&&ms(n[l+1]))o.push(Object.assign(Object.assign({},c),{},{widgets:Il(zl(c))}));else{var s=0,u=[c],d=[];while(n[l+1]&&!ms(n[l+1]))l+=1,s+=1,s%2===0?u.push(n[l]):d.push(n[l]);o.push({group:!0,left:u,right:d})}}var p=fs(o);return p})))}return as(e,[{key:"fetchPage",value:function(e,t){var n=this;return this.resetPage(),Promise.all([El.getAllPages(),cc.fetchReportMetadata()]).then((function(){return n.privateState.page=El.findPage(e,t),n.page.value}))}},{key:"resetPage",value:function(){this.privateState.page=void 0}}]),e}(),gs=new hs;function vs(){var e="category=General_Visitors&subcategory=Live_VisitorLog",t=window.broadcast.buildReportingUrl(e);hl.show({id:"onlyRawData",animate:!1,context:"info",message:C("CoreHome_PeriodHasOnlyRawData",'<a href="'.concat(t,'">'),"</a>"),type:"transient"})}function bs(){hl.remove("onlyRawData")}var ys=Object(a["defineComponent"])({components:{ActivityIndicator:go,Widget:Xc},data:function(){return{loading:!1,hasRawData:!1,hasNoVisits:!1,dateLastChecked:null,hasNoPage:!1}},created:function(){var e=this;gs.resetPage(),this.loading=!0,this.renderInitialPage(),Object(a["watch"])((function(){return Ee.parsed.value}),(function(t,n){t.category===n.category&&t.subcategory===n.subcategory&&t.period===n.period&&t.date===n.date&&t.segment===n.segment&&JSON.stringify(t.compareDates)===JSON.stringify(n.compareDates)&&JSON.stringify(t.comparePeriods)===JSON.stringify(n.comparePeriods)&&JSON.stringify(t.compareSegments)===JSON.stringify(n.compareSegments)&&JSON.stringify(t.columns||"")===JSON.stringify(n.columns||"")||(t.date===n.date&&t.period===n.period||(bs(),e.dateLastChecked=null,e.hasRawData=!1,e.hasNoVisits=!1),e.renderPage(t.category,t.subcategory))})),S.on("loadPage",(function(t,n){e.renderPage(t,n)}))},computed:{widgets:function(){return gs.widgets.value}},methods:{renderPage:function(e,t){var n=this;if(!e||!t)return gs.resetPage(),void(this.loading=!1);var r=Ee.parsed.value,i=r.period,a=r.date;try{p.parse(i,a)}catch(l){return hl.show({id:"invalidDate",animate:!1,context:"error",message:C("CoreHome_DateInvalid"),type:"transient"}),gs.resetPage(),void(this.loading=!1)}hl.remove("invalidDate"),S.postEvent("piwikPageChange",{}),hl.clearTransientNotifications(),p.parse(i,a).containsToday()&&this.showOnlyRawDataMessageIfRequired();var o={category:e,subcategory:t};if(S.postEvent("ReportingPage.loadPage",o),o.promise)return this.loading=!0,void Promise.resolve(o.promise).finally((function(){n.loading=!1}));gs.fetchPage(e,t).then((function(){var t=!gs.page.value;if(t){var r=El.findPageInCategory(e);if(r&&r.subcategory)return void Ee.updateHash(Object.assign(Object.assign({},Ee.hashParsed.value),{},{subcategory:r.subcategory.id}))}n.hasNoPage=t,n.loading=!1}))},renderInitialPage:function(){var e=Ee.parsed.value;this.renderPage(e.category,e.subcategory)},showOnlyRawDataMessageIfRequired:function(){var e=this;this.hasRawData&&this.hasNoVisits&&vs();var t=Ee.parsed.value,n=t.segment;if(n)bs();else{var r=["Live_VisitorLog","General_RealTime","UserCountryMap_RealTimeMap","MediaAnalytics_TypeAudienceLog","MediaAnalytics_TypeRealTime","FormAnalytics_TypeRealTime","Goals_AddNewGoal"],i=["HeatmapSessionRecording_Heatmaps","HeatmapSessionRecording_SessionRecordings","Marketplace_Marketplace"],a=t.subcategory,o=t.category;if(-1===r.indexOf(a)&&-1===i.indexOf(o)&&-1===a.toLowerCase().indexOf("manage")){var l=6e4;this.dateLastChecked&&(new Date).valueOf()-this.dateLastChecked.valueOf()<l||Ze.fetch({method:"VisitsSummary.getVisits"}).then((function(t){return e.dateLastChecked=new Date,t.value>0?(e.hasNoVisits=!1,void bs()):(e.hasNoVisits=!0,e.hasRawData?void vs():Ze.fetch({method:"Live.getLastVisitsDetails",filter_limit:1,doNotFetchActions:1}))})).then((function(t){if(!t||0===t.length)return e.hasRawData=!1,void bs();e.hasRawData=!0,vs()}))}else bs()}}}});ys.render=ns;var ws=ys,Os=(kt({component:ws,directiveName:"piwikReportingPage"}),{class:"report-export-popover row",id:"reportExport"}),js={class:"col l6"},ks={name:"format"},Ss={name:"option_flat"},Cs={name:"option_expanded"},Es={name:"option_format_metrics"},Ds={class:"col l6"},Ps={name:"filter_type"},Vs={class:"filter_limit"},Ns={name:"filter_limit_all"},Ts={key:0,name:"filter_limit"},As={key:1,name:"filter_limit"},Is={class:"col l12"},xs=["value"],Bs=Object(a["createTextVNode"])("\n "),Ms=[Bs],Ls=["innerHTML"],Rs={class:"col l12"},Fs=["href","title"]; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function _s(e,t,n,r,i,o){var l=Object(a["resolveComponent"])("Field"),c=Object(a["resolveDirective"])("select-on-focus");return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Os,[Object(a["createElementVNode"])("div",js,[Object(a["createElementVNode"])("div",ks,[Object(a["createVNode"])(l,{uicontrol:"radio",name:"format",title:e.translate("CoreHome_ExportFormat"),modelValue:e.reportFormat,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.reportFormat=t}),"full-width":!0,options:e.availableReportFormats[e.reportType]},null,8,["title","modelValue","options"])]),Object(a["createElementVNode"])("div",null,[Object(a["createElementVNode"])("div",Ss,[Object(a["withDirectives"])(Object(a["createVNode"])(l,{uicontrol:"checkbox",name:"option_flat",title:e.translate("CoreHome_FlattenReport"),modelValue:e.optionFlat,"onUpdate:modelValue":t[1]||(t[1]=function(t){return e.optionFlat=t})},null,8,["title","modelValue"]),[[a["vShow"],e.hasSubtables]])])]),Object(a["createElementVNode"])("div",null,[Object(a["createElementVNode"])("div",Cs,[Object(a["withDirectives"])(Object(a["createVNode"])(l,{uicontrol:"checkbox",name:"option_expanded",title:e.translate("CoreHome_ExpandSubtables"),modelValue:e.optionExpanded,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.optionExpanded=t})},null,8,["title","modelValue"]),[[a["vShow"],e.hasSubtables&&!e.optionFlat]])])]),Object(a["createElementVNode"])("div",null,[Object(a["createElementVNode"])("div",Es,[Object(a["createVNode"])(l,{uicontrol:"checkbox",name:"option_format_metrics",title:e.translate("CoreHome_FormatMetrics"),modelValue:e.optionFormatMetrics,"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.optionFormatMetrics=t})},null,8,["title","modelValue"])])])]),Object(a["createElementVNode"])("div",Ds,[Object(a["createElementVNode"])("div",null,[Object(a["createElementVNode"])("div",Ps,[Object(a["createVNode"])(l,{uicontrol:"radio",name:"filter_type",title:e.translate("CoreHome_ReportType"),modelValue:e.reportType,"onUpdate:modelValue":t[4]||(t[4]=function(t){return e.reportType=t}),"full-width":!0,options:e.availableReportTypes},null,8,["title","modelValue","options"])])]),Object(a["createElementVNode"])("div",Vs,[Object(a["withDirectives"])(Object(a["createElementVNode"])("div",Ns,[Object(a["createVNode"])(l,{uicontrol:"radio",name:"filter_limit_all",title:e.translate("CoreHome_RowLimit"),modelValue:e.reportLimitAll,"onUpdate:modelValue":t[5]||(t[5]=function(t){return e.reportLimitAll=t}),"full-width":!0,options:e.limitAllOptions},null,8,["title","modelValue","options"])],512),[[a["vShow"],!e.maxFilterLimit||e.maxFilterLimit<=0]]),"no"===e.reportLimitAll&&e.maxFilterLimit<=0?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",Ts,[Object(a["createVNode"])(l,{uicontrol:"number",name:"filter_limit",min:1,modelValue:e.reportLimit,"onUpdate:modelValue":t[6]||(t[6]=function(t){return e.reportLimit=t}),"full-width":!0},null,8,["modelValue"])])):Object(a["createCommentVNode"])("",!0),"no"===e.reportLimitAll&&e.maxFilterLimit>0?(Object(a["openBlock"])(),Object(a["createElementBlock"])("div",As,[Object(a["createVNode"])(l,{uicontrol:"number",name:"filter_limit",min:1,max:e.maxFilterLimit,modelValue:e.reportLimit,"onUpdate:modelValue":t[7]||(t[7]=function(t){return e.reportLimit=t}),value:e.reportLimit,"full-width":!0,title:e.filterLimitTooltip},null,8,["max","modelValue","value","title"])])):Object(a["createCommentVNode"])("",!0)])]),Object(a["withDirectives"])(Object(a["createElementVNode"])("div",Is,[Object(a["withDirectives"])(Object(a["createElementVNode"])("textarea",{readonly:"",class:"exportFullUrl",value:e.exportLinkWithoutToken},Ms,8,xs),[[c,{}]]),Object(a["createElementVNode"])("div",{class:"tooltip",innerHTML:e.$sanitize(e.translate("CoreHome_ExportTooltipWithLink","<a target=_blank href='?module=UsersManager&action=userSecurity'>","</a>","ENTER_YOUR_TOKEN_AUTH_HERE"))},null,8,Ls)],512),[[a["vShow"],e.showUrl]]),Object(a["createElementVNode"])("div",Rs,[Object(a["createElementVNode"])("a",{class:"btn",href:e.exportLink,target:"_new",title:e.translate("CoreHome_ExportTooltip")},Object(a["toDisplayString"])(e.translate("General_Export")),9,Fs),Object(a["createElementVNode"])("a",{href:"javascript:",onClick:t[8]||(t[8]=function(t){return e.showUrl=!e.showUrl}),class:"toggle-export-url"},[Object(a["withDirectives"])(Object(a["createElementVNode"])("span",null,Object(a["toDisplayString"])(e.translate("CoreHome_ShowExportUrl")),513),[[a["vShow"],!e.showUrl]]),Object(a["withDirectives"])(Object(a["createElementVNode"])("span",null,Object(a["toDisplayString"])(e.translate("CoreHome_HideExportUrl")),513),[[a["vShow"],e.showUrl]])])])])}function $s(e,t){return Js(e)||Ws(e,t)||Us(e,t)||Hs()}function Hs(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function Us(e,t){if(e){if("string"===typeof e)return qs(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?qs(e,t):void 0}}function qs(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n<t;n++)r[n]=e[n];return r}function Ws(e,t){var n=null==e?null:"undefined"!==typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,i,a=[],o=!0,l=!1;try{for(n=n.call(e);!(o=(r=n.next()).done);o=!0)if(a.push(r.value),t&&a.length===t)break}catch(c){l=!0,i=c}finally{try{o||null==n["return"]||n["return"]()}finally{if(l)throw i}}return a}}function Js(e){if(Array.isArray(e))return e}var Gs=$n("CorePluginsAdmin","Field"),zs=Object(a["defineComponent"])({components:{Field:Gs},directives:{SelectOnFocus:vn},props:{hasSubtables:Boolean,availableReportTypes:Object,availableReportFormats:{type:Object,required:!0},maxFilterLimit:Number,limitAllOptions:Object,dataTable:{type:Object,required:!0},requestParams:[Object,String],apiMethod:{type:String,required:!0},initialReportType:{type:String,default:"default"},initialReportLimit:{type:[String,Number],default:100},initialReportLimitAll:{type:String,default:"yes"},initialOptionFlat:{type:Boolean,default:!1},initialOptionExpanded:{type:Boolean,default:!0},initialOptionFormatMetrics:{type:Boolean,default:!1},initialReportFormat:{type:String,default:"XML"}},data:function(){return{showUrl:!1,reportFormat:this.initialReportFormat,optionFlat:this.initialOptionFlat,optionExpanded:this.initialOptionExpanded,optionFormatMetrics:this.initialOptionFormatMetrics,reportType:this.initialReportType,reportLimitAll:this.initialReportLimitAll,reportLimit:"string"===typeof this.initialReportLimit?parseInt(this.initialReportLimit,10):this.initialReportLimit}},watch:{reportType:function(e){this.availableReportFormats[e][this.reportFormat]||(this.reportFormat="XML")},reportLimit:function(e,t){this.maxFilterLimit&&this.maxFilterLimit>0&&e>this.maxFilterLimit&&(this.reportLimit=t)}},computed:{filterLimitTooltip:function(){var e=C("CoreHome_RowLimit"),t=this.maxFilterLimit?C("General_ComputedMetricMax",this.maxFilterLimit.toString()):"";return"".concat(e," (").concat(t,")")},exportLink:function(){return this.getExportLink(!0)},exportLinkWithoutToken:function(){return this.getExportLink(!1)}},methods:{getExportLink:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=this.reportFormat,n=this.apiMethod,r=this.reportType,i=this.dataTable;if(t){var a={},o="yes"===this.reportLimitAll?-1:this.reportLimit;this.requestParams&&"string"===typeof this.requestParams&&(a=JSON.parse(this.requestParams));var l=i.param,c=l.segment,s=l.label,u=l.idGoal,d=l.idDimension,p=l.idSite,m=i.param,f=m.date,h=m.period;"RSS"===t&&(f="last10"),"undefined"!==typeof i.param.dateUsedInGraph&&(f=i.param.dateUsedInGraph);var g=S.config.datatable_export_range_as_day.toLowerCase();-1!==g.indexOf(t.toLowerCase())&&"range"===i.param.period&&(h="day"),"range"===i.param.period&&"graphEvolution"===i.param.viewDataTable&&(h="day");var v={module:"API",format:t,idSite:p,period:h,date:f};if("processed"===r){v.method="API.getProcessedReport";var b=n.split("."),y=$s(b,2);v.apiModule=y[0],v.apiAction=y[1]}else v.method=n;if(i.param.compareDates&&i.param.compareDates.length&&(v.compareDates=i.param.compareDates,v.compare="1"),i.param.comparePeriods&&i.param.comparePeriods.length&&(v.comparePeriods=i.param.comparePeriods,v.compare="1"),i.param.compareSegments&&i.param.compareSegments.length&&(v.compareSegments=i.param.compareSegments,v.compare="1"),"undefined"!==typeof i.param.filter_pattern&&(v.filter_pattern=i.param.filter_pattern),"undefined"!==typeof i.param.filter_pattern_recursive&&(v.filter_pattern_recursive=i.param.filter_pattern_recursive),window.$.isPlainObject(a)&&Object.entries(a).forEach((function(e){var t=$s(e,2),n=t[0],r=t[1],i=r;!0===i?i=1:!1===i&&(i=0),v[n]=i})),this.optionFlat&&(v.flat=1,"undefined"!==typeof i.param.include_aggregate_rows&&"1"===i.param.include_aggregate_rows&&(v.include_aggregate_rows=1)),!this.optionFlat&&this.optionExpanded&&(v.expanded=1),this.optionFormatMetrics&&(v.format_metrics=1),i.param.pivotBy&&(v.pivotBy=i.param.pivotBy,v.pivotByColumnLimit=20,i.props.pivot_by_column&&(v.pivotByColumn=i.props.pivot_by_column)),"CSV"!==t&&"TSV"!==t&&"RSS"!==t||(v.translateColumnNames=1,v.language=S.language),"undefined"!==typeof c&&(v.segment=decodeURIComponent(c)),"undefined"!==typeof u&&"-1"!==u&&(v.idGoal=u),"undefined"!==typeof d&&"-1"!==d&&(v.idDimension=d),s){var w=s.split(",");if(w.length>1)v.label=w;else{var O=$s(w,1);v.label=O[0]}}v.token_auth="ENTER_YOUR_TOKEN_AUTH_HERE",!0===e&&(v.token_auth=S.token_auth,v.force_api_session=1),v.filter_limit=o;var j=window.location.href.split("?")[0];return"".concat(j,"?").concat(Ee.stringify(v))}}}});zs.render=_s;var Ys=zs,Qs=window,Ks=Qs.$,Xs={mounted:function(e,t){e.addEventListener("click",(function(){var n=Ee.hashParsed.value.popover,r=Ks(e).closest("[data-report]").data("uiControlObject"),i=window.Piwik_Popover.showLoading("Export"),a=t.value.reportFormats,o=r.param.filter_limit;t.value.maxFilterLimit>0&&(o=Math.min(o,t.value.maxFilterLimit));var l=!0===r.param.flat||1===r.param.flat||"1"===r.param.flat,c={initialReportType:"default",initialReportLimit:o>0?o:100,initialReportLimitAll:-1===o?"yes":"no",initialOptionFlat:l,initialOptionExpanded:!0,initialOptionFormatMetrics:!1,hasSubtables:l||r.numberOfSubtables>0,availableReportFormats:{default:a,processed:{XML:a.XML,JSON:a.JSON}},availableReportTypes:{default:C("CoreHome_StandardReport"),processed:C("CoreHome_ReportWithMetadata")},limitAllOptions:{yes:C("General_All"),no:C("CoreHome_CustomLimit")},maxFilterLimit:t.value.maxFilterLimit,dataTable:r,requestParams:t.value.requestParams,apiMethod:t.value.apiMethod},s=dt({template:'\n <popover v-bind="bind"/>',data:function(){return{bind:c}}});s.component("popover",Ys);var u=document.createElement("div");s.mount(u);var d=t.value.reportTitle;window.Piwik_Popover.setTitle("".concat(C("General_Export")," ").concat(S.helper.htmlEntities(d))),window.Piwik_Popover.setContent(u),window.Piwik_Popover.onClose((function(){s.unmount(),""!==n&&setTimeout((function(){Ee.updateHash(Object.assign(Object.assign({},Ee.hashParsed.value),{},{popover:n})),t.value.onClose&&t.value.onClose()}),100)})),setTimeout((function(){i.dialog(),Ks(".exportFullUrl, .btn",i).tooltip({track:!0,show:!1,hide:!1})}),100)}))}}; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -angular.module("piwikApp").factory("notifications",(function(){return zr}));var Qr={class:"notification-group"},Yr=["innerHTML"];function Wr(e,t,n,r,a,i){var c=Object(o["resolveComponent"])("Notification");return Object(o["openBlock"])(),Object(o["createElementBlock"])("div",Qr,[(Object(o["openBlock"])(!0),Object(o["createElementBlock"])(o["Fragment"],null,Object(o["renderList"])(e.notifications,(function(t,n){return Object(o["openBlock"])(),Object(o["createBlock"])(c,{key:t.id||"no-id-".concat(n),"notification-id":t.id,title:t.title,context:t.context,type:t.type,noclear:t.noclear,"toast-length":t.toastLength,style:Object(o["normalizeStyle"])(t.style),animate:t.animate,message:t.message,"notification-instance-id":t.notificationInstanceId,"css-class":t.class,onClosed:function(n){return e.removeNotification(t.id)}},{default:Object(o["withCtx"])((function(){return[Object(o["createElementVNode"])("div",{innerHTML:e.$sanitize(t.message)},null,8,Yr)]})),_:2},1032,["notification-id","title","context","type","noclear","toast-length","style","animate","message","notification-instance-id","css-class","onClosed"])})),128))])}var Kr=Object(o["defineComponent"])({props:{group:String},components:{Notification:Fr},computed:{notifications:function(){var e=this;return zr.state.notifications.filter((function(t){return e.group?e.group===t.group:!t.group}))}},methods:{removeNotification:function(e){zr.remove(e)}}});Kr.render=Wr;var Xr=Kr; /*! * Matomo - free/libre analytics platform * * @link https://matomo.org * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ +function Zs(e){return{restrict:"A",scope:{reportTitle:"@",requestParams:"@",reportFormats:"@",apiMethod:"@",maxFilterLimit:"@"},link:function(t,n){var r={instance:null,value:{reportTitle:t.reportTitle,requestParams:t.requestParams,reportFormats:"string"===typeof t.reportFormats?JSON.parse(t.reportFormats):t.reportFormats,apiMethod:t.apiMethod,maxFilterLimit:parseInt(t.maxFilterLimit,10),onClose:function(){e((function(){window.angular.element(document).injector().get("$rootScope").$apply()}),10)}},oldValue:null,modifiers:{},dir:{}};Xs.mounted(n[0],r)}}}Zs.$inject=["$timeout"],window.angular.module("piwikApp").directive("piwikReportExport",Zs);var eu=["src"];function tu(e,t,n,r,i,o){return Object(a["openBlock"])(),Object(a["createElementBlock"])("img",{src:e.sparklineUrl},null,8,eu)}var nu=Object(a["defineComponent"])({props:{seriesIndices:Array,params:Object},data:function(){return{isWidget:!1}},mounted:function(){this.isWidget=!!this.$el.closest("[widgetId]")},computed:{sparklineUrl:function(){var e=this.seriesIndices,t=this.params,n=S.getSparklineColors();e&&(n.lineColor=n.lineColor.filter((function(t,n){return-1!==e.indexOf(n)})));var r=JSON.stringify(n),i={forceView:"1",viewDataTable:"sparkline",widget:this.isWidget?"1":"0",showtitle:"1",colors:r,random:Date.now(),date:this.defaultDate},a=new Ze,o=a.mixinDefaultGetParams(Object.assign(Object.assign({},i),t)),l=Ee.parsed.value.token_auth;return l&&l.length&&S.shouldPropagateTokenAuth&&(o.token_auth=l),"?".concat(Ee.stringify(o))},defaultDate:function(){if("range"===S.period)return"".concat(S.startDateString,",").concat(S.endDateString);var e=H.getLastNRange(S.period,30,S.currentDateString).getDateRange(),t=new Date(S.minDateYear,S.minDateMonth-1,S.minDateDay);e[0]<t&&(e[0]=t);var n=D(e[0]),r=D(e[1]);return"".concat(n,",").concat(r)}}});nu.render=tu;var ru=nu,iu=(kt({component:ru,scope:{seriesIndices:{angularJsBind:"<"},params:{angularJsBind:"<"}},directiveName:"piwikSparkline",restrict:"E"}),{class:"progressbar"}),au={class:"progress"},ou=Object(a["createElementVNode"])("img",{src:"plugins/Morpheus/images/loading-blue.gif",style:{"margin-right":"3.5px"}},null,-1),lu=["innerHTML"]; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function cu(e,t,n,r,i,o){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",iu,[Object(a["createElementVNode"])("div",au,[Object(a["createElementVNode"])("div",{class:"determinate",style:Object(a["normalizeStyle"])([{width:"0"},{width:"".concat(e.actualProgress,"%")}])},null,4)]),Object(a["withDirectives"])(Object(a["createElementVNode"])("span",null,[ou,Object(a["createElementVNode"])("span",{class:"label",innerHTML:e.$sanitize(e.label)},null,8,lu)],512),[[a["vShow"],!!e.label]])])}var su=Object(a["defineComponent"])({props:{progress:{type:Number,required:!0},label:String},computed:{actualProgress:function(){return this.progress>100?100:this.progress<0?0:this.progress}}});su.render=cu;var uu=su,du=(kt({component:uu,scope:{progress:{angularJsBind:"="},label:{angularJsBind:"="}},directiveName:"piwikProgressbar"}),{mounted:function(e){e.classList.add("piwik-content-intro")},updated:function(e){Object(a["nextTick"])((function(){e.classList.add("piwik-content-intro")}))}}); +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function pu(){return{restrict:"A",link:function(e,t){du.mounted(t[0])}}}window.angular.module("piwikApp").directive("piwikContentIntro",pu); +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */var mu={mounted:function(e){e.classList.add("card","card-table","entityTable")},updated:function(e){Object(a["nextTick"])((function(){e.classList.add("card","card-table","entityTable")}))}}; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function fu(){return{restrict:"A",link:function(e,t){mu.mounted(t[0])}}}window.angular.module("piwikApp").directive("piwikContentTable",fu);var hu={ref:"root"};function gu(e,t,n,r,i,o){return Object(a["openBlock"])(),Object(a["createElementBlock"])("div",hu,[Object(a["renderSlot"])(e.$slots,"default",{formData:e.formData,submitApiMethod:e.submitApiMethod,sendJsonPayload:e.sendJsonPayload,noErrorNotification:e.noErrorNotification,noSuccessNotification:e.noSuccessNotification,submitForm:e.submitForm,isSubmitting:e.isSubmitting,successfulPostResponse:e.successfulPostResponse,errorPostResponse:e.errorPostResponse})],512)}var vu=window,bu=vu.$,yu=Object(a["defineComponent"])({props:{formData:{type:Object,required:!0},submitApiMethod:{type:String,required:!0},sendJsonPayload:Boolean,noErrorNotification:Boolean,noSuccessNotification:Boolean},data:function(){return{isSubmitting:!1,successfulPostResponse:null,errorPostResponse:null}},emits:["update:modelValue"],mounted:function(){var e=this;bu(this.$refs.root).on("click","input[type=submit]",(function(){e.submitForm()}))},methods:{submitForm:function(){var e=this;this.successfulPostResponse=null,this.errorPostResponse=null;var t=this.formData;this.sendJsonPayload&&(t={data:JSON.stringify(this.formData)}),this.isSubmitting=!0,Ze.post({module:"API",method:this.submitApiMethod},t,{createErrorNotification:!this.noErrorNotification}).then((function(t){if(e.successfulPostResponse=t,!e.noSuccessNotification){var n=hl.show({message:C("General_YourChangesHaveBeenSaved"),context:"success",type:"toast",id:"ajaxHelper"});hl.scrollToNotification(n)}})).catch((function(t){e.errorPostResponse=t.message})).finally((function(){e.isSubmitting=!1}))}}});yu.render=gu;var wu=yu,Ou=window,ju=Ou.$; +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */function ku(e){return{restrict:"A",scope:{submitApiMethod:"=",sendJsonPayload:"=",noErrorNotification:"=",noSuccessNotification:"=",useCustomDataBinding:"="},require:"?ngModel",transclude:!0,compile:function(t,n){return n.noErrorNotification=!!n.noErrorNotification,function(t,n,r,i,o){if(!t.submitApiMethod)throw new Error("submitApiMethod is required");if(t.ajaxForm={},t.ajaxForm.submitApiMethod=t.submitApiMethod,t.ajaxForm.sendJsonPayload=t.sendJsonPayload,t.ajaxForm.noErrorNotification=t.noErrorNotification,t.ajaxForm.noSuccessNotification=t.noSuccessNotification,t.ajaxForm.data={},i){var l=e(r.ngModel);t.ajaxForm.data=l(t.$parent)}var c={mounted:function(e,n){t.ajaxForm.submitForm=n.value.submitForm}},s='\n <AjaxForm\n :form-data="data"\n :submit-api-method="submitApiMethod"\n :send-json-payload="sendJsonPayload"\n :no-error-notification="noErrorNotification"\n :no-success-notification="noSuccessNotification"\n >\n <template v-slot:default="ajaxFormVue">\n <div\n ref="transcludeTarget"\n v-special-bind-directive="{ submitForm: ajaxFormVue.submitForm }"\n />\n </template>\n </AjaxForm>',u=dt({template:s,data:function(){return t.ajaxForm},setup:function(){var e=Object(a["ref"])(null);return{transcludeTarget:e}}});u.component("AjaxForm",wu),u.directive("SpecialBindDirective",c);var d=u.mount(n[0]);function p(e,n){var r,i=ju(e).attr("name");r="checkbox"===ju(e).attr("type")?ju(e).is(":checked"):ju(e).val(),t.ajaxForm.data[i]=r,n||setTimeout((function(){t.$apply()}),0)}n.on("$destroy",(function(){u.unmount()})),t.useCustomDataBinding||n.on("change","input,select",(function(e){p(e.target)})),o(t,(function(e,t){if(!t.useCustomDataBinding){var n=e.find("input,select").not("[type=submit]");n.each((function(){p(this,!0)}))}ju(d.transcludeTarget).append(e)}))}}}} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +function Su(e,t){var n,r=parseInt(t,10),i=parseInt(e,10)-r;return n=0===i||Number.isNaN(i)?0:0===r||Number.isNaN(r)?100:i/r*100,n}function Cu(e){return"".concat(e>0?S.numbers.symbolPlus:"").concat(Math.round(e),"}%")}function Eu(e,t){var n=Su(e,t);return Cu(n)} +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ku.$inject=["$parse"],window.angular.module("piwikApp").directive("piwikAjaxForm",ku);var Du=kt({component:go,scope:{loading:{vue:"loading",angularJsBind:"<"},loadingMessage:{vue:"loadingMessage",angularJsBind:"<",default:function(){return C("General_LoadingData")}}},$inject:[],directiveName:"piwikActivityIndicator"});function Pu(e,t,n){var r=new Date;n||(n=432e4),r.setTime(r.getTime()+n),document.cookie="".concat(e,"=").concat(t,"; expires=").concat(r.toUTCString(),"; path=/")}function Vu(e){var t="; ".concat(document.cookie),n=t.split("; ".concat(e,"="));if(2==n.length){var r=n.pop().split(";").shift();if("undefined"!==typeof r)return r}return null}function Nu(e){var t=new Date;t.setTime(t.getTime()+-864e5),document.cookie="".concat(e,"=; expires=").concat(t.toUTCString(),"; path=/")} /*! * Matomo - free/libre analytics platform * diff --git a/plugins/CoreHome/vue/dist/umd.metadata.json b/plugins/CoreHome/vue/dist/umd.metadata.json new file mode 100644 index 0000000000..c63babfe11 --- /dev/null +++ b/plugins/CoreHome/vue/dist/umd.metadata.json @@ -0,0 +1,3 @@ +{ + "dependsOn": [] +}
\ No newline at end of file diff --git a/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts b/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts index 84cb965fc6..614d128056 100644 --- a/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts +++ b/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts @@ -6,7 +6,7 @@ */ import ActivityIndicator from './ActivityIndicator.vue'; -import translate from '../translate'; +import { translate } from '../translate'; import createAngularJsAdapter from '../createAngularJsAdapter'; export default createAngularJsAdapter({ diff --git a/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue b/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue index a5f27080dc..ea3daf5ddb 100644 --- a/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue +++ b/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue @@ -14,7 +14,7 @@ <script lang="ts"> import { defineComponent } from 'vue'; -import translate from '../translate'; +import { translate } from '../translate'; export default defineComponent({ props: { diff --git a/plugins/CoreHome/vue/src/AjaxForm/AjaxForm.adapter.ts b/plugins/CoreHome/vue/src/AjaxForm/AjaxForm.adapter.ts new file mode 100644 index 0000000000..a998f1403b --- /dev/null +++ b/plugins/CoreHome/vue/src/AjaxForm/AjaxForm.adapter.ts @@ -0,0 +1,193 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { DirectiveBinding, ref } from 'vue'; +import { IDirective, IDirectiveLinkFn, IParseService } from 'angular'; +import createVueApp from '../createVueApp'; +import AjaxForm from './AjaxForm.vue'; + +const { $ } = window; + +/** + * AngularJS directive that manages an AJAX form. + * + * This directive will detect inputs & selects defined within an element and when a + * submit button is clicked, will post data from the inputs & selects to a Piwik API method. + * + * When the POST request is finished the result will, by default, be displayed as a + * notification. + * + * This directive accepts the following attributes: + * + * - **submit-api-method**: **required** The Piwik API method that handles the POST request. + * - **send-json-payload**: Whether to send the data as a form encoded URL or to send it as JSON. + * If sending as JSON, the payload will still be a form encoded value, + * but will contain a JSON object like `{data: {...form data...}}`. + * + * This is for forms with lots of fields where having the same number + * of parameters in an API method would not be desired. + * - **no-error-notification**: If true, does not display an error notification if the AJAX post + * fails. + * - **no-success-notification**: If true, does not display an error notification if the AJAX + * results in success. + * + * **Custom Success/Error Handling** + * + * On success/failure, the response will be stored in controller scope. Child elements of a + * piwik-ajax-form element can access this data, and thus, can customize what happens when + * a form submit succeeds/fails. + * + * See the ajax-form.controller.js file for more info. + * + * Usage: + * + * <div piwik-ajax-form + * submit-api-method="'MyPlugin.myFormSaveMethod'" + * send-json-payload="true" + * ng-model="myFormData"> + * + * <h2>My Form</h2> + * <input name="myOption" value="myDefaultValue" type="text" /> + * <input name="myOtherOption" type="checkbox" checked="checked" /> + * <input type="submit" value="Submit" ng-disabled="ajaxForm.isSubmitting" /> + * + * <div piwik-notification context='error' ng-show="errorPostResponse">ERROR!</div> + * </div> + * @deprecated + */ + +function piwikAjaxForm($parse: IParseService): IDirective { + return { + restrict: 'A', + scope: { + submitApiMethod: '=', + sendJsonPayload: '=', + noErrorNotification: '=', + noSuccessNotification: '=', + useCustomDataBinding: '=', + }, + require: '?ngModel', + transclude: true, + compile: function piwikAjaxFormCompile(compileElement, compileAttrs): IDirectiveLinkFn { + compileAttrs.noErrorNotification = !!compileAttrs.noErrorNotification; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return function piwikAjaxFormLink(scope: any, element, attrs, ngModel, transclude) { + if (!scope.submitApiMethod) { + throw new Error('submitApiMethod is required'); + } + + scope.ajaxForm = {}; + scope.ajaxForm.submitApiMethod = scope.submitApiMethod; + scope.ajaxForm.sendJsonPayload = scope.sendJsonPayload; + scope.ajaxForm.noErrorNotification = scope.noErrorNotification; + scope.ajaxForm.noSuccessNotification = scope.noSuccessNotification; + + scope.ajaxForm.data = {}; + + // if a model is supplied, initiate form data w/ model value + if (ngModel) { + // probably redundant, but I cannot find another way to get the ng model value here + const ngModelGetter = $parse(attrs.ngModel); + scope.ajaxForm.data = ngModelGetter(scope.$parent); + } + + interface SpecialDirectiveBinding { + submitForm: () => void; + } + + const specialBindDirective = { + mounted(el: HTMLElement, binding: DirectiveBinding<SpecialDirectiveBinding>) { + scope.ajaxForm.submitForm = binding.value.submitForm; + }, + }; + + const rootTemplate = ` + <AjaxForm + :form-data="data" + :submit-api-method="submitApiMethod" + :send-json-payload="sendJsonPayload" + :no-error-notification="noErrorNotification" + :no-success-notification="noSuccessNotification" + > + <template v-slot:default="ajaxFormVue"> + <div + ref="transcludeTarget" + v-special-bind-directive="{ submitForm: ajaxFormVue.submitForm }" + /> + </template> + </AjaxForm>`; + + const app = createVueApp({ + template: rootTemplate, + data() { + return scope.ajaxForm; + }, + setup() { + const transcludeTarget = ref(null); + return { + transcludeTarget, + }; + }, + }); + app.component('AjaxForm', AjaxForm); + app.directive('SpecialBindDirective', specialBindDirective); + const vm = app.mount(element[0]); + + element.on('$destroy', () => { + app.unmount(); + }); + + function setFormValueFromInput(inputElement: HTMLElement, skipScopeApply?: boolean) { + const name = $(inputElement).attr('name')!; + let val; + + if ($(inputElement).attr('type') === 'checkbox') { + val = $(inputElement).is(':checked'); + } else { + val = $(inputElement).val(); + } + + scope.ajaxForm.data[name] = val; + + if (!skipScopeApply) { + setTimeout(() => { + scope.$apply(); + }, 0); + } + } + + // on change of any input, change appropriate value in model, but only if requested + if (!scope.useCustomDataBinding) { + element.on('change', 'input,select', (event) => { + setFormValueFromInput(event.target as HTMLElement); + }); + } + + // make sure child elements can access this directive's scope + // eslint-disable-next-line @typescript-eslint/no-explicit-any + transclude!(scope, (clone, transcludeScope: any) => { + if (!transcludeScope.useCustomDataBinding) { + const $inputs = clone!.find('input,select').not('[type=submit]'); + + // initialize form data to input values (include <select>s + $inputs.each(function inputEach() { + setFormValueFromInput(this, true); + }); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + $((vm as any).transcludeTarget as HTMLElement).append(clone!); + }); + }; + }, + }; +} + +piwikAjaxForm.$inject = ['$parse']; + +window.angular.module('piwikApp').directive('piwikAjaxForm', piwikAjaxForm); diff --git a/plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue b/plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue new file mode 100644 index 0000000000..2a84ef2559 --- /dev/null +++ b/plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue @@ -0,0 +1,113 @@ +<!-- + Matomo - free/libre analytics platform + + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div ref="root"> + <slot + :form-data="formData" + :submit-api-method="submitApiMethod" + :send-json-payload="sendJsonPayload" + :no-error-notification="noErrorNotification" + :no-success-notification="noSuccessNotification" + :submit-form="submitForm" + :is-submitting="isSubmitting" + :successful-post-response="successfulPostResponse" + :error-post-response="errorPostResponse" + ></slot> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import { translate } from '../translate'; +import AjaxHelper from '../AjaxHelper/AjaxHelper'; +import { NotificationsStore } from '../Notification'; + +const { $ } = window; + +/** + * Example usage: + * + * <AjaxForm :form-data="myData" ...> + * <template v-slot:default="ajaxForm"> + * <Field v-model="myData.something" .../> + * <SaveButton @confirm="ajaxForm.submitForm()" :saving="ajaxForm.isSubmitting"/> + * </template> + * </AjaxForm> + * + * Data does not flow upwards in any way. :form-data is used for submitForm(), and the + * containing component binds to properties of the object in controls to fill the object. + */ +export default defineComponent({ + props: { + formData: { + type: Object, + required: true, + }, + submitApiMethod: { + type: String, + required: true, + }, + sendJsonPayload: Boolean, + noErrorNotification: Boolean, + noSuccessNotification: Boolean, + }, + data() { + return { + isSubmitting: false, + successfulPostResponse: null, + errorPostResponse: null, + }; + }, + emits: ['update:modelValue'], + mounted() { + // on submit call controller submit method + $(this.$refs.root as HTMLElement).on('click', 'input[type=submit]', () => { + this.submitForm(); + }); + }, + methods: { + submitForm() { + this.successfulPostResponse = null; + this.errorPostResponse = null; + + let postParams = this.formData; + if (this.sendJsonPayload) { + postParams = { data: JSON.stringify(this.formData) }; + } + + this.isSubmitting = true; + AjaxHelper.post( + { + module: 'API', + method: this.submitApiMethod, + }, + postParams, + { + createErrorNotification: !this.noErrorNotification, + }, + ).then((response) => { + this.successfulPostResponse = response; + + if (!this.noSuccessNotification) { + const notificationInstanceId = NotificationsStore.show({ + message: translate('General_YourChangesHaveBeenSaved'), + context: 'success', + type: 'toast', + id: 'ajaxHelper', + }); + NotificationsStore.scrollToNotification(notificationInstanceId); + } + }).catch((error) => { + this.errorPostResponse = error.message; + }).finally(() => { + this.isSubmitting = false; + }); + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.adapter.ts b/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.adapter.ts index c960a42130..59bc1db685 100644 --- a/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.adapter.ts +++ b/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.adapter.ts @@ -2,14 +2,14 @@ import AjaxHelper from './AjaxHelper'; declare global { interface Window { - ajaxHelper: AjaxHelper; + ajaxHelper: typeof AjaxHelper; } } window.ajaxHelper = AjaxHelper; function ajaxQueue() { - return globalAjaxQueue; + return window.globalAjaxQueue; } -angular.module('piwikApp.service').service('globalAjaxQueue', ajaxQueue); +window.angular.module('piwikApp.service').service('globalAjaxQueue', ajaxQueue); diff --git a/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts b/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts index f128ae6c32..61a3aa7c09 100644 --- a/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts +++ b/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts @@ -5,13 +5,28 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ +/* eslint-disable max-classes-per-file */ + +import { ITimeoutService } from 'angular'; import jqXHR = JQuery.jqXHR; import MatomoUrl from '../MatomoUrl/MatomoUrl'; import Matomo from '../Matomo/Matomo'; -interface AjaxOptions { +export interface AjaxOptions { withTokenInUrl?: boolean; postParams?: QueryParameters; + headers?: Record<string, string>; + format?: string; + createErrorNotification?: boolean; + abortController?: AbortController; + returnResponseObject?: boolean; + errorElement?: HTMLElement|JQuery|JQLite|string; + redirectOnSuccess?: QueryParameters|boolean; +} + +interface ErrorResponse { + result: string; + message: string; } window.globalAjaxQueue = [] as unknown as GlobalAjaxQueue; @@ -71,6 +86,8 @@ function defaultErrorCallback(deferred: XMLHttpRequest, status: string): void { } } +class ApiResponseError extends Error {} + /** * Global ajax helper to handle requests within Matomo */ @@ -100,7 +117,7 @@ export default class AjaxHelper<T = any> { // eslint-disable-line * * @deprecated use the jquery promise API */ - errorCallback: AnyFunction; + errorCallback: AnyFunction|null; withToken = false; @@ -146,24 +163,139 @@ export default class AjaxHelper<T = any> { // eslint-disable-line errorElement: HTMLElement|JQuery|JQLite|string = '#ajaxError'; /** + * Extra headers to add to the request. + */ + headers?: Record<string, string>; + + /** * Handle for current request */ requestHandle: JQuery.jqXHR|null = null; + abortController: AbortController|null = null; + defaultParams = ['idSite', 'period', 'date', 'segment']; + resolveWithHelper = false; + // helper method entry point - static fetch<R = any>(params: QueryParameters, options: AjaxOptions = {}): Promise<R> { // eslint-disable-line + static fetch<R = any>( // eslint-disable-line + params: QueryParameters|QueryParameters[], + options: AjaxOptions = {}, + ): Promise<R> { const helper = new AjaxHelper<R>(); if (options.withTokenInUrl) { helper.withTokenInUrl(); } - helper.setFormat('json'); - helper.addParams({ module: 'API', format: 'json', ...params }, 'get'); + if (options.errorElement) { + helper.setErrorElement(options.errorElement); + } + if (options.redirectOnSuccess) { + helper.redirectOnSuccess( + options.redirectOnSuccess !== true ? options.redirectOnSuccess : undefined, + ); + } + helper.setFormat(options.format || 'json'); + if (Array.isArray(params)) { + helper.setBulkRequests(...(params as QueryParameters[])); + } else { + helper.addParams({ + module: 'API', + format: options.format || 'json', + ...params, + // ajax helper does not encode the segment parameter assuming it is already encoded. this is + // probably for pre-angularjs code, so we don't want to do this now, but just treat segment + // as a normal query parameter input (so it will have double encoded values in input params + // object, then naturally triple encoded in the URL after a $.param call), however we need + // to support any existing uses of the old code, so instead we do a manual encode here. new + // code that uses .fetch() will not need to pre-encode the parameter, while old code + // can pre-encode it. + segment: params.segment ? encodeURIComponent(params.segment as string) : undefined, + }, 'get'); + } if (options.postParams) { helper.addParams(options.postParams, 'post'); } - return helper.send(); + if (options.headers) { + helper.headers = options.headers; + } + + let createErrorNotification = true; + if (typeof options.createErrorNotification !== 'undefined' + && !options.createErrorNotification + ) { + helper.useCallbackInCaseOfError(); + helper.setErrorCallback(null); + createErrorNotification = false; + } + + if (options.abortController) { + helper.abortController = options.abortController; + } + + if (options.returnResponseObject) { + helper.resolveWithHelper = true; + } + + return helper.send().then((result: R | ErrorResponse | AjaxHelper) => { + const data = result instanceof AjaxHelper ? result.requestHandle!.responseJSON : result; + + // check for error if not using default notification behavior + if ((data as ErrorResponse).result === 'error') { + throw new ApiResponseError((data as ErrorResponse).message); + } + + return result as R; + }).catch((xhr: jqXHR) => { + if (createErrorNotification) { + throw xhr; + } + + let message = 'Something went wrong'; + if (xhr.status === 504) { + message = 'Request was prossibly aborted'; + } + throw new Error(message); + }); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + static post<R = any>( + params: QueryParameters, + // eslint-disable-next-line + postParams: any = {}, + options: AjaxOptions = {}, + ): Promise<R> { + return AjaxHelper.fetch<R>(params, { ...options, postParams }); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + static oneAtATime<R = any>( + method: string, + options?: AjaxOptions, + ): (params: QueryParameters, postParams?: QueryParameters) => Promise<R> { + let abortController: AbortController|null = null; + + return (params: QueryParameters, postParams?: QueryParameters) => { + if (abortController) { + abortController.abort(); + } + + abortController = new AbortController(); + return AjaxHelper.post<R>( + { + ...params, + method, + }, + postParams, + { + ...options, + abortController, + }, + ).finally(() => { + abortController = null; + }); + }; } constructor() { @@ -184,13 +316,17 @@ export default class AjaxHelper<T = any> { // eslint-disable-line const arrayParams = ['compareSegments', 'comparePeriods', 'compareDates']; Object.keys(params).forEach((key) => { - const value = params[key]; + let value = params[key]; if (arrayParams.indexOf(key) !== -1 && !value ) { return; } + if (typeof value === 'boolean') { + value = value ? 1 : 0; + } + if (type.toLowerCase() === 'get') { this.getParams[key] = value; } else if (type.toLowerCase() === 'post') { @@ -259,7 +395,7 @@ export default class AjaxHelper<T = any> { // eslint-disable-line * @param [params] to modify in redirect url * @return {void} */ - redirectOnSuccess(params: QueryParameters): void { + redirectOnSuccess(params?: QueryParameters): void { this.setCallback(() => { piwikHelper.redirect(params); }); @@ -270,7 +406,7 @@ export default class AjaxHelper<T = any> { // eslint-disable-line * * @deprecated use the jquery promise API */ - setErrorCallback(callback: AnyFunction): void { + setErrorCallback(callback: AnyFunction|null): void { this.errorCallback = callback; } @@ -346,7 +482,7 @@ export default class AjaxHelper<T = any> { // eslint-disable-line /** * Send the request */ - send(): Promise<T> { + send(): Promise<T | ErrorResponse> { if ($(this.errorElement).length) { $(this.errorElement).hide(); } @@ -358,15 +494,46 @@ export default class AjaxHelper<T = any> { // eslint-disable-line this.requestHandle = this.buildAjaxCall(); window.globalAjaxQueue.push(this.requestHandle); - return new Promise<T>((resolve, reject) => { - this.requestHandle!.then(resolve).fail((xhr: jqXHR) => { - if (xhr.statusText !== 'abort') { - console.log(`Warning: the ${$.param(this.getParams)} request failed!`); + let $timeout: ITimeoutService|null = null; + try { + $timeout = Matomo.helper.getAngularDependency('$timeout'); + } catch (e) { + // ignore + } + + if (this.abortController) { + this.abortController.signal.addEventListener('abort', () => { + if (this.requestHandle) { + this.requestHandle.abort(); + } + }); + } + + const result = new Promise<T | ErrorResponse>((resolve, reject) => { + this.requestHandle!.then((data: unknown) => { + if (this.resolveWithHelper) { + // NOTE: we can't resolve w/ the jquery xhr, because it's a promise, and will + // just result in following the promise chain back to 'data' + resolve(this as unknown as (T | ErrorResponse)); // casting hack here + } else { + resolve(data as (T | ErrorResponse)); // ignoring textStatus/jqXHR + } + }).fail((xhr: jqXHR) => { + if (xhr.statusText === 'abort') { + return; + } + + console.log(`Warning: the ${$.param(this.getParams)} request failed!`); - reject(xhr); + reject(xhr); + }).done(() => { + if ($timeout) { + $timeout(); // trigger digest } }); }); + + return result; } /** @@ -408,6 +575,7 @@ export default class AjaxHelper<T = any> { // eslint-disable-line url, dataType: this.format || 'json', complete: this.completeCallback, + headers: this.headers ? this.headers : undefined, error: function errorCallback(...args: any[]) { // eslint-disable-line window.globalAjaxQueue.active -= 1; @@ -429,7 +597,8 @@ export default class AjaxHelper<T = any> { // eslint-disable-line type = null; } - if (response.message) { + const isLoggedIn = !document.querySelector('#login_form'); + if (response.message && isLoggedIn) { const UI = window['require']('piwik/UI'); // eslint-disable-line const notification = new UI.Notification(); notification.show(response.message, { @@ -499,7 +668,7 @@ export default class AjaxHelper<T = any> { // eslint-disable-line * * @param params parameter object */ - private mixinDefaultGetParams(originalParams: QueryParameters): QueryParameters { + public mixinDefaultGetParams(originalParams: QueryParameters): QueryParameters { const segment = MatomoUrl.getSearchParam('segment'); const defaultParams: Record<string, string> = { @@ -533,4 +702,8 @@ export default class AjaxHelper<T = any> { // eslint-disable-line return params; } + + getRequestHandle(): jqXHR|null { + return this.requestHandle; + } } diff --git a/plugins/CoreHome/vue/src/Alert/alert.less b/plugins/CoreHome/vue/src/Alert/alert.less index 6d1dc174cb..4f335d5f15 100644 --- a/plugins/CoreHome/vue/src/Alert/alert.less +++ b/plugins/CoreHome/vue/src/Alert/alert.less @@ -82,17 +82,17 @@ body #content .alert-warning p { } .alert-warning { - color: #f57c00; - border-color: #f57c00; + color: @color-orange-brand; + border-color: @color-orange-brand; &:before { content: "\e621"; - color: #f57c00; + color: @color-orange-brand; } p { - color: #f57c00; + color: @color-orange-brand; } a { - color: #f57c00; + color: @color-orange-brand; text-decoration: underline; &:hover { text-decoration: underline; diff --git a/plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts b/plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts index 845c965081..c2133ed48d 100644 --- a/plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts +++ b/plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts @@ -13,9 +13,7 @@ function ComparisonFactory() { return ComparisonsStoreInstance; } -ComparisonFactory.$inject = []; - -angular.module('piwikApp.service').factory('piwikComparisonsService', ComparisonFactory); +window.angular.module('piwikApp.service').factory('piwikComparisonsService', ComparisonFactory); export default createAngularJsAdapter({ component: Comparisons, diff --git a/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.spec.ts b/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.spec.ts index 97e1ad3f22..2dc4ef3157 100644 --- a/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.spec.ts +++ b/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.spec.ts @@ -177,7 +177,7 @@ describe('CoreHome/Comparisons.store', () => { angularApply(); await wait(); - expect(window.location.href).toEqual('http://localhost/#?category=MyModule1&subcategory=enabledPage&date=2018-01-02&period=day&segment=abcdefg&compareDates%5B%5D=2018-03-04&comparePeriods%5B%5D=week&compareSegments%5B%5D='); + expect(window.location.href).toEqual('http://localhost/#?period=day&date=2018-01-02&segment=abcdefg&category=MyModule1&subcategory=enabledPage&compareDates%5B%5D=2018-03-04&comparePeriods%5B%5D=week&compareSegments%5B%5D='); }); it('should change the base comparison if the first segment is removed', async () => { @@ -187,7 +187,7 @@ describe('CoreHome/Comparisons.store', () => { angularApply(); await wait(); - expect(window.location.href).toEqual('http://localhost/#?category=MyModule1&subcategory=enabledPage&date=2018-01-02&period=day&segment=comparedsegment&compareDates%5B%5D=2018-03-04&comparePeriods%5B%5D=week&compareSegments%5B%5D='); + expect(window.location.href).toEqual('http://localhost/#?period=day&date=2018-01-02&segment=comparedsegment&category=MyModule1&subcategory=enabledPage&compareDates%5B%5D=2018-03-04&comparePeriods%5B%5D=week&compareSegments%5B%5D='); }); }); diff --git a/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts b/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts index 6d3b8462dd..1e29790099 100644 --- a/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts +++ b/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts @@ -13,7 +13,7 @@ import { } from 'vue'; import MatomoUrl from '../MatomoUrl/MatomoUrl'; import Matomo from '../Matomo/Matomo'; -import translate from '../translate'; +import { translate } from '../translate'; import Periods from '../Periods/Periods'; import AjaxHelper from '../AjaxHelper/AjaxHelper'; import SegmentsStore from '../Segmentation/Segments.store'; @@ -58,7 +58,7 @@ function wrapArray<T>(values: T | T[]): T[] { if (!values) { return []; } - return values instanceof Array ? values : [values]; + return Array.isArray(values) ? values : [values]; } export default class ComparisonsStore { @@ -262,39 +262,14 @@ export default class ComparisonsStore { }; // change the page w/ these new param values - if (Matomo.helper.isAngularRenderingThePage()) { - const search = MatomoUrl.hashParsed.value; - - const newSearch: {[key: string]: string|string[]} = { - ...search, - ...compareParams, - ...extraParams, - }; - - delete newSearch['compareSegments[]']; - delete newSearch['comparePeriods[]']; - delete newSearch['compareDates[]']; - - if (JSON.stringify(newSearch) !== JSON.stringify(search)) { - MatomoUrl.updateHash(newSearch); - } - - return; - } - - const paramsToRemove: string[] = []; - ['compareSegments', 'comparePeriods', 'compareDates'].forEach((name) => { - if (!compareParams[name].length) { - paramsToRemove.push(name); - } + const baseParams = Matomo.helper.isAngularRenderingThePage() + ? MatomoUrl.hashParsed.value + : MatomoUrl.urlParsed.value; + MatomoUrl.updateLocation({ + ...baseParams, + ...compareParams, + ...extraParams, }); - - // angular is not rendering the page (ie, we are in the embedded dashboard) or we need to change - // the segment - const url = MatomoUrl.stringify(extraParams); - const strHash = MatomoUrl.stringify(compareParams); - - window.broadcast.propagateNewPage(url, undefined, strHash, paramsToRemove); } private getAllSeriesColors() { @@ -317,8 +292,17 @@ export default class ComparisonsStore { private loadComparisonsDisabledFor() { const matomoModule: string = MatomoUrl.parsed.value.module as string; + + // check if body id #installation exist + if (window.piwik.installation) { + this.privateState.comparisonsDisabledFor = []; + return; + } + if (matomoModule === 'CoreUpdater' || matomoModule === 'Installation' + || matomoModule === 'Overlay' + || window.piwik.isPagesComparisonApiDisabled ) { this.privateState.comparisonsDisabledFor = []; return; diff --git a/plugins/CoreHome/vue/src/Comparisons/Comparisons.vue b/plugins/CoreHome/vue/src/Comparisons/Comparisons.vue index 7639c2e620..d9ab36781d 100644 --- a/plugins/CoreHome/vue/src/Comparisons/Comparisons.vue +++ b/plugins/CoreHome/vue/src/Comparisons/Comparisons.vue @@ -5,7 +5,12 @@ --> <template> - <div v-if="isComparing" ref="root" class="matomo-comparisons"> + <div + v-if="isComparing" + ref="root" + class="matomo-comparisons" + v-tooltips="{ duration: 200, delay: 200, content: transformTooltipContent }" + > <h3>{{ translate('General_Comparisons') }}</h3> <div class="comparison card" @@ -71,7 +76,8 @@ import ComparisonsStoreInstance from './Comparisons.store.instance'; import Matomo from '../Matomo/Matomo'; import MatomoUrl from '../MatomoUrl/MatomoUrl'; import AjaxHelper from '../AjaxHelper/AjaxHelper'; -import translate from '../translate'; +import { translate } from '../translate'; +import Tooltips from '../Tooltips/Tooltips'; interface ProcessedReportComparison { compareSegmentPretty: string; @@ -88,10 +94,17 @@ interface ProcessedReportResponse { reportData: ProcessedReportData; } +interface ComparisonState { + comparisonTooltips: Record<string, Record<string, string>>|null; +} + export default defineComponent({ props: { }, - data() { + directives: { + Tooltips, + }, + data(): ComparisonState { return { comparisonTooltips: null, }; @@ -103,11 +116,21 @@ export default defineComponent({ const segmentComparisons = computed(() => ComparisonsStoreInstance.getSegmentComparisons()); const periodComparisons = computed(() => ComparisonsStoreInstance.getPeriodComparisons()); const getSeriesColor = ComparisonsStoreInstance.getSeriesColor.bind(ComparisonsStoreInstance); + + function transformTooltipContent(this: HTMLElement) { + const title = window.$(this).attr('title'); + if (!title) { + return title; + } + return window.vueSanitize(title.replace(/\n/g, '<br />')); + } + return { isComparing, segmentComparisons, periodComparisons, getSeriesColor, + transformTooltipContent, }; }, methods: { @@ -116,7 +139,7 @@ export default defineComponent({ }, removeSegmentComparison(index: number) { // otherwise the tooltip will be stuck on the screen - window.$(this.$refs.root).tooltip('destroy'); + window.$(this.$refs.root as HTMLElement).tooltip('destroy'); ComparisonsStoreInstance.removeSegmentComparison(index); }, getComparisonPeriodType(comparison: AnyComparison) { @@ -149,18 +172,6 @@ export default defineComponent({ hash.segment = segment; return `${window.location.search}#?${MatomoUrl.stringify(hash)}`; }, - setUpTooltips() { - const { $ } = window; - $(this.$refs.root).tooltip({ - track: true, - content: function transformTooltipContent() { - const title = $(this).attr('title'); - return window.vueSanitize(title.replace(/\n/g, '<br />')); - }, - show: { delay: 200, duration: 200 }, - hide: false, - }); - }, onComparisonsChanged() { this.comparisonTooltips = null; @@ -182,11 +193,11 @@ export default defineComponent({ }).then((report) => { this.comparisonTooltips = {}; periodComparisons.forEach((periodComp) => { - this.comparisonTooltips[periodComp.index] = {}; + this.comparisonTooltips![periodComp.index] = {}; segmentComparisons.forEach((segmentComp) => { const tooltip = this.generateComparisonTooltip(report, periodComp, segmentComp); - this.comparisonTooltips[periodComp.index][segmentComp.index] = tooltip; + this.comparisonTooltips![periodComp.index][segmentComp.index] = tooltip; }); }); }); @@ -241,24 +252,12 @@ export default defineComponent({ return tooltip; }, }, - updated() { - setTimeout(() => this.setUpTooltips()); - }, mounted() { Matomo.on('piwikComparisonsChanged', () => { this.onComparisonsChanged(); }); this.onComparisonsChanged(); - - setTimeout(() => this.setUpTooltips()); - }, - beforeUnmount() { - try { - window.$(this.refs.root).tooltip('destroy'); - } catch (e) { - // ignore - } }, }); </script> diff --git a/plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue b/plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue index 12a89d770b..6bee7fab95 100644 --- a/plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue +++ b/plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue @@ -36,6 +36,8 @@ import EnrichedHeadline from '../EnrichedHeadline/EnrichedHeadline.vue'; let adminContent: HTMLElement|null = null; +const { $ } = window; + export default defineComponent({ props: { contentTitle: String, @@ -62,12 +64,13 @@ export default defineComponent({ }, }, mounted() { - const { root, content } = this.$refs; + const root = this.$refs.root as HTMLElement; + const content = this.$refs.content as HTMLElement; - if (this.anchor) { + if (this.anchor && root && root.parentElement) { const anchorElement = document.createElement('a'); anchorElement.id = this.anchor; - root.parentElement.prepend(anchorElement); + $(root.parentElement).prepend(anchorElement); } setTimeout(() => { @@ -78,7 +81,7 @@ export default defineComponent({ } }, 0); - if (this.actualFeature && (this.actualFeature === true || this.actualFeature === 'true')) { + if (this.actualFeature && this.actualFeature === 'true') { this.actualFeature = this.contentTitle; } @@ -87,13 +90,13 @@ export default defineComponent({ adminContent = document.querySelector('#content.admin'); } - let contentTopPosition: number; + let contentTopPosition: number|null = null; if (adminContent) { contentTopPosition = adminContent.offsetTop; } if (contentTopPosition || contentTopPosition === 0) { - const parents = root.closest('[piwik-widget-loader]'); + const parents = root.closest('[piwik-widget-loader]') as HTMLElement; // when shown within the widget loader, we need to get the offset of that element // as the widget loader might be still shown. Would otherwise not position correctly @@ -103,7 +106,7 @@ export default defineComponent({ if (topThis - contentTopPosition < 17) { // we make sure to display the first card with no margin-top to have it on same as line as // navigation - root.style.marginTop = 0; + root.style.marginTop = '0'; } } }, diff --git a/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.adapter.ts b/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.adapter.ts new file mode 100644 index 0000000000..8669a29b52 --- /dev/null +++ b/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.adapter.ts @@ -0,0 +1,20 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { IDirective, IScope } from 'angular'; +import ContentIntro from './ContentIntro'; + +export default function piwikContentIntro(): IDirective { + return { + restrict: 'A', + link: function piwikContentIntroLink(scope: IScope, element: JQuery) { + ContentIntro.mounted(element[0]); + }, + }; +} + +window.angular.module('piwikApp').directive('piwikContentIntro', piwikContentIntro); diff --git a/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.ts b/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.ts new file mode 100644 index 0000000000..ba550ae21a --- /dev/null +++ b/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.ts @@ -0,0 +1,22 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { nextTick } from 'vue'; + +export default { + mounted(el: HTMLElement): void { + el.classList.add('piwik-content-intro'); + }, + updated(el: HTMLElement): void { + // classes can be overwritten when elements bind to :class, nextTick + using + // updated avoids this problem (and doing in both mounted and updated avoids a temporary + // state where the classes aren't added) + nextTick(() => { + el.classList.add('piwik-content-intro'); + }); + }, +}; diff --git a/plugins/CoreHome/vue/src/ContentTable/ContentTable.adapter.ts b/plugins/CoreHome/vue/src/ContentTable/ContentTable.adapter.ts new file mode 100644 index 0000000000..a57d53ed4d --- /dev/null +++ b/plugins/CoreHome/vue/src/ContentTable/ContentTable.adapter.ts @@ -0,0 +1,20 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { IDirective, IScope } from 'angular'; +import ContentTable from './ContentTable'; + +export default function piwikContentTable(): IDirective { + return { + restrict: 'A', + link: function piwikContentTableLink(scope: IScope, element: JQuery) { + ContentTable.mounted(element[0]); + }, + }; +} + +window.angular.module('piwikApp').directive('piwikContentTable', piwikContentTable); diff --git a/plugins/CoreHome/vue/src/ContentTable/ContentTable.ts b/plugins/CoreHome/vue/src/ContentTable/ContentTable.ts new file mode 100644 index 0000000000..7d7dfc3893 --- /dev/null +++ b/plugins/CoreHome/vue/src/ContentTable/ContentTable.ts @@ -0,0 +1,22 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { nextTick } from 'vue'; + +export default { + mounted(el: HTMLElement): void { + el.classList.add('card', 'card-table', 'entityTable'); + }, + updated(el: HTMLElement): void { + // classes can be overwritten when elements bind to :class, nextTick + using + // updated avoids this problem (and doing in both mounted and updated avoids a temporary + // state where the classes aren't added) + nextTick(() => { + el.classList.add('card', 'card-table', 'entityTable'); + }); + }, +}; diff --git a/plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts b/plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts index 71223d58f2..e276e59dc3 100644 --- a/plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts +++ b/plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts @@ -9,7 +9,7 @@ import { ITimeoutService } from 'angular'; import createAngularJsAdapter from '../createAngularJsAdapter'; import DatePicker from './DatePicker.vue'; -export default createAngularJsAdapter({ +export default createAngularJsAdapter<[ITimeoutService]>({ component: DatePicker, scope: { selectedDateStart: { @@ -48,13 +48,13 @@ export default createAngularJsAdapter({ }, directiveName: 'piwikDatePicker', events: { - 'cell-hover': (event, scope, element, attrs, $timeout: ITimeoutService) => { + 'cell-hover': (event, vm, scope, element, attrs, controller, $timeout) => { $timeout(); // trigger new digest }, - 'cell-hover-leave': (event, scope, element, attrs, $timeout: ITimeoutService) => { + 'cell-hover-leave': (event, vm, scope, element, attrs, controller, $timeout) => { $timeout(); // trigger new digest }, - 'date-select': (event, scope, element, attrs, $timeout: ITimeoutService) => { + 'date-select': (event, vm, scope, element, attrs, controller, $timeout) => { $timeout(); // trigger new digest }, }, diff --git a/plugins/CoreHome/vue/src/DatePicker/DatePicker.vue b/plugins/CoreHome/vue/src/DatePicker/DatePicker.vue index 784d0d9311..1f605c70aa 100644 --- a/plugins/CoreHome/vue/src/DatePicker/DatePicker.vue +++ b/plugins/CoreHome/vue/src/DatePicker/DatePicker.vue @@ -15,7 +15,6 @@ import { watch, onMounted, } from 'vue'; -import JQuery = JQuery; import Matomo from '../Matomo/Matomo'; import { parseDate } from '../Periods'; @@ -36,7 +35,7 @@ export default defineComponent({ }, emits: ['cellHover', 'cellHoverLeave', 'dateSelect'], setup(props, context) { - const root = ref<HTMLElement>(null); + const root = ref<HTMLElement|null>(null); function setDateCellColor($dateCell: JQuery, dateValue: Date): void { const $dateCellLink = $dateCell.children('a'); @@ -75,7 +74,7 @@ export default defineComponent({ return new Date(year, month, day); } - function getOtherMonthDate($dateCell, month, year) { + function getOtherMonthDate($dateCell: JQuery, month: number, year: number) { let date; const $row = $dateCell.parent(); @@ -99,17 +98,17 @@ export default defineComponent({ } function getMonthYearDisplayed(): number[] { - const element = $(root.value); + const element = $(root.value!) as JQuery; const $firstCellWithMonth = element.find('td[data-month]'); - const month = parseInt($firstCellWithMonth.attr('data-month'), 10); - const year = parseInt($firstCellWithMonth.attr('data-year'), 10); + const month = parseInt($firstCellWithMonth.attr('data-month')!, 10); + const year = parseInt($firstCellWithMonth.attr('data-year')!, 10); return [month, year]; } function setDatePickerCellColors() { - const element = $(root.value); + const element = $(root.value!); const $calendarTable = element.find('.ui-datepicker-calendar'); @@ -129,20 +128,22 @@ export default defineComponent({ } function viewDateChanged(): boolean { - let date = props.viewDate; - if (!date) { + if (!props.viewDate) { return false; } - if (!(date instanceof Date)) { + let date: Date; + if (typeof props.viewDate === 'string') { try { - date = parseDate(date); + date = parseDate(props.viewDate); } catch (e) { return false; } + } else { + date = props.viewDate as Date; } - const element = $(root.value); + const element = $(root.value!); // only change the datepicker date if the date is outside of the current month/year. // this avoids a re-render in other cases. @@ -158,7 +159,7 @@ export default defineComponent({ // remove the ui-state-active class & click handlers for every cell. we bypass // the datepicker's date selection logic for smoother browser rendering. function onJqueryUiRenderedPicker(): void { - const element = $(root.value); + const element = $(root.value!); element.find('td[data-event]').off('click'); element.find('.ui-state-active').removeClass('ui-state-active'); @@ -169,7 +170,7 @@ export default defineComponent({ } function stepMonthsChanged(): boolean { - const element = $(root.value); + const element = $(root.value!); const stepMonths = props.stepMonths || DEFAULT_STEP_MONTHS; if (element.datepicker('option', 'stepMonths') === stepMonths) { @@ -178,8 +179,8 @@ export default defineComponent({ // setting stepMonths will change the month in view back to the selected date. to avoid // we set the selected date to the month in view. - const currentMonth = $('.ui-datepicker-month', element).val(); - const currentYear = $('.ui-datepicker-year', element).val(); + const currentMonth = $('.ui-datepicker-month', element).val() as number; + const currentYear = $('.ui-datepicker-year', element).val() as number; element .datepicker('option', 'stepMonths', stepMonths) @@ -191,12 +192,14 @@ export default defineComponent({ } function enableDisableMonthDropdown(): void { - const element = $(root.value); - - element.find('.ui-datepicker-month').attr('disabled', props.disableMonthDropdown); + const element = $(root.value!); + const monthPicker = element.find('.ui-datepicker-month')[0] as HTMLInputElement; + if (monthPicker) { + monthPicker.disabled = props.disableMonthDropdown; + } } - function handleOtherMonthClick() { + function handleOtherMonthClick(this: HTMLElement) { if (!$(this).hasClass('ui-state-hover')) { return; } @@ -229,26 +232,29 @@ export default defineComponent({ let redraw = false; [ - 'selectedDateStart', - 'selectedDateEnd', - 'highlightedDateStart', - 'highlightedDateEnd', - ].forEach((propName) => { + (x: typeof props): Date|undefined => x.selectedDateStart, + (x: typeof props): Date|undefined => x.selectedDateEnd, + (x: typeof props): Date|undefined => x.highlightedDateStart, + (x: typeof props): Date|undefined => x.highlightedDateEnd, + ].forEach((selector) => { if (redraw) { return; } - if (!newProps[propName] && oldProps[propName]) { + const newProp = selector(newProps); + const oldProp = selector(oldProps); + + if (!newProp && oldProp) { redraw = true; } - if (newProps[propName] && !oldProps[propName]) { + if (newProp && !oldProp) { redraw = true; } - if (newProps[propName] - && oldProps[propName] - && newProps[propName].getTime() !== oldProps[propName].getTime() + if (newProp + && oldProp + && newProp.getTime() !== oldProp.getTime() ) { redraw = true; } @@ -262,7 +268,7 @@ export default defineComponent({ stepMonthsChanged(); } - if (newProps.enableDisableMonthDropdown !== oldProps.enableDisableMonthDropdown) { + if (newProps.disableMonthDropdown !== oldProps.disableMonthDropdown) { enableDisableMonthDropdown(); } @@ -273,7 +279,7 @@ export default defineComponent({ }); onMounted(() => { - const element = $(root.value); + const element = $(root.value!); const customOptions = props.options || {}; const datePickerOptions = { @@ -319,8 +325,7 @@ export default defineComponent({ .on('mouseenter', 'thead', () => context.emit('cellHoverLeave')); // make sure whitespace is clickable when the period makes it appropriate - element.on('click', 'tbody td.ui-datepicker-other-month', - () => handleOtherMonthClick()); + element.on('click', 'tbody td.ui-datepicker-other-month', handleOtherMonthClick); // NOTE: using a selector w/ .on() doesn't seem to work for some reason... element.on('click', (e) => { @@ -340,8 +345,8 @@ export default defineComponent({ // with onJqueryUiRenderedPicker(), overrides the date picker's click behavior. element.on('click', 'td[data-month]', (event) => { const $cell = $(event.target).closest('td') as JQuery; - const month = parseInt($cell.attr('data-month'), 10); - const year = parseInt($cell.attr('data-year'), 10); + const month = parseInt($cell.attr('data-month')!, 10); + const year = parseInt($cell.attr('data-year')!, 10); const day = parseInt($cell.children('a,span').text(), 10); context.emit('dateSelect', { date: new Date(year, month, day) }); }); diff --git a/plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue b/plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue index c2af7ecb1c..0a5608d2aa 100644 --- a/plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue +++ b/plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue @@ -5,67 +5,81 @@ --> <template> - <div id="calendarRangeFrom"> - <h6> - {{ translate('General_DateRangeFrom') }} - <input - type="text" - id="inputCalendarFrom" - name="inputCalendarFrom" - class="browser-default" - v-model="startDateText" - v-on:change="onRangeInputChanged('from', $event)" - v-on:keyup="handleEnterPress($event)" - /> - </h6> - <DatePicker - id="calendarFrom" - :view-date="startDate" - :selected-date-start="fromPickerSelectedDates[0]" - :selected-date-end="fromPickerSelectedDates[1]" - :highlighted-date-start="fromPickerHighlightedDates[0]" - :highlighted-date-end="fromPickerHighlightedDates[1]" - @date-select="setStartRangeDate($event.date)" - @cell-hover="fromPickerHighlightedDates = getNewHighlightedDates($event.date, $event.$cell)" - @cell-hover-leave="fromPickerHighlightedDates = [null, null]" - > - </DatePicker> - </div> - <div id="calendarRangeTo"> - <h6> - {{ translate('General_DateRangeTo') }} - <input - type="text" - id="inputCalendarTo" - name="inputCalendarTo" - class="browser-default" - v-model="endDateText" - v-on:change="onRangeInputChanged('to', $event)" - v-on:keyup="handleEnterPress($event)" - /> - </h6> - <DatePicker - id="calendarTo" - :view-date="endDate" - :selected-date-start="toPickerSelectedDates[0]" - :selected-date-end="toPickerSelectedDates[1]" - :highlighted-date-start="toPickerHighlightedDates[0]" - :highlighted-date-end="toPickerHighlightedDates[1]" - @date-select="setEndRangeDate($event.date)" - @cell-hover="toPickerHighlightedDates = getNewHighlightedDates($event.date, $event.$cell)" - @cell-hover-leave="toPickerHighlightedDates = [null, null]" - > - </DatePicker> + <div> + <div id="calendarRangeFrom"> + <h6> + {{ translate('General_DateRangeFrom') }} + <input + type="text" + id="inputCalendarFrom" + name="inputCalendarFrom" + class="browser-default" + v-model="startDateText" + @keydown="onRangeInputChanged('from', $event)" + @keyup="handleEnterPress($event)" + /> + </h6> + <DatePicker + id="calendarFrom" + :view-date="startDate" + :selected-date-start="fromPickerSelectedDates[0]" + :selected-date-end="fromPickerSelectedDates[1]" + :highlighted-date-start="fromPickerHighlightedDates[0]" + :highlighted-date-end="fromPickerHighlightedDates[1]" + @date-select="setStartRangeDate($event.date)" + @cell-hover="fromPickerHighlightedDates = getNewHighlightedDates($event.date, $event.$cell)" + @cell-hover-leave="fromPickerHighlightedDates = [null, null]" + > + </DatePicker> + </div> + <div id="calendarRangeTo"> + <h6> + {{ translate('General_DateRangeTo') }} + <input + type="text" + id="inputCalendarTo" + name="inputCalendarTo" + class="browser-default" + v-model="endDateText" + @keydown="onRangeInputChanged('to', $event)" + @keyup="handleEnterPress($event)" + /> + </h6> + <DatePicker + id="calendarTo" + :view-date="endDate" + :selected-date-start="toPickerSelectedDates[0]" + :selected-date-end="toPickerSelectedDates[1]" + :highlighted-date-start="toPickerHighlightedDates[0]" + :highlighted-date-end="toPickerHighlightedDates[1]" + @date-select="setEndRangeDate($event.date)" + @cell-hover="toPickerHighlightedDates = getNewHighlightedDates($event.date, $event.$cell)" + @cell-hover-leave="toPickerHighlightedDates = [null, null]" + > + </DatePicker> + </div> </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; -import JQuery = JQuery; import DatePicker from '../DatePicker/DatePicker.vue'; import { parseDate, format } from '../Periods/utilities'; import ChangeEvent = JQuery.ChangeEvent; +const DATE_FORMAT = 'YYYY-MM-DD'; + +interface DateRangePickerState { + fromPickerSelectedDates: (Date|null)[]; + toPickerSelectedDates: (Date|null)[]; + fromPickerHighlightedDates: (Date|null)[]; + toPickerHighlightedDates: (Date|null)[]; + startDateText?: string; + endDateText?: string; + startDateInvalid: boolean; + endDateInvalid: boolean; +} + export default defineComponent({ props: { startDate: String, @@ -74,17 +88,21 @@ export default defineComponent({ components: { DatePicker, }, - data() { + data(): DateRangePickerState { let startDate = null; try { - startDate = parseDate(this.startDate); + if (this.startDate) { + startDate = parseDate(this.startDate); + } } catch (e) { // ignore } let endDate = null; try { - endDate = parseDate(this.endDate); + if (this.endDate) { + endDate = parseDate(this.endDate); + } } catch (e) { // ignore } @@ -96,6 +114,8 @@ export default defineComponent({ toPickerHighlightedDates: [null, null], startDateText: this.startDate, endDateText: this.endDate, + startDateInvalid: false, + endDateInvalid: false, }; }, emits: ['rangeChange', 'submit'], @@ -124,11 +144,13 @@ export default defineComponent({ this.rangeChanged(); }, onRangeInputChanged(source: string, event: ChangeEvent) { - if (source === 'from') { - this.setStartRangeDateFromStr(event.target.value); - } else { - this.setEndRangeDateFromStr(event.target.value); - } + setTimeout(() => { + if (source === 'from') { + this.setStartRangeDateFromStr(event.target.value); + } else { + this.setEndRangeDateFromStr(event.target.value); + } + }); }, getNewHighlightedDates(date: Date, $cell: JQuery) { if ($cell.hasClass('ui-datepicker-unselectable')) { @@ -147,38 +169,48 @@ export default defineComponent({ end: this.endDate, }); }, - setStartRangeDateFromStr(dateStr: string) { - let startDateParsed: Date; + setStartRangeDateFromStr(dateStr?: string) { + this.startDateInvalid = true; + + let startDateParsed: Date|null = null; try { - startDateParsed = parseDate(dateStr); + if (dateStr && dateStr.length === DATE_FORMAT.length) { + startDateParsed = parseDate(dateStr); + } } catch (e) { - this.startDateText = this.startDate; + // ignore } if (startDateParsed) { this.fromPickerSelectedDates = [startDateParsed, startDateParsed]; - } + this.startDateInvalid = false; - this.rangeChanged(); + this.rangeChanged(); + } }, - setEndRangeDateFromStr(dateStr: string) { - let endDateParsed: Date; + setEndRangeDateFromStr(dateStr?: string) { + this.endDateInvalid = true; + + let endDateParsed: Date|null = null; try { - endDateParsed = parseDate(dateStr); + if (dateStr && dateStr.length === DATE_FORMAT.length) { + endDateParsed = parseDate(dateStr); + } } catch (e) { - this.endDateText = this.endDate; + // ignore } if (endDateParsed) { this.toPickerSelectedDates = [endDateParsed, endDateParsed]; - } + this.endDateInvalid = false; - this.rangeChanged(); + this.rangeChanged(); + } }, rangeChanged() { this.$emit('rangeChange', { - start: format(this.fromPickerSelectedDates[0]), - end: format(this.toPickerSelectedDates[0]), + start: this.fromPickerSelectedDates[0] ? format(this.fromPickerSelectedDates[0]) : null, + end: this.toPickerSelectedDates[0] ? format(this.toPickerSelectedDates[0]) : null, }); }, }, diff --git a/plugins/CoreHome/vue/src/DropdownButton/DropdownButton.adapter.ts b/plugins/CoreHome/vue/src/DropdownButton/DropdownButton.adapter.ts new file mode 100644 index 0000000000..24cbb668e8 --- /dev/null +++ b/plugins/CoreHome/vue/src/DropdownButton/DropdownButton.adapter.ts @@ -0,0 +1,20 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { IDirective, IScope } from 'angular'; +import DropdownButton from './DropdownButton'; + +export default function piwikDropdownButton(): IDirective { + return { + restrict: 'C', + link: function piwikDropdownButtonLink(scope: IScope, element: JQuery) { + DropdownButton.mounted(element[0]); + }, + }; +} + +window.angular.module('piwikApp').directive('dropdownButton', piwikDropdownButton); diff --git a/plugins/CoreHome/vue/src/DropdownButton/DropdownButton.ts b/plugins/CoreHome/vue/src/DropdownButton/DropdownButton.ts new file mode 100644 index 0000000000..ae1f20d6a2 --- /dev/null +++ b/plugins/CoreHome/vue/src/DropdownButton/DropdownButton.ts @@ -0,0 +1,32 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +const { $ } = window; + +export default { + mounted(el: HTMLElement): void { + const element = $(el) as JQuery; + + // BC for materializecss 0.97 => 1.0 + if (!element.attr('data-target') + && element.attr('data-activates') + ) { + element.attr('data-target', element.attr('data-activates')!); + } + + const target = element.attr('data-target'); + if (target && $(`#${target}`).length) { + (element as any).dropdown({ // eslint-disable-line + inDuration: 300, + outDuration: 225, + constrainWidth: false, // Does not change width of dropdown to that of the activator + // hover: true, // Activate on hover + belowOrigin: true, // Displays dropdown below the button + }); + } + }, +}; diff --git a/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.adapter.ts b/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.adapter.ts index 1e8598881a..fa50cbcce1 100644 --- a/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.adapter.ts +++ b/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.adapter.ts @@ -5,10 +5,10 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import { IDirective } from 'angular'; +import { IDirective, ITimeoutService } from 'angular'; import DropdownMenu from './DropdownMenu'; -function piwikDropdownMenu($timeout): IDirective { +function piwikDropdownMenu($timeout: ITimeoutService): IDirective { return { restrict: 'A', link: function piwikDropdownMenuLink(scope, element, attrs) { @@ -31,4 +31,4 @@ function piwikDropdownMenu($timeout): IDirective { piwikDropdownMenu.$inject = ['$timeout']; -angular.module('piwikApp').directive('piwikDropdownMenu', piwikDropdownMenu); +window.angular.module('piwikApp').directive('piwikDropdownMenu', piwikDropdownMenu); diff --git a/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.less b/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.less index 606b42bd1f..ad5bbf948d 100644 --- a/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.less +++ b/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.less @@ -1,4 +1,4 @@ -[piwik-dropdown-menu],[matomo-dropdown-menu] { +[piwik-dropdown-menu],.matomo-dropdown-menu { position: relative; &::after { diff --git a/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.ts b/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.ts index a39d288565..f1870df185 100644 --- a/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.ts +++ b/plugins/CoreHome/vue/src/DropdownMenu/DropdownMenu.ts @@ -5,10 +5,10 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import { DirectiveBinding } from 'vue'; +import { DirectiveBinding, nextTick } from 'vue'; interface DropdownArgs { - activates: HTMLElement, + activates?: HTMLElement|string, } /** @@ -42,7 +42,8 @@ export default { if (isSubmenu) { options = { hover: true }; $(element).addClass('submenu'); - $(binding.value.activates).addClass('submenu-dropdown-content'); + $(binding.value?.activates || $(element).data('target')) + .addClass('submenu-dropdown-content'); // if a submenu is used, the dropdown will never scroll $(element).parents('.dropdown-content').addClass('submenu-container'); @@ -50,4 +51,12 @@ export default { $(element).dropdown(options); }, + updated(element: HTMLElement): void { + // classes can be overwritten when elements bind to :class, nextTick + using + // updated avoids this problem (and doing in both mounted and updated avoids a temporary + // state where the classes aren't added) + nextTick(() => { + $(element).addClass('matomo-dropdown-menu'); + }); + }, }; diff --git a/plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue b/plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue index f7d8cd7912..c83ee915fa 100644 --- a/plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue +++ b/plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue @@ -56,6 +56,9 @@ v-show="showInlineHelp" > <div v-html="$sanitize(actualInlineHelp)"/> + <span class="helpDate" + v-if="reportGenerated!=''" + v-html="$sanitize(reportGenerated)"></span> <a v-if="helpUrl" rel="noreferrer noopener" @@ -68,23 +71,21 @@ </template> <script lang="ts"> -import { - defineComponent, - defineAsyncComponent, -} from 'vue'; +import { defineComponent } from 'vue'; import Matomo from '../Matomo/Matomo'; import Periods from '../Periods/Periods'; +import useExternalPluginComponent from '../useExternalPluginComponent'; // working around a cycle in dependencies (CoreHome depends on Feedback, Feedback depends on // CoreHome) -// TODO: may need a generic solution at some point, but it's bad practice to have -// cyclic dependencies like this. it worked before because it was individual files -// dependening on each other, not whole plugins. -const RateFeature = defineAsyncComponent(() => new Promise((resolve) => { - window.$(document).ready(() => { - resolve((window as any).Feedback.RateFeature); // eslint-disable-line - }); -})); +const RateFeature = useExternalPluginComponent('Feedback', 'RateFeature'); + +interface EnrichedHeadlineData { + showIcons: boolean; + showInlineHelp: boolean; + actualFeatureName?: string | null; + actualInlineHelp?: string | null, +} /** * Usage: @@ -134,7 +135,7 @@ export default defineComponent({ components: { RateFeature, }, - data() { + data(): EnrichedHeadlineData { return { showIcons: false, showInlineHelp: false, @@ -151,13 +152,13 @@ export default defineComponent({ }, }, mounted() { - const { root } = this.$refs; + const root = this.$refs.root as HTMLElement; // timeout used since angularjs does not fill out the transclude at this point setTimeout(() => { if (!this.actualInlineHelp) { let helpNode = root.querySelector('.title .inlineHelp'); - if (!helpNode && root.parentElement.nextElementSibling) { + if (!helpNode && root.parentElement?.nextElementSibling) { // hack for reports :( helpNode = (root.parentElement.nextElementSibling as HTMLElement) .querySelector('.reportDocumentation'); @@ -167,28 +168,35 @@ export default defineComponent({ // hackish solution to get binded html of p tag within the help node // at this point the ng-bind-html is not yet converted into html when report is not // initially loaded. Using $compile doesn't work. So get and set it manually - const helpDocs = helpNode.getAttribute('data-content').trim(); - if (helpDocs.length) { + const helpDocs = helpNode.getAttribute('data-content')?.trim(); + if (helpDocs && helpDocs.length) { this.actualInlineHelp = `<p>${helpDocs}</p>`; - setTimeout(() => helpNode.remove(), 0); + setTimeout(() => helpNode!.remove(), 0); } } } if (!this.actualFeatureName) { - this.actualFeatureName = root.querySelector('.title').textContent; + this.actualFeatureName = root.querySelector('.title')?.textContent; } - if (this.reportGenerated - && Periods.parse(Matomo.period, Matomo.currentDateString).containsToday() - ) { - window.$(root.querySelector('.report-generated')).tooltip({ - track: true, - content: this.reportGenerated, - items: 'div', - show: false, - hide: false, - }); + if (Matomo.period && Matomo.currentDateString) { + const currentPeriod = Periods.parse( + Matomo.period as string, + Matomo.currentDateString as string, + ); + + if (this.reportGenerated + && currentPeriod.containsToday() + ) { + window.$(root.querySelector('.report-generated')!).tooltip({ + track: true, + content: this.reportGenerated, + items: 'div', + show: false, + hide: false, + }); + } } }); }, diff --git a/plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.adapter.ts b/plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.adapter.ts index c4d39aab52..f4aa4bf46f 100644 --- a/plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.adapter.ts +++ b/plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.adapter.ts @@ -28,6 +28,4 @@ export default function piwikExpandOnClick(): IDirective { }; } -piwikExpandOnClick.$inject = []; - -angular.module('piwikApp').directive('piwikExpandOnClick', piwikExpandOnClick); +window.angular.module('piwikApp').directive('piwikExpandOnClick', piwikExpandOnClick); diff --git a/plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.ts b/plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.ts index 9ce10091d5..76e22ca075 100644 --- a/plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.ts +++ b/plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.ts @@ -7,13 +7,17 @@ import { DirectiveBinding } from 'vue'; import Matomo from '../Matomo/Matomo'; +import DirectiveUtilities from '../directiveUtilities'; interface ExpandOnClickArgs { - expander: HTMLElement, + // input (specified by user) + expander: string | HTMLElement, + // state isMouseDown?: boolean; hasScrolled?: boolean; + // event handlers onExpand?: () => void; onClickOutsideElement?: (event: MouseEvent) => void; onScroll?: () => void; @@ -70,6 +74,7 @@ function onEscapeHandler( } const doc = document.documentElement; +const { $ } = window; /** * Usage (in a component): @@ -89,17 +94,25 @@ export default { binding.value.onClickOutsideElement = onClickOutsideElement.bind(null, el, binding); binding.value.onScroll = onScroll.bind(null, binding); - binding.value.expander.addEventListener('click', binding.value.onExpand); + setTimeout(() => { + const expander = DirectiveUtilities.getRef(binding.value.expander, binding); + if (expander) { + $(expander).on('click', binding.value.onExpand!); + } + }); doc.addEventListener('keyup', binding.value.onEscapeHandler); doc.addEventListener('mousedown', binding.value.onMouseDown); doc.addEventListener('mouseup', binding.value.onClickOutsideElement); doc.addEventListener('scroll', binding.value.onScroll); }, unmounted(el: HTMLElement, binding: DirectiveBinding<ExpandOnClickArgs>): void { - binding.value.expander.removeEventListener('click', binding.value.onExpand); - doc.removeEventListener('keyup', binding.value.onEscapeHandler); - doc.removeEventListener('mousedown', binding.value.onMouseDown); - doc.removeEventListener('mouseup', binding.value.onClickOutsideElement); - doc.removeEventListener('scroll', binding.value.onScroll); + const expander = DirectiveUtilities.getRef(binding.value.expander, binding); + if (expander) { + $(expander).off('click', binding.value.onExpand!); + } + doc.removeEventListener('keyup', binding.value.onEscapeHandler!); + doc.removeEventListener('mousedown', binding.value.onMouseDown!); + doc.removeEventListener('mouseup', binding.value.onClickOutsideElement!); + doc.removeEventListener('scroll', binding.value.onScroll!); }, }; diff --git a/plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.adapter.ts b/plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.adapter.ts index 83ea6ff966..5dee0e351b 100644 --- a/plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.adapter.ts +++ b/plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.adapter.ts @@ -5,12 +5,13 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ +import { IScope } from 'angular'; import ExpandOnHover from './ExpandOnHover'; function piwikExpandOnHover() { return { restrict: 'A', - link: function expandOnHoverLink(scope, element) { + link: function expandOnHoverLink(scope: IScope, element: JQLite) { const binding = { instance: null, value: { @@ -27,6 +28,4 @@ function piwikExpandOnHover() { }; } -piwikExpandOnHover.$inject = []; - -angular.module('piwikApp').directive('piwikExpandOnHover', piwikExpandOnHover); +window.angular.module('piwikApp').directive('piwikExpandOnHover', piwikExpandOnHover); diff --git a/plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.ts b/plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.ts index 6d86d0b212..73afcd820d 100644 --- a/plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.ts +++ b/plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.ts @@ -7,10 +7,13 @@ import { DirectiveBinding } from 'vue'; import Matomo from '../Matomo/Matomo'; +import DirectiveUtilities from '../directiveUtilities'; interface ExpandOnHoverArgs { - expander: HTMLElement, + // input (provided by user) + expander: string | HTMLElement, + // event handlers onMouseEnter?: () => void; onMouseLeave?: () => void; onClickOutsideElement?: (event: MouseEvent) => void; @@ -59,15 +62,24 @@ export default { binding.value.onClickOutsideElement = onClickOutsideElement.bind(null, el); binding.value.onEscapeHandler = onEscapeHandler.bind(null, el); - binding.value.expander.addEventListener('mouseenter', binding.value.onMouseEnter); + setTimeout(() => { + const expander = DirectiveUtilities.getRef(binding.value.expander, binding); + if (expander) { + expander.addEventListener('mouseenter', binding.value.onMouseEnter!); + } + }); + el.addEventListener('mouseleave', binding.value.onMouseLeave); doc.addEventListener('keyup', binding.value.onEscapeHandler); doc.addEventListener('mouseup', binding.value.onClickOutsideElement); }, unmounted(el: HTMLElement, binding: DirectiveBinding<ExpandOnHoverArgs>): void { - binding.value.expander.removeEventListener('mouseenter', binding.value.onMouseEnter); - el.removeEventListener('mouseleave', binding.value.onMouseLeave); - document.removeEventListener('keyup', binding.value.onEscapeHandler); - document.removeEventListener('mouseup', binding.value.onClickOutsideElement); + const expander = DirectiveUtilities.getRef(binding.value.expander, binding); + if (expander) { + expander.removeEventListener('mouseenter', binding.value.onMouseEnter!); + } + el.removeEventListener('mouseleave', binding.value.onMouseLeave!); + document.removeEventListener('keyup', binding.value.onEscapeHandler!); + document.removeEventListener('mouseup', binding.value.onClickOutsideElement!); }, }; diff --git a/plugins/CoreHome/vue/src/FieldArray/FieldArray.adapter.ts b/plugins/CoreHome/vue/src/FieldArray/FieldArray.adapter.ts new file mode 100644 index 0000000000..43b533806e --- /dev/null +++ b/plugins/CoreHome/vue/src/FieldArray/FieldArray.adapter.ts @@ -0,0 +1,51 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { INgModelController } from 'angular'; +import createAngularJsAdapter from '../createAngularJsAdapter'; +import FieldArray from './FieldArray.vue'; + +export default createAngularJsAdapter({ + component: FieldArray, + require: '?ngModel', + scope: { + name: { + angularJsBind: '=', + }, + field: { + angularJsBind: '=', + }, + }, + directiveName: 'matomoFieldArray', + events: { + 'update:modelValue': (newValue, vm, scope, element, attrs, ngModel) => { + if (newValue !== vm.modelValue) { + element.trigger('change', newValue); + + if (ngModel) { + ngModel.$setViewValue(newValue); + } + } + }, + }, + postCreate(vm, scope, element, attrs, controller) { + const ngModel = controller as INgModelController; + + // setup ng-model mapping + if (ngModel) { + ngModel.$setViewValue(vm.modelValue); + + ngModel.$render = () => { + if (window.angular.isString(ngModel.$viewValue)) { + vm.modelValue = JSON.parse(ngModel.$viewValue); + } else { + vm.modelValue = ngModel.$viewValue; + } + }; + } + }, +}); diff --git a/plugins/CoreHome/angularjs/field-array/field-array.directive.less b/plugins/CoreHome/vue/src/FieldArray/FieldArray.less index 29f63392d7..29f63392d7 100644 --- a/plugins/CoreHome/angularjs/field-array/field-array.directive.less +++ b/plugins/CoreHome/vue/src/FieldArray/FieldArray.less diff --git a/plugins/CoreHome/vue/src/FieldArray/FieldArray.vue b/plugins/CoreHome/vue/src/FieldArray/FieldArray.vue new file mode 100644 index 0000000000..3721ddf976 --- /dev/null +++ b/plugins/CoreHome/vue/src/FieldArray/FieldArray.vue @@ -0,0 +1,89 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div class="fieldArray form-group"> + <div + class="fieldArrayTable multiple valign-wrapper" + v-for="(item, index) in modelValue" + :class="{[`fieldArrayTable${index}`]: true}" + :key="index" + > + <div + v-if="field.uiControl" + class="fieldUiControl" + > + <Field + :full-width="true" + :model-value="item" + :options="field.availableValues" + @update:modelValue="onEntryChange($event, index)" + :placeholder="' '" + :uicontrol="field.uiControl" + :title="field.title" + :name="`${name}-${index}`" + :template-file="field.templateFile" + :component="field.component" + > + </Field> + </div> + <span + @click="removeEntry(index)" + class="icon-minus valign" + v-show="index + 1 !== modelValue.length" + :title="translate('General_Remove')" + /> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import useExternalPluginComponent from '../useExternalPluginComponent'; + +// async since this is a a recursive component +const Field = useExternalPluginComponent('CorePluginsAdmin', 'Field'); + +export default defineComponent({ + props: { + modelValue: Array, + name: String, + field: Object, + }, + components: { + Field, + }, + emits: ['update:modelValue'], + watch: { + modelValue(newValue) { + this.checkEmptyModelValue(newValue); + }, + }, + mounted() { + this.checkEmptyModelValue(this.modelValue); + }, + methods: { + checkEmptyModelValue(newValue?: unknown[]) { + // make sure there is always an empty new value + if (!newValue || !newValue.length || newValue.slice(-1)[0] !== '') { + this.$emit('update:modelValue', [...(newValue || []), '']); + } + }, + onEntryChange(newValue: unknown, index: number) { + const newArrayValue = [...(this.modelValue || [])]; + newArrayValue[index] = newValue; + + this.$emit('update:modelValue', newArrayValue); + }, + removeEntry(index: number) { + if (index > -1 && this.modelValue) { + const newValue = this.modelValue.filter((x, i) => i !== index); + this.$emit('update:modelValue', newValue); + } + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.adapter.ts b/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.adapter.ts index 348a51cd73..5e272d6643 100644 --- a/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.adapter.ts +++ b/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.adapter.ts @@ -39,6 +39,7 @@ function piwikFocusAnywhereButHere(): IDirective { }; } -piwikFocusAnywhereButHere.$inject = []; - -angular.module('piwikApp.directive').directive('piwikFocusAnywhereButHere', piwikFocusAnywhereButHere); +window.angular.module('piwikApp.directive').directive( + 'piwikFocusAnywhereButHere', + piwikFocusAnywhereButHere, +); diff --git a/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.ts b/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.ts index dcfb3928f9..df31210a81 100644 --- a/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.ts +++ b/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.ts @@ -8,8 +8,10 @@ import { DirectiveBinding } from 'vue'; interface FocusAnywhereButHereArgs { + // input (provided by user) blur: () => void, + // state/event handlers isMouseDown?: boolean; hasScrolled?: boolean; onEscapeHandler?: (event: KeyboardEvent) => void; @@ -90,9 +92,9 @@ export default { doc.addEventListener('scroll', binding.value.onScroll); }, unmounted(el: HTMLElement, binding: DirectiveBinding<FocusAnywhereButHereArgs>): void { - doc.removeEventListener('keyup', binding.value.onEscapeHandler); - doc.removeEventListener('mousedown', binding.value.onMouseDown); - doc.removeEventListener('mouseup', binding.value.onClickOutsideElement); - doc.removeEventListener('scroll', binding.value.onScroll); + doc.removeEventListener('keyup', binding.value.onEscapeHandler!); + doc.removeEventListener('mousedown', binding.value.onMouseDown!); + doc.removeEventListener('mouseup', binding.value.onClickOutsideElement!); + doc.removeEventListener('scroll', binding.value.onScroll!); }, }; diff --git a/plugins/CoreHome/vue/src/FocusIf/FocusIf.adapter.ts b/plugins/CoreHome/vue/src/FocusIf/FocusIf.adapter.ts index 2d48e8f254..e02ef6c021 100644 --- a/plugins/CoreHome/vue/src/FocusIf/FocusIf.adapter.ts +++ b/plugins/CoreHome/vue/src/FocusIf/FocusIf.adapter.ts @@ -36,4 +36,4 @@ function piwikFocusIf(): IDirective { }; } -angular.module('piwikApp.directive').directive('piwikFocusIf', piwikFocusIf); +window.angular.module('piwikApp.directive').directive('piwikFocusIf', piwikFocusIf); diff --git a/plugins/CoreHome/vue/src/FocusIf/FocusIf.ts b/plugins/CoreHome/vue/src/FocusIf/FocusIf.ts index 6a13e46ff0..3a79d51e40 100644 --- a/plugins/CoreHome/vue/src/FocusIf/FocusIf.ts +++ b/plugins/CoreHome/vue/src/FocusIf/FocusIf.ts @@ -8,6 +8,7 @@ import { DirectiveBinding } from 'vue'; interface FocusIfArgs { + // input (provided by user) afterFocus?: () => void; } diff --git a/plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts b/plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts index 0ab71e38ef..9a6da109da 100644 --- a/plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts +++ b/plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts @@ -18,15 +18,14 @@ function initPiwikService(piwik: PiwikGlobal, $rootScope: IRootScopeService) { // overwrite $rootScope so all events also go through Matomo.postEvent(...) too. ($rootScope as any).$oldEmit = $rootScope.$emit; // eslint-disable-line $rootScope.$emit = function emitWrapper(name: string, ...args: any[]): IAngularEvent { // eslint-disable-line - Matomo.postEvent(name, ...args); - // can't always get the result. it's not really used in angularjs though, so it should be ok. - return null as unknown as IAngularEvent; + Matomo.postEventNoEmit(name, ...args); + return (this as any).$oldEmit(name, ...args); // eslint-disable-line }; ($rootScope as any).$oldBroadcast = $rootScope.$broadcast; // eslint-disable-line $rootScope.$broadcast = function broadcastWrapper(name: string, ...args: any[]): IAngularEvent { // eslint-disable-line Matomo.postEventNoEmit(name, ...args); - return ($rootScope as any).$oldBroadcast(name, ...args); // eslint-disable-line + return (this as any).$oldBroadcast(name, ...args); // eslint-disable-line }; $rootScope.$on('$locationChangeSuccess', piwik.updatePeriodParamsFromUrl); diff --git a/plugins/CoreHome/vue/src/Matomo/Matomo.ts b/plugins/CoreHome/vue/src/Matomo/Matomo.ts index 30b821f403..5db37c0882 100644 --- a/plugins/CoreHome/vue/src/Matomo/Matomo.ts +++ b/plugins/CoreHome/vue/src/Matomo/Matomo.ts @@ -24,7 +24,7 @@ piwik.updateDateInTitle = function updateDateInTitle(date: string, period: strin if (originalTitle.indexOf(piwik.siteName) === 0) { const dateString = ` - ${Periods.parse(period, date).getPrettyString()} `; - document.title = `${piwik.siteName}${dateString}${originalTitle.substr(piwik.siteName.length)}`; + document.title = `${piwik.siteName}${dateString}${originalTitle.slice(piwik.siteName.length)}`; } }; diff --git a/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts b/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts index ee03ce55c7..687bbabfc0 100644 --- a/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts +++ b/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts @@ -5,8 +5,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import { IParseService } from 'angular'; -import { ComponentPublicInstance } from 'vue'; +import { IParseService, IScope } from 'angular'; import MatomoDialog from './MatomoDialog.vue'; import createAngularJsAdapter from '../createAngularJsAdapter'; @@ -18,35 +17,35 @@ export default createAngularJsAdapter<[IParseService]>({ default: false, }, element: { - default: (scope, element) => element[0], + default: (scope: IScope, element: JQLite) => element[0], }, }, events: { - yes: ($event, scope, element, attrs) => { + yes: ($event, vm, scope, element, attrs) => { if (attrs.yes) { scope.$eval(attrs.yes); setTimeout(() => { scope.$apply(); }, 0); } }, - no: ($event, scope, element, attrs) => { + no: ($event, vm, scope, element, attrs) => { if (attrs.no) { scope.$eval(attrs.no); setTimeout(() => { scope.$apply(); }, 0); } }, - validation: ($event, scope, element, attrs) => { + validation: ($event, vm, scope, element, attrs) => { if (attrs.no) { scope.$eval(attrs.no); setTimeout(() => { scope.$apply(); }, 0); } }, - close: ($event, scope, element, attrs) => { + close: ($event, vm, scope, element, attrs) => { if (attrs.close) { scope.$eval(attrs.close); setTimeout(() => { scope.$apply(); }, 0); } }, - 'update:modelValue': (newValue, scope, element, attrs, $parse: IParseService) => { + 'update:modelValue': (newValue, vm, scope, element, attrs, controller, $parse: IParseService) => { setTimeout(() => { scope.$apply($parse(attrs.piwikDialog).assign(scope, newValue)); }, 0); @@ -60,7 +59,7 @@ export default createAngularJsAdapter<[IParseService]>({ vueRootPlaceholder.appendTo(element); return vueRootPlaceholder[0]; }, - postCreate: (vm: ComponentPublicInstance, scope, element, attrs) => { + postCreate: (vm, scope, element, attrs) => { scope.$watch(attrs.piwikDialog, (newValue: boolean, oldValue: boolean) => { if (oldValue !== newValue) { vm.modelValue = newValue || false; diff --git a/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue b/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue index 76c12c5807..2b871acf07 100644 --- a/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue +++ b/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue @@ -35,14 +35,15 @@ export default defineComponent({ required: false, }, }, - emits: ['yes', 'no', 'closeEnd', 'close', 'update:modelValue'], + emits: ['yes', 'no', 'closeEnd', 'close', 'validation', 'update:modelValue'], activated() { this.$emit('update:modelValue', false); }, watch: { modelValue(newValue, oldValue) { if (newValue) { - const slotElement = this.element || this.$refs.root.firstElementChild; + const slotElement = this.element + || (this.$refs.root as HTMLElement).firstElementChild as HTMLElement; Matomo.helper.modalConfirm(slotElement, { yes: () => { this.$emit('yes'); }, no: () => { this.$emit('no'); }, @@ -51,7 +52,7 @@ export default defineComponent({ onCloseEnd: () => { // materialize removes the child element, so we move it back to the slot if (!this.element) { - this.$refs.root.appendChild(slotElement); + (this.$refs.root as HTMLElement).appendChild(slotElement); } this.$emit('update:modelValue', false); this.$emit('closeEnd'); diff --git a/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.adapter.ts b/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.adapter.ts index b82329739b..2e3d69ccab 100644 --- a/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.adapter.ts +++ b/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.adapter.ts @@ -14,6 +14,7 @@ function piwikUrl() { return model; } -piwikUrl.$inject = []; +window.angular.module('piwikApp.service').service('piwikUrl', piwikUrl); -angular.module('piwikApp.service').service('piwikUrl', piwikUrl); +// make sure $location is initialized early +window.angular.module('piwikApp.service').run(['$location', () => null]); diff --git a/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.ts b/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.ts index 11eec228a8..9ab1dc54aa 100644 --- a/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.ts +++ b/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.ts @@ -5,7 +5,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import { ILocationService } from 'angular'; +import { ILocationService, ITimeoutService } from 'angular'; import { computed, ref, readonly } from 'vue'; import Matomo from '../Matomo/Matomo'; import { Periods, format } from '../Periods'; // important to load all periods here @@ -28,16 +28,16 @@ type ParsedQueryParameters = Record<string, unknown>; * URL store and helper functions. */ class MatomoUrl { - private urlQuery = ref(''); + readonly urlQuery = ref(''); - private hashQuery = ref(''); + readonly hashQuery = ref(''); readonly urlParsed = computed(() => readonly( - broadcast.getValuesFromUrl(`?${this.urlQuery.value}`, true) as ParsedQueryParameters, + this.parse(this.urlQuery.value) as ParsedQueryParameters, )); readonly hashParsed = computed(() => readonly( - broadcast.getValuesFromUrl(`?${this.hashQuery.value}`, true) as ParsedQueryParameters, + this.parse(this.hashQuery.value) as ParsedQueryParameters, )); readonly parsed = computed(() => readonly({ @@ -61,11 +61,69 @@ class MatomoUrl { this.updatePeriodParamsFromUrl(); } + updateHashToUrl(url: string) { + const $location: ILocationService = Matomo.helper.getAngularDependency('$location'); + $location.url(url); + } + updateHash(params: QueryParameters|string) { - const serializedParams: string = typeof params !== 'string' ? this.stringify(params) : params; + const modifiedParams = this.getFinalHashParams(params); + const serializedParams = this.stringify(modifiedParams); const $location: ILocationService = Matomo.helper.getAngularDependency('$location'); $location.search(serializedParams); + + const $timeout: ITimeoutService = Matomo.helper.getAngularDependency('$timeout'); + $timeout(); + } + + updateUrl(params: QueryParameters|string, hashParams: QueryParameters|string = {}) { + const serializedParams: string = typeof params !== 'string' ? this.stringify(params) : params; + + const modifiedHashParams = Object.keys(hashParams).length + ? this.getFinalHashParams(hashParams, params) + : {}; + + const serializedHashParams: string = this.stringify(modifiedHashParams); + + let url = `?${serializedParams}`; + if (serializedHashParams.length) { + url = `${url}#?${serializedHashParams}`; + } + + window.broadcast.propagateNewPage('', undefined, undefined, undefined, url); + } + + private getFinalHashParams( + params: QueryParameters|string, + urlParams: QueryParameters|string = {}, + ) { + const paramsObj = typeof params !== 'string' + ? params as QueryParameters + : this.parse(params as string); + + const urlParamsObj = typeof params !== 'string' + ? urlParams as QueryParameters + : this.parse(urlParams as string); + + return { + // these params must always be present in the hash + period: urlParamsObj.period || this.parsed.value.period, + date: urlParamsObj.date || this.parsed.value.date, + segment: urlParamsObj.segment || this.parsed.value.segment, + + ...paramsObj, + }; + } + + // if we're in an embedded context, loads an entire new URL, otherwise updates the hash + updateLocation(params: QueryParameters|string) { + if (Matomo.helper.isAngularRenderingThePage()) { + this.updateHash(params); + return; + } + + this.updateUrl(params); } getSearchParam(paramName: string): string { @@ -86,9 +144,21 @@ class MatomoUrl { return window.broadcast.getValueFromUrl(paramName, window.location.search); } + parse(query: string): QueryParameters { + return broadcast.getValuesFromUrl(`?${query}`, true); + } + stringify(search: QueryParameters): string { + const searchWithoutEmpty = Object.fromEntries( + Object.entries(search).filter(([, value]) => value !== '' && value !== null && value !== undefined), + ); + // TODO: using $ since URLSearchParams does not handle array params the way Matomo uses them - return $.param(search).replace(/%5B%5D/g, '[]'); + return $.param(searchWithoutEmpty).replace(/%5B%5D/g, '[]') + // some browsers treat URLs w/ date=a,b differently from date=a%2Cb, causing multiple + // entries to show up in the browser history. this has a compounding effect w/ angular.js, + // which when the back button is pressed to effectively abort the back navigation. + .replace(/%2C/g, ','); } updatePeriodParamsFromUrl(): void { diff --git a/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.adapter.ts b/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.adapter.ts index f56616f54d..99fa4dcaff 100644 --- a/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.adapter.ts +++ b/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.adapter.ts @@ -6,10 +6,10 @@ */ import createAngularJsAdapter from '../createAngularJsAdapter'; -import Menudropdown from './Menudropdown.vue'; +import MenuItemsDropdown from './MenuItemsDropdown.vue'; export default createAngularJsAdapter({ - component: Menudropdown, + component: MenuItemsDropdown, scope: { menuTitle: { angularJsBind: '@', @@ -27,7 +27,7 @@ export default createAngularJsAdapter({ directiveName: 'piwikMenudropdown', transclude: true, events: { - 'after-select': ($event, scope) => { + 'after-select': ($event, vm, scope) => { setTimeout(() => { scope.$apply(); }, 0); diff --git a/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.less b/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.less index 2a04d675df..2a04d675df 100644 --- a/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.less +++ b/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.less diff --git a/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue b/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue index fdd26bfdba..80b57eaabf 100644 --- a/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue +++ b/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue @@ -66,7 +66,7 @@ export default defineComponent({ menuTitle: String, tooltip: String, showSearch: Boolean, - menuTitleChangeOnClick: String, + menuTitleChangeOnClick: Boolean, }, directives: { FocusAnywhereButHere, @@ -98,14 +98,14 @@ export default defineComponent({ return; } - if (this.menuTitleChangeOnClick !== false) { - this.actualMenuTitle = (event.target as HTMLElement).textContent + if (this.menuTitleChangeOnClick) { + this.actualMenuTitle = ((event.target as HTMLElement).textContent || '') .replace(/[\u0000-\u2666]/g, (c) => `&#${c.charCodeAt(0)};`); // eslint-disable-line } this.showItems = false; - $(this.$slots.default()).find('.item').removeClass('active'); + $(this.$slots.default!()[0]!.el as HTMLElement).find('.item').removeClass('active'); targetClasses.add('active'); this.$emit('afterSelect'); @@ -118,7 +118,7 @@ export default defineComponent({ searchItems(unprocessedSearchTerm: string) { const searchTerm = unprocessedSearchTerm.toLowerCase(); - $(this.$refs.root).find('.item').each((index: number, node: HTMLElement) => { + $(this.$refs.root as HTMLElement).find('.item').each((index: number, node: HTMLElement) => { const $node = $(node); if ($node.text().toLowerCase().indexOf(searchTerm) === -1) { diff --git a/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.adapter.ts b/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.adapter.ts new file mode 100644 index 0000000000..3313d4c65e --- /dev/null +++ b/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.adapter.ts @@ -0,0 +1,60 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { INgModelController } from 'angular'; +import createAngularJsAdapter from '../createAngularJsAdapter'; +import MultiPairField from './MultiPairField.vue'; + +export default createAngularJsAdapter({ + component: MultiPairField, + require: '?ngModel', + scope: { + name: { + angularJsBind: '=', + }, + field1: { + angularJsBind: '=', + }, + field2: { + angularJsBind: '=', + }, + field3: { + angularJsBind: '=', + }, + field4: { + angularJsBind: '=', + }, + }, + directiveName: 'matomoMultiPairField', + events: { + 'update:modelValue': (newValue, vm, scope, element, attrs, ngModel) => { + if (newValue !== vm.modelValue) { + element.trigger('change', newValue); + + if (ngModel) { + ngModel.$setViewValue(newValue); + } + } + }, + }, + postCreate(vm, scope, element, attrs, controller) { + const ngModel = controller as INgModelController; + + // setup ng-model mapping + if (ngModel) { + ngModel.$setViewValue(vm.modelValue); + + ngModel.$render = () => { + if (window.angular.isString(ngModel.$viewValue)) { + vm.modelValue = JSON.parse(ngModel.$viewValue); + } else { + vm.modelValue = ngModel.$viewValue; + } + }; + } + }, +}); diff --git a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less b/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.less index 3a2f34c736..3a2f34c736 100644 --- a/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less +++ b/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.less diff --git a/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue b/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue new file mode 100644 index 0000000000..87a812d57e --- /dev/null +++ b/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue @@ -0,0 +1,211 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div class="multiPairField form-group"> + <div + v-for="(item, index) in modelValue" + class="multiPairFieldTable multiple valign-wrapper" + :class="{ [`multiPairFieldTable${index}`]: true, [`has${fieldCount}Fields`]: true }" + :key="index" + > + <div + class="fieldUiControl fieldUiControl1" + v-if="field1" + :class="{ hasMultiFields: field1.type && field2.type }" + > + <Field + :full-width="true" + v-model="item[field1.key]" + :options="field1.availableValues" + @update:modelValue="onEntryChange(index, field1.key, $event)" + :placeholder="' '" + :uicontrol="field1.uiControl" + :name="`${name}-p1-${index}`" + :title="field1.title" + :template-file="field1.templateFile" + :component="field1.component" + > + </Field> + </div> + <div + class="fieldUiControl fieldUiControl2" + v-if="field2" + > + <Field + :full-width="true" + :options="field2.availableValues" + @update:modelValue="onEntryChange(index, field2.key, $event)" + v-model="item[field2.key]" + :placeholder="' '" + :uicontrol="field2.uiControl" + :name="`${name}-p2-${index}`" + :title="field2.title" + :template-file="field2.templateFile" + :component="field2.component" + > + </Field> + </div> + <div + class="fieldUiControl fieldUiControl3" + v-if="field3" + > + <Field + :full-width="true" + :options="field3.availableValues" + @update:modelValue="onEntryChange(index, field3.key, $event)" + v-model="item[field3.key]" + :placeholder="' '" + :uicontrol="field3.uiControl" + :title="field3.title" + :template-file="field3.templateFile" + :component="field3.component" + > + </Field> + </div> + <div + class="fieldUiControl fieldUiControl4" + v-if="field4" + > + <Field + :full-width="true" + :options="field4.availableValues" + @update:modelValue="onEntryChange(index, field4.key, $event)" + v-model="item[field4.key]" + :placeholder="' '" + :uicontrol="field4.uiControl" + :title="field4.title" + :template-file="field4.templateFile" + :component="field4.component" + > + </Field> + </div> + <span + @click="removeEntry(index)" + class="icon-minus valign" + v-show="index + 1 !== modelValue.length" + :title="translate('General_Remove')" + /> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import useExternalPluginComponent from '../useExternalPluginComponent'; + +// async since this is a a recursive component +const Field = useExternalPluginComponent('CorePluginsAdmin', 'Field'); + +export default defineComponent({ + props: { + modelValue: Array, + name: String, + field1: Object, + field2: Object, + field3: Object, + field4: Object, + }, + components: { + Field, + }, + computed: { + fieldCount() { + if (this.field1 && this.field2 && this.field3 && this.field4) { + return 4; + } + + if (this.field1 && this.field2 && this.field3) { + return 3; + } + + if (this.field1 && this.field2) { + return 2; + } + + if (this.field1) { + return 1; + } + + return 0; + }, + }, + emits: ['update:modelValue'], + watch: { + modelValue(newValue?: Record<string, unknown>[]) { + this.checkEmptyModelValue(newValue); + }, + }, + mounted() { + this.checkEmptyModelValue(this.modelValue as Record<string, unknown>[]); + }, + methods: { + checkEmptyModelValue(newValue?: Record<string, unknown>[]) { + // make sure there is always an empty new value + if (!newValue + || !newValue.length + || this.isEmptyValue(newValue.slice(-1)[0]) + ) { + this.$emit('update:modelValue', [...(newValue || []), this.makeEmptyValue()]); + } + }, + onEntryChange(index: number, key: string, newValue: Record<string, unknown>) { + const newWholeValue = [...(this.modelValue as Record<string, unknown>[])]; + newWholeValue[index] = { ...newWholeValue[index], [key]: newValue }; + this.$emit('update:modelValue', newWholeValue); + }, + removeEntry(index: number) { + if (index > -1 && this.modelValue) { + const newValue = this.modelValue.filter((x, i) => i !== index); + this.$emit('update:modelValue', newValue); + } + }, + isEmptyValue(value: Record<string, unknown>) { + const { fieldCount } = this; + + if (fieldCount === 4) { + if (!value[this.field1!.key] + && !value[this.field2!.key] + && !value[this.field3!.key] + && !value[this.field4!.key] + ) { + return false; + } + } else if (fieldCount === 3) { + if (!value[this.field1!.key] && !value[this.field2!.key] && !value[this.field3!.key]) { + return false; + } + } else if (fieldCount === 2) { + if (!value[this.field1!.key] && !value[this.field2!.key]) { + return false; + } + } else if (fieldCount === 1) { + if (!value[this.field1!.key]) { + return false; + } + } + + return true; + }, + makeEmptyValue(): Record<string, unknown> { + const result: Record<string, unknown> = {}; + if (this.field1 && this.field1.key) { + result[this.field1.key] = ''; + } + if (this.field2 && this.field2.key) { + result[this.field2.key] = ''; + } + if (this.field3 && this.field3.key) { + result[this.field3.key] = ''; + } + if (this.field4 && this.field4.key) { + result[this.field4.key] = ''; + } + return result; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/Notification/Notification.adapter.ts b/plugins/CoreHome/vue/src/Notification/Notification.adapter.ts index 5845718976..4ff27943e9 100644 --- a/plugins/CoreHome/vue/src/Notification/Notification.adapter.ts +++ b/plugins/CoreHome/vue/src/Notification/Notification.adapter.ts @@ -5,7 +5,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import createAngularJsAdapter from '../createAngularJsAdapter'; +import createAngularJsAdapter, { transformAngularJsBoolAttr } from '../createAngularJsAdapter'; import Notification from './Notification.vue'; export default createAngularJsAdapter({ @@ -25,7 +25,7 @@ export default createAngularJsAdapter({ }, noclear: { angularJsBind: '@?', - transform: (v) => !!v, + transform: transformAngularJsBoolAttr, }, toastLength: { angularJsBind: '@?', diff --git a/plugins/CoreHome/vue/src/Notification/Notification.less b/plugins/CoreHome/vue/src/Notification/Notification.less index 9bafc751c9..a99d63be14 100644 --- a/plugins/CoreHome/vue/src/Notification/Notification.less +++ b/plugins/CoreHome/vue/src/Notification/Notification.less @@ -40,7 +40,7 @@ } &.notification-warning { .alert-warning; - background-color: #f57c00; + background-color: @color-orange-brand; color: #fbf7f1 !important; &:before, p, a { color: #fbf7f1; diff --git a/plugins/CoreHome/vue/src/Notification/Notification.ts b/plugins/CoreHome/vue/src/Notification/Notification.ts new file mode 100644 index 0000000000..8ddfcd62f2 --- /dev/null +++ b/plugins/CoreHome/vue/src/Notification/Notification.ts @@ -0,0 +1,87 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +interface Notification { + /** + * Only needed for persistent notifications. The id will be sent to the + * frontend once the user closes the notifications. The notification has to + * be registered/notified under this name. + */ + id?: string; + + /** + * Unique ID generated for the notification so it can be referenced specifically + * to scroll to. + */ + notificationInstanceId?: string; + + /** + * Determines which notification group a notification is meant to be displayed + * in. + */ + group?: string; + + /** + * The title of the notification. For instance the plugin name. + */ + title?: string; + + /** + * The actual message that will be displayed. Must be set. + */ + message: string; + + /** + * Context of the notification: 'info', 'warning', 'success' or 'error' + */ + context: 'success'|'error'|'info'|'warning'; + + /** + * The type of the notification: Either 'toast' or 'transient'. 'persistent' is valid, but + * has no effect if only specified client side. + * + * 'help' is only used by ReportingMenu.vue. + */ + type: 'toast'|'persistent'|'transient'|'help'; + + /** + * If set, the close icon is not displayed. + */ + noclear?: boolean; + + /** + * The number of milliseconds before a toast animation disappears. + */ + toastLength?: number; + + /** + * Optional style/css dictionary. For instance {'display': 'inline-block'} + */ + style?: string|Record<string, unknown>; + + /** + * Optional CSS class to add. + */ + class?: string; + + /** + * If true, fades the animation in. + */ + animate?: boolean; + + /** + * Where to place the notification. Required if showing a toast. + */ + placeat?: string|HTMLElement|JQuery; + + /** + * If true, the notification will be displayed before others currently displayed. + */ + prepend?: boolean; +} + +export default Notification; diff --git a/plugins/CoreHome/vue/src/Notification/Notification.vue b/plugins/CoreHome/vue/src/Notification/Notification.vue index e25dcb1711..0047e10bad 100644 --- a/plugins/CoreHome/vue/src/Notification/Notification.vue +++ b/plugins/CoreHome/vue/src/Notification/Notification.vue @@ -108,7 +108,7 @@ export default defineComponent({ } if (this.style) { - $(this.$refs.root).css(this.style); + $(this.$refs.root as HTMLElement).css(this.style as JQLiteCssProperties); } }, methods: { @@ -132,13 +132,13 @@ export default defineComponent({ if (!this.notificationId) { return; } - - AjaxHelper.fetch({ // GET params + AjaxHelper.post({ // GET params module: 'CoreHome', action: 'markNotificationAsRead', }, { // POST params - postParams: { notificationId: this.notificationId }, - }); + notificationId: this.notificationId, + }, + { withTokenInUrl: true }); }, }, }); diff --git a/plugins/CoreHome/vue/src/Notification/Notifications.store.adapter.ts b/plugins/CoreHome/vue/src/Notification/Notifications.store.adapter.ts index 95cacccbcd..e759836e4c 100644 --- a/plugins/CoreHome/vue/src/Notification/Notifications.store.adapter.ts +++ b/plugins/CoreHome/vue/src/Notification/Notifications.store.adapter.ts @@ -7,4 +7,4 @@ import NotificationsStore from './Notifications.store'; -angular.module('piwikApp').factory('notifications', () => NotificationsStore); +window.angular.module('piwikApp').factory('notifications', () => NotificationsStore); diff --git a/plugins/CoreHome/vue/src/Notification/Notifications.store.ts b/plugins/CoreHome/vue/src/Notification/Notifications.store.ts index e014e9beda..701bddee17 100644 --- a/plugins/CoreHome/vue/src/Notification/Notifications.store.ts +++ b/plugins/CoreHome/vue/src/Notification/Notifications.store.ts @@ -9,97 +9,28 @@ import { DeepReadonly, reactive, createVNode, - createApp, + readonly, } from 'vue'; import NotificationComponent from './Notification.vue'; -import translate from '../translate'; import Matomo from '../Matomo/Matomo'; - -interface Notification { - /** - * Only needed for persistent notifications. The id will be sent to the - * frontend once the user closes the notifications. The notification has to - * be registered/notified under this name. - */ - id?: string; - - /** - * Unique ID generated for the notification so it can be referenced specifically - * to scroll to. - */ - notificationInstanceId: string; - - /** - * Determines which notification group a notification is meant to be displayed - * in. - */ - group?: string; - - /** - * The title of the notification. For instance the plugin name. - */ - title?: string; - - /** - * The actual message that will be displayed. Must be set. - */ - message: string; - - /** - * Context of the notification: 'info', 'warning', 'success' or 'error' - */ - context: 'success'|'error'|'info'|'warning'; - - /** - * The type of the notification: Either 'toast' or 'transient'. 'persistent' is valid, but - * has no effect if only specified client side. - */ - type: 'toast'|'persistent'|'transient'; - - /** - * If set, the close icon is not displayed. - */ - noclear?: boolean; - - /** - * The number of milliseconds before a toast animation disappears. - */ - toastLength?: number; - - /** - * Optional style/css dictionary. For instance {'display': 'inline-block'} - */ - style?: string|Record<string, unknown>; - - /** - * Optional CSS class to add. - */ - class?: string; - - /** - * If true, fades the animation in. - */ - animate?: boolean; - - /** - * Where to place the notification. Required if showing a toast. - */ - placeat?: string|HTMLElement|JQuery; -} +import createVueApp from '../createVueApp'; +import Notification from './Notification'; interface NotificationsData { notifications: Notification[]; } +const { $ } = window; + class NotificationsStore { - private privateState: NotificationsData = reactive<NotificationsData>({ + private privateState = reactive<NotificationsData>({ notifications: [], }); private nextNotificationId = 0; get state(): DeepReadonly<NotificationsData> { - return this.privateState; + return readonly(this.privateState); } appendNotification(notification: Notification): void { @@ -134,14 +65,14 @@ class NotificationsStore { parseNotificationDivs(): void { const $notificationNodes = $('[data-role="notification"]'); - const notificationsToShow = []; - $notificationNodes.each((index, notificationNode) => { + const notificationsToShow: Notification[] = []; + $notificationNodes.each((index: number, notificationNode: HTMLElement) => { const $notificationNode = $(notificationNode); const attributes = $notificationNode.data(); const message = $notificationNode.html(); if (message) { - notificationsToShow.push({ ...attributes, message, animate: false }); + notificationsToShow.push({ ...attributes, message, animate: false } as Notification); } $notificationNodes.remove(); @@ -162,23 +93,28 @@ class NotificationsStore { show(notification: Notification): string { this.checkMessage(notification.message); - let addMethod = this.appendNotification; + let addMethod = notification.prepend ? this.prependNotification : this.appendNotification; - let notificationPosition: typeof Notification['placeat'] = '#notificationContainer'; + let notificationPosition: Notification['placeat'] = '#notificationContainer'; if (notification.placeat) { notificationPosition = notification.placeat; } else { // If a modal is open, we want to make sure the error message is visible and therefore // show it within the opened modal const modalSelector = '.modal.open .modal-content'; - if (document.querySelector(modalSelector)) { - notificationPosition = modalSelector; + const modal = document.querySelector(modalSelector); + if (modal) { + if (!modal.querySelector('#modalNotificationContainer')) { + $(modal).prepend('<div id="modalNotificationContainer"/>'); + } + + notificationPosition = `${modalSelector} #modalNotificationContainer`; addMethod = this.prependNotification; } } const group = notification.group - || (notification.placeat ? notification.placeat.toString() : ''); + || (notificationPosition ? notificationPosition.toString() : ''); this.initializeNotificationContainer(notificationPosition, group); @@ -198,7 +134,9 @@ class NotificationsStore { scrollToNotification(notificationInstanceId: string) { setTimeout(() => { - const element = document.querySelector(`[data-notification-instance-id='${notificationInstanceId}']`); + const element = document.querySelector( + `[data-notification-instance-id='${notificationInstanceId}']`, + ) as HTMLElement; if (element) { Matomo.helper.lazyScrollTo(element, 250); } @@ -211,19 +149,19 @@ class NotificationsStore { toast(notification: Notification): void { this.checkMessage(notification.message); - const $placeat = $(notification.placeat); - if (!$placeat.length) { + const $placeat = notification.placeat ? $(notification.placeat) : undefined; + if (!$placeat || !$placeat.length) { throw new Error('A valid selector is required for the placeat option when using Notification.toast().'); } const toastElement = document.createElement('div'); toastElement.style.position = 'absolute'; - toastElement.style.top = `${$placeat.offset().top}px`; - toastElement.style.left = `${$placeat.offset().left}px`; + toastElement.style.top = `${$placeat.offset()!.top}px`; + toastElement.style.left = `${$placeat.offset()!.left}px`; toastElement.style.zIndex = '1000'; document.body.appendChild(toastElement); - const app = createApp({ + const app = createVueApp({ render: () => createVNode(NotificationComponent, { ...notification, notificationId: notification.id, @@ -233,16 +171,18 @@ class NotificationsStore { }, }), }); - app.config.globalProperties.$sanitize = window.vueSanitize; - app.config.globalProperties.translate = translate; app.mount(toastElement); } private initializeNotificationContainer( - notificationPosition: typeof Notification['placeat'], + notificationPosition: Notification['placeat'], group: string, ) { - const $container = window.$(notificationPosition); + if (!notificationPosition) { + return; + } + + const $container = $(notificationPosition); if ($container.children('.notification-group').length) { return; } @@ -251,12 +191,10 @@ class NotificationsStore { // to be dynamically initialized. const NotificationGroup = (window as any).CoreHome.NotificationGroup; // eslint-disable-line - const app = createApp({ + const app = createVueApp({ template: '<NotificationGroup :group="group"></NotificationGroup>', data: () => ({ group }), }); - app.config.globalProperties.$sanitize = window.vueSanitize; - app.config.globalProperties.translate = translate; app.component('NotificationGroup', NotificationGroup); app.mount($container[0]); } diff --git a/plugins/CoreHome/vue/src/Notification/index.ts b/plugins/CoreHome/vue/src/Notification/index.ts index abcc74b952..a7a929a5bb 100644 --- a/plugins/CoreHome/vue/src/Notification/index.ts +++ b/plugins/CoreHome/vue/src/Notification/index.ts @@ -10,3 +10,4 @@ import './Notifications.store.adapter'; export { default as Notification } from './Notification.vue'; export { default as NotificationGroup } from './NotificationGroup.vue'; export { default as NotificationsStore } from './Notifications.store'; +export { default as NotificationType } from './Notification'; diff --git a/plugins/CoreHome/vue/src/Orderable.ts b/plugins/CoreHome/vue/src/Orderable.ts new file mode 100644 index 0000000000..7b8cfd32a8 --- /dev/null +++ b/plugins/CoreHome/vue/src/Orderable.ts @@ -0,0 +1,26 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +export interface Orderable { + order: number; +} + +export function sortOrderables<T extends Orderable>(menu?: ReadonlyArray<T>): T[] { + const result = [...(menu || [])]; + result.sort((lhs, rhs) => { + if (lhs.order < rhs.order) { + return -1; + } + + if (lhs.order > rhs.order) { + return 1; + } + + return 0; + }); + return result; +} diff --git a/plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue b/plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue index ab0e8c19f8..49c05a4a4f 100644 --- a/plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue +++ b/plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue @@ -22,17 +22,19 @@ <script lang="ts"> import { defineComponent, watch, ref } from 'vue'; -import JQuery = JQuery; import DatePicker from '../DatePicker/DatePicker.vue'; import Matomo from '../Matomo/Matomo'; -import Periods from '../Periods/Periods'; +import { Periods, parseDate } from '../Periods'; const piwikMinDate = new Date(Matomo.minDateYear, Matomo.minDateMonth - 1, Matomo.minDateDay); const piwikMaxDate = new Date(Matomo.maxDateYear, Matomo.maxDateMonth - 1, Matomo.maxDateDay); export default defineComponent({ props: { - period: String, + period: { + type: String, + required: true, + }, date: [String, Date], }, components: { @@ -40,9 +42,9 @@ export default defineComponent({ }, emits: ['select'], setup(props, context) { - const viewDate = ref(props.date); - const selectedDates = ref([null, null]); - const highlightedDates = ref([null, null]); + const viewDate = ref<string|Date|undefined|null>(props.date); + const selectedDates = ref<(Date|null)[]>([null, null]); + const highlightedDates = ref<(Date|null)[]>([null, null]); function getBoundedDateRange(date: string|Date) { const dates = Periods.get(props.period).parse(date).getDateRange(); @@ -83,10 +85,12 @@ export default defineComponent({ function onChanges() { if (!props.period || !props.date) { selectedDates.value = [null, null]; + viewDate.value = null; return; } selectedDates.value = getBoundedDateRange(props.date); + viewDate.value = parseDate(props.date); } watch(props, onChanges); diff --git a/plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.adapter.ts b/plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.adapter.ts new file mode 100644 index 0000000000..6fa84325a2 --- /dev/null +++ b/plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.adapter.ts @@ -0,0 +1,19 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import PeriodSelector from './PeriodSelector.vue'; + +export default createAngularJsAdapter({ + component: PeriodSelector, + scope: { + periods: { + angularJsBind: '<', + }, + }, + directiveName: 'piwikPeriodSelector', +}); diff --git a/plugins/CoreHome/angularjs/period-selector/period-selector.directive.less b/plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.less index a4a3d74897..257c8753d5 100644 --- a/plugins/CoreHome/angularjs/period-selector/period-selector.directive.less +++ b/plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.less @@ -1,4 +1,4 @@ -[piwik-period-selector] { +[piwik-period-selector],.periodSelector { display: inline-block; &.compare-dropdown-open { @@ -24,6 +24,7 @@ span { padding-left:25px; font-size: 14px; + margin-right: 3px; } } } @@ -83,9 +84,9 @@ } .compare-dates-separator { - height: 1px; - margin-left: 8px; - margin-right: 8px; + height: 0.5px; + margin-left: 11px; + margin-right: 11px; background-color: @color-silver-l14; width: 16px; display: inline-block; diff --git a/plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue b/plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue new file mode 100644 index 0000000000..15f8d10e78 --- /dev/null +++ b/plugins/CoreHome/vue/src/PeriodSelector/PeriodSelector.vue @@ -0,0 +1,550 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div + ref="root" + class="periodSelector piwikSelector" + v-expand-on-click="{ expander: 'title' }" + > + <a + ref="title" + id="date" + class="title" + tabindex="-1" + :title="translate('General_ChooseDate', currentlyViewingText)" + > + <span class="icon icon-calendar" /> + {{ currentlyViewingText }} + </a> + <div + id="periodMore" + class="dropdown" + > + <div class="flex"> + <div> + <DateRangePicker + v-show="selectedPeriod === 'range'" + class="period-range" + :start-date="startRangeDate" + :end-date="endRangeDate" + @range-change="onRangeChange($event.start, $event.end)" + @submit="onApplyClicked()" + > + </DateRangePicker> + <div + class="period-date" + v-if="selectedPeriod !== 'range'" + > + <PeriodDatePicker + id="datepicker" + :period="selectedPeriod" + :date="periodValue === selectedPeriod ? dateValue : null" + @select="setPiwikPeriodAndDate(selectedPeriod, $event.date)" + > + </PeriodDatePicker> + </div> + </div> + <div class="period-type"> + <h6>{{ translate('General_Period') }}</h6> + <div id="otherPeriods"> + <p + v-for="period in periodsFiltered" + :key="period" + > + <label + :class="{ 'selected-period-label': period === selectedPeriod }" + @dblclick="changeViewedPeriod(period)" + :title="period === periodValue + ? '' + : translate('General_DoubleClickToChangePeriod')" + > + <input + type="radio" + name="period" + :id="`period_id_${ period }`" + v-model="selectedPeriod" + :checked="selectedPeriod === period" + @change="selectedPeriod = period" + @dblclick="changeViewedPeriod(period)" + /> + <span>{{ getPeriodDisplayText(period) }}</span> + </label> + </p> + </div> + </div> + </div> + <div + class="compare-checkbox" + v-if="isComparisonEnabled" + > + <label> + <input + id="comparePeriodTo" + type="checkbox" + v-model="isComparing" + /> + <span>{{ translate('General_CompareTo') }}</span> + </label> + <div id="comparePeriodToDropdown"> + <Field + v-model="comparePeriodType" + :style="{'visibility': isComparing ? 'visible' : 'hidden'}" + :name="'comparePeriodToDropdown'" + :uicontrol="'select'" + :options="comparePeriodDropdownOptions" + :full-width="true" + :disabled="!isComparing" + /> + </div> + </div> + <div + class="compare-date-range" + v-if="isComparing && comparePeriodType === 'custom'" + > + <div> + <div id="comparePeriodStartDate"> + <div> + <Field + v-model="compareStartDate" + :name="'comparePeriodStartDate'" + :uicontrol="'text'" + :full-width="true" + :title="translate('CoreHome_StartDate')" + :placeholder="'YYYY-MM-DD'" + /> + </div> + </div> + <span class="compare-dates-separator" /> + <div id="comparePeriodEndDate"> + <div> + <Field + v-model="compareEndDate" + :name="'comparePeriodEndDate'" + :uicontrol="'text'" + :full-width="true" + :title="translate('CoreHome_EndDate')" + :placeholder="'YYYY-MM-DD'" + /> + </div> + </div> + </div> + </div> + <div class="apply-button-container"> + <input + type="submit" + id="calendarApply" + class="btn" + @click="onApplyClicked()" + :disabled="!isApplyEnabled()" + :value="translate('General_Apply')" + /> + </div> + <div + id="ajaxLoadingCalendar" + v-if="isLoadingNewPage" + > + <ActivityIndicator + :loading="true" + /> + <div class="loadingSegment"> + {{ translate('SegmentEditor_LoadingSegmentedDataMayTakeSomeTime') }} + </div> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent, watch } from 'vue'; +import ExpandOnClick from '../ExpandOnClick/ExpandOnClick'; +import DateRangePicker from '../DateRangePicker/DateRangePicker.vue'; +import PeriodDatePicker from '../PeriodDatePicker/PeriodDatePicker.vue'; +import ActivityIndicator from '../ActivityIndicator/ActivityIndicator.vue'; +import Matomo from '../Matomo/Matomo'; +import { translate } from '../translate'; +import ComparisonsStore from '../Comparisons/Comparisons.store.instance'; +import useExternalPluginComponent from '../useExternalPluginComponent'; +import { + Periods, + parseDate, + Range, + format, +} from '../Periods'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; + +const Field = useExternalPluginComponent('CorePluginsAdmin', 'Field'); + +const NBSP = Matomo.helper.htmlDecode(' '); + +const COMPARE_PERIOD_OPTIONS = [ + { key: 'custom', value: translate('General_Custom') }, + { + key: 'previousPeriod', + value: translate('General_PreviousPeriod').replace(/\s+/, NBSP), + }, + { + key: 'previousYear', + value: translate('General_PreviousYear').replace(/\s+/, NBSP), + }, +]; + +const piwikMinDate = new Date(Matomo.minDateYear, Matomo.minDateMonth - 1, Matomo.minDateDay); +const piwikMaxDate = new Date(Matomo.maxDateYear, Matomo.maxDateMonth - 1, Matomo.maxDateDay); + +function isValidDate(d: any) { // eslint-disable-line @typescript-eslint/no-explicit-any + if (Object.prototype.toString.call(d) !== '[object Date]') { + return false; + } + + return !Number.isNaN(d.getTime()); +} + +interface PeriodSelectorState { + comparePeriodDropdownOptions: typeof COMPARE_PERIOD_OPTIONS; + periodValue: string; + dateValue: Date|null; + selectedPeriod: string; + startRangeDate: string|null; + endRangeDate: string|null; + isRangeValid: boolean|null; + isLoadingNewPage: boolean; + isComparing: null|boolean; + comparePeriodType: string; + compareStartDate: string; + compareEndDate: string; +} + +export default defineComponent({ + props: { + periods: Array, + }, + components: { + DateRangePicker, + PeriodDatePicker, + Field, + ActivityIndicator, + }, + directives: { + ExpandOnClick, + }, + data(): PeriodSelectorState { + const selectedPeriod = MatomoUrl.parsed.value.period as string; + return { + comparePeriodDropdownOptions: COMPARE_PERIOD_OPTIONS, + periodValue: selectedPeriod, + dateValue: null, + selectedPeriod, + startRangeDate: null, + endRangeDate: null, + isRangeValid: null, + isLoadingNewPage: false, + isComparing: null, + comparePeriodType: 'previousPeriod', + compareStartDate: '', + compareEndDate: '', + }; + }, + mounted() { + Matomo.on('hidePeriodSelector', () => { + window.$(this.$refs.root as HTMLElement).hide(); + }); + + // some widgets might hide the period selector using the event above, so ensure it's + // shown again when switching the page + Matomo.on('piwikPageChange', () => { + window.$(this.$refs.root as HTMLElement).show(); + }); + + this.updateSelectedValuesFromHash(); + watch(() => MatomoUrl.parsed.value, this.updateSelectedValuesFromHash); + + this.isComparing = ComparisonsStore.isComparingPeriods(); + watch(() => ComparisonsStore.isComparingPeriods(), (newVal) => { + this.isComparing = newVal; + }); + + window.initTopControls(); // must be called when a top control changes width + + this.handleZIndexPositionRelativeCompareDropdownIssue(); + }, + computed: { + currentlyViewingText() { + let date; + if (this.periodValue === 'range') { + if (!this.startRangeDate || !this.endRangeDate) { + return translate('General_Error'); + } + + date = `${this.startRangeDate},${this.endRangeDate}`; + } else { + if (!this.dateValue) { + return translate('General_Error'); + } + + date = format(this.dateValue); + } + + try { + return Periods.parse(this.periodValue!, date).getPrettyString(); + } catch (e) { + return translate('General_Error'); + } + }, + isComparisonEnabled() { + return ComparisonsStore.isComparisonEnabled(); + }, + periodsFiltered() { + return (this.periods as string[] || []).filter( + (periodLabel) => Periods.isRecognizedPeriod(periodLabel), + ); + }, + selectedComparisonParams() { + if (!this.isComparing) { + return {}; + } + + if (this.comparePeriodType === 'custom') { + return { + comparePeriods: ['range'], + compareDates: [`${this.compareStartDate},${this.compareEndDate}`], + }; + } + + if (this.comparePeriodType === 'previousPeriod') { + return { + comparePeriods: [this.selectedPeriod], + compareDates: [this.previousPeriodDateToSelectedPeriod], + }; + } + + if (this.comparePeriodType === 'previousYear') { + const dateStr = this.selectedPeriod === 'range' + ? `${this.startRangeDate},${this.endRangeDate}` + : format(this.dateValue!); + + const currentDateRange = Periods.parse( + this.selectedPeriod as string, + dateStr, + ).getDateRange(); + currentDateRange[0].setFullYear(currentDateRange[0].getFullYear() - 1); + currentDateRange[1].setFullYear(currentDateRange[1].getFullYear() - 1); + + if (this.selectedPeriod === 'range') { + return { + comparePeriods: ['range'], + compareDates: [`${format(currentDateRange[0])},${format(currentDateRange[1])}`], + }; + } + + return { + comparePeriods: [this.selectedPeriod], + compareDates: [format(currentDateRange[0])], + }; + } + + console.warn(`Unknown compare period type: ${this.comparePeriodType}`); + return {}; + }, + previousPeriodDateToSelectedPeriod() { + if (this.selectedPeriod === 'range') { + const currentStartRange = parseDate(this.startRangeDate!); + const currentEndRange = parseDate(this.endRangeDate!); + const newEndDate = Range.getLastNRange('day', 2, currentStartRange).startDate; + + const rangeSize = Math.floor( + (currentEndRange.valueOf() - currentStartRange.valueOf()) / 86400000, + ); + const newRange = Range.getLastNRange('day', 1 + rangeSize, newEndDate); + + return `${format(newRange.startDate)},${format(newRange.endDate)}`; + } + + const newStartDate = Range.getLastNRange(this.selectedPeriod, 2, this.dateValue!).startDate; + return format(newStartDate); + }, + selectedDateString() { + if (this.selectedPeriod === 'range') { + const dateFrom = this.startRangeDate!; + const dateTo = this.endRangeDate!; + const oDateFrom = parseDate(dateFrom); + const oDateTo = parseDate(dateTo); + + if (!isValidDate(oDateFrom) + || !isValidDate(oDateTo) + || oDateFrom > oDateTo + ) { + // TODO: use a notification instead? + window.$('#alert') + .find('h2') + .text(translate('General_InvalidDateRange')); + Matomo.helper.modalConfirm('#alert', {}); + return null; + } + + return `${dateFrom},${dateTo}`; + } + + return format(this.dateValue!); + }, + }, + methods: { + handleZIndexPositionRelativeCompareDropdownIssue() { + const $element = window.$(this.$refs.root as HTMLElement); + $element.on('focus', '#comparePeriodToDropdown .select-dropdown', () => { + $element.addClass('compare-dropdown-open'); + }).on('blur', '#comparePeriodToDropdown .select-dropdown', () => { + $element.removeClass('compare-dropdown-open'); + }); + }, + changeViewedPeriod(period: string) { + // only change period if it's different from what's being shown currently + if (period === this.periodValue) { + return; + } + + // can't just change to a range period, w/o setting two new dates + if (period === 'range') { + return; + } + + this.setPiwikPeriodAndDate(period, this.dateValue!); + }, + setPiwikPeriodAndDate(period: string, date: Date) { + this.periodValue = period; + this.selectedPeriod = period; + this.dateValue = date; + + const currentDateString = format(date); + this.setRangeStartEndFromPeriod(period, currentDateString); + + this.propagateNewUrlParams(currentDateString, this.selectedPeriod); + + window.initTopControls(); + }, + propagateNewUrlParams(date: string, period: string) { + const compareParams = this.selectedComparisonParams; + + let baseParams: Record<string, unknown>; + if (Matomo.helper.isAngularRenderingThePage()) { + this.closePeriodSelector(); + baseParams = MatomoUrl.hashParsed.value; + } else { + this.isLoadingNewPage = true; + baseParams = MatomoUrl.parsed.value; + } + + // get params without comparePeriods/compareSegments/compareDates + const paramsWithoutCompare = { ...baseParams }; + delete paramsWithoutCompare.comparePeriods; + delete paramsWithoutCompare.compareDates; + + MatomoUrl.updateLocation({ + ...paramsWithoutCompare, + date, + period, + ...compareParams, + }); + }, + onApplyClicked() { + if (this.selectedPeriod === 'range') { + const dateString = this.selectedDateString; + if (!dateString) { + return; + } + + this.periodValue = 'range'; + + this.propagateNewUrlParams(dateString, 'range'); + return; + } + + this.setPiwikPeriodAndDate(this.selectedPeriod, this.dateValue!); + }, + updateSelectedValuesFromHash() { + const date = MatomoUrl.parsed.value.date as string; + const period = MatomoUrl.parsed.value.period as string; + + this.periodValue = period; + this.selectedPeriod = period; + + this.dateValue = null; + this.startRangeDate = null; + this.endRangeDate = null; + + try { + Periods.parse(period, date); + } catch (e) { + return; + } + + if (period === 'range') { + const periodObj = Periods.get(period).parse(date) as Range; + + const [startDate, endDate] = periodObj.getDateRange(); + this.dateValue = startDate; + this.startRangeDate = format(startDate); + this.endRangeDate = format(endDate); + } else { + this.dateValue = parseDate(date); + this.setRangeStartEndFromPeriod(period, date); + } + }, + setRangeStartEndFromPeriod(period: string, dateStr: string) { + const dateRange = Periods.parse(period, dateStr).getDateRange(); + this.startRangeDate = format(dateRange[0] < piwikMinDate ? piwikMinDate : dateRange[0]); + this.endRangeDate = format(dateRange[1] > piwikMaxDate ? piwikMaxDate : dateRange[1]); + }, + getPeriodDisplayText(periodLabel: string) { + return Periods.get(periodLabel).getDisplayText(); + }, + onRangeChange(start: string, end: string) { + if (!start || !end) { + this.isRangeValid = false; + return; + } + + this.isRangeValid = true; + this.startRangeDate = start; + this.endRangeDate = end; + }, + isApplyEnabled() { + if (this.selectedPeriod === 'range' + && !this.isRangeValid + ) { + return false; + } + + if (this.isComparing + && this.comparePeriodType === 'custom' + && !this.isCompareRangeValid() + ) { + return false; + } + + return true; + }, + closePeriodSelector() { + (this.$refs.root as HTMLElement).classList.remove('expanded'); + }, + isCompareRangeValid() { + try { + parseDate(this.compareStartDate); + } catch (e) { + return false; + } + + try { + parseDate(this.compareEndDate); + } catch (e) { + return false; + } + + return true; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/Periods/Day.ts b/plugins/CoreHome/vue/src/Periods/Day.ts index f4150d9a35..f6a49efa07 100644 --- a/plugins/CoreHome/vue/src/Periods/Day.ts +++ b/plugins/CoreHome/vue/src/Periods/Day.ts @@ -5,7 +5,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import translate from '../translate'; +import { translate } from '../translate'; import Periods from './Periods'; import { parseDate, format, todayIsInRange } from './utilities'; diff --git a/plugins/CoreHome/vue/src/Periods/Month.ts b/plugins/CoreHome/vue/src/Periods/Month.ts index 2924745912..ea19981dbc 100644 --- a/plugins/CoreHome/vue/src/Periods/Month.ts +++ b/plugins/CoreHome/vue/src/Periods/Month.ts @@ -5,7 +5,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import translate from '../translate'; +import { translate } from '../translate'; import Periods from './Periods'; import { parseDate, todayIsInRange } from './utilities'; diff --git a/plugins/CoreHome/vue/src/Periods/Range.ts b/plugins/CoreHome/vue/src/Periods/Range.ts index 07660dae5e..144a945c91 100644 --- a/plugins/CoreHome/vue/src/Periods/Range.ts +++ b/plugins/CoreHome/vue/src/Periods/Range.ts @@ -5,7 +5,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import translate from '../translate'; +import { translate } from '../translate'; import Periods from './Periods'; import { parseDate, @@ -176,6 +176,11 @@ export default class RangePeriod { containsToday(): boolean { return todayIsInRange(this.getDateRange()); } + + getDayCount(): number { + return (Math.ceil((this.endDate.getTime() - this.startDate.getTime()) / (1000 * 3600 * 24)) + + 1); + } } Periods.addCustomPeriod('range', RangePeriod); diff --git a/plugins/CoreHome/vue/src/Periods/Week.ts b/plugins/CoreHome/vue/src/Periods/Week.ts index 4bb45ceedf..2045fb4afe 100644 --- a/plugins/CoreHome/vue/src/Periods/Week.ts +++ b/plugins/CoreHome/vue/src/Periods/Week.ts @@ -5,7 +5,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import translate from '../translate'; +import { translate } from '../translate'; import Periods from './Periods'; import { parseDate, format, todayIsInRange } from './utilities'; diff --git a/plugins/CoreHome/vue/src/Periods/Year.ts b/plugins/CoreHome/vue/src/Periods/Year.ts index 9f9c0c0c88..178781af37 100644 --- a/plugins/CoreHome/vue/src/Periods/Year.ts +++ b/plugins/CoreHome/vue/src/Periods/Year.ts @@ -5,7 +5,7 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -import translate from '../translate'; +import { translate } from '../translate'; import Periods from './Periods'; import { parseDate, todayIsInRange } from './utilities'; diff --git a/plugins/CoreHome/vue/src/PopoverHandler/PopoverHandler.ts b/plugins/CoreHome/vue/src/PopoverHandler/PopoverHandler.ts new file mode 100644 index 0000000000..341cdf868b --- /dev/null +++ b/plugins/CoreHome/vue/src/PopoverHandler/PopoverHandler.ts @@ -0,0 +1,82 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { watch } from 'vue'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; + +const { $ } = window; + +class PopoverHandler { + constructor() { + this.setup(); + } + + private setup() { + watch(() => MatomoUrl.parsed.value.popover, () => this.onPopoverParamChanged()); + + if (MatomoUrl.parsed.value.popover) { + this.onPopoverParamChangedInitial(); + } + } + + // don't initiate the handler until the page had a chance to render, + // since some rowactions depend on what's been loaded. + private onPopoverParamChangedInitial() { + $(() => { + setTimeout(() => { + this.openOrClose(); + }); + }); + } + + private onPopoverParamChanged() { + // make sure all popover handles were registered + $(() => { + this.openOrClose(); + }); + } + + private openOrClose() { + this.close(); + + // should be rather done by routing + const popoverParam = MatomoUrl.parsed.value.popover as string; + if (popoverParam) { + this.open(popoverParam); + } else { + // the URL should only be set to an empty popover if there are no popovers in the stack. + // to avoid avoid any strange inconsistent states, we reset the popover stack here. + window.broadcast.resetPopoverStack(); + } + } + + private close() { + window.Piwik_Popover.close(); + } + + private open(thePopoverParam: string) { + // in case the $ was encoded (e.g. when using copy&paste on urls in some browsers) + let popoverParam = decodeURIComponent(thePopoverParam); + + // revert special encoding from broadcast.propagateNewPopoverParameter() + popoverParam = popoverParam.replace(/\$/g, '%'); + popoverParam = decodeURIComponent(popoverParam); + + const popoverParamParts = popoverParam.split(':'); + const handlerName = popoverParamParts[0]; + popoverParamParts.shift(); + + const param = popoverParamParts.join(':'); + if (typeof window.broadcast.popoverHandlers[handlerName] !== 'undefined' + && !window.broadcast.isLoginPage() + ) { + window.broadcast.popoverHandlers[handlerName](param); + } + } +} + +export default new PopoverHandler(); diff --git a/plugins/CoreHome/vue/src/Progressbar/Progressbar.adapter.ts b/plugins/CoreHome/vue/src/Progressbar/Progressbar.adapter.ts new file mode 100644 index 0000000000..79cb2049b3 --- /dev/null +++ b/plugins/CoreHome/vue/src/Progressbar/Progressbar.adapter.ts @@ -0,0 +1,22 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import Progressbar from './Progressbar.vue'; + +export default createAngularJsAdapter({ + component: Progressbar, + scope: { + progress: { + angularJsBind: '=', + }, + label: { + angularJsBind: '=', + }, + }, + directiveName: 'piwikProgressbar', +}); diff --git a/plugins/CoreHome/angularjs/progressbar/progressbar.directive.less b/plugins/CoreHome/vue/src/Progressbar/Progressbar.less index 70a02c8247..70a02c8247 100644 --- a/plugins/CoreHome/angularjs/progressbar/progressbar.directive.less +++ b/plugins/CoreHome/vue/src/Progressbar/Progressbar.less diff --git a/plugins/CoreHome/vue/src/Progressbar/Progressbar.vue b/plugins/CoreHome/vue/src/Progressbar/Progressbar.vue new file mode 100644 index 0000000000..985c44dc92 --- /dev/null +++ b/plugins/CoreHome/vue/src/Progressbar/Progressbar.vue @@ -0,0 +1,48 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div class="progressbar"> + <div class="progress"> + <div + class="determinate" + style="width: 0" + :style="{ width: `${actualProgress}%` }" + /> + </div> + <span v-show="!!label"> + <img src="plugins/Morpheus/images/loading-blue.gif" style="margin-right: 3.5px" /> + <span class="label" v-html="$sanitize(label)" /> + </span> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; + +export default defineComponent({ + props: { + progress: { + type: Number, + required: true, + }, + label: String, + }, + computed: { + actualProgress() { + if (this.progress > 100) { + return 100; + } + + if (this.progress < 0) { + return 0; + } + + return this.progress; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.adapter.ts b/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.adapter.ts new file mode 100644 index 0000000000..2818deff0a --- /dev/null +++ b/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.adapter.ts @@ -0,0 +1,23 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { ITimeoutService } from 'angular'; +import createAngularJsAdapter from '../createAngularJsAdapter'; +import QuickAccess from './QuickAccess.vue'; + +export default createAngularJsAdapter<[ITimeoutService]>({ + component: QuickAccess, + directiveName: 'piwikQuickAccess', + events: { + itemSelected(event, vm, scope, elem, attrs, controller, $timeout: ITimeoutService) { + $timeout(); + }, + blur(event, vm, scope) { + setTimeout(() => scope.$apply()); + }, + }, +}); diff --git a/plugins/CoreHome/angularjs/quick-access/quick-access.directive.less b/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.less index 3bad77b9ba..1bfdf4285c 100644 --- a/plugins/CoreHome/angularjs/quick-access/quick-access.directive.less +++ b/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.less @@ -43,6 +43,7 @@ .quick-access-category { text-align: left !important; font-size: 11px; + font-weight: bold; padding: 5px 5px 5px 10px; cursor: pointer; } diff --git a/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue b/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue new file mode 100644 index 0000000000..d7812cd992 --- /dev/null +++ b/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue @@ -0,0 +1,481 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div + ref="root" + class="quickAccessInside" + v-focus-anywhere-but-here="{ blur: onBlur }" + > + <span + class="icon-search" + @mouseenter="searchActive = true" + /> + <input + class="s" + @keydown="onKeypress($event)" + @focus="searchActive = true" + v-model="searchTerm" + type="text" + tabindex="2" + v-focus-if:[searchActive]="{}" + :title="quickAccessTitle" + :placeholder="translate('General_Search')" + ref="input" + /> + <div + class="dropdown" + v-show="searchTerm && searchActive" + > + <ul v-show="!(numMenuItems > 0 || sites.length)"> + <li class="no-result">{{ translate('General_SearchNoResults') }}</li> + </ul> + <ul v-for="subcategory in menuItems" :key="subcategory.title"> + <li + class="quick-access-category" + @click="searchTerm = subcategory.title;searchMenu(searchTerm)" + > + {{ subcategory.title }} + </li> + <li + class="result" + :class="{ selected: submenuEntry.menuIndex === searchIndex }" + @mouseenter="searchIndex = submenuEntry.menuIndex" + @click="selectMenuItem(submenuEntry.index)" + v-for="submenuEntry in subcategory.items" + :key="submenuEntry.index" + > + <a>{{ submenuEntry.name.trim() }}</a> + </li> + </ul> + <ul class="quickAccessMatomoSearch"> + <li + class="quick-access-category websiteCategory" + v-show="hasSitesSelector && sites.length || isLoading" + > + {{ translate('SitesManager_Sites') }} + </li> + <li + class="no-result" + v-show="hasSitesSelector && isLoading" + > + {{ translate('MultiSites_LoadingWebsites') }} + </li> + <li + class="result" + v-for="(site, index) in sites" + v-show="hasSitesSelector && !isLoading" + @mouseenter="searchIndex = numMenuItems + index" + :class="{ selected: numMenuItems + index === searchIndex }" + @click="selectSite(site.idsite)" + :key="site.idsite" + > + <a v-text="site.name" /> + </li> + </ul> + <ul> + <li class="quick-access-category helpCategory">{{ translate('General_HelpResources') }}</li> + <li + :class="{ selected: searchIndex === 'help' }" + class="quick-access-help" + @mouseenter="searchIndex = 'help'" + > + <a + :href="`https://matomo.org?mtm_campaign=App_Help&mtm_source=Matomo_App&mtm_keyword=QuickSearch&s=${encodeURIComponent(searchTerm)}`" + target="_blank" + > + {{ translate('CoreHome_SearchOnMatomo', searchTerm) }} + </a> + </li> + </ul> + </div> + </div> +</template> + +<script lang="ts"> +import { DeepReadonly, defineComponent } from 'vue'; +import FocusAnywhereButHere from '../FocusAnywhereButHere/FocusAnywhereButHere'; +import FocusIf from '../FocusIf/FocusIf'; +import { translate } from '../translate'; +import SitesStore from '../SiteSelector/SitesStore'; +import Site from '../SiteSelector/Site'; +import Matomo from '../Matomo/Matomo'; +import debounce from '../debounce'; + +interface SubMenuItem { + name: string; + index: number; + category: string; + menuIndex?: number; +} + +interface MenuItem { + title: string; + items: SubMenuItem[]; +} + +interface QuickAccessState { + menuItems: Array<unknown>; + numMenuItems: number; + searchActive: boolean; + searchTerm: string; + searchIndex: number; + + menuIndexCounter: number; + topMenuItems: SubMenuItem[]|null; + leftMenuItems: SubMenuItem[]|null; + segmentItems: SubMenuItem[]|null; + hasSegmentSelector: boolean; + + sites: DeepReadonly<Site[]>; + isLoading: boolean; +} + +function isElementInViewport(element: HTMLElement) { + const rect = element.getBoundingClientRect(); + const $window = window.$(window); + + return rect.top >= 0 + && rect.left >= 0 + && rect.bottom <= $window.height()! + && rect.right <= $window.width()!; +} + +function scrollFirstElementIntoView(element: HTMLElement) { + if (element && element.scrollIntoView) { + // make sure search is visible + element.scrollIntoView(); + } +} + +export default defineComponent({ + directives: { + FocusAnywhereButHere, + FocusIf, + }, + watch: { + searchActive(newValue: boolean) { + const root = this.$refs.root as HTMLElement; + if (!root || !root.parentElement) { + return; + } + + const classes = root.parentElement.classList; + classes.toggle('active', newValue); + classes.toggle('expanded', newValue); + }, + }, + mounted() { + const root = this.$refs.root as HTMLElement; + + // TODO: temporary, remove after angularjs is removed. + // this is currently needed since angularjs will render a div, then vue will render a div + // within it, but the top controls and CSS expect to have certain CSS classes in the root + // element. + // same applies to above watch for searchActive() + if (root && root.parentElement) { + root.parentElement.classList.add('quick-access', 'piwikSelector'); + } + + if (typeof window.initTopControls !== 'undefined' && window.initTopControls) { + window.initTopControls(); + } + + Matomo.helper.registerShortcut('f', translate('CoreHome_ShortcutSearch'), (event) => { + if (event.altKey) { + return; + } + + event.preventDefault(); + + scrollFirstElementIntoView(this.$refs.root as HTMLElement); + + this.activateSearch(); + }); + }, + data(): QuickAccessState { + const hasSegmentSelector = !!document.querySelector('.segmentEditorPanel'); + + return { + menuItems: [], + numMenuItems: 0, + searchActive: false, + searchTerm: '', + searchIndex: 0, + menuIndexCounter: -1, + topMenuItems: null, + leftMenuItems: null, + segmentItems: null, + hasSegmentSelector, + sites: [], + isLoading: false, + }; + }, + created() { + this.searchMenu = debounce(this.searchMenu.bind(this)); + }, + computed: { + hasSitesSelector() { + return !!document.querySelector('.top_controls [piwik-siteselector]'); + }, + quickAccessTitle() { + let searchAreasTitle = ''; + const searchAreas = [translate('CoreHome_MenuEntries')]; + + if (this.hasSegmentSelector) { + searchAreas.push(translate('CoreHome_Segments')); + } + + if (this.hasSitesSelector) { + searchAreas.push(translate('SitesManager_Sites')); + } + + while (searchAreas.length) { + searchAreasTitle += searchAreas.shift(); + if (searchAreas.length >= 2) { + searchAreasTitle += ', '; + } else if (searchAreas.length === 1) { + searchAreasTitle += ` ${translate('General_And')} `; + } + } + + return translate('CoreHome_QuickAccessTitle', searchAreasTitle); + }, + }, + emits: ['itemSelected', 'blur'], + methods: { + onKeypress(event: KeyboardEvent) { + const areSearchResultsDisplayed = this.searchTerm && this.searchActive; + const isTabKey = event.which === 9; + const isEscKey = event.which === 27; + + if (event.which === 38) { + this.highlightPreviousItem(); + event.preventDefault(); + } else if (event.which === 40) { + this.highlightNextItem(); + event.preventDefault(); + } else if (event.which === 13) { + this.clickQuickAccessMenuItem(); + } else if (isTabKey && areSearchResultsDisplayed) { + this.deactivateSearch(); + } else if (isEscKey && areSearchResultsDisplayed) { + this.deactivateSearch(); + } else { + setTimeout(() => { + this.searchActive = true; + this.searchMenu(this.searchTerm); + }); + } + }, + highlightPreviousItem() { + if ((this.searchIndex - 1) < 0) { + this.searchIndex = 0; + } else { + this.searchIndex -= 1; + } + this.makeSureSelectedItemIsInViewport(); + }, + highlightNextItem() { + const numTotal = (this.$refs.root as HTMLElement).querySelectorAll('li.result').length; + + if (numTotal <= (this.searchIndex + 1)) { + this.searchIndex = numTotal - 1; + } else { + this.searchIndex += 1; + } + + this.makeSureSelectedItemIsInViewport(); + }, + clickQuickAccessMenuItem() { + const selectedMenuElement = this.getCurrentlySelectedElement(); + if (selectedMenuElement) { + setTimeout(() => { + selectedMenuElement.click(); + this.$emit('itemSelected', selectedMenuElement); + }, 20); + } + }, + deactivateSearch() { + this.searchTerm = ''; + this.searchActive = false; + if (this.$refs.input) { + (this.$refs.input as HTMLElement).blur(); + } + }, + makeSureSelectedItemIsInViewport() { + const element = this.getCurrentlySelectedElement(); + + if (element && !isElementInViewport(element)) { + scrollFirstElementIntoView(element); + } + }, + getCurrentlySelectedElement(): HTMLElement|undefined { + const results = (this.$refs.root as HTMLElement).querySelectorAll('li.result'); + if (results && results.length && results.item(this.searchIndex)) { + return results.item(this.searchIndex) as HTMLElement; + } + return undefined; + }, + searchMenu(unprocessedSearchTerm: string) { + const searchTerm = unprocessedSearchTerm.toLowerCase(); + + let index = -1; + const menuItemsIndex: Record<string, number> = {}; + const menuItems: MenuItem[] = []; + + const moveToCategory = (theSubmenuItem: SubMenuItem) => { + // force rerender of element to prevent weird side effects + const submenuItem = { ...theSubmenuItem }; + // needed for proper highlighting with arrow keys + index += 1; + submenuItem.menuIndex = index; + + const { category } = submenuItem; + if (!(category in menuItemsIndex)) { + menuItems.push({ title: category, items: [] }); + menuItemsIndex[category] = menuItems.length - 1; + } + + const indexOfCategory = menuItemsIndex[category]; + menuItems[indexOfCategory].items.push(submenuItem); + }; + + this.resetSearchIndex(); + + if (this.hasSitesSelector) { + this.isLoading = true; + SitesStore.searchSite(searchTerm).then((sites) => { + if (sites) { + this.sites = sites; + } + }).finally(() => { + this.isLoading = false; + }); + } + + const menuItemMatches = (i: SubMenuItem) => i.name.toLowerCase().indexOf(searchTerm) !== -1 + || i.category.toLowerCase().indexOf(searchTerm) !== -1; + + // get the menu items on first search since this component can be mounted + // before the menus are + if (this.topMenuItems === null) { + this.topMenuItems = this.getTopMenuItems(); + } + if (this.leftMenuItems === null) { + this.leftMenuItems = this.getLeftMenuItems(); + } + if (this.segmentItems === null) { + this.segmentItems = this.getSegmentItems(); + } + + const topMenuItems = this.topMenuItems.filter(menuItemMatches); + const leftMenuItems = this.leftMenuItems.filter(menuItemMatches); + const segmentItems = this.segmentItems.filter(menuItemMatches); + + topMenuItems.forEach(moveToCategory); + leftMenuItems.forEach(moveToCategory); + segmentItems.forEach(moveToCategory); + + this.numMenuItems = topMenuItems.length + leftMenuItems.length + segmentItems.length; + this.menuItems = menuItems; + }, + resetSearchIndex() { + this.searchIndex = 0; + this.makeSureSelectedItemIsInViewport(); + }, + selectSite(idSite: string|number) { + SitesStore.loadSite(idSite); + }, + selectMenuItem(index: number) { + const target: HTMLElement|null = document.querySelector(`[quick_access='${index}']`); + if (target) { + this.deactivateSearch(); + + const href = target.getAttribute('href'); + if (href && href.length > 10 && target && target.click) { + try { + target.click(); + } catch (e) { + window.$(target).click(); + } + } else { + // not sure why jquery is used here and above, but only sometimes. keeping for BC. + window.$(target).click(); + } + } + }, + onBlur() { + this.searchActive = false; + this.$emit('blur'); + }, + activateSearch() { + this.searchActive = true; + }, + getTopMenuItems() { + const category = translate('CoreHome_Menu'); + + const topMenuItems: SubMenuItem[] = []; + document.querySelectorAll('nav .sidenav li > a').forEach((element) => { + let text = element.textContent?.trim(); + + if (!text) { + text = element.getAttribute('title')?.trim(); // possibly a icon, use title instead + } + + if (text) { + topMenuItems.push({ name: text, index: this.menuIndexCounter += 1, category }); + element.setAttribute('quick_access', `${this.menuIndexCounter}`); + } + }); + + return topMenuItems; + }, + getLeftMenuItems() { + const leftMenuItems: SubMenuItem[] = []; + + document.querySelectorAll('#secondNavBar .menuTab').forEach((element) => { + const categoryElement = window.$(element).find('> .item'); + let category = categoryElement[0]?.innerText.trim() || ''; + + if (category && category.lastIndexOf('\n') !== -1) { + // remove "\n\nMenu" + category = category.slice(0, category.lastIndexOf('\n')).trim(); + } + + window.$(element).find('li .item').each((i, subElement) => { + const text = subElement.textContent?.trim(); + if (text) { + leftMenuItems.push({ name: text, category, index: this.menuIndexCounter += 1 }); + subElement.setAttribute('quick_access', `${this.menuIndexCounter}`); + } + }); + }); + + return leftMenuItems; + }, + getSegmentItems() { + if (!this.hasSegmentSelector) { + return []; + } + + const category = translate('CoreHome_Segments'); + + const segmentItems: SubMenuItem[] = []; + document.querySelectorAll('.segmentList [data-idsegment]').forEach((element) => { + const text = element.querySelector('.segname')?.textContent?.trim(); + + if (text) { + segmentItems.push({ name: text, category, index: this.menuIndexCounter += 1 }); + element.setAttribute('quick_access', `${this.menuIndexCounter}`); + } + }); + + return segmentItems; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/ReportExport/ReportExport.adapter.ts b/plugins/CoreHome/vue/src/ReportExport/ReportExport.adapter.ts new file mode 100644 index 0000000000..a949af3a80 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportExport/ReportExport.adapter.ts @@ -0,0 +1,51 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { IDirective, ITimeoutService } from 'angular'; +import ReportExport from './ReportExport'; + +export default function piwikReportExport($timeout: ITimeoutService): IDirective { + return { + restrict: 'A', + scope: { + reportTitle: '@', + requestParams: '@', + reportFormats: '@', + apiMethod: '@', + maxFilterLimit: '@', + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + link: function piwikReportExportLink(scope: any, element: JQuery) { + const binding = { + instance: null, + value: { + reportTitle: scope.reportTitle, + requestParams: scope.requestParams, + reportFormats: typeof scope.reportFormats === 'string' + ? JSON.parse(scope.reportFormats) + : scope.reportFormats, + apiMethod: scope.apiMethod, + maxFilterLimit: parseInt(scope.maxFilterLimit, 10), + onClose: () => { + $timeout(() => { + window.angular.element(document).injector().get('$rootScope').$apply(); + }, 10); + }, + }, + oldValue: null, + modifiers: {}, + dir: {}, + }; + + ReportExport.mounted(element[0], binding); + }, + }; +} + +piwikReportExport.$inject = ['$timeout']; + +window.angular.module('piwikApp').directive('piwikReportExport', piwikReportExport); diff --git a/plugins/CoreHome/angularjs/report-export/reportexport.popover.less b/plugins/CoreHome/vue/src/ReportExport/ReportExport.less index 303340e11c..29137514e7 100644 --- a/plugins/CoreHome/angularjs/report-export/reportexport.popover.less +++ b/plugins/CoreHome/vue/src/ReportExport/ReportExport.less @@ -20,19 +20,19 @@ .toggle-export-url { font-size: 14px; - margin-left: 20px; + margin-left: 24px; } .filter_limit { clear: both; float: none; - [piwik-field] { + > div { width: 50%; float: left; } } - + .showoptions > span { color: @color-blue-piwik; cursor: pointer; @@ -46,7 +46,7 @@ } .tooltip > a { - color: @color-blue-piwik; - text-decoration: underline; + color: @color-blue-piwik; + text-decoration: underline; } }
\ No newline at end of file diff --git a/plugins/CoreHome/vue/src/ReportExport/ReportExport.ts b/plugins/CoreHome/vue/src/ReportExport/ReportExport.ts new file mode 100644 index 0000000000..f7f8a07430 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportExport/ReportExport.ts @@ -0,0 +1,122 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { DirectiveBinding } from 'vue'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import { translate } from '../translate'; +import ReportExportPopover from './ReportExportPopover.vue'; +import Matomo from '../Matomo/Matomo'; +import createVueApp from '../createVueApp'; + +interface ReportExportArgs { + reportTitle: string; + requestParams: QueryParameters; + reportFormats: Record<string, unknown>; + apiMethod: string; + maxFilterLimit: number; + onClose?: () => void; +} + +const { $ } = window; + +export default { + mounted(el: HTMLElement, binding: DirectiveBinding<ReportExportArgs>): void { + el.addEventListener('click', () => { + const popoverParamBackup = MatomoUrl.hashParsed.value.popover; + + const dataTable = $(el).closest('[data-report]').data('uiControlObject'); + const popover = window.Piwik_Popover.showLoading('Export'); + + const formats = binding.value.reportFormats; + + let reportLimit = dataTable.param.filter_limit; + if (binding.value.maxFilterLimit > 0) { + reportLimit = Math.min(reportLimit, binding.value.maxFilterLimit); + } + + const optionFlat = dataTable.param.flat === true + || dataTable.param.flat === 1 + || dataTable.param.flat === '1'; + + const props = { + initialReportType: 'default', + initialReportLimit: reportLimit > 0 ? reportLimit : 100, + initialReportLimitAll: reportLimit === -1 ? 'yes' : 'no', + initialOptionFlat: optionFlat, + initialOptionExpanded: true, + initialOptionFormatMetrics: false, + hasSubtables: optionFlat || dataTable.numberOfSubtables > 0, + availableReportFormats: { + default: formats, + processed: { + XML: formats.XML, + JSON: formats.JSON, + }, + }, + availableReportTypes: { + default: translate('CoreHome_StandardReport'), + processed: translate('CoreHome_ReportWithMetadata'), + }, + limitAllOptions: { + yes: translate('General_All'), + no: translate('CoreHome_CustomLimit'), + }, + maxFilterLimit: binding.value.maxFilterLimit, + dataTable, + requestParams: binding.value.requestParams, + apiMethod: binding.value.apiMethod, + }; + + const app = createVueApp({ + template: ` + <popover v-bind="bind"/>`, + data() { + return { + bind: props, + }; + }, + }); + app.component('popover', ReportExportPopover); + + const mountPoint = document.createElement('div'); + app.mount(mountPoint); + + const { reportTitle } = binding.value; + window.Piwik_Popover.setTitle( + `${translate('General_Export')} ${Matomo.helper.htmlEntities(reportTitle)}`, + ); + window.Piwik_Popover.setContent(mountPoint); + + window.Piwik_Popover.onClose(() => { + app.unmount(); + + if (popoverParamBackup !== '') { + setTimeout(() => { + MatomoUrl.updateHash({ + ...MatomoUrl.hashParsed.value, + popover: popoverParamBackup, + }); + + if (binding.value.onClose) { + binding.value.onClose(); + } + }, 100); + } + }); + + setTimeout(() => { + popover.dialog(); + + $('.exportFullUrl, .btn', popover).tooltip({ + track: true, + show: false, + hide: false, + }); + }, 100); + }); + }, +}; diff --git a/plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue b/plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue new file mode 100644 index 0000000000..37caea1e2b --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue @@ -0,0 +1,444 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div class="report-export-popover row" id="reportExport"> + + <div class="col l6"> + <div name="format"> + <Field + :uicontrol="'radio'" + :name="'format'" + :title="translate('CoreHome_ExportFormat')" + v-model="reportFormat" + :full-width="true" + :options="availableReportFormats[reportType]" + /> + </div> + + <div> + <div name="option_flat"> + <Field + :uicontrol="'checkbox'" + :name="'option_flat'" + :title="translate('CoreHome_FlattenReport')" + v-model="optionFlat" + v-show="hasSubtables" + > + </Field> + </div> + </div> + <div> + <div name="option_expanded"> + <Field + :uicontrol="'checkbox'" + :name="'option_expanded'" + :title="translate('CoreHome_ExpandSubtables')" + v-model="optionExpanded" + v-show="hasSubtables && !optionFlat" + > + </Field> + </div> + </div> + <div> + <div name="option_format_metrics"> + <Field + :uicontrol="'checkbox'" + :name="'option_format_metrics'" + :title="translate('CoreHome_FormatMetrics')" + v-model="optionFormatMetrics" + > + </Field> + </div> + </div> + </div> + + <div class="col l6"> + <div> + <div name="filter_type"> + <Field + :uicontrol="'radio'" + :name="'filter_type'" + :title="translate('CoreHome_ReportType')" + v-model="reportType" + :full-width="true" + :options="availableReportTypes" + > + </Field> + </div> + </div> + + <div class="filter_limit"> + <div v-show="!maxFilterLimit || maxFilterLimit <= 0" name="filter_limit_all"> + <Field + :uicontrol="'radio'" + :name="'filter_limit_all'" + :title="translate('CoreHome_RowLimit')" + v-model="reportLimitAll" + + :full-width="true" + :options="limitAllOptions" + > + </Field> + </div> + + <div v-if="reportLimitAll === 'no' && maxFilterLimit <= 0" name="filter_limit"> + <Field + :uicontrol="'number'" + name="filter_limit" + :min="1" + v-model="reportLimit" + :full-width="true" + > + </Field> + </div> + + <div v-if="reportLimitAll === 'no' && maxFilterLimit > 0" name="filter_limit"> + <Field + :uicontrol="'number'" + :name="'filter_limit'" + :min="1" + :max="maxFilterLimit" + v-model="reportLimit" + :value="reportLimit" + :full-width="true" + :title="filterLimitTooltip" + > + </Field> + </div> + </div> + </div> + + <div class="col l12" v-show="showUrl"> + <textarea + v-select-on-focus="{}" + readonly + class="exportFullUrl" + :value="exportLinkWithoutToken" + > + </textarea> + <div class="tooltip" v-html="$sanitize(translate( + 'CoreHome_ExportTooltipWithLink', + '<a target=_blank href=\'?module=UsersManager&action=userSecurity\'>', + '</a>', + 'ENTER_YOUR_TOKEN_AUTH_HERE', + ))"></div> + </div> + + <div class="col l12"> + <a + class="btn" + :href="exportLink" + target="_new" + :title="translate('CoreHome_ExportTooltip')" + >{{ translate('General_Export') }}</a> + <a href="javascript:" @click="showUrl=!showUrl" class="toggle-export-url"> + <span v-show="!showUrl">{{ translate('CoreHome_ShowExportUrl') }}</span> + <span v-show="showUrl">{{ translate('CoreHome_HideExportUrl') }}</span> + </a> + </div> + + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import useExternalPluginComponent from '../useExternalPluginComponent'; +import SelectOnFocus from '../SelectOnFocus/SelectOnFocus'; +import Matomo from '../Matomo/Matomo'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import { translate } from '../translate'; + +interface DataTable { + param: Record<string, string|string[]>; + props: Record<string, string|string[]>; +} + +const Field = useExternalPluginComponent('CorePluginsAdmin', 'Field'); + +export default defineComponent({ + components: { + Field, + }, + directives: { + SelectOnFocus, + }, + props: { + hasSubtables: Boolean, + availableReportTypes: Object, + availableReportFormats: { + type: Object, + required: true, + }, + maxFilterLimit: Number, + limitAllOptions: Object, + dataTable: { + type: Object, + required: true, + }, + requestParams: [Object, String], + apiMethod: { + type: String, + required: true, + }, + initialReportType: { + type: String, + default: 'default', + }, + initialReportLimit: { + type: [String, Number], + default: 100, + }, + initialReportLimitAll: { + type: String, + default: 'yes', + }, + initialOptionFlat: { + type: Boolean, + default: false, + }, + initialOptionExpanded: { + type: Boolean, + default: true, + }, + initialOptionFormatMetrics: { + type: Boolean, + default: false, + }, + initialReportFormat: { + type: String, + default: 'XML', + }, + }, + data() { + return { + showUrl: false, + reportFormat: this.initialReportFormat, + optionFlat: this.initialOptionFlat, + optionExpanded: this.initialOptionExpanded, + optionFormatMetrics: this.initialOptionFormatMetrics, + reportType: this.initialReportType, + reportLimitAll: this.initialReportLimitAll, + reportLimit: typeof this.initialReportLimit === 'string' + ? parseInt(this.initialReportLimit, 10) + : this.initialReportLimit, + }; + }, + watch: { + reportType(newVal) { + if (!this.availableReportFormats[newVal][this.reportFormat]) { + this.reportFormat = 'XML'; + } + }, + reportLimit(newVal, oldVal) { + if (this.maxFilterLimit && this.maxFilterLimit > 0 && newVal > this.maxFilterLimit) { + this.reportLimit = oldVal; + } + }, + }, + computed: { + filterLimitTooltip() { + const rowLimit = translate('CoreHome_RowLimit'); + const computedMetricMax = this.maxFilterLimit + ? translate( + 'General_ComputedMetricMax', + this.maxFilterLimit.toString(), + ) + : ''; + return `${rowLimit} (${computedMetricMax})`; + }, + exportLink() { + return this.getExportLink(true); + }, + exportLinkWithoutToken() { + return this.getExportLink(false); + }, + }, + methods: { + getExportLink(withToken = true) { + const { + reportFormat, + apiMethod, + reportType, + } = this; + + const dataTable: DataTable = this.dataTable as DataTable; + + if (!reportFormat) { + return undefined; + } + + let requestParams: Record<string, unknown> = {}; + + const limit = this.reportLimitAll === 'yes' ? -1 : this.reportLimit; + + if (this.requestParams && typeof this.requestParams === 'string') { + requestParams = JSON.parse(this.requestParams); + } + + const { + segment, + label, + idGoal, + idDimension, + idSite, + } = dataTable.param; + + let { date, period } = dataTable.param; + + if (reportFormat === 'RSS') { + date = 'last10'; + } + if (typeof dataTable.param.dateUsedInGraph !== 'undefined') { + date = dataTable.param.dateUsedInGraph; + } + + const formatsUseDayNotRange = (Matomo.config.datatable_export_range_as_day as string) + .toLowerCase(); + + if (formatsUseDayNotRange.indexOf(reportFormat.toLowerCase()) !== -1 + && dataTable.param.period === 'range' + ) { + period = 'day'; + } + + // Below evolution graph, show daily exports + if (dataTable.param.period === 'range' + && dataTable.param.viewDataTable === 'graphEvolution' + ) { + period = 'day'; + } + + const exportUrlParams: QueryParameters = { + module: 'API', + format: reportFormat, + idSite, + period, + date, + }; + + if (reportType === 'processed') { + exportUrlParams.method = 'API.getProcessedReport'; + [exportUrlParams.apiModule, exportUrlParams.apiAction] = apiMethod.split('.'); + } else { + exportUrlParams.method = apiMethod; + } + + if (dataTable.param.compareDates + && dataTable.param.compareDates.length + ) { + exportUrlParams.compareDates = dataTable.param.compareDates; + exportUrlParams.compare = '1'; + } + + if (dataTable.param.comparePeriods + && dataTable.param.comparePeriods.length + ) { + exportUrlParams.comparePeriods = dataTable.param.comparePeriods; + exportUrlParams.compare = '1'; + } + + if (dataTable.param.compareSegments + && dataTable.param.compareSegments.length + ) { + exportUrlParams.compareSegments = dataTable.param.compareSegments; + exportUrlParams.compare = '1'; + } + + if (typeof dataTable.param.filter_pattern !== 'undefined') { + exportUrlParams.filter_pattern = dataTable.param.filter_pattern; + } + + if (typeof dataTable.param.filter_pattern_recursive !== 'undefined') { + exportUrlParams.filter_pattern_recursive = dataTable.param.filter_pattern_recursive; + } + + if (window.$.isPlainObject(requestParams)) { + Object.entries(requestParams).forEach(([index, param]) => { + let value = param; + if (value === true) { + value = 1; + } else if (value === false) { + value = 0; + } + exportUrlParams[index] = value as QueryParameterValue; + }); + } + + if (this.optionFlat) { + exportUrlParams.flat = 1; + if (typeof dataTable.param.include_aggregate_rows !== 'undefined' + && dataTable.param.include_aggregate_rows === '1' + ) { + exportUrlParams.include_aggregate_rows = 1; + } + } + + if (!this.optionFlat && this.optionExpanded) { + exportUrlParams.expanded = 1; + } + + if (this.optionFormatMetrics) { + exportUrlParams.format_metrics = 1; + } + + if (dataTable.param.pivotBy) { + exportUrlParams.pivotBy = dataTable.param.pivotBy; + exportUrlParams.pivotByColumnLimit = 20; + + if (dataTable.props.pivot_by_column) { + exportUrlParams.pivotByColumn = dataTable.props.pivot_by_column; + } + } + + if (reportFormat === 'CSV' || reportFormat === 'TSV' || reportFormat === 'RSS') { + exportUrlParams.translateColumnNames = 1; + exportUrlParams.language = Matomo.language; + } + + if (typeof segment !== 'undefined') { + exportUrlParams.segment = decodeURIComponent(segment as string); + } + + // Export Goals specific reports + if (typeof idGoal !== 'undefined' + && idGoal !== '-1' + ) { + exportUrlParams.idGoal = idGoal; + } + + // Export Dimension specific reports + if (typeof idDimension !== 'undefined' + && idDimension !== '-1' + ) { + exportUrlParams.idDimension = idDimension; + } + + if (label) { + const labelParts = (label as string).split(','); + + if (labelParts.length > 1) { + exportUrlParams.label = labelParts; + } else { + [exportUrlParams.label] = labelParts; + } + } + + exportUrlParams.token_auth = 'ENTER_YOUR_TOKEN_AUTH_HERE'; + + if (withToken === true) { + exportUrlParams.token_auth = Matomo.token_auth; + exportUrlParams.force_api_session = 1; + } + + exportUrlParams.filter_limit = limit; + + const prefix = window.location.href.split('?')[0]; + return `${prefix}?${MatomoUrl.stringify(exportUrlParams)}`; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.adapter.ts b/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.adapter.ts new file mode 100644 index 0000000000..bc1c37f6fe --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.adapter.ts @@ -0,0 +1,19 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import ReportMetadataStoreInstance from './ReportMetadata.store'; +import { cloneThenApply } from '../createAngularJsAdapter'; + +window.angular.module('piwikApp.service').factory('reportMetadataModel', () => ({ + get reports() { + return ReportMetadataStoreInstance.reports.value; + }, + findReport: + ReportMetadataStoreInstance.findReport.bind(ReportMetadataStoreInstance), + fetchReportMetadata: () => ReportMetadataStoreInstance.fetchReportMetadata() + .then((m) => cloneThenApply(m)), +})); diff --git a/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.ts b/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.ts new file mode 100644 index 0000000000..1839e63ca9 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.ts @@ -0,0 +1,66 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { + reactive, + computed, + readonly, + DeepReadonly, +} from 'vue'; +import AjaxHelper from '../AjaxHelper/AjaxHelper'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import Matomo from '../Matomo/Matomo'; + +interface ReportRef { + module: string; + action: string; +} + +interface Report { + relatedReports: ReportRef[]; + module: string; + action: string; + documentation?: string; +} + +interface ReportMetadataStoreState { + reports: Report[]; +} + +export class ReportMetadataStore { + private privateState = reactive<ReportMetadataStoreState>({ + reports: [], + }); + + private state = readonly(this.privateState); + + readonly reports = computed(() => this.state.reports); + + private reportsPromise?: Promise<Report[]>; + + // TODO: it used to return an empty array when nothing was found, will that be an issue? + findReport(reportModule?: string, reportAction?: string): DeepReadonly<Report>|undefined { + return this.reports.value.find((r) => r.module === reportModule && r.action === reportAction); + } + + fetchReportMetadata(): Promise<ReportMetadataStore['reports']['value']> { + if (!this.reportsPromise) { + this.reportsPromise = AjaxHelper.fetch({ + method: 'API.getReportMetadata', + filter_limit: '-1', + idSite: Matomo.idSite || MatomoUrl.parsed.value.idSite, + }).then((response) => { + this.privateState.reports = response; + return response; + }); + } + + return this.reportsPromise.then(() => this.reports.value); + } +} + +export default new ReportMetadataStore(); diff --git a/plugins/CoreHome/vue/src/ReportingMenu/Category.ts b/plugins/CoreHome/vue/src/ReportingMenu/Category.ts new file mode 100644 index 0000000000..5e2672b9e1 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingMenu/Category.ts @@ -0,0 +1,33 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { Orderable } from '../Orderable'; +import { Subcategory } from './Subcategory'; + +export interface Category extends Orderable { + id: string; + name: string; + icon?: string; + tooltip?: string; + + /** + * @deprecated exists for BC, should be removed in Matomo 5 + */ + active?: boolean; +} + +export interface CategoryContainer extends Category { + subcategories: Subcategory[]; +} + +export function getCategoryChildren(category: Category): Subcategory[] { + const container = category as CategoryContainer; + if (container.subcategories) { + return container.subcategories; + } + return []; +} diff --git a/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.adapter.ts b/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.adapter.ts new file mode 100644 index 0000000000..8de6fd465c --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.adapter.ts @@ -0,0 +1,14 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import ReportingMenu from './ReportingMenu.vue'; + +export default createAngularJsAdapter({ + component: ReportingMenu, + directiveName: 'piwikReportingMenu', +}); diff --git a/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.adapter.ts b/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.adapter.ts new file mode 100644 index 0000000000..3407fb6948 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.adapter.ts @@ -0,0 +1,50 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import ReportingMenuStoreInstance from './ReportingMenu.store'; +import { cloneThenApply } from '../createAngularJsAdapter'; +import { CategoryContainer } from './Category'; +import { SubcategoryContainer } from './Subcategory'; + +// removed boolean active property from objects in vue so we can keep the store immutable, but, +// angularjs version should still have them +function addActiveMenuItems(menu: typeof ReportingMenuStoreInstance.menu.value) { + menu.forEach((category) => { + if (category.id === ReportingMenuStoreInstance.activeCategory.value) { + category.active = true; + + ((category as CategoryContainer).subcategories || []).forEach((subcat) => { + if (subcat.id === ReportingMenuStoreInstance.activeSubcategory.value) { + subcat.active = true; + + ((subcat as SubcategoryContainer).subcategories || []).forEach((subsubcat) => { + if (subsubcat.id === ReportingMenuStoreInstance.activeSubsubcategory.value) { + subsubcat.active = true; + } + }); + } + }); + } + }); + return menu; +} + +function reportingMenuModelAdapter() { + return { + get menu() { + return ReportingMenuStoreInstance.menu.value; + }, + findSubcategory: + ReportingMenuStoreInstance.findSubcategory.bind(ReportingMenuStoreInstance), + reloadMenuItems: () => ReportingMenuStoreInstance.reloadMenuItems() + .then((p) => addActiveMenuItems(cloneThenApply(p))), + fetchMenuItems: () => ReportingMenuStoreInstance.fetchMenuItems() + .then((p) => addActiveMenuItems(cloneThenApply(p))), + }; +} + +window.angular.module('piwikApp.service').factory('reportingMenuModel', reportingMenuModelAdapter); diff --git a/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.ts b/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.ts new file mode 100644 index 0000000000..2241b23d8e --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.ts @@ -0,0 +1,218 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { computed, reactive, readonly } from 'vue'; +import ReportingPagesStoreInstance from '../ReportingPages/ReportingPages.store'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import { translate } from '../translate'; +import { sortOrderables } from '../Orderable'; +import { Category, CategoryContainer, getCategoryChildren } from './Category'; +import { getSubcategoryChildren, Subcategory, SubcategoryContainer } from './Subcategory'; + +interface ReportingMenuStoreState { + activeCategoryId: string|null; + activeSubcategoryId: string|null; + activeSubsubcategoryId: string|null; +} + +interface SubcategoryFindResult { + category?: Category; + subcategory?: Subcategory; + subsubcategory?: Subcategory; +} + +function isNumeric(text: string) { + const n = parseFloat(text); + return !Number.isNaN(n) && Number.isFinite(n); +} + +export class ReportingMenuStore { + private privateState = reactive<ReportingMenuStoreState>({ + activeCategoryId: null, + activeSubcategoryId: null, + activeSubsubcategoryId: null, + }); + + private state = computed(() => readonly(this.privateState)); + + readonly activeCategory = computed(() => this.state.value.activeCategoryId + || MatomoUrl.parsed.value.category as string); + + readonly activeSubcategory = computed(() => this.state.value.activeSubcategoryId + || MatomoUrl.parsed.value.subcategory as string); + + readonly activeSubsubcategory = computed(() => { + const manuallySetId = this.state.value.activeSubsubcategoryId; + if (manuallySetId) { + return manuallySetId; + } + + // default to activeSubcategory if the activeSubcategory is part of a group + const foundCategory = this.findSubcategory( + this.activeCategory.value, + this.activeSubcategory.value, + ); + + if (foundCategory.subsubcategory + && foundCategory.subsubcategory.id === this.activeSubcategory.value + ) { + return foundCategory.subsubcategory.id; + } + + return null; + }); + + readonly menu = computed(() => this.buildMenuFromPages()); + + fetchMenuItems(): Promise<ReportingMenuStore['menu']['value']> { + return ReportingPagesStoreInstance.getAllPages().then(() => this.menu.value); + } + + reloadMenuItems(): Promise<ReportingMenuStore['menu']['value']> { + return ReportingPagesStoreInstance.reloadAllPages().then(() => this.menu.value); + } + + findSubcategory(categoryId: string, subcategoryId: string): SubcategoryFindResult { + let foundCategory: Category|undefined = undefined; + let foundSubcategory: Subcategory|undefined = undefined; + let foundSubSubcategory: Subcategory|undefined = undefined; + + this.menu.value.forEach((category) => { + if (category.id !== categoryId) { + return; + } + + (getCategoryChildren(category) || []).forEach((subcategory) => { + if (subcategory.id === subcategoryId) { + foundCategory = category; + foundSubcategory = subcategory; + } + + if (subcategory.isGroup) { + (getSubcategoryChildren(subcategory) || []).forEach((subcat) => { + if (subcat.id === subcategoryId) { + foundCategory = category; + foundSubcategory = subcategory; + foundSubSubcategory = subcat; + } + }); + } + }); + }); + + return { + category: foundCategory, + subcategory: foundSubcategory, + subsubcategory: foundSubSubcategory, + }; + } + + private buildMenuFromPages() { + const menu: Category[] = []; + + const displayedCategory = MatomoUrl.parsed.value.category as string; + const displayedSubcategory = MatomoUrl.parsed.value.subcategory as string; + + const pages = ReportingPagesStoreInstance.pages.value; + + const categoriesHandled: Record<string, boolean> = {}; + pages.forEach((page) => { + const category = { ...page.category } as Category; + const categoryId = category.id; + const isCategoryDisplayed = categoryId === displayedCategory; + + if (categoriesHandled[categoryId]) { + return; + } + + categoriesHandled[categoryId] = true; + + (category as CategoryContainer).subcategories = []; + + let categoryGroups: Subcategory|null = null; + + const pagesWithCategory = pages.filter((p) => p.category.id === categoryId); + pagesWithCategory.forEach((p) => { + const subcategory = { ...p.subcategory } as Subcategory; + const isSubcategoryDisplayed = subcategory.id === displayedSubcategory + && isCategoryDisplayed; + + if (p.widgets && p.widgets[0] && isNumeric(p.subcategory.id)) { + // we handle a goal or something like it + if (!categoryGroups) { + categoryGroups = { ...subcategory } as Subcategory; + categoryGroups.name = translate('CoreHome_ChooseX', [category.name]); + categoryGroups.isGroup = true; + (categoryGroups as SubcategoryContainer).subcategories = []; + categoryGroups.order = 10; + } + + if (isSubcategoryDisplayed) { + categoryGroups.name = subcategory.name; + } + + const entityId = page.subcategory.id; + subcategory.tooltip = `${subcategory.name} (id = ${entityId})`; + + (categoryGroups as SubcategoryContainer).subcategories.push(subcategory); + return; + } + + (category as CategoryContainer).subcategories.push(subcategory); + }); + + if (categoryGroups + && (categoryGroups as SubcategoryContainer).subcategories + && (categoryGroups as SubcategoryContainer).subcategories.length <= 5 + ) { + (categoryGroups as SubcategoryContainer).subcategories.forEach( + (sub) => (category as CategoryContainer).subcategories.push(sub), + ); + } else if (categoryGroups) { + (category as CategoryContainer).subcategories.push(categoryGroups); + } + + (category as CategoryContainer).subcategories = sortOrderables(getCategoryChildren(category)); + + menu.push(category); + }); + + return sortOrderables(menu); + } + + toggleCategory(category: Category): boolean { + this.privateState.activeSubcategoryId = null; + this.privateState.activeSubsubcategoryId = null; + + if (this.privateState.activeCategoryId === category.id) { + this.privateState.activeCategoryId = null; + return false; + } + + this.privateState.activeCategoryId = category.id; + return true; + } + + enterSubcategory( + category?: Category, + subcategory?: Subcategory, + subsubcategory?: Subcategory, + ): void { + if (!category || !subcategory) { + return; + } + + this.privateState.activeCategoryId = category.id; + this.privateState.activeSubcategoryId = subcategory.id; + + if (subsubcategory) { + this.privateState.activeSubsubcategoryId = subsubcategory.id; + } + } +} + +export default new ReportingMenuStore(); diff --git a/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue b/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue new file mode 100644 index 0000000000..3e60c63c93 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue @@ -0,0 +1,388 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div class="reportingMenu"> + <ul + class="navbar hide-on-med-and-down" + role="menu" + :aria-label="translate('CoreHome_MainNavigation')" + > + <li + class="menuTab" + role="menuitem" + v-for="category in menu" + :class="{ 'active': category.id === activeCategory }" + :key="category.id" + > + <a + class="item" + tabindex="5" + href="" + @click.prevent="loadCategory(category)" + > + <span + :class="`menu-icon ${category.icon ? category.icon : 'icon-arrow-right'}`" + />{{ category.name }} + <span class="hidden"> + {{ translate('CoreHome_Menu') }} + </span> + </a> + <ul role="menu"> + <li + role="menuitem" + :class="{ + 'active': (subcategory.id === displayedSubcategory + || (subcategory.isGroup && activeSubsubcategory === displayedSubcategory) + ) && category.id === displayedCategory, + }" + v-for="subcategory in category.subcategories" + :key="subcategory.id" + > + <MenuItemsDropdown + v-if="subcategory.isGroup" + :show-search="true" + :menu-title="htmlEntities(subcategory.name)" + > + <a + class="item" + tabindex="5" + :class="{ + active: subcat.id === activeSubsubcategory + && subcategory.id === displayedSubcategory + && category.id === displayedCategory, + }" + :href="`#?${makeUrl(category, subcat)}`" + @click="loadSubcategory(category, subcat, $event)" + v-for="subcat in subcategory.subcategories" + :title="subcat.tooltip" + :key="subcat.id" + > + {{ subcat.name }} + </a> + </MenuItemsDropdown> + <a + v-if="!subcategory.isGroup" + :href="`#?${makeUrl(category, subcategory)}`" + class="item" + @click="loadSubcategory(category, subcategory, $event)" + > + {{ subcategory.name }} + </a> + <a + class="item-help-icon" + tabindex="5" + href="javascript:" + v-if="subcategory.help" + @click="showHelp(category, subcategory, $event)" + :class="{active: helpShownCategory + && helpShownCategory.subcategory === subcategory.id + && helpShownCategory.category === category.id + && subcategory.help}" + > + <span class="icon-help" /> + </a> + </li> + </ul> + </li> + </ul> + <ul + id="mobile-left-menu" + class="sidenav hide-on-large-only" + > + <li + class="no-padding" + v-for="category in menu" + :key="category.id" + > + <ul + class="collapsible collapsible-accordion" + v-side-nav="{ activator: sideNavActivator }" + > + <li> + <a class="collapsible-header"> + <i :class="category.icon ? category.icon : 'icon-arrow-bottom'" />{{ category.name }} + </a> + <div class="collapsible-body"> + <ul> + <li v-for="subcategory in category.subcategories" :key="subcategory.id"> + <span v-if="subcategory.isGroup"> + <a + @click="loadSubcategory(category, subcat)" + :href="`#?${makeUrl(category, subcat)}`" + v-for="subcat in subcategory.subcategories" + :key="subcat.id" + > + {{ subcat.name }} + </a> + </span> + <span v-if="!subcategory.isGroup"> + <a + @click="loadSubcategory(category, subcategory)" + :href="`#?${makeUrl(category, subcategory)}`" + > + {{ subcategory.name }} + </a> + </span> + </li> + </ul> + </div> + </li> + </ul> + </li> + </ul> + </div> +</template> + +<script lang="ts"> +import { defineComponent, watch } from 'vue'; +import MenuItemsDropdown from '../MenuItemsDropdown/MenuItemsDropdown.vue'; +import SideNav from '../SideNav/SideNav'; +import { NotificationsStore } from '../Notification'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import ReportingMenuStoreInstance from './ReportingMenu.store'; +import Matomo from '../Matomo/Matomo'; +import { translate } from '../translate'; +import WidgetsStoreInstance from '../Widget/Widgets.store'; +import { Category, CategoryContainer } from './Category'; +import { Subcategory, SubcategoryContainer } from './Subcategory'; + +const REPORTING_HELP_NOTIFICATION_ID = 'reportingmenu-help'; + +interface ReportingMenuState { + showSubcategoryHelpOnLoad: { category: Category, subcategory: Subcategory } | null; + initialLoad: boolean | null; + helpShownCategory: { category: string, subcategory: string } | null; +} + +export default defineComponent({ + components: { + MenuItemsDropdown, + }, + directives: { + SideNav, + }, + props: {}, + data(): ReportingMenuState { + return { + showSubcategoryHelpOnLoad: null, + initialLoad: true, + helpShownCategory: null, + }; + }, + computed: { + sideNavActivator() { + return document.querySelector('nav .activateLeftMenu'); + }, + menu() { + return ReportingMenuStoreInstance.menu.value; + }, + activeCategory() { + return ReportingMenuStoreInstance.activeCategory.value; + }, + activeSubcategory() { + return ReportingMenuStoreInstance.activeSubcategory.value; + }, + activeSubsubcategory() { + return ReportingMenuStoreInstance.activeSubsubcategory.value; + }, + displayedCategory() { + return MatomoUrl.parsed.value.category; + }, + displayedSubcategory() { + return MatomoUrl.parsed.value.subcategory; + }, + }, + created() { + ReportingMenuStoreInstance.fetchMenuItems().then((menu) => { + if (!MatomoUrl.parsed.value.subcategory) { + const categoryToLoad = menu[0]; + const subcategoryToLoad = (categoryToLoad as CategoryContainer).subcategories[0]; + + // load first, initial page if no subcategory is present + ReportingMenuStoreInstance.enterSubcategory(categoryToLoad, subcategoryToLoad); + this.propagateUrlChange(categoryToLoad, subcategoryToLoad); + } + }); + + watch(() => MatomoUrl.parsed.value, (query) => { + const found = ReportingMenuStoreInstance.findSubcategory( + query.category as string, + query.subcategory as string, + ); + + ReportingMenuStoreInstance.enterSubcategory( + found.category, + found.subcategory, + found.subsubcategory, + ); + }); + + Matomo.on('piwikPageChange', () => { + if (!this.initialLoad) { + window.globalAjaxQueue.abort(); + } + + this.helpShownCategory = null; + + if (this.showSubcategoryHelpOnLoad) { + this.showHelp( + this.showSubcategoryHelpOnLoad.category, + this.showSubcategoryHelpOnLoad.subcategory, + ); + this.showSubcategoryHelpOnLoad = null; + } + + window.$('#loadingError').hide(); + + this.initialLoad = false; + }); + + Matomo.on('updateReportingMenu', () => { + ReportingMenuStoreInstance.reloadMenuItems().then(() => { + const category = MatomoUrl.parsed.value.category as string; + const subcategory = MatomoUrl.parsed.value.subcategory as string; + + // we need to make sure to select same categories again + if (category && subcategory) { + const found = ReportingMenuStoreInstance.findSubcategory(category, subcategory); + if (found.category) { + ReportingMenuStoreInstance.enterSubcategory( + found.category, + found.subcategory, + found.subsubcategory, + ); + } + } + }); + + WidgetsStoreInstance.reloadAvailableWidgets(); + }); + }, + methods: { + propagateUrlChange(category: Category, subcategory: Subcategory) { + const queryParams = MatomoUrl.parsed.value; + if (queryParams.category === category.id && queryParams.subcategory === subcategory.id) { + // we need to manually trigger change as URL would not change and therefore page would not + // be reloaded + this.loadSubcategory(category, subcategory); + } else { + MatomoUrl.updateHash({ + ...MatomoUrl.hashParsed.value, + category: category.id, + subcategory: subcategory.id, + }); + } + }, + loadCategory(category: Category) { + NotificationsStore.remove(REPORTING_HELP_NOTIFICATION_ID); + + const isActive = ReportingMenuStoreInstance.toggleCategory(category); + if (isActive + && (category as SubcategoryContainer).subcategories + && (category as SubcategoryContainer).subcategories.length === 1 + ) { + this.helpShownCategory = null; + + const subcategory = (category as SubcategoryContainer).subcategories[0]; + this.propagateUrlChange(category, subcategory); + } + }, + loadSubcategory(category: Category, subcategory: Subcategory, event?: MouseEvent) { + if (event + && (event.shiftKey || event.ctrlKey || event.metaKey) + ) { + return; + } + + NotificationsStore.remove(REPORTING_HELP_NOTIFICATION_ID); + + if (subcategory && subcategory.id === this.activeSubcategory) { + this.helpShownCategory = null; + + // this menu item is already active, a location change success would not be triggered, + // instead trigger an event (after the URL changes) + setTimeout(() => { + Matomo.postEvent('loadPage', category.id, subcategory.id); + }); + } + }, + makeUrl(category: Category, subcategory: Subcategory) { + const { + idSite, + period, + date, + segment, + comparePeriods, + compareDates, + compareSegments, + } = MatomoUrl.parsed.value; + + return MatomoUrl.stringify({ + idSite, + period, + date, + segment, + comparePeriods, + compareDates, + compareSegments, + category: category.id, + subcategory: subcategory.id, + }); + }, + htmlEntities(v: string) { + return Matomo.helper.htmlEntities(v); + }, + showHelp(category: Category, subcategory: Subcategory, event?: Event) { + const parsedUrl = MatomoUrl.parsed.value; + const currentCategory = parsedUrl.category; + const currentSubcategory = parsedUrl.subcategory; + + if ((currentCategory !== category.id + || currentSubcategory !== subcategory.id) + && event + ) { + this.showSubcategoryHelpOnLoad = { category, subcategory }; + MatomoUrl.updateHash({ + ...MatomoUrl.hashParsed.value, + category: category.id, + subcategory: subcategory.id, + }); + return; + } + + if (this.helpShownCategory + && category.id === this.helpShownCategory.category + && subcategory.id === this.helpShownCategory.subcategory + ) { + NotificationsStore.remove(REPORTING_HELP_NOTIFICATION_ID); + this.helpShownCategory = null; + return; + } + + const prefixText = translate('CoreHome_ReportingCategoryHelpPrefix', + category.name, subcategory.name); + const prefix = `<strong>${prefixText}</strong><br/>`; + + NotificationsStore.show({ + context: 'info', + id: REPORTING_HELP_NOTIFICATION_ID, + type: 'help', + noclear: true, + class: 'help-notification', + message: prefix + subcategory.help, + placeat: '#notificationContainer', + prepend: true, + }); + + this.helpShownCategory = { + category: category.id, + subcategory: subcategory.id, + }; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/ReportingMenu/Subcategory.ts b/plugins/CoreHome/vue/src/ReportingMenu/Subcategory.ts new file mode 100644 index 0000000000..b18efea4bd --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingMenu/Subcategory.ts @@ -0,0 +1,34 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { Orderable } from '../Orderable'; + +export interface Subcategory extends Orderable { + id: string; + name: string; + isGroup: boolean; + icon?: string; + tooltip?: string; + help?: string; + + /** + * @deprecated exists for BC, should be removed in Matomo 5 + */ + active?: boolean; +} + +export interface SubcategoryContainer extends Subcategory { + subcategories: Subcategory[]; +} + +export function getSubcategoryChildren(subcategory: Subcategory): Subcategory[] { + const container = subcategory as SubcategoryContainer; + if (container.subcategories) { + return container.subcategories; + } + return []; +} diff --git a/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.adapter.ts b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.adapter.ts new file mode 100644 index 0000000000..f54501f8ee --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.adapter.ts @@ -0,0 +1,14 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import ReportingPage from './ReportingPage.vue'; + +export default createAngularJsAdapter({ + component: ReportingPage, + directiveName: 'piwikReportingPage', +}); diff --git a/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.less b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.less new file mode 100644 index 0000000000..ea7137f68e --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.less @@ -0,0 +1,24 @@ +.reporting-page { + > .row { + margin-bottom: 0; + } + + .fullWidgetColumn { + padding-left: 0; + padding-right: 0; + } + + .leftWidgetColumn { + padding-left: 0; + } + + .rightWidgetColumn { + padding-right: 0; + } + + .isFirstWidgetInPage { + .card { + margin-top: 0; + } + } +}
\ No newline at end of file diff --git a/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.adapter.ts b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.adapter.ts new file mode 100644 index 0000000000..e9feb23393 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.adapter.ts @@ -0,0 +1,23 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import ReportingPageStoreInstance from './ReportingPage.store'; + +function reportingPageModelAdapter() { + return { + get page() { + return ReportingPageStoreInstance.page.value; + }, + get widgets() { + return ReportingPageStoreInstance.widgets.value; + }, + resetPage: ReportingPageStoreInstance.resetPage.bind(ReportingPageStoreInstance), + fetchPage: ReportingPageStoreInstance.fetchPage.bind(ReportingPageStoreInstance), + }; +} + +window.angular.module('piwikApp.service').factory('reportingPageModel', reportingPageModelAdapter); diff --git a/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.ts b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.ts new file mode 100644 index 0000000000..869117dfc6 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.ts @@ -0,0 +1,169 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { + computed, + DeepReadonly, + reactive, + readonly, +} from 'vue'; +import ReportingPagesStoreInstance, { Page } from '../ReportingPages/ReportingPages.store'; +import ReportMetadataStoreInstance from '../ReportMetadata/ReportMetadata.store'; +import { sortOrderables } from '../Orderable'; +import { getWidgetChildren } from '../Widget/Widgets.store'; +import { + GroupedWidgets, + Widget, + WidgetContainer, +} from '../Widget/types'; + +interface ReportingMenuStoreState { + page?: DeepReadonly<Page>; +} + +function shouldBeRenderedWithFullWidth(widget: Widget) { + // rather controller logic + if ((widget.isContainer && widget.layout && widget.layout === 'ByDimension') + || widget.viewDataTable === 'bydimension' + ) { + return true; + } + + if (widget.isWide) { + return true; + } + + return widget.viewDataTable + && (widget.viewDataTable === 'tableAllColumns' + || widget.viewDataTable === 'sparklines' + || widget.viewDataTable === 'graphEvolution'); +} + +function markWidgetsInFirstRowOfPage(widgets: (Widget|GroupedWidgets)[]) { + if (widgets && widgets[0]) { + const newWidgets: (Widget|GroupedWidgets)[] = [...widgets]; + + const groupedWidgets = widgets[0] as GroupedWidgets; + if (groupedWidgets.group) { + newWidgets[0] = { + ...newWidgets[0], + left: markWidgetsInFirstRowOfPage(groupedWidgets.left || []), + right: markWidgetsInFirstRowOfPage(groupedWidgets.right || []), + } as GroupedWidgets; + } else { + newWidgets[0] = { ...newWidgets[0], isFirstInPage: true }; + } + + return newWidgets; + } + + return widgets; +} + +export class ReportingPageStore { + private privateState = reactive<ReportingMenuStoreState>({}); + + private state = computed(() => readonly(this.privateState)); + + readonly page = computed(() => this.state.value.page); + + readonly widgets = computed(() => { + const page = this.page.value; + if (!page) { + return []; + } + + let widgets: Widget[] = []; + const reportsToIgnore: Record<string, unknown> = {}; + + const isIgnoredReport = (widget: Widget) => widget.isReport + && reportsToIgnore[`${widget.module}.${widget.action}`]; + + const getRelatedReports = (widget: Widget) => { + if (!widget.isReport) { + return []; + } + + const report = ReportMetadataStoreInstance.findReport(widget.module, widget.action); + if (!report || !report.relatedReports) { + return []; + } + + return report.relatedReports; + }; + + (page.widgets || []).forEach((widget) => { + if (isIgnoredReport(widget)) { + return; + } + + getRelatedReports(widget).forEach((report) => { + reportsToIgnore[`${report.module}.${report.action}`] = true; + }); + + widgets.push(widget); + }); + + widgets = sortOrderables(widgets); + + if (widgets.length === 1) { + // if there is only one widget, we always display it full width + return markWidgetsInFirstRowOfPage(widgets); + } + + const groupedWidgets: (Widget|GroupedWidgets)[] = []; + for (let i = 0; i < widgets.length; i += 1) { + const widget = widgets[i]; + + if (shouldBeRenderedWithFullWidth(widget) + || (widgets[i + 1] && shouldBeRenderedWithFullWidth(widgets[i + 1])) + ) { + groupedWidgets.push({ + ...widget, + widgets: sortOrderables(getWidgetChildren(widget)), + } as WidgetContainer); + } else { + let counter = 0; + const left = [widget]; + const right = []; + + while (widgets[i + 1] && !shouldBeRenderedWithFullWidth(widgets[i + 1])) { + i += 1; + counter += 1; + if (counter % 2 === 0) { + left.push(widgets[i]); + } else { + right.push(widgets[i]); + } + } + + groupedWidgets.push({ group: true, left, right } as GroupedWidgets); + } + } + + const sortedWidgets = markWidgetsInFirstRowOfPage(groupedWidgets); + return sortedWidgets; + }); + + fetchPage(category: string, subcategory: string): Promise<ReportingPageStore['page']['value']> { + this.resetPage(); + + return Promise.all([ + ReportingPagesStoreInstance.getAllPages(), + ReportMetadataStoreInstance.fetchReportMetadata(), + ]).then(() => { + this.privateState.page = ReportingPagesStoreInstance.findPage(category, subcategory); + return this.page.value; + }); + } + + resetPage(): void { + this.privateState.page = undefined; + } +} + +export default new ReportingPageStore(); diff --git a/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue new file mode 100644 index 0000000000..2cba4525ae --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue @@ -0,0 +1,293 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div class="reporting-page"> + <ActivityIndicator + :loading="loading" + /> + <div v-show="hasNoPage">{{ translate('CoreHome_NoSuchPage') }}</div> + <div + class="row" + v-for="widget in widgets" + :key="widget.uniqueId" + > + <Widget + class="col s12 fullWidgetColumn" + v-if="!widget.group" + :widget="widget" + /> + <div + v-if="widget.group" + class="col s12 l6 leftWidgetColumn" + > + <Widget + v-for="widgetInGroup in widget.left" + :widget="widgetInGroup" + :key="widgetInGroup.uniqueId" + /> + </div> + <div + v-if="widget.group" + class="col s12 l6 rightWidgetColumn" + > + <Widget + v-for="widgetInGroup in widget.right" + :widget="widgetInGroup" + :key="widgetInGroup.uniqueId" + /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent, watch } from 'vue'; +import ActivityIndicator from '../ActivityIndicator/ActivityIndicator.vue'; +import Widget from '../Widget/Widget.vue'; +import ReportingPageStoreInstance from './ReportingPage.store'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import { Periods } from '../Periods'; +import { NotificationsStore } from '../Notification'; +import { translate } from '../translate'; +import Matomo from '../Matomo/Matomo'; +import ReportingPagesStoreInstance from '../ReportingPages/ReportingPages.store'; +import AjaxHelper from '../AjaxHelper/AjaxHelper'; + +function showOnlyRawDataNotification() { + const params = 'category=General_Visitors&subcategory=Live_VisitorLog'; + const url = window.broadcast.buildReportingUrl(params); + NotificationsStore.show({ + id: 'onlyRawData', + animate: false, + context: 'info', + message: translate('CoreHome_PeriodHasOnlyRawData', `<a href="${url}">`, '</a>'), + type: 'transient', + }); +} + +function hideOnlyRawDataNoticifation() { + NotificationsStore.remove('onlyRawData'); +} + +interface ReportingPageState { + loading: boolean; + hasRawData: boolean; + hasNoVisits: boolean; + dateLastChecked: Date|null; + hasNoPage: boolean; +} + +interface LoadPageArgs { + category: string; + subcategory: string; + promise?: Promise<void>; +} + +export default defineComponent({ + components: { + ActivityIndicator, + Widget, + }, + data(): ReportingPageState { + return { + loading: false, + hasRawData: false, + hasNoVisits: false, + dateLastChecked: null, + hasNoPage: false, + }; + }, + created() { + ReportingPageStoreInstance.resetPage(); + + this.loading = true; // we only set loading on initial load + this.renderInitialPage(); + + watch(() => MatomoUrl.parsed.value, (newValue, oldValue) => { + if (newValue.category === oldValue.category + && newValue.subcategory === oldValue.subcategory + && newValue.period === oldValue.period + && newValue.date === oldValue.date + && newValue.segment === oldValue.segment + && JSON.stringify(newValue.compareDates) === JSON.stringify(oldValue.compareDates) + && JSON.stringify(newValue.comparePeriods) === JSON.stringify(oldValue.comparePeriods) + && JSON.stringify(newValue.compareSegments) === JSON.stringify(oldValue.compareSegments) + && JSON.stringify(newValue.columns || '') === JSON.stringify(oldValue.columns || '') + ) { + // this page is already loaded + return; + } + + if (newValue.date !== oldValue.date || newValue.period !== oldValue.period) { + hideOnlyRawDataNoticifation(); + this.dateLastChecked = null; + this.hasRawData = false; + this.hasNoVisits = false; + } + + this.renderPage(newValue.category as string, newValue.subcategory as string); + }); + + Matomo.on('loadPage', (category: string, subcategory: string) => { + this.renderPage(category, subcategory); + }); + }, + computed: { + widgets() { + return ReportingPageStoreInstance.widgets.value; + }, + }, + methods: { + renderPage(category: string, subcategory: string) { + if (!category || !subcategory) { + ReportingPageStoreInstance.resetPage(); + this.loading = false; + return; + } + + const parsedUrl = MatomoUrl.parsed.value; + const currentPeriod = parsedUrl.period as string; + const currentDate = parsedUrl.date as string; + + try { + Periods.parse(currentPeriod, currentDate); + } catch (e) { + NotificationsStore.show({ + id: 'invalidDate', + animate: false, + context: 'error', + message: translate('CoreHome_DateInvalid'), + type: 'transient', + }); + + ReportingPageStoreInstance.resetPage(); + this.loading = false; + return; + } + + NotificationsStore.remove('invalidDate'); + + Matomo.postEvent('piwikPageChange', {}); + + NotificationsStore.clearTransientNotifications(); + + if (Periods.parse(currentPeriod, currentDate).containsToday()) { + this.showOnlyRawDataMessageIfRequired(); + } + + const params: LoadPageArgs = { category, subcategory }; + Matomo.postEvent('ReportingPage.loadPage', params); + if (params.promise) { + this.loading = true; + Promise.resolve(params.promise).finally(() => { + this.loading = false; + }); + return; + } + + ReportingPageStoreInstance.fetchPage(category, subcategory).then(() => { + const hasNoPage = !ReportingPageStoreInstance.page.value; + if (hasNoPage) { + const page = ReportingPagesStoreInstance.findPageInCategory(category); + if (page && page.subcategory) { + MatomoUrl.updateHash({ + ...MatomoUrl.hashParsed.value, + subcategory: page.subcategory.id, + }); + return; + } + } + + this.hasNoPage = hasNoPage; + this.loading = false; + }); + }, + renderInitialPage() { + const parsed = MatomoUrl.parsed.value; + this.renderPage(parsed.category as string, parsed.subcategory as string); + }, + showOnlyRawDataMessageIfRequired() { + if (this.hasRawData && this.hasNoVisits) { + showOnlyRawDataNotification(); + } + + const parsedUrl = MatomoUrl.parsed.value; + + const { segment } = parsedUrl; + if (segment) { + hideOnlyRawDataNoticifation(); + return; + } + + const subcategoryExceptions = [ + 'Live_VisitorLog', + 'General_RealTime', + 'UserCountryMap_RealTimeMap', + 'MediaAnalytics_TypeAudienceLog', + 'MediaAnalytics_TypeRealTime', + 'FormAnalytics_TypeRealTime', + 'Goals_AddNewGoal', + ]; + + const categoryExceptions = [ + 'HeatmapSessionRecording_Heatmaps', + 'HeatmapSessionRecording_SessionRecordings', + 'Marketplace_Marketplace', + ]; + + const subcategory = parsedUrl.subcategory as string; + const category = parsedUrl.category as string; + if (subcategoryExceptions.indexOf(subcategory) !== -1 + || categoryExceptions.indexOf(category) !== -1 + || subcategory.toLowerCase().indexOf('manage') !== -1 + ) { + hideOnlyRawDataNoticifation(); + return; + } + + const minuteInMilliseconds = 60000; + if (this.dateLastChecked + && ((new Date()).valueOf() - this.dateLastChecked.valueOf()) < minuteInMilliseconds + ) { + return; + } + + AjaxHelper.fetch({ method: 'VisitsSummary.getVisits' }).then((json) => { + this.dateLastChecked = new Date(); + + if (json.value > 0) { + this.hasNoVisits = false; + hideOnlyRawDataNoticifation(); + return undefined; + } + + this.hasNoVisits = true; + + if (this.hasRawData) { + showOnlyRawDataNotification(); + return undefined; + } + + return AjaxHelper.fetch({ + method: 'Live.getLastVisitsDetails', + filter_limit: 1, + doNotFetchActions: 1, + }); + }).then((lastVisits) => { + if (!lastVisits || lastVisits.length === 0) { + this.hasRawData = false; + hideOnlyRawDataNoticifation(); + return; + } + + this.hasRawData = true; + showOnlyRawDataNotification(); + }); + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.adapter.ts b/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.adapter.ts new file mode 100644 index 0000000000..0c1981badb --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.adapter.ts @@ -0,0 +1,29 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import ReportingPagesStoreInstance from './ReportingPages.store'; +import { cloneThenApply, clone } from '../createAngularJsAdapter'; + +function reportingPagesModelAdapter() { + return { + get pages() { + return ReportingPagesStoreInstance.pages.value; + }, + findPageInCategory: ( + ...args: Parameters<typeof ReportingPagesStoreInstance.findPageInCategory> + ) => clone(ReportingPagesStoreInstance.findPageInCategory(...args)), + findPage: (...args: Parameters<typeof ReportingPagesStoreInstance.findPage>) => clone( + ReportingPagesStoreInstance.findPage(...args), + ), + reloadAllPages: () => ReportingPagesStoreInstance.reloadAllPages() + .then((p) => cloneThenApply(p)), + getAllPages: () => ReportingPagesStoreInstance.getAllPages() + .then((p) => cloneThenApply(p)), + }; +} + +window.angular.module('piwikApp.service').factory('reportingPagesModel', reportingPagesModelAdapter); diff --git a/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.ts b/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.ts new file mode 100644 index 0000000000..e59986d6f6 --- /dev/null +++ b/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.ts @@ -0,0 +1,79 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { + reactive, + computed, readonly, DeepReadonly, +} from 'vue'; +import AjaxHelper from '../AjaxHelper/AjaxHelper'; +import { Widget } from '../Widget/types'; + +interface CategoryRef { + id: string; + name: string; +} + +interface SubcategoryRef { + id: string; + name: string; +} + +export interface Page { + category: CategoryRef; + subcategory: SubcategoryRef; + widgets: Widget[]; +} + +interface ReportingPagesStoreState { + pages: Page[]; +} + +export class ReportingPagesStore { + private privateState = reactive<ReportingPagesStoreState>({ + pages: [], + }); + + private state = computed(() => readonly(this.privateState)); + + private fetchAllPagesPromise?: Promise<DeepReadonly<Page[]>>; + + readonly pages = computed(() => this.state.value.pages); + + findPageInCategory(categoryId: string): DeepReadonly<Page>|undefined { + // happens when user switches between sites, in this case check if the same category exists and + // if so, select first entry from that category + return this.pages.value.find((p) => p + && p.category && p.category.id === categoryId && p.subcategory && p.subcategory.id); + } + + findPage(categoryId: string, subcategoryId: string): DeepReadonly<Page>|undefined { + return this.pages.value.find((p) => p + && p.category && p.subcategory && p.category.id === categoryId + && `${p.subcategory.id}` === subcategoryId); + } + + reloadAllPages(): Promise<ReportingPagesStore['pages']['value']> { + delete this.fetchAllPagesPromise; + return this.getAllPages(); + } + + getAllPages(): Promise<ReportingPagesStore['pages']['value']> { + if (!this.fetchAllPagesPromise) { + this.fetchAllPagesPromise = AjaxHelper.fetch({ + method: 'API.getReportPagesMetadata', + filter_limit: '-1', + }).then((response) => { + this.privateState.pages = response; + return this.pages.value; + }); + } + + return this.fetchAllPagesPromise.then(() => this.pages.value); + } +} + +export default new ReportingPagesStore(); diff --git a/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.adapter.ts b/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.adapter.ts new file mode 100644 index 0000000000..9a8fac6a76 --- /dev/null +++ b/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.adapter.ts @@ -0,0 +1,29 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { IDirective, IScope } from 'angular'; +import SelectOnFocus from './SelectOnFocus'; + +export default function piwikSelectOnFocus(): IDirective { + return { + restrict: 'A', + link: function piwikSelectOnFocusLink(scope: IScope, element: JQuery) { + const binding = { + instance: null, + value: {}, + oldValue: null, + modifiers: {}, + dir: {}, + }; + + SelectOnFocus.mounted(element[0], binding); + element.on('$destroy', () => SelectOnFocus.unmounted(element[0], binding)); + }, + }; +} + +window.angular.module('piwikApp').directive('piwikSelectOnFocus', piwikSelectOnFocus); diff --git a/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.ts b/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.ts new file mode 100644 index 0000000000..a1a588336b --- /dev/null +++ b/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.ts @@ -0,0 +1,70 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { DirectiveBinding } from 'vue'; + +interface SelectOnFocusArgs { + // state + focusedElement?: HTMLElement; + elementSupportsSelect?: boolean; + + // event handlers + onFocusHandler?: (event: Event) => void; + onClickHandler?: (event: MouseEvent) => void; + onBlurHandler?: (event: Event) => void; +} + +function onFocusHandler(binding: DirectiveBinding<SelectOnFocusArgs>, event: Event) { + if (binding.value.focusedElement !== event.target) { + binding.value.focusedElement = event.target as HTMLElement; + window.angular.element(event.target!).select(); + } +} + +function onClickHandler(event: Event) { + // .select() + focus and blur seems to not work on pre elements + const range = document.createRange(); + range.selectNode(event.target as Node); + const selection = window.getSelection(); + if (selection && selection.rangeCount > 0) { + selection.removeAllRanges(); + } + if (selection) { + selection.addRange(range); + } +} + +function onBlurHandler(binding: DirectiveBinding<SelectOnFocusArgs>) { + delete binding.value.focusedElement; +} + +export default { + mounted(el: HTMLElement, binding: DirectiveBinding<SelectOnFocusArgs>): void { + const tagName = el.tagName.toLowerCase(); + binding.value.elementSupportsSelect = tagName === 'textarea'; + + if (binding.value.elementSupportsSelect) { + binding.value.onFocusHandler = onFocusHandler.bind(null, binding); + binding.value.onBlurHandler = onBlurHandler.bind(null, binding); + + el.addEventListener('focus', binding.value.onFocusHandler); + el.addEventListener('blur', binding.value.onBlurHandler); + } else { + binding.value.onClickHandler = onClickHandler; + + el.addEventListener('click', binding.value.onClickHandler); + } + }, + unmounted(el: HTMLElement, binding: DirectiveBinding<SelectOnFocusArgs>): void { + if (binding.value.elementSupportsSelect) { + el.removeEventListener('focus', binding.value.onFocusHandler!); + el.removeEventListener('blur', binding.value.onBlurHandler!); + } else { + el.removeEventListener('click', binding.value.onClickHandler!); + } + }, +}; diff --git a/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.adapter.ts b/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.adapter.ts new file mode 100644 index 0000000000..24f8186cb8 --- /dev/null +++ b/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.adapter.ts @@ -0,0 +1,32 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { IAttributes, IDirective, IScope } from 'angular'; +import ShowSensitiveData from './ShowSensitiveData'; + +export default function piwikShowSensitiveData(): IDirective { + return { + restrict: 'A', + link: function piwikShowSensitiveDataLink(scope: IScope, element: JQuery, attr: IAttributes) { + const binding = { + instance: null, + value: { + sensitiveData: attr.piwikShowSensitiveData || (attr.text ? attr.text() : ''), + showCharacters: attr.showCharacters ? parseInt(attr.showCharacters, 10) : undefined, + clickElementSelector: attr.clickElementSelector as string, + }, + oldValue: null, + modifiers: {}, + dir: {}, + }; + + ShowSensitiveData.mounted(element[0], binding); + }, + }; +} + +window.angular.module('piwikApp').directive('piwikShowSensitiveData', piwikShowSensitiveData); diff --git a/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.ts b/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.ts new file mode 100644 index 0000000000..777394e7e6 --- /dev/null +++ b/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.ts @@ -0,0 +1,65 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { DirectiveBinding } from 'vue'; +import { translate } from '../translate'; + +interface ShowSensitiveDataArgs { + sensitiveData: string; + showCharacters?: number; + clickElementSelector: string|HTMLElement|JQuery; +} + +const { $ } = window; + +/** + * Handles visibility of sensitive data. By default data will be shown replaced with stars (*) + * On click on the element the full data will be shown + * + * Configuration attributes: + * data-show-characters number of characters to show in clear text (defaults to 6) + * data-click-element-selector selector for element that will show the full data on click + * (defaults to element) + * + * Example: + * <div v-show-sensitive-date="some text"></div> + */ +export default { + mounted(el: HTMLElement, binding: DirectiveBinding<ShowSensitiveDataArgs>): void { + const element = $(el); + + const { sensitiveData } = binding.value; + const showCharacters = binding.value.showCharacters || 6; + const clickElement = binding.value.clickElementSelector || element; + + let protectedData = ''; + if (showCharacters > 0) { + protectedData += sensitiveData.slice(0, showCharacters); + } + protectedData += sensitiveData.slice(showCharacters).replace(/./g, '*'); + element.html(protectedData); + + function onClickHandler() { + element.html(sensitiveData); + $(clickElement).css({ + cursor: '', + }); + $(clickElement).tooltip('destroy'); + } + + $(clickElement).tooltip({ + content: translate('CoreHome_ClickToSeeFullInformation'), + items: '*', + track: true, + }); + + $(clickElement).one('click', onClickHandler); + $(clickElement).css({ + cursor: 'pointer', + }); + }, +}; diff --git a/plugins/CoreHome/vue/src/SideNav/SideNav.adapter.ts b/plugins/CoreHome/vue/src/SideNav/SideNav.adapter.ts new file mode 100644 index 0000000000..3778689d94 --- /dev/null +++ b/plugins/CoreHome/vue/src/SideNav/SideNav.adapter.ts @@ -0,0 +1,35 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { IDirective, ITimeoutService } from 'angular'; +import SideNav from './SideNav'; + +export default function piwikSideNav($timeout: ITimeoutService): IDirective { + return { + restrict: 'A', + priority: 10, + link: function linkPiwikSideNav(scope, element, attr) { + const binding = { + instance: null, + value: { + activator: $(attr.piwikSideNav)[0], + }, + oldValue: null, + modifiers: {}, + dir: {}, + }; + + $timeout(() => { + SideNav.mounted(element[0], binding); + }); + }, + }; +} + +piwikSideNav.$inject = ['$timeout']; + +window.angular.module('piwikApp.directive').directive('piwikSideNav', piwikSideNav); diff --git a/plugins/CoreHome/vue/src/SideNav/SideNav.ts b/plugins/CoreHome/vue/src/SideNav/SideNav.ts new file mode 100644 index 0000000000..ba98585066 --- /dev/null +++ b/plugins/CoreHome/vue/src/SideNav/SideNav.ts @@ -0,0 +1,56 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +import { DirectiveBinding } from 'vue'; +import DirectiveUtilities from '../directiveUtilities'; + +interface SideNavArgs { + activator: HTMLElement | string; +} + +let initialized = false; + +/** + * Will activate the materialize side nav feature once rendered. We use this directive as + * it makes sure the actual left menu is rendered at the time we init the side nav. + * + * Has to be set on a collaapsible element + * + * Example: + * <div class="collapsible" v-side-nav="nav .activateLeftMenu">...</div> + */ +export default { + mounted(el: HTMLElement, binding: DirectiveBinding<SideNavArgs>): void { + if (!binding.value.activator) { + return; + } + + setTimeout(() => { + if (!initialized) { + initialized = true; + + const sideNavActivator = DirectiveUtilities.getRef(binding.value.activator, binding); + if (sideNavActivator) { + window.$(sideNavActivator).show(); + + const targetSelector = sideNavActivator.getAttribute('data-target'); + + // @ts-ignore + window.$(`#${targetSelector}`).sidenav({ + closeOnClick: true, + }); + } + } + + if (el.classList.contains('collapsible')) { + window.$(el).collapsible(); + } + }); + }, +}; diff --git a/plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue b/plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue new file mode 100644 index 0000000000..548a697403 --- /dev/null +++ b/plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue @@ -0,0 +1,36 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div + @click="this.onClick($event)" + class="custom_select_all" + > + <a + @click="$event.preventDefault()" + v-html="$sanitize(allSitesText)" + tabindex="4" + :href="href" + /> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; + +export default defineComponent({ + props: { + href: String, + allSitesText: String, + }, + emits: ['click'], + methods: { + onClick(event: MouseEvent) { + this.$emit('click', event); + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/SiteSelector/Site.ts b/plugins/CoreHome/vue/src/SiteSelector/Site.ts new file mode 100644 index 0000000000..ee3d818dbd --- /dev/null +++ b/plugins/CoreHome/vue/src/SiteSelector/Site.ts @@ -0,0 +1,24 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +interface Site { + idsite: string|number; + name: string; + type: string; + group?: string; + timezone: string; + currency?: string; + timezone_name: string; + currency_name?: string; + main_url: string; + alias_urls: string[]; + excluded_ips: string; + excluded_parameters: string; + excluded_user_agents: string; +} + +export default Site; diff --git a/plugins/CoreHome/vue/src/SiteSelector/SiteRef.ts b/plugins/CoreHome/vue/src/SiteSelector/SiteRef.ts new file mode 100644 index 0000000000..f827f804a1 --- /dev/null +++ b/plugins/CoreHome/vue/src/SiteSelector/SiteRef.ts @@ -0,0 +1,13 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +interface SiteRef { + id: string|number; + name: string; +} + +export default SiteRef; diff --git a/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.adapter.ts b/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.adapter.ts new file mode 100644 index 0000000000..a29f6c4a1f --- /dev/null +++ b/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.adapter.ts @@ -0,0 +1,126 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { + IAttributes, + INgModelController, + IScope, + ITimeoutService, +} from 'angular'; +import { nextTick } from 'vue'; +import createAngularJsAdapter from '../createAngularJsAdapter'; +import SiteSelector from './SiteSelector.vue'; +import Matomo from '../Matomo/Matomo'; + +export default createAngularJsAdapter<[ITimeoutService]>({ + component: SiteSelector, + require: '?ngModel', + scope: { + showSelectedSite: { + angularJsBind: '=', + }, + showAllSitesItem: { + angularJsBind: '=', + }, + switchSiteOnSelect: { + angularJsBind: '=', + }, + onlySitesWithAdminAccess: { + angularJsBind: '=', + }, + name: { + angularJsBind: '@', + }, + allSitesText: { + angularJsBind: '@', + }, + allSitesLocation: { + angularJsBind: '@', + }, + placeholder: { + angularJsBind: '@', + }, + modelValue: { + default(scope: IScope, element: JQLite, attrs: IAttributes) { + if (attrs.siteid && attrs.sitename) { + return { id: attrs.siteid, name: Matomo.helper.htmlDecode(attrs.sitename) }; + } + + if (Matomo.idSite) { + return { + id: Matomo.idSite, + name: Matomo.helper.htmlDecode(Matomo.siteName), + }; + } + + return undefined; + }, + }, + }, + $inject: ['$timeout'], + directiveName: 'piwikSiteselector', + events: { + 'update:modelValue': (newValue, vm, scope, element, attrs, ngModel, $timeout) => { + if ((newValue && !vm.modelValue) + || (!newValue && vm.modelValue) + || newValue.id !== vm.modelValue.id + ) { + $timeout(() => { + scope.value = newValue; + + element.attr('siteid', newValue.id); + element.trigger('change', newValue); + + if (ngModel) { + ngModel.$setViewValue(newValue); + ngModel.$render(); // not called automatically by the digest + } + }); + } + }, + blur(event, vm, scope) { + setTimeout(() => scope.$apply()); + }, + }, + postCreate(vm, scope, element, attrs, controller) { + const ngModel = controller as INgModelController; + + scope.$watch('value', (newVal: unknown) => { + nextTick(() => { + if (newVal !== vm.modelValue) { + vm.modelValue = newVal; + } + }); + }); + + if (attrs.siteid && attrs.sitename) { + vm.modelValue = { id: attrs.siteid, name: Matomo.helper.htmlDecode(attrs.sitename) }; + } else if (Matomo.idSite) { + vm.modelValue = { + id: Matomo.idSite, + name: Matomo.helper.htmlDecode(Matomo.siteName), + }; + } + + // setup ng-model mapping + if (ngModel) { + ngModel.$setViewValue(vm.modelValue); + + ngModel.$render = () => { + nextTick(() => { + nextTick(() => { + if (window.angular.isString(ngModel.$viewValue)) { + vm.modelValue = JSON.parse(ngModel.$viewValue); + } else { + vm.modelValue = ngModel.$viewValue; + } + }); + }); + }; + } + }, +}); diff --git a/plugins/CoreHome/angularjs/siteselector/siteselector.directive.less b/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.less index 48700196c2..48700196c2 100644 --- a/plugins/CoreHome/angularjs/siteselector/siteselector.directive.less +++ b/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.less diff --git a/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue b/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue new file mode 100644 index 0000000000..5d115f8136 --- /dev/null +++ b/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue @@ -0,0 +1,378 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div + class="siteSelector piwikSelector borderedControl" + :class="{'expanded': showSitesList, 'disabled': !hasMultipleSites}" + v-focus-anywhere-but-here="{ blur: onBlur }" + > + <input + v-if="name" + type="hidden" + :value="modelValue?.id" + :name="name" + /> + <a + ref="selectorLink" + @click="onClickSelector" + @keydown="onPressEnter($event)" + href="javascript:void(0)" + :class="{'loading': isLoading}" + class="title" + tabindex="4" + :title="selectorLinkTitle" + > + <span + class="icon icon-arrow-bottom" + :class="{'iconHidden': isLoading, 'collapsed': !showSitesList}" + /> + <span> + <span + v-text="modelValue?.name || firstSiteName" + v-if="modelValue?.name || !placeholder" + /> + <span + v-if="!modelValue?.name && placeholder" + class="placeholder" + >{{ placeholder }}</span> + </span> + </a> + <div + v-show="showSitesList" + class="dropdown" + > + <div + class="custom_select_search" + v-show="autocompleteMinSites <= sites.length || searchTerm" + > + <input + type="text" + @click="searchTerm = '';loadInitialSites()" + v-model="searchTerm" + tabindex="4" + class="websiteSearch inp browser-default" + v-focus-if:[shouldFocusOnSearch]="{}" + :placeholder="translate('General_Search')" + /> + <img + title="Clear" + v-show="searchTerm" + @click="searchTerm = '';loadInitialSites()" + class="reset" + src="plugins/CoreHome/images/reset_search.png" + /> + </div> + <div v-if="allSitesLocation === 'top' && showAllSitesItem"> + <AllSitesLink + :href="urlAllSites" + :all-sites-text="allSitesText" + @click="onAllSitesClick($event)" + /> + </div> + <div class="custom_select_container"> + <ul + class="custom_select_ul_list" + @click="showSitesList = false" + > + <li + @click="switchSite({ ...site, id: site.idsite }, $event)" + v-show="!(!showSelectedSite && activeSiteId === site.idsite)" + v-for="(site, index) in sites" + :key="index" + > + <a + @click="$event.preventDefault()" + v-html="$sanitize(getMatchedSiteName(site.name))" + tabindex="4" + :href="getUrlForSiteId(site.idsite)" + :title="site.name" + /> + </li> + </ul> + <ul + v-show="!sites.length && searchTerm" + class="ui-autocomplete ui-front ui-menu ui-widget ui-widget-content ui-corner-all + siteSelect" + > + <li class="ui-menu-item"> + <a + class="ui-corner-all" + tabindex="-1" + > + {{ translate('SitesManager_NotFound') + ' ' + searchTerm }} + </a> + </li> + </ul> + </div> + <div v-if="allSitesLocation === 'bottom' && showAllSitesItem"> + <AllSitesLink + :href="urlAllSites" + :all-sites-text="allSitesText" + @click="onAllSitesClick($event)" + /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { DeepReadonly, defineComponent } from 'vue'; +import FocusAnywhereButHere from '../FocusAnywhereButHere/FocusAnywhereButHere'; +import FocusIf from '../FocusIf/FocusIf'; +import AllSitesLink from './AllSitesLink.vue'; +import Matomo from '../Matomo/Matomo'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import { translate } from '../translate'; +import SitesStore from './SitesStore'; +import debounce from '../debounce'; +import SiteRef from './SiteRef'; +import Site from './Site'; + +interface SiteSelectorState { + searchTerm: string; + showSitesList: boolean; + activeSiteId: string; + isLoading: boolean; + sites: DeepReadonly<Site[]>; + autocompleteMinSites: number; +} + +export default defineComponent({ + props: { + modelValue: { + type: Object, + default: (props: { modelValue?: SiteRef }): SiteRef|undefined => { + if (props.modelValue) { + return props.modelValue; + } + + return (Matomo.idSite ? { + id: Matomo.idSite, + name: Matomo.helper.htmlDecode(Matomo.siteName), + } : undefined); + }, + }, + showSelectedSite: { + type: Boolean, + default: false, + }, + showAllSitesItem: { + type: Boolean, + default: true, + }, + switchSiteOnSelect: { + type: Boolean, + default: true, + }, + onlySitesWithAdminAccess: { + type: Boolean, + default: false, + }, + name: { + type: String, + default: '', + }, + allSitesText: { + type: String, + default: translate('General_MultiSitesSummary'), + }, + allSitesLocation: { + type: String, + default: 'bottom', + }, + placeholder: String, + }, + emits: ['update:modelValue', 'blur'], + components: { + AllSitesLink, + }, + directives: { + FocusAnywhereButHere, + FocusIf, + }, + watch: { + searchTerm() { + this.onSearchTermChanged(); + }, + }, + data(): SiteSelectorState { + return { + searchTerm: '', + activeSiteId: `${Matomo.idSite}`, + showSitesList: false, + isLoading: false, + sites: [], + autocompleteMinSites: parseInt(Matomo.config.autocomplete_min_sites as string, 10), + }; + }, + created() { + this.searchSite = debounce(this.searchSite); + }, + mounted() { + window.initTopControls(); + + this.loadInitialSites().then(() => { + if ((!this.modelValue || !this.modelValue.id) && !this.hasMultipleSites && this.sites[0]) { + this.$emit('update:modelValue', { id: this.sites[0].idsite, name: this.sites[0].name }); + } + }); + + const shortcutTitle = translate('CoreHome_ShortcutWebsiteSelector'); + Matomo.helper.registerShortcut('w', shortcutTitle, (event: KeyboardEvent) => { + if (event.altKey) { + return; + } + if (event.preventDefault) { + event.preventDefault(); + } else { + event.returnValue = false; // IE + } + + const selectorLink = this.$refs.selectorLink as HTMLElement; + if (selectorLink) { + selectorLink.click(); + selectorLink.focus(); + } + }); + }, + computed: { + shouldFocusOnSearch() { + return (this.showSitesList && this.autocompleteMinSites <= this.sites.length) + || this.searchTerm; + }, + selectorLinkTitle() { + return this.hasMultipleSites + ? translate('CoreHome_ChangeCurrentWebsite', this.modelValue?.name || this.firstSiteName) + : ''; + }, + hasMultipleSites() { + return SitesStore.initialSites.value && SitesStore.initialSites.value.length > 1; + }, + firstSiteName() { + const initialSites = SitesStore.initialSites.value; + return initialSites && initialSites.length > 0 ? initialSites[0].name : ''; + }, + urlAllSites() { + const newQuery = MatomoUrl.stringify({ + ...MatomoUrl.urlParsed.value, + module: 'MultiSites', + action: 'index', + date: MatomoUrl.parsed.value.date, + period: MatomoUrl.parsed.value.period, + }); + return `?${newQuery}`; + }, + }, + methods: { + onSearchTermChanged() { + if (!this.searchTerm) { + this.isLoading = false; + this.loadInitialSites(); + } else { + this.isLoading = true; + this.searchSite(this.searchTerm); + } + }, + onAllSitesClick(event: MouseEvent) { + this.switchSite({ id: 'all', name: this.$props.allSitesText }, event); + this.showSitesList = false; + }, + switchSite(site: SiteRef, event: KeyboardEvent|MouseEvent) { + // for Mac OS cmd key needs to be pressed, ctrl key on other systems + const controlKey = navigator.userAgent.indexOf('Mac OS X') !== -1 ? event.metaKey : event.ctrlKey; + + if (event && controlKey && event.target && (event.target as HTMLLinkElement).href) { + window.open((event.target as HTMLLinkElement).href, '_blank'); + return; + } + + this.$emit('update:modelValue', { id: site.id, name: site.name }); + + if (!this.switchSiteOnSelect || this.activeSiteId === site.id) { + return; + } + + SitesStore.loadSite(site.id); + }, + onBlur() { + this.showSitesList = false; + this.$emit('blur'); + }, + onClickSelector() { + if (this.hasMultipleSites) { + this.showSitesList = !this.showSitesList; + + if (!this.isLoading && !this.searchTerm) { + this.loadInitialSites(); + } + } + }, + onPressEnter(event: KeyboardEvent) { + if (event.key !== 'Enter') { + return; + } + + event.preventDefault(); + + this.showSitesList = !this.showSitesList; + if (this.showSitesList && !this.isLoading) { + this.loadInitialSites(); + } + }, + getMatchedSiteName(siteName: string) { + const index = siteName.toUpperCase().indexOf(this.searchTerm.toUpperCase()); + if (index === -1 + || this.isLoading // only highlight when we know the displayed results are for a search + ) { + return Matomo.helper.htmlEntities(siteName); + } + + const previousPart = Matomo.helper.htmlEntities(siteName.substring(0, index)); + const lastPart = Matomo.helper.htmlEntities( + siteName.substring(index + this.searchTerm.length), + ); + + return `${previousPart}<span class="autocompleteMatched">${this.searchTerm}</span>${lastPart}`; + }, + loadInitialSites() { + return SitesStore.loadInitialSites().then((sites) => { + this.sites = sites || []; + }); + }, + searchSite(term: string) { + this.isLoading = true; + + SitesStore.searchSite(term, this.onlySitesWithAdminAccess).then((sites) => { + if (term !== this.searchTerm) { + return; // search term changed in the meantime + } + + if (sites) { + this.sites = sites; + } + }).finally(() => { + this.isLoading = false; + }); + }, + getUrlForSiteId(idSite: string|number) { + const newQuery = MatomoUrl.stringify({ + ...MatomoUrl.urlParsed.value, + segment: '', + idSite, + }); + + const newHash = MatomoUrl.stringify({ + ...MatomoUrl.hashParsed.value, + segment: '', + idSite, + }); + + return `?${newQuery}#?${newHash}`; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/SiteSelector/SitesStore.adapter.ts b/plugins/CoreHome/vue/src/SiteSelector/SitesStore.adapter.ts new file mode 100644 index 0000000000..c454d60625 --- /dev/null +++ b/plugins/CoreHome/vue/src/SiteSelector/SitesStore.adapter.ts @@ -0,0 +1,24 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import SitesStore from './SitesStore'; +import { cloneThenApply } from '../createAngularJsAdapter'; + +function siteSelectorModelAdapter() { + return { + get initialSites() { + return SitesStore.initialSites.value; + }, + loadSite: SitesStore.loadSite.bind(SitesStore), + loadInitialSites: () => cloneThenApply(SitesStore.loadInitialSites()), + searchSite: (...args: Parameters<typeof SitesStore['searchSite']>) => cloneThenApply( + SitesStore.searchSite(...args), + ), + }; +} + +window.angular.module('piwikApp.service').factory('siteSelectorModel', siteSelectorModelAdapter); diff --git a/plugins/CoreHome/vue/src/SiteSelector/SitesStore.ts b/plugins/CoreHome/vue/src/SiteSelector/SitesStore.ts new file mode 100644 index 0000000000..4a45b37799 --- /dev/null +++ b/plugins/CoreHome/vue/src/SiteSelector/SitesStore.ts @@ -0,0 +1,134 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { + reactive, + computed, + readonly, + DeepReadonly, +} from 'vue'; +import AjaxHelper from '../AjaxHelper/AjaxHelper'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import Site from './Site'; + +interface SitesStoreState { + initialSites: DeepReadonly<Site[]>; + isInitialized: boolean; +} + +class SitesStore { + private state = reactive<SitesStoreState>({ + initialSites: [], + isInitialized: false, + }); + + private currentRequestAbort: AbortController | null = null; + + private limitRequest?: Promise<{ value: number|string }>; + + public readonly initialSites = computed(() => readonly(this.state.initialSites)); + + loadInitialSites(): Promise<DeepReadonly<Site[]>|null> { + if (this.state.isInitialized) { + return Promise.resolve(readonly(this.state.initialSites)); + } + + return this.searchSite('%').then((sites) => { + this.state.isInitialized = true; + if (sites !== null) { + this.state.initialSites = sites; + } + return sites; + }); + } + + loadSite(idSite: number|string): void { + if (idSite === 'all') { + MatomoUrl.updateUrl({ + ...MatomoUrl.urlParsed.value, + module: 'MultiSites', + action: 'index', + date: MatomoUrl.parsed.value.date, + period: MatomoUrl.parsed.value.period, + }); + } else { + MatomoUrl.updateUrl({ + ...MatomoUrl.urlParsed.value, + segment: '', + idSite, + }, { + ...MatomoUrl.hashParsed.value, + segment: '', + idSite, + }); + } + } + + searchSite(term?: string, onlySitesWithAdminAccess = false): Promise<DeepReadonly<Site[]>|null> { + if (!term) { + return this.loadInitialSites(); + } + + if (this.currentRequestAbort) { + this.currentRequestAbort.abort(); + } + + if (!this.limitRequest) { + this.limitRequest = AjaxHelper.fetch({ method: 'SitesManager.getNumWebsitesToDisplayPerPage' }); + } + + return this.limitRequest.then((response) => { + const limit = response.value; + + let methodToCall = 'SitesManager.getPatternMatchSites'; + if (onlySitesWithAdminAccess) { + methodToCall = 'SitesManager.getSitesWithAdminAccess'; + } + + this.currentRequestAbort = new AbortController(); + return AjaxHelper.fetch({ + method: methodToCall, + limit, + pattern: term, + }, { + abortController: this.currentRequestAbort, + }); + }).then((response) => { + if (response) { + return this.processWebsitesList(response as Site[]); + } + + return null; + }).finally(() => { + this.currentRequestAbort = null; + }); + } + + private processWebsitesList(response: Site[]): Site[] { + let sites = response; + + if (!sites || !sites.length) { + return []; + } + + sites = sites.map((s) => ({ + ...s, + name: s.group ? `[${s.group}] ${s.name}` : s.name, + })); + + sites.sort((lhs: Site, rhs: Site) => { + if (lhs.name.toLowerCase() < rhs.name.toLowerCase()) { + return -1; + } + return lhs.name.toLowerCase() > rhs.name.toLowerCase() ? 1 : 0; + }); + + return sites; + } +} + +export default new SitesStore(); diff --git a/plugins/CoreHome/vue/src/Sparkline/Sparkline.adapter.ts b/plugins/CoreHome/vue/src/Sparkline/Sparkline.adapter.ts new file mode 100644 index 0000000000..70dacd306e --- /dev/null +++ b/plugins/CoreHome/vue/src/Sparkline/Sparkline.adapter.ts @@ -0,0 +1,23 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import Sparkline from './Sparkline.vue'; + +export default createAngularJsAdapter({ + component: Sparkline, + scope: { + seriesIndices: { + angularJsBind: '<', + }, + params: { + angularJsBind: '<', + }, + }, + directiveName: 'piwikSparkline', + restrict: 'E', +}); diff --git a/plugins/CoreHome/angularjs/sparkline/sparkline.component.less b/plugins/CoreHome/vue/src/Sparkline/Sparkline.less index a31d68547e..a31d68547e 100644 --- a/plugins/CoreHome/angularjs/sparkline/sparkline.component.less +++ b/plugins/CoreHome/vue/src/Sparkline/Sparkline.less diff --git a/plugins/CoreHome/vue/src/Sparkline/Sparkline.vue b/plugins/CoreHome/vue/src/Sparkline/Sparkline.vue new file mode 100644 index 0000000000..37f9008d0e --- /dev/null +++ b/plugins/CoreHome/vue/src/Sparkline/Sparkline.vue @@ -0,0 +1,90 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <img :src="sparklineUrl" /> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import Matomo from '../Matomo/Matomo'; +import AjaxHelper from '../AjaxHelper/AjaxHelper'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import RangePeriod from '../Periods/Range'; +import { format } from '../Periods'; + +export default defineComponent({ + props: { + seriesIndices: Array, + params: Object, + }, + data() { + return { + isWidget: false, + }; + }, + mounted() { + this.isWidget = !!this.$el.closest('[widgetId]'); + }, + computed: { + sparklineUrl() { + const { seriesIndices, params } = this; + + const sparklineColors = Matomo.getSparklineColors(); + + if (seriesIndices) { + sparklineColors.lineColor = sparklineColors.lineColor.filter( + (c, index) => seriesIndices.indexOf(index) !== -1, + ); + } + + const colors = JSON.stringify(sparklineColors); + + const defaultParams = { + forceView: '1', + viewDataTable: 'sparkline', + widget: this.isWidget ? '1' : '0', + showtitle: '1', + colors, + random: Date.now(), + date: this.defaultDate, + }; + + const helper = new AjaxHelper(); + const urlParams = helper.mixinDefaultGetParams({ ...defaultParams, ...params }); + + // Append the token_auth to the URL if it was set (eg. embed dashboard) + const token_auth = MatomoUrl.parsed.value.token_auth as string; + if (token_auth && token_auth.length && Matomo.shouldPropagateTokenAuth) { + urlParams.token_auth = token_auth; + } + + return `?${MatomoUrl.stringify(urlParams)}`; + }, + defaultDate() { + if (Matomo.period === 'range') { + return `${Matomo.startDateString},${Matomo.endDateString}`; + } + + const dateRange = RangePeriod.getLastNRange( + Matomo.period!, + 30, + Matomo.currentDateString!, + ).getDateRange(); + + const piwikMinDate = new Date(Matomo.minDateYear, Matomo.minDateMonth - 1, Matomo.minDateDay); + if (dateRange[0] < piwikMinDate) { + dateRange[0] = piwikMinDate; + } + + const startDateStr = format(dateRange[0]); + const endDateStr = format(dateRange[1]); + + return `${startDateStr},${endDateStr}`; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/Tooltips/Tooltips.ts b/plugins/CoreHome/vue/src/Tooltips/Tooltips.ts new file mode 100644 index 0000000000..b5cb0010a9 --- /dev/null +++ b/plugins/CoreHome/vue/src/Tooltips/Tooltips.ts @@ -0,0 +1,46 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { DirectiveBinding } from 'vue'; + +interface TooltipsArgs { + content?: () => void; + delay?: number; + duration?: number; +} + +const { $ } = window; + +function defaultContentTransform(this: HTMLElement) { + const title = $(this).attr('title') || ''; + return window.vueSanitize(title.replace(/\n/g, '<br />')); +} + +function setupTooltips(el: HTMLElement, binding: DirectiveBinding<TooltipsArgs>) { + $(el).tooltip({ + track: true, + content: binding.value?.content || defaultContentTransform, + show: { delay: binding.value?.delay || 700, duration: binding.value?.duration || 200 }, + hide: false, + }); +} + +export default { + mounted(el: HTMLElement, binding: DirectiveBinding<TooltipsArgs>): void { + setTimeout(() => setupTooltips(el, binding)); + }, + updated(el: HTMLElement, binding: DirectiveBinding<TooltipsArgs>): void { + setTimeout(() => setupTooltips(el, binding)); + }, + beforeUnmount(el: HTMLElement): void { + try { + window.$(el).tooltip('destroy'); + } catch (e) { + // ignore + } + }, +}; diff --git a/plugins/CoreHome/vue/src/Widget/Widget.adapter.ts b/plugins/CoreHome/vue/src/Widget/Widget.adapter.ts new file mode 100644 index 0000000000..c33934c04a --- /dev/null +++ b/plugins/CoreHome/vue/src/Widget/Widget.adapter.ts @@ -0,0 +1,25 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import Widget from './Widget.vue'; + +export default createAngularJsAdapter({ + component: Widget, + scope: { + widget: { + angularJsBind: '=?piwikWidget', + }, + widgetized: { + angularJsBind: '=?', + }, + containerid: { + angularJsBind: '@', + }, + }, + directiveName: 'piwikWidget', +}); diff --git a/plugins/CoreHome/vue/src/Widget/Widget.vue b/plugins/CoreHome/vue/src/Widget/Widget.vue new file mode 100644 index 0000000000..720970109e --- /dev/null +++ b/plugins/CoreHome/vue/src/Widget/Widget.vue @@ -0,0 +1,187 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div + v-if="actualWidget" + v-show="showWidget" + class="matomo-widget" + :class="{'isFirstWidgetInPage': actualWidget.isFirstInPage}" + :id="actualWidget.uniqueId" + v-tooltips="{ content: tooltipContent }" + > + <WidgetLoader + v-if="!actualWidget.isContainer && actualWidget.parameters" + :widget-params="actualWidget.parameters" + :widget-name="actualWidget.name" + /> + <div v-if="actualWidget.isContainer + && actualWidget.layout !== 'ByDimension' + && !this.preventRecursion" + > + <div> + <WidgetContainer :container="actualWidget.widgets" /> + </div> + </div> + <div v-if="actualWidget.isContainer && actualWidget.layout === 'ByDimension'"> + <div> + <WidgetByDimensionContainer :widgets="actualWidget.widgets" /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { DeepReadonly, defineComponent } from 'vue'; +import WidgetLoader from '../WidgetLoader/WidgetLoader.vue'; +import WidgetContainer from '../WidgetContainer/WidgetContainer.vue'; +import WidgetByDimensionContainer from '../WidgetByDimensionContainer/WidgetByDimensionContainer.vue'; +import WidgetsStoreInstance, { getWidgetChildren } from './Widgets.store'; +import { + Widget as WidgetData, + WidgetContainer as WidgetDataContainer, +} from './types'; +import AjaxHelper from '../AjaxHelper/AjaxHelper'; +import ReportMetadataStoreInstance from '../ReportMetadata/ReportMetadata.store'; +import Tooltips from '../Tooltips/Tooltips'; + +function findContainer( + widgetsByCategory: typeof WidgetsStoreInstance.widgets.value, + containerId: string, +): DeepReadonly<WidgetData>|undefined { + let widget: DeepReadonly<WidgetData>|undefined = undefined; + Object.values(widgetsByCategory || {}).some((widgets: DeepReadonly<WidgetData[]>) => { + widget = widgets.find((w) => w && w.isContainer && w.parameters?.containerId === containerId); + return widget; + }); + return widget; +} + +/** + * Renders any kind of widget. If you have a widget and you want to have it rendered, use this + * directive. It will display a name on top and the actual widget below. It can handle any kind + * of widget, no matter whether it is a regular widget or a container. + * + * @param {Object} piwikWidget A widget object as returned by the WidgetMetadata API. + * @param {Object} piwikWidget.middlewareParameters If present, we will request a URL using the + * given parameters and only if this URL + * returns a JSON `true` the widget will be + * shown. Otherwise the widget won't be shown. + * @param {String} containerId If you do not have a widget object but a containerId we will find + * the correct widget object based on the given containerId. Be aware + * that we might not find the widget if it is for example not + * available for the current user or period/date. + * @param {Boolean} widgetized true if the widget is widgetized (eg in Dashboard or exported). + * In this case we will add a URL parameter widget=1 to all widgets. + * Eg sparklines will be then displayed one after another + * (vertically aligned) instead of two next to each other. + * + * Example: + * <Widget :widget="widget"></Widget> + * // in this case we will find the correct widget automatically + * <Widget :containerid="widgetGoalsOverview"></Widget> + * // disables rating feature, no initial headline + * <Widget :widget="widget" :widetized="true"></Widget> + */ +export default defineComponent({ + props: { + widget: Object, + widgetized: Boolean, + containerid: String, + preventRecursion: Boolean, + }, + components: { + WidgetLoader, + WidgetContainer, + WidgetByDimensionContainer, + }, + directives: { + Tooltips, + }, + data() { + return { + showWidget: false, + }; + }, + setup() { + function tooltipContent(this: HTMLElement) { + const $this = window.$(this) as JQuery; + if ($this.attr('piwik-field') === '' || $this.hasClass('matomo-form-field')) { + // do not show it for form fields + return ''; + } + + const title = window.$(this).attr('title') || ''; + return window.vueSanitize(title.replace(/\n/g, '<br />')); + } + + return { + tooltipContent, + }; + }, + created() { + const { actualWidget } = this; + + if (actualWidget && actualWidget.middlewareParameters) { + const params = actualWidget.middlewareParameters as unknown as QueryParameters; + AjaxHelper.fetch(params).then((response) => { + this.showWidget = !!response; + }); + } else { + this.showWidget = true; + } + }, + computed: { + allWidgets() { + return WidgetsStoreInstance.widgets.value; + }, + actualWidget() { + const widget = this.widget as WidgetData; + + if (widget) { + const result = { ...widget }; + + if (widget && widget.isReport && !widget.documentation) { + const report = ReportMetadataStoreInstance.findReport(widget.module, widget.action); + if (report && report.documentation) { + result.documentation = report.documentation; + } + } + + return widget; + } + + if (this.containerid) { + const containerWidget = findContainer(this.allWidgets, this.containerid); + if (containerWidget) { + const result = { ...containerWidget }; + + if (this.widgetized) { + result.isFirstInPage = true; + result.parameters = { ...result.parameters, widget: '1' }; + + const widgets = getWidgetChildren(result); + if (widgets) { + (result as WidgetDataContainer).widgets = widgets.map((w) => ({ + ...w, + parameters: { + ...w.parameters, + widget: '1', + containerId: this.containerid!, + }, + })); + } + } + + return result; + } + } + + return null; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/Widget/Widgets.store.ts b/plugins/CoreHome/vue/src/Widget/Widgets.store.ts new file mode 100644 index 0000000000..0ef76bee1c --- /dev/null +++ b/plugins/CoreHome/vue/src/Widget/Widgets.store.ts @@ -0,0 +1,79 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { + reactive, + readonly, + computed, + DeepReadonly, +} from 'vue'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import { Widget, WidgetContainer } from './types'; + +interface WidgetsStoreState { + isFetchedFirstTime: boolean; + categorizedWidgets: Record<string, Widget[]>; +} + +export function getWidgetChildren(widget: Widget): Widget[] { + const container = widget as WidgetContainer; + if (container.widgets) { + return container.widgets; + } + return []; +} + +class WidgetsStore { + private privateState = reactive<WidgetsStoreState>({ + isFetchedFirstTime: false, + categorizedWidgets: {}, + }); + + private state = computed((): DeepReadonly<WidgetsStoreState> => { + if (!this.privateState.isFetchedFirstTime) { + // initiating a side effect in a computed property seems wrong, but it needs to be + // executed after knowing a user's logged in and it will succeed. + this.fetchAvailableWidgets(); + } + + return readonly(this.privateState); + }); + + readonly widgets = computed(() => this.state.value.categorizedWidgets); + + private fetchAvailableWidgets(): Promise<WidgetsStore['widgets']['value']> { + // if there's no idSite, don't make the request since it will just fail + if (!MatomoUrl.parsed.value.idSite) { + return Promise.resolve(this.widgets.value); + } + + this.privateState.isFetchedFirstTime = true; + return new Promise((resolve, reject) => { + try { + window.widgetsHelper.getAvailableWidgets((widgets: Record<string, unknown[]>) => { + const casted = widgets as unknown as Record<string, Widget[]>; + this.privateState.categorizedWidgets = casted; + resolve(this.widgets.value); + }); + } catch (e) { + reject(e); + } + }); + } + + reloadAvailableWidgets(): Promise<WidgetsStore['widgets']['value']> { + if (typeof window.widgetsHelper === 'object' && window.widgetsHelper.availableWidgets) { + // lets also update widgetslist so will be easier to update list of available widgets in + // dashboard selector immediately + delete window.widgetsHelper.availableWidgets; + } + + return this.fetchAvailableWidgets(); + } +} + +export default new WidgetsStore(); diff --git a/plugins/CoreHome/vue/src/Widget/types.ts b/plugins/CoreHome/vue/src/Widget/types.ts new file mode 100644 index 0000000000..598fe567b9 --- /dev/null +++ b/plugins/CoreHome/vue/src/Widget/types.ts @@ -0,0 +1,37 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { Orderable } from '../Orderable'; +import { Subcategory } from '../ReportingMenu/Subcategory'; + +export interface Widget extends Orderable { + uniqueId?: string; + module?: string; + action?: string; + viewDataTable?: string; + parameters?: Record<string, unknown>; + subcategory?: Subcategory; + isContainer?: boolean; + isReport?: boolean; + middlewareParameters?: Record<string, unknown>; + documentation?: string; + layout?: string; + isWide?: boolean; + isFirstInPage?: boolean; +} + +// get around DeepReadonly<> not being able to handle recursive types by moving the +// recursive properties to subtypes that are only referenced when needed +export interface WidgetContainer extends Widget { + widgets?: Widget[]; +} + +export interface GroupedWidgets { + group: boolean; + left?: Widget[]; + right?: Widget[]; +} diff --git a/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.adapter.ts b/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.adapter.ts new file mode 100644 index 0000000000..7f3f2bfb65 --- /dev/null +++ b/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.adapter.ts @@ -0,0 +1,23 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import WidgetByDimensionContainer from './WidgetByDimensionContainer.vue'; +import { Widget } from '../Widget/types'; + +export default createAngularJsAdapter({ + component: WidgetByDimensionContainer, + scope: { + widgets: { + angularJsBind: '=piwikWidgetByDimensionContainer', + transform(v) { + return (v as { widgets: Widget[] }).widgets; + }, + }, + }, + directiveName: 'piwikWidgetByDimensionContainer', +}); diff --git a/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.less b/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.less index 7f2e4844fa..9f8f6cce9c 100644 --- a/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.less +++ b/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.less @@ -14,6 +14,7 @@ .dimensionReport { float: left; min-width: 500px; + max-width: 100%; } table.dataTable tr td.label { diff --git a/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue b/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue new file mode 100644 index 0000000000..60e87a342b --- /dev/null +++ b/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue @@ -0,0 +1,101 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div class="reportsByDimensionView"> + <div class="entityList"> + <div + class="dimensionCategory" + v-for="category in widgetsByCategory" + :key="category.name" + > + {{ category.name }} + <ul class="listCircle"> + <li + class="reportDimension" + v-for="widget in category.widgets" + :key="widget.uniqueId" + :class="{ activeDimension: selectedWidget.uniqueId === widget.uniqueId }" + @click="selectWidget(widget)" + > + <span class="dimension">{{ widget.name }}</span> + </li> + </ul> + </div> + </div> + <div class="reportContainer"> + <WidgetLoader + v-if="selectedWidget.parameters" + :widget-params="selectedWidget.parameters" + class="dimensionReport" + /> + </div> + <div class="clear" /> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import WidgetLoader from '../WidgetLoader/WidgetLoader.vue'; +import { Widget } from '../Widget/types'; +import { sortOrderables } from '../Orderable'; + +interface WidgetByDimensionContainerState { + selectedWidget: Widget|null; +} + +interface WidgetCategory { + name: string; + order: number; + widgets: Widget[]; +} + +export default defineComponent({ + props: { + widgets: Array, + }, + components: { + WidgetLoader, + }, + data(): WidgetByDimensionContainerState { + return { + selectedWidget: null, + }; + }, + created() { + [this.selectedWidget] = this.widgetsSorted; + }, + computed: { + widgetsSorted(): Widget[] { + return sortOrderables(this.widgets as Widget[]); + }, + widgetsByCategory() { + const byCategory: Record<string, WidgetCategory> = {}; + + this.widgetsSorted.forEach((widget) => { + const category = widget.subcategory?.name; + if (!category) { + return; + } + + if (!byCategory[category]) { + byCategory[category] = { name: category, order: widget.order, widgets: [] }; + } + + byCategory[category].widgets!.push(widget); + }); + + return sortOrderables(Object.values(byCategory)); + }, + }, + methods: { + selectWidget(widget: Widget) { + // we copy to force rerender if selecting same widget + this.selectedWidget = { ...widget }; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.adapter.ts b/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.adapter.ts new file mode 100644 index 0000000000..3a8a714823 --- /dev/null +++ b/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.adapter.ts @@ -0,0 +1,19 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import WidgetContainer from './WidgetContainer.vue'; + +export default createAngularJsAdapter({ + component: WidgetContainer, + scope: { + container: { + angularJsBind: '=piwikWidgetContainer', + }, + }, + directiveName: 'piwikWidgetContainer', +}); diff --git a/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue b/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue new file mode 100644 index 0000000000..5f294cbc0b --- /dev/null +++ b/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue @@ -0,0 +1,66 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div> + <div + v-for="(widget, index) in actualContainer" + :key="index" + > + <div> + <Widget + :widget="widget" + :prevent-recursion="true" + /> + </div> + </div> + </div> +</template> + +<script lang="ts"> +import { defineComponent } from 'vue'; +import useExternalPluginComponent from '../useExternalPluginComponent'; +import { Widget as WidgetData } from '../Widget/types'; + +// since we're recursing, don't import the plugin directly +const Widget = useExternalPluginComponent('CoreHome', 'Widget'); + +export default defineComponent({ + props: { + container: { + type: Array, + required: true, + }, + }, + components: { + Widget, + }, + computed: { + actualContainer() { + const container = this.container as WidgetData[]; + + if (!container?.[0]?.parameters) { + return container; + } + + const [widget] = container; + const isWidgetized = widget.parameters?.widget === '1' || widget.parameters?.widget === 1; + + const isGraphEvolution = isWidgetized && widget.viewDataTable === 'graphEvolution'; + + // we hide the first title for Visits Overview with Graph and Goal Overview + const firstWidget = isGraphEvolution + ? { ...widget, parameters: { ...widget.parameters, showtitle: '0' } } + : widget; + + return [ + firstWidget, + ...container.slice(1), + ]; + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.adapter.ts b/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.adapter.ts new file mode 100644 index 0000000000..9ec44f3174 --- /dev/null +++ b/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.adapter.ts @@ -0,0 +1,23 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import createAngularJsAdapter from '../createAngularJsAdapter'; +import WidgetLoader from './WidgetLoader.vue'; + +export default createAngularJsAdapter({ + component: WidgetLoader, + scope: { + piwikWidgetLoader: { + vue: 'widgetParams', + angularJsBind: '=', + }, + widgetName: { + angularJsBind: '@', + }, + }, + directiveName: 'piwikWidgetLoader', +}); diff --git a/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue b/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue new file mode 100644 index 0000000000..7b42c8ab1c --- /dev/null +++ b/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue @@ -0,0 +1,256 @@ +<!-- + Matomo - free/libre analytics platform + @link https://matomo.org + @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later +--> + +<template> + <div> + <ActivityIndicator + :loading-message="loadingMessage" + :loading="loading" + /> + <div v-show="loadingFailed"> + <h2 v-if="widgetName">{{ widgetName }}</h2> + <div class="notification system notification-error"> + {{ translate('General_ErrorRequest', '', '') }} + <a + rel="noreferrer noopener" + target="_blank" + href="https://matomo.org/faq/troubleshooting/faq_19489/" + v-if="hasErrorFaqLink" + > + {{ translate('General_ErrorRequestFaqLink') }} + </a> + </div> + </div> + <div class="theWidgetContent" ref="widgetContent" /> + </div> +</template> + +<script lang="ts"> +import { IRootScopeService, IScope } from 'angular'; +import { defineComponent } from 'vue'; +import ActivityIndicator from '../ActivityIndicator/ActivityIndicator.vue'; +import { translate } from '../translate'; +import Matomo from '../Matomo/Matomo'; +import AjaxHelper from '../AjaxHelper/AjaxHelper'; +import { NotificationsStore } from '../Notification'; +import MatomoUrl from '../MatomoUrl/MatomoUrl'; +import ComparisonsStoreInstance from '../Comparisons/Comparisons.store.instance'; + +interface WidgetLoaderState { + loading: boolean; + loadingFailed: boolean; + changeCounter: number; + currentScope: null|IScope; + lastWidgetAbortController: null|AbortController; +} + +/** + * Loads any custom widget or URL based on the given parameters. + * + * The currently active idSite, period, date and segment (if needed) is automatically + * appended to the parameters. If this widget is removed from the DOM and requests are in + * progress, these requests will be aborted. A loading message or an error message on failure + * is shown as well. It's kinda similar to ng-include but there it is not possible to + * listen to HTTP errors etc. + * + * Example: + * <WidgetLoader :widget-params="{module: '', action: '', ...}"/> + */ +export default defineComponent({ + props: { + widgetParams: Object, + widgetName: String, + }, + components: { + ActivityIndicator, + }, + data(): WidgetLoaderState { + return { + loading: false, + loadingFailed: false, + changeCounter: 0, + currentScope: null, + lastWidgetAbortController: null, + }; + }, + watch: { + widgetParams(parameters: QueryParameters) { + if (parameters) { + this.loadWidgetUrl(parameters, this.changeCounter += 1); + } + }, + }, + computed: { + loadingMessage() { + if (!this.widgetName) { + return translate('General_LoadingData'); + } + + return translate('General_LoadingPopover', this.widgetName); + }, + hasErrorFaqLink() { + const isGeneralSettingsAdminEnabled = Matomo.config.enable_general_settings_admin; + const isPluginsAdminEnabled = Matomo.config.enable_plugins_admin; + + return Matomo.hasSuperUserAccess + && (isGeneralSettingsAdminEnabled + || isPluginsAdminEnabled); + }, + }, + mounted() { + if (this.widgetParams) { + this.loadWidgetUrl(this.widgetParams as QueryParameters, this.changeCounter += 1); + } + }, + beforeUnmount() { + this.cleanupLastWidgetContent(); + }, + methods: { + abortHttpRequestIfNeeded() { + if (this.lastWidgetAbortController) { + this.lastWidgetAbortController.abort(); + this.lastWidgetAbortController = null; + } + }, + cleanupLastWidgetContent() { + const widgetContent = this.$refs.widgetContent as HTMLElement; + Matomo.helper.destroyVueComponent(widgetContent); + if (this.currentScope) { + this.currentScope.$destroy(); + } + if (widgetContent) { + widgetContent.innerHTML = ''; + } + }, + getWidgetUrl(parameters?: QueryParameters): QueryParameters { + const urlParams = MatomoUrl.parsed.value; + + let fullParameters: QueryParameters = { ...(parameters || {}) }; + + const paramsToForward = Object.keys({ + ...MatomoUrl.hashParsed.value, + idSite: '', + period: '', + date: '', + segment: '', + widget: '', + }); + + paramsToForward.forEach((key) => { + if (key === 'category' || key === 'subcategory') { + return; + } + + if (!(key in fullParameters)) { + fullParameters[key] = urlParams[key]; + } + }); + + if (ComparisonsStoreInstance.isComparisonEnabled()) { + fullParameters = { + ...fullParameters, + comparePeriods: urlParams.comparePeriods, + compareDates: urlParams.compareDates, + compareSegments: urlParams.compareSegments, + }; + } + + if (!parameters || !('showtitle' in parameters)) { + fullParameters.showtitle = '1'; + } + + if (Matomo.shouldPropagateTokenAuth + && urlParams.token_auth + ) { + if (!Matomo.broadcast.isWidgetizeRequestWithoutSession()) { + fullParameters.force_api_session = '1'; + } + fullParameters.token_auth = urlParams.token_auth; + } + + fullParameters.random = Math.floor(Math.random() * 10000); + + return fullParameters; + }, + loadWidgetUrl(parameters: QueryParameters, thisChangeId: number) { + this.loading = true; + + this.abortHttpRequestIfNeeded(); + this.cleanupLastWidgetContent(); + + this.lastWidgetAbortController = new AbortController(); + + AjaxHelper.fetch(this.getWidgetUrl(parameters), { + format: 'html', + headers: { + 'X-Requested-With': 'XMLHttpRequest', + }, + abortController: this.lastWidgetAbortController, + }).then((response) => { + if (thisChangeId !== this.changeCounter || !response || typeof response !== 'string') { + // another widget was requested meanwhile, ignore this response + return; + } + + this.lastWidgetAbortController = null; + this.loading = false; + this.loadingFailed = false; + + const widgetContent = this.$refs.widgetContent as HTMLElement; + window.$(widgetContent).html(response); + const $content = window.$(widgetContent).children(); + + if (this.widgetName) { + // we need to respect the widget title, which overwrites a possibly set report title + let $title = $content.find('> .card-content .card-title'); + if (!$title.length) { + $title = $content.find('> h2'); + } + + if ($title.length) { + // required to use htmlEntities since it also escapes '{{' format items + $title.html(Matomo.helper.htmlEntities(this.widgetName)); + } + } + + const $rootScope: IRootScopeService = Matomo.helper.getAngularDependency('$rootScope'); + const scope = $rootScope.$new(); + this.currentScope = scope; + + // compile angularjs first since it will modify all dom nodes, breaking vue bindings + // if they are present + Matomo.helper.compileAngularComponents($content, { scope }); + Matomo.helper.compileVueEntryComponents($content); + + NotificationsStore.parseNotificationDivs(); + + setTimeout(() => { + Matomo.postEvent('widget:loaded', { + parameters, + element: $content, + }); + }); + }).catch((response) => { + if (thisChangeId !== this.changeCounter) { + // another widget was requested meanwhile, ignore this response + return; + } + + this.lastWidgetAbortController = null; + this.cleanupLastWidgetContent(); + + this.loading = false; + + if (response.xhrStatus === 'abort') { + return; + } + + this.loadingFailed = true; + }); + }, + }, +}); +</script> diff --git a/plugins/CoreHome/vue/src/createAngularJsAdapter.ts b/plugins/CoreHome/vue/src/createAngularJsAdapter.ts index b28ee95d33..e6b7b22d56 100644 --- a/plugins/CoreHome/vue/src/createAngularJsAdapter.ts +++ b/plugins/CoreHome/vue/src/createAngularJsAdapter.ts @@ -5,47 +5,65 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + import { - createApp, defineComponent, ref, - ComponentPublicInstance, } from 'vue'; -import translate from './translate'; +import { IDirectiveFactory, IDirectivePrePost, Injectable } from 'angular'; +import Matomo from './Matomo/Matomo'; +import createVueApp from './createVueApp'; -interface SingleScopeVarInfo { +interface SingleScopeVarInfo<InjectTypes extends unknown[]> { vue?: string; - default?: any; // eslint-disable-line - transform?: (v: unknown) => unknown; + default?: any; + transform?: ( + v: unknown, + vm: any, + scope: any, + element: ng.IAugmentedJQuery, + attrs: ng.IAttributes, + otherController?: ng.IController, + ...injected: InjectTypes + ) => unknown; angularJsBind?: string; + deepWatch?: boolean; } -type ScopeMapping = { [scopeVarName: string]: SingleScopeVarInfo }; +type ScopeMapping<InjectTypes extends unknown[]> = { + [scopeVarName: string]: SingleScopeVarInfo<InjectTypes>, +}; -type AdapterFunction<InjectTypes, R = void> = ( - scope: ng.IScope, +type AdapterFunction<InjectTypes extends unknown[], R = void> = ( + scope: any, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, - ...injected: InjectTypes, + ...injected: InjectTypes ) => R; -type EventAdapterFunction<InjectTypes, R = void> = ( - $event: any, // eslint-disable-line - scope: ng.IScope, +type EventAdapterFunction<InjectTypes extends unknown[], R = void> = ( + $event: any, + vm: any, + scope: any, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, - ...injected: InjectTypes, + otherController?: ng.IController, + ...injected: InjectTypes ) => R; -type PostCreateFunction<InjectTypes, R = void> = ( - vm: ComponentPublicInstance, - scope: ng.IScope, +type PostCreateFunction<InjectTypes extends unknown[], R = void> = ( + vm: any, + scope: any, element: ng.IAugmentedJQuery, attrs: ng.IAttributes, - ...injected: InjectTypes, + otherController?: ng.IController, + ...injected: InjectTypes ) => R; -type EventMapping<InjectTypes> = { [vueEventName: string]: EventAdapterFunction<InjectTypes> }; +type EventMapping<InjectTypes extends unknown[]> = { + [vueEventName: string]: EventAdapterFunction<InjectTypes>, +}; type ComponentType = ReturnType<typeof defineComponent>; @@ -61,9 +79,21 @@ function toAngularJsCamelCase(arg: string): string { .replace(/-([a-z])/g, (s, p) => p.toUpperCase()); } -export default function createAngularJsAdapter<InjectTypes = []>(options: { +export function removeAngularJsSpecificProperties<T>(newValue: T): T { + if (typeof newValue === 'object' + && newValue !== null + && Object.getPrototypeOf(newValue) === Object.prototype + ) { + return Object.fromEntries(Object.entries(newValue).filter((pair) => !/^\$/.test(pair[0]))) as T; + } + + return newValue; +} + +export default function createAngularJsAdapter<InjectTypes extends unknown[] = []>(options: { component: ComponentType, - scope?: ScopeMapping, + require?: string, + scope?: ScopeMapping<InjectTypes>, directiveName: string, events?: EventMapping<InjectTypes>, $inject?: string[], @@ -72,9 +102,12 @@ export default function createAngularJsAdapter<InjectTypes = []>(options: { postCreate?: PostCreateFunction<InjectTypes>, noScope?: boolean, restrict?: string, -}): ng.IDirectiveFactory { + priority?: number, + replace?: boolean, +}): Injectable<ng.IDirectiveFactory> { const { component, + require, scope = {}, events = {}, $inject, @@ -84,6 +117,8 @@ export default function createAngularJsAdapter<InjectTypes = []>(options: { postCreate, noScope, restrict = 'A', + priority, + replace, } = options; const currentTranscludeCounter = transcludeCounter; @@ -91,7 +126,8 @@ export default function createAngularJsAdapter<InjectTypes = []>(options: { transcludeCounter += 1; } - const angularJsScope = {}; + const vueToAngular: Record<string, string> = {}; + const angularJsScope: Record<string, string> = {}; Object.entries(scope).forEach(([scopeVarName, info]) => { if (!info.vue) { info.vue = scopeVarName; @@ -99,35 +135,41 @@ export default function createAngularJsAdapter<InjectTypes = []>(options: { if (info.angularJsBind) { angularJsScope[scopeVarName] = info.angularJsBind; } + vueToAngular[info.vue] = scopeVarName; }); - function angularJsAdapter(...injectedServices: InjectTypes) { + function angularJsAdapter(...injectedServices: InjectTypes): ng.IDirective { const adapter: ng.IDirective = { restrict, + require, + priority, scope: noScope ? undefined : angularJsScope, - compile: function angularJsAdapterCompile() { + compile: function angularJsAdapterCompile(): IDirectivePrePost { return { post: function angularJsAdapterLink( - ngScope: ng.IScope, + ngScope: any, ngElement: ng.IAugmentedJQuery, ngAttrs: ng.IAttributes, + ngController?: ng.IController, ) { - const clone = transclude ? ngElement.find(`[ng-transclude][counter=${currentTranscludeCounter}]`) : null; + const transcludeClone = transclude + ? ngElement.find(`[ng-transclude][counter=${currentTranscludeCounter}]`) + : null; // build the root vue template let rootVueTemplate = '<root-component'; Object.entries(events).forEach((info) => { const [eventName] = info; - rootVueTemplate += ` @${eventName}="onEventHandler('${eventName}', $event)"`; + rootVueTemplate += ` @${toKebabCase(eventName)}="onEventHandler('${eventName}', $event)"`; }); - Object.entries(scope).forEach(([key, info]) => { - if (info.angularJsBind === '&') { - const eventName = toKebabCase(key); - if (!events[eventName]) { // pass through scope & w/o a custom event handler - rootVueTemplate += ` @${eventName}="onEventHandler('${eventName}', $event)"`; + Object.entries(scope).forEach(([, info]) => { + if (info.angularJsBind === '&' || info.angularJsBind === '&?') { + const eventName = toKebabCase(info.vue!); + if (!events[info.vue!]) { // pass through scope & w/o a custom event handler + rootVueTemplate += ` @${eventName}="onEventHandler('${info.vue!}', $event)"`; } } else { - rootVueTemplate += ` :${info.vue}="${info.vue}"`; + rootVueTemplate += ` :${toKebabCase(info.vue!)}="${info.vue}"`; } }); rootVueTemplate += '>'; @@ -137,21 +179,29 @@ export default function createAngularJsAdapter<InjectTypes = []>(options: { rootVueTemplate += '</root-component>'; // build the vue app - const app = createApp({ + const app = createVueApp({ template: rootVueTemplate, data() { - const initialData = {}; + const initialData: Record<string, unknown> = {}; Object.entries(scope).forEach(([scopeVarName, info]) => { - let value = ngScope[scopeVarName]; + let value = removeAngularJsSpecificProperties(ngScope[scopeVarName]); if (typeof value === 'undefined' && typeof info.default !== 'undefined') { value = info.default instanceof Function ? info.default(ngScope, ngElement, ngAttrs, ...injectedServices) : info.default; } if (info.transform) { - value = info.transform(value); + value = info.transform( + value, + this, + ngScope, + ngElement, + ngAttrs, + ngController, + ...injectedServices, + ); } - initialData[info.vue] = value; + initialData[info.vue!] = value; }); return initialData; }, @@ -166,54 +216,93 @@ export default function createAngularJsAdapter<InjectTypes = []>(options: { return undefined; }, methods: { - onEventHandler(name: string, $event: any) { // eslint-disable-line - const scopePropertyName = toAngularJsCamelCase(name); + onEventHandler(name: string, $event: any) { + let scopePropertyName = toAngularJsCamelCase(name); + scopePropertyName = vueToAngular[scopePropertyName] || scopePropertyName; if (ngScope[scopePropertyName]) { ngScope[scopePropertyName]($event); } if (events[name]) { - events[name]($event, ngScope, ngElement, ngAttrs, ...injectedServices); + events[name]( + $event, + this, + ngScope, + ngElement, + ngAttrs, + ngController, + ...injectedServices, + ); } }, }, }); - app.config.globalProperties.$sanitize = window.vueSanitize; - app.config.globalProperties.translate = translate; app.component('root-component', component); // mount the app const mountPoint = mountPointFactory ? mountPointFactory(ngScope, ngElement, ngAttrs, ...injectedServices) : ngElement[0]; - const vm = app.mount(mountPoint); + const vm: any = app.mount(mountPoint); // setup watches to bind between angularjs + vue Object.entries(scope).forEach(([scopeVarName, info]) => { - if (!info.angularJsBind || info.angularJsBind === '&') { + if (!info.angularJsBind || info.angularJsBind === '&' || info.angularJsBind === '&?') { return; } - ngScope.$watch(scopeVarName, (newValue: any) => { // eslint-disable-line - let newValueFinal = newValue; + ngScope.$watch(scopeVarName, (newValue: any, oldValue: any) => { + if (newValue === oldValue + && JSON.stringify(vm[info.vue!]) === JSON.stringify(newValue) + ) { + return; // initial + } + + let newValueFinal = removeAngularJsSpecificProperties(newValue); if (typeof info.default !== 'undefined' && typeof newValue === 'undefined') { newValueFinal = info.default instanceof Function ? info.default(ngScope, ngElement, ngAttrs, ...injectedServices) : info.default; } if (info.transform) { - newValueFinal = info.transform(newValueFinal); + newValueFinal = info.transform( + newValueFinal, + vm, + ngScope, + ngElement, + ngAttrs, + ngController, + ...injectedServices, + ); } - vm[scopeVarName] = newValueFinal; - }); + + vm[info.vue!] = newValueFinal; + }, info.deepWatch); }); - if (transclude) { - $(vm.transcludeTarget).append(clone); + if (transclude && transcludeClone) { + $(vm.transcludeTarget).append(transcludeClone); } if (postCreate) { - postCreate(vm, ngScope, ngElement, ngAttrs, ...injectedServices); + postCreate(vm, ngScope, ngElement, ngAttrs, ngController, ...injectedServices); + } + + // specifying replace: true on the directive does nothing w/ vue inside, so + // handle it here. + if (replace) { + // transfer attributes from angularjs element that are not in scope to + // mount point element + Array.from(ngElement[0].attributes).forEach((attr) => { + if (scope[attr.nodeName]) { + return; + } + if (mountPoint.firstElementChild) { + mountPoint.firstElementChild.setAttribute(attr.nodeName, attr.nodeValue!); + } + }); + + ngElement.replaceWith(window.$(mountPoint).children()); } ngElement.on('$destroy', () => { @@ -234,7 +323,49 @@ export default function createAngularJsAdapter<InjectTypes = []>(options: { angularJsAdapter.$inject = $inject || []; - angular.module('piwikApp').directive(directiveName, angularJsAdapter); + window.angular.module('piwikApp').directive( + directiveName, + angularJsAdapter as unknown as Injectable<IDirectiveFactory>, + ); + + return angularJsAdapter as unknown as Injectable<IDirectiveFactory>; +} + +export function transformAngularJsBoolAttr(v: unknown): boolean|undefined { + if (typeof v === 'undefined') { + return undefined; + } + + if (v === 'true') { + return true; + } + + return !!v && v as number > 0 && v !== '0'; +} + +export function transformAngularJsIntAttr(v: unknown): number|undefined|null { + if (typeof v === 'undefined') { + return undefined; + } + + if (v === null) { + return null; + } + + return parseInt(v as string, 10); +} + +// utility function for service adapters +export function clone<T>(p: T): T { + if (typeof p === 'undefined') { + return p; + } + + return JSON.parse(JSON.stringify(p)) as T; +} - return angularJsAdapter; +export function cloneThenApply<T>(p: T): T { + const result = clone(p); + Matomo.helper.getAngularDependency('$rootScope').$applyAsync(); + return result; } diff --git a/plugins/CoreHome/vue/src/createVueApp.ts b/plugins/CoreHome/vue/src/createVueApp.ts new file mode 100644 index 0000000000..65caca5251 --- /dev/null +++ b/plugins/CoreHome/vue/src/createVueApp.ts @@ -0,0 +1,19 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { createApp } from 'vue'; +import { translate, translateOrDefault } from './translate'; + +export default function createVueApp( + ...args: Parameters<typeof createApp> +): ReturnType<typeof createApp> { + const app = createApp(...args); + app.config.globalProperties.$sanitize = window.vueSanitize; + app.config.globalProperties.translate = translate; + app.config.globalProperties.translateOrDefault = translateOrDefault; + return app; +} diff --git a/plugins/CoreHome/vue/src/debounce.ts b/plugins/CoreHome/vue/src/debounce.ts new file mode 100644 index 0000000000..7a5e2f5af9 --- /dev/null +++ b/plugins/CoreHome/vue/src/debounce.ts @@ -0,0 +1,18 @@ +const DEFAULT_DEBOUNCE_DELAY = 300; + +export default function debounce<This, Args extends unknown[]>( + fn: (this: This, ...args: Args) => void, + delayInMs = DEFAULT_DEBOUNCE_DELAY, +): (this: This, ...args: Args) => void { + let timeout: ReturnType<typeof setTimeout>; + + return function wrapper(this: This, ...args: Args): void { + if (timeout) { + clearTimeout(timeout); + } + + timeout = setTimeout(() => { + fn.call(this, ...args); + }, delayInMs); + }; +} diff --git a/plugins/CoreHome/vue/src/directiveUtilities.ts b/plugins/CoreHome/vue/src/directiveUtilities.ts new file mode 100644 index 0000000000..4ca073fca1 --- /dev/null +++ b/plugins/CoreHome/vue/src/directiveUtilities.ts @@ -0,0 +1,18 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import { DirectiveBinding } from 'vue'; + +function getRef<T>(expander: string | HTMLElement, binding: DirectiveBinding<T>): HTMLElement|null { + return expander instanceof HTMLElement + ? expander + : binding.instance?.$refs[expander] as HTMLElement; +} + +export default { + getRef, +}; diff --git a/plugins/CoreHome/vue/src/getFormattedEvolution.ts b/plugins/CoreHome/vue/src/getFormattedEvolution.ts new file mode 100644 index 0000000000..84b8e57dec --- /dev/null +++ b/plugins/CoreHome/vue/src/getFormattedEvolution.ts @@ -0,0 +1,37 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +import Matomo from './Matomo/Matomo'; + +function calculateEvolution(currentValue: string|number, pastValue: string|number) { + const pastValueParsed = parseInt(pastValue as string, 10); + const currentValueParsed = parseInt(currentValue as string, 10) - pastValueParsed; + + let evolution: number; + + if (currentValueParsed === 0 || Number.isNaN(currentValueParsed)) { + evolution = 0; + } else if (pastValueParsed === 0 || Number.isNaN(pastValueParsed)) { + evolution = 100; + } else { + evolution = (currentValueParsed / pastValueParsed) * 100; + } + + return evolution; +} + +function formatEvolution(evolution: number) { + return `${evolution > 0 ? Matomo.numbers.symbolPlus : ''}${Math.round(evolution)}}%`; +} + +export default function getFormattedEvolution( + currentValue: string|number, + pastValue: string|number, +): string { + const evolution = calculateEvolution(currentValue, pastValue); + return formatEvolution(evolution); +} diff --git a/plugins/CoreHome/vue/src/index.ts b/plugins/CoreHome/vue/src/index.ts index baaada6b9a..27fad8fc99 100644 --- a/plugins/CoreHome/vue/src/index.ts +++ b/plugins/CoreHome/vue/src/index.ts @@ -15,41 +15,114 @@ import './Periods/Year'; import './Periods/Range'; import './Periods/Periods.adapter'; import './AjaxHelper/AjaxHelper.adapter'; +import './PopoverHandler/PopoverHandler'; +import './Alert/Alert.adapter'; import './DropdownMenu/DropdownMenu.adapter'; import './FocusAnywhereButHere/FocusAnywhereButHere.adapter'; import './FocusIf/FocusIf.adapter'; import './ExpandOnClick/ExpandOnClick.adapter'; import './ExpandOnHover/ExpandOnHover.adapter'; +import './ShowSensitiveData/ShowSensitiveData.adapter'; +import './DropdownButton/DropdownButton.adapter'; +import './SelectOnFocus/SelectOnFocus.adapter'; +import './SideNav/SideNav.adapter'; import './MatomoDialog/MatomoDialog.adapter'; import './EnrichedHeadline/EnrichedHeadline.adapter'; import './ContentBlock/ContentBlock.adapter'; import './Comparisons/Comparisons.adapter'; -import './Menudropdown/Menudropdown.adapter'; +import './MenuItemsDropdown/MenuItemsDropdown.adapter'; import './DatePicker/DatePicker.adapter'; import './DateRangePicker/DateRangePicker.adapter'; import './PeriodDatePicker/PeriodDatePicker.adapter'; +import './SiteSelector/SiteSelector.adapter'; +import './SiteSelector/SitesStore.adapter'; +import './QuickAccess/QuickAccess.adapter'; +import './FieldArray/FieldArray.adapter'; +import './MultiPairField/MultiPairField.adapter'; +import './PeriodSelector/PeriodSelector.adapter'; +import './ReportingMenu/ReportingMenu.adapter'; +import './ReportingMenu/ReportingMenu.store.adapter'; +import './ReportingPages/ReportingPages.store.adapter'; +import './ReportMetadata/ReportMetadata.store.adapter'; +import './WidgetLoader/WidgetLoader.adapter'; +import './WidgetContainer/WidgetContainer.adapter'; +import './WidgetByDimensionContainer/WidgetByDimensionContainer.adapter'; +import './Widget/Widget.adapter'; +import './ReportingPage/ReportingPage.adapter'; +import './ReportExport/ReportExport.adapter'; +import './Sparkline/Sparkline.adapter'; +import './Progressbar/Progressbar.adapter'; +import './ContentIntro/ContentIntro.adapter'; +import './ContentTable/ContentTable.adapter'; +import './AjaxForm/AjaxForm.adapter'; -export { default as createAngularJsAdapter } from './createAngularJsAdapter'; +export { default as createVueApp } from './createVueApp'; +export { default as useExternalPluginComponent } from './useExternalPluginComponent'; +export { default as DirectiveUtilities } from './directiveUtilities'; +export { default as debounce } from './debounce'; +export { default as getFormattedEvolution } from './getFormattedEvolution'; +export { + default as createAngularJsAdapter, + transformAngularJsBoolAttr, + transformAngularJsIntAttr, + removeAngularJsSpecificProperties, + clone, + cloneThenApply, +} from './createAngularJsAdapter'; export { default as activityIndicatorAdapter } from './ActivityIndicator/ActivityIndicator.adapter'; export { default as ActivityIndicator } from './ActivityIndicator/ActivityIndicator.vue'; -export { default as translate } from './translate'; -export { default as alertAdapter } from './Alert/Alert.adapter'; -export { default as AjaxHelper } from './AjaxHelper/AjaxHelper'; +export * from './translate'; +export { default as Alert } from './Alert/Alert.vue'; +export { default as AjaxHelper, AjaxOptions } from './AjaxHelper/AjaxHelper'; export { setCookie, getCookie, deleteCookie } from './CookieHelper/CookieHelper'; export { default as MatomoUrl } from './MatomoUrl/MatomoUrl'; export { default as Matomo } from './Matomo/Matomo'; export * from './Periods'; -export { default as Dropdown } from './DropdownMenu/DropdownMenu'; +export { default as DropdownMenu } from './DropdownMenu/DropdownMenu'; export { default as FocusAnywhereButHere } from './FocusAnywhereButHere/FocusAnywhereButHere'; export { default as FocusIf } from './FocusIf/FocusIf'; +export { default as Tooltips } from './Tooltips/Tooltips'; export { default as MatomoDialog } from './MatomoDialog/MatomoDialog.vue'; export { default as ExpandOnClick } from './ExpandOnClick/ExpandOnClick'; export { default as ExpandOnHover } from './ExpandOnHover/ExpandOnHover'; +export { default as ShowSensitiveData } from './ShowSensitiveData/ShowSensitiveData'; +export { default as DropdownButton } from './DropdownButton/DropdownButton'; +export { default as SelectOnFocus } from './SelectOnFocus/SelectOnFocus'; +export { default as SideNav } from './SideNav/SideNav'; export { default as EnrichedHeadline } from './EnrichedHeadline/EnrichedHeadline.vue'; export { default as ContentBlock } from './ContentBlock/ContentBlock.vue'; export { default as Comparisons } from './Comparisons/Comparisons.vue'; -export { default as Menudropdown } from './Menudropdown/Menudropdown.vue'; +export { default as MenuItemsDropdown } from './MenuItemsDropdown/MenuItemsDropdown.vue'; export { default as DatePicker } from './DatePicker/DatePicker.vue'; export { default as DateRangePicker } from './DateRangePicker/DateRangePicker.vue'; export { default as PeriodDatePicker } from './PeriodDatePicker/PeriodDatePicker.vue'; export * from './Notification'; +export { default as SitesStore } from './SiteSelector/SitesStore'; +export { default as Site } from './SiteSelector/Site'; +export { default as SiteSelector } from './SiteSelector/SiteSelector.vue'; +export { default as SiteRef } from './SiteSelector/SiteRef'; +export { default as QuickAccess } from './QuickAccess/QuickAccess.vue'; +export { default as FieldArray } from './FieldArray/FieldArray.vue'; +export { default as MultiPairField } from './MultiPairField/MultiPairField.vue'; +export { default as PeriodSelector } from './PeriodSelector/PeriodSelector.vue'; +export { default as ReportingMenu } from './ReportingMenu/ReportingMenu.vue'; +export { default as ReportingMenuStore } from './ReportingMenu/ReportingMenu.store'; +export { default as ReportingPagesStore } from './ReportingPages/ReportingPages.store'; +export { default as ReportMetadataStore } from './ReportMetadata/ReportMetadata.store'; +export { default as WidgetsStore } from './Widget/Widgets.store'; +export { default as WidgetLoader } from './WidgetLoader/WidgetLoader.vue'; +export { default as WidgetContainer } from './WidgetContainer/WidgetContainer.vue'; +export { default as WidgetByDimensionContainer } from './WidgetByDimensionContainer/WidgetByDimensionContainer.vue'; +export { default as Widget } from './Widget/Widget.vue'; +export { + Widget as WidgetType, + WidgetContainer as WidgetContainerType, + GroupedWidgets as GroupedWidgetsType, +} from './Widget/types'; +export { default as ReportingPage } from './ReportingPage/ReportingPage.vue'; +export { default as ReportExport } from './ReportExport/ReportExport'; +export { default as Sparkline } from './Sparkline/Sparkline.vue'; +export { default as Progressbar } from './Progressbar/Progressbar.vue'; +export { default as ContentIntro } from './ContentIntro/ContentIntro'; +export { default as ContentTable } from './ContentTable/ContentTable'; +export { default as AjaxForm } from './AjaxForm/AjaxForm.vue'; diff --git a/plugins/CoreHome/vue/src/translate.ts b/plugins/CoreHome/vue/src/translate.ts index 317b5a8751..e6004196b4 100644 --- a/plugins/CoreHome/vue/src/translate.ts +++ b/plugins/CoreHome/vue/src/translate.ts @@ -5,14 +5,29 @@ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later */ -export default function translate( +export function translate( translationStringId: string, - ...values: string[]|string[][] + ...values: (string|string[]|number|number[]|boolean|boolean[])[] ): string { - let pkArgs = values as string[]; + if (!translationStringId) { + return ''; + } + + let pkArgs = values as (string|number|boolean)[]; // handle variadic args AND single array of values (to match _pk_translate signature) - if (values.length === 1 && values[0] && values[0] instanceof Array) { - [pkArgs] = values as string[][]; + if (values.length === 1 && values[0] && Array.isArray(values[0])) { + [pkArgs] = values as (string|number|boolean)[][]; } return window._pk_translate(translationStringId, pkArgs); // eslint-disable-line } + +export function translateOrDefault( + translationStringIdOrText?: string, + ...values: (string|string[]|number|number[]|boolean|boolean[])[] +): string { + if (!translationStringIdOrText || !window.piwik_translations[translationStringIdOrText]) { + return translationStringIdOrText!; + } + + return translate(translationStringIdOrText!, ...values); +} diff --git a/plugins/CoreHome/vue/src/useExternalPluginComponent.ts b/plugins/CoreHome/vue/src/useExternalPluginComponent.ts new file mode 100644 index 0000000000..0829c348d3 --- /dev/null +++ b/plugins/CoreHome/vue/src/useExternalPluginComponent.ts @@ -0,0 +1,27 @@ +/*! + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/ban-ts-comment */ + +import { defineAsyncComponent } from 'vue'; + +export default function useExternalPluginComponent( + plugin: string, + component: string, +): typeof defineAsyncComponent { + return defineAsyncComponent(() => (new Promise((resolve) => { + window.$(document).ready(() => { + if ((window as any)[plugin]) { + resolve((window as any)[plugin][component]); + } else { + // @ts-ignore + resolve(null); // plugin not loaded + } + }); + }))); +} |