diff --git a/CHANGELOG.md b/CHANGELOG.md
old mode 100644
new mode 100755
index 720156637..0fc9b07ae
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
== Changelog ==
+= 4.10.0 =
+* Update Matomo core to 4.10.0
+* Fix a white screen issue in multisite mode
+* Add wpstatistics import feature
+
= 4.6.0 =
* Update Matomo core to 4.6.0
* WooCommerce: Make excluded order status configurable using a constant
diff --git a/app/LEGALNOTICE b/app/LEGALNOTICE
index ae764aad3..fbbd91319 100644
--- a/app/LEGALNOTICE
+++ b/app/LEGALNOTICE
@@ -283,7 +283,7 @@ THIRD-PARTY CONTENT
Link: https://design.google.com/icons/
License: Apache License Version 2.0
- Name: IcoMoon - Free icons ("icon-funnel", "icon-lab", "icon-archive", "icon-rocket", "icon-embed", "icon-page-performance") in plugins/Morpheus/fonts
+ Name: IcoMoon - Free icons ("icon-funnel", "icon-lab", "icon-archive", "icon-rocket", "icon-embed", "icon-page-performance", "icon-github") in plugins/Morpheus/fonts
Link: https://icomoon.io/#icons-icomoon
License: GPL
diff --git a/app/README.md b/app/README.md
index 726dc87d4..ca1ce8baa 100644
--- a/app/README.md
+++ b/app/README.md
@@ -6,7 +6,7 @@
## Code Status
-[![Build Status](https://travis-ci.com/matomo-org/matomo.svg?branch=4.x-dev)](https://travis-ci.com/matomo-org/matomo/branches)
+[![Build Status](https://travis-ci.com/matomo-org/matomo.svg?branch=4.x-dev)](https://app.travis-ci.com/matomo-org/matomo/branches)
[![Percentage of issues still open](http://isitmaintained.com/badge/open/matomo-org/matomo.svg)](http://isitmaintained.com/project/matomo-org/matomo "Percentage of issues still open")
## Description
diff --git a/app/bootstrap.php b/app/bootstrap.php
index 4d5fb61b1..41b493ff0 100644
--- a/app/bootstrap.php
+++ b/app/bootstrap.php
@@ -156,7 +156,7 @@ function matomo_log_message_no_display($message)
if ( !is_plugin_active('matomo/matomo.php')
&& (!defined( 'MATOMO_PHPUNIT_TEST' ) || !MATOMO_PHPUNIT_TEST) ) { // during tests the plugin may temporarily not be active
- exit;
+ exit;
}
if ( $GLOBALS['MATOMO_LOADED_DIRECTLY'] ) {
diff --git a/app/config/global.ini.php b/app/config/global.ini.php
old mode 100755
new mode 100644
index 8443a5d2a..4f79340bb
--- a/app/config/global.ini.php
+++ b/app/config/global.ini.php
@@ -385,6 +385,11 @@
; This feature will not work with the MYSQLI extension.
archiving_query_max_execution_time = 7200
+
+; Allows you to disable archiving segments for selected plugins. For more details please see https://matomo.org/faq/how-to-disable-archiving-the-segment-reports-for-specific-plugins
+; Here you can specify the comma separated list eg: "plugin1,plugin2"
+disable_archiving_segment_for_plugins = ""
+
; By default Matomo runs OPTIMIZE TABLE SQL queries to free spaces after deleting some data.
; If your Matomo tracks millions of pages, the OPTIMIZE TABLE queries might run for hours (seen in "SHOW FULL PROCESSLIST \g")
; so you can disable these special queries here:
@@ -634,6 +639,7 @@
; By enabling this flag we will for example not allow the installation of a plugin via the UI as a plugin would be only
; installed on one server or a config one change would be only made on one server instead of all servers.
; This flag doesn't need to be enabled when the config file is on a shared filesystem such as NFS or EFS.
+; When enabled, Matomo will return the response code 200 instead of 503 in maintenance mode.
multi_server_environment = 0
; List of proxy headers for client IP addresses
@@ -676,7 +682,8 @@
enable_trusted_host_check = 1
; List of trusted hosts (eg domain or subdomain names) when generating absolute URLs.
-;
+; This only needs to be set for any hostnames that the Matomo UI will be accessed from. It is not necessary to set this
+; for other additional hostnames (For example tracking, API, etc.)
; Examples:
;trusted_hosts[] = example.com
;trusted_hosts[] = stats.example.com
@@ -922,6 +929,11 @@
; By default, Matomo will remove the most common parameters which are known to change often (eg. session ID parameters)
url_query_parameter_to_exclude_from_url = "gclid,fbclid,fb_xd_fragment,fb_comment_id,phpsessid,jsessionid,sessionid,aspsessionid,doing_wp_cron,sid,pk_vid"
+; If set to 1, Matomo will use the default provider if no other provider is configured.
+; In addition the default provider will be used as a fallback when the configure provider does not return any results.
+; If set to 0, the default provider will be unavailable. Instead the "disabled" provider will be used as default and fallback instead.
+enable_default_location_provider = 1
+
; if set to 1, Matomo attempts a "best guess" at the visitor's country of
; origin when the preferred language tag omits region information.
; The mapping is defined in core/DataFiles/LanguageToCountry.php,
@@ -1229,4 +1241,4 @@
SDK_batch_size = 10
SDK_interval_value = 30
-; NOTE: do not directly edit this file! See notice at the top
\ No newline at end of file
+; NOTE: do not directly edit this file! See notice at the top
diff --git a/app/config/global.php b/app/config/global.php
index 1e43a2e47..f6fbe51e0 100644
--- a/app/config/global.php
+++ b/app/config/global.php
@@ -4,7 +4,7 @@
use Matomo\Cache\Eager;
use Piwik\SettingsServer;
-return array(
+return [
'path.root' => PIWIK_DOCUMENT_ROOT,
@@ -35,6 +35,8 @@
'view.clearcompiledtemplates.enable' => true,
+ 'twig.cache' => DI\string('{path.tmp.templates}'),
+
'Matomo\Cache\Eager' => function (ContainerInterface $c) {
$backend = $c->get('Matomo\Cache\Backend');
$cacheId = $c->get('cache.eager.cache_id');
@@ -58,7 +60,7 @@
// If Piwik is not installed yet, it's possible the tmp/ folder is not writable
// we prevent failing with an unclear message eg. coming from doctrine-cache
// by forcing to use a cache backend which always works ie. array
- if(!\Piwik\SettingsPiwik::isMatomoInstalled()) {
+ if (!\Piwik\SettingsPiwik::isMatomoInstalled()) {
$backend = 'array';
} else {
try {
@@ -71,10 +73,10 @@
return \Piwik\Cache::buildBackend($backend);
},
'cache.eager.cache_id' => function () {
- return 'eagercache-' . str_replace(array('.', '-'), '', \Piwik\Version::VERSION) . '-';
+ return 'eagercache-' . str_replace(['.', '-'], '', \Piwik\Version::VERSION) . '-';
},
- 'entities.idNames' => DI\add(array('idGoal', 'idDimension')),
+ 'entities.idNames' => DI\add(['idGoal', 'idDimension']),
'Psr\Log\LoggerInterface' => DI\create('Psr\Log\NullLogger'),
@@ -83,19 +85,20 @@
'DeviceDetector\Cache\Cache' => DI\autowire('Piwik\DeviceDetector\DeviceDetectorCache')->constructor(86400),
- 'observers.global' => array(),
+ 'observers.global' => [],
/**
- * By setting this option to false, the check that the DB schema version matches the version of the source code will be no longer performed.
- * Thus it allows you to execute for example a newer version of Matomo with an older Matomo database version. Please note
- * disabling this setting is not recommended because often an older DB version is not compatible with newer source code.
- * If you disable this setting, make sure to execute the updates after updating the source code. The setting can be useful if
- * you want to update Matomo without any outage when you know the current source code update will still run fine for a short time
- * while in the background the database updates are running.
+ * By setting this option to false, the check that the DB schema version matches the version of the source code will
+ * be no longer performed. Thus it allows you to execute for example a newer version of Matomo with an older Matomo
+ * database version. Please note disabling this setting is not recommended because often an older DB version is not
+ * compatible with newer source code.
+ * If you disable this setting, make sure to execute the updates after updating the source code. The setting can be
+ * useful if you want to update Matomo without any outage when you know the current source code update will still
+ * run fine for a short time while in the background the database updates are running.
*/
'EnableDbVersionCheck' => true,
- 'fileintegrity.ignore' => DI\add(array(
+ 'fileintegrity.ignore' => DI\add([
'*.htaccess',
'*web.config',
'bootstrap.php',
@@ -146,7 +149,7 @@
'*.gitattributes',
'*.bower.json',
'*.travis.yml',
- )),
+ ]),
'Piwik\EventDispatcher' => DI\autowire()->constructorParameter('observers', DI\get('observers.global')),
@@ -155,7 +158,7 @@
$config = $c->get('Piwik\Config');
$general = $config->General;
- $ips = array();
+ $ips = [];
if (!empty($general['login_allowlist_ip']) && is_array($general['login_allowlist_ip'])) {
$ips = $general['login_allowlist_ip'];
} elseif (!empty($general['login_whitelist_ip']) && is_array($general['login_whitelist_ip'])) {
@@ -163,7 +166,7 @@
$ips = $general['login_whitelist_ip'];
}
- $ipsResolved = array();
+ $ipsResolved = [];
foreach ($ips as $ip) {
$ip = trim($ip);
@@ -186,8 +189,10 @@
if (function_exists('dns_get_record')) {
$entry = @dns_get_record($ip, DNS_AAAA);
- if (!empty($entry['0']['ipv6'])
- && filter_var($entry['0']['ipv6'], FILTER_VALIDATE_IP)) {
+ if (
+ !empty($entry['0']['ipv6'])
+ && filter_var($entry['0']['ipv6'], FILTER_VALIDATE_IP)
+ ) {
$resolvedIps[] = $entry['0']['ipv6'];
}
}
@@ -216,15 +221,19 @@
->constructorParameter('lookbackNSecondsCustom', DI\get('ini.Tracker.window_look_back_for_visitor')),
'Piwik\Tracker\Settings' => DI\autowire()
- ->constructorParameter('isSameFingerprintsAcrossWebsites', DI\get('ini.Tracker.enable_fingerprinting_across_websites')),
+ ->constructorParameter(
+ 'isSameFingerprintsAcrossWebsites',
+ DI\get('ini.Tracker.enable_fingerprinting_across_websites')
+ ),
'archiving.performance.logger' => null,
- \Piwik\CronArchive\Performance\Logger::class => DI\autowire()->constructorParameter('logger', DI\get('archiving.performance.logger')),
+ \Piwik\CronArchive\Performance\Logger::class => DI\autowire()
+ ->constructorParameter('logger', DI\get('archiving.performance.logger')),
\Piwik\Concurrency\LockBackend::class => \DI\get(\Piwik\Concurrency\LockBackend\MySqlLockBackend::class),
- \Piwik\Segment\SegmentsList::class => function(){
+ \Piwik\Segment\SegmentsList::class => function () {
return \Piwik\Segment\SegmentsList::get();
}
-);
+];
diff --git a/app/core/Access.php b/app/core/Access.php
index b95e7f304..3a5b30626 100644
--- a/app/core/Access.php
+++ b/app/core/Access.php
@@ -616,7 +616,7 @@ public function checkUserHasCapability($idSites, $capability)
foreach ($idSites as $idsite) {
if (!in_array($idsite, $idSitesAccessible)) {
- $this->throwNoAccessException(Piwik::translate('ExceptionCapabilityAccessWebsite', array("'" . $capability ."'", $idsite)));
+ $this->throwNoAccessException(Piwik::translate('General_ExceptionCapabilityAccessWebsite', array("'" . $capability ."'", $idsite)));
}
}
diff --git a/app/core/Access/RolesProvider.php b/app/core/Access/RolesProvider.php
index 4295e9b71..50df3fa1e 100644
--- a/app/core/Access/RolesProvider.php
+++ b/app/core/Access/RolesProvider.php
@@ -59,7 +59,7 @@ public function checkValidRole(string $roleId): void
{
if (!$this->isValidRole($roleId)) {
$roles = $this->getAllRoleIds();
- throw new Exception(Piwik::translate("UsersManager_ExceptionAccessValues", implode(", ", $roles)));
+ throw new Exception(Piwik::translate("UsersManager_ExceptionAccessValues", [implode(", ", $roles), $roleId]));
}
}
diff --git a/app/core/Archive.php b/app/core/Archive.php
index 007ca09e5..09e6c3bb3 100644
--- a/app/core/Archive.php
+++ b/app/core/Archive.php
@@ -1,4 +1,5 @@
params = $params;
$this->forceIndexedBySite = $forceIndexedBySite;
$this->forceIndexedByDate = $forceIndexedByDate;
@@ -210,8 +214,13 @@ public function __construct(Parameters $params, $forceIndexedBySite = false,
*/
public static function build($idSites, $period, $strDate, $segment = false, $_restrictSitesToLogin = false)
{
- return StaticContainer::get(ArchiveQueryFactory::class)->build($idSites, $period, $strDate, $segment,
- $_restrictSitesToLogin);
+ return StaticContainer::get(ArchiveQueryFactory::class)->build(
+ $idSites,
+ $period,
+ $strDate,
+ $segment,
+ $_restrictSitesToLogin
+ );
}
/**
@@ -236,11 +245,20 @@ public static function build($idSites, $period, $strDate, $segment = false, $_re
*
* @return ArchiveQuery
*/
- public static function factory(Segment $segment, array $periods, array $idSites, $idSiteIsAll = false,
- $isMultipleDate = false)
- {
- return StaticContainer::get(ArchiveQueryFactory::class)->factory($segment, $periods, $idSites, $idSiteIsAll,
- $isMultipleDate);
+ public static function factory(
+ Segment $segment,
+ array $periods,
+ array $idSites,
+ $idSiteIsAll = false,
+ $isMultipleDate = false
+ ) {
+ return StaticContainer::get(ArchiveQueryFactory::class)->factory(
+ $segment,
+ $periods,
+ $idSites,
+ $idSiteIsAll,
+ $isMultipleDate
+ );
}
public static function shouldSkipArchiveIfSkippingSegmentArchiveForToday(Site $site, Period $period, Segment $segment)
@@ -277,7 +295,8 @@ public function getNumeric($names)
$result = $data->getIndexedArray($resultIndices);
// if only one metric is returned, just return it as a numeric value
- if (empty($resultIndices)
+ if (
+ empty($resultIndices)
&& count($result) <= 1
&& (!is_array($names) || count($names) === 1)
) {
@@ -410,7 +429,7 @@ public function getDataTableExpanded($name, $idSubtable = null, $depth = null, $
*/
private function getRequestedPlugins($archiveNames)
{
- $result = array();
+ $result = [];
foreach ($archiveNames as $name) {
$result[] = self::getPluginForReport($name);
@@ -441,7 +460,7 @@ public function getParams()
* @param string $segment @see {@link build()}
* @param bool $expanded If true, loads all subtables. See {@link getDataTableExpanded()}
* @param bool $flat If true, loads all subtables and disabled all recursive filters.
- * @param int|null $idSubtable See {@link getDataTableExpanded()}
+ * @param int|null|string $idSubtable See {@link getDataTableExpanded()}
* @param int|null $depth See {@link getDataTableExpanded()}
* @return DataTable|DataTable\Map
*/
@@ -449,14 +468,19 @@ public static function createDataTableFromArchive($recordName, $idSite, $period,
{
Piwik::checkUserHasViewAccess($idSite);
+ if ($idSubtable === false || $idSubtable === '') {
+ $idSubtable = null;
+ }
+
+ if (!empty($idSubtable) && (strtolower($idSubtable) !== self::ID_SUBTABLE_LOAD_ALL_SUBTABLES && !is_numeric($idSubtable))) {
+ throw new \Exception("idSubtable needs to be a number or '" . self::ID_SUBTABLE_LOAD_ALL_SUBTABLES . "', '$idSubtable' given.");
+ }
+
if ($flat && !$idSubtable) {
$expanded = true;
}
$archive = Archive::build($idSite, $period, $date, $segment, $_restrictSitesToLogin = false);
- if ($idSubtable === false) {
- $idSubtable = null;
- }
if ($expanded) {
$dataTable = $archive->getDataTableExpanded($recordName, $idSubtable, $depth);
@@ -489,19 +513,20 @@ public static function createDataTableFromArchive($recordName, $idSite, $period,
protected function get($archiveNames, $archiveDataType, $idSubtable = null)
{
if (!is_array($archiveNames)) {
- $archiveNames = array($archiveNames);
+ $archiveNames = [$archiveNames];
}
$archiveNames = array_filter($archiveNames);
// apply idSubtable
- if ($idSubtable !== null
+ if (
+ $idSubtable !== null
&& $idSubtable !== self::ID_SUBTABLE_LOAD_ALL_SUBTABLES
) {
// this is also done in ArchiveSelector. It should be actually only done in ArchiveSelector but DataCollection
// does require to have the subtableId appended. Needs to be changed in refactoring to have it only in one
// place.
- $dataNames = array();
+ $dataNames = [];
foreach ($archiveNames as $name) {
$dataNames[] = ArchiveSelector::appendIdsubtable($name, $idSubtable);
}
@@ -510,9 +535,15 @@ protected function get($archiveNames, $archiveDataType, $idSubtable = null)
}
$result = new Archive\DataCollection(
- $dataNames, $archiveDataType, $this->params->getIdSites(), $this->params->getPeriods(), $this->params->getSegment(), $defaultRow = null);
+ $dataNames,
+ $archiveDataType,
+ $this->params->getIdSites(),
+ $this->params->getPeriods(),
+ $this->params->getSegment(),
+ $defaultRow = null
+ );
if (empty($dataNames)) {
- return $result; // NOTE: note posting Archive.noArchivedData here, because there might be archive data, someone just requested nothing
+ return $result; // NOTE: not posting Archive.noArchivedData here, because there might be archive data, someone just requested nothing
}
$archiveIds = $this->getArchiveIds($archiveNames);
@@ -560,8 +591,8 @@ private function getArchiveIds($archiveNames)
// figure out which archives haven't been processed (if an archive has been processed,
// then we have the archive IDs in $this->idarchives)
- $doneFlags = array();
- $archiveGroups = array();
+ $doneFlags = [];
+ $archiveGroups = [];
foreach (array_merge($plugins, ['all']) as $plugin) {
$doneFlag = $this->getDoneStringForPlugin($plugin, $this->params->getIdSites());
@@ -586,7 +617,8 @@ private function getArchiveIds($archiveNames)
// cache id archives for plugins we haven't processed yet
if (!empty($archiveGroups)) {
- if (Rules::isArchivingEnabledFor($this->params->getIdSites(), $this->params->getSegment(), $this->getPeriodLabel())
+ if (
+ Rules::isArchivingEnabledFor($this->params->getIdSites(), $this->params->getSegment(), $this->getPeriodLabel())
&& !$this->forceFetchingWithoutLaunchingArchiving
) {
$this->cacheArchiveIdsAfterLaunching($archiveGroups, $plugins);
@@ -610,16 +642,14 @@ private function getArchiveIds($archiveNames)
*/
private function cacheArchiveIdsAfterLaunching($archiveGroups, $plugins)
{
- $today = Date::today();
-
foreach ($this->params->getPeriods() as $period) {
- $twoDaysBeforePeriod = $period->getDateStart()->subDay(2);
$twoDaysAfterPeriod = $period->getDateEnd()->addDay(2);
foreach ($this->params->getIdSites() as $idSite) {
$site = new Site($idSite);
- if (Common::getRequestVar('skipArchiveSegmentToday', 0, 'int')
+ if (
+ Common::getRequestVar('skipArchiveSegmentToday', 0, 'int')
&& self::shouldSkipArchiveIfSkippingSegmentArchiveForToday($site, $period, $this->params->getSegment())
) {
Log::debug("Skipping archive %s for %s as segment today is disabled", $period->getLabel(), $period->getPrettyString());
@@ -630,15 +660,26 @@ private function cacheArchiveIdsAfterLaunching($archiveGroups, $plugins)
// we already know there are no stats for this period
// we add one day to make sure we don't miss the day of the website creation
if ($twoDaysAfterPeriod->isEarlier($site->getCreationDate())) {
- Log::debug("Archive site %s, %s (%s) skipped, archive is before the website was created.",
- $idSite, $period->getLabel(), $period->getPrettyString());
+ Log::debug(
+ "Archive site %s, %s (%s) skipped, archive is before the website was created.",
+ $idSite,
+ $period->getLabel(),
+ $period->getPrettyString()
+ );
continue;
}
- // if the starting date is in the future we know there is no visiidsite = ?t
- if ($twoDaysBeforePeriod->isLater($today)) {
- Log::debug("Archive site %s, %s (%s) skipped, archive is after today.",
- $idSite, $period->getLabel(), $period->getPrettyString());
+ // Allow for site timezone, local time may have started a new day ahead of UTC
+ $today = \Piwik\Date::factory('now', $site->getTimezone());
+
+ // if the starting date is in the future we know there are no visits
+ if ($period->getDateStart()->isLater($today)) {
+ Log::debug(
+ "Archive site %s, %s (%s) skipped, archive is after today.",
+ $idSite,
+ $period->getLabel(),
+ $period->getPrettyString()
+ );
continue;
}
@@ -657,7 +698,11 @@ private function cacheArchiveIdsAfterLaunching($archiveGroups, $plugins)
private function cacheArchiveIdsWithoutLaunching($plugins)
{
$idarchivesByReport = ArchiveSelector::getArchiveIds(
- $this->params->getIdSites(), $this->params->getPeriods(), $this->params->getSegment(), $plugins);
+ $this->params->getIdSites(),
+ $this->params->getPeriods(),
+ $this->params->getSegment(),
+ $plugins
+ );
// initialize archive ID cache for each report
foreach ($plugins as $plugin) {
@@ -686,10 +731,10 @@ private function cacheArchiveIdsWithoutLaunching($plugins)
private function getDoneStringForPlugin($plugin, $idSites)
{
return Rules::getDoneStringFlagFor(
- $idSites,
- $this->params->getSegment(),
- $this->getPeriodLabel(),
- $plugin
+ $idSites,
+ $this->params->getSegment(),
+ $this->getPeriodLabel(),
+ $plugin
);
}
@@ -707,15 +752,17 @@ private function getPeriodLabel()
*/
private function getResultIndices()
{
- $indices = array();
+ $indices = [];
- if (count($this->params->getIdSites()) > 1
+ if (
+ count($this->params->getIdSites()) > 1
|| $this->forceIndexedBySite
) {
$indices['site'] = 'idSite';
}
- if (count($this->params->getPeriods()) > 1
+ if (
+ count($this->params->getPeriods()) > 1
|| $this->forceIndexedByDate
) {
$indices['period'] = 'date';
@@ -757,7 +804,7 @@ private function formatNumericValue($value)
private function initializeArchiveIdCache($doneFlag)
{
if (!isset($this->idarchives[$doneFlag])) {
- $this->idarchives[$doneFlag] = array();
+ $this->idarchives[$doneFlag] = [];
}
}
@@ -795,11 +842,11 @@ private function getArchiveGroupOfPlugin($plugin)
*/
public static function getPluginForReport($report)
{
- // Core metrics are always processed in Core, for the requested date/period/segment
if (in_array($report, Metrics::getVisitsMetricNames())) {
+ // Core metrics are always processed in Core, for the requested date/period/segment
$report = 'VisitsSummary_CoreMetrics';
- } // Goal_* metrics are processed by the Goals plugin (HACK)
- elseif (strpos($report, 'Goal_') === 0) {
+ } elseif (strpos($report, 'Goal_') === 0) {
+ // Goal_* metrics are processed by the Goals plugin (HACK)
$report = 'Goals_Metrics';
} elseif (
strrpos($report, '_returning') === strlen($report) - strlen('_returning') ||
@@ -809,7 +856,8 @@ public static function getPluginForReport($report)
}
$plugin = substr($report, 0, strpos($report, '_'));
- if (empty($plugin)
+ if (
+ empty($plugin)
|| !\Piwik\Plugin\Manager::getInstance()->isPluginActivated($plugin)
) {
throw new \Exception("Error: The report '$report' was requested but it is not available at this stage."
@@ -835,7 +883,7 @@ private function prepareArchive(array $archiveGroups, Site $site, Period $period
$periodString = $period->getRangeString();
$periodDateStr = $period->getLabel() == 'range' ? $periodString : $period->getDateStart()->toString();
- $idSites = array($site->getId());
+ $idSites = [$site->getId()];
// process for each plugin as well
foreach ($archiveGroups as $plugin) {
@@ -843,10 +891,16 @@ private function prepareArchive(array $archiveGroups, Site $site, Period $period
$this->initializeArchiveIdCache($doneFlag);
$prepareResult = $coreAdminHomeApi->archiveReports(
- $site->getId(), $period->getLabel(), $periodDateStr, $this->params->getSegment()->getOriginalString(),
- $plugin, $requestedReport);
-
- if (!empty($prepareResult)
+ $site->getId(),
+ $period->getLabel(),
+ $periodDateStr,
+ $this->params->getSegment()->getOriginalString(),
+ $plugin,
+ $requestedReport
+ );
+
+ if (
+ !empty($prepareResult)
&& !empty($prepareResult['idarchives'])
) {
foreach ($prepareResult['idarchives'] as $idArchive) {
@@ -859,7 +913,7 @@ private function prepareArchive(array $archiveGroups, Site $site, Period $period
private function getIdArchivesByMonth($doneFlags)
{
// order idarchives by the table month they belong to
- $idArchivesByMonth = array();
+ $idArchivesByMonth = [];
foreach (array_keys($doneFlags) as $doneFlag) {
if (empty($this->idarchives[$doneFlag])) {
diff --git a/app/core/Archive/ArchiveInvalidator.php b/app/core/Archive/ArchiveInvalidator.php
index e7c83cf7d..585c22dd8 100644
--- a/app/core/Archive/ArchiveInvalidator.php
+++ b/app/core/Archive/ArchiveInvalidator.php
@@ -30,7 +30,6 @@
use Piwik\SettingsServer;
use Piwik\Site;
use Piwik\Tracker\Cache;
-use Piwik\Tracker\Model as TrackerModel;
use Psr\Log\LoggerInterface;
/**
@@ -97,7 +96,7 @@ public function getAllRememberToInvalidateArchivedReportsLater()
// we do not really have to get the value first. we could simply always try to call set() and it would update or
// insert the record if needed but we do not want to lock the table (especially since there are still some
// MyISAM installations)
- $values = Option::getLike('%' . $this->rememberArchivedReportIdStart . '%');
+ $values = Option::getLike('%' . str_replace('_', '\_', $this->rememberArchivedReportIdStart) . '%');
$all = [];
foreach ($values as $name => $value) {
@@ -122,7 +121,7 @@ public function rememberToInvalidateArchivedReportsLater($idSite, Date $date)
// we do not really have to get the value first. we could simply always try to call set() and it would update or
// insert the record if needed but we do not want to lock the table (especially since there are still some
// MyISAM installations)
- $value = Option::getLike('%' . $key . '%');
+ $value = Option::getLike('%' . str_replace('_', '\_', $key) . '%');
}
// getLike() returns an empty array rather than 'false'
@@ -155,7 +154,7 @@ private function getRememberedArchivedReportsOptionFromTracker($idSite, $dateStr
public function getRememberedArchivedReportsThatShouldBeInvalidated()
{
- $reports = Option::getLike('%' . $this->rememberArchivedReportIdStart . '%_%');
+ $reports = Option::getLike('%' . str_replace('_', '\_', $this->rememberArchivedReportIdStart) . '%\_%');
$sitesPerDay = array();
@@ -205,9 +204,11 @@ private function buildRememberArchivedReportIdProcessSafe($idSite, $date)
public function forgetRememberedArchivedReportsToInvalidateForSite($idSite)
{
- $id = $this->buildRememberArchivedReportIdForSite($idSite) . '\_';
- $this->deleteOptionLike($id);
- Cache::clearCacheGeneral();
+ $id = $this->buildRememberArchivedReportIdForSite($idSite) . '_';
+ $hasDeletedSomething = $this->deleteOptionLike($id);
+ if ($hasDeletedSomething) {
+ Cache::clearCacheGeneral();
+ }
}
/**
@@ -221,17 +222,22 @@ public function forgetRememberedArchivedReportsToInvalidate($idSite, Date $date)
// The process pid is added to the end of the entry in order to support multiple concurrent transactions.
// So this must be a deleteLike call to get all the entries, where there used to only be one.
- $this->deleteOptionLike($id);
+ return $this->deleteOptionLike($id);
}
+ /**
+ * @param $id
+ * @return bool true if a record was deleted, false otherwise.
+ * @throws \Zend_Db_Statement_Exception
+ */
private function deleteOptionLike($id)
{
// we're not using deleteLike since it maybe could cause deadlocks see https://github.com/matomo-org/matomo/issues/15545
// we want to reduce number of rows scanned and only delete specific primary key
- $keys = Option::getLike('%' . $id . '%');
+ $keys = Option::getLike('%' . str_replace('_', '\_', $id) . '%');
if (empty($keys)) {
- return;
+ return false;
}
$keys = array_keys($keys);
@@ -239,7 +245,8 @@ private function deleteOptionLike($id)
$placeholders = Common::getSqlStringFieldsArray($keys);
$table = Common::prefixTable('option');
- Db::query('DELETE FROM `' . $table . '` WHERE `option_name` IN (' . $placeholders . ')', $keys);
+ $db = Db::query('DELETE FROM `' . $table . '` WHERE `option_name` IN (' . $placeholders . ')', $keys);
+ return (bool) $db->rowCount();
}
/**
@@ -251,6 +258,7 @@ private function deleteOptionLike($id)
* @param bool $forceInvalidateNonexistantRanges set true to force inserting rows for ranges in archive_invalidations
* @param string $name null to make sure every plugin is archived when this invalidation is processed by core:archive,
* or a plugin name to only archive the specific plugin.
+ * @param bool $ignorePurgeLogDataDate
* @return InvalidationResult
* @throws \Exception
*/
@@ -281,6 +289,7 @@ public function markArchivesAsInvalidated(array $idSites, array $dates, $period,
&& count($dates) == 1
&& ((string)$dates[0]) == ((string)Date::factoryInTimezone('today', $tz))
) {
+ // date is for today
$hasMoreThanJustToday[$idSite] = false;
}
}
@@ -316,20 +325,27 @@ public function markArchivesAsInvalidated(array $idSites, array $dates, $period,
$isInvalidatingDays = $period == 'day' || $cascadeDown || empty($period);
$isNotInvalidatingSegment = empty($segment) || empty($segment->getString());
+
if ($isInvalidatingDays
&& $isNotInvalidatingSegment
) {
+
+ $hasDeletedAny = false;
+
foreach ($idSites as $idSite) {
foreach ($dates as $date) {
if (is_string($date)) {
$date = Date::factory($date);
}
- $this->forgetRememberedArchivedReportsToInvalidate($idSite, $date);
+ $hasDeletedAny = $this->forgetRememberedArchivedReportsToInvalidate($idSite, $date) || $hasDeletedAny;
}
}
+
+ if ($hasDeletedAny) {
+ Cache::clearCacheGeneral();
+ }
}
- Cache::clearCacheGeneral();
return $invalidationInfo;
}
@@ -457,7 +473,7 @@ public function markArchivesOverlappingRangeAsInvalidated(array $idSites, array
*/
public function reArchiveReport($idSites, string $plugin = null, string $report = null, Date $startDate = null, Segment $segment = null)
{
- $date2 = Date::yesterday();
+ $date2 = Date::today();
$earliestDateToRearchive = $this->getEarliestDateToRearchive();
if (empty($startDate)) {
diff --git a/app/core/Archive/DataTableFactory.php b/app/core/Archive/DataTableFactory.php
index d2c247944..0725fd1b5 100644
--- a/app/core/Archive/DataTableFactory.php
+++ b/app/core/Archive/DataTableFactory.php
@@ -11,7 +11,6 @@
use Piwik\DataTable;
use Piwik\DataTable\Row;
-use Piwik\Period;
use Piwik\Segment;
use Piwik\Site;
diff --git a/app/core/ArchiveProcessor.php b/app/core/ArchiveProcessor.php
index 09bfeb242..2fa72d2db 100644
--- a/app/core/ArchiveProcessor.php
+++ b/app/core/ArchiveProcessor.php
@@ -679,8 +679,9 @@ public function processDependentArchive($plugin, $segment)
// vs here we would use
// userId!@%40matomo.org;userId!=hello%40matomo.org;visitorType==new
// thus these would result in different segment hashes and therefore the reports would either show 0 or archive the data twice
- $newSegment = Segment::combine($params->getSegment()->getOriginalString(), SegmentExpression::AND_DELIMITER, $segment);
- if ($newSegment === $segment && $params->getRequestedPlugin() === $plugin) { // being processed now
+ $originSegmentString = $params->getSegment()->getOriginalString();
+ $newSegment = Segment::combine($originSegmentString, SegmentExpression::AND_DELIMITER, $segment);
+ if (!empty($originSegmentString) && $newSegment === $segment && $params->getRequestedPlugin() === $plugin) { // being processed now
return;
}
diff --git a/app/core/ArchiveProcessor/ArchivingStatus.php b/app/core/ArchiveProcessor/ArchivingStatus.php
index 54dfae9da..5f0bd763b 100644
--- a/app/core/ArchiveProcessor/ArchivingStatus.php
+++ b/app/core/ArchiveProcessor/ArchivingStatus.php
@@ -9,11 +9,9 @@
namespace Piwik\ArchiveProcessor;
-use Piwik\Common;
use Piwik\Concurrency\Lock;
use Piwik\Concurrency\LockBackend;
use Piwik\Container\StaticContainer;
-use Piwik\SettingsPiwik;
class ArchivingStatus
{
diff --git a/app/core/ArchiveProcessor/Loader.php b/app/core/ArchiveProcessor/Loader.php
index d99a5ea0f..00d834a8e 100644
--- a/app/core/ArchiveProcessor/Loader.php
+++ b/app/core/ArchiveProcessor/Loader.php
@@ -468,6 +468,10 @@ public function canSkipArchiveForSegment()
return false;
}
+ if (!empty($params->getRequestedPlugin()) && Rules::isSegmentPluginArchivingDisabled($params->getRequestedPlugin(), $params->getSite()->getId())) {
+ return true;
+ }
+
/** @var SegmentArchiving */
$segmentArchiving = StaticContainer::get(SegmentArchiving::class);
$segmentInfo = $segmentArchiving->findSegmentForHash($params->getSegment()->getHash(), $params->getSite()->getId());
diff --git a/app/core/ArchiveProcessor/LoaderLock.php b/app/core/ArchiveProcessor/LoaderLock.php
index 3ab8d3f00..fca94a554 100644
--- a/app/core/ArchiveProcessor/LoaderLock.php
+++ b/app/core/ArchiveProcessor/LoaderLock.php
@@ -18,6 +18,10 @@ class LoaderLock
const MAX_LOCK_TIME = 60; //in seconds
protected $id;
+ /**
+ * @param string $id
+ * @throws \Exception
+ */
public function __construct($id)
{
// instanceId is needed for multi tenant database solution
diff --git a/app/core/ArchiveProcessor/Parameters.php b/app/core/ArchiveProcessor/Parameters.php
index c32817063..4d9975ca9 100644
--- a/app/core/ArchiveProcessor/Parameters.php
+++ b/app/core/ArchiveProcessor/Parameters.php
@@ -9,9 +9,6 @@
namespace Piwik\ArchiveProcessor;
-use Piwik\Cache;
-use Piwik\DataAccess\Model;
-use Piwik\DataAccess\RawLogDao;
use Piwik\Date;
use Piwik\Log;
use Piwik\Period;
diff --git a/app/core/ArchiveProcessor/Rules.php b/app/core/ArchiveProcessor/Rules.php
index c31c3bf4f..d1ff2e088 100644
--- a/app/core/ArchiveProcessor/Rules.php
+++ b/app/core/ArchiveProcessor/Rules.php
@@ -9,17 +9,15 @@
namespace Piwik\ArchiveProcessor;
use Exception;
-use Piwik\Common;
use Piwik\Config;
+use Piwik\Config\GeneralConfig;
use Piwik\DataAccess\ArchiveWriter;
-use Piwik\DataAccess\Model;
use Piwik\Date;
use Piwik\Log;
use Piwik\Option;
use Piwik\Piwik;
use Piwik\Plugin\Manager;
use Piwik\Plugins\CoreAdminHome\Controller;
-use Piwik\Scheduler\Task;
use Piwik\Segment;
use Piwik\SettingsPiwik;
use Piwik\SettingsServer;
@@ -58,7 +56,7 @@ class Rules
public static function getDoneStringFlagFor(array $idSites, $segment, $periodLabel, $plugin)
{
if (!empty($plugin)
- && !self::shouldProcessReportsAllPlugins($idSites, $segment, $periodLabel)
+ && !self::shouldProcessReportsAllPlugins($idSites, $segment, $periodLabel)
) {
return self::getDoneFlagArchiveContainsOnePlugin($segment, $plugin);
}
@@ -101,7 +99,7 @@ public static function getSegmentsToProcess($idSites)
public static function getDoneFlagArchiveContainsOnePlugin(Segment $segment, $plugin)
{
- return 'done' . $segment->getHash() . '.' . $plugin ;
+ return 'done' . $segment->getHash() . '.' . $plugin;
}
public static function getDoneFlagArchiveContainsAllPlugins(Segment $segment)
@@ -131,8 +129,11 @@ public static function getDoneFlags(array $plugins, Segment $segment)
}
public static function getMinTimeProcessedForInProgressArchive(
- Date $dateStart, \Piwik\Period $period, Segment $segment, Site $site)
- {
+ Date $dateStart,
+ \Piwik\Period $period,
+ Segment $segment,
+ Site $site
+ ) {
$todayArchiveTimeToLive = self::getPeriodArchiveTimeToLiveDefault($period->getLabel());
$now = time();
@@ -142,7 +143,7 @@ public static function getMinTimeProcessedForInProgressArchive(
$isArchivingDisabled = Rules::isArchivingDisabledFor($idSites, $segment, $period->getLabel());
if ($isArchivingDisabled) {
if ($period->getNumberOfSubperiods() == 0
- && $dateStart->getTimestamp() <= $now
+ && $dateStart->getTimestamp() <= $now
) {
// Today: accept any recent enough archive
$minimumArchiveTime = false;
@@ -150,7 +151,8 @@ public static function getMinTimeProcessedForInProgressArchive(
// This week, this month, this year:
// accept any archive that was processed today after 00:00:01 this morning
$timezone = $site->getTimezone();
- $minimumArchiveTime = Date::factory(Date::factory('now', $timezone)->getDateStartUTC())->setTimezone($timezone)->getTimestamp();
+ $minimumArchiveTime = Date::factory(Date::factory('now',
+ $timezone)->getDateStartUTC())->setTimezone($timezone)->getTimestamp();
}
}
return $minimumArchiveTime;
@@ -214,7 +216,7 @@ public static function isArchivingEnabledFor(array $idSites, Segment $segment, $
if ($periodLabel === 'range') {
if (isset($generalConfig['archiving_range_force_on_browser_request'])
- && $generalConfig['archiving_range_force_on_browser_request'] == false
+ && $generalConfig['archiving_range_force_on_browser_request'] == false
) {
Log::debug("Not forcing archiving for range period.");
return $isArchivingEnabled;
@@ -229,8 +231,8 @@ public static function isArchivingEnabledFor(array $idSites, Segment $segment, $
}
if (!$isArchivingEnabled
- && (!self::isBrowserArchivingAvailableForSegments() || self::isSegmentPreProcessed($idSites, $segment))
- && !SettingsServer::isArchivePhpTriggered() // Only applies when we are not running core:archive command
+ && (!self::isBrowserArchivingAvailableForSegments() || self::isSegmentPreProcessed($idSites, $segment))
+ && !SettingsServer::isArchivePhpTriggered() // Only applies when we are not running core:archive command
) {
Log::debug("Archiving is disabled because of config setting browser_archiving_disabled_enforce=1 or because the segment is selected to be pre-processed.");
return false;
@@ -315,7 +317,7 @@ public static function isSegmentPreProcessed(array $idSites, Segment $segment)
$segmentsToProcessUrlDecoded = array_map('urldecode', $segmentsToProcess);
return in_array($segment, $segmentsToProcess)
- || in_array($segment, $segmentsToProcessUrlDecoded);
+ || in_array($segment, $segmentsToProcessUrlDecoded);
}
/**
@@ -323,8 +325,11 @@ public static function isSegmentPreProcessed(array $idSites, Segment $segment)
*
* @return string[]
*/
- public static function getSelectableDoneFlagValues($includeInvalidated = true, Parameters $params = null, $checkAuthorizedToArchive = true)
- {
+ public static function getSelectableDoneFlagValues(
+ $includeInvalidated = true,
+ Parameters $params = null,
+ $checkAuthorizedToArchive = true
+ ) {
$possibleValues = array(ArchiveWriter::DONE_OK, ArchiveWriter::DONE_OK_TEMPORARY);
if ($includeInvalidated) {
@@ -356,4 +361,24 @@ public static function shouldProcessSegmentsWhenReArchivingReports()
{
return Config::getInstance()->General['rearchive_reports_in_past_exclude_segments'] != 1;
}
+
+ public static function isSegmentPluginArchivingDisabled($pluginName, $siteId = null)
+ {
+ $pluginArchivingSetting = GeneralConfig::getConfigValue('disable_archiving_segment_for_plugins', $siteId);
+
+ if (empty($pluginArchivingSetting)) {
+ return false;
+ }
+
+ if (is_string($pluginArchivingSetting)) {
+ $pluginArchivingSetting = explode(",", $pluginArchivingSetting);
+ $pluginArchivingSetting = array_filter($pluginArchivingSetting, function($plugin){
+ return Manager::getInstance()->isValidPluginName($plugin);
+ });
+ }
+
+ $pluginArchivingSetting = array_map('strtolower', $pluginArchivingSetting);
+
+ return in_array(strtolower($pluginName), $pluginArchivingSetting);
+ }
}
diff --git a/app/core/AssetManager.php b/app/core/AssetManager.php
index 3e174718e..1eb8820f0 100644
--- a/app/core/AssetManager.php
+++ b/app/core/AssetManager.php
@@ -16,6 +16,7 @@
use Piwik\AssetManager\UIAssetFetcher\JScriptUIAssetFetcher;
use Piwik\AssetManager\UIAssetFetcher\StaticUIAssetFetcher;
use Piwik\AssetManager\UIAssetFetcher\StylesheetUIAssetFetcher;
+use Piwik\AssetManager\UIAssetFetcher\PluginUmdAssetFetcher;
use Piwik\AssetManager\UIAssetFetcher;
use Piwik\AssetManager\UIAssetMerger\JScriptUIAssetMerger;
use Piwik\AssetManager\UIAssetMerger\StylesheetUIAssetMerger;
@@ -44,9 +45,11 @@ class AssetManager extends Singleton
const CSS_IMPORT_DIRECTIVE = " \n";
const JS_IMPORT_DIRECTIVE = "\n";
+ const JS_DEFER_IMPORT_DIRECTIVE = "\n";
const GET_CSS_MODULE_ACTION = "index.php?module=Proxy&action=getCss";
const GET_CORE_JS_MODULE_ACTION = "index.php?module=Proxy&action=getCoreJs";
const GET_NON_CORE_JS_MODULE_ACTION = "index.php?module=Proxy&action=getNonCoreJs";
+ const GET_JS_UMD_MODULE_ACTION = "index.php?module=Proxy&action=getUmdJs&chunk=";
/**
* @var UIAssetCacheBuster
@@ -149,11 +152,27 @@ public function getJsInclusionDirective()
} else {
$result .= sprintf(self::JS_IMPORT_DIRECTIVE, self::GET_CORE_JS_MODULE_ACTION);
$result .= sprintf(self::JS_IMPORT_DIRECTIVE, self::GET_NON_CORE_JS_MODULE_ACTION);
+
+ $result .= $this->getPluginUmdChunks();
}
return $result;
}
+ protected function getPluginUmdChunks()
+ {
+ $fetcher = $this->getPluginUmdJScriptFetcher();
+
+ $chunks = $fetcher->getChunkFiles();
+
+ $result = '';
+ foreach ($chunks as $chunk) {
+ $src = self::GET_JS_UMD_MODULE_ACTION . urlencode($chunk->getChunkName());
+ $result .= sprintf(self::JS_DEFER_IMPORT_DIRECTIVE, $src);
+ }
+ return $result;
+ }
+
/**
* Return the base.less compiled to css
*
@@ -212,7 +231,22 @@ public function getMergedNonCoreJavaScript()
}
/**
- * @param boolean $core
+ * Return a chunk JS merged file absolute location.
+ * If there is none, the generation process will be triggered.
+ *
+ * @param string $chunk The name of the chunk. Will either be a plugin name or an integer.
+ * @return UIAsset
+ */
+ public function getMergedJavaScriptChunk($chunk)
+ {
+ $assetFetcher = $this->getPluginUmdJScriptFetcher($chunk);
+ $outputFile = $assetFetcher->getRequestedChunkOutputFile();
+
+ return $this->getMergedJavascript($assetFetcher, $this->getMergedUIAsset($outputFile));
+ }
+
+ /**
+ * @param boolean|"all" $core
* @return string[]
*/
public function getLoadedPlugins($core)
@@ -223,7 +257,7 @@ public function getLoadedPlugins($core)
$pluginName = $plugin->getPluginName();
$pluginIsCore = Manager::getInstance()->isPluginBundledWithCore($pluginName);
- if (($pluginIsCore && $core) || (!$pluginIsCore && !$core)) {
+ if ($core === 'all' || ($pluginIsCore && $core) || (!$pluginIsCore && !$core)) {
$loadedPlugins[] = $pluginName;
}
}
@@ -245,10 +279,40 @@ public function removeMergedAssets($pluginName = false)
} else {
$assetsToRemove[] = $this->getMergedNonCoreJSAsset();
}
+
+ $assetFetcher = $this->getPluginUmdJScriptFetcher();
+ foreach ($assetFetcher->getChunkFiles() as $chunk) {
+ $files = $chunk->getFiles();
+
+ $foundInChunk = false;
+ foreach ($files as $file) {
+ if (strpos($file, "/$pluginName.umd.") !== false) {
+ $foundInChunk = true;
+ }
+ }
+
+ if ($foundInChunk) {
+ $outputFile = $chunk->getOutputFile();
+ $asset = $this->getMergedUIAsset($outputFile);
+ if ($asset->exists()) {
+ $assetsToRemove[] = $asset;
+ }
+ break;
+ }
+ }
}
} else {
$assetsToRemove[] = $this->getMergedCoreJSAsset();
$assetsToRemove[] = $this->getMergedNonCoreJSAsset();
+
+ $assetFetcher = $this->getPluginUmdJScriptFetcher();
+ foreach ($assetFetcher->getChunkFiles() as $chunk) {
+ $outputFile = $chunk->getOutputFile();
+ $asset = $this->getMergedUIAsset($outputFile);
+ if ($asset->exists()) {
+ $assetsToRemove[] = $asset;
+ }
+ }
}
$this->removeAssets($assetsToRemove);
@@ -285,11 +349,11 @@ public function isMergedAssetsDisabled()
if (Config::getInstance()->Development['disable_merged_assets'] == 1) {
return true;
}
-
+
if (isset($_GET['disable_merged_assets']) && $_GET['disable_merged_assets'] == 1) {
return true;
}
-
+
return false;
}
@@ -316,7 +380,8 @@ protected function getIndividualCoreAndNonCoreJsIncludes()
{
return
$this->getIndividualJsIncludesFromAssetFetcher($this->getCoreJScriptFetcher()) .
- $this->getIndividualJsIncludesFromAssetFetcher($this->getNonCoreJScriptFetcher());
+ $this->getIndividualJsIncludesFromAssetFetcher($this->getNonCoreJScriptFetcher()) .
+ $this->getIndividualJsIncludesFromAssetFetcher($this->getPluginUmdJScriptFetcher());
}
/**
@@ -347,6 +412,11 @@ protected function getNonCoreJScriptFetcher()
return new JScriptUIAssetFetcher($this->getLoadedPlugins(false), $this->theme);
}
+ protected function getPluginUmdJScriptFetcher($chunk = null)
+ {
+ return new PluginUmdAssetFetcher($this->getLoadedPlugins('all'), $this->theme, $chunk);
+ }
+
/**
* @param string $pluginName
* @return boolean
@@ -440,12 +510,12 @@ public static function compileCustomJs($files)
{
$mergedAsset = new InMemoryUIAsset();
$fetcher = new StaticUIAssetFetcher($files, $priorityOrder = array(), $theme = null);
-
+
$cacheBuster = UIAssetCacheBuster::getInstance();
$assetMerger = new JScriptUIAssetMerger($mergedAsset, $fetcher, $cacheBuster);
$assetMerger->generateFile();
-
+
return $mergedAsset->getContent();
}
}
diff --git a/app/core/AssetManager/UIAsset.php b/app/core/AssetManager/UIAsset.php
index cc26ba956..012d5ab1e 100644
--- a/app/core/AssetManager/UIAsset.php
+++ b/app/core/AssetManager/UIAsset.php
@@ -8,7 +8,6 @@
*/
namespace Piwik\AssetManager;
-use Exception;
abstract class UIAsset
{
diff --git a/app/core/AssetManager/UIAssetFetcher/Chunk.php b/app/core/AssetManager/UIAssetFetcher/Chunk.php
new file mode 100644
index 000000000..db42428ba
--- /dev/null
+++ b/app/core/AssetManager/UIAssetFetcher/Chunk.php
@@ -0,0 +1,69 @@
+chunkName = $chunkName;
+ $this->files = $files;
+ }
+
+ /**
+ * @return string
+ */
+ public function getOutputFile(): string
+ {
+ return "asset_manager_chunk.{$this->chunkName}.js";
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getFiles(): array
+ {
+ return $this->files;
+ }
+
+ /**
+ * @param string[] $files
+ */
+ public function setFiles(array $files): void
+ {
+ $this->files = $files;
+ }
+
+ /**
+ * @return string
+ */
+ public function getChunkName(): string
+ {
+ return $this->chunkName;
+ }
+
+ /**
+ * @param string $chunkName
+ */
+ public function setChunkName(string $chunkName): void
+ {
+ $this->chunkName = $chunkName;
+ }
+}
\ No newline at end of file
diff --git a/app/core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php b/app/core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php
index 84484ab0d..4248db939 100644
--- a/app/core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php
+++ b/app/core/AssetManager/UIAssetFetcher/JScriptUIAssetFetcher.php
@@ -9,7 +9,6 @@
namespace Piwik\AssetManager\UIAssetFetcher;
use Piwik\AssetManager\UIAssetFetcher;
-use Piwik\Development;
use Piwik\Piwik;
class JScriptUIAssetFetcher extends UIAssetFetcher
@@ -18,7 +17,6 @@ class JScriptUIAssetFetcher extends UIAssetFetcher
protected function retrieveFileLocations()
{
if (!empty($this->plugins)) {
-
/**
* Triggered when gathering the list of all JavaScript files needed by Piwik
* and its plugins.
@@ -44,8 +42,6 @@ protected function retrieveFileLocations()
* @param string[] $jsFiles The JavaScript files to load.
*/
Piwik::postEvent('AssetManager.getJavaScriptFiles', array(&$this->fileLocations), null, $this->plugins);
-
- $this->addUmdFilesIfDetected($this->plugins);
}
$this->addThemeFiles();
@@ -74,8 +70,10 @@ protected function getPriorityOrder()
{
return array(
'node_modules/jquery/dist/jquery.min.js',
+ 'node_modules/jquery/dist/jquery.js',
'node_modules/materialize-css/dist/js/materialize.min.js', // so jquery ui datepicker overrides materializecss
'node_modules/jquery-ui-dist/jquery-ui.min.js',
+ 'node_modules/jquery-ui-dist/jquery-ui.js',
"plugins/CoreHome/javascripts/materialize-bc.js",
"node_modules/jquery.browser/dist/jquery.browser.min.js",
'node_modules/',
@@ -94,18 +92,4 @@ protected function getPriorityOrder()
'tests/',
);
}
-
- private function addUmdFilesIfDetected($plugins)
- {
- foreach ($plugins as $plugin) {
- $devUmd = "plugins/$plugin/vue/dist/$plugin.development.umd.js";
- $minifiedUmd = "plugins/$plugin/vue/dist/$plugin.umd.min.js";
-
- if (Development::isEnabled() && is_file(PIWIK_INCLUDE_PATH . '/' . $devUmd)) {
- $this->fileLocations[] = $devUmd;
- } else if (is_file(PIWIK_INCLUDE_PATH . '/' . $minifiedUmd)) {
- $this->fileLocations[] = $minifiedUmd;
- }
- }
- }
}
diff --git a/app/core/AssetManager/UIAssetFetcher/PluginUmdAssetFetcher.php b/app/core/AssetManager/UIAssetFetcher/PluginUmdAssetFetcher.php
new file mode 100644
index 000000000..9ac1edaec
--- /dev/null
+++ b/app/core/AssetManager/UIAssetFetcher/PluginUmdAssetFetcher.php
@@ -0,0 +1,297 @@
+requestedChunk = $chunk;
+ $this->loadIndividually = $loadIndividually;
+ $this->chunkCount = $chunkCount;
+
+ if (!$this->loadIndividually && (!is_int($chunkCount) || $chunkCount <= 0)) {
+ throw new \Exception("Invalid chunk count: $chunkCount");
+ }
+ }
+
+ public function getRequestedChunkOutputFile()
+ {
+ return "asset_manager_chunk.{$this->requestedChunk}.js";
+ }
+
+ /**
+ * @return Chunk[]
+ */
+ public function getChunkFiles()
+ {
+ $allPluginUmds = $this->getAllPluginUmds();
+
+ if ($this->loadIndividually) {
+ return $allPluginUmds;
+ }
+
+ $totalSize = $this->getTotalChunkSize($allPluginUmds);
+
+ $chunkFiles = $this->dividePluginUmdsByChunkCount($allPluginUmds, $totalSize);
+
+ $chunks = [];
+ foreach ($chunkFiles as $index => $jsFiles) {
+ $chunks[] = new Chunk($index, $jsFiles);
+ }
+ return $chunks;
+ }
+
+ private function getTotalChunkSize($allPluginUmds)
+ {
+ $totalSize = 0;
+ foreach ($allPluginUmds as $chunk) {
+ $path = PIWIK_INCLUDE_PATH . '/' . $chunk->getFiles()[0];
+ if (is_file($path)) {
+ $totalSize += filesize($path);
+ }
+ }
+ return $totalSize;
+ }
+
+ private function getAllPluginUmds()
+ {
+ $plugins = self::orderPluginsByPluginDependencies($this->plugins, false);
+
+ $allPluginUmds = [];
+ foreach ($plugins as $plugin) {
+ $pluginDir = self::getRelativePluginDirectory($plugin);
+ $minifiedUmd = "$pluginDir/vue/dist/$plugin.umd.min.js";
+ if (!is_file(PIWIK_INCLUDE_PATH . '/' . $minifiedUmd)) {
+ continue;
+ }
+
+ $allPluginUmds[] = new Chunk($plugin, [$minifiedUmd]);
+ }
+ return $allPluginUmds;
+ }
+
+ private function dividePluginUmdsByChunkCount($allPluginUmds, $totalSize)
+ {
+ $chunkSizeLimit = floor($totalSize / $this->chunkCount);
+
+ $chunkFiles = [];
+
+ $currentChunkIndex = 0;
+ $currentChunkSize = 0;
+ foreach ($allPluginUmds as $pluginChunk) {
+ $path = PIWIK_INCLUDE_PATH . '/' . $pluginChunk->getFiles()[0];
+ if (!is_file($path)) {
+ continue;
+ }
+
+ $size = filesize($path);
+ $currentChunkSize += $size;
+
+ if ($currentChunkSize > $chunkSizeLimit
+ && !empty($chunkFiles[$currentChunkIndex])
+ && $currentChunkIndex < $this->chunkCount - 1
+ ) {
+ ++$currentChunkIndex;
+ $currentChunkSize = $size;
+ }
+
+ $chunkFiles[$currentChunkIndex][] = $pluginChunk->getFiles()[0];
+ }
+
+ return $chunkFiles;
+ }
+
+ protected function retrieveFileLocations()
+ {
+ if (empty($this->plugins)) {
+ return;
+ }
+
+ if ($this->requestedChunk !== null && $this->requestedChunk !== '') {
+ $chunkFiles = $this->getChunkFiles();
+
+ $foundChunk = null;
+ foreach ($chunkFiles as $chunk) {
+ if ($chunk->getChunkName() == $this->requestedChunk) {
+ $foundChunk = $chunk;
+ break;
+ }
+ }
+
+ if (!$foundChunk) {
+ throw new \Exception("Could not find chunk {$this->requestedChunk}");
+ }
+
+ foreach ($foundChunk->getFiles() as $file) {
+ $this->fileLocations[] = $file;
+ }
+
+ return;
+ }
+
+ // either loadFilesIndividually = true, or being called w/ disable_merged_assets=1
+ $this->addUmdFilesIfDetected($this->plugins);
+ }
+
+ private function addUmdFilesIfDetected($plugins)
+ {
+ $plugins = self::orderPluginsByPluginDependencies($plugins, false);
+
+ foreach ($plugins as $plugin) {
+ $fileLocation = self::getUmdFileToUseForPlugin($plugin);
+ if ($fileLocation) {
+ $this->fileLocations[] = $fileLocation;
+ }
+ }
+ }
+
+ public static function getUmdFileToUseForPlugin($plugin)
+ {
+ $pluginDir = self::getRelativePluginDirectory($plugin);
+
+ $devUmd = "$pluginDir/vue/dist/$plugin.development.umd.js";
+ $minifiedUmd = "$pluginDir/vue/dist/$plugin.umd.min.js";
+ $umdSrcFolder = "$pluginDir/vue/src";
+
+ // in case there are dist files but no src files, which can happen during development
+ if (is_dir(PIWIK_INCLUDE_PATH . '/' . $umdSrcFolder)) {
+ if (Development::isEnabled() && is_file(PIWIK_INCLUDE_PATH . '/' . $devUmd)) {
+ return $devUmd;
+ } else if (is_file(PIWIK_INCLUDE_PATH . '/' . $minifiedUmd)) {
+ return $minifiedUmd;
+ }
+ }
+
+ return null;
+ }
+
+ public static function orderPluginsByPluginDependencies($plugins, $keepUnresolved = true)
+ {
+ $result = [];
+
+ while (!empty($plugins)) {
+ self::visitPlugin(reset($plugins), $keepUnresolved, $plugins, $result);
+ }
+
+ return $result;
+ }
+
+ public static function getPluginDependencies($plugin)
+ {
+ $pluginDir = self::getPluginDirectory($plugin);
+ $umdMetadata = "$pluginDir/vue/dist/umd.metadata.json";
+
+ $cache = Cache::getTransientCache();
+ $cacheKey = 'PluginUmdAssetFetcher.pluginDependencies.' . $plugin;
+
+ $pluginDependencies = $cache->fetch($cacheKey);
+ if (!is_array($pluginDependencies)) {
+ $pluginDependencies = [];
+ if (is_file($umdMetadata)) {
+ $pluginDependencies = json_decode(file_get_contents($umdMetadata), true);
+ $pluginDependencies = $pluginDependencies['dependsOn'] ?? [];
+ }
+ $cache->save($cacheKey, $pluginDependencies);
+ }
+ return $cache->fetch($cacheKey);
+ }
+
+ private static function visitPlugin($plugin, $keepUnresolved, &$plugins, &$result)
+ {
+ // remove the plugin from the array of plugins to visit
+ $index = array_search($plugin, $plugins);
+ if ($index !== false) {
+ unset($plugins[$index]);
+ } else {
+ return; // already visited
+ }
+
+ // read the plugin dependencies, if any
+ $pluginDependencies = self::getPluginDependencies($plugin);
+
+ if (!empty($pluginDependencies)) {
+ // visit each plugin this one depends on first, so it is loaded first
+ foreach ($pluginDependencies as $pluginDependency) {
+ // check if dependency is not activated
+ if (!in_array($pluginDependency, $plugins)
+ && !in_array($pluginDependency, $result)
+ && !$keepUnresolved
+ ) {
+ return;
+ }
+
+ self::visitPlugin($pluginDependency, $keepUnresolved, $plugins, $result);
+ }
+ }
+
+ // add the plugin to the load order after visiting its dependencies
+ $result[] = $plugin;
+ }
+
+ protected function getPriorityOrder()
+ {
+ // the JS files are already ordered properly so this result doesn't matter
+ return [];
+ }
+
+ private static function getRelativePluginDirectory($plugin)
+ {
+ $result = self::getPluginDirectory($plugin);
+ $result = str_replace(PIWIK_INCLUDE_PATH . '/', '', $result);
+ return $result;
+ }
+
+ private static function getPluginDirectory($plugin)
+ {
+ return Manager::getInstance()->getPluginDirectory($plugin);
+ }
+
+ public static function getDefaultLoadIndividually()
+ {
+ return (Config::getInstance()->General['assets_umd_load_individually'] ?? 0) == 1;
+ }
+
+ public static function getDefaultChunkCount()
+ {
+ return (int)(Config::getInstance()->General['assets_umd_chunk_count'] ?? 3);
+ }
+}
\ No newline at end of file
diff --git a/app/core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php b/app/core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php
index cca95ef38..68004330e 100644
--- a/app/core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php
+++ b/app/core/AssetManager/UIAssetFetcher/StylesheetUIAssetFetcher.php
@@ -9,7 +9,6 @@
namespace Piwik\AssetManager\UIAssetFetcher;
use Piwik\AssetManager\UIAssetFetcher;
-use Piwik\Development;
use Piwik\Piwik;
class StylesheetUIAssetFetcher extends UIAssetFetcher
diff --git a/app/core/Changes/Model.php b/app/core/Changes/Model.php
new file mode 100644
index 000000000..0988ca96d
--- /dev/null
+++ b/app/core/Changes/Model.php
@@ -0,0 +1,218 @@
+db = ($db ?? Db::get());
+ $this->pluginManager = ($pluginManager ?? PluginManager::getInstance());
+ }
+
+ /**
+ * Add any new changes for a plugin to the changes table
+ *
+ * @param string $pluginName
+ *
+ * @throws \Exception
+ */
+ public function addChanges(string $pluginName): void
+ {
+ if ($this->pluginManager->isValidPluginName($pluginName) && $this->pluginManager->isPluginInFilesystem($pluginName)) {
+
+ $plugin = $this->pluginManager->loadPlugin($pluginName);
+ if (!$plugin) {
+ return;
+ }
+
+ $changes = $plugin->getChanges();
+ foreach ($changes as $change) {
+ $this->addChange($pluginName, $change);
+ }
+ }
+ }
+
+ /**
+ * Remove all changes for a plugin
+ *
+ * @param string $pluginName
+ */
+ public function removeChanges(string $pluginName): void
+ {
+ $table = Common::prefixTable('changes');
+
+ try {
+ $this->db->query("DELETE FROM " . $table . " WHERE plugin_name = ?", [$pluginName]);
+ } catch (\Exception $e) {
+ if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) {
+ return;
+ }
+ throw $e;
+ }
+ }
+
+ /**
+ * Add a change item to the database table
+ *
+ * @param string $pluginName
+ * @param array $change
+ */
+ public function addChange(string $pluginName, array $change): void
+ {
+ if(!isset($change['version']) || !isset($change['title']) || !isset($change['description'])) {
+ StaticContainer::get('Psr\Log\LoggerInterface')->warning(
+ "Change item for plugin {plugin} missing version, title or description fields - ignored",
+ ['plugin' => $pluginName]);
+ return;
+ }
+
+ $table = Common::prefixTable('changes');
+
+ $fields = ['created_time', 'plugin_name', 'version', 'title', 'description'];
+ $params = [Date::now()->getDatetime(), $pluginName, $change['version'], $change['title'], $change['description']];
+
+ if (isset($change['link_name']) && isset($change['link'])) {
+ $fields[] = 'link_name';
+ $fields[] = 'link';
+ $params[] = $change['link_name'];
+ $params[] = $change['link'];
+ }
+
+ $insertSql = 'INSERT IGNORE INTO ' . $table . ' ('.implode(',', $fields).')
+ VALUES ('.Common::getSqlStringFieldsArray($params).')';
+
+ try {
+ $this->db->query($insertSql, $params);
+ } catch (\Exception $e) {
+ if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) {
+ return;
+ }
+ throw $e;
+ }
+ }
+
+ /**
+ * Check if any changes items exist
+ *
+ * @param int|null $newerThanId Only count new changes as having a key > than this sequential key
+ *
+ * @return int
+ */
+ public function doChangesExist(?int $newerThanId = null): int
+ {
+ $changes = $this->getChangeItems();
+
+ $all = 0;
+ $new = 0;
+ foreach ($changes as $c) {
+ $all++;
+ if ($newerThanId !== null && isset($c['idchange']) && $c['idchange'] > $newerThanId) {
+ $new++;
+ }
+ }
+
+ if ($all === 0) {
+ return self::NO_CHANGES_EXIST;
+ } else if ($all > 0 && $new === 0) {
+ return self::CHANGES_EXIST;
+ } else {
+ return self::NEW_CHANGES_EXIST;
+ }
+ }
+
+ /**
+ * Return an array of change items from the changes table
+ *
+ * @return array
+ * @throws DbException
+ */
+ public function getChangeItems(): array
+ {
+ $showAtLeast = 10; // Always show at least this number of changes
+ $expireOlderThanDays = 90; // Don't show changes that were added to the table more than x days ago
+
+ $table = Common::prefixTable('changes');
+ $selectSql = "SELECT * FROM " . $table . " WHERE title IS NOT NULL ORDER BY idchange DESC";
+
+ try {
+ $changes = $this->db->fetchAll($selectSql);
+ } catch (\Exception $e) {
+ if (Db::get()->isErrNo($e, Migration\Db::ERROR_CODE_TABLE_NOT_EXISTS)) {
+ return [];
+ }
+ throw $e;
+ }
+
+ // Remove expired changes, only if there are at more than the minimum changes
+ $cutOffDate = Date::now()->subDay($expireOlderThanDays);
+ foreach ($changes as $k => $change) {
+ if (isset($change['idchange'])) {
+ $changes[$k]['idchange'] = (int)$change['idchange'];
+ }
+ if (count($changes) > $showAtLeast && $change['created_time'] < $cutOffDate) {
+ unset($changes[$k]);
+ }
+ }
+
+ /**
+ * Event triggered before changes are displayed
+ *
+ * Can be used to filter out unwanted changes
+ *
+ * **Example**
+ *
+ * Piwik::addAction('Changes.filterChanges', function ($changes) {
+ * foreach ($changes as $k => $c) {
+ * // Hide changes for the CoreHome plugin
+ * if (isset($c['plugin_name']) && $c['plugin_name'] == 'CoreHome') {
+ * unset($changes[$k]);
+ * }
+ * }
+ * });
+ *
+ * @param array &$changes
+ */
+ Piwik::postEvent('Changes.filterChanges', array(&$changes));
+
+ return $changes;
+ }
+
+}
diff --git a/app/core/Changes/UserChanges.php b/app/core/Changes/UserChanges.php
new file mode 100644
index 000000000..5e971c776
--- /dev/null
+++ b/app/core/Changes/UserChanges.php
@@ -0,0 +1,77 @@
+db = ($db ?? Db::get());
+ $this->user = $user;
+ }
+
+ /**
+ * Return a value indicating if there are any changes available to show the user
+ *
+ * @return int Changes\Model::NO_CHANGES_EXIST, Changes\Model::CHANGES_EXIST or Changes\Model::NEW_CHANGES_EXIST
+ * @throws \Exception
+ */
+ public function getNewChangesStatus(): int
+ {
+ $idchangeLastViewed = (isset($this->user['idchange_last_viewed']) ? $this->user['idchange_last_viewed'] : null);
+
+ $changesModel = new ChangesModel($this->db);
+ return $changesModel->doChangesExist($idchangeLastViewed);
+ }
+
+ /**
+ * Return an array of changes and update the user's changes last viewed value
+ *
+ * @return array
+ */
+ public function getChanges(): array
+ {
+ $changesModel = new ChangesModel(Db::get());
+ $changes = $changesModel->getChangeItems();
+
+ // Record the time that changes were viewed for the current user
+ $maxId = null;
+ foreach ($changes as $k => $change) {
+ if ($maxId < $change['idchange']) {
+ $maxId = $change['idchange'];
+ }
+ }
+
+ if ($maxId) {
+ $usersModel = new UsersModel();
+ $usersModel->updateUserFields($this->user['login'], ['idchange_last_viewed' => $maxId]);
+ }
+
+ return $changes;
+ }
+
+}
diff --git a/app/core/CliMulti/Output.php b/app/core/CliMulti/Output.php
index eced3854a..84fbaefb9 100644
--- a/app/core/CliMulti/Output.php
+++ b/app/core/CliMulti/Output.php
@@ -8,7 +8,6 @@
namespace Piwik\CliMulti;
use Piwik\CliMulti;
-use Piwik\Common;
use Piwik\Filesystem;
class Output implements OutputInterface
diff --git a/app/core/CliMulti/OutputInterface.php b/app/core/CliMulti/OutputInterface.php
index 33d197879..8eead52bd 100644
--- a/app/core/CliMulti/OutputInterface.php
+++ b/app/core/CliMulti/OutputInterface.php
@@ -7,9 +7,6 @@
*/
namespace Piwik\CliMulti;
-use Piwik\CliMulti;
-use Piwik\Common;
-use Piwik\Filesystem;
interface OutputInterface
{
diff --git a/app/core/CliMulti/Process.php b/app/core/CliMulti/Process.php
index e3a6bd968..a2e6f86e6 100644
--- a/app/core/CliMulti/Process.php
+++ b/app/core/CliMulti/Process.php
@@ -215,6 +215,7 @@ public static function isSupportedWithReason()
if (SettingsServer::isWindows()) {
$reasons[] = 'not supported on windows';
+ return $reasons;
}
if (self::isMethodDisabled('shell_exec')) {
@@ -287,6 +288,11 @@ private static function returnsSuccessCode($command)
{
$exec = $command . ' > /dev/null 2>&1; echo $?';
$returnCode = @shell_exec($exec);
+
+ if (false === $returnCode || null === $returnCode) {
+ return false;
+ }
+
$returnCode = trim($returnCode);
return 0 == (int) $returnCode;
}
diff --git a/app/core/CliMulti/StaticOutput.php b/app/core/CliMulti/StaticOutput.php
index d298cc7bc..8c2291db6 100644
--- a/app/core/CliMulti/StaticOutput.php
+++ b/app/core/CliMulti/StaticOutput.php
@@ -7,9 +7,7 @@
*/
namespace Piwik\CliMulti;
-use Piwik\CliMulti;
use Piwik\Common;
-use Piwik\Filesystem;
class StaticOutput implements OutputInterface
{
diff --git a/app/core/Columns/Dimension.php b/app/core/Columns/Dimension.php
index fd5c50860..0875e1e75 100644
--- a/app/core/Columns/Dimension.php
+++ b/app/core/Columns/Dimension.php
@@ -12,7 +12,6 @@
use Piwik\Piwik;
use Piwik\Plugin;
use Piwik\Plugin\ArchivedMetric;
-use Piwik\Plugin\ComponentFactory;
use Piwik\Plugin\Segment;
use Exception;
use Piwik\CacheId;
@@ -456,10 +455,7 @@ public function formatValue($value, $idSite, Formatter $formatter)
case Dimension::TYPE_DURATION_S:
return $formatter->getPrettyTimeFromSeconds($value, $displayAsSentence = false);
case Dimension::TYPE_DURATION_MS:
- $val = number_format($value / 1000, 2);
- if ($val > 60) {
- $val = round($val);
- }
+ $val = round(($value / 1000), ($value / 1000) > 60 ? 0 : 2);
return $formatter->getPrettyTimeFromSeconds($val, $displayAsSentence = true);
case Dimension::TYPE_PERCENT:
return $formatter->getPrettyPercentFromQuotient($value);
diff --git a/app/core/Columns/Discriminator.php b/app/core/Columns/Discriminator.php
index 7f8568498..98a85d20a 100644
--- a/app/core/Columns/Discriminator.php
+++ b/app/core/Columns/Discriminator.php
@@ -9,7 +9,6 @@
namespace Piwik\Columns;
use Exception;
-use Piwik\Plugins\Actions\Actions\ActionSiteSearch;
/**
* @api
diff --git a/app/core/Common.php b/app/core/Common.php
index 90ceda1d4..44d9e2cfd 100644
--- a/app/core/Common.php
+++ b/app/core/Common.php
@@ -13,7 +13,6 @@
use Piwik\Container\StaticContainer;
use Piwik\Intl\Data\Provider\LanguageDataProvider;
use Piwik\Intl\Data\Provider\RegionDataProvider;
-use Piwik\Plugins\UserCountry\LocationProvider\DefaultProvider;
use Piwik\Tracker\Cache as TrackerCache;
/**
@@ -577,6 +576,38 @@ public static function getRequestVar($varName, $varDefault = null, $varType = nu
return $value;
}
+ /**
+ * Replaces lbrace with an encoded entity to prevent angular from parsing the content
+ *
+ * @deprecated Will be removed, once the vue js migration is done
+ *
+ * @param $string
+ * @return array|string|string[]|null
+ */
+ public static function fixLbrace($string)
+ {
+ $chars = array('{', '{', '{', '{', '{', '{');
+
+ static $search;
+ static $replace;
+
+ if (!isset($search)) {
+ $search = array_map(function ($val) { return $val . $val; }, $chars);
+ }
+ if (!isset($replace)) {
+ $replace = array_map(function ($val) { return $val . '' . $val; }, $chars);
+ }
+
+ $replacedString = is_null($string) ? $string : str_replace($search, $replace, $string);
+
+ // try to replace characters until there are no changes
+ if ($string !== $replacedString) {
+ return self::fixLbrace($replacedString);
+ }
+
+ return $string;
+ }
+
/*
* Generating unique strings
*/
@@ -1139,7 +1170,7 @@ public static function getCurrentLocationProviderId()
{
$cache = TrackerCache::getCacheGeneral();
return empty($cache['currentLocationProviderId'])
- ? DefaultProvider::ID
+ ? Plugins\UserCountry\LocationProvider::getDefaultProviderId()
: $cache['currentLocationProviderId'];
}
diff --git a/app/core/Config/Cache.php b/app/core/Config/Cache.php
index 5548c1486..d0b781dea 100644
--- a/app/core/Config/Cache.php
+++ b/app/core/Config/Cache.php
@@ -1,4 +1,5 @@
directory;
- foreach ($hosts as $host)
- {
+ foreach ($hosts as $host) {
$dir = $this->makeCacheDir($host);
if (@is_dir($dir)) {
$this->directory = $dir;
$success = parent::doDelete($id);
if ($success) {
- Piwik::postEvent('Core.configFileDeleted', array($this->getFilename($id)));
+ Piwik::postEvent('Core.configFileDeleted', [$this->getFilename($id)]);
}
}
}
$this->directory = $initialDir;
}
-
}
diff --git a/app/core/Config/GeneralConfig.php b/app/core/Config/GeneralConfig.php
new file mode 100644
index 000000000..89fe39ddb
--- /dev/null
+++ b/app/core/Config/GeneralConfig.php
@@ -0,0 +1,48 @@
+General = $section;
+ }
+
+ public static function getConfigValue($name, $idSite = null)
+ {
+ $config = self::getConfig();
+ if (!empty($idSite)) {
+ $siteSpecificConfig = self::getSiteSpecificConfig($idSite);
+ $config = array_merge($config, $siteSpecificConfig);
+ }
+ return $config[$name] ?? null;
+ }
+
+ private static function getConfig()
+ {
+ return Config::getInstance()->General;
+ }
+
+ private static function getSiteSpecificConfig($idSite)
+ {
+ $key = 'General_' . $idSite;
+ return Config::getInstance()->$key;
+ }
+}
diff --git a/app/core/Config/IniFileChain.php b/app/core/Config/IniFileChain.php
index 2801cbeb2..83d0f7344 100644
--- a/app/core/Config/IniFileChain.php
+++ b/app/core/Config/IniFileChain.php
@@ -1,10 +1,12 @@
reload($defaultSettingsFiles, $userSettingsFile);
}
@@ -71,7 +73,7 @@ public function __construct(array $defaultSettingsFiles = array(), $userSettings
public function &get($name)
{
if (!isset($this->mergedSettings[$name])) {
- $this->mergedSettings[$name] = array();
+ $this->mergedSettings[$name] = [];
}
$result =& $this->mergedSettings[$name];
@@ -146,12 +148,12 @@ public function dumpChanges($header = '')
$dirty = false;
- $configToWrite = array();
+ $configToWrite = [];
foreach ($this->mergedSettings as $sectionName => $changedSection) {
- if(isset($existingMutableSettings[$sectionName])){
+ if (isset($existingMutableSettings[$sectionName])) {
$existingMutableSection = $existingMutableSettings[$sectionName];
- } else{
- $existingMutableSection = array();
+ } else {
+ $existingMutableSection = [];
}
// remove default values from both (they should not get written to local)
@@ -162,7 +164,8 @@ public function dumpChanges($header = '')
// if either local/config have non-default values and the other doesn't,
// OR both have values, but different values, we must write to config.ini.php
- if (empty($changedSection) xor empty($existingMutableSection)
+ if (
+ empty($changedSection) xor empty($existingMutableSection)
|| (!empty($changedSection)
&& !empty($existingMutableSection)
&& self::compareElements($changedSection, $existingMutableSection))
@@ -207,9 +210,10 @@ public function dumpChanges($header = '')
/**
* Reloads settings from disk.
*/
- public function reload($defaultSettingsFiles = array(), $userSettingsFile = null)
+ public function reload($defaultSettingsFiles = [], $userSettingsFile = null)
{
- if (!empty($defaultSettingsFiles)
+ if (
+ !empty($defaultSettingsFiles)
|| !empty($userSettingsFile)
) {
$this->resetSettingsChain($defaultSettingsFiles, $userSettingsFile);
@@ -218,13 +222,15 @@ public function reload($defaultSettingsFiles = array(), $userSettingsFile = null
$hasAbsoluteConfigFile = !empty($userSettingsFile) && strpos($userSettingsFile, DIRECTORY_SEPARATOR) === 0;
$useConfigCache = !empty($GLOBALS['ENABLE_CONFIG_PHP_CACHE']) && $hasAbsoluteConfigFile;
- if ($useConfigCache) {
+ if ($useConfigCache && is_file($userSettingsFile)) {
$cache = new Cache();
$values = $cache->doFetch(self::CONFIG_CACHE_KEY);
-
- if (!empty($values)
+
+ if (
+ !empty($values)
&& isset($values['mergedSettings'])
- && isset($values['settingsChain'][$userSettingsFile])) {
+ && isset($values['settingsChain'][$userSettingsFile])
+ ) {
$this->mergedSettings = $values['mergedSettings'];
$this->settingsChain = $values['settingsChain'];
return;
@@ -253,16 +259,18 @@ public function reload($defaultSettingsFiles = array(), $userSettingsFile = null
if (!empty($GLOBALS['MATOMO_MODIFY_CONFIG_SETTINGS']) && !empty($this->mergedSettings)) {
$this->mergedSettings = call_user_func($GLOBALS['MATOMO_MODIFY_CONFIG_SETTINGS'], $this->mergedSettings);
}
-
- if ($useConfigCache
- && !empty($this->mergedSettings)
- && !empty($this->settingsChain)) {
+ if (
+ $useConfigCache
+ && !empty($this->mergedSettings)
+ && !empty($this->settingsChain)
+ && Cache::hasHostConfig($this->mergedSettings)
+ ) {
$ttlOneHour = 3600;
$cache = new Cache();
if ($cache->isValidHost($this->mergedSettings)) {
// we make sure to save the config only if the host is valid...
- $data = array('mergedSettings' => $this->mergedSettings, 'settingsChain' => $this->settingsChain);
+ $data = ['mergedSettings' => $this->mergedSettings, 'settingsChain' => $this->settingsChain];
$cache->doSave(self::CONFIG_CACHE_KEY, $data, $ttlOneHour);
}
}
@@ -278,7 +286,7 @@ public function deleteConfigCache()
private function copy($merged)
{
- $copy = array();
+ $copy = [];
foreach ($merged as $index => $value) {
if (is_array($value)) {
$copy[$index] = $this->copy($value);
@@ -291,7 +299,7 @@ private function copy($merged)
private function resetSettingsChain($defaultSettingsFiles, $userSettingsFile)
{
- $this->settingsChain = array();
+ $this->settingsChain = [];
if (!empty($defaultSettingsFiles)) {
foreach ($defaultSettingsFiles as $file) {
@@ -308,7 +316,7 @@ protected function mergeFileSettings()
{
$mergedSettings = $this->getMergedDefaultSettings();
- $userSettings = end($this->settingsChain) ?: array();
+ $userSettings = end($this->settingsChain) ?: [];
foreach ($userSettings as $sectionName => $section) {
if (!isset($mergedSettings[$sectionName])) {
$mergedSettings[$sectionName] = $section;
@@ -326,9 +334,10 @@ protected function getMergedDefaultSettings()
{
$userSettingsFile = $this->getUserSettingsFile();
- $mergedSettings = array();
+ $mergedSettings = [];
foreach ($this->settingsChain as $file => $settings) {
- if ($file == $userSettingsFile
+ if (
+ $file == $userSettingsFile
|| empty($settings)
) {
continue;
@@ -396,14 +405,14 @@ public function arrayUnmerge($original, $modified)
// ignore keys that are in $original but not in $modified
if (empty($original) || !is_array($original)) {
- $original = array();
+ $original = [];
}
if (empty($modified) || !is_array($modified)) {
- $modified = array();
+ $modified = [];
}
- return array_udiff_assoc($modified, $original, array(__CLASS__, 'compareElements'));
+ return array_udiff_assoc($modified, $original, [__CLASS__, 'compareElements']);
}
/**
@@ -537,7 +546,7 @@ private function dumpSettings($values, $header)
*
* @param array &$values Config values that will be saved
*/
- Piwik::postEvent('Config.beforeSave', array(&$values));
+ Piwik::postEvent('Config.beforeSave', [&$values]);
$values = $this->encodeValues($values);
$writer = new IniWriter();
diff --git a/app/core/Console.php b/app/core/Console.php
index 945c2dc9a..0d1b99505 100644
--- a/app/core/Console.php
+++ b/app/core/Console.php
@@ -53,6 +53,11 @@ public function __construct(Environment $environment = null)
);
$this->getDefinition()->addOption($option);
+
+ $option = new InputOption('ignore-warn', null, InputOption::VALUE_NONE,
+ 'Return 0 exit code even if there are warning logs or error logs detected in the command output.');
+
+ $this->getDefinition()->addOption($option);
}
public function renderException($e, $output)
@@ -132,7 +137,10 @@ private function doRunImpl(InputInterface $input, OutputInterface $output)
}
$importantLogDetector = StaticContainer::get(FailureLogMessageDetector::class);
- if ($exitCode === 0 && $importantLogDetector->hasEncounteredImportantLog()) {
+ if (!$input->hasParameterOption('--ignore-warn')
+ && $exitCode === 0
+ && $importantLogDetector->hasEncounteredImportantLog()
+ ) {
$output->writeln("Error: error or warning logs detected, exit 1");
$exitCode = 1;
}
diff --git a/app/core/Cookie.php b/app/core/Cookie.php
index ed7d1351a..6ce81416e 100644
--- a/app/core/Cookie.php
+++ b/app/core/Cookie.php
@@ -146,7 +146,10 @@ protected function setCookie($Name, $Value, $Expires, $Path = '', $Domain = '',
}
}
- $Expires = $this->formatExpireTime($Expires);
+ // Format expire time only for non session cookies
+ if (0 !== $Expires) {
+ $Expires = $this->formatExpireTime($Expires);
+ }
$header = 'Set-Cookie: ' . rawurlencode($Name) . '=' . rawurlencode($Value)
. (empty($Expires) ? '' : '; expires=' . $Expires)
diff --git a/app/core/CronArchive.php b/app/core/CronArchive.php
index bbdd8a691..de55cddcc 100644
--- a/app/core/CronArchive.php
+++ b/app/core/CronArchive.php
@@ -23,8 +23,6 @@
use Piwik\CronArchive\SharedSiteIds;
use Piwik\CronArchive\StopArchiverException;
use Piwik\DataAccess\ArchiveSelector;
-use Piwik\DataAccess\ArchiveTableCreator;
-use Piwik\DataAccess\ArchiveWriter;
use Piwik\DataAccess\Model;
use Piwik\DataAccess\RawLogDao;
use Piwik\Exception\UnexpectedWebsiteFoundException;
@@ -162,6 +160,23 @@ class CronArchive
*/
public $maxConcurrentArchivers = false;
+ /**
+ * Maximum number of sites to process during a single execution of the archiver.
+ *
+ * @var int|null
+ */
+ public $maxSitesToProcess = null;
+
+ /**
+ * Maximum number of archives to process during a single execution of the archiver.
+ *
+ * Note that this is not a hard limit as the limit is only checked after all
+ * archives for a site have been processed.
+ *
+ * @var int|null
+ */
+ public $maxArchivesToProcess = null;
+
private $archivingStartingTime;
private $formatter;
@@ -360,6 +375,8 @@ public function run()
$queueConsumer = new QueueConsumer($this->logger, $this->websiteIdArchiveList, $countOfProcesses, $pid,
$this->model, $this->segmentArchiving, $this, $this->cliMultiRequestParser, $this->archiveFilter);
+ $queueConsumer->setMaxSitesToProcess($this->maxSitesToProcess);
+
while (true) {
if ($this->isMaintenanceModeEnabled()) {
$this->logger->info("Archiving will stop now because maintenance mode is enabled");
@@ -389,6 +406,10 @@ public function run()
$successCount = $this->launchArchivingFor($archivesToProcess, $queueConsumer);
$numArchivesFinished += $successCount;
+ if ($this->maxArchivesToProcess && $numArchivesFinished >= $this->maxArchivesToProcess) {
+ $this->logger->info("Maximum number of archives to process per execution has been reached.");
+ break;
+ }
}
$this->disconnectDb();
@@ -474,7 +495,7 @@ private function launchArchivingFor($archives, QueueConsumer $queueConsumer)
foreach ($urls as $index => $url) {
$content = array_key_exists($index, $responses) ? $responses[$index] : null;
- $this->checkResponse($content, $url);
+ $checkInvalid = $this->checkResponse($content, $url);
$stats = json_decode($content, $assoc = true);
if (!is_array($stats)) {
@@ -491,7 +512,10 @@ private function launchArchivingFor($archives, QueueConsumer $queueConsumer)
$visitsForPeriod = $this->getVisitsFromApiResponse($stats);
- $this->logArchiveJobFinished($url, $timers[$index], $visitsForPeriod, $archivesBeingQueried[$index]['plugin'], $archivesBeingQueried[$index]['report']);
+
+ $this->logArchiveJobFinished($url, $timers[$index], $visitsForPeriod,
+ $archivesBeingQueried[$index]['plugin'], $archivesBeingQueried[$index]['report'], !$checkInvalid);
+
$this->deleteInvalidatedArchives($archivesBeingQueried[$index]);
@@ -549,12 +573,14 @@ private function generateUrlToArchiveFromArchiveInfo($archive)
return [$url, $segment, $plugin];
}
- private function logArchiveJobFinished($url, $timer, $visits, $plugin = null, $report = null)
+ private function logArchiveJobFinished($url, $timer, $visits, $plugin = null, $report = null, $wasSkipped = null)
{
$params = UrlHelper::getArrayFromQueryString($url);
$visits = (int) $visits;
- $this->logger->info("Archived website id {$params['idSite']}, period = {$params['period']}, date = "
+ $message = $wasSkipped ? "Skipped Archiving website" : "Archived website";
+
+ $this->logger->info($message." id {$params['idSite']}, period = {$params['period']}, date = "
. "{$params['date']}, segment = '" . (isset($params['segment']) ? urldecode(urldecode($params['segment'])) : '') . "', "
. ($plugin ? "plugin = $plugin, " : "") . ($report ? "report = $report, " : "") . "$visits visits found. $timer");
}
@@ -692,6 +718,12 @@ public function logError($m)
private function logNetworkError($url, $response)
{
+
+ if (preg_match("/Segment (.*?) is not a supported segment/i", $response, $match)) {
+ $this->logger->info($match[0]);
+ return false;
+ }
+
$message = "Got invalid response from API request: $url. ";
if (empty($response)) {
$message .= "The response was empty. This usually means a server error. A solution to this error is generally to increase the value of 'memory_limit' in your php.ini file. ";
@@ -896,6 +928,11 @@ private function invalidateWithSegments($idSites, $date, $period, $_forceInvalid
}
foreach ($this->segmentArchiving->getAllSegmentsToArchive($idSite) as $segmentDefinition) {
+
+ // check if the segment is available
+ if (!$this->isSegmentAvailable($segmentDefinition, [$idSite])) {
+ continue;
+ }
$params = new Parameters(new Site($idSite), $periodObj, new Segment($segmentDefinition, [$idSite], $periodObj->getDateStart(), $periodObj->getDateEnd()));
if ($this->canWeSkipInvalidatingBecauseThereIsAUsablePeriod($params, $doNotIncludeTtlInExistingArchiveCheck)) {
$this->logger->debug(' Found usable archive for {archive}, skipping invalidation.', ['archive' => $params]);
@@ -924,6 +961,24 @@ private function invalidateWithSegments($idSites, $date, $period, $_forceInvalid
}
}
+
+ /**
+ * check if segments that contain dimensions that don't exist anymore
+ * @param $segmentDefinition
+ * @param $idSites
+ * @return bool
+ */
+ protected function isSegmentAvailable($segmentDefinition, $idSites)
+ {
+ try {
+ new Segment($segmentDefinition, $idSites);
+ } catch (\Exception $e) {
+ $this->logger->info("Segment '".$segmentDefinition."' is not a supported segment");
+ return false;
+ }
+ return true;
+ }
+
/**
* Returns true if there is an existing valid period we can use, or false if there isn't and the invalidation should go through.
*
@@ -1115,11 +1170,18 @@ private function logArchiveTimeoutInfo()
}
}
+ if ($this->maxSitesToProcess) {
+ $this->logger->info("- Maximum {$this->maxSitesToProcess} websites will be processed.");
+ }
+ if ($this->maxArchivesToProcess) {
+ $this->logger->info("- Maximum {$this->maxArchivesToProcess} archives will be processed (soft limit).");
+ }
+
// Try and not request older data we know is already archived
if ($this->lastSuccessRunTimestamp !== false) {
$dateLast = time() - $this->lastSuccessRunTimestamp;
$this->logger->info("- Archiving was last executed without error "
- . $this->formatter->getPrettyTimeFromSeconds($dateLast, true) . " ago");
+ . $this->formatter->getPrettyTimeFromSeconds($dateLast, true) . " ago.");
}
}
diff --git a/app/core/CronArchive/QueueConsumer.php b/app/core/CronArchive/QueueConsumer.php
index e527ac0e7..7e920fa6b 100644
--- a/app/core/CronArchive/QueueConsumer.php
+++ b/app/core/CronArchive/QueueConsumer.php
@@ -14,18 +14,14 @@
use Piwik\ArchiveProcessor\Parameters;
use Piwik\ArchiveProcessor\Rules;
use Piwik\CliMulti\RequestParser;
-use Piwik\Common;
use Piwik\CronArchive;
use Piwik\DataAccess\ArchiveSelector;
use Piwik\DataAccess\Model;
use Piwik\Date;
-use Piwik\Db;
-use Piwik\Exception\UnexpectedWebsiteFoundException;
use Piwik\Period;
use Piwik\Period\Factory as PeriodFactory;
use Piwik\Piwik;
use Piwik\Plugin\Manager;
-use Piwik\Plugins\SitesManager\API;
use Piwik\Segment;
use Piwik\Site;
use Piwik\Timer;
@@ -108,6 +104,11 @@ class QueueConsumer
*/
private $currentSiteArchivingStartTime;
+ /**
+ * @var int|null
+ */
+ private $maxSitesToProcess = null;
+
private $processedSiteCount = 0;
public function __construct(LoggerInterface $logger, $websiteIdArchiveList, $countOfProcesses, $pid, Model $model,
@@ -131,9 +132,22 @@ public function __construct(LoggerInterface $logger, $websiteIdArchiveList, $cou
$this->periodIdsToLabels = array_flip(Piwik::$idPeriods);
}
+ /**
+ * Get next archives to process.
+ *
+ * Returns either an array of archives to process for the current site (may be
+ * empty if there are no more archives to process for it) or null when there are
+ * no more sites to process.
+ *
+ * @return null|array
+ */
public function getNextArchivesToProcess()
{
if (empty($this->idSite)) {
+ if ($this->maxSitesToProcess && $this->processedSiteCount >= $this->maxSitesToProcess) {
+ $this->logger->info("Maximum number of sites to process per execution has been reached.");
+ return null;
+ }
$this->idSite = $this->getNextIdSiteToArchive();
if (empty($this->idSite)) { // no sites left to archive, stop
$this->logger->debug("No more sites left to archive, stopping.");
@@ -617,4 +631,19 @@ public function getIdSite()
{
return $this->idSite;
}
+
+ /**
+ * Set or get the maximum number of sites to process
+ *
+ * @param int|null $newValue New value or null to just return current value
+ *
+ * @return int|null New or existing value
+ */
+ public function setMaxSitesToProcess($newValue = null)
+ {
+ if (null !== $newValue) {
+ $this->maxSitesToProcess = $newValue;
+ }
+ return $this->maxSitesToProcess;
+ }
}
diff --git a/app/core/CronArchive/SegmentArchiving.php b/app/core/CronArchive/SegmentArchiving.php
index 1464eeb29..f7dc4636e 100644
--- a/app/core/CronArchive/SegmentArchiving.php
+++ b/app/core/CronArchive/SegmentArchiving.php
@@ -14,7 +14,6 @@
use Piwik\ArchiveProcessor\Rules;
use Piwik\Common;
use Piwik\Container\StaticContainer;
-use Piwik\CronArchive;
use Piwik\Date;
use Piwik\Db;
use Piwik\Period\Range;
diff --git a/app/core/DataAccess/ArchiveSelector.php b/app/core/DataAccess/ArchiveSelector.php
index c0a19a603..721163804 100644
--- a/app/core/DataAccess/ArchiveSelector.php
+++ b/app/core/DataAccess/ArchiveSelector.php
@@ -20,7 +20,6 @@
use Piwik\Period;
use Piwik\Period\Range;
use Piwik\Segment;
-use Piwik\SettingsServer;
use Psr\Log\LoggerInterface;
/**
diff --git a/app/core/DataAccess/ArchivingDbAdapter.php b/app/core/DataAccess/ArchivingDbAdapter.php
index 660268c27..6483869a0 100644
--- a/app/core/DataAccess/ArchivingDbAdapter.php
+++ b/app/core/DataAccess/ArchivingDbAdapter.php
@@ -13,6 +13,7 @@
use Piwik\Db\AdapterInterface;
use Piwik\DbHelper;
use Psr\Log\LoggerInterface;
+use Exception;
class ArchivingDbAdapter
{
@@ -48,7 +49,7 @@ public function exec($sql)
$sql = DbHelper::addMaxExecutionTimeHintToQuery($sql, $this->maxExecutionTime);
$this->logSql($sql);
- return call_user_func_array([$this->wrapped, __FUNCTION__], func_get_args());
+ return call_user_func_array([$this, "callFunction"], array_merge([__FUNCTION__], func_get_args()));
}
public function query($sql)
@@ -56,7 +57,7 @@ public function query($sql)
$sql = DbHelper::addMaxExecutionTimeHintToQuery($sql, $this->maxExecutionTime);
$this->logSql($sql);
- return call_user_func_array([$this->wrapped, __FUNCTION__], func_get_args());
+ return call_user_func_array([$this, "callFunction"], array_merge([__FUNCTION__], func_get_args()));
}
public function fetchAll($sql)
@@ -64,7 +65,7 @@ public function fetchAll($sql)
$sql = DbHelper::addMaxExecutionTimeHintToQuery($sql, $this->maxExecutionTime);
$this->logSql($sql);
- return call_user_func_array([$this->wrapped, __FUNCTION__], func_get_args());
+ return call_user_func_array([$this, "callFunction"], array_merge([__FUNCTION__], func_get_args()));
}
public function fetchRow($sql)
@@ -72,7 +73,7 @@ public function fetchRow($sql)
$sql = DbHelper::addMaxExecutionTimeHintToQuery($sql, $this->maxExecutionTime);
$this->logSql($sql);
- return call_user_func_array([$this->wrapped, __FUNCTION__], func_get_args());
+ return call_user_func_array([$this, "callFunction"], array_merge([__FUNCTION__], func_get_args()));
}
public function fetchOne($sql)
@@ -80,7 +81,7 @@ public function fetchOne($sql)
$sql = DbHelper::addMaxExecutionTimeHintToQuery($sql, $this->maxExecutionTime);
$this->logSql($sql);
- return call_user_func_array([$this->wrapped, __FUNCTION__], func_get_args());
+ return call_user_func_array([$this, "callFunction"], array_merge([__FUNCTION__], func_get_args()));
}
public function fetchAssoc($sql)
@@ -88,7 +89,19 @@ public function fetchAssoc($sql)
$sql = DbHelper::addMaxExecutionTimeHintToQuery($sql, $this->maxExecutionTime);
$this->logSql($sql);
- return call_user_func_array([$this->wrapped, __FUNCTION__], func_get_args());
+ return call_user_func_array([$this, "callFunction"], array_merge([__FUNCTION__], func_get_args()));
+ }
+
+ /**
+ * Test error number
+ *
+ * @param Exception $e
+ * @param string $errno
+ * @return bool
+ */
+ public function isErrNo($e, $errno)
+ {
+ return $this->wrapped->isErrNo($e, $errno);
}
private function logSql($sql)
@@ -98,4 +111,25 @@ private function logSql($sql)
$this->logger->debug($sql);
}
}
+
+ private function callFunction($function) {
+
+ $args = func_get_args();
+ unset($args[0]);
+
+ try {
+ return call_user_func_array([$this->wrapped, $function], $args);
+ } catch (\Exception $e) {
+ if ($this->isErrNo($e, \Piwik\Updater\Migration\Db::ERROR_CODE_MAX_EXECUTION_TIME_EXCEEDED_QUERY_INTERRUPTED) ||
+ $this->isErrNo($e, \Piwik\Updater\Migration\Db::ERROR_CODE_MAX_EXECUTION_TIME_EXCEEDED_SORT_ABORTED)
+ )
+ {
+ $this->logger->warning('Archiver query exceeded maximum execution time: {details}',
+ ['details' => json_encode($args, true)]);
+
+ }
+ throw $e;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/app/core/DataAccess/LogAggregator.php b/app/core/DataAccess/LogAggregator.php
index e283af269..cada4b157 100644
--- a/app/core/DataAccess/LogAggregator.php
+++ b/app/core/DataAccess/LogAggregator.php
@@ -282,8 +282,7 @@ private function createTemporaryTable($unprefixedSegmentTableName, $segmentSelec
if (defined('PIWIK_TEST_MODE') && PIWIK_TEST_MODE) {
$engine = 'ENGINE=MEMORY';
}
- $tempTableIdVisitColumn = 'idvisit BIGINT(10) UNSIGNED NOT NULL';
- $createTableSql = 'CREATE TEMPORARY TABLE ' . $table . ' (' . $tempTableIdVisitColumn . ') ' . $engine;
+ $createTableSql = 'CREATE TEMPORARY TABLE ' . $table . ' (idvisit BIGINT(10) UNSIGNED NOT NULL, PRIMARY KEY (`idvisit`)) ' . $engine;
// we do not insert the data right away using create temporary table ... select ...
// to avoid metadata lock see eg https://www.percona.com/blog/2018/01/10/why-avoid-create-table-as-select-statement/
@@ -293,23 +292,7 @@ private function createTemporaryTable($unprefixedSegmentTableName, $segmentSelec
} catch (\Exception $e) {
if ($readerDb->isErrNo($e, \Piwik\Updater\Migration\Db::ERROR_CODE_TABLE_EXISTS)) {
return;
- } elseif ($readerDb->isErrNo($e, \Piwik\Updater\Migration\Db::ERROR_CODE_REQUIRES_PRIMARY_KEY)
- || $readerDb->isErrNo($e, \Piwik\Updater\Migration\Db::ERROR_CODE_UNABLE_CREATE_TABLE_WITHOUT_PRIMARY_KEY
- || stripos($e->getMessage(), 'requires a primary key') !== false
- || stripos($e->getMessage(), 'table without a primary key') !== false)
- ) {
- $createTableSql = str_replace($tempTableIdVisitColumn, $tempTableIdVisitColumn . ', PRIMARY KEY (`idvisit`)', $createTableSql);
-
- try {
- $readerDb->query($createTableSql);
- } catch (\Exception $e) {
- if ($readerDb->isErrNo($e, \Piwik\Updater\Migration\Db::ERROR_CODE_TABLE_EXISTS)) {
- return;
- } else {
- throw $e;
- }
- }
- } else {
+ } else {
throw $e;
}
}
diff --git a/app/core/DataAccess/Model.php b/app/core/DataAccess/Model.php
index e6e821e1a..4d2199ce2 100644
--- a/app/core/DataAccess/Model.php
+++ b/app/core/DataAccess/Model.php
@@ -82,7 +82,7 @@ public function getInvalidatedArchiveIdsSafeToDelete($archiveTable, $setGroupCon
break;
}
- list($idarchive, $value) = explode('.', $pair);
+ [$idarchive, $value] = explode('.', $pair);
array_shift($duplicateArchives);
@@ -99,7 +99,7 @@ public function getInvalidatedArchiveIdsSafeToDelete($archiveTable, $setGroupCon
break;
}
- list($idarchive, $value) = explode('.', $pair);
+ [$idarchive, $value] = explode('.', $pair);
$archiveIds[] = $idarchive; // does not matter what the value is, the latest is usable so older archives can be purged
}
}
@@ -157,7 +157,7 @@ public function updateArchiveAsInvalidated($archiveTable, $idSites, $allPeriodsT
if (!empty($name)) {
if (strpos($name, '.') !== false) {
- list($plugin, $name) = explode('.', $name, 2);
+ [$plugin, $name] = explode('.', $name, 2);
} else {
$plugin = $name;
$name = null;
@@ -512,7 +512,14 @@ public function allocateNewArchiveId($numericTable)
$idarchive = $sequence->getNextId();
} catch (Exception $e) {
// edge case: sequence was not found, create it now
- $sequence->create();
+ try {
+ $sequence->create();
+ } catch (Exception $ex) {
+ // Ignore duplicate entry error, as that means another request might have already created the sequence
+ if (!Db::get()->isErrNo($ex, \Piwik\Updater\Migration\Db::ERROR_CODE_DUPLICATE_ENTRY)) {
+ throw $ex;
+ }
+ }
$idarchive = $sequence->getNextId();
}
diff --git a/app/core/DataTable.php b/app/core/DataTable.php
index 8b9291a78..62ebc6db1 100644
--- a/app/core/DataTable.php
+++ b/app/core/DataTable.php
@@ -11,7 +11,6 @@
use Closure;
use Exception;
-use Piwik\Archive\DataTableFactory;
use Piwik\DataTable\DataTableInterface;
use Piwik\DataTable\Manager;
use Piwik\DataTable\Renderer\Html;
diff --git a/app/core/DataTable/Map.php b/app/core/DataTable/Map.php
index 8700d8822..351cb4d05 100644
--- a/app/core/DataTable/Map.php
+++ b/app/core/DataTable/Map.php
@@ -11,7 +11,6 @@
use Closure;
use Piwik\Common;
use Piwik\DataTable;
-use Piwik\DataTable\Renderer\Console;
use Piwik\DataTable\Renderer\Html;
/**
diff --git a/app/core/DataTable/Renderer/Xml.php b/app/core/DataTable/Renderer/Xml.php
index 879c814d0..daac72865 100644
--- a/app/core/DataTable/Renderer/Xml.php
+++ b/app/core/DataTable/Renderer/Xml.php
@@ -179,7 +179,7 @@ private function renderArray($array, $prefixLines)
} else {
$xmlValue = self::formatValueXml($value);
- if (strlen($xmlValue) != 0) {
+ if (strlen(strval($xmlValue)) !== 0) {
$result .= $prefixLines . $prefix . $xmlValue . $suffix . "\n";
} else {
$result .= $prefixLines . $emptyNode . "\n";
diff --git a/app/core/DataTable/Row.php b/app/core/DataTable/Row.php
index bfa1a4966..878c1a61c 100644
--- a/app/core/DataTable/Row.php
+++ b/app/core/DataTable/Row.php
@@ -12,7 +12,6 @@
use Piwik\Container\StaticContainer;
use Piwik\DataTable;
use Piwik\Date;
-use Piwik\Log;
use Piwik\Metrics;
use Piwik\Period;
use Psr\Log\LoggerInterface;
@@ -36,7 +35,8 @@ class Row extends \ArrayObject
*/
private static $unsummableColumns = array(
'label' => true,
- 'full_url' => true // column used w/ old Piwik versions,
+ 'full_url' => true, // column used w/ old Piwik versions,
+ 'ts_archived' => true // date column used in metadata for proportional tooltips
);
// @see sumRow - implementation detail
@@ -677,6 +677,9 @@ protected function sumRowArray($thisColumnValue, $columnToSumValue, $columnName
if (is_array($columnToSumValue)) {
$newValue = $thisColumnValue;
foreach ($columnToSumValue as $arrayIndex => $arrayValue) {
+ if (!is_numeric($arrayIndex) && !$this->isSummableColumn($arrayIndex)) {
+ continue;
+ }
if (!isset($newValue[$arrayIndex])) {
$newValue[$arrayIndex] = false;
}
diff --git a/app/core/Date.php b/app/core/Date.php
index a214751b8..6c5b4d785 100644
--- a/app/core/Date.php
+++ b/app/core/Date.php
@@ -889,6 +889,10 @@ protected function formatToken($token)
case "ss":
case "s":
return $this->toString('s');
+ // would normally also include AM, PM, Noon and Midnight
+ case "b":
+ // would normally be a textual presentation like "in the afternoon"
+ case "B":
// am / pm
case "a":
return $this->toString('a') == 'am' ? $translator->translate('Intl_Time_AM') : $translator->translate('Intl_Time_PM');
@@ -911,7 +915,7 @@ protected function formatToken($token)
}
protected static $tokens = array(
- 'G', 'y', 'M', 'L', 'd', 'h', 'H', 'k', 'K', 'm', 's', 'E', 'c', 'e', 'D', 'F', 'w', 'W', 'a', 'z', 'Z', 'v',
+ 'G', 'y', 'M', 'L', 'd', 'h', 'H', 'k', 'K', 'm', 's', 'E', 'c', 'e', 'D', 'F', 'w', 'W', 'a', 'b', 'B', 'z', 'Z', 'v',
);
/**
diff --git a/app/core/Db.php b/app/core/Db.php
index 23d0a493b..b047d1d8f 100644
--- a/app/core/Db.php
+++ b/app/core/Db.php
@@ -9,7 +9,6 @@
namespace Piwik;
use Exception;
-use Piwik\DataAccess\TableMetadata;
use Piwik\Db\Adapter;
/**
@@ -40,6 +39,8 @@ class Db
private static $logQueries = true;
+ // this is used for indicate TransactionLevel Cache
+ public $supportsUncommitted;
/**
* Returns the database connection and creates it if it hasn't been already.
*
diff --git a/app/core/Db/Adapter/Mysqli.php b/app/core/Db/Adapter/Mysqli.php
index 87f91ac32..a46236c57 100644
--- a/app/core/Db/Adapter/Mysqli.php
+++ b/app/core/Db/Adapter/Mysqli.php
@@ -25,6 +25,10 @@ class Mysqli extends Zend_Db_Adapter_Mysqli implements AdapterInterface
*
* @param array|Zend_Config $config database configuration
*/
+
+ // this is used for indicate TransactionLevel Cache
+ public $supportsUncommitted;
+
public function __construct($config)
{
// Enable LOAD DATA INFILE
diff --git a/app/core/Db/Adapter/Pdo/Mysql.php b/app/core/Db/Adapter/Pdo/Mysql.php
index 1170afe3f..adbdaa690 100644
--- a/app/core/Db/Adapter/Pdo/Mysql.php
+++ b/app/core/Db/Adapter/Pdo/Mysql.php
@@ -29,6 +29,10 @@ class Mysql extends Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
*
* @param array|Zend_Config $config database configuration
*/
+
+ // this is used for indicate TransactionLevel Cache
+ public $supportsUncommitted;
+
public function __construct($config)
{
// Enable LOAD DATA INFILE
diff --git a/app/core/Db/Schema/Mysql.php b/app/core/Db/Schema/Mysql.php
index 92d2b882f..fcf943bbd 100644
--- a/app/core/Db/Schema/Mysql.php
+++ b/app/core/Db/Schema/Mysql.php
@@ -52,6 +52,7 @@ public function getTablesCreateSql()
superuser_access TINYINT(2) unsigned NOT NULL DEFAULT '0',
date_registered TIMESTAMP NULL,
ts_password_modified TIMESTAMP NULL,
+ idchange_last_viewed TIMESTAMP NULL,
PRIMARY KEY(login)
) ENGINE=$engine DEFAULT CHARSET=$charset
",
@@ -190,7 +191,7 @@ public function getTablesCreateSql()
PRIMARY KEY(idvisit),
INDEX index_idsite_config_datetime (idsite, config_id, visit_last_action_time),
INDEX index_idsite_datetime (idsite, visit_last_action_time),
- INDEX index_idsite_idvisitor (idsite, idvisitor)
+ INDEX index_idsite_idvisitor (idsite, idvisitor, visit_last_action_time DESC)
) ENGINE=$engine DEFAULT CHARSET=$charset
",
@@ -358,6 +359,19 @@ public function getTablesCreateSql()
PRIMARY KEY (`key`)
) ENGINE=$engine DEFAULT CHARSET=$charset
",
+ 'changes' => "CREATE TABLE `{$prefixTables}changes` (
+ `idchange` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
+ `created_time` DATETIME NOT NULL,
+ `plugin_name` VARCHAR(60) NOT NULL,
+ `version` VARCHAR(20) NOT NULL,
+ `title` VARCHAR(255) NOT NULL,
+ `description` TEXT NULL,
+ `link_name` VARCHAR(255) NULL,
+ `link` VARCHAR(255) NULL,
+ PRIMARY KEY(`idchange`),
+ UNIQUE KEY unique_plugin_version_title (`plugin_name`, `version`, `title`(100))
+ ) ENGINE=$engine DEFAULT CHARSET=$charset
+ ",
);
return $tables;
@@ -574,8 +588,9 @@ public function createAnonymousUser()
// note that the token_auth value is anonymous, which is assigned by default as well in the Login plugin
$db = $this->getDb();
$db->query("INSERT IGNORE INTO " . Common::prefixTable("user") . "
- (`login`, `password`, `email`, `twofactor_secret`, `superuser_access`, `date_registered`, `ts_password_modified`)
- VALUES ( 'anonymous', '', 'anonymous@example.org', '', 0, '$now', '$now' );");
+ (`login`, `password`, `email`, `twofactor_secret`, `superuser_access`, `date_registered`, `ts_password_modified`,
+ `idchange_last_viewed`)
+ VALUES ( 'anonymous', '', 'anonymous@example.org', '', 0, '$now', '$now' , NULL);");
$model = new Model();
$model->addTokenAuth('anonymous', 'anonymous', 'anonymous default token', $now);
diff --git a/app/core/Db/TransactionLevel.php b/app/core/Db/TransactionLevel.php
index c19699084..f087f4adc 100644
--- a/app/core/Db/TransactionLevel.php
+++ b/app/core/Db/TransactionLevel.php
@@ -40,12 +40,18 @@ public function canLikelySetTransactionLevel()
public function setUncommitted()
{
+ if ($this->db->supportsUncommitted === false) {
+ // we know "Uncommitted" transaction level is not supported, we don't need to do anything as it won't work to set the status
+ return false;
+ }
+
try {
$backup = $this->db->fetchOne('SELECT @@TX_ISOLATION');
} catch (\Exception $e) {
try {
$backup = $this->db->fetchOne('SELECT @@transaction_isolation');
} catch (\Exception $e) {
+ $this->db->supportsUncommitted = false;
return false;
}
}
@@ -54,9 +60,17 @@ public function setUncommitted()
$this->db->query('SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED');
$this->statusBackup = $backup;
- Option::set(self::TEST_OPTION_NAME, '1'); // try setting something w/ the new transaction isolation level
+ if ($this->db->supportsUncommitted === null) {
+ // the first time we need to check if the transaction level actually works by
+ // trying to set something w/ the new transaction isolation level
+ Option::set(self::TEST_OPTION_NAME, '1');
+ }
+
+ $this->db->supportsUncommitted = true;
} catch (\Exception $e) {
+ // setting the transaction level status did not work
// catch eg 1665 Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = STATEMENT and at least one table uses a storage engine limited to row-based logging. InnoDB is limited to row-logging when transaction isolation level is READ COMMITTED or READ UNCOMMITTED
+ $this->db->supportsUncommitted = false;
$this->restorePreviousStatus();
return false;
}
@@ -77,7 +91,5 @@ public function restorePreviousStatus()
$this->db->query('SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ');
}
}
-
}
-
}
diff --git a/app/core/DeviceDetector/DeviceDetectorFactory.php b/app/core/DeviceDetector/DeviceDetectorFactory.php
index 83931aaa1..bc81a74a5 100644
--- a/app/core/DeviceDetector/DeviceDetectorFactory.php
+++ b/app/core/DeviceDetector/DeviceDetectorFactory.php
@@ -9,7 +9,6 @@
namespace Piwik\DeviceDetector;
use DeviceDetector\DeviceDetector;
-use Piwik\Common;
use Piwik\Container\StaticContainer;
class DeviceDetectorFactory
diff --git a/app/core/Exception/NotYetInstalledException.php b/app/core/Exception/NotYetInstalledException.php
index c1635f505..a8ebbb7d8 100644
--- a/app/core/Exception/NotYetInstalledException.php
+++ b/app/core/Exception/NotYetInstalledException.php
@@ -8,8 +8,6 @@
*/
namespace Piwik\Exception;
-use Piwik\Common;
-use Piwik\Url;
use Throwable;
class NotYetInstalledException extends InvalidRequestParameterException
diff --git a/app/core/ExceptionHandler.php b/app/core/ExceptionHandler.php
index a6af86354..ca549622b 100644
--- a/app/core/ExceptionHandler.php
+++ b/app/core/ExceptionHandler.php
@@ -1,4 +1,5 @@
getMessage();
@@ -118,11 +120,9 @@ private static function getErrorResponse($ex)
$isHtmlMessage = method_exists($ex, 'isHtmlMessage') && $ex->isHtmlMessage();
if (!$isHtmlMessage && Request::isApiRequest($_GET)) {
-
$outputFormat = strtolower(Common::getRequestVar('format', 'xml', 'string', $_GET + $_POST));
$response = new ResponseBuilder($outputFormat);
return $response->getResponseException($ex);
-
} elseif (!$isHtmlMessage) {
$message = Common::sanitizeInputValue($message);
}
@@ -146,7 +146,24 @@ private static function getErrorResponse($ex)
}
}
- $result = Piwik_GetErrorMessagePage($message, $debugTrace, true, true, $logoHeaderUrl, $logoFaviconUrl);
+ // Unsupported browser errors shouldn't be written to the web server log. At DEBUG logging level this error will
+ // be written to the application log instead
+ $writeErrorLog = !($ex instanceof \Piwik\Exception\NotSupportedBrowserException);
+
+ $hostname = Url::getRFCValidHostname();
+ $hostStr = $hostname ? "[$hostname] " : '- ';
+
+ $result = Piwik_GetErrorMessagePage(
+ $message,
+ $debugTrace,
+ true,
+ true,
+ $logoHeaderUrl,
+ $logoFaviconUrl,
+ null,
+ $hostStr,
+ $writeErrorLog
+ );
try {
/**
@@ -158,7 +175,7 @@ private static function getErrorResponse($ex)
* @param string &$result The HTML of the error page.
* @param Exception $ex The Exception displayed in the error page.
*/
- Piwik::postEvent('FrontController.modifyErrorPage', array(&$result, $ex));
+ Piwik::postEvent('FrontController.modifyErrorPage', [&$result, $ex]);
} catch (ContainerDoesNotExistException $ex) {
// this can happen when an error occurs before the Piwik environment is created
}
@@ -166,17 +183,17 @@ private static function getErrorResponse($ex)
return $result;
}
- private static function logException($exception, $loglevel=Log::ERROR)
+ private static function logException($exception, $loglevel = Log::ERROR)
{
try {
switch ($loglevel) {
- case(Log::DEBUG):
+ case (Log::DEBUG):
StaticContainer::get(LoggerInterface::class)->debug('Uncaught exception: {exception}', [
'exception' => $exception,
'ignoreInScreenWriter' => true,
]);
break;
- case(Log::ERROR):
+ case (Log::ERROR):
default:
StaticContainer::get(LoggerInterface::class)->error('Uncaught exception: {exception}', [
'exception' => $exception,
diff --git a/app/core/Filechecks.php b/app/core/Filechecks.php
index 1c0fc049e..b37b52a58 100644
--- a/app/core/Filechecks.php
+++ b/app/core/Filechecks.php
@@ -107,9 +107,13 @@ public static function getAutoUpdateMakeWritableMessage()
{
$realpath = Filesystem::realpath(PIWIK_INCLUDE_PATH . '/');
$message = '';
- $message .= "" . self::getCommandToChangeOwnerOfPiwikFiles() . "
";
+ if (!SettingsServer::isWindows()) {
+ $message .= "" . self::getCommandToChangeOwnerOfPiwikFiles() . "
";
+ }
$message .= self::getMakeWritableCommand($realpath);
- $message .= 'chmod 755 '.$realpath.'/console
';
+ if (!SettingsServer::isWindows()) {
+ $message .= 'chmod 755 ' . $realpath . '/console
';
+ }
$message .= 'After you execute these commands (or change permissions via your FTP software), refresh the page and you should be able to use the "Automatic Update" feature.';
return $message;
}
diff --git a/app/core/Filesystem.php b/app/core/Filesystem.php
index ff7942190..5b8101291 100644
--- a/app/core/Filesystem.php
+++ b/app/core/Filesystem.php
@@ -294,8 +294,17 @@ public static function sortFilesDescByPathLength($files)
*/
public static function directoryDiff($source, $target)
{
- $sourceFiles = self::globr($source, '*');
- $targetFiles = self::globr($target, '*');
+ $flags = 0;
+ $pattern = '*';
+
+ if (defined('GLOB_BRACE')) {
+ // The GLOB_BRACE flag is not available on some non GNU systems, like Solaris or Alpine Linux.
+ $flags = GLOB_BRACE;
+ $pattern = '{,.}*[!.]*'; // matches all files and folders, including those starting with ".", but excludes "." and ".."
+ }
+
+ $sourceFiles = self::globr($source, $pattern, $flags);
+ $targetFiles = self::globr($target, $pattern, $flags);
$sourceFiles = array_map(function ($file) use ($source) {
return str_replace($source, '', $file);
@@ -305,7 +314,11 @@ public static function directoryDiff($source, $target)
return str_replace($target, '', $file);
}, $targetFiles);
- $diff = array_diff($targetFiles, $sourceFiles);
+ if (FileSystem::isFileSystemCaseInsensitive()) {
+ $diff = array_udiff($targetFiles, $sourceFiles, 'strcasecmp');
+ } else {
+ $diff = array_diff($targetFiles, $sourceFiles);
+ }
return array_values($diff);
}
@@ -548,6 +561,23 @@ private static function isPathWithinTmpFolder($path)
return $isPathWithinTmpFolder;
}
+ /**
+ * Check if the filesystem is case sensitive by writing a temporary file
+ *
+ * @return bool
+ */
+ public static function isFileSystemCaseInsensitive() : bool
+ {
+ $testFileName = 'caseSensitivityTest.txt';
+ $pathTmp = StaticContainer::get('path.tmp');
+ @file_put_contents($pathTmp.'/'.$testFileName, 'Nothing to see here.');
+ if (\file_exists($pathTmp.'/'.strtolower($testFileName))) {
+ // Wrote caseSensitivityTest.txt but casesensitivitytest.txt exists, so case insensitive
+ return true;
+ }
+ return false;
+ }
+
/**
* in tmp/ (sub-)folder(s) we create empty index.htm|php files
*
diff --git a/app/core/FrontController.php b/app/core/FrontController.php
index 448abb5b7..3227ffa33 100644
--- a/app/core/FrontController.php
+++ b/app/core/FrontController.php
@@ -11,6 +11,7 @@
use Exception;
use Piwik\API\Request;
+use Piwik\Config\GeneralConfig;
use Piwik\Container\StaticContainer;
use Piwik\DataTable\Manager;
use Piwik\Exception\AuthenticationFailedException;
@@ -396,6 +397,11 @@ public function init()
$loggedIn = false;
+ //move this up unsupported Browser do not create session
+ if ($this->isSupportedBrowserCheckNeeded()) {
+ SupportedBrowser::checkIfBrowserSupported();
+ }
+
// don't use sessionauth in cli mode
// try authenticating w/ session first...
$sessionAuth = $this->makeSessionAuthenticator();
@@ -423,9 +429,7 @@ public function init()
$this->makeAuthenticator($sessionAuth); // Piwik\Auth must be set to the correct Login plugin
}
- if ($this->isSupportedBrowserCheckNeeded()) {
- SupportedBrowser::checkIfBrowserSupported();
- }
+
// Force the auth to use the token_auth if specified, so that embed dashboard
// and all other non widgetized controller methods works fine
@@ -457,6 +461,10 @@ protected function prepareDispatch($module, $action, $parameters)
if (is_null($action)) {
$action = Common::getRequestVar('action', false);
+ if ($action !== false) {
+ // If a value was provided, check it has the correct type.
+ $action = Common::getRequestVar('action', null, 'string');
+ }
}
if (Session::isSessionStarted()) {
@@ -486,10 +494,14 @@ protected function prepareDispatch($module, $action, $parameters)
protected function handleMaintenanceMode()
{
- if ((Config::getInstance()->General['maintenance_mode'] != 1) || Common::isPhpCliMode()) {
+ if ((GeneralConfig::getConfigValue('maintenance_mode') != 1) || Common::isPhpCliMode() ) {
return;
}
- Common::sendResponseCode(503);
+
+ // as request matomo behind load balancer should not return 503. https://github.com/matomo-org/matomo/issues/18054
+ if (GeneralConfig::getConfigValue('multi_server_environment') != 1) {
+ Common::sendResponseCode(503);
+ }
$logoUrl = 'plugins/Morpheus/images/logo.svg';
$faviconUrl = 'plugins/CoreHome/images/favicon.png';
diff --git a/app/core/Http.php b/app/core/Http.php
index 500cfe8e4..ae9b0b411 100644
--- a/app/core/Http.php
+++ b/app/core/Http.php
@@ -226,7 +226,7 @@ public static function sendHttpRequestBy(
$isBlocked = false;
foreach ($disallowedHosts as $host) {
- if (preg_match(self::convertWildcardToPattern($host), $parsedUrl['host']) === 1) {
+ if (!empty($parsedUrl['host']) && preg_match(self::convertWildcardToPattern($host), $parsedUrl['host']) === 1) {
$isBlocked = true;
break;
}
diff --git a/app/core/Http/ControllerResolver.php b/app/core/Http/ControllerResolver.php
index 82b289132..b518b38a0 100644
--- a/app/core/Http/ControllerResolver.php
+++ b/app/core/Http/ControllerResolver.php
@@ -10,7 +10,6 @@
use DI\FactoryInterface;
use Exception;
-use Piwik\Plugin\Controller;
use Piwik\Plugin\ReportsProvider;
use Piwik\Plugin\WidgetsProvider;
diff --git a/app/core/Mail/Transport.php b/app/core/Mail/Transport.php
index edf6b1375..e88440b0a 100644
--- a/app/core/Mail/Transport.php
+++ b/app/core/Mail/Transport.php
@@ -15,7 +15,6 @@
use Piwik\Container\StaticContainer;
use Piwik\Mail;
use Piwik\Piwik;
-use Piwik\Version;
class Transport
{
diff --git a/app/core/Menu/MenuAbstract.php b/app/core/Menu/MenuAbstract.php
index 2783d7f48..5a276dce2 100644
--- a/app/core/Menu/MenuAbstract.php
+++ b/app/core/Menu/MenuAbstract.php
@@ -98,10 +98,11 @@ protected function getAllMenus()
* @param bool|string $tooltip An optional tooltip to display or false to display the tooltip.
* @param bool|string $icon An icon classname, such as "icon-add". Only supported by admin menu
* @param bool|string $onclick Will execute the on click handler instead of executing the link. Only supported by admin menu.
+ * @param string $attribute Will add this string as a link attribute.
* @since 2.7.0
* @api
*/
- public function addItem($menuName, $subMenuName, $url, $order = 50, $tooltip = false, $icon = false, $onclick = false)
+ public function addItem($menuName, $subMenuName, $url, $order = 50, $tooltip = false, $icon = false, $onclick = false, $attribute = false)
{
// make sure the idSite value used is numeric (hack-y fix for #3426)
if (isset($url['idSite']) && !is_numeric($url['idSite'])) {
@@ -116,7 +117,8 @@ public function addItem($menuName, $subMenuName, $url, $order = 50, $tooltip = f
$order,
$tooltip,
$icon,
- $onclick
+ $onclick,
+ $attribute
);
}
@@ -144,7 +146,7 @@ public function remove($menuName, $subMenuName = false)
* @param int $order
* @param bool|string $tooltip Tooltip to display.
*/
- private function buildMenuItem($menuName, $subMenuName, $url, $order = 50, $tooltip = false, $icon = false, $onclick = false)
+ private function buildMenuItem($menuName, $subMenuName, $url, $order = 50, $tooltip = false, $icon = false, $onclick = false, $attribute = false)
{
if (!isset($this->menu[$menuName])) {
$this->menu[$menuName] = array(
@@ -158,17 +160,22 @@ private function buildMenuItem($menuName, $subMenuName, $url, $order = 50, $tool
$this->menu[$menuName]['_order'] = $order;
$this->menu[$menuName]['_name'] = $menuName;
$this->menu[$menuName]['_tooltip'] = $tooltip;
+ $this->menu[$menuName]['_attribute'] = $attribute;
if (!empty($this->menuIcons[$menuName])) {
$this->menu[$menuName]['_icon'] = $this->menuIcons[$menuName];
} else {
$this->menu[$menuName]['_icon'] = '';
}
+ if (!empty($onclick)) {
+ $this->menu[$menuName]['_onclick'] = $onclick;
+ }
}
if (!empty($subMenuName)) {
$this->menu[$menuName][$subMenuName]['_url'] = $url;
$this->menu[$menuName][$subMenuName]['_order'] = $order;
$this->menu[$menuName][$subMenuName]['_name'] = $subMenuName;
$this->menu[$menuName][$subMenuName]['_tooltip'] = $tooltip;
+ $this->menu[$menuName][$subMenuName]['_attribute'] = $attribute;
$this->menu[$menuName][$subMenuName]['_icon'] = $icon;
$this->menu[$menuName][$subMenuName]['_onclick'] = $onclick;
$this->menu[$menuName]['_hasSubmenu'] = true;
@@ -185,7 +192,7 @@ private function buildMenuItem($menuName, $subMenuName, $url, $order = 50, $tool
private function buildMenu()
{
foreach ($this->menuEntries as $menuEntry) {
- $this->buildMenuItem($menuEntry[0], $menuEntry[1], $menuEntry[2], $menuEntry[3], $menuEntry[4], $menuEntry[5], $menuEntry[6]);
+ $this->buildMenuItem($menuEntry[0], $menuEntry[1], $menuEntry[2], $menuEntry[3], $menuEntry[4], $menuEntry[5], $menuEntry[6], $menuEntry[7]);
}
}
diff --git a/app/core/Metrics.php b/app/core/Metrics.php
index 7cb3f26b8..cde226b60 100644
--- a/app/core/Metrics.php
+++ b/app/core/Metrics.php
@@ -9,7 +9,6 @@
namespace Piwik;
use Piwik\Cache as PiwikCache;
-use Piwik\Container\StaticContainer;
require_once PIWIK_INCLUDE_PATH . "/core/Piwik.php";
diff --git a/app/core/NumberFormatter.php b/app/core/NumberFormatter.php
index 694b94735..d0a3ebe7e 100644
--- a/app/core/NumberFormatter.php
+++ b/app/core/NumberFormatter.php
@@ -142,7 +142,7 @@ public function formatPercentEvolution($value)
*/
public function formatCurrency($value, $currency, $precision=2)
{
- $newValue = trim($value, " \0\x0B$currency");
+ $newValue = trim(strval($value), " \0\x0B$currency");
if (!is_numeric($newValue)) {
return $value;
}
diff --git a/app/core/Period/Range.php b/app/core/Period/Range.php
index 1a4e381dc..cdebc2711 100644
--- a/app/core/Period/Range.php
+++ b/app/core/Period/Range.php
@@ -263,7 +263,7 @@ protected function generate()
if (strpos($strDateEnd, '-') === false) {
$timezone = $this->timezone;
}
- $endDate = Date::factory($strDateEnd, $timezone);
+ $endDate = Date::factory($strDateEnd, $timezone)->setTime("00:00:00");
} else {
throw new Exception($this->translator->translate('General_ExceptionInvalidDateRange', array($this->strDate, ' \'lastN\', \'previousN\', \'YYYY-MM-DD,YYYY-MM-DD\'')));
}
@@ -498,6 +498,16 @@ public static function getDateXPeriodsAgo($subXPeriods, $date = false, $period =
return array($strLastDate, $lastPeriod);
}
+ /**
+ * Return the number of days contained in this range
+ *
+ * @return int
+ * @throws Exception
+ */
+ public function getDayCount()
+ {
+ return (self::getNumDaysDifference($this->getDateStart(), $this->getDateEnd()) + 1);
+ }
private static function getNumDaysDifference(Date $date1, Date $date2)
{
diff --git a/app/core/Piwik.php b/app/core/Piwik.php
index e0c25d81d..0c9c1ff66 100644
--- a/app/core/Piwik.php
+++ b/app/core/Piwik.php
@@ -185,7 +185,7 @@ public static function getCurrentUserCreationDate()
$user = APIUsersManager::getInstance()->getUser(Piwik::getCurrentUserLogin());
return $user['date_registered'] ?? '';
}
-
+
/**
* Returns the current user's Last Seen.
*
@@ -889,4 +889,32 @@ public static function translate($translationId, $args = array(), $language = nu
return $translator->translate($translationId, $args, $language);
}
+
+ /**
+ * Returns the period provided in the current request.
+ * If no $default is provided, this method will throw an Exception if `period` can't be found in the request
+ *
+ * @param string|null $default default value to use
+ * @throws Exception
+ * @return string
+ * @api
+ */
+ public static function getPeriod($default = null)
+ {
+ return Common::getRequestVar('period', $default, 'string');
+ }
+
+ /**
+ * Returns the date provided in the current request.
+ * If no $default is provided, this method will throw an Exception if `date` can't be found in the request
+ *
+ * @param string|null $default default value to use
+ * @throws Exception
+ * @return string
+ * @api
+ */
+ public static function getDate($default = null)
+ {
+ return Common::getRequestVar('date', $default, 'string');
+ }
}
diff --git a/app/core/Plugin.php b/app/core/Plugin.php
index 109592635..4e1df7eba 100644
--- a/app/core/Plugin.php
+++ b/app/core/Plugin.php
@@ -648,6 +648,28 @@ private function makeDependency($piwikVersion)
}
return $dependency;
}
+
+ /**
+ * Get all changes for this plugin
+ *
+ * @return array Array of changes
+ * [{"title":"abc","description":"xyz","linkName":"def","link":"https://link","version":"1.2.3"}]
+ */
+ public function getChanges()
+ {
+ $file = Manager::getPluginDirectory($this->pluginName).'/changes.json';
+ if (file_exists($file)) {
+ $json = file_get_contents($file);
+ if ($json) {
+ $changes = json_decode($json, true);
+ if ($changes && is_array($changes)) {
+ return array_reverse($changes);
+ }
+ }
+ }
+ return [];
+ }
+
}
}
diff --git a/app/core/Plugin/ArchivedMetric.php b/app/core/Plugin/ArchivedMetric.php
index c55d2fde5..20dff6953 100644
--- a/app/core/Plugin/ArchivedMetric.php
+++ b/app/core/Plugin/ArchivedMetric.php
@@ -147,10 +147,7 @@ public function format($value, Formatter $formatter)
case Dimension::TYPE_DURATION_S:
return $formatter->getPrettyTimeFromSeconds($value, $displayAsSentence = true);
case Dimension::TYPE_DURATION_MS:
- $val = number_format($value / 1000, 2);
- if ($val > 60) {
- $val = round($val);
- }
+ $val = round(($value / 1000), ($value / 1000) > 60 ? 0 : 2);
return $formatter->getPrettyTimeFromSeconds($val, $displayAsSentence = true);
case Dimension::TYPE_PERCENT:
return $formatter->getPrettyPercentFromQuotient($value);
diff --git a/app/core/Plugin/ComputedMetric.php b/app/core/Plugin/ComputedMetric.php
index e0daa970f..2039555d6 100644
--- a/app/core/Plugin/ComputedMetric.php
+++ b/app/core/Plugin/ComputedMetric.php
@@ -167,10 +167,7 @@ public function format($value, Formatter $formatter)
case Dimension::TYPE_DURATION_S:
return $formatter->getPrettyTimeFromSeconds(round($value), $displayAsSentence = true);
case Dimension::TYPE_DURATION_MS:
- $val = number_format($value / 1000, 2);
- if ($val > 60) {
- $val = round($val);
- }
+ $val = round(($value / 1000), ($value / 1000) > 60 ? 0 : 2);
return $formatter->getPrettyTimeFromSeconds($val, $displayAsSentence = true);
case Dimension::TYPE_PERCENT:
return $formatter->getPrettyPercentFromQuotient($value);
diff --git a/app/core/Plugin/Controller.php b/app/core/Plugin/Controller.php
index 241ef0632..2d0093912 100644
--- a/app/core/Plugin/Controller.php
+++ b/app/core/Plugin/Controller.php
@@ -476,25 +476,14 @@ protected function getLastUnitGraphAcrossPlugins($currentModuleName, $currentCon
*/
protected function getGraphParamsModified($paramsToSet = array())
{
- if (!isset($paramsToSet['period'])) {
- $period = Common::getRequestVar('period');
- } else {
- $period = $paramsToSet['period'];
- }
+ $period = $paramsToSet['period'] ?? Piwik::getPeriod();
+
if ($period === 'range') {
return $paramsToSet;
}
- if (!isset($paramsToSet['range'])) {
- $range = 'last30';
- } else {
- $range = $paramsToSet['range'];
- }
- if (!isset($paramsToSet['date'])) {
- $endDate = $this->strDate;
- } else {
- $endDate = $paramsToSet['date'];
- }
+ $range = isset($paramsToSet['range']) ? $paramsToSet['range'] : 'last30';
+ $endDate = isset($paramsToSet['date']) ? $paramsToSet['date'] : $this->strDate;
if (is_null($this->site)) {
throw new NoAccessException("Website not initialized, check that you are logged in and/or using the correct token_auth.");
@@ -640,10 +629,10 @@ protected function setGeneralVariablesViewAs($view, $viewType)
$maxDate = Date::factory('now', $siteTimezone);
$this->setMaxDateView($maxDate, $view);
- $rawDate = Common::getRequestVar('date');
+ $rawDate = Piwik::getDate();
Period::checkDateFormat($rawDate);
- $periodStr = Common::getRequestVar('period');
+ $periodStr = Piwik::getPeriod();
if ($periodStr !== 'range') {
$date = Date::factory($this->strDate);
@@ -923,14 +912,15 @@ public static function setPeriodVariablesView($view)
$periodValidator = new PeriodValidator();
- $currentPeriod = Common::getRequestVar('period');
- $view->displayUniqueVisitors = SettingsPiwik::isUniqueVisitorsEnabled($currentPeriod);
+ $currentPeriod = Piwik::getPeriod();
$availablePeriods = $periodValidator->getPeriodsAllowedForUI();
if (! $periodValidator->isPeriodAllowedForUI($currentPeriod)) {
throw new Exception("Period must be one of: " . implode(", ", $availablePeriods));
}
+ $view->displayUniqueVisitors = SettingsPiwik::isUniqueVisitorsEnabled($currentPeriod);
+
$found = array_search($currentPeriod, $availablePeriods);
unset($availablePeriods[$found]);
diff --git a/app/core/Plugin/Dimension/VisitDimension.php b/app/core/Plugin/Dimension/VisitDimension.php
index 9ba020611..030ec18f9 100644
--- a/app/core/Plugin/Dimension/VisitDimension.php
+++ b/app/core/Plugin/Dimension/VisitDimension.php
@@ -12,6 +12,7 @@
use Piwik\Cache as PiwikCache;
use Piwik\Columns\Dimension;
use Piwik\Common;
+use Piwik\DataTable;
use Piwik\Db;
use Piwik\DbHelper;
use Piwik\Plugin\Manager as PluginManager;
@@ -346,4 +347,51 @@ public static function getDimensions(Plugin $plugin)
return $instances;
}
+
+ /**
+ * Sort a key => value array descending by the number of occurances of the key in the supplied table and column
+ *
+ * @param array $array Key value array
+ * @param DataTable $table Datatable from which to count occurances
+ * @param string $keyColumn Column in the datatable to match against the array key
+ * @param int $maxValuesToReturn Limit the return array to this number of elements
+ *
+ * @return array An array of values from the source array sorted by most occurances, descending
+ */
+ public function sortStaticListByUsage(array $array, DataTable $table, string $keyColumn, int $maxValuesToReturn) : array
+ {
+ // Convert to multi-dimensional array and count the number of visits for each browser name
+ foreach ($array as $k => $v) {
+ $array[$k] = ['count' => 0, 'name' => $v];
+ }
+ $array['xx'] = ['count' => 0, 'name' => 'Unknown'];
+
+ foreach ($table->getRows() as $row) {
+ if (isset($row[$keyColumn])) {
+ if (isset($array[$row[$keyColumn]])) {
+ $array[$row[$keyColumn]]['count']++;
+ } else {
+ $array['xx']['count']++;
+ }
+ }
+ }
+ // Sort by most visits descending
+ uasort($array, function($a, $b) {
+ return $a <=> $b;
+ });
+ $array = array_reverse($array, true);
+
+ // Flatten and limit the return array
+ $flat = [];
+ $i = 0;
+ foreach ($array as $k => $v) {
+ $flat[$k] = $v['name'];
+ $i++;
+ if ($i == ($maxValuesToReturn)) {
+ break;
+ }
+ }
+
+ return array_values($flat);
+ }
}
diff --git a/app/core/Plugin/Manager.php b/app/core/Plugin/Manager.php
index a3339f027..61538b596 100644
--- a/app/core/Plugin/Manager.php
+++ b/app/core/Plugin/Manager.php
@@ -16,7 +16,6 @@
use Piwik\Config;
use Piwik\Config as PiwikConfig;
use Piwik\Container\StaticContainer;
-use Piwik\Date;
use Piwik\Development;
use Piwik\EventDispatcher;
use Piwik\Exception\PluginDeactivatedException;
diff --git a/app/core/Plugin/MetadataLoader.php b/app/core/Plugin/MetadataLoader.php
index a6fb42025..df478d543 100644
--- a/app/core/Plugin/MetadataLoader.php
+++ b/app/core/Plugin/MetadataLoader.php
@@ -11,7 +11,6 @@
use Exception;
use Piwik\Piwik;
use Piwik\Version;
-use Piwik\Plugin;
/**
* @see core/Version.php
diff --git a/app/core/Plugin/Segment.php b/app/core/Plugin/Segment.php
index 505935755..8fd27241b 100644
--- a/app/core/Plugin/Segment.php
+++ b/app/core/Plugin/Segment.php
@@ -56,6 +56,7 @@ class Segment
private $unionOfSegments;
private $isInternalSegment = false;
private $suggestedValuesApi = '';
+ private $needsMostFrequentValues = true;
/**
* If true, this segment will only be visible to a registered user (see API.getSegmentsMetadata).
@@ -323,6 +324,14 @@ public function setSuggestedValuesApi($suggestedValuesApi)
$this->suggestedValuesApi = $suggestedValuesApi;
}
+ /**
+ * @param bool $value
+ */
+ public function setNeedsMostFrequentValues(bool $value)
+ {
+ $this->needsMostFrequentValues = $value;
+ }
+
/**
* You can restrict the access to this segment by passing a boolean `false`. For instance if you want to make
* a certain segment only available to users having super user access you could do the following:
@@ -342,11 +351,12 @@ public function setPermission($permission)
public function toArray()
{
$segment = array(
- 'type' => $this->type,
- 'category' => $this->category,
- 'name' => $this->name,
- 'segment' => $this->segment,
- 'sqlSegment' => $this->sqlSegment,
+ 'type' => $this->type,
+ 'category' => $this->category,
+ 'name' => $this->name,
+ 'segment' => $this->segment,
+ 'sqlSegment' => $this->sqlSegment,
+ 'needsMostFrequentValues' => $this->needsMostFrequentValues,
);
if (!empty($this->unionOfSegments)) {
diff --git a/app/core/Plugin/Visualization.php b/app/core/Plugin/Visualization.php
index 246a0a9cd..b2ff753f3 100644
--- a/app/core/Plugin/Visualization.php
+++ b/app/core/Plugin/Visualization.php
@@ -14,6 +14,7 @@
use Piwik\API\Request;
use Piwik\API\Request as ApiRequest;
use Piwik\API\ResponseBuilder;
+use Piwik\ArchiveProcessor\Rules;
use Piwik\Common;
use Piwik\Container\StaticContainer;
use Piwik\DataTable;
@@ -156,7 +157,6 @@ class Visualization extends ViewDataTable
private $templateVars = array();
private $reportLastUpdatedMessage = null;
- private $metadata = null;
protected $metricsFormatter = null;
/**
@@ -232,6 +232,7 @@ public function render()
// if it's likely that the report data for this data table has been purged,
// set whether we should display a message to that effect.
$view->showReportDataWasPurgedMessage = $this->hasReportBeenPurged();
+ $view->showPluginArchiveDisabled = $this->hasReportSegmentDisabled();
$view->deleteReportsOlderThan = Option::get('delete_reports_older_than');
}
@@ -456,14 +457,35 @@ private function postDataTableLoadedFromAPI()
}
// deal w/ table metadata
+ $metadata = null;
if ($this->dataTable instanceof DataTable) {
- $this->metadata = $this->dataTable->getAllTableMetadata();
-
- if (isset($this->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME])) {
- $this->reportLastUpdatedMessage = $this->makePrettyArchivedOnText();
+ $metadata = $this->dataTable->getAllTableMetadata();
+ } else {
+ // if the dataTable is Map
+ if ($this->dataTable instanceof DataTable\Map) {
+ // load all the data
+ $dataTable = $this->dataTable->getDataTables();
+ // find the latest key
+ foreach ($dataTable as $item) {
+ $itemMetaData = $item->getAllTableMetadata();
+ // initial metadata and update metadata if current is more recent
+ if (!empty($itemMetaData[DataTable::ARCHIVED_DATE_METADATA_NAME])
+ && (
+ empty($metadata[DataTable::ARCHIVED_DATE_METADATA_NAME])
+ || strtotime($itemMetaData[DataTable::ARCHIVED_DATE_METADATA_NAME]) > strtotime($metadata[DataTable::ARCHIVED_DATE_METADATA_NAME])
+ )
+ ) {
+ $metadata = $itemMetaData;
+ }
+ }
}
}
+ // if metadata set display report date
+ if (!empty($metadata[DataTable::ARCHIVED_DATE_METADATA_NAME])) {
+ $this->reportLastUpdatedMessage = $this->makePrettyArchivedOnText($metadata[DataTable::ARCHIVED_DATE_METADATA_NAME]);
+ }
+
$pivotBy = Common::getRequestVar('pivotBy', false) ?: $this->requestConfig->pivotBy;
if (empty($pivotBy)
&& $this->dataTable instanceof DataTable
@@ -556,14 +578,16 @@ private function removeEmptyColumnsFromDisplay()
}
}
+
/**
* Returns prettified and translated text that describes when a report was last updated.
*
+ * @param $dateText
* @return string
+ * @throws \Exception
*/
- private function makePrettyArchivedOnText()
+ private function makePrettyArchivedOnText($dateText)
{
- $dateText = $this->metadata[DataTable::ARCHIVED_DATE_METADATA_NAME];
$date = Date::factory($dateText);
$today = mktime(0, 0, 0);
$metricsFormatter = new HtmlFormatter();
@@ -600,6 +624,22 @@ private function hasReportBeenPurged()
return PrivacyManager::hasReportBeenPurged($this->dataTable);
}
+ /**
+ * Return true if the config for the plug is disabled
+ * @return bool
+ */
+
+ private function hasReportSegmentDisabled()
+ {
+ $module = $this->requestConfig->getApiModuleToRequest();
+ $rawSegment = \Piwik\API\Request::getRawSegmentFromRequest();
+
+ if (!empty($rawSegment) && Rules::isSegmentPluginArchivingDisabled($module)) {
+ return true;
+ }
+ return false;
+ }
+
/**
* Returns array of properties that should be visible to client side JavaScript. The data
* will be available in the data-props HTML attribute of the .dataTable div.
diff --git a/app/core/ProfessionalServices/Advertising.php b/app/core/ProfessionalServices/Advertising.php
index 852a992d8..163b366e7 100644
--- a/app/core/ProfessionalServices/Advertising.php
+++ b/app/core/ProfessionalServices/Advertising.php
@@ -93,6 +93,7 @@ public function addPromoCampaignParametersToUrl($url, $campaignName, $campaignMe
}
/**
+ * @deprecated
* Generates campaign URL parameters that can be used with promoting Professional Support service.
*
* @param string $campaignName
diff --git a/app/core/ReportRenderer.php b/app/core/ReportRenderer.php
index ce95e7e32..ee1cd6272 100644
--- a/app/core/ReportRenderer.php
+++ b/app/core/ReportRenderer.php
@@ -1,4 +1,5 @@
Piwik::translate('General_Name'),
'value' => Piwik::translate('General_Value'),
- );
+ ];
}
- return array(
+ return [
$finalReport,
$reportColumns,
- );
+ ];
}
public static function getStaticGraph($reportMetadata, $width, $height, $evolution, $segment)
diff --git a/app/core/ReportRenderer/Html.php b/app/core/ReportRenderer/Html.php
index ef3029cf6..71b77c00d 100644
--- a/app/core/ReportRenderer/Html.php
+++ b/app/core/ReportRenderer/Html.php
@@ -8,7 +8,6 @@
*/
namespace Piwik\ReportRenderer;
-use Piwik\Mail;
use Piwik\Piwik;
use Piwik\ReportRenderer;
use Piwik\View;
diff --git a/app/core/ReportRenderer/Pdf.php b/app/core/ReportRenderer/Pdf.php
index 3875f1e48..2ec74f473 100644
--- a/app/core/ReportRenderer/Pdf.php
+++ b/app/core/ReportRenderer/Pdf.php
@@ -12,10 +12,10 @@
use Piwik\Filesystem;
use Piwik\NumberFormatter;
use Piwik\Piwik;
-use Piwik\Plugins\API\API;
use Piwik\Plugins\CoreAdminHome\CustomLogo;
use Piwik\ReportRenderer;
use Piwik\TCPDF;
+use TCPDF_FONTS;
/**
* @see libs/tcpdf
@@ -40,6 +40,8 @@ class Pdf extends ReportRenderer
const MAX_GRAPH_REPORTS = 3;
const MAX_2COL_TABLE_REPORTS = 2;
+ const IMPORT_FONT_PATH = 'plugins/ImageGraph/fonts/unifont.ttf';
+
const PDF_CONTENT_TYPE = 'pdf';
private $reportFontStyle = '';
@@ -136,6 +138,10 @@ public function setLocale($locale)
}
// WARNING: Did you read the warning above?
+ // When user follow the FAQ https://matomo.org/faq/how-to-install/faq_142/, imported unifont font, it will apply across the entire report
+ if (is_file(self::IMPORT_FONT_PATH)) {
+ $reportFont = TCPDF_FONTS::addTTFfont(self::IMPORT_FONT_PATH, 'TrueTypeUnicode');
+ }
$this->reportFont = $reportFont;
}
@@ -370,7 +376,7 @@ private function paintReportTable()
$posX = $this->TCPDF->GetX();
$posY = $this->TCPDF->GetY();
if (isset($rowMetrics[$columnId])) {
- $text = substr($rowMetrics[$columnId], 0, $this->truncateAfter);
+ $text = mb_substr($rowMetrics[$columnId], 0, $this->truncateAfter);
if ($isLogoDisplayable) {
$text = $leftSpacesBeforeLogo . $text;
}
diff --git a/app/core/Scheduler/RetryableException.php b/app/core/Scheduler/RetryableException.php
new file mode 100644
index 000000000..70650089a
--- /dev/null
+++ b/app/core/Scheduler/RetryableException.php
@@ -0,0 +1,9 @@
+scheduledTime = $scheduledTime;
+ }
+
}
\ No newline at end of file
diff --git a/app/core/Scheduler/Scheduler.php b/app/core/Scheduler/Scheduler.php
index b126ccf7b..0d7b8296b 100644
--- a/app/core/Scheduler/Scheduler.php
+++ b/app/core/Scheduler/Scheduler.php
@@ -8,7 +8,6 @@
namespace Piwik\Scheduler;
-use Exception;
use Piwik\Piwik;
use Piwik\Timer;
use Psr\Log\LoggerInterface;
@@ -54,6 +53,12 @@ class Scheduler
*/
private $isRunningTask = false;
+ /**
+ * Should the last run task be scheduled for a retry
+ * @var bool
+ */
+ private $scheduleRetry = false;
+
/**
* @var Timetable
*/
@@ -145,8 +150,36 @@ public function run()
if ($shouldExecuteTask) {
$readFromOption = true;
+ $this->scheduleRetry = false;
$message = $this->executeTask($task);
+ // Task has thrown an exception and should be scheduled for a retry
+ if ($this->scheduleRetry) {
+
+ if($this->timetable->getRetryCount($task->getName()) == 3) {
+
+ // Task has already been retried three times, give up
+ $this->timetable->clearRetryCount($task->getName());
+
+ $this->logger->warning("Scheduler: '{task}' has already been retried three times, giving up",
+ ['task' => $task->getName()]);
+
+ } else {
+
+ $readFromOption = true;
+ $rescheduledDate = $this->timetable->rescheduleTaskAndRunInOneHour($task);
+ $this->timetable->incrementRetryCount($task->getName());
+
+ $this->logger->info("Scheduler: '{task}' retry scheduled for {date}",
+ ['task' => $task->getName(), 'date' => $rescheduledDate]);
+ }
+ $this->scheduleRetry = false;
+ } else {
+ if ($this->timetable->getRetryCount($task->getName()) > 0) {
+ $this->timetable->clearRetryCount($task->getName());
+ }
+ }
+
$executionResults[] = array('task' => $taskName, 'output' => $message);
}
}
@@ -275,8 +308,15 @@ private function executeTask($task)
$callable = array($task->getObjectInstance(), $task->getMethodName());
call_user_func($callable, $task->getMethodParameter());
$message = $timer->__toString();
- } catch (Exception $e) {
+ } catch (\Exception $e) {
+ $this->logger->error("Scheduler: Error {errorMessage} for task '{task}'",
+ ['errorMessage' => $e->getMessage(), 'task' => $task->getName()]);
$message = 'ERROR: ' . $e->getMessage();
+
+ // If the task has indicated that retrying on exception is safe then flag for rescheduling
+ if ($e instanceof RetryableException) {
+ $this->scheduleRetry = true;
+ }
}
$this->isRunningTask = false;
diff --git a/app/core/Scheduler/Timetable.php b/app/core/Scheduler/Timetable.php
index 47e6b094d..9073b73dc 100644
--- a/app/core/Scheduler/Timetable.php
+++ b/app/core/Scheduler/Timetable.php
@@ -19,8 +19,10 @@
class Timetable
{
const TIMETABLE_OPTION_STRING = "TaskScheduler.timetable";
+ const RETRY_OPTION_STRING = "TaskScheduler.retryList";
private $timetable;
+ private $retryList;
public function __construct()
{
@@ -37,6 +39,11 @@ public function setTimetable($timetable)
$this->timetable = $timetable;
}
+ public function setRetryList($retryList)
+ {
+ $this->retryList = $retryList;
+ }
+
/**
* @param Task[] $activeTasks
*/
@@ -124,6 +131,17 @@ public function rescheduleTaskAndRunTomorrow(Task $task)
return $tomorrow;
}
+ public function rescheduleTaskAndRunInOneHour(Task $task)
+ {
+ $oneHourFromNow = Date::factory('now')->addHour(1);
+
+ // update the scheduled time
+ $this->timetable[$task->getName()] = $oneHourFromNow->getTimestamp();
+ $this->save();
+
+ return $oneHourFromNow;
+ }
+
public function save()
{
Option::set(self::TIMETABLE_OPTION_STRING, serialize($this->timetable));
@@ -149,4 +167,74 @@ public function readFromOption()
$this->timetable = $unserializedTimetable === false ? array() : $unserializedTimetable;
}
+
+ /**
+ * Read the retry list option from the database
+ *
+ * @throws \Throwable
+ */
+ private function readRetryList()
+ {
+ Option::clearCachedOption(self::RETRY_OPTION_STRING);
+ $retryData = Option::get(self::RETRY_OPTION_STRING);
+ $unserializedRetryList = Common::safe_unserialize($retryData);
+
+ $this->retryList = $unserializedRetryList === false ? array() : $unserializedRetryList;
+ }
+
+ /**
+ * Save the retry list option to the database
+ */
+ public function saveRetryList()
+ {
+ Option::set(self::RETRY_OPTION_STRING, serialize($this->retryList));
+ }
+
+ /**
+ * Remove a task from the retry list
+ *
+ * @param string $taskName
+ */
+ public function clearRetryCount(string $taskName)
+ {
+ if (isset($this->retryList[$taskName])) {
+ unset($this->retryList[$taskName]);
+ $this->saveRetryList();
+ }
+ }
+
+ /**
+ * Increment the retry counter for a task
+ *
+ * @param string $taskName
+ */
+ public function incrementRetryCount(string $taskName)
+ {
+ $this->readRetryList();
+ if (!isset($this->retryList[$taskName])) {
+ $this->retryList[$taskName] = 0;
+ }
+ $this->retryList[$taskName]++;
+ $this->saveRetryList();
+ }
+
+ /**
+ * Return the current number of retries for a task
+ *
+ * @param string $taskName
+ *
+ * @return int
+ */
+ public function getRetryCount(string $taskName) : int
+ {
+ $this->readRetryList();
+
+ // Ignore excessive retry counts, workaround for SchedulerTest mock
+ if (!isset($this->retryList[$taskName]) || $this->retryList[$taskName] > 10000) {
+ return 0;
+ }
+
+ return $this->retryList[$taskName];
+ }
+
}
diff --git a/app/core/Segment.php b/app/core/Segment.php
index 4149f9b13..b39d9072a 100644
--- a/app/core/Segment.php
+++ b/app/core/Segment.php
@@ -11,12 +11,12 @@
use Exception;
use Piwik\API\Request;
use Piwik\ArchiveProcessor\Rules;
+use Piwik\Cache as PiwikCache;
use Piwik\Container\StaticContainer;
use Piwik\DataAccess\LogQueryBuilder;
use Piwik\Plugins\SegmentEditor\SegmentEditor;
use Piwik\Segment\SegmentExpression;
use Piwik\Plugins\SegmentEditor\Model as SegmentEditorModel;
-use Piwik\Cache;
/**
* Limits the set of visits Piwik uses when aggregating analytics data.
@@ -180,17 +180,30 @@ public function getSegmentExpression()
return $this->segmentExpression;
}
+ /**
+ * @throws Exception
+ */
private function getAvailableSegments()
{
+ // start cache
+ $cache = PiwikCache::getTransientCache();
+
+ //covert cache id
+ $cacheId = 'API.getSegmentsMetadata.'.SettingsPiwik::getPiwikInstanceId() . '.' . implode(",", $this->idSites);
+
+ //fetch cache lockId
+ $this->availableSegments = $cache->fetch($cacheId);
// segment metadata
if (empty($this->availableSegments)) {
+
$this->availableSegments = Request::processRequest('API.getSegmentsMetadata', array(
- 'idSites' => $this->idSites,
- '_hideImplementationData' => 0,
- 'filter_limit' => -1,
- 'filter_offset' => 0,
- '_showAllSegments' => 1,
+ 'idSites' => $this->idSites,
+ '_hideImplementationData' => 0,
+ 'filter_limit' => -1,
+ 'filter_offset' => 0,
+ '_showAllSegments' => 1,
), []);
+ $cache->save($cacheId, $this->availableSegments);
}
return $this->availableSegments;
diff --git a/app/core/Segment/SegmentsList.php b/app/core/Segment/SegmentsList.php
index 82ea86065..448a4f159 100644
--- a/app/core/Segment/SegmentsList.php
+++ b/app/core/Segment/SegmentsList.php
@@ -132,6 +132,20 @@ public static function get()
$dimension->configureSegments($list, new DimensionSegmentFactory($dimension));
}
+ /**
+ * Triggered to filter segment definitions.
+ *
+ * **Example**
+ *
+ * public function filterSegments(&$segmentList)
+ * {
+ * $segmentList->remove('Category');
+ * }
+ *
+ * @param SegmentsList $list An instance of the SegmentsList.
+ */
+ Piwik::postEvent('Segment.filterSegments', array($list));
+
$cache->save($cacheKey, $list);
return $list;
diff --git a/app/core/Session.php b/app/core/Session.php
index 641334676..096914e6e 100644
--- a/app/core/Session.php
+++ b/app/core/Session.php
@@ -11,6 +11,7 @@
use Exception;
use Piwik\Container\StaticContainer;
use Piwik\Exception\MissingFilePermissionException;
+use Piwik\Plugins\Overlay\Overlay;
use Piwik\Session\SaveHandler\DbTable;
use Psr\Log\LoggerInterface;
use Zend_Session;
@@ -170,10 +171,11 @@ public static function getSameSiteCookieValue()
$module = Piwik::getModule();
$action = Piwik::getAction();
+ $method = Common::getRequestVar('method', '', 'string');
+ $referer = Url::getReferrer();
$isOptOutRequest = $module == 'CoreAdminHome' && $action == 'optOut';
- $isOverlay = $module == 'Overlay';
- $shouldUseNone = !empty($general['enable_framed_pages']) || $isOptOutRequest || $isOverlay;
+ $shouldUseNone = !empty($general['enable_framed_pages']) || $isOptOutRequest || Overlay::isOverlayRequest($module, $action, $method, $referer);
if ($shouldUseNone && ProxyHttp::isHttps()) {
return 'None';
diff --git a/app/core/Session/SessionAuth.php b/app/core/Session/SessionAuth.php
index bff91c113..0f2d1cada 100644
--- a/app/core/Session/SessionAuth.php
+++ b/app/core/Session/SessionAuth.php
@@ -11,11 +11,9 @@
use Piwik\Auth;
use Piwik\AuthResult;
-use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Date;
-use Piwik\Plugins\UsersManager\Model;
use Piwik\Plugins\UsersManager\Model as UsersModel;
use Piwik\Session;
use Psr\Log\LoggerInterface;
diff --git a/app/core/Session/SessionFingerprint.php b/app/core/Session/SessionFingerprint.php
index 231ba17ea..fa6a4fd22 100644
--- a/app/core/Session/SessionFingerprint.php
+++ b/app/core/Session/SessionFingerprint.php
@@ -9,7 +9,6 @@
namespace Piwik\Session;
-use Piwik\Common;
use Piwik\Config;
use Piwik\Date;
diff --git a/app/core/Settings/FieldConfig.php b/app/core/Settings/FieldConfig.php
index bf9f9f46d..a6480216b 100644
--- a/app/core/Settings/FieldConfig.php
+++ b/app/core/Settings/FieldConfig.php
@@ -123,9 +123,21 @@ class FieldConfig
* "formField.value" angular model. For an example see "plugins/CorePluginsAdmin/angularjs/form-field/field-text.html"
*
* @var string
+ * @deprecated set $customFieldComponent to ['plugin' => 'MyPlugin', 'component' => 'MyComponentAsItIsExported']
*/
public $customUiControlTemplateFile = '';
+ /**
+ * Defines a custom Vue component to use for the internal field UI control. This should be an array with two
+ * keys:
+ *
+ * - plugin: the name of the plugin that the UI control exists in.
+ * - name: the name of the export for the component in the plugin's Vue UMD module.
+ *
+ * @var string[]
+ */
+ public $customFieldComponent;
+
/**
* Name-value mapping of HTML attributes that will be added HTML form control, eg,
* `array('size' => 3)`. Attributes will be escaped before outputting.
diff --git a/app/core/Settings/FieldConfig/ArrayField.php b/app/core/Settings/FieldConfig/ArrayField.php
index 8410cf4c0..9628e2925 100644
--- a/app/core/Settings/FieldConfig/ArrayField.php
+++ b/app/core/Settings/FieldConfig/ArrayField.php
@@ -39,6 +39,14 @@ class ArrayField
*/
public $customUiControlTemplateFile = '';
+ /**
+ * Array like ['plugin' => 'MyPlugin', 'component' => 'MyExportedCustomFieldComponent']. For an example see
+ * "plugins/CorePluginsAdmin/vue/src/FormField/FieldText.vue"
+ *
+ * @var string[]
+ */
+ public $customFieldComponent = null;
+
/**
* This setting's display name, for example, `'Refresh Interval'`.
*
@@ -72,6 +80,7 @@ public function toArray()
'title' => $this->title,
'uiControl' => $this->uiControl,
'templateFile' => $this->customUiControlTemplateFile,
+ 'component' => $this->customFieldComponent,
'availableValues' => $this->availableValues,
);
}
diff --git a/app/core/Settings/FieldConfig/MultiPair.php b/app/core/Settings/FieldConfig/MultiPair.php
index 40b27c97b..22788e76b 100644
--- a/app/core/Settings/FieldConfig/MultiPair.php
+++ b/app/core/Settings/FieldConfig/MultiPair.php
@@ -44,9 +44,18 @@ class MultiPair
* "formField.value" angular model. For an example see "plugins/CorePluginsAdmin/angularjs/form-field/field-text.html"
*
* @var string
+ * @deprecated use customFieldComponent instead
*/
public $customUiControlTemplateFile = '';
+ /**
+ * Array like ['plugin' => 'MyPlugin', 'component' => 'MyExportedCustomFieldComponent']. For an example see
+ * "plugins/CorePluginsAdmin/vue/src/FormField/FieldText.vue"
+ *
+ * @var string[]
+ */
+ public $customFieldComponent = null;
+
/**
* This setting's display name, for example, `'Refresh Interval'`.
*
@@ -82,6 +91,7 @@ public function toArray()
'title' => $this->title,
'uiControl' => $this->uiControl,
'templateFile' => $this->customUiControlTemplateFile,
+ 'component' => $this->customFieldComponent,
'availableValues' => $this->availableValues,
);
}
diff --git a/app/core/SettingsPiwik.php b/app/core/SettingsPiwik.php
index 14f4547d2..a78f0a84c 100644
--- a/app/core/SettingsPiwik.php
+++ b/app/core/SettingsPiwik.php
@@ -31,7 +31,7 @@ public static function getSalt(): ?string
{
static $salt = null;
if (is_null($salt)) {
- $salt = @Config::getInstance()->General['salt'];
+ $salt = Config::getInstance()->General['salt'] ?? '';
}
return $salt;
}
diff --git a/app/core/SupportedBrowser.php b/app/core/SupportedBrowser.php
index 6f9abe631..3f9f195df 100644
--- a/app/core/SupportedBrowser.php
+++ b/app/core/SupportedBrowser.php
@@ -9,7 +9,6 @@
namespace Piwik;
-use Piwik\Http;
use Piwik\Piwik;
use Piwik\Container\StaticContainer;
use Piwik\DeviceDetector\DeviceDetectorFactory;
diff --git a/app/core/Tracker.php b/app/core/Tracker.php
index 9d813c079..90485e1a5 100644
--- a/app/core/Tracker.php
+++ b/app/core/Tracker.php
@@ -1,4 +1,5 @@
init();
+
+ if ($this->isPreFlightCorsRequest()) {
+ Common::sendHeader('Access-Control-Allow-Methods: GET, POST');
+ Common::sendHeader('Access-Control-Allow-Headers: *');
+ Common::sendHeader('Access-Control-Allow-Origin: *');
+ Common::sendResponseCode(204);
+ $this->logger->debug("Tracker detected preflight CORS request. Skipping...");
+ return null;
+ }
+
$handler->init($this, $requestSet);
$this->track($handler, $requestSet);
} catch (Exception $e) {
- StaticContainer::get(LoggerInterface::class)->debug("Tracker encountered an exception: {ex}", [$e]);
+ $this->logger->debug("Tracker encountered an exception: {ex}", [$e]);
$handler->onException($this, $requestSet, $e);
}
@@ -171,7 +183,8 @@ public function trackRequest(Request $request)
*/
public static function initCorePiwikInTrackerMode()
{
- if (SettingsServer::isTrackerApiRequest()
+ if (
+ SettingsServer::isTrackerApiRequest()
&& self::$initTrackerMode === false
) {
self::$initTrackerMode = true;
@@ -291,7 +304,8 @@ public static function setTestEnvironment($args = null, $requestMethod = null)
}
// Tests using window_look_back_for_visitor
- if (Common::getRequestVar('forceLargeWindowLookBackForVisitor', false, null, $args) == 1
+ if (
+ Common::getRequestVar('forceLargeWindowLookBackForVisitor', false, null, $args) == 1
// also look for this in bulk requests (see fake_logs_replay.log)
|| strpos(json_encode($args, true), '"forceLargeWindowLookBackForVisitor":"1"') !== false
) {
@@ -330,7 +344,8 @@ protected function loadTrackerPlugins()
private function handleFatalErrors()
{
- register_shutdown_function(function () { // TODO: add a log here
+ register_shutdown_function(function () {
+ // TODO: add a log here
$lastError = error_get_last();
if (!empty($lastError) && $lastError['type'] == E_ERROR) {
Common::sendResponseCode(500);
@@ -355,4 +370,12 @@ private static function isDebugEnabled()
return false;
}
+
+ public function isPreFlightCorsRequest(): bool
+ {
+ if (isset($_SERVER['REQUEST_METHOD']) && strtoupper($_SERVER['REQUEST_METHOD']) === 'OPTIONS') {
+ return !empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']) || !empty($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']);
+ }
+ return false;
+ }
}
diff --git a/app/core/Tracker/Action.php b/app/core/Tracker/Action.php
index bd0cc078c..13baf6c0d 100644
--- a/app/core/Tracker/Action.php
+++ b/app/core/Tracker/Action.php
@@ -381,6 +381,8 @@ public function loadIdsFromLogActionTable()
*/
public function record(Visitor $visitor, $idReferrerActionUrl, $idReferrerActionName)
{
+
+
$this->loadIdsFromLogActionTable();
$visitAction = array(
diff --git a/app/core/Tracker/Cache.php b/app/core/Tracker/Cache.php
index 4cce6e413..67ab93b71 100644
--- a/app/core/Tracker/Cache.php
+++ b/app/core/Tracker/Cache.php
@@ -17,7 +17,6 @@
use Piwik\Piwik;
use Piwik\Tracker;
use Psr\Log\LoggerInterface;
-use function DI\object;
/**
* Simple cache mechanism used in Tracker to avoid requesting settings from mysql on every request
diff --git a/app/core/Tracker/Db.php b/app/core/Tracker/Db.php
index 22a9173a8..a6bce56a7 100644
--- a/app/core/Tracker/Db.php
+++ b/app/core/Tracker/Db.php
@@ -30,6 +30,9 @@ abstract class Db
protected $connection = null;
+ // this is used for indicate TransactionLevel Cache
+ public $supportsUncommitted = null;
+
/**
* Enables the SQL profiling.
* For each query, saves in the DB the time spent on this query.
diff --git a/app/core/Tracker/Db/Pdo/Mysql.php b/app/core/Tracker/Db/Pdo/Mysql.php
index 1e83b7135..8b1a53670 100644
--- a/app/core/Tracker/Db/Pdo/Mysql.php
+++ b/app/core/Tracker/Db/Pdo/Mysql.php
@@ -12,7 +12,6 @@
use PDO;
use PDOException;
use PDOStatement;
-use Piwik\Config;
use Piwik\Tracker\Db;
use Piwik\Tracker\Db\DbException;
diff --git a/app/core/Tracker/FingerprintSalt.php b/app/core/Tracker/FingerprintSalt.php
index 9896c074c..c3d056ba7 100644
--- a/app/core/Tracker/FingerprintSalt.php
+++ b/app/core/Tracker/FingerprintSalt.php
@@ -11,13 +11,7 @@
use Piwik\Common;
use Piwik\Date;
-use Piwik\Exception\InvalidRequestParameterException;
-use Piwik\Exception\UnexpectedWebsiteFoundException;
use Piwik\Option;
-use Piwik\Piwik;
-use Piwik\SettingsServer;
-use Piwik\Site;
-use Piwik\Db as PiwikDb;
class FingerprintSalt
{
diff --git a/app/core/Tracker/GoalManager.php b/app/core/Tracker/GoalManager.php
index 1d1e3314d..ea37d447b 100644
--- a/app/core/Tracker/GoalManager.php
+++ b/app/core/Tracker/GoalManager.php
@@ -19,7 +19,6 @@
use Piwik\Plugin\Manager;
use Piwik\Plugins\CustomVariables\CustomVariables;
use Piwik\Plugins\Events\Actions\ActionEvent;
-use Piwik\Tracker;
use Piwik\Tracker\Visit\VisitProperties;
/**
@@ -561,8 +560,10 @@ private function getCleanedEcommerceItems($items)
foreach ($cleanedItems as $item) {
$actionsToLookup = array();
- list($sku, $name, $category, $price, $quantity) = $item;
+ list($sku_check, $name_check, $category, $price, $quantity) = $item;
+ $sku = is_array($sku_check) ? join(',', $sku_check) : $sku_check;
$actionsToLookup[] = array(trim($sku), Action::TYPE_ECOMMERCE_ITEM_SKU);
+ $name = is_array($name_check) ? join(',', $name_check) : $name_check;
$actionsToLookup[] = array(trim($name), Action::TYPE_ECOMMERCE_ITEM_NAME);
// Only one category
diff --git a/app/core/Tracker/PageUrl.php b/app/core/Tracker/PageUrl.php
index 0d875145a..a500877c9 100644
--- a/app/core/Tracker/PageUrl.php
+++ b/app/core/Tracker/PageUrl.php
@@ -287,8 +287,8 @@ public static function reencodeParameters(&$queryParameters, $encoding = false)
if (function_exists('mb_check_encoding')) {
// if query params are encoded w/ non-utf8 characters (due to browser bug or whatever),
// encode to UTF-8.
- if (strtolower($encoding) != 'utf-8'
- && $encoding != false
+ if (is_string($encoding) &&
+ strtolower($encoding) !== 'utf-8'
) {
Common::printDebug("Encoding page URL query parameters to $encoding.");
diff --git a/app/core/Tracker/Request.php b/app/core/Tracker/Request.php
index 2dd8be557..2b1496f45 100644
--- a/app/core/Tracker/Request.php
+++ b/app/core/Tracker/Request.php
@@ -10,7 +10,6 @@
use Exception;
use Piwik\Common;
-use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Cookie;
use Piwik\Exception\InvalidRequestParameterException;
@@ -18,7 +17,6 @@
use Piwik\IP;
use Matomo\Network\IPUtils;
use Piwik\Piwik;
-use Piwik\Plugins\PrivacyManager\PrivacyManager;
use Piwik\Plugins\UsersManager\UsersManager;
use Piwik\ProxyHttp;
use Piwik\Segment\SegmentExpression;
@@ -46,6 +44,8 @@ class Request
protected $tokenAuth;
+
+
/**
* Stores plugin specific tracking request metadata. RequestProcessors can store
* whatever they want in this array, and other RequestProcessors can modify these
@@ -74,6 +74,7 @@ public function __construct($params, $tokenAuth = false)
$this->timestamp = time();
$this->isEmptyRequest = empty($params);
+
// When the 'url' and referrer url parameter are not given, we might be in the 'Simple Image Tracker' mode.
// The URL can default to the Referrer, which will be in this case
// the URL of the page containing the Simple Image beacon
@@ -923,4 +924,5 @@ private function getVisitorIdAsBinary($idVisitor)
}
return false;
}
+
}
diff --git a/app/core/Tracker/RequestSet.php b/app/core/Tracker/RequestSet.php
index d243f4550..7249ea226 100644
--- a/app/core/Tracker/RequestSet.php
+++ b/app/core/Tracker/RequestSet.php
@@ -36,7 +36,7 @@ public function setRequests($requests)
if (empty($requests)|| !is_array($requests)) {
return;
}
-
+
foreach ($requests as $request) {
if (empty($request) && !is_array($request)) {
continue;
@@ -45,7 +45,6 @@ public function setRequests($requests)
if (!$request instanceof Request) {
$request = new Request($request, $this->getTokenAuth());
}
-
$this->requests[] = $request;
}
}
diff --git a/app/core/Tracker/Response.php b/app/core/Tracker/Response.php
old mode 100755
new mode 100644
index 9e1a63c84..e99feb8b3
--- a/app/core/Tracker/Response.php
+++ b/app/core/Tracker/Response.php
@@ -1,4 +1,5 @@
isDebugModeEnabled()
+ if (
+ $tracker->isDebugModeEnabled()
&& $tracker->isDatabaseConnected()
&& TrackerDb::isProfilingEnabled()
) {
@@ -190,7 +194,7 @@ private function outputCustomImage(string $customImage): bool
// Base64 image string
$img = base64_decode($customImage);
$size = getimagesizefromstring($img);
- } else if (is_file($customImage) && is_readable($customImage)) {
+ } elseif (is_file($customImage) && is_readable($customImage)) {
// Image file
$img = file_get_contents($customImage);
$size = getimagesize($customImage); // imagesize is used to get the mime type
@@ -198,7 +202,7 @@ private function outputCustomImage(string $customImage): bool
// Must have valid image data and a valid mime type to proceed
if ($img && $size && isset($size['mime']) && in_array($size['mime'], $supportedMimeTypes)) {
- Common::sendHeader('Content-Type: '.$size['mime']);
+ Common::sendHeader('Content-Type: ' . $size['mime']);
echo $img;
return true;
}
@@ -229,6 +233,8 @@ protected function getMessageFromException($e)
protected function logExceptionToErrorLog($e)
{
- error_log(sprintf("Error in Matomo (tracker): %s", str_replace("\n", " ", $this->getMessageFromException($e))));
+ $hostname = Url::getRFCValidHostname();
+ $hostStr = $hostname ? "[$hostname]" : '-';
+ error_log(sprintf("$hostStr Error in Matomo (tracker): %s", str_replace("\n", " ", $this->getMessageFromException($e))));
}
}
diff --git a/app/core/Twig.php b/app/core/Twig.php
index 4a0960a4b..4aa9e6b4e 100644
--- a/app/core/Twig.php
+++ b/app/core/Twig.php
@@ -42,26 +42,7 @@ function piwik_format_number($string, $minFractionDigits, $maxFractionDigits)
function piwik_fix_lbrace($string)
{
- $chars = array('{', '{', '{', '{', '{', '{');
-
- static $search;
- static $replace;
-
- if (!isset($search)) {
- $search = array_map(function ($val) { return $val . $val; }, $chars);
- }
- if (!isset($replace)) {
- $replace = array_map(function ($val) { return $val . '' . $val; }, $chars);
- }
-
- $replacedString = is_null($string) ? $string : str_replace($search, $replace, $string);
-
- // try to replace characters until there are no changes
- if ($string !== $replacedString) {
- return piwik_fix_lbrace($replacedString);
- }
-
- return $string;
+ return Common::fixLbrace($string);
}
function piwik_escape_filter(Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) {
@@ -153,13 +134,13 @@ public function __construct()
$chainLoader = new ChainLoader($loaders);
// Create new Twig Environment and set cache dir
- $templatesCompiledPath = StaticContainer::get('path.tmp.templates');
+ $cache = StaticContainer::get('twig.cache');
$this->twig = new Environment($chainLoader,
array(
'debug' => true, // to use {{ dump(var) }} in twig templates
'strict_variables' => true, // throw an exception if variables are invalid
- 'cache' => $templatesCompiledPath,
+ 'cache' => $cache,
)
);
$this->twig->addExtension(new DebugExtension());
@@ -185,6 +166,9 @@ public function __construct()
$this->twig->addFilter(new TwigFilter('ucwords', 'ucwords'));
$this->twig->addFilter(new TwigFilter('lcfirst', 'lcfirst'));
$this->twig->addFilter(new TwigFilter('ucfirst', 'ucfirst'));
+ $this->twig->addFilter(new TwigFilter('preg_replace', function ($subject, $pattern, $replacement) {
+ return preg_replace($pattern, $replacement, $subject);
+ }));
$this->addFunction_includeAssets();
$this->addFunction_linkTo();
@@ -376,6 +360,11 @@ protected function addFilter_notification()
protected function addFilter_safeDecodeRaw()
{
$rawSafeDecoded = new TwigFilter('rawSafeDecoded', function ($string) {
+
+ if ($string === null) {
+ return '';
+ }
+
$string = str_replace('+', '%2B', $string);
$string = str_replace(' ', html_entity_decode(' ', ENT_COMPAT | ENT_HTML401, 'UTF-8'), $string);
diff --git a/app/core/Updater.php b/app/core/Updater.php
index 407a0b72d..5c01f70f4 100644
--- a/app/core/Updater.php
+++ b/app/core/Updater.php
@@ -233,8 +233,8 @@ public function hasMajorDbUpdate()
*/
public function getSqlQueriesToExecute()
{
- $queries = array();
- $classNames = array();
+ $queries = [];
+ $classNames = [];
foreach ($this->componentsWithUpdateFile as $componentName => $componentUpdateInfo) {
foreach ($componentUpdateInfo as $file => $fileVersion) {
@@ -253,14 +253,16 @@ public function getSqlQueriesToExecute()
$classNames[] = $className;
- /** @var Updates $update */
- $update = StaticContainer::getContainer()->make($className);
- $migrationsForComponent = $update->getMigrations($this);
+ $migrationsForComponent = Access::doAsSuperUser(function() use ($className) {
+ /** @var Updates $update */
+ $update = StaticContainer::getContainer()->make($className);
+ return $update->getMigrations($this);
+ });
foreach ($migrationsForComponent as $index => $migration) {
$migration = $this->keepBcForOldMigrationQueryFormat($index, $migration);
$queries[] = $migration;
}
- $this->hasMajorDbUpdate = $this->hasMajorDbUpdate || call_user_func(array($className, 'isMajorUpdate'));
+ $this->hasMajorDbUpdate = $this->hasMajorDbUpdate || call_user_func([$className, 'isMajorUpdate']);
}
}
return $queries;
@@ -477,40 +479,34 @@ public function updateComponents($componentsWithUpdateFile)
}
if (!empty($componentsWithUpdateFile)) {
- $currentAccess = Access::getInstance();
- $hasSuperUserAccess = $currentAccess->hasSuperUserAccess();
- if (!$hasSuperUserAccess) {
- $currentAccess->setSuperUserAccess(true);
- }
-
- $pluginManager = \Piwik\Plugin\Manager::getInstance();
-
- // if error in any core update, show message + help message + EXIT
- // if errors in any plugins updates, show them on screen, disable plugins that errored + CONTINUE
- // if warning in any core update or in any plugins update, show message + CONTINUE
- // if no error or warning, success message + CONTINUE
- foreach ($componentsWithUpdateFile as $name => $filenames) {
- try {
- $warnings = array_merge($warnings, $this->update($name));
- } catch (UpdaterErrorException $e) {
- $errors[] = $e->getMessage();
- if ($name == 'core') {
- $coreError = true;
- break;
- } elseif ($pluginManager->isPluginActivated($name) && $pluginManager->isPluginBundledWithCore($name)) {
- $coreError = true;
- break;
- } elseif ($pluginManager->isPluginActivated($name)) {
- $pluginManager->deactivatePlugin($name);
- $deactivatedPlugins[] = $name;
+ Access::doAsSuperUser(function() use ($componentsWithUpdateFile, &$coreError, &$deactivatedPlugins, &$errors, &$warnings) {
+
+ $pluginManager = \Piwik\Plugin\Manager::getInstance();
+
+ // if error in any core update, show message + help message + EXIT
+ // if errors in any plugins updates, show them on screen, disable plugins that errored + CONTINUE
+ // if warning in any core update or in any plugins update, show message + CONTINUE
+ // if no error or warning, success message + CONTINUE
+ foreach ($componentsWithUpdateFile as $name => $filenames) {
+ try {
+ $warnings = array_merge($warnings, $this->update($name));
+ } catch (UpdaterErrorException $e) {
+ $errors[] = $e->getMessage();
+ if ($name == 'core') {
+ $coreError = true;
+ break;
+ } elseif ($pluginManager->isPluginActivated($name) && $pluginManager->isPluginBundledWithCore($name)) {
+ $coreError = true;
+ break;
+ } elseif ($pluginManager->isPluginActivated($name)) {
+ $pluginManager->deactivatePlugin($name);
+ $deactivatedPlugins[] = $name;
+ }
}
}
- }
- if (!$hasSuperUserAccess) {
- $currentAccess->setSuperUserAccess(false);
- }
+ });
}
Filesystem::deleteAllCacheOnUpdate();
diff --git a/app/core/Updater/Migration/Custom.php b/app/core/Updater/Migration/Custom.php
index c69dca9fd..3e4e92bea 100644
--- a/app/core/Updater/Migration/Custom.php
+++ b/app/core/Updater/Migration/Custom.php
@@ -7,8 +7,6 @@
*/
namespace Piwik\Updater\Migration;
-use Piwik\Config;
-use Piwik\Container\StaticContainer;
use Piwik\Updater\Migration;
/**
diff --git a/app/core/Updater/Migration/Db/DropColumns.php b/app/core/Updater/Migration/Db/DropColumns.php
index 5df61ddf0..f71c17969 100644
--- a/app/core/Updater/Migration/Db/DropColumns.php
+++ b/app/core/Updater/Migration/Db/DropColumns.php
@@ -7,7 +7,6 @@
*/
namespace Piwik\Updater\Migration\Db;
-use Piwik\Db;
use Piwik\DbHelper;
/**
diff --git a/app/core/Updates/4.0.0-b1.php b/app/core/Updates/4.0.0-b1.php
index 13c7bdd86..1aaa6cfee 100644
--- a/app/core/Updates/4.0.0-b1.php
+++ b/app/core/Updates/4.0.0-b1.php
@@ -25,7 +25,6 @@
use Piwik\Plugins\PagePerformance\Columns\TimeOnLoad;
use Piwik\Plugins\PagePerformance\Columns\TimeServer;
use Piwik\Plugins\PagePerformance\Columns\TimeTransfer;
-use Piwik\Plugins\UsersManager\Model;
use Piwik\Common;
use Piwik\Config;
use Piwik\Plugins\UserCountry\LocationProvider;
diff --git a/app/core/Updates/4.0.0-rc3.php b/app/core/Updates/4.0.0-rc3.php
index 86c9ca018..cda763e66 100644
--- a/app/core/Updates/4.0.0-rc3.php
+++ b/app/core/Updates/4.0.0-rc3.php
@@ -9,7 +9,6 @@
namespace Piwik\Updates;
-use Piwik\Config;
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
use Piwik\Updater\Migration\Factory as MigrationFactory;
diff --git a/app/core/Updates/4.0.0-rc4.php b/app/core/Updates/4.0.0-rc4.php
index ad408f1ed..2315f491c 100644
--- a/app/core/Updates/4.0.0-rc4.php
+++ b/app/core/Updates/4.0.0-rc4.php
@@ -9,7 +9,6 @@
namespace Piwik\Updates;
-use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\DataAccess\ArchiveTableCreator;
use Piwik\Date;
diff --git a/app/core/Updates/4.0.1-b1.php b/app/core/Updates/4.0.1-b1.php
index 852b3b934..c3b4d503d 100644
--- a/app/core/Updates/4.0.1-b1.php
+++ b/app/core/Updates/4.0.1-b1.php
@@ -10,12 +10,6 @@
namespace Piwik\Updates;
use Piwik\Common;
-use Piwik\Config;
-use Piwik\Container\StaticContainer;
-use Piwik\DataAccess\ArchiveTableCreator;
-use Piwik\Date;
-use Piwik\DbHelper;
-use Piwik\Plugin\ReleaseChannels;
use Piwik\SettingsPiwik;
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
diff --git a/app/core/Updates/4.1.2-b2.php b/app/core/Updates/4.1.2-b2.php
index 0c38c3848..bbabf2ca9 100644
--- a/app/core/Updates/4.1.2-b2.php
+++ b/app/core/Updates/4.1.2-b2.php
@@ -9,13 +9,7 @@
namespace Piwik\Updates;
-use Piwik\Container\StaticContainer;
-use Piwik\CronArchive;
use Piwik\DataAccess\ArchiveTableCreator;
-use Piwik\Date;
-use Piwik\Plugins\SegmentEditor\API;
-use Piwik\Archive\ArchiveInvalidator;
-use Piwik\ArchiveProcessor\Rules;
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
use Piwik\Updater\Migration\Factory as MigrationFactory;
diff --git a/app/core/Updates/4.10.0-b1.php b/app/core/Updates/4.10.0-b1.php
new file mode 100644
index 000000000..df8d40804
--- /dev/null
+++ b/app/core/Updates/4.10.0-b1.php
@@ -0,0 +1,61 @@
+migration = $factory;
+ }
+
+ /**
+ * @param Updater $updater
+ *
+ * @return Migration[]
+ */
+ public function getMigrations(Updater $updater)
+ {
+ $table = Common::prefixTable('report');
+ $invalidCount = Db::fetchOne(
+ "SELECT COUNT(*) FROM $table WHERE reports = ? OR parameters = ?",
+ ['Array', 'Array']
+ );
+
+ if (0 === (int) $invalidCount) {
+ return [];
+ }
+
+ return [
+ $this->migration->db->sql("DELETE FROM " . $table . " WHERE reports = 'Array' OR parameters = 'Array'")
+ ];
+ }
+
+ public function doUpdate(Updater $updater)
+ {
+ $updater->executeMigrations(__FILE__, $this->getMigrations($updater));
+ }
+}
diff --git a/app/core/Updates/4.3.0-b3.php b/app/core/Updates/4.3.0-b3.php
index d9588f1d3..14a79f575 100644
--- a/app/core/Updates/4.3.0-b3.php
+++ b/app/core/Updates/4.3.0-b3.php
@@ -11,10 +11,7 @@
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
-use Piwik\Updater\Migration;
use Piwik\Updater\Migration\Factory as MigrationFactory;
-use Piwik\Db;
-use Piwik\Common;
/**
* Update for version 4.3.0-b3.
diff --git a/app/core/Updates/4.3.0-b4.php b/app/core/Updates/4.3.0-b4.php
index de579b9c1..f0ced8b9e 100644
--- a/app/core/Updates/4.3.0-b4.php
+++ b/app/core/Updates/4.3.0-b4.php
@@ -11,7 +11,6 @@
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
-use Piwik\Updater\Migration;
use Piwik\Updater\Migration\Factory as MigrationFactory;
use Piwik\Db;
use Piwik\Common;
diff --git a/app/core/Updates/4.3.0-rc2.php b/app/core/Updates/4.3.0-rc2.php
index 924699772..09ad6f2f2 100644
--- a/app/core/Updates/4.3.0-rc2.php
+++ b/app/core/Updates/4.3.0-rc2.php
@@ -11,10 +11,7 @@
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
-use Piwik\Updater\Migration;
use Piwik\Updater\Migration\Factory as MigrationFactory;
-use Piwik\Db;
-use Piwik\Common;
/**
* Update for version 4.3.0-rc2.
diff --git a/app/core/Updates/4.5.0-b1.php b/app/core/Updates/4.5.0-b1.php
index 1ac0cae44..3cd30ac85 100644
--- a/app/core/Updates/4.5.0-b1.php
+++ b/app/core/Updates/4.5.0-b1.php
@@ -9,7 +9,6 @@
namespace Piwik\Updates;
-use Piwik\DbHelper;
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
use Piwik\Updater\Migration\Factory as MigrationFactory;
diff --git a/app/core/Updates/4.6.0-b1.php b/app/core/Updates/4.6.0-b1.php
index 557ed9b95..d48a72ea4 100644
--- a/app/core/Updates/4.6.0-b1.php
+++ b/app/core/Updates/4.6.0-b1.php
@@ -11,7 +11,6 @@
use Piwik\Updater;
use Piwik\Updates as PiwikUpdates;
-use Piwik\Updater\Migration;
use Piwik\Updater\Migration\Factory as MigrationFactory;
class Updates_4_6_0_b1 extends PiwikUpdates
diff --git a/app/core/Updates/4.7.0-b2.php b/app/core/Updates/4.7.0-b2.php
new file mode 100644
index 000000000..7d57ee147
--- /dev/null
+++ b/app/core/Updates/4.7.0-b2.php
@@ -0,0 +1,67 @@
+migration = $factory;
+ }
+
+ /**
+ * Here you can define one or multiple SQL statements that should be executed during the update.
+ *
+ * @param Updater $updater
+ *
+ * @return Migration[]
+ */
+ public function getMigrations(Updater $updater)
+ {
+ $migrations = [];
+
+ // add column to track the last change a user viewed the changes list
+ $migrations[] = $this->migration->db->addColumn('user', 'idchange_last_viewed',
+ 'INTEGER UNSIGNED NULL');
+
+ $migrations[] = $this->migration->db->createTable('changes', array(
+ 'idchange' => 'INT(11) NOT NULL AUTO_INCREMENT',
+ 'created_time' => 'DATETIME NOT NULL',
+ 'plugin_name' => 'VARCHAR(255) NOT NULL',
+ 'version' => 'VARCHAR(20) NOT NULL',
+ 'title' => 'VARCHAR(255) NOT NULL',
+ 'description' => 'TEXT NOT NULL',
+ 'link_name' => 'VARCHAR(255) NULL',
+ 'link' => 'VARCHAR(255) NULL',
+ ), $primaryKey = 'idchange');
+
+ return $migrations;
+ }
+
+ public function doUpdate(Updater $updater)
+ {
+ $updater->executeMigrations(__FILE__, $this->getMigrations($updater));
+ }
+
+}
diff --git a/app/core/Updates/4.7.1-b1.php b/app/core/Updates/4.7.1-b1.php
new file mode 100644
index 000000000..b543b812b
--- /dev/null
+++ b/app/core/Updates/4.7.1-b1.php
@@ -0,0 +1,57 @@
+migration = $factory;
+ }
+
+ /**
+ * Here you can define one or multiple SQL statements that should be executed during the update.
+ *
+ * @param Updater $updater
+ *
+ * @return Migration[]
+ */
+ public function getMigrations(Updater $updater)
+ {
+ $migrations = [];
+
+ $migrations[] = $this->migration->db->changeColumn('changes', 'plugin_name', 'plugin_name', 'VARCHAR(60) NOT NULL');
+
+ $migrations[] = $this->migration->db->dropIndex('changes', 'unique_plugin_version_title');
+ $migrations[] = $this->migration->db->addUniqueKey('changes', ['plugin_name', 'version', 'title(100)'], 'unique_plugin_version_title');
+
+ return $migrations;
+ }
+
+ public function doUpdate(Updater $updater)
+ {
+ $updater->executeMigrations(__FILE__, $this->getMigrations($updater));
+ }
+
+}
diff --git a/app/core/Updates/5.0.0-b1.php b/app/core/Updates/5.0.0-b1.php
new file mode 100644
index 000000000..883788132
--- /dev/null
+++ b/app/core/Updates/5.0.0-b1.php
@@ -0,0 +1,91 @@
+migration = $factory;
+
+ $this->tableName = Common::prefixTable('log_visit');
+ $this->indexName = 'index_idsite_idvisitor';
+ }
+
+ public function doUpdate(Updater $updater)
+ {
+ $updater->executeMigrations(__FILE__, $this->getMigrations($updater));
+ }
+
+ public function getMigrations(Updater $updater)
+ {
+ if ($this->requiresUpdatedLogVisitTableIndex()) {
+ return $this->getLogVisitTableMigrations();
+ }
+
+ return [];
+ }
+
+ private function getLogVisitTableMigrations()
+ {
+ $migrations = [];
+
+ $migrations[] = $this->migration->db->dropIndex('log_visit', $this->indexName);
+
+ // Using the custom `sql` method instead of the `addIndex` method as it doesn't support DESC collation
+ $migrations[] = $this->migration->db->sql(
+ "ALTER TABLE `{$this->tableName}` ADD INDEX `{$this->indexName}` (`idsite`, `idvisitor`, `visit_last_action_time` DESC)",
+ [DbAlias::ERROR_CODE_DUPLICATE_KEY, DbAlias::ERROR_CODE_KEY_COLUMN_NOT_EXISTS]
+ );
+
+ return $migrations;
+ }
+
+ private function requiresUpdatedLogVisitTableIndex()
+ {
+ $sql = "SHOW INDEX FROM `{$this->tableName}` WHERE Key_name = '{$this->indexName}'";
+
+ $result = Db::fetchAll($sql);
+
+ if (empty($result)) {
+ // No index present - should be added
+ return true;
+ }
+
+ // Check that the $result contains all the required column names. This is required as there was a previous index
+ // with the same name that only consisted of two columns. We want to check this index is built with all three.
+ // $diff will be empty if all three columns are found, meaning that the index already exists.
+ $diff = array_diff(['idsite', 'idvisitor', 'visit_last_action_time'], array_column($result, 'Column_name'));
+
+ if (!$diff) {
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/app/core/Url.php b/app/core/Url.php
index a79fdecb5..cc572aed0 100644
--- a/app/core/Url.php
+++ b/app/core/Url.php
@@ -1,4 +1,5 @@
General['proxy_uri_header'])
+ if (
+ isset(Config::getInstance()->General['proxy_uri_header'])
&& Config::getInstance()->General['proxy_uri_header'] == 1
&& !empty($_SERVER['HTTP_X_FORWARDED_URI'])
) {
@@ -206,16 +209,17 @@ public static function getCurrentScheme()
* value from the request.
* @return bool `true` if valid; `false` otherwise.
*/
- public static function isValidHost($host = false)
+ public static function isValidHost($host = false): bool
{
// only do trusted host check if it's enabled
- if (isset(Config::getInstance()->General['enable_trusted_host_check'])
+ if (
+ isset(Config::getInstance()->General['enable_trusted_host_check'])
&& Config::getInstance()->General['enable_trusted_host_check'] == 0
) {
return true;
}
- if ($host === false) {
+ if (false === $host || null === $host) {
$host = self::getHostFromServerVariable();
if (empty($host)) {
// if no current host, assume valid
@@ -277,12 +281,13 @@ public static function saveCORSHostnameInConfig($host)
protected static function saveHostsnameInConfig($host, $domain, $key)
{
- if (Piwik::hasUserSuperUserAccess()
+ if (
+ Piwik::hasUserSuperUserAccess()
&& file_exists(Config::getLocalConfigPath())
) {
$config = Config::getInstance()->$domain;
if (!is_array($host)) {
- $host = array($host);
+ $host = [$host];
}
$host = array_filter($host);
if (empty($host)) {
@@ -339,6 +344,21 @@ protected static function getHostFromServerVariable()
return false;
}
+ /**
+ * Returns the valid hostname (according to RFC standards) as a string; else it will return false if it isn't valid.
+ * If the hostname isn't supplied it will default to using Url::getHost
+ * Note: this will not verify if the hostname is trusted.
+ * @param $hostname
+ * @return false|string
+ */
+ public static function getRFCValidHostname($hostname = null)
+ {
+ if (empty($hostname)) {
+ $hostname = self::getHost(false);
+ }
+ return filter_var($hostname, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME);
+ }
+
/**
* Sets the host. Useful for CLI scripts, eg. core:archive command
*
@@ -363,7 +383,7 @@ public static function setHost($host)
*/
public static function getCurrentHost($default = 'unknown', $checkTrustedHost = true)
{
- $hostHeaders = array();
+ $hostHeaders = [];
$config = Config::getInstance()->General;
if (isset($config['proxy_host_headers'])) {
@@ -371,7 +391,7 @@ public static function getCurrentHost($default = 'unknown', $checkTrustedHost =
}
if (!is_array($hostHeaders)) {
- $hostHeaders = array();
+ $hostHeaders = [];
}
$host = self::getHost($checkTrustedHost);
@@ -390,7 +410,8 @@ public static function getCurrentHost($default = 'unknown', $checkTrustedHost =
public static function getCurrentQueryString()
{
$url = '';
- if (isset($_SERVER['QUERY_STRING'])
+ if (
+ isset($_SERVER['QUERY_STRING'])
&& !empty($_SERVER['QUERY_STRING'])
) {
$url .= "?" . $_SERVER['QUERY_STRING'];
@@ -491,7 +512,8 @@ public static function redirectToReferrer()
private static function redirectToUrlNoExit($url)
{
- if (UrlHelper::isLookLikeUrl($url)
+ if (
+ UrlHelper::isLookLikeUrl($url)
|| strpos($url, 'index.php') === 0
) {
Common::sendResponseCode(302);
@@ -568,13 +590,13 @@ public static function isLocalUrl($url)
// handle host name mangling
$requestUri = isset($_SERVER['SCRIPT_URI']) ? $_SERVER['SCRIPT_URI'] : '';
$parseRequest = @parse_url($requestUri);
- $hosts = array(self::getHost(), self::getCurrentHost());
+ $hosts = [self::getHost(), self::getCurrentHost()];
if (!empty($parseRequest['host'])) {
$hosts[] = $parseRequest['host'];
}
// drop port numbers from hostnames and IP addresses
- $hosts = array_map(array('self', 'getHostSanitized'), $hosts);
+ $hosts = array_map(['self', 'getHostSanitized'], $hosts);
$disableHostCheck = Config::getInstance()->General['enable_trusted_host_check'] == 0;
// compare scheme and host
@@ -583,7 +605,7 @@ public static function isLocalUrl($url)
return !empty($host)
&& ($disableHostCheck || in_array($host, $hosts))
&& !empty($parsedUrl['scheme'])
- && in_array($parsedUrl['scheme'], array('http', 'https'));
+ && in_array($parsedUrl['scheme'], ['http', 'https']);
}
/**
@@ -635,7 +657,7 @@ public static function getCorsHostsFromConfig()
* Returns hostname, without port numbers
*
* @param $host
- * @return array
+ * @return string
*/
public static function getHostSanitized($host)
{
@@ -650,12 +672,12 @@ protected static function getHostsFromConfig($domain, $key)
$config = @Config::getInstance()->$domain;
if (!isset($config[$key])) {
- return array();
+ return [];
}
$hosts = $config[$key];
if (!is_array($hosts)) {
- return array();
+ return [];
}
return $hosts;
}
@@ -735,7 +757,7 @@ private static function getAlwaysTrustedHosts()
*/
public static function getLocalHostnames()
{
- return array('localhost', '127.0.0.1', '::1', '[::1]', '[::]', '0000::1', '0177.0.0.1', '2130706433', '[0:0:0:0:0:ffff:127.0.0.1]');
+ return ['localhost', '127.0.0.1', '::1', '[::1]', '[::]', '0000::1', '0177.0.0.1', '2130706433', '[0:0:0:0:0:ffff:127.0.0.1]'];
}
/**
@@ -769,10 +791,10 @@ protected static function getCurrentSchemeFromRequestHeader()
return 'http';
}
- if ((isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] === true))
+ if (
+ (isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] === true))
|| (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
) {
-
return 'https';
}
return 'http';
@@ -796,7 +818,8 @@ public static function getHostFromServerNameVar()
{
$host = @$_SERVER['SERVER_NAME'];
if (!empty($host)) {
- if (strpos($host, ':') === false
+ if (
+ strpos($host, ':') === false
&& !empty($_SERVER['SERVER_PORT'])
&& $_SERVER['SERVER_PORT'] != 80
&& $_SERVER['SERVER_PORT'] != 443
diff --git a/app/core/UrlHelper.php b/app/core/UrlHelper.php
index 2a0fc4cb1..94c8ff9d5 100644
--- a/app/core/UrlHelper.php
+++ b/app/core/UrlHelper.php
@@ -202,7 +202,7 @@ public static function getParseUrlReverse($parsed)
*/
public static function getArrayFromQueryString($urlQuery)
{
- if (strlen($urlQuery) == 0) {
+ if (empty($urlQuery)) {
return array();
}
diff --git a/app/core/Validators/CharacterLength.php b/app/core/Validators/CharacterLength.php
index d40b11bfc..6e235bf08 100644
--- a/app/core/Validators/CharacterLength.php
+++ b/app/core/Validators/CharacterLength.php
@@ -9,7 +9,6 @@
namespace Piwik\Validators;
-use Piwik\Common;
use Piwik\Piwik;
class CharacterLength extends BaseValidator
diff --git a/app/core/Version.php b/app/core/Version.php
index 130102258..0b44b74cd 100644
--- a/app/core/Version.php
+++ b/app/core/Version.php
@@ -1,4 +1,5 @@
save('cssCacheBusterId', $cssCacheBusterId);
}
- $tagJs = 'cb=' . $cacheBuster->piwikVersionBasedCacheBuster();
+ $tagJs = 'cb=' . ($this->cacheBuster ?? $cacheBuster->piwikVersionBasedCacheBuster());
$tagCss = 'cb=' . $cssCacheBusterId;
$pattern = array(
'~
diff --git a/app/plugins/CoreAdminHome/vue/src/BrandingSettings/BrandingSettings.adapter.ts b/app/plugins/CoreAdminHome/vue/src/BrandingSettings/BrandingSettings.adapter.ts
new file mode 100644
index 000000000..67a669560
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/BrandingSettings/BrandingSettings.adapter.ts
@@ -0,0 +1,49 @@
+/*!
+ * 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 'CoreHome';
+import BrandingSettings from './BrandingSettings.vue';
+
+export default createAngularJsAdapter({
+ component: BrandingSettings,
+ scope: {
+ fileUploadEnabled: {
+ angularJsBind: '<',
+ },
+ logosWriteable: {
+ angularJsBind: '<',
+ },
+ useCustomLogo: {
+ angularJsBind: '<',
+ },
+ pathUserLogoDirectory: {
+ angularJsBind: '<',
+ },
+ pathUserLogo: {
+ angularJsBind: '<',
+ },
+ pathUserLogoSmall: {
+ angularJsBind: '<',
+ },
+ pathUserLogoSvg: {
+ angularJsBind: '<',
+ },
+ hasUserLogo: {
+ angularJsBind: '<',
+ },
+ pathUserFavicon: {
+ angularJsBind: '<',
+ },
+ hasUserFavicon: {
+ angularJsBind: '<',
+ },
+ isPluginsAdminEnabled: {
+ angularJsBind: '<',
+ },
+ },
+ directiveName: 'matomoBrandingSettings',
+});
diff --git a/app/plugins/CoreAdminHome/vue/src/BrandingSettings/BrandingSettings.vue b/app/plugins/CoreAdminHome/vue/src/BrandingSettings/BrandingSettings.vue
new file mode 100644
index 000000000..631250639
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/BrandingSettings/BrandingSettings.vue
@@ -0,0 +1,321 @@
+
+
+
+
+
+
{{ translate('CoreAdminHome_CustomLogoHelpText') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreAdminHome/vue/src/ImageTrackingCodeGenerator/ImageTrackingCodeGenerator.adapter.ts b/app/plugins/CoreAdminHome/vue/src/ImageTrackingCodeGenerator/ImageTrackingCodeGenerator.adapter.ts
new file mode 100644
index 000000000..84e06eef0
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/ImageTrackingCodeGenerator/ImageTrackingCodeGenerator.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 'CoreHome';
+import ImageTrackingCodeGenerator from './ImageTrackingCodeGenerator.vue';
+
+export default createAngularJsAdapter({
+ component: ImageTrackingCodeGenerator,
+ scope: {
+ defaultSite: {
+ angularJsBind: '<',
+ },
+ },
+ directiveName: 'matomoImageTrackingCodeGenerator',
+});
diff --git a/app/plugins/CoreAdminHome/vue/src/ImageTrackingCodeGenerator/ImageTrackingCodeGenerator.vue b/app/plugins/CoreAdminHome/vue/src/ImageTrackingCodeGenerator/ImageTrackingCodeGenerator.vue
new file mode 100644
index 000000000..0e8f02e1d
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/ImageTrackingCodeGenerator/ImageTrackingCodeGenerator.vue
@@ -0,0 +1,306 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ translate('CoreAdminHome_ImageTrackingLink') }}
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreAdminHome/vue/src/JsTrackingCodeGenerator/JsTrackingCodeGenerator.adapter.ts b/app/plugins/CoreAdminHome/vue/src/JsTrackingCodeGenerator/JsTrackingCodeGenerator.adapter.ts
new file mode 100644
index 000000000..daca15cb4
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/JsTrackingCodeGenerator/JsTrackingCodeGenerator.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 'CoreHome';
+import JsTrackingCodeGenerator from './JsTrackingCodeGenerator.vue';
+
+export default createAngularJsAdapter({
+ component: JsTrackingCodeGenerator,
+ scope: {
+ defaultSite: {
+ angularJsBind: '<',
+ },
+ maxCustomVariables: {
+ angularJsBind: '<',
+ },
+ serverSideDoNotTrackEnabled: {
+ angularJsBind: '<',
+ },
+ },
+ directiveName: 'matomoJsTrackingCodeGenerator',
+});
diff --git a/app/plugins/CoreAdminHome/vue/src/JsTrackingCodeGenerator/JsTrackingCodeGenerator.vue b/app/plugins/CoreAdminHome/vue/src/JsTrackingCodeGenerator/JsTrackingCodeGenerator.vue
new file mode 100644
index 000000000..de0dfb784
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/JsTrackingCodeGenerator/JsTrackingCodeGenerator.vue
@@ -0,0 +1,622 @@
+
+
+
+
+
+
+ {{ translate('CoreAdminHome_JSTrackingIntro1') }}
+
+ {{ translate('CoreAdminHome_JSTrackingIntro2') }}
+
+
+
+
+
+
+
+ {{ translate('SitesManager_InstallationGuides') }} :
+ WordPress |
+ Squarespace |
+ Wix |
+ SharePoint |
+ Joomla |
+ Shopify |
+ Google Tag Manager
+
+
+
+
+
+
+
+
+
+
+ {{ translate('CoreAdminHome_JSTracking_GroupPageTitlesByDomainDesc1', currentSiteHost) }}
+
+
+
+
+
+
+ {{ translate('CoreAdminHome_JSTracking_MergeAliasesDesc', currentSiteAlias) }}
+
+
+
+
+
+
+
+ {{ translate('Mobile_Advanced') }}
+
+
+ {{ translate('General_Show') }}
+ {{ translate('General_Hide') }}
+
+
+
+
+
+
+
+
+
+
+ {{ translate('General_Name') }}
+
+
+ {{ translate('General_Value') }}
+
+
+
+
+
+
+
+
+ {{ translate('CoreAdminHome_JSTracking_CrossDomain') }}
+
+ {{ translate('CoreAdminHome_JSTracking_CrossDomain_NeedsMultipleDomains') }}
+
+
+
+
+
+
+ {{ translate('CoreAdminHome_JSTracking_EnableDoNotTrackDesc') }}
+
+
+ {{ translate('CoreAdminHome_JSTracking_EnableDoNotTrack_AlreadyEnabled') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreAdminHome/vue/src/SmtpSettings/SmtpSettings.adapter.ts b/app/plugins/CoreAdminHome/vue/src/SmtpSettings/SmtpSettings.adapter.ts
new file mode 100644
index 000000000..21e752b3a
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/SmtpSettings/SmtpSettings.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 'CoreHome';
+import SmtpSettings from './SmtpSettings.vue';
+
+export default createAngularJsAdapter({
+ component: SmtpSettings,
+ scope: {
+ mail: {
+ angularJsBind: '<',
+ },
+ mailTypes: {
+ angularJsBind: '<',
+ },
+ mailEncryptions: {
+ angularJsBind: '<',
+ },
+ },
+ directiveName: 'matomoSmtpSettings',
+});
diff --git a/app/plugins/CoreAdminHome/vue/src/SmtpSettings/SmtpSettings.vue b/app/plugins/CoreAdminHome/vue/src/SmtpSettings/SmtpSettings.vue
new file mode 100644
index 000000000..64214e076
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/SmtpSettings/SmtpSettings.vue
@@ -0,0 +1,241 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreAdminHome/vue/src/TrackingFailures/FailureRow.vue b/app/plugins/CoreAdminHome/vue/src/TrackingFailures/FailureRow.vue
new file mode 100644
index 000000000..a1b48fb3c
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/TrackingFailures/FailureRow.vue
@@ -0,0 +1,67 @@
+
+ {{ failure.site_name }} ({{ translate('General_Id') }} {{ failure.idsite }})
+ {{ failure.problem }}
+ {{ failure.solution }} {{ translate('CoreAdminHome_LearnMore') }}
+ {{ failure.pretty_date_first_occurred }}
+ {{ failure.url }}
+
+ {{ limtedRequestUrl }}...
+ {{ failure.request_url }}
+
+
+
+
+
diff --git a/app/plugins/CoreAdminHome/vue/src/TrackingFailures/TrackingFailures.adapter.ts b/app/plugins/CoreAdminHome/vue/src/TrackingFailures/TrackingFailures.adapter.ts
new file mode 100644
index 000000000..2b7b6ac04
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/TrackingFailures/TrackingFailures.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 'CoreHome';
+import TrackingFailures from './TrackingFailures.vue';
+
+export default createAngularJsAdapter({
+ component: TrackingFailures,
+ directiveName: 'matomoTrackingFailures',
+});
diff --git a/app/plugins/CoreAdminHome/angularjs/trackingfailures/trackingfailures.directive.less b/app/plugins/CoreAdminHome/vue/src/TrackingFailures/TrackingFailures.less
similarity index 100%
rename from app/plugins/CoreAdminHome/angularjs/trackingfailures/trackingfailures.directive.less
rename to app/plugins/CoreAdminHome/vue/src/TrackingFailures/TrackingFailures.less
diff --git a/app/plugins/CoreAdminHome/vue/src/TrackingFailures/TrackingFailures.vue b/app/plugins/CoreAdminHome/vue/src/TrackingFailures/TrackingFailures.vue
new file mode 100644
index 000000000..d7cd39358
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/TrackingFailures/TrackingFailures.vue
@@ -0,0 +1,220 @@
+
+
+
+
+
+ {{ translate('CoreAdminHome_TrackingFailuresIntroduction', '2') }}
+
+
+
+
+
+
+
+ {{ translate('General_Measurable') }}
+ {{ translate('CoreAdminHome_Problem') }}
+ {{ translate('CoreAdminHome_Solution') }}
+ {{ translate('General_Date') }}
+ {{ translate('Actions_ColumnPageURL') }}
+
+ {{ translate('CoreAdminHome_TrackingURL') }}
+
+ {{ translate('General_Action') }}
+
+
+
+
+ {{ translate('CoreAdminHome_NoKnownFailures') }}
+
+
+
+
+
+
+
+
{{ translate('CoreAdminHome_ConfirmDeleteAllTrackingFailures') }}
+
+
+
+
+
{{ translate('CoreAdminHome_ConfirmDeleteThisTrackingFailure') }}
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreAdminHome/vue/src/index.ts b/app/plugins/CoreAdminHome/vue/src/index.ts
new file mode 100644
index 000000000..ebe1b72c7
--- /dev/null
+++ b/app/plugins/CoreAdminHome/vue/src/index.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 './ArchivingSettings/ArchivingSettings.adapter';
+import './BrandingSettings/BrandingSettings.adapter';
+import './SmtpSettings/SmtpSettings.adapter';
+import './JsTrackingCodeGenerator/JsTrackingCodeGenerator.adapter';
+import './ImageTrackingCodeGenerator/ImageTrackingCodeGenerator.adapter';
+import './TrackingFailures/TrackingFailures.adapter';
+
+export { default as ArchivingSettings } from './ArchivingSettings/ArchivingSettings.vue';
+export { default as BrandingSettings } from './BrandingSettings/BrandingSettings.vue';
+export { default as SmtpSettings } from './SmtpSettings/SmtpSettings.vue';
+export {
+ default as JsTrackingCodeGenerator,
+} from './JsTrackingCodeGenerator/JsTrackingCodeGenerator.vue';
+export {
+ default as ImageTrackingCodeGenerator,
+} from './ImageTrackingCodeGenerator/ImageTrackingCodeGenerator.vue';
+export { default as TrackingFailures } from './TrackingFailures/TrackingFailures.vue';
diff --git a/app/plugins/CoreConsole/Commands/ComputeJsAssetSize.php b/app/plugins/CoreConsole/Commands/ComputeJsAssetSize.php
index 9b0bd310e..0d6abab12 100644
--- a/app/plugins/CoreConsole/Commands/ComputeJsAssetSize.php
+++ b/app/plugins/CoreConsole/Commands/ComputeJsAssetSize.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\CoreConsole\Commands;
use Piwik\AssetManager;
-use Piwik\Common;
use Piwik\Development;
use Piwik\Metrics\Formatter;
use Piwik\Piwik;
@@ -18,6 +17,7 @@
use Piwik\Plugin\Manager;
use Piwik\ProxyHttp;
use Piwik\SettingsPiwik;
+use Piwik\Theme;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
@@ -25,12 +25,15 @@
class ComputeJsAssetSize extends ConsoleCommand
{
+ private $totals = [];
+
protected function configure()
{
$this->setName('development:compute-js-asset-size');
$this->setDescription('Generates production assets and computes the size of the resulting code.');
$this->addOption('exclude-angular', null, InputOption::VALUE_NONE);
$this->addOption('no-delete', null, InputOption::VALUE_NONE, 'Do not delete files after creating them.');
+ $this->addOption('plugin', null, InputOption::VALUE_REQUIRED, 'For submodule plugins and 3rd party plugins.');
}
public function isEnabled()
@@ -42,31 +45,36 @@ protected function execute(InputInterface $input, OutputInterface $output)
{
$excludeAngular = $input->getOption('exclude-angular');
$noDelete = $input->getOption('no-delete');
+ $plugin = $input->getOption('plugin');
$this->checkDevelopmentModeDisabled();
- $this->ensureThirdPartyPluginsActivated();
+
+ $this->ensureThirdPartyPluginsActivated($plugin);
$output->writeln("Building and printing sizes of built JS assets...");
+ $fetcher = $this->makeUmdFetcher();
+
if ($excludeAngular) {
$this->excludeAngular($output);
}
$this->deleteMergedAssets();
- $this->buildAssets();
+ $this->buildAssets($fetcher);
$output->writeln("");
- $this->printCurrentGitHashAndBranch($output, $excludeAngular);
+
+ $this->printCurrentGitHashAndBranch($output, $excludeAngular, $plugin);
$output->writeln("");
- $this->printFilesizes($output);
+ $this->printFilesizes($fetcher, $output);
if (!$noDelete) {
$this->deleteMergedAssets();
}
}
- private function ensureThirdPartyPluginsActivated()
+ private function ensureThirdPartyPluginsActivated($plugin = null)
{
$expectedPluginsLoadedAndActivated = [
"CorePluginsAdmin",
@@ -154,12 +162,19 @@ private function ensureThirdPartyPluginsActivated()
"WhiteLabel",
"WooCommerceAnalytics",
"AdvertisingConversionExport",
+ "AnonymousPiwikUsageMeasurement",
];
+ if ($plugin) {
+ $expectedPluginsLoadedAndActivated[] = $plugin;
+ }
+
if (is_file(PIWIK_INCLUDE_PATH . '/plugins/CoreVue/plugin.json')) {
$expectedPluginsLoadedAndActivated[] = "CoreVue";
}
+ $expectedPluginsLoadedAndActivated = array_unique($expectedPluginsLoadedAndActivated);
+
$pluginsLoadedAndActivated = Manager::getInstance()->getPluginsLoadedAndActivated();
$pluginsLoadedAndActivated = array_map(function (Plugin $p) { return $p->getPluginName(); }, $pluginsLoadedAndActivated);
@@ -187,10 +202,15 @@ private function excludeAngular(OutputInterface $output)
});
}
- private function buildAssets()
+ private function buildAssets(AssetManager\UIAssetFetcher\PluginUmdAssetFetcher $fetcher)
{
AssetManager::getInstance()->getMergedCoreJavaScript();
AssetManager::getInstance()->getMergedNonCoreJavaScript();
+
+ $chunks = $fetcher->getChunkFiles();
+ foreach ($chunks as $chunk) {
+ AssetManager::getInstance()->getMergedJavaScriptChunk($chunk->getChunkName());
+ }
}
private function deleteMergedAssets()
@@ -198,26 +218,40 @@ private function deleteMergedAssets()
AssetManager::getInstance()->removeMergedAssets();
}
- private function printFilesizes(OutputInterface $output)
+ private function printFilesizes(AssetManager\UIAssetFetcher\PluginUmdAssetFetcher $fetcher, OutputInterface $output)
{
$fileSizes = [];
$mergedCore = AssetManager::getInstance()->getMergedCoreJavaScript();
- $fileSizes[] = [$mergedCore->getRelativeLocation(), $this->getFileSize($mergedCore->getAbsoluteLocation()), $this->getGzippedFileSize($mergedCore->getAbsoluteLocation())];
+ $fileSizes[] = $this->getFileSizeRow($mergedCore);
$mergedNonCore = AssetManager::getInstance()->getMergedNonCoreJavaScript();
- $fileSizes[] = [$mergedNonCore->getRelativeLocation(), $this->getFileSize($mergedNonCore->getAbsoluteLocation()), $this->getGzippedFileSize($mergedNonCore->getAbsoluteLocation())];
+ $fileSizes[] = $this->getFileSizeRow($mergedNonCore);
+
+ $chunks = $fetcher->getChunkFiles();
+ foreach ($chunks as $chunk) {
+ $chunkAsset = AssetManager::getInstance()->getMergedJavaScriptChunk($chunk->getChunkName());
+ $fileSizes[] = $this->getFileSizeRow($chunkAsset);
+ }
+
+ $fileSizes[] = [];
+ $fileSizes[] = ['Total', $this->getFormattedSize($this->totals['merged']), $this->getFormattedSize($this->totals['gzip'])];
$table = new Table($output);
$table->setHeaders(['File', 'Size', 'Size (gzipped)'])->setRows($fileSizes);
$table->render();
}
- private function getFileSize($fileLocation)
+ private function getFileSize($fileLocation, $type)
{
- $formatter = new Formatter();
-
$size = filesize($fileLocation);
+ $this->totals[$type] = ($this->totals[$type] ?? 0) + $size;
+ return $this->getFormattedSize($size);
+ }
+
+ private function getFormattedSize($size)
+ {
+ $formatter = new Formatter();
$size = $formatter->getPrettySizeFromBytes($size, 'K', 2);
return $size;
}
@@ -240,14 +274,44 @@ private function getGzippedFileSize($path)
$compressedPath = dirname($path) . '/' . basename($path) . '.gz';
file_put_contents($compressedPath, $data);
- return $this->getFileSize($compressedPath);
+ return $this->getFileSize($compressedPath, 'gzip');
}
- private function printCurrentGitHashAndBranch(OutputInterface $output, $excludeAngular)
+ private function printCurrentGitHashAndBranch(OutputInterface $output, $excludeAngular, $plugin = null)
{
$branchName = trim(`git rev-parse --abbrev-ref HEAD`);
$lastCommit = trim(`git log --pretty=format:'%h' -n 1`);
- $output->writeln("$branchName ($lastCommit) " . ($excludeAngular ? '(without angularjs)' : '') . " ");
+ $pluginSuffix = '';
+ if ($plugin) {
+ $prefix = 'cd "' . addslashes(PIWIK_INCLUDE_PATH . '/plugins/' . $plugin) . '"; ';
+
+ $pluginBranchName = trim(`$prefix git rev-parse --abbrev-ref HEAD`);
+ $pluginLastCommit = trim(`$prefix git log --pretty=format:'%h' -n 1`);
+
+ $pluginSuffix = " [$plugin: $pluginBranchName ($pluginLastCommit)]";
+ }
+
+ $output->writeln("$branchName ($lastCommit)$pluginSuffix "
+ . ($excludeAngular ? '(without angularjs)' : '') . " ");
+ }
+
+ private function makeUmdFetcher()
+ {
+ $plugins = Manager::getInstance()->getPluginsLoadedAndActivated();
+ $pluginNames = array_map(function ($p) { return $p->getPluginName(); }, $plugins);
+
+ $theme = Manager::getInstance()->getThemeEnabled();
+ if (!empty($theme)) {
+ $theme = new Theme();
+ }
+
+ $fetcher = new AssetManager\UIAssetFetcher\PluginUmdAssetFetcher($pluginNames, $theme, null);
+ return $fetcher;
+ }
+
+ private function getFileSizeRow(AssetManager\UIAsset $asset)
+ {
+ return [$asset->getRelativeLocation(), $this->getFileSize($asset->getAbsoluteLocation(), 'merged'), $this->getGzippedFileSize($asset->getAbsoluteLocation())];
}
}
diff --git a/app/plugins/CoreConsole/Commands/CoreArchiver.php b/app/plugins/CoreConsole/Commands/CoreArchiver.php
index 9f4f3cd87..25cef83c8 100644
--- a/app/plugins/CoreConsole/Commands/CoreArchiver.php
+++ b/app/plugins/CoreConsole/Commands/CoreArchiver.php
@@ -46,6 +46,8 @@ public static function makeArchiver($url, InputInterface $input)
$archiver->concurrentRequestsPerWebsite = $input->getOption('concurrent-requests-per-website');
$archiver->maxConcurrentArchivers = $input->getOption('concurrent-archivers');
$archiver->shouldArchiveAllSites = $input->getOption('force-all-websites');
+ $archiver->maxSitesToProcess = $input->getOption('max-websites-to-process');
+ $archiver->maxArchivesToProcess = $input->getOption('max-archives-to-process');
$archiver->setUrlToPiwik($url);
$archiveFilter = new CronArchive\ArchiveFilter();
@@ -111,6 +113,10 @@ public static function configureArchiveCommand(ConsoleCommand $command)
"When processing a website and its segments, number of requests to process in parallel", CronArchive::MAX_CONCURRENT_API_REQUESTS);
$command->addOption('concurrent-archivers', null, InputOption::VALUE_OPTIONAL,
"The number of max archivers to run in parallel. Depending on how you start the archiver as a cronjob, you may need to double the amount of archivers allowed if the same process appears twice in the `ps ex` output.", false);
+ $command->addOption('max-websites-to-process', null, InputOption::VALUE_REQUIRED,
+ "Maximum number of websites to process during a single execution of the archiver. Can be used to limit the process lifetime e.g. to avoid increasing memory usage.");
+ $command->addOption('max-archives-to-process', null, InputOption::VALUE_REQUIRED,
+ "Maximum number of archives to process during a single execution of the archiver. Can be used to limit the process lifetime e.g. to avoid increasing memory usage.");
$command->addOption('disable-scheduled-tasks', null, InputOption::VALUE_NONE,
"Skips executing Scheduled tasks (sending scheduled reports, db optimization, etc.).");
$command->addOption('accept-invalid-ssl-certificate', null, InputOption::VALUE_NONE,
diff --git a/app/plugins/CoreConsole/Commands/DevelopmentEnable.php b/app/plugins/CoreConsole/Commands/DevelopmentEnable.php
index ec1df4735..c13376119 100644
--- a/app/plugins/CoreConsole/Commands/DevelopmentEnable.php
+++ b/app/plugins/CoreConsole/Commands/DevelopmentEnable.php
@@ -14,7 +14,6 @@
use Piwik\SettingsPiwik;
use Piwik\Plugin\ConsoleCommand;
use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
/**
diff --git a/app/plugins/CoreConsole/Commands/GenerateDimension.php b/app/plugins/CoreConsole/Commands/GenerateDimension.php
index 9168e0bcc..f8efe64e4 100644
--- a/app/plugins/CoreConsole/Commands/GenerateDimension.php
+++ b/app/plugins/CoreConsole/Commands/GenerateDimension.php
@@ -12,7 +12,6 @@
use Piwik\Common;
use Piwik\DbHelper;
use Piwik\Plugin\Manager;
-use Piwik\Plugin\Report;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
diff --git a/app/plugins/CoreHome/Categories/VisitorsCategory.php b/app/plugins/CoreHome/Categories/VisitorsCategory.php
index 8cbbbb903..ad75ace57 100644
--- a/app/plugins/CoreHome/Categories/VisitorsCategory.php
+++ b/app/plugins/CoreHome/Categories/VisitorsCategory.php
@@ -10,7 +10,6 @@
use Piwik\Category\Category;
use Piwik\Piwik;
-use Piwik\Url;
class VisitorsCategory extends Category
{
diff --git a/app/plugins/CoreHome/Columns/Metrics/ConversionRate.php b/app/plugins/CoreHome/Columns/Metrics/ConversionRate.php
index 16dd7bba1..31447dd72 100644
--- a/app/plugins/CoreHome/Columns/Metrics/ConversionRate.php
+++ b/app/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/app/plugins/CoreHome/Columns/Metrics/VisitsPercent.php b/app/plugins/CoreHome/Columns/Metrics/VisitsPercent.php
index 325e1e3e4..49f18a8aa 100644
--- a/app/plugins/CoreHome/Columns/Metrics/VisitsPercent.php
+++ b/app/plugins/CoreHome/Columns/Metrics/VisitsPercent.php
@@ -13,7 +13,6 @@
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/app/plugins/CoreHome/Columns/ServerMinute.php b/app/plugins/CoreHome/Columns/ServerMinute.php
index 8f2c761d3..ec1128351 100644
--- a/app/plugins/CoreHome/Columns/ServerMinute.php
+++ b/app/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/app/plugins/CoreHome/Columns/ServerTime.php b/app/plugins/CoreHome/Columns/ServerTime.php
index d2005f11f..9c41d89db 100644
--- a/app/plugins/CoreHome/Columns/ServerTime.php
+++ b/app/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/app/plugins/CoreHome/Columns/UserId.php b/app/plugins/CoreHome/Columns/UserId.php
index db23f9b7f..bc0c77ab7 100644
--- a/app/plugins/CoreHome/Columns/UserId.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitFirstActionMinute.php b/app/plugins/CoreHome/Columns/VisitFirstActionMinute.php
index 1db6e914f..47e2d0ff6 100644
--- a/app/plugins/CoreHome/Columns/VisitFirstActionMinute.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitFirstActionTime.php b/app/plugins/CoreHome/Columns/VisitFirstActionTime.php
index 5f76c5076..56ee0231e 100644
--- a/app/plugins/CoreHome/Columns/VisitFirstActionTime.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitGoalBuyer.php b/app/plugins/CoreHome/Columns/VisitGoalBuyer.php
index 904519494..711380cf9 100644
--- a/app/plugins/CoreHome/Columns/VisitGoalBuyer.php
+++ b/app/plugins/CoreHome/Columns/VisitGoalBuyer.php
@@ -11,7 +11,6 @@
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/app/plugins/CoreHome/Columns/VisitLastActionDate.php b/app/plugins/CoreHome/Columns/VisitLastActionDate.php
index 6b2fd6756..9f0d1cdaf 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionDate.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionDayOfMonth.php b/app/plugins/CoreHome/Columns/VisitLastActionDayOfMonth.php
index e3ef6bd8a..c263c17cf 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionDayOfMonth.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionDayOfWeek.php b/app/plugins/CoreHome/Columns/VisitLastActionDayOfWeek.php
index 81c5df338..9bd42bdc0 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionDayOfWeek.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionDayOfYear.php b/app/plugins/CoreHome/Columns/VisitLastActionDayOfYear.php
index b00cea3c0..5e3449851 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionDayOfYear.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionMinute.php b/app/plugins/CoreHome/Columns/VisitLastActionMinute.php
index b3b50fbd5..a465916cb 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionMinute.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionMonth.php b/app/plugins/CoreHome/Columns/VisitLastActionMonth.php
index 92094685e..369d8bf77 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionMonth.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionQuarter.php b/app/plugins/CoreHome/Columns/VisitLastActionQuarter.php
index f55daec3e..196616945 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionQuarter.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionSecond.php b/app/plugins/CoreHome/Columns/VisitLastActionSecond.php
index 34dd1552b..291589883 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionSecond.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionTime.php b/app/plugins/CoreHome/Columns/VisitLastActionTime.php
index 2ec021f68..f40643f99 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionTime.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionWeekOfYear.php b/app/plugins/CoreHome/Columns/VisitLastActionWeekOfYear.php
index 2f3db58d9..44c21a067 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionWeekOfYear.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitLastActionYear.php b/app/plugins/CoreHome/Columns/VisitLastActionYear.php
index ffc3d2929..18d05db6e 100644
--- a/app/plugins/CoreHome/Columns/VisitLastActionYear.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitTotalTime.php b/app/plugins/CoreHome/Columns/VisitTotalTime.php
index 858028f59..0401a54e0 100644
--- a/app/plugins/CoreHome/Columns/VisitTotalTime.php
+++ b/app/plugins/CoreHome/Columns/VisitTotalTime.php
@@ -10,7 +10,6 @@
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/app/plugins/CoreHome/Columns/VisitorFingerprint.php b/app/plugins/CoreHome/Columns/VisitorFingerprint.php
index cc216a042..e88b3b5b6 100644
--- a/app/plugins/CoreHome/Columns/VisitorFingerprint.php
+++ b/app/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/app/plugins/CoreHome/Columns/VisitorId.php b/app/plugins/CoreHome/Columns/VisitorId.php
index f6b29699b..ff1596837 100644
--- a/app/plugins/CoreHome/Columns/VisitorId.php
+++ b/app/plugins/CoreHome/Columns/VisitorId.php
@@ -1,4 +1,5 @@
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/app/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php b/app/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php
index bed71d332..64e2a3403 100644
--- a/app/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php
+++ b/app/plugins/CoreHome/Columns/VisitorSecondsSinceFirst.php
@@ -11,7 +11,6 @@
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/app/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php b/app/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php
index 8837bfdd7..0e67fe418 100644
--- a/app/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php
+++ b/app/plugins/CoreHome/Columns/VisitorSecondsSinceOrder.php
@@ -10,7 +10,6 @@
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/app/plugins/CoreHome/Controller.php b/app/plugins/CoreHome/Controller.php
index a8f6fa09b..6982562ea 100644
--- a/app/plugins/CoreHome/Controller.php
+++ b/app/plugins/CoreHome/Controller.php
@@ -24,7 +24,6 @@
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 @@ public function saveViewDataTableParameters()
ViewDataTableManager::saveViewDataTableParameters($login, $reportId, $parameters, $containerId);
}
+
}
diff --git a/app/plugins/CoreHome/CoreHome.php b/app/plugins/CoreHome/CoreHome.php
index 4464aa1cd..3c9aff226 100644
--- a/app/plugins/CoreHome/CoreHome.php
+++ b/app/plugins/CoreHome/CoreHome.php
@@ -14,6 +14,7 @@
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 @@ public function getStylesheetFiles(&$stylesheets)
$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 @@ public function getJsFiles(&$jsFiles)
$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 @@ public function getJsFiles(&$jsFiles)
$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 @@ public function getJsFiles(&$jsFiles)
$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 @@ public function getJsFiles(&$jsFiles)
$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 @@ public function getClientSideTranslationKeys(&$translationKeys)
$translationKeys[] = 'General_PreviousYear';
$translationKeys[] = 'CoreHome_ReportingCategoryHelpPrefix';
$translationKeys[] = 'CoreHome_TechDeprecationWarning';
+ $translationKeys[] = 'CoreHome_StartDate';
+ $translationKeys[] = 'CoreHome_EndDate';
+ $translationKeys[] = 'CoreHome_DataForThisReportHasBeenDisabled';
}
}
diff --git a/app/plugins/CoreHome/Menu.php b/app/plugins/CoreHome/Menu.php
index 3b3051f60..6cade0124 100644
--- a/app/plugins/CoreHome/Menu.php
+++ b/app/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/app/plugins/CoreHome/Tracker/VisitRequestProcessor.php b/app/plugins/CoreHome/Tracker/VisitRequestProcessor.php
index 65906cd45..74abe8ffd 100644
--- a/app/plugins/CoreHome/Tracker/VisitRequestProcessor.php
+++ b/app/plugins/CoreHome/Tracker/VisitRequestProcessor.php
@@ -10,7 +10,6 @@
use Piwik\Common;
use Piwik\Date;
-use Piwik\Config;
use Piwik\EventDispatcher;
use Piwik\Exception\UnexpectedWebsiteFoundException;
use Piwik\Tracker\Cache;
diff --git a/app/plugins/CoreHome/Widgets/GetDonateForm.php b/app/plugins/CoreHome/Widgets/GetDonateForm.php
index 72431e2d7..c5ea5cf46 100644
--- a/app/plugins/CoreHome/Widgets/GetDonateForm.php
+++ b/app/plugins/CoreHome/Widgets/GetDonateForm.php
@@ -13,7 +13,6 @@
use Piwik\Widget\Widget;
use Piwik\Widget\WidgetConfig;
use Piwik\Translation\Translator;
-use Piwik\View;
class GetDonateForm extends Widget
{
diff --git a/app/plugins/CoreHome/Widgets/GetSystemSummary.php b/app/plugins/CoreHome/Widgets/GetSystemSummary.php
index 3d56a9979..e09fe22d4 100644
--- a/app/plugins/CoreHome/Widgets/GetSystemSummary.php
+++ b/app/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 @@
class GetSystemSummary extends Widget
{
+ const TEST_MYSQL_VERSION = 'mysql-version-redacted';
/**
* @var StoredSegmentService
*/
@@ -108,6 +108,10 @@ public function render()
private function getMySqlVersion()
{
+ if (defined('PIWIK_TEST_MODE')) {
+ return self::TEST_MYSQL_VERSION;
+ }
+
$db = Db::get();
return $db->getServerVersion();
}
diff --git a/app/plugins/CoreHome/angularjs/field-array/field-array.directive.html b/app/plugins/CoreHome/angularjs/field-array/field-array.directive.html
deleted file mode 100644
index 1ce3fcaec..000000000
--- a/app/plugins/CoreHome/angularjs/field-array/field-array.directive.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
\ No newline at end of file
diff --git a/app/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html b/app/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html
deleted file mode 100644
index a14cc99c3..000000000
--- a/app/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.html
+++ /dev/null
@@ -1,61 +0,0 @@
-
\ No newline at end of file
diff --git a/app/plugins/CoreHome/angularjs/period-selector/period-selector.directive.html b/app/plugins/CoreHome/angularjs/period-selector/period-selector.directive.html
deleted file mode 100644
index a93c638b5..000000000
--- a/app/plugins/CoreHome/angularjs/period-selector/period-selector.directive.html
+++ /dev/null
@@ -1,134 +0,0 @@
-
-
-
- {{ periodSelector.getCurrentlyViewingText() }}
-
-
-
-
-
-
-
{{ 'General_Period'|translate }}
-
-
-
-
- {{ periodSelector.getPeriodDisplayText(period) }}
-
-
-
-
-
-
-
-
-
- {{ 'General_CompareTo'|translate }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ 'SegmentEditor_LoadingSegmentedDataMayTakeSomeTime'|translate }}
-
-
-
-
diff --git a/app/plugins/CoreHome/angularjs/progressbar/progressbar.directive.html b/app/plugins/CoreHome/angularjs/progressbar/progressbar.directive.html
deleted file mode 100644
index 5bbb4e440..000000000
--- a/app/plugins/CoreHome/angularjs/progressbar/progressbar.directive.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CoreHome/angularjs/quick-access/quick-access.directive.html b/app/plugins/CoreHome/angularjs/quick-access/quick-access.directive.html
deleted file mode 100644
index c28c8f1d1..000000000
--- a/app/plugins/CoreHome/angularjs/quick-access/quick-access.directive.html
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-
-
-
- {{ 'General_SearchNoResults' | translate }}
-
-
-
- {{ 'SitesManager_Sites' | translate }}
- {{ 'MultiSites_LoadingWebsites' | translate }}
-
-
-
-
-
diff --git a/app/plugins/CoreHome/angularjs/report-export/reportexport.popover.html b/app/plugins/CoreHome/angularjs/report-export/reportexport.popover.html
deleted file mode 100644
index f20642460..000000000
--- a/app/plugins/CoreHome/angularjs/report-export/reportexport.popover.html
+++ /dev/null
@@ -1,76 +0,0 @@
-
\ No newline at end of file
diff --git a/app/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html b/app/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html
deleted file mode 100644
index ff3a54906..000000000
--- a/app/plugins/CoreHome/angularjs/reporting-menu/reportingmenu.directive.html
+++ /dev/null
@@ -1,72 +0,0 @@
-
diff --git a/app/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html b/app/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html
deleted file mode 100644
index 4abf3a27e..000000000
--- a/app/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
{{ 'CoreHome_NoSuchPage'|translate }}
-
-
-
diff --git a/app/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.less b/app/plugins/CoreHome/angularjs/reporting-page/reportingpage.directive.less
deleted file mode 100644
index 1d9fde17b..000000000
--- a/app/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/app/plugins/CoreHome/angularjs/siteselector/siteselector.directive.html b/app/plugins/CoreHome/angularjs/siteselector/siteselector.directive.html
deleted file mode 100644
index 8954b2042..000000000
--- a/app/plugins/CoreHome/angularjs/siteselector/siteselector.directive.html
+++ /dev/null
@@ -1,73 +0,0 @@
-
diff --git a/app/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html b/app/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html
deleted file mode 100644
index 502cdaf72..000000000
--- a/app/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
- {{ category.name }}
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html b/app/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html
deleted file mode 100644
index 21ebd3d0c..000000000
--- a/app/plugins/CoreHome/angularjs/widget-container/widgetcontainer.directive.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
\ No newline at end of file
diff --git a/app/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html b/app/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html
deleted file mode 100644
index c29f0bbbd..000000000
--- a/app/plugins/CoreHome/angularjs/widget-loader/widgetloader.directive.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
{{widgetName}}
-
-
- {{ 'General_ErrorRequest'|translate:(''):('') }}
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CoreHome/angularjs/widget/widget.directive.html b/app/plugins/CoreHome/angularjs/widget/widget.directive.html
deleted file mode 100644
index f0e9c4862..000000000
--- a/app/plugins/CoreHome/angularjs/widget/widget.directive.html
+++ /dev/null
@@ -1,15 +0,0 @@
-
\ No newline at end of file
diff --git a/app/plugins/CoreHome/config/test.php b/app/plugins/CoreHome/config/test.php
deleted file mode 100644
index 9e625c422..000000000
--- a/app/plugins/CoreHome/config/test.php
+++ /dev/null
@@ -1,38 +0,0 @@
- DI\add([
- [
- 'Request.dispatch',
- DI\value(
- function () {
- if (!empty($_GET['setNotifications']) && $_GET['setNotifications'] == 1) {
- // trigger some notification
- $notification = new Notification('This is a persistent test notification');
- $notification->title = 'Warning:';
- $notification->context = Notification::CONTEXT_WARNING;
- $notification->type = Notification::TYPE_PERSISTENT;
- $notification->flags = Notification::FLAG_CLEAR;
- Notification\Manager::notify('NotificationFixture_persistent_warning', $notification);
-
- $notification = new Notification('This is another persistent test notification');
- $notification->title = 'Error:';
- $notification->context = Notification::CONTEXT_ERROR;
- $notification->type = Notification::TYPE_PERSISTENT;
- $notification->flags = Notification::FLAG_CLEAR;
- Notification\Manager::notify('NotificationFixture_persistent_error', $notification);
-
- $notification = new Notification('This is transient test notification');
- $notification->title = 'Error:';
- $notification->context = Notification::CONTEXT_ERROR;
- $notification->type = Notification::TYPE_TRANSIENT;
- $notification->flags = Notification::FLAG_CLEAR;
- Notification\Manager::notify('NotificationFixture_transient_error', $notification);
- }
- }
- ),
- ],
- ]),
-];
\ No newline at end of file
diff --git a/app/plugins/CoreHome/lang/ga.json b/app/plugins/CoreHome/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/CoreHome/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/CoreHome/stylesheets/layout.less b/app/plugins/CoreHome/stylesheets/layout.less
index dd1a8b6fd..07da8e266 100644
--- a/app/plugins/CoreHome/stylesheets/layout.less
+++ b/app/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/app/plugins/CoreHome/stylesheets/vue-transitions.less b/app/plugins/CoreHome/stylesheets/vue-transitions.less
index cdfef3e1e..d9bd4cf49 100644
--- a/app/plugins/CoreHome/stylesheets/vue-transitions.less
+++ b/app/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/app/plugins/CoreHome/templates/_adblockDetect.twig b/app/plugins/CoreHome/templates/_adblockDetect.twig
index f60d2ac0e..22d02e8c2 100644
--- a/app/plugins/CoreHome/templates/_adblockDetect.twig
+++ b/app/plugins/CoreHome/templates/_adblockDetect.twig
@@ -1,42 +1,44 @@
\ No newline at end of file
diff --git a/app/plugins/CoreHome/templates/_dataTable.twig b/app/plugins/CoreHome/templates/_dataTable.twig
index f9abda1fc..4ba518a51 100644
--- a/app/plugins/CoreHome/templates/_dataTable.twig
+++ b/app/plugins/CoreHome/templates/_dataTable.twig
@@ -13,7 +13,7 @@
{% if properties.title %}
{{ properties.title }}
{% endif %}
@@ -59,6 +59,8 @@
{% if showReportDataWasPurgedMessage is defined and showReportDataWasPurgedMessage %}
{{ 'CoreHome_DataForThisReportHasBeenPurged'|translate(deleteReportsOlderThan) }}
+ {% elseif showPluginArchiveDisabled is defined and showPluginArchiveDisabled%}
+ {{ 'CoreHome_DataForThisReportHasBeenDisabled'|translate('
', ' ')|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 %}
diff --git a/app/plugins/CoreHome/templates/_dataTableJS.twig b/app/plugins/CoreHome/templates/_dataTableJS.twig
index 975dca4b3..7d671c398 100644
--- a/app/plugins/CoreHome/templates/_dataTableJS.twig
+++ b/app/plugins/CoreHome/templates/_dataTableJS.twig
@@ -1,5 +1,5 @@
diff --git a/app/plugins/CoreHome/templates/_topBar.twig b/app/plugins/CoreHome/templates/_topBar.twig
index febe66468..961c6d6b8 100644
--- a/app/plugins/CoreHome/templates/_topBar.twig
+++ b/app/plugins/CoreHome/templates/_topBar.twig
@@ -13,6 +13,8 @@
{{ menu._html|raw }}
{% else %}
Menu
- *
- */
-/* harmony default export */ var DropdownMenu = ({
- mounted: function mounted(element, binding) {
- var options = {};
- $(element).addClass('matomo-dropdown-menu');
- var isSubmenu = !!$(element).parent().closest('.dropdown-content').length;
- if (isSubmenu) {
- options = {
- hover: true
- };
- $(element).addClass('submenu');
- $(binding.value.activates).addClass('submenu-dropdown-content'); // if a submenu is used, the dropdown will never scroll
+var PopoverHandler_window = window,
+ PopoverHandler_$ = PopoverHandler_window.$;
- $(element).parents('.dropdown-content').addClass('submenu-container');
+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;
- $(element).dropdown(options);
+ // 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
+
+/* 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/DropdownMenu/DropdownMenu.adapter.ts
+}));
+// 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
*
@@ -1921,106 +2313,312 @@ angular.module('piwikApp.service').service('globalAjaxQueue', ajaxQueue);
*/
-function piwikDropdownMenu($timeout) {
- return {
- restrict: 'A',
- link: function piwikDropdownMenuLink(scope, element, attrs) {
- var binding = {
- instance: null,
- value: {
- activates: $("#".concat(attrs.activates))[0]
- },
- oldValue: null,
- modifiers: {},
- dir: {}
- };
- $timeout(function () {
- DropdownMenu.mounted(element[0], binding);
- });
- }
- };
+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); }
-piwikDropdownMenu.$inject = ['$timeout'];
-angular.module('piwikApp').directive('piwikDropdownMenu', piwikDropdownMenu);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.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 onClickOutsideElement(element, binding, event) {
- var hadUsedScrollbar = binding.value.isMouseDown && binding.value.hasScrolled;
- binding.value.isMouseDown = false;
- binding.value.hasScrolled = false;
- if (hadUsedScrollbar) {
- return;
- }
+/* eslint-disable @typescript-eslint/no-explicit-any */
- if (!element.contains(event.target)) {
- if (binding.value) {
- binding.value.blur();
- }
- }
+
+
+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 onScroll(element, binding) {
- binding.value.hasScrolled = true;
+function toAngularJsCamelCase(arg) {
+ return arg.substring(0, 1).toLowerCase() + arg.substring(1).replace(/-([a-z])/g, function (s, p) {
+ return p.toUpperCase();
+ });
}
-function onMouseDown(element, binding) {
- binding.value.isMouseDown = true;
- binding.value.hasScrolled = false;
+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;
-function onEscapeHandler(element, binding, event) {
- if (event.which === 27) {
- setTimeout(function () {
- binding.value.isMouseDown = false;
- binding.value.hasScrolled = false;
+ if (transclude) {
+ transcludeCounter += 1;
+ }
- if (binding.value.blur) {
- binding.value.blur();
+ 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 = '';
+
+ if (transclude) {
+ rootVueTemplate += '
';
+ }
+
+ rootVueTemplate += ' '; // 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();
+ });
+ }
+ };
}
- }, 0);
+ };
+
+ if (transclude) {
+ adapter.transclude = true;
+ adapter.template = "
");
+ }
+
+ return adapter;
}
+
+ angularJsAdapter.$inject = $inject || [];
+ window.angular.module('piwikApp').directive(directiveName, angularJsAdapter);
+ return angularJsAdapter;
}
+function transformAngularJsBoolAttr(v) {
+ if (typeof v === 'undefined') {
+ return undefined;
+ }
-var doc = document.documentElement;
-/**
- * Usage (in a component):
- *
- * directives: {
- * // function call is important since we store state in this directive
- * FocusAnywhereButHere: FocusAnywhereButHere(),
- * }
- *
- * Note: the binding data needs to be static, changes will not be handled.
- */
+ if (v === 'true') {
+ return true;
+ }
-/* harmony default export */ var FocusAnywhereButHere = ({
- mounted: function mounted(el, binding) {
- binding.value.isMouseDown = false;
- binding.value.hasScrolled = false;
- binding.value.onEscapeHandler = onEscapeHandler.bind(null, el, binding);
- binding.value.onMouseDown = onMouseDown.bind(null, el, binding);
- binding.value.onClickOutsideElement = onClickOutsideElement.bind(null, el, binding);
- binding.value.onScroll = onScroll.bind(null, el, binding);
- 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: function unmounted(el, binding) {
- doc.removeEventListener('keyup', binding.value.onEscapeHandler);
- doc.removeEventListener('mousedown', binding.value.onMouseDown);
- doc.removeEventListener('mouseup', binding.value.onClickOutsideElement);
- doc.removeEventListener('scroll', binding.value.onScroll);
+ return !!v && v > 0 && v !== '0';
+}
+function transformAngularJsIntAttr(v) {
+ if (typeof v === 'undefined') {
+ return undefined;
}
-});
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.adapter.ts
+
+ 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
*
@@ -2028,15 +2626,202 @@ var doc = document.documentElement;
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
-/**
- * The given expression will be executed when the user presses either escape or presses something
- * outside of this element
- *
- * Example:
- * my dialog
- */
-function piwikFocusAnywhereButHere() {
+/* 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
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+/**
+ * A materializecss dropdown menu that supports submenus.
+ *
+ * To use a submenu, just use this directive within another dropdown.
+ *
+ * Note: if submenus are used, then dropdowns will never scroll.
+ *
+ * Usage:
+ * Menu
+ *
+ */
+
+/* harmony default export */ var DropdownMenu = ({
+ mounted: function mounted(element, binding) {
+ var options = {};
+ $(element).addClass('matomo-dropdown-menu');
+ var isSubmenu = !!$(element).parent().closest('.dropdown-content').length;
+
+ if (isSubmenu) {
+ var _binding$value;
+
+ options = {
+ hover: true
+ };
+ $(element).addClass('submenu');
+ $(((_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
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+function piwikDropdownMenu($timeout) {
+ return {
+ restrict: 'A',
+ link: function piwikDropdownMenuLink(scope, element, attrs) {
+ var binding = {
+ instance: null,
+ value: {
+ activates: $("#".concat(attrs.activates))[0]
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ };
+ $timeout(function () {
+ DropdownMenu.mounted(element[0], binding);
+ });
+ }
+ };
+}
+
+piwikDropdownMenu.$inject = ['$timeout'];
+window.angular.module('piwikApp').directive('piwikDropdownMenu', piwikDropdownMenu);
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.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 onClickOutsideElement(element, binding, event) {
+ var hadUsedScrollbar = binding.value.isMouseDown && binding.value.hasScrolled;
+ binding.value.isMouseDown = false;
+ binding.value.hasScrolled = false;
+
+ if (hadUsedScrollbar) {
+ return;
+ }
+
+ if (!element.contains(event.target)) {
+ if (binding.value) {
+ binding.value.blur();
+ }
+ }
+}
+
+function onScroll(element, binding) {
+ binding.value.hasScrolled = true;
+}
+
+function onMouseDown(element, binding) {
+ binding.value.isMouseDown = true;
+ binding.value.hasScrolled = false;
+}
+
+function onEscapeHandler(element, binding, event) {
+ if (event.which === 27) {
+ setTimeout(function () {
+ binding.value.isMouseDown = false;
+ binding.value.hasScrolled = false;
+
+ if (binding.value.blur) {
+ binding.value.blur();
+ }
+ }, 0);
+ }
+}
+
+var doc = document.documentElement;
+/**
+ * Usage (in a component):
+ *
+ * directives: {
+ * // function call is important since we store state in this directive
+ * FocusAnywhereButHere: FocusAnywhereButHere(),
+ * }
+ *
+ * Note: the binding data needs to be static, changes will not be handled.
+ */
+
+/* harmony default export */ var FocusAnywhereButHere = ({
+ mounted: function mounted(el, binding) {
+ binding.value.isMouseDown = false;
+ binding.value.hasScrolled = false;
+ binding.value.onEscapeHandler = onEscapeHandler.bind(null, el, binding);
+ binding.value.onMouseDown = onMouseDown.bind(null, el, binding);
+ binding.value.onClickOutsideElement = onClickOutsideElement.bind(null, el, binding);
+ binding.value.onScroll = onScroll.bind(null, el, binding);
+ 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: function unmounted(el, binding) {
+ doc.removeEventListener('keyup', binding.value.onEscapeHandler);
+ doc.removeEventListener('mousedown', binding.value.onMouseDown);
+ doc.removeEventListener('mouseup', binding.value.onClickOutsideElement);
+ doc.removeEventListener('scroll', binding.value.onScroll);
+ }
+});
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.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
+ */
+
+/**
+ * The given expression will be executed when the user presses either escape or presses something
+ * outside of this element
+ *
+ * Example:
+ * my dialog
+ */
+
+function piwikFocusAnywhereButHere() {
return {
restrict: 'A',
link: function focusAnywhereButHereLink(scope, element, attr) {
@@ -2061,36 +2846,5953 @@ function piwikFocusAnywhereButHere() {
};
}
-piwikFocusAnywhereButHere.$inject = [];
-angular.module('piwikApp.directive').directive('piwikFocusAnywhereButHere', piwikFocusAnywhereButHere);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusIf/FocusIf.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 doFocusIf(el, binding) {
- if (binding.arg) {
- setTimeout(function () {
- el.focus();
+window.angular.module('piwikApp.directive').directive('piwikFocusAnywhereButHere', piwikFocusAnywhereButHere);
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusIf/FocusIf.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 doFocusIf(el, binding) {
+ if (binding.arg) {
+ setTimeout(function () {
+ el.focus();
+
+ if (binding.value.afterFocus) {
+ binding.value.afterFocus();
+ }
+ }, 5);
+ }
+}
+
+/* harmony default export */ var FocusIf = ({
+ mounted: function mounted(el, binding) {
+ doFocusIf(el, binding);
+ },
+ updated: function updated(el, binding) {
+ doFocusIf(el, binding);
+ }
+});
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusIf/FocusIf.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
+ */
+
+/**
+ * If the given expression evaluates to true the element will be focused
+ *
+ * Example:
+ *
+ */
+
+function piwikFocusIf() {
+ return {
+ restrict: 'A',
+ link: function focusIfLink(scope, element, attrs) {
+ scope.$watch(attrs.piwikFocusIf, function (newValue) {
+ var binding = {
+ instance: null,
+ arg: newValue ? '1' : undefined,
+ value: {
+ afterFocus: function afterFocus() {
+ return scope.$apply();
+ }
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ };
+ FocusIf.updated(element[0], binding);
+ });
+ }
+ };
+}
+
+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
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+
+function onExpand(element) {
+ element.classList.toggle('expanded');
+ var positionElement = element.querySelector('.dropdown.positionInViewport');
+
+ if (positionElement) {
+ Matomo_Matomo.helper.setMarginLeftToBeInViewport(positionElement);
+ }
+}
+
+function ExpandOnClick_onClickOutsideElement(element, binding, event) {
+ var hadUsedScrollbar = binding.value.isMouseDown && binding.value.hasScrolled;
+ binding.value.isMouseDown = false;
+ binding.value.hasScrolled = false;
+
+ if (hadUsedScrollbar) {
+ return;
+ }
+
+ if (!element.contains(event.target)) {
+ element.classList.remove('expanded');
+ }
+}
+
+function ExpandOnClick_onScroll(binding) {
+ binding.value.hasScrolled = true;
+}
+
+function ExpandOnClick_onMouseDown(binding) {
+ binding.value.isMouseDown = true;
+ binding.value.hasScrolled = false;
+}
+
+function ExpandOnClick_onEscapeHandler(element, binding, event) {
+ if (event.which === 27) {
+ binding.value.isMouseDown = false;
+ binding.value.hasScrolled = false;
+ element.classList.remove('expanded');
+ }
+}
+
+var ExpandOnClick_doc = document.documentElement;
+var ExpandOnClick_window = window,
+ ExpandOnClick_$ = ExpandOnClick_window.$;
+/**
+ * Usage (in a component):
+ *
+ * directives: {
+ * ExpandOnClick: ExpandOnClick(), // function call is important since we store state
+ * // in this directive
+ * }
+ */
+
+/* harmony default export */ var ExpandOnClick = ({
+ mounted: function mounted(el, binding) {
+ binding.value.isMouseDown = false;
+ binding.value.hasScrolled = false;
+ binding.value.onExpand = onExpand.bind(null, el);
+ binding.value.onEscapeHandler = ExpandOnClick_onEscapeHandler.bind(null, el, binding);
+ 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);
+ 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) {
+ 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);
+ ExpandOnClick_doc.removeEventListener('scroll', binding.value.onScroll);
+ }
+});
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.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 piwikExpandOnClick() {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink(scope, element) {
+ var binding = {
+ instance: null,
+ value: {
+ expander: element.find('.title').first()[0]
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ };
+ ExpandOnClick.mounted(element[0], binding);
+ element.on('$destroy', function () {
+ return ExpandOnClick.unmounted(element[0], binding);
+ });
+ }
+ };
+}
+window.angular.module('piwikApp').directive('piwikExpandOnClick', piwikExpandOnClick);
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.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 onMouseEnter(element) {
+ element.classList.add('expanded');
+ var positionElement = element.querySelector('.dropdown.positionInViewport');
+
+ if (positionElement) {
+ Matomo_Matomo.helper.setMarginLeftToBeInViewport(positionElement);
+ }
+}
+
+function onMouseLeave(element) {
+ element.classList.remove('expanded');
+}
+
+function ExpandOnHover_onClickOutsideElement(element, event) {
+ if (!element.contains(event.target)) {
+ element.classList.remove('expanded');
+ }
+}
+
+function ExpandOnHover_onEscapeHandler(element, event) {
+ if (event.which === 27) {
+ element.classList.remove('expanded');
+ }
+}
+
+var ExpandOnHover_doc = document.documentElement;
+/**
+ * Usage (in a component):
+ *
+ * directives: {
+ * ExpandOnHover: ExpandOnHover(), // function call is important since we store state
+ * // in this directive
+ * }
+ */
+
+/* harmony default export */ var ExpandOnHover = ({
+ mounted: function mounted(el, binding) {
+ binding.value.onMouseEnter = onMouseEnter.bind(null, el);
+ binding.value.onMouseLeave = onMouseLeave.bind(null, el);
+ binding.value.onClickOutsideElement = ExpandOnHover_onClickOutsideElement.bind(null, el);
+ binding.value.onEscapeHandler = ExpandOnHover_onEscapeHandler.bind(null, el);
+ 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) {
+ 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);
+ }
+});
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.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 piwikExpandOnHover() {
+ return {
+ restrict: 'A',
+ link: function expandOnHoverLink(scope, element) {
+ var binding = {
+ instance: null,
+ value: {
+ expander: element.find('.title').first()[0]
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ };
+ ExpandOnHover.mounted(element[0], binding);
+ element.on('$destroy', function () {
+ return ExpandOnHover.unmounted(element[0], binding);
+ });
+ }
+ };
+}
+
+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:
+ *
+ */
+
+/* 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.substr(0, showCharacters);
+ }
+
+ protectedData += sensitiveData.substr(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:
+ * ...
+ */
+
+/* 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_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=00aba563
+
+// 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"])({
+ props: {
+ /**
+ * Whether the modal is displayed or not;
+ */
+ modelValue: {
+ type: Boolean,
+ required: true
+ },
+
+ /**
+ * Only here for backwards compatibility w/ AngularJS. If supplied, we use this
+ * element to launch the modal instead of the element in the slot. This should not
+ * be used for new Vue code.
+ *
+ * @deprecated
+ */
+ element: {
+ type: HTMLElement,
+ required: false
+ }
+ },
+ emits: ['yes', 'no', 'closeEnd', 'close', 'validation', 'update:modelValue'],
+ activated: function activated() {
+ this.$emit('update:modelValue', false);
+ },
+ watch: {
+ modelValue: function modelValue(newValue, oldValue) {
+ var _this = this;
+
+ if (newValue) {
+ var slotElement = this.element || this.$refs.root.firstElementChild;
+ Matomo_Matomo.helper.modalConfirm(slotElement, {
+ yes: function yes() {
+ _this.$emit('yes');
+ },
+ no: function no() {
+ _this.$emit('no');
+ },
+ validation: function validation() {
+ _this.$emit('validation');
+ }
+ }, {
+ onCloseEnd: function onCloseEnd() {
+ // materialize removes the child element, so we move it back to the slot
+ if (!_this.element) {
+ _this.$refs.root.appendChild(slotElement);
+ }
+
+ _this.$emit('update:modelValue', false);
+
+ _this.$emit('closeEnd');
+ }
+ });
+ } else if (newValue === false && oldValue === true) {
+ // the user closed the dialog, e.g. by pressing Esc or clicking away from it
+ this.$emit('close');
+ }
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue
+
+
+
+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/MatomoDialog/MatomoDialog.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 MatomoDialog_adapter = (createAngularJsAdapter({
+ component: MatomoDialog,
+ scope: {
+ show: {
+ vue: 'modelValue',
+ default: false
+ },
+ element: {
+ default: function _default(scope, element) {
+ return element[0];
+ }
+ }
+ },
+ events: {
+ yes: function yes($event, vm, scope, element, attrs) {
+ if (attrs.yes) {
+ scope.$eval(attrs.yes);
+ setTimeout(function () {
+ scope.$apply();
+ }, 0);
+ }
+ },
+ no: function no($event, vm, scope, element, attrs) {
+ if (attrs.no) {
+ scope.$eval(attrs.no);
+ setTimeout(function () {
+ scope.$apply();
+ }, 0);
+ }
+ },
+ validation: function validation($event, vm, scope, element, attrs) {
+ if (attrs.no) {
+ scope.$eval(attrs.no);
+ setTimeout(function () {
+ scope.$apply();
+ }, 0);
+ }
+ },
+ close: function close($event, vm, scope, element, attrs) {
+ if (attrs.close) {
+ scope.$eval(attrs.close);
+ setTimeout(function () {
+ scope.$apply();
+ }, 0);
+ }
+ },
+ 'update:modelValue': function updateModelValue(newValue, vm, scope, element, attrs, controller, $parse) {
+ setTimeout(function () {
+ scope.$apply($parse(attrs.piwikDialog).assign(scope, newValue));
+ }, 0);
+ }
+ },
+ $inject: ['$parse'],
+ directiveName: 'piwikDialog',
+ transclude: true,
+ mountPointFactory: function mountPointFactory(scope, element) {
+ var vueRootPlaceholder = $('
');
+ vueRootPlaceholder.appendTo(element);
+ return vueRootPlaceholder[0];
+ },
+ postCreate: function postCreate(vm, scope, element, attrs) {
+ scope.$watch(attrs.piwikDialog, function (newValue, oldValue) {
+ if (oldValue !== newValue) {
+ vm.modelValue = newValue || false;
+ }
+ });
+ },
+ 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=7b85675d
+
+var EnrichedHeadlinevue_type_template_id_7b85675d_hoisted_1 = {
+ key: 0,
+ class: "title",
+ tabindex: "6"
+};
+var _hoisted_2 = ["href", "title"];
+var _hoisted_3 = {
+ class: "iconsBar"
+};
+var _hoisted_4 = ["href", "title"];
+
+var _hoisted_5 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: "icon-help"
+}, null, -1);
+
+var _hoisted_6 = [_hoisted_5];
+var _hoisted_7 = ["title"];
+
+var _hoisted_8 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: "icon-info"
+}, null, -1);
+
+var _hoisted_9 = [_hoisted_8];
+var _hoisted_10 = {
+ class: "ratingIcons"
+};
+var _hoisted_11 = {
+ class: "inlineHelp"
+};
+var _hoisted_12 = ["innerHTML"];
+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", {
+ class: "enrichedHeadline",
+ onMouseenter: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.showIcons = true;
+ }),
+ onMouseleave: _cache[2] || (_cache[2] = function ($event) {
+ 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_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,
+ title: _ctx.translate('CoreHome_ClickToEditX', _ctx.$sanitize(_ctx.actualFeatureName))
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")], 8, _hoisted_2)) : 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", _hoisted_3, [_ctx.helpUrl && !_ctx.actualInlineHelp ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", {
+ key: 0,
+ rel: "noreferrer noopener",
+ target: "_blank",
+ class: "helpIcon",
+ href: _ctx.helpUrl,
+ title: _ctx.translate('CoreHome_ExternalHelp')
+ }, _hoisted_6, 8, _hoisted_4)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.actualInlineHelp ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", {
+ key: 1,
+ onClick: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.showInlineHelp = !_ctx.showInlineHelp;
+ }),
+ class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["helpIcon", {
+ 'active': _ctx.showInlineHelp
+ }]),
+ title: _ctx.translate(_ctx.reportGenerated ? 'General_HelpReport' : 'General_Help')
+ }, _hoisted_9, 10, _hoisted_7)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_10, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_RateFeature, {
+ 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.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_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=7b85675d
+
+// 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 */
+
+/* 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:
+ *
+ * All Websites Dashboard
+ * -> uses "All Websites Dashboard" as featurename
+ *
+ * All Websites Dashboard (Total:
+ * 309 Visits)
+ * -> custom featurename
+ *
+ * All Websites Dashboard
+ * -> shows help icon and links to external url
+ *
+ * All Websites
+ * Dashboard
+ * -> makes the headline clickable linking to the specified url
+ *
+ * Pages report
+ * -> inlineHelp specified via a attribute shows help icon on headline hover
+ *
+ * All Websites Dashboard
+ * My inline help
+ *
+ * -> alternative definition for inline help
+ * -> shows help icon to display inline help on click. Note: You can combine inlinehelp and help-url
+ *
+ * * Pages report
+ * -> reportGenerated specified via this attribute shows a clock icon with a tooltip which
+ * activated by hover
+ * -> the tooltip shows the value of the attribute
+ */
+
+/* harmony default export */ var EnrichedHeadlinevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ helpUrl: {
+ type: String,
+ default: ''
+ },
+ editUrl: {
+ type: String,
+ default: ''
+ },
+ reportGenerated: String,
+ featureName: String,
+ inlineHelp: String
+ },
+ components: {
+ RateFeature: RateFeature
+ },
+ data: function data() {
+ return {
+ showIcons: false,
+ showInlineHelp: false,
+ actualFeatureName: this.featureName,
+ actualInlineHelp: this.inlineHelp
+ };
+ },
+ watch: {
+ inlineHelp: function inlineHelp(newValue) {
+ this.actualInlineHelp = newValue;
+ },
+ featureName: function featureName(newValue) {
+ this.actualFeatureName = newValue;
+ }
+ },
+ mounted: function mounted() {
+ var _this = this;
+
+ var root = this.$refs.root; // timeout used since angularjs does not fill out the transclude at this point
+
+ setTimeout(function () {
+ if (!_this.actualInlineHelp) {
+ var _root$parentElement;
+
+ var helpNode = root.querySelector('.title .inlineHelp');
+
+ 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$getAttribut = helpNode.getAttribute('data-content')) === null || _helpNode$getAttribut === void 0 ? void 0 : _helpNode$getAttribut.trim();
+
+ if (helpDocs && helpDocs.length) {
+ _this.actualInlineHelp = "".concat(helpDocs, "
");
+ setTimeout(function () {
+ return helpNode.remove();
+ }, 0);
+ }
+ }
+ }
+
+ if (!_this.actualFeatureName) {
+ var _root$querySelector;
+
+ _this.actualFeatureName = (_root$querySelector = root.querySelector('.title')) === null || _root$querySelector === void 0 ? void 0 : _root$querySelector.textContent;
+ }
+
+ 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
+ });
+ }
+ }
+ });
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue
+
+
+
+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
+/*!
+ * 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 EnrichedHeadline_adapter = (createAngularJsAdapter({
+ component: EnrichedHeadline,
+ scope: {
+ helpUrl: {
+ angularJsBind: '@'
+ },
+ editUrl: {
+ angularJsBind: '@'
+ },
+ reportGenerated: {
+ angularJsBind: '@?'
+ },
+ featureName: {
+ angularJsBind: '@'
+ },
+ inlineHelp: {
+ angularJsBind: '@?'
+ }
+ },
+ 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=3f4d113e
+
+var ContentBlockvue_type_template_id_3f4d113e_hoisted_1 = {
+ class: "card",
+ ref: "root"
+};
+var ContentBlockvue_type_template_id_3f4d113e_hoisted_2 = {
+ class: "card-content"
+};
+var ContentBlockvue_type_template_id_3f4d113e_hoisted_3 = {
+ key: 0,
+ class: "card-title"
+};
+var ContentBlockvue_type_template_id_3f4d113e_hoisted_4 = {
+ key: 1,
+ class: "card-title"
+};
+var ContentBlockvue_type_template_id_3f4d113e_hoisted_5 = {
+ ref: "content"
+};
+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_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
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ 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_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=3f4d113e
+
+// 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,
+ feature: String,
+ helpUrl: String,
+ helpText: String,
+ anchor: String
+ },
+ components: {
+ EnrichedHeadline: EnrichedHeadline
+ },
+ data: function data() {
+ return {
+ actualFeature: this.feature,
+ actualHelpText: this.helpText
+ };
+ },
+ watch: {
+ feature: function feature(newValue) {
+ this.actualFeature = newValue;
+ },
+ helpText: function helpText(newValue) {
+ this.actualHelpText = newValue;
+ }
+ },
+ mounted: function mounted() {
+ var _this = this;
+
+ var root = this.$refs.root;
+ var content = this.$refs.content;
+
+ if (this.anchor && root && root.parentElement) {
+ var anchorElement = document.createElement('a');
+ anchorElement.id = this.anchor;
+ ContentBlockvue_type_script_lang_ts_$(root.parentElement).prepend(anchorElement);
+ }
+
+ setTimeout(function () {
+ var inlineHelp = content.querySelector('.contentHelp');
+
+ if (inlineHelp) {
+ _this.actualHelpText = inlineHelp.innerHTML;
+ inlineHelp.remove();
+ }
+ }, 0);
+
+ if (this.actualFeature && this.actualFeature === 'true') {
+ this.actualFeature = this.contentTitle;
+ }
+
+ if (adminContent === null) {
+ // cache admin node for further content blocks
+ adminContent = document.querySelector('#content.admin');
+ }
+
+ var contentTopPosition = null;
+
+ if (adminContent) {
+ contentTopPosition = adminContent.offsetTop;
+ }
+
+ if (contentTopPosition || contentTopPosition === 0) {
+ var parents = root.closest('[piwik-widget-loader]'); // 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
+ // the widgets on the admin home page
+
+ var topThis = parents ? parents.offsetTop : root.offsetTop;
+
+ 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';
+ }
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue
+
+
+
+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
+/*!
+ * 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 ContentBlock_adapter = (createAngularJsAdapter({
+ component: ContentBlock,
+ scope: {
+ contentTitle: {
+ angularJsBind: '@'
+ },
+ feature: {
+ angularJsBind: '@'
+ },
+ helpUrl: {
+ angularJsBind: '@'
+ },
+ helpText: {
+ angularJsBind: '@'
+ },
+ anchor: {
+ angularJsBind: '@?'
+ }
+ },
+ directiveName: 'piwikContentBlock',
+ transclude: true
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Segmentation/Segments.store.ts
+function Segments_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function Segments_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 Segments_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) Segments_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) Segments_store_defineProperties(Constructor, staticProps); return Constructor; }
+
+function Segments_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 Segments_store_SegmentsStore = /*#__PURE__*/function () {
+ function SegmentsStore() {
+ var _this = this;
+
+ Segments_store_classCallCheck(this, SegmentsStore);
+
+ Segments_store_defineProperty(this, "segmentState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({
+ availableSegments: []
+ }));
+
+ Matomo_Matomo.on('piwikSegmentationInited', function () {
+ return _this.setSegmentState();
+ });
+ }
+
+ Segments_store_createClass(SegmentsStore, [{
+ key: "state",
+ get: function get() {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(this.segmentState);
+ }
+ }, {
+ key: "setSegmentState",
+ value: function setSegmentState() {
+ try {
+ var uiControlObject = $('.segmentEditorPanel').data('uiControlObject');
+ this.segmentState.availableSegments = uiControlObject.impl.availableSegments || [];
+ } catch (e) {// segment editor is not initialized yet
+ }
+ }
+ }]);
+
+ return SegmentsStore;
+}();
+
+/* harmony default export */ var Segments_store = (new Segments_store_SegmentsStore());
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts
+function Comparisons_store_toConsumableArray(arr) { return Comparisons_store_arrayWithoutHoles(arr) || Comparisons_store_iterableToArray(arr) || Comparisons_store_unsupportedIterableToArray(arr) || Comparisons_store_nonIterableSpread(); }
+
+function Comparisons_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 Comparisons_store_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return Comparisons_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 Comparisons_store_arrayLikeToArray(o, minLen); }
+
+function Comparisons_store_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
+
+function Comparisons_store_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return Comparisons_store_arrayLikeToArray(arr); }
+
+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_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); } }
+
+function Comparisons_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) Comparisons_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) Comparisons_store_defineProperties(Constructor, staticProps); return Constructor; }
+
+function Comparisons_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 SERIES_COLOR_COUNT = 8;
+var SERIES_SHADE_COUNT = 3;
+
+function wrapArray(values) {
+ if (!values) {
+ return [];
+ }
+
+ return Array.isArray(values) ? values : [values];
+}
+
+var Comparisons_store_ComparisonsStore = /*#__PURE__*/function () {
+ // for tests
+ function ComparisonsStore() {
+ var _this = this;
+
+ Comparisons_store_classCallCheck(this, ComparisonsStore);
+
+ Comparisons_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({
+ comparisonsDisabledFor: []
+ }));
+
+ Comparisons_store_defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(this.privateState));
+
+ Comparisons_store_defineProperty(this, "colors", {});
+
+ Comparisons_store_defineProperty(this, "segmentComparisons", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
+ return _this.parseSegmentComparisons();
+ }));
+
+ Comparisons_store_defineProperty(this, "periodComparisons", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
+ return _this.parsePeriodComparisons();
+ }));
+
+ Comparisons_store_defineProperty(this, "isEnabled", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
+ return _this.checkEnabledForCurrentPage();
+ }));
+
+ this.loadComparisonsDisabledFor();
+ $(function () {
+ _this.colors = _this.getAllSeriesColors();
+ });
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () {
+ return _this.getComparisons();
+ }, function () {
+ return Matomo_Matomo.postEvent('piwikComparisonsChanged');
+ }, {
+ deep: true
+ });
+ }
+
+ Comparisons_store_createClass(ComparisonsStore, [{
+ key: "getComparisons",
+ value: function getComparisons() {
+ return this.getSegmentComparisons().concat(this.getPeriodComparisons());
+ }
+ }, {
+ key: "isComparing",
+ value: function isComparing() {
+ return this.isComparisonEnabled() // first two in each array are for the currently selected segment/period
+ && (this.segmentComparisons.value.length > 1 || this.periodComparisons.value.length > 1);
+ }
+ }, {
+ key: "isComparingPeriods",
+ value: function isComparingPeriods() {
+ return this.getPeriodComparisons().length > 1; // first is currently selected period
+ }
+ }, {
+ key: "getSegmentComparisons",
+ value: function getSegmentComparisons() {
+ if (!this.isComparisonEnabled()) {
+ return [];
+ }
+
+ return this.segmentComparisons.value;
+ }
+ }, {
+ key: "getPeriodComparisons",
+ value: function getPeriodComparisons() {
+ if (!this.isComparisonEnabled()) {
+ return [];
+ }
+
+ return this.periodComparisons.value;
+ }
+ }, {
+ key: "getSeriesColor",
+ value: function getSeriesColor(segmentComparison, periodComparison) {
+ var metricIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
+ var seriesIndex = this.getComparisonSeriesIndex(periodComparison.index, segmentComparison.index) % SERIES_COLOR_COUNT;
+
+ if (metricIndex === 0) {
+ return this.colors["series".concat(seriesIndex)];
+ }
+
+ var shadeIndex = metricIndex % SERIES_SHADE_COUNT;
+ return this.colors["series".concat(seriesIndex, "-shade").concat(shadeIndex)];
+ }
+ }, {
+ key: "getSeriesColorName",
+ value: function getSeriesColorName(seriesIndex, metricIndex) {
+ var colorName = "series".concat(seriesIndex % SERIES_COLOR_COUNT);
+
+ if (metricIndex > 0) {
+ colorName += "-shade".concat(metricIndex % SERIES_SHADE_COUNT);
+ }
+
+ return colorName;
+ }
+ }, {
+ key: "isComparisonEnabled",
+ value: function isComparisonEnabled() {
+ return this.isEnabled.value;
+ }
+ }, {
+ key: "getIndividualComparisonRowIndices",
+ value: function getIndividualComparisonRowIndices(seriesIndex) {
+ var segmentCount = this.getSegmentComparisons().length;
+ var segmentIndex = seriesIndex % segmentCount;
+ var periodIndex = Math.floor(seriesIndex / segmentCount);
+ return {
+ segmentIndex: segmentIndex,
+ periodIndex: periodIndex
+ };
+ }
+ }, {
+ key: "getComparisonSeriesIndex",
+ value: function getComparisonSeriesIndex(periodIndex, segmentIndex) {
+ var segmentCount = this.getSegmentComparisons().length;
+ return periodIndex * segmentCount + segmentIndex;
+ }
+ }, {
+ key: "getAllComparisonSeries",
+ value: function getAllComparisonSeries() {
+ var _this2 = this;
+
+ var seriesInfo = [];
+ var seriesIndex = 0;
+ this.getPeriodComparisons().forEach(function (periodComp) {
+ _this2.getSegmentComparisons().forEach(function (segmentComp) {
+ seriesInfo.push({
+ index: seriesIndex,
+ params: Object.assign(Object.assign({}, segmentComp.params), periodComp.params),
+ color: _this2.colors["series".concat(seriesIndex)]
+ });
+ seriesIndex += 1;
+ });
+ });
+ return seriesInfo;
+ }
+ }, {
+ key: "removeSegmentComparison",
+ value: function removeSegmentComparison(index) {
+ if (!this.isComparisonEnabled()) {
+ throw new Error('Comparison disabled.');
+ }
+
+ var newComparisons = Comparisons_store_toConsumableArray(this.segmentComparisons.value);
+
+ newComparisons.splice(index, 1);
+ var extraParams = {};
+
+ if (index === 0) {
+ extraParams.segment = newComparisons[0].params.segment;
+ }
+
+ this.updateQueryParamsFromComparisons(newComparisons, this.periodComparisons.value, extraParams);
+ }
+ }, {
+ key: "addSegmentComparison",
+ value: function addSegmentComparison(params) {
+ if (!this.isComparisonEnabled()) {
+ throw new Error('Comparison disabled.');
+ }
+
+ var newComparisons = this.segmentComparisons.value.concat([{
+ params: params,
+ index: -1,
+ title: ''
+ }]);
+ this.updateQueryParamsFromComparisons(newComparisons, this.periodComparisons.value);
+ }
+ }, {
+ key: "updateQueryParamsFromComparisons",
+ value: function updateQueryParamsFromComparisons(segmentComparisons, periodComparisons) {
+ var extraParams = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+ // get unique segments/periods/dates from new Comparisons
+ var compareSegments = {};
+ var comparePeriodDatePairs = {};
+ var firstSegment = false;
+ var firstPeriod = false;
+ segmentComparisons.forEach(function (comparison) {
+ if (firstSegment) {
+ compareSegments[comparison.params.segment] = true;
+ } else {
+ firstSegment = true;
+ }
+ });
+ periodComparisons.forEach(function (comparison) {
+ if (firstPeriod) {
+ comparePeriodDatePairs["".concat(comparison.params.period, "|").concat(comparison.params.date)] = true;
+ } else {
+ firstPeriod = true;
+ }
+ });
+ var comparePeriods = [];
+ var compareDates = [];
+ Object.keys(comparePeriodDatePairs).forEach(function (pair) {
+ var parts = pair.split('|');
+ comparePeriods.push(parts[0]);
+ compareDates.push(parts[1]);
+ });
+ var compareParams = {
+ compareSegments: Object.keys(compareSegments),
+ comparePeriods: comparePeriods,
+ compareDates: compareDates
+ }; // change the page w/ these new param values
+
+ 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",
+ value: function getAllSeriesColors() {
+ var ColorManager = Matomo_Matomo.ColorManager;
+
+ if (!ColorManager) {
+ return [];
+ }
+
+ var seriesColorNames = [];
+
+ for (var i = 0; i < SERIES_COLOR_COUNT; i += 1) {
+ seriesColorNames.push("series".concat(i));
+
+ for (var j = 0; j < SERIES_SHADE_COUNT; j += 1) {
+ seriesColorNames.push("series".concat(i, "-shade").concat(j));
+ }
+ }
+
+ return ColorManager.getColors('comparison-series-color', seriesColorNames);
+ }
+ }, {
+ key: "loadComparisonsDisabledFor",
+ value: function loadComparisonsDisabledFor() {
+ var _this3 = this;
+
+ var matomoModule = src_MatomoUrl_MatomoUrl.parsed.value.module; // check if body id #installation exist
+
+ if (window.piwik.installation) {
+ this.privateState.comparisonsDisabledFor = [];
+ return;
+ }
+
+ if (matomoModule === 'CoreUpdater' || matomoModule === 'Installation' || matomoModule === 'Overlay') {
+ this.privateState.comparisonsDisabledFor = [];
+ return;
+ }
+
+ AjaxHelper_AjaxHelper.fetch({
+ module: 'API',
+ method: 'API.getPagesComparisonsDisabledFor'
+ }).then(function (result) {
+ _this3.privateState.comparisonsDisabledFor = result;
+ });
+ }
+ }, {
+ key: "parseSegmentComparisons",
+ value: function parseSegmentComparisons() {
+ var availableSegments = Segments_store.state.availableSegments;
+
+ var compareSegments = Comparisons_store_toConsumableArray(wrapArray(src_MatomoUrl_MatomoUrl.parsed.value.compareSegments)); // add base comparisons
+
+
+ compareSegments.unshift(src_MatomoUrl_MatomoUrl.parsed.value.segment || '');
+ var newSegmentComparisons = [];
+ compareSegments.forEach(function (segment, idx) {
+ var storedSegment;
+ availableSegments.forEach(function (s) {
+ if (s.definition === segment || s.definition === decodeURIComponent(segment) || decodeURIComponent(s.definition) === segment) {
+ storedSegment = s;
+ }
+ });
+ var segmentTitle = storedSegment ? storedSegment.name : translate('General_Unknown');
+
+ if (segment.trim() === '') {
+ segmentTitle = translate('SegmentEditor_DefaultAllVisits');
+ }
+
+ newSegmentComparisons.push({
+ params: {
+ segment: segment
+ },
+ title: Matomo_Matomo.helper.htmlDecode(segmentTitle),
+ index: idx
+ });
+ });
+ return newSegmentComparisons;
+ }
+ }, {
+ key: "parsePeriodComparisons",
+ value: function parsePeriodComparisons() {
+ var comparePeriods = Comparisons_store_toConsumableArray(wrapArray(src_MatomoUrl_MatomoUrl.parsed.value.comparePeriods));
+
+ var compareDates = Comparisons_store_toConsumableArray(wrapArray(src_MatomoUrl_MatomoUrl.parsed.value.compareDates));
+
+ comparePeriods.unshift(src_MatomoUrl_MatomoUrl.parsed.value.period);
+ compareDates.unshift(src_MatomoUrl_MatomoUrl.parsed.value.date);
+ var newPeriodComparisons = [];
+
+ for (var i = 0; i < Math.min(compareDates.length, comparePeriods.length); i += 1) {
+ var title = void 0;
+
+ try {
+ title = Periods_Periods.parse(comparePeriods[i], compareDates[i]).getPrettyString();
+ } catch (e) {
+ title = translate('General_Error');
+ }
+
+ newPeriodComparisons.push({
+ params: {
+ date: compareDates[i],
+ period: comparePeriods[i]
+ },
+ title: title,
+ index: i
+ });
+ }
+
+ return newPeriodComparisons;
+ }
+ }, {
+ key: "checkEnabledForCurrentPage",
+ value: function checkEnabledForCurrentPage() {
+ // category/subcategory is not included on top bar pages, so in that case we use module/action
+ var category = src_MatomoUrl_MatomoUrl.parsed.value.category || src_MatomoUrl_MatomoUrl.parsed.value.module;
+ var subcategory = src_MatomoUrl_MatomoUrl.parsed.value.subcategory || src_MatomoUrl_MatomoUrl.parsed.value.action;
+ var id = "".concat(category, ".").concat(subcategory);
+ var isEnabled = this.privateState.comparisonsDisabledFor.indexOf(id) === -1 && this.privateState.comparisonsDisabledFor.indexOf("".concat(category, ".*")) === -1;
+ document.documentElement.classList.toggle('comparisonsDisabled', !isEnabled);
+ return isEnabled;
+ }
+ }]);
+
+ return ComparisonsStore;
+}();
+
+
+// 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=d1a096d8
+
+var Comparisonsvue_type_template_id_d1a096d8_hoisted_1 = {
+ key: 0,
+ ref: "root",
+ class: "matomo-comparisons"
+};
+var Comparisonsvue_type_template_id_d1a096d8_hoisted_2 = {
+ class: "comparison-type"
+};
+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_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_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_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 + ' ' + 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_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,
+ title: _ctx.getComparisonTooltip(comparison, periodComparison)
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: "comparison-dot",
+ 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_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",
+ onClick: function onClick($event) {
+ return _ctx.removeSegmentComparison($index);
+ }
+ }, [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_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_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=d1a096d8
+
+// 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 defaultContentTransform() {
+ var title = Tooltips_$(this).attr('title') || '';
+ return window.vueSanitize(title.replace(/\n/g, ' '));
+}
+
+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
+
+
+
+
+
+
+
+/* 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
+ };
+ },
+ setup: function setup() {
+ // accessing has to be done through a computed property so we can use the computed
+ // instance directly in the template. unfortunately, vue won't register to changes.
+ var isComparing = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
+ return Comparisons_store_instance.isComparing();
+ });
+ var segmentComparisons = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
+ return Comparisons_store_instance.getSegmentComparisons();
+ });
+ var periodComparisons = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
+ 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, ' '));
+ }
+
+ return {
+ isComparing: isComparing,
+ segmentComparisons: segmentComparisons,
+ periodComparisons: periodComparisons,
+ getSeriesColor: getSeriesColor,
+ transformTooltipContent: transformTooltipContent
+ };
+ },
+ methods: {
+ comparisonHasSegment: function comparisonHasSegment(comparison) {
+ return typeof comparison.params.segment !== 'undefined';
+ },
+ removeSegmentComparison: function removeSegmentComparison(index) {
+ // otherwise the tooltip will be stuck on the screen
+ window.$(this.$refs.root).tooltip('destroy');
+ Comparisons_store_instance.removeSegmentComparison(index);
+ },
+ getComparisonPeriodType: function getComparisonPeriodType(comparison) {
+ var period = comparison.params.period;
+
+ if (period === 'range') {
+ return translate('CoreHome_PeriodRange');
+ }
+
+ var periodStr = translate("Intl_Period".concat(period.substring(0, 1).toUpperCase()).concat(period.substring(1)));
+ return periodStr.substring(0, 1).toUpperCase() + periodStr.substring(1);
+ },
+ getComparisonTooltip: function getComparisonTooltip(segmentComparison, periodComparison) {
+ if (!this.comparisonTooltips || !Object.keys(this.comparisonTooltips).length) {
+ return undefined;
+ }
+
+ return (this.comparisonTooltips[periodComparison.index] || {})[segmentComparison.index];
+ },
+ getUrlToSegment: function getUrlToSegment(segment) {
+ 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));
+ },
+ onComparisonsChanged: function onComparisonsChanged() {
+ var _this = this;
+
+ this.comparisonTooltips = null;
+
+ if (!Comparisons_store_instance.isComparing()) {
+ return;
+ }
+
+ var periodComparisons = Comparisons_store_instance.getPeriodComparisons();
+ var segmentComparisons = Comparisons_store_instance.getSegmentComparisons();
+ AjaxHelper_AjaxHelper.fetch({
+ method: 'API.getProcessedReport',
+ apiModule: 'VisitsSummary',
+ apiAction: 'get',
+ compare: '1',
+ compareSegments: src_MatomoUrl_MatomoUrl.getSearchParam('compareSegments'),
+ comparePeriods: src_MatomoUrl_MatomoUrl.getSearchParam('comparePeriods'),
+ compareDates: src_MatomoUrl_MatomoUrl.getSearchParam('compareDates'),
+ format_metrics: '1'
+ }).then(function (report) {
+ _this.comparisonTooltips = {};
+ periodComparisons.forEach(function (periodComp) {
+ _this.comparisonTooltips[periodComp.index] = {};
+ segmentComparisons.forEach(function (segmentComp) {
+ var tooltip = _this.generateComparisonTooltip(report, periodComp, segmentComp);
+
+ _this.comparisonTooltips[periodComp.index][segmentComp.index] = tooltip;
+ });
+ });
+ });
+ },
+ generateComparisonTooltip: function generateComparisonTooltip(visitsSummary, periodComp, segmentComp) {
+ if (!visitsSummary.reportData.comparisons) {
+ // sanity check
+ return '';
+ }
+
+ var firstRowIndex = Comparisons_store_instance.getComparisonSeriesIndex(periodComp.index, 0);
+ var firstRow = visitsSummary.reportData.comparisons[firstRowIndex];
+ var comparisonRowIndex = Comparisons_store_instance.getComparisonSeriesIndex(periodComp.index, segmentComp.index);
+ var comparisonRow = visitsSummary.reportData.comparisons[comparisonRowIndex];
+ var firstPeriodRow = visitsSummary.reportData.comparisons[segmentComp.index];
+ var tooltip = '';
+ var visitsPercent = (comparisonRow.nb_visits / firstRow.nb_visits * 100).toFixed(2);
+ visitsPercent = "".concat(visitsPercent, "%");
+ tooltip += translate('General_ComparisonCardTooltip1', ["'".concat(comparisonRow.compareSegmentPretty, "'"), comparisonRow.comparePeriodPretty, visitsPercent, comparisonRow.nb_visits.toString(), firstRow.nb_visits.toString()]);
+
+ if (periodComp.index > 0) {
+ tooltip += ' ';
+ tooltip += translate('General_ComparisonCardTooltip2', [comparisonRow.nb_visits_change.toString(), firstPeriodRow.compareSegmentPretty, firstPeriodRow.comparePeriodPretty]);
+ }
+
+ tooltip += '
';
+ return tooltip;
+ }
+ },
+ mounted: function mounted() {
+ var _this2 = this;
+
+ Matomo_Matomo.on('piwikComparisonsChanged', function () {
+ _this2.onComparisonsChanged();
+ });
+ this.onComparisonsChanged();
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue
+
+
+
+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
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+
+
+function ComparisonFactory() {
+ return Comparisons_store_instance;
+}
+
+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/MenuItemsDropdown/MenuItemsDropdown.vue?vue&type=template&id=ee5932cc
+
+var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_1 = {
+ ref: "root",
+ class: "menuDropdown"
+};
+var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_2 = ["title"];
+var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_3 = ["innerHTML"];
+
+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 MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_5 = {
+ class: "items"
+};
+var MenuItemsDropdownvue_type_template_id_ee5932cc_hoisted_6 = {
+ key: 0,
+ class: "search"
+};
+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", 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;
+ }),
+ title: _ctx.tooltip
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ innerHTML: _ctx.$sanitize(this.actualMenuTitle)
+ }, 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;
+ }),
+ onKeydown: _cache[2] || (_cache[2] = function ($event) {
+ return _ctx.onSearchTermKeydown($event);
+ }),
+ placeholder: _ctx.translate('General_Search')
+ }, 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, 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 = '';
+
+ _ctx.searchItems('');
+ }),
+ class: "reset",
+ src: "plugins/CoreHome/images/reset_search.png",
+ title: _ctx.translate('General_Clear')
+ }, 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);
+ })
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showItems]])], 512)), [[_directive_focus_anywhere_but_here, {
+ blur: _ctx.lostFocus
+ }]]);
+}
+// 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/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 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: Boolean
+ },
+ directives: {
+ FocusAnywhereButHere: FocusAnywhereButHere,
+ FocusIf: FocusIf
+ },
+ emits: ['afterSelect'],
+ watch: {
+ menuTitle: function menuTitle() {
+ this.actualMenuTitle = this.menuTitle;
+ }
+ },
+ data: function data() {
+ return {
+ showItems: false,
+ searchTerm: '',
+ actualMenuTitle: this.menuTitle
+ };
+ },
+ methods: {
+ lostFocus: function lostFocus() {
+ this.showItems = false;
+ },
+ selectItem: function selectItem(event) {
+ var targetClasses = event.target.classList;
+
+ if (!targetClasses.contains('item') || targetClasses.contains('disabled') || targetClasses.contains('separator')) {
+ return;
+ }
+
+ 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;
+ MenuItemsDropdownvue_type_script_lang_ts_$(this.$slots.default()[0].el).find('.item').removeClass('active');
+ targetClasses.add('active');
+ this.$emit('afterSelect');
+ },
+ onSearchTermKeydown: function onSearchTermKeydown() {
+ var _this = this;
+
+ setTimeout(function () {
+ _this.searchItems(_this.searchTerm);
+ });
+ },
+ searchItems: function searchItems(unprocessedSearchTerm) {
+ var searchTerm = unprocessedSearchTerm.toLowerCase();
+ 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();
+ } else {
+ $node.show();
+ }
+ });
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue
+
+
+
+MenuItemsDropdownvue_type_script_lang_ts.render = MenuItemsDropdownvue_type_template_id_ee5932cc_render
+
+/* 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
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+/* harmony default export */ var MenuItemsDropdown_adapter = (createAngularJsAdapter({
+ component: MenuItemsDropdown,
+ scope: {
+ menuTitle: {
+ angularJsBind: '@'
+ },
+ tooltip: {
+ angularJsBind: '@'
+ },
+ showSearch: {
+ angularJsBind: '='
+ },
+ menuTitleChangeOnClick: {
+ angularJsBind: '='
+ }
+ },
+ directiveName: 'piwikMenudropdown',
+ transclude: true,
+ events: {
+ '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=589729fc
+
+var DatePickervue_type_template_id_589729fc_hoisted_1 = {
+ ref: "root"
+};
+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=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
+
+
+
+var DEFAULT_STEP_MONTHS = 1;
+var DatePickervue_type_script_lang_ts_window = window,
+ DatePickervue_type_script_lang_ts_$ = DatePickervue_type_script_lang_ts_window.$;
+/* harmony default export */ var DatePickervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["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 setup(props, context) {
+ var root = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(null);
+
+ function setDateCellColor($dateCell, dateValue) {
+ var $dateCellLink = $dateCell.children('a');
+
+ if (props.selectedDateStart && props.selectedDateEnd && dateValue >= props.selectedDateStart && dateValue <= props.selectedDateEnd) {
+ $dateCell.addClass('ui-datepicker-current-period');
+ } else {
+ $dateCell.removeClass('ui-datepicker-current-period');
+ }
+
+ if (props.highlightedDateStart && props.highlightedDateEnd && dateValue >= props.highlightedDateStart && dateValue <= props.highlightedDateEnd) {
+ // other-month cells don't have links, so the must have the ui-state-hover class
+ var elementToAddClassTo = $dateCellLink.length ? $dateCellLink : $dateCell;
+ elementToAddClassTo.addClass('ui-state-hover');
+ } else {
+ $dateCell.removeClass('ui-state-hover');
+ $dateCellLink.removeClass('ui-state-hover');
+ }
+ }
+
+ function getCellDate($dateCell, month, year) {
+ if ($dateCell.hasClass('ui-datepicker-other-month')) {
+ return getOtherMonthDate($dateCell, month, year); // eslint-disable-line
+ }
+
+ var day = parseInt($dateCell.children('a,span').text(), 10);
+ return new Date(year, month, day);
+ }
+
+ function getOtherMonthDate($dateCell, month, year) {
+ var date;
+ var $row = $dateCell.parent();
+ var $rowCells = $row.children('td'); // if in the first row, the date cell is before the current month
+
+ if ($row.is(':first-child')) {
+ var $firstDateInMonth = $row.children('td:not(.ui-datepicker-other-month)').first();
+ date = getCellDate($firstDateInMonth, month, year);
+ date.setDate($rowCells.index($dateCell) - $rowCells.index($firstDateInMonth) + 1);
+ return date;
+ } // the date cell is after the current month
+
+
+ var $lastDateInMonth = $row.children('td:not(.ui-datepicker-other-month)').last();
+ date = getCellDate($lastDateInMonth, month, year);
+ date.setDate(date.getDate() + $rowCells.index($dateCell) - $rowCells.index($lastDateInMonth));
+ return date;
+ }
+
+ function getMonthYearDisplayed() {
+ var element = DatePickervue_type_script_lang_ts_$(root.value);
+ var $firstCellWithMonth = element.find('td[data-month]');
+ var month = parseInt($firstCellWithMonth.attr('data-month'), 10);
+ var year = parseInt($firstCellWithMonth.attr('data-year'), 10);
+ return [month, year];
+ }
+
+ function setDatePickerCellColors() {
+ var element = DatePickervue_type_script_lang_ts_$(root.value);
+ var $calendarTable = element.find('.ui-datepicker-calendar');
+ var monthYear = getMonthYearDisplayed(); // highlight the rest of the cells by first getting the date for the first cell
+ // in the calendar, then just incrementing by one for the rest of the cells.
+
+ var $cells = $calendarTable.find('td');
+ var $firstDateCell = $cells.first();
+ var currentDate = getCellDate($firstDateCell, monthYear[0], monthYear[1]);
+ $cells.each(function setCellColor() {
+ setDateCellColor(DatePickervue_type_script_lang_ts_$(this), currentDate);
+ currentDate.setDate(currentDate.getDate() + 1);
+ });
+ }
+
+ function viewDateChanged() {
+ if (!props.viewDate) {
+ return false;
+ }
+
+ var date;
+
+ if (typeof props.viewDate === 'string') {
+ try {
+ 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.
+ // this avoids a re-render in other cases.
+
+ var monthYear = getMonthYearDisplayed();
+
+ if (monthYear[0] !== date.getMonth() || monthYear[1] !== date.getFullYear()) {
+ element.datepicker('setDate', date);
+ return true;
+ }
+
+ return false;
+ } // 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() {
+ var element = DatePickervue_type_script_lang_ts_$(root.value);
+ element.find('td[data-event]').off('click');
+ element.find('.ui-state-active').removeClass('ui-state-active');
+ element.find('.ui-datepicker-current-day').removeClass('ui-datepicker-current-day'); // add href to left/right nav in calendar so they can be accessed via keyboard
+
+ element.find('.ui-datepicker-prev,.ui-datepicker-next').attr('href', '');
+ }
+
+ function stepMonthsChanged() {
+ var element = DatePickervue_type_script_lang_ts_$(root.value);
+ var stepMonths = props.stepMonths || DEFAULT_STEP_MONTHS;
+
+ if (element.datepicker('option', 'stepMonths') === stepMonths) {
+ return false;
+ } // 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.
+
+
+ var currentMonth = DatePickervue_type_script_lang_ts_$('.ui-datepicker-month', element).val();
+ var currentYear = DatePickervue_type_script_lang_ts_$('.ui-datepicker-year', element).val();
+ element.datepicker('option', 'stepMonths', stepMonths).datepicker('setDate', new Date(currentYear, currentMonth));
+ onJqueryUiRenderedPicker();
+ return true;
+ }
+
+ function enableDisableMonthDropdown() {
+ var element = DatePickervue_type_script_lang_ts_$(root.value);
+ var monthPicker = element.find('.ui-datepicker-month')[0];
+
+ if (monthPicker) {
+ monthPicker.disabled = props.disableMonthDropdown;
+ }
+ }
+
+ function handleOtherMonthClick() {
+ if (!DatePickervue_type_script_lang_ts_$(this).hasClass('ui-state-hover')) {
+ return;
+ }
+
+ var $row = DatePickervue_type_script_lang_ts_$(this).parent();
+ var $tbody = $row.parent();
+
+ if ($row.is(':first-child')) {
+ // click on first of the month
+ $tbody.find('a').first().click();
+ } else {
+ // click on last of month
+ $tbody.find('a').last().click();
+ }
+ }
+
+ function onCalendarViewChange() {
+ // clicking left/right re-enables the month dropdown, so we disable it again
+ enableDisableMonthDropdown();
+ setDatePickerCellColors();
+ } // on a prop change (NOTE: we can't watch just `props`, since then newProps and oldProps will
+ // have the same values (since it is a proxy object). Using a copy doesn't quite work, the
+ // object it returns will always be different, BUT, since we check what changes it works
+ // for our purposes. The only downside is that it runs on every tick basically, but since
+ // that is within the context of the date picker component, it's bearable.
+
+
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () {
+ return Object.assign({}, props);
+ }, function (newProps, oldProps) {
+ var redraw = false;
+ [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;
+ }
+
+ var newProp = selector(newProps);
+ var oldProp = selector(oldProps);
+
+ if (!newProp && oldProp) {
+ redraw = true;
+ }
+
+ if (newProp && !oldProp) {
+ redraw = true;
+ }
+
+ if (newProp && oldProp && newProp.getTime() !== oldProp.getTime()) {
+ redraw = true;
+ }
+ });
+
+ if (newProps.viewDate !== oldProps.viewDate && viewDateChanged()) {
+ redraw = true;
+ }
+
+ if (newProps.stepMonths !== oldProps.stepMonths) {
+ stepMonthsChanged();
+ }
+
+ if (newProps.disableMonthDropdown !== oldProps.disableMonthDropdown) {
+ enableDisableMonthDropdown();
+ } // redraw when selected/highlighted dates change
+
+
+ if (redraw) {
+ setDatePickerCellColors();
+ }
+ });
+ 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 = 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.
+ setTimeout(function () {
+ onJqueryUiRenderedPicker();
+ });
+ }
+ });
+ 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,
+ // the originalEvent is null. we don't need to redraw again for that, so
+ // we ignore events like that.
+ if (event.originalEvent) {
+ setDatePickerCellColors();
+ }
+ }); // on hover cell, execute scope.cellHover()
+
+ element.on('mouseenter', 'tbody td', function onMouseEnter() {
+ var monthYear = getMonthYearDisplayed();
+ var $dateCell = DatePickervue_type_script_lang_ts_$(this);
+ var dateValue = getCellDate($dateCell, monthYear[0], monthYear[1]);
+ context.emit('cellHover', {
+ date: dateValue,
+ $cell: $dateCell
+ });
+ }); // overrides jquery UI handler that unhighlights a cell when the mouse leaves it
+
+ element.on('mouseout', 'tbody td a', function () {
+ setDatePickerCellColors();
+ }); // call scope.cellHoverLeave() when mouse leaves table body (can't do event on tbody, for
+ // some reason that fails, so we do two events, one on the table & one on thead)
+
+ element.on('mouseleave', 'table', function () {
+ return context.emit('cellHoverLeave');
+ }).on('mouseenter', 'thead', function () {
+ return context.emit('cellHoverLeave');
+ }); // make sure whitespace is clickable when the period makes it appropriate
+
+ 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();
+ var $target = DatePickervue_type_script_lang_ts_$(e.target).closest('a');
+
+ if (!$target.is('.ui-datepicker-next') && !$target.is('.ui-datepicker-prev')) {
+ return;
+ }
+
+ onCalendarViewChange();
+ }); // when a cell is clicked, invoke the onDateSelected function. this, in conjunction
+ // with onJqueryUiRenderedPicker(), overrides the date picker's click behavior.
+
+ element.on('click', 'td[data-month]', function (event) {
+ var $cell = DatePickervue_type_script_lang_ts_$(event.target).closest('td');
+ var month = parseInt($cell.attr('data-month'), 10);
+ var year = parseInt($cell.attr('data-year'), 10);
+ var day = parseInt($cell.children('a,span').text(), 10);
+ context.emit('dateSelect', {
+ date: new Date(year, month, day)
+ });
+ });
+ var renderPostProcessed = stepMonthsChanged();
+ viewDateChanged();
+ enableDisableMonthDropdown();
+
+ if (!renderPostProcessed) {
+ onJqueryUiRenderedPicker();
+ }
+
+ setDatePickerCellColors();
+ });
+ return {
+ root: root
+ };
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue
+
+
+
+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
+/*!
+ * 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 DatePicker_adapter = (createAngularJsAdapter({
+ component: DatePicker,
+ 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 cellHover(event, vm, scope, element, attrs, controller, $timeout) {
+ $timeout(); // trigger new digest
+ },
+ 'cell-hover-leave': function cellHoverLeave(event, vm, scope, element, attrs, controller, $timeout) {
+ $timeout(); // trigger new digest
+ },
+ '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=7bf842c2
+
+var DateRangePickervue_type_template_id_7bf842c2_hoisted_1 = {
+ id: "calendarRangeFrom"
+};
+var DateRangePickervue_type_template_id_7bf842c2_hoisted_2 = {
+ id: "calendarRangeTo"
+};
+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"])("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",
+ class: "browser-default",
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.startDateText = $event;
+ }),
+ onKeydown: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.onRangeInputChanged('from', $event);
+ }),
+ onKeyup: _cache[2] || (_cache[2] = function ($event) {
+ return _ctx.handleEnterPress($event);
+ })
+ }, null, 544), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.startDateText]])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_DatePicker, {
+ id: "calendarFrom",
+ "view-date": _ctx.startDate,
+ "selected-date-start": _ctx.fromPickerSelectedDates[0],
+ "selected-date-end": _ctx.fromPickerSelectedDates[1],
+ "highlighted-date-start": _ctx.fromPickerHighlightedDates[0],
+ "highlighted-date-end": _ctx.fromPickerHighlightedDates[1],
+ onDateSelect: _cache[3] || (_cache[3] = function ($event) {
+ return _ctx.setStartRangeDate($event.date);
+ }),
+ onCellHover: _cache[4] || (_cache[4] = function ($event) {
+ return _ctx.fromPickerHighlightedDates = _ctx.getNewHighlightedDates($event.date, $event.$cell);
+ }),
+ 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_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",
+ class: "browser-default",
+ "onUpdate:modelValue": _cache[6] || (_cache[6] = function ($event) {
+ return _ctx.endDateText = $event;
+ }),
+ onKeydown: _cache[7] || (_cache[7] = function ($event) {
+ return _ctx.onRangeInputChanged('to', $event);
+ }),
+ onKeyup: _cache[8] || (_cache[8] = function ($event) {
+ return _ctx.handleEnterPress($event);
+ })
+ }, null, 544), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.endDateText]])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_DatePicker, {
+ id: "calendarTo",
+ "view-date": _ctx.endDate,
+ "selected-date-start": _ctx.toPickerSelectedDates[0],
+ "selected-date-end": _ctx.toPickerSelectedDates[1],
+ "highlighted-date-start": _ctx.toPickerHighlightedDates[0],
+ "highlighted-date-end": _ctx.toPickerHighlightedDates[1],
+ onDateSelect: _cache[9] || (_cache[9] = function ($event) {
+ return _ctx.setEndRangeDate($event.date);
+ }),
+ onCellHover: _cache[10] || (_cache[10] = function ($event) {
+ return _ctx.toPickerHighlightedDates = _ctx.getNewHighlightedDates($event.date, $event.$cell);
+ }),
+ 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"])])]);
+}
+// 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/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,
+ endDate: String
+ },
+ components: {
+ DatePicker: DatePicker
+ },
+ data: function data() {
+ var startDate = null;
+
+ try {
+ if (this.startDate) {
+ startDate = parseDate(this.startDate);
+ }
+ } catch (e) {// ignore
+ }
+
+ var endDate = null;
+
+ try {
+ if (this.endDate) {
+ endDate = parseDate(this.endDate);
+ }
+ } catch (e) {// ignore
+ }
+
+ return {
+ fromPickerSelectedDates: [startDate, startDate],
+ toPickerSelectedDates: [endDate, endDate],
+ fromPickerHighlightedDates: [null, null],
+ toPickerHighlightedDates: [null, null],
+ startDateText: this.startDate,
+ endDateText: this.endDate,
+ startDateInvalid: false,
+ endDateInvalid: false
+ };
+ },
+ emits: ['rangeChange', 'submit'],
+ watch: {
+ startDate: function startDate() {
+ this.startDateText = this.startDate;
+ this.setStartRangeDateFromStr(this.startDate);
+ },
+ endDate: function endDate() {
+ this.endDateText = this.endDate;
+ this.setEndRangeDateFromStr(this.endDate);
+ }
+ },
+ mounted: function mounted() {
+ this.rangeChanged(); // emit with initial range pair
+ },
+ methods: {
+ setStartRangeDate: function setStartRangeDate(date) {
+ this.fromPickerSelectedDates = [date, date];
+ this.rangeChanged();
+ },
+ setEndRangeDate: function setEndRangeDate(date) {
+ this.toPickerSelectedDates = [date, date];
+ this.rangeChanged();
+ },
+ onRangeInputChanged: function onRangeInputChanged(source, event) {
+ 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')) {
+ return null;
+ }
+
+ return [date, date];
+ },
+ handleEnterPress: function handleEnterPress($event) {
+ if ($event.keyCode !== 13) {
+ return;
+ }
+
+ this.$emit('submit', {
+ start: this.startDate,
+ end: this.endDate
+ });
+ },
+ setStartRangeDateFromStr: function setStartRangeDateFromStr(dateStr) {
+ this.startDateInvalid = true;
+ var startDateParsed = null;
+
+ try {
+ if (dateStr && dateStr.length === DATE_FORMAT.length) {
+ startDateParsed = parseDate(dateStr);
+ }
+ } catch (e) {// ignore
+ }
+
+ if (startDateParsed) {
+ this.fromPickerSelectedDates = [startDateParsed, startDateParsed];
+ this.startDateInvalid = false;
+ this.rangeChanged();
+ }
+ },
+ setEndRangeDateFromStr: function setEndRangeDateFromStr(dateStr) {
+ this.endDateInvalid = true;
+ var endDateParsed = null;
+
+ try {
+ if (dateStr && dateStr.length === DATE_FORMAT.length) {
+ endDateParsed = parseDate(dateStr);
+ }
+ } catch (e) {// ignore
+ }
+
+ if (endDateParsed) {
+ this.toPickerSelectedDates = [endDateParsed, endDateParsed];
+ this.endDateInvalid = false;
+ this.rangeChanged();
+ }
+ },
+ rangeChanged: function rangeChanged() {
+ this.$emit('rangeChange', {
+ start: this.fromPickerSelectedDates[0] ? format(this.fromPickerSelectedDates[0]) : null,
+ end: this.toPickerSelectedDates[0] ? format(this.toPickerSelectedDates[0]) : null
+ });
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue
+
+
+
+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
+/*!
+ * 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 DateRangePicker_adapter = (createAngularJsAdapter({
+ component: DateRangePicker,
+ scope: {
+ startDate: {
+ angularJsBind: '<'
+ },
+ endDate: {
+ angularJsBind: '<'
+ },
+ rangeChange: {
+ angularJsBind: '&'
+ },
+ submit: {
+ angularJsBind: '&'
+ }
+ },
+ 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=6d1fa14c
+
+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, {
+ "selected-date-start": _ctx.selectedDates[0],
+ "selected-date-end": _ctx.selectedDates[1],
+ "highlighted-date-start": _ctx.highlightedDates[0],
+ "highlighted-date-end": _ctx.highlightedDates[1],
+ "view-date": _ctx.viewDate,
+ "step-months": _ctx.period === 'year' ? 12 : 1,
+ "disable-month-dropdown": _ctx.period === 'year',
+ onCellHover: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onHoverNormalCell($event.date, $event.$cell);
+ }),
+ onCellHoverLeave: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.onHoverLeaveNormalCells();
+ }),
+ onDateSelect: _cache[2] || (_cache[2] = function ($event) {
+ return _ctx.onDateSelected($event.date);
+ })
+ }, 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=6d1fa14c
+
+// 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 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: {
+ type: String,
+ required: true
+ },
+ date: [String, Date]
+ },
+ components: {
+ DatePicker: DatePicker
+ },
+ emits: ['select'],
+ setup: function setup(props, context) {
+ var viewDate = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(props.date);
+ var selectedDates = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])([null, null]);
+ var highlightedDates = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])([null, null]);
+
+ 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] = 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 < 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');
+
+ if (isOutOfMinMaxDateRange || shouldNotHighlightFromWhitespace) {
+ highlightedDates.value = [null, null];
+ return;
+ }
+
+ highlightedDates.value = getBoundedDateRange(cellDate);
+ }
+
+ function onHoverLeaveNormalCells() {
+ highlightedDates.value = [null, null];
+ }
+
+ function onDateSelected(date) {
+ context.emit('select', {
+ date: date
+ });
+ }
+
+ 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);
+ onChanges();
+ return {
+ selectedDates: selectedDates,
+ highlightedDates: highlightedDates,
+ viewDate: viewDate,
+ onHoverNormalCell: onHoverNormalCell,
+ onHoverLeaveNormalCells: onHoverLeaveNormalCells,
+ onDateSelected: onDateSelected
+ };
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue
+
+
+
+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
+/*!
+ * 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 PeriodDatePicker_adapter = (createAngularJsAdapter({
+ component: PeriodDatePicker,
+ scope: {
+ period: {
+ angularJsBind: '<'
+ },
+ date: {
+ angularJsBind: '<'
+ },
+ select: {
+ angularJsBind: '&'
+ }
+ },
+ 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/SiteSelector/SiteSelector.vue?vue&type=template&id=48e19035
+
+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 _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");
+
+ 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/SiteSelector/SiteSelector.vue?vue&type=template&id=48e19035
+
+// 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;
+
+ 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: {
+ 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,
+ 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: 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, "").concat(this.searchTerm, " ").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/SiteSelector/SiteSelector.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue
+
+
+
+SiteSelectorvue_type_script_lang_ts.render = SiteSelectorvue_type_template_id_48e19035_render
+
+/* 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
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+
+
+/* harmony default export */ var SiteSelector_adapter = (createAngularJsAdapter({
+ component: SiteSelector,
+ require: '?ngModel',
+ scope: {
+ showSelectedSite: {
+ angularJsBind: '='
+ },
+ 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: ['$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: ./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 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));
+ }
+ };
+}
+
+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=7b45bbd5
+
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_1 = {
+ ref: "root",
+ class: "quickAccessInside"
+};
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_2 = ["title", "placeholder"];
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_3 = {
+ class: "dropdown"
+};
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_4 = {
+ class: "no-result"
+};
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_5 = ["onClick"];
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_6 = ["onMouseenter", "onClick"];
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_7 = {
+ class: "quickAccessMatomoSearch"
+};
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_8 = ["onMouseenter", "onClick"];
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_9 = ["textContent"];
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_10 = {
+ class: "quick-access-category helpCategory"
+};
+var QuickAccessvue_type_template_id_7b45bbd5_hoisted_11 = ["href"];
+function QuickAccessvue_type_template_id_7b45bbd5_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_7b45bbd5_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_7b45bbd5_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_7b45bbd5_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_7b45bbd5_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_7b45bbd5_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_7b45bbd5_hoisted_6);
+ }), 128))]);
+ }), 128)), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", QuickAccessvue_type_template_id_7b45bbd5_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_7b45bbd5_hoisted_9)], 42, QuickAccessvue_type_template_id_7b45bbd5_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_7b45bbd5_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_7b45bbd5_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=7b45bbd5
+
+// 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.substr(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_7b45bbd5_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: {
+ 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/FieldArray/FieldArray.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FieldArray/FieldArray.vue
+
+
+
+FieldArrayvue_type_script_lang_ts.render = FieldArrayvue_type_template_id_66b76384_render
+
+/* 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
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+/* harmony default export */ var FieldArray_adapter = (createAngularJsAdapter({
+ component: FieldArray,
+ require: '?ngModel',
+ scope: {
+ name: {
+ angularJsBind: '='
+ },
+ field: {
+ angularJsBind: '='
+ }
+ },
+ 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: ./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
+ */
+
+
+/* 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
+
+ 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: ./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
+
+var PeriodSelectorvue_type_template_id_0115e905_hoisted_1 = {
+ ref: "root",
+ class: "periodSelector piwikSelector"
+};
+var PeriodSelectorvue_type_template_id_0115e905_hoisted_2 = ["title"];
+
+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);
+
+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
+
+
+
+ActivityIndicatorvue_type_script_lang_ts.render = ActivityIndicatorvue_type_template_id_7c5fe406_render
+
+/* 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());
+}
+
+/* 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_52166f8a_hoisted_2 = ["data-notification-instance-id"];
+var Notificationvue_type_template_id_52166f8a_hoisted_3 = {
+ key: 1
+};
+var Notificationvue_type_template_id_52166f8a_hoisted_4 = {
+ class: "notification-body"
+};
+var Notificationvue_type_template_id_52166f8a_hoisted_5 = ["innerHTML"];
+var Notificationvue_type_template_id_52166f8a_hoisted_6 = {
+ key: 1
+};
+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) {
+ return _ctx.toastClosed();
+ })
+ }, {
+ 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_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: ""
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Transition"], {
+ name: _ctx.animate ? 'fade-in' : undefined,
+ appear: ""
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["notification system", _ctx.cssClasses]),
+ style: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeStyle"])(_ctx.style),
+ ref: "root",
+ "data-notification-instance-id": _ctx.notificationInstanceId
+ }, [_ctx.canClose ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("button", {
+ key: 0,
+ type: "button",
+ class: "close",
+ "data-dismiss": "alert",
+ 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_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_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"])])];
+ }),
+ _: 3
+ }, 8, ["name"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)];
+ }),
+ _: 3
+ }, 8, ["name"]);
+}
+// 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/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,
+ Notificationvue_type_script_lang_ts_$ = Notificationvue_type_script_lang_ts_window.$;
+/* harmony default export */ var Notificationvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ notificationId: String,
+ // NOTE: notificationId refers to server side ID for notifications stored in the session.
+ // this ID is just so it can be selected outside of this component (just for scrolling).
+ notificationInstanceId: String,
+ title: String,
+ context: String,
+ type: String,
+ noclear: Boolean,
+ toastLength: {
+ type: Number,
+ default: 12 * 1000
+ },
+ style: [String, Object],
+ animate: Boolean,
+ message: String,
+ cssClass: String
+ },
+ computed: {
+ cssClasses: function cssClasses() {
+ var result = {};
+
+ if (this.context) {
+ result["notification-".concat(this.context)] = true;
+ }
+
+ if (this.cssClass) {
+ result[this.cssClass] = true;
+ }
+
+ return result;
+ },
+ canClose: function canClose() {
+ if (this.type === 'persistent') {
+ // otherwise it is never possible to dismiss the notification
+ return true;
+ }
+
+ return !this.noclear;
+ }
+ },
+ emits: ['closed'],
+ data: function data() {
+ return {
+ deleted: false
+ };
+ },
+ mounted: function mounted() {
+ var _this = this;
+
+ var addToastEvent = function addToastEvent() {
+ setTimeout(function () {
+ _this.deleted = true;
+ }, _this.toastLength);
+ };
+
+ if (this.type === 'toast') {
+ addToastEvent();
+ }
+
+ if (this.style) {
+ Notificationvue_type_script_lang_ts_$(this.$refs.root).css(this.style);
+ }
+ },
+ methods: {
+ toastClosed: function toastClosed() {
+ var _this2 = this;
+
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ _this2.$emit('closed');
+ });
+ },
+ closeNotification: function closeNotification(event) {
+ var _this3 = this;
+
+ if (this.canClose && event && event.target) {
+ this.deleted = true;
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ _this3.$emit('closed');
+ });
+ }
+
+ this.markNotificationAsRead();
+ },
+ markNotificationAsRead: function markNotificationAsRead() {
+ if (!this.notificationId) {
+ return;
+ }
+
+ AjaxHelper_AjaxHelper.post({
+ module: 'CoreHome',
+ action: 'markNotificationAsRead'
+ }, {
+ notificationId: this.notificationId
+ }, {
+ withTokenInUrl: true
+ });
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.vue
+
+
+
+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
+/*!
+ * 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 Notification_adapter = (createAngularJsAdapter({
+ component: Notification,
+ scope: {
+ notificationId: {
+ angularJsBind: '@?'
+ },
+ title: {
+ angularJsBind: '@?notificationTitle'
+ },
+ context: {
+ angularJsBind: '@?'
+ },
+ type: {
+ angularJsBind: '@?'
+ },
+ noclear: {
+ angularJsBind: '@?',
+ transform: transformAngularJsBoolAttr
+ },
+ toastLength: {
+ angularJsBind: '@?'
+ }
+ },
+ directiveName: 'piwikNotification',
+ transclude: true
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notifications.store.ts
+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); } }
+
+function Notifications_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) Notifications_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) Notifications_store_defineProperties(Constructor, staticProps); return Constructor; }
+
+function Notifications_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 Notifications_store_window = window,
+ Notifications_store_$ = Notifications_store_window.$;
+
+var Notifications_store_NotificationsStore = /*#__PURE__*/function () {
+ function NotificationsStore() {
+ Notifications_store_classCallCheck(this, NotificationsStore);
+
+ Notifications_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({
+ notifications: []
+ }));
+
+ Notifications_store_defineProperty(this, "nextNotificationId", 0);
+ }
+
+ Notifications_store_createClass(NotificationsStore, [{
+ key: "state",
+ get: function get() {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(this.privateState);
+ }
+ }, {
+ key: "appendNotification",
+ value: function appendNotification(notification) {
+ this.checkMessage(notification.message); // remove existing notification before adding
+
+ if (notification.id) {
+ this.remove(notification.id);
+ }
+
+ this.privateState.notifications.push(notification);
+ }
+ }, {
+ key: "prependNotification",
+ value: function prependNotification(notification) {
+ this.checkMessage(notification.message); // remove existing notification before adding
+
+ if (notification.id) {
+ this.remove(notification.id);
+ }
+
+ this.privateState.notifications.unshift(notification);
+ }
+ /**
+ * Removes a previously shown notification having the given notification id.
+ */
+
+ }, {
+ key: "remove",
+ value: function remove(id) {
+ this.privateState.notifications = this.privateState.notifications.filter(function (n) {
+ return n.id !== id;
+ });
+ }
+ }, {
+ key: "parseNotificationDivs",
+ value: function parseNotificationDivs() {
+ var _this = this;
+
+ var $notificationNodes = Notifications_store_$('[data-role="notification"]');
+ var notificationsToShow = [];
+ $notificationNodes.each(function (index, notificationNode) {
+ var $notificationNode = Notifications_store_$(notificationNode);
+ var attributes = $notificationNode.data();
+ var message = $notificationNode.html();
+
+ if (message) {
+ notificationsToShow.push(Object.assign(Object.assign({}, attributes), {}, {
+ message: message,
+ animate: false
+ }));
+ }
+
+ $notificationNodes.remove();
+ });
+ notificationsToShow.forEach(function (n) {
+ return _this.show(n);
+ });
+ }
+ }, {
+ key: "clearTransientNotifications",
+ value: function clearTransientNotifications() {
+ this.privateState.notifications = this.privateState.notifications.filter(function (n) {
+ return n.type !== 'transient';
+ });
+ }
+ /**
+ * Creates a notification and shows it to the user.
+ */
+
+ }, {
+ key: "show",
+ value: function show(notification) {
+ this.checkMessage(notification.message);
+ var addMethod = notification.prepend ? this.prependNotification : this.appendNotification;
+ var notificationPosition = '#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
+ var modalSelector = '.modal.open .modal-content';
+ var modal = document.querySelector(modalSelector);
+
+ if (modal) {
+ if (!modal.querySelector('#modalNotificationContainer')) {
+ Notifications_store_$(modal).prepend('
');
+ }
+
+ notificationPosition = "".concat(modalSelector, " #modalNotificationContainer");
+ addMethod = this.prependNotification;
+ }
+ }
+
+ var group = notification.group || (notificationPosition ? notificationPosition.toString() : '');
+ this.initializeNotificationContainer(notificationPosition, group);
+ var notificationInstanceId = (this.nextNotificationId += 1).toString();
+ addMethod.call(this, Object.assign(Object.assign({}, notification), {}, {
+ noclear: !!notification.noclear,
+ group: group,
+ notificationId: notification.id,
+ notificationInstanceId: notificationInstanceId,
+ type: notification.type || 'transient'
+ }));
+ return notificationInstanceId;
+ }
+ }, {
+ key: "scrollToNotification",
+ value: function scrollToNotification(notificationInstanceId) {
+ setTimeout(function () {
+ var element = document.querySelector("[data-notification-instance-id='".concat(notificationInstanceId, "']"));
+
+ if (element) {
+ Matomo_Matomo.helper.lazyScrollTo(element, 250);
+ }
+ });
+ }
+ /**
+ * Shows a notification at a certain point with a quick upwards animation.
+ */
+
+ }, {
+ key: "toast",
+ value: function toast(notification) {
+ this.checkMessage(notification.message);
+ var $placeat = notification.placeat ? Notifications_store_$(notification.placeat) : undefined;
+
+ if (!$placeat || !$placeat.length) {
+ throw new Error('A valid selector is required for the placeat option when using Notification.toast().');
+ }
+
+ var toastElement = document.createElement('div');
+ toastElement.style.position = 'absolute';
+ toastElement.style.top = "".concat($placeat.offset().top, "px");
+ toastElement.style.left = "".concat($placeat.offset().left, "px");
+ toastElement.style.zIndex = '1000';
+ document.body.appendChild(toastElement);
+ var app = createVueApp({
+ render: function render() {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(Notification, Object.assign(Object.assign({}, notification), {}, {
+ notificationId: notification.id,
+ type: 'toast',
+ onClosed: function onClosed() {
+ app.unmount();
+ }
+ }));
+ }
+ });
+ app.mount(toastElement);
+ }
+ }, {
+ key: "initializeNotificationContainer",
+ value: function initializeNotificationContainer(notificationPosition, group) {
+ if (!notificationPosition) {
+ return;
+ }
+
+ var $container = Notifications_store_$(notificationPosition);
+
+ if ($container.children('.notification-group').length) {
+ return;
+ } // avoiding a dependency cycle. won't need to do this when NotificationGroup's do not need
+ // to be dynamically initialized.
+
+
+ var NotificationGroup = window.CoreHome.NotificationGroup; // eslint-disable-line
+
+ var app = createVueApp({
+ template: ' ',
+ data: function data() {
+ return {
+ group: group
+ };
+ }
+ });
+ app.component('NotificationGroup', NotificationGroup);
+ app.mount($container[0]);
+ }
+ }, {
+ key: "checkMessage",
+ value: function checkMessage(message) {
+ if (!message) {
+ throw new Error('No message given, cannot display notification');
+ }
+ }
+ }]);
+
+ return NotificationsStore;
+}();
+
+var Notifications_store_instance = new Notifications_store_NotificationsStore();
+/* harmony default export */ var Notifications_store = (Notifications_store_instance); // parse notifications on dom load
+
+Notifications_store_$(function () {
+ return Notifications_store_instance.parseNotificationDivs();
+});
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notifications.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').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
+
+var NotificationGroupvue_type_template_id_672051da_hoisted_1 = {
+ class: "notification-group"
+};
+var NotificationGroupvue_type_template_id_672051da_hoisted_2 = ["innerHTML"];
+function NotificationGroupvue_type_template_id_672051da_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_Notification = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Notification");
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", NotificationGroupvue_type_template_id_672051da_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.notifications, function (notification, index) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Notification, {
+ key: notification.id || "no-id-".concat(index),
+ "notification-id": notification.id,
+ title: notification.title,
+ context: notification.context,
+ type: notification.type,
+ noclear: notification.noclear,
+ "toast-length": notification.toastLength,
+ style: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeStyle"])(notification.style),
+ animate: notification.animate,
+ message: notification.message,
+ "notification-instance-id": notification.notificationInstanceId,
+ "css-class": notification.class,
+ onClosed: function onClosed($event) {
+ return _ctx.removeNotification(notification.id);
+ }
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ innerHTML: _ctx.$sanitize(notification.message)
+ }, null, 8, NotificationGroupvue_type_template_id_672051da_hoisted_2)];
+ }),
+ _: 2
+ }, 1032, ["notification-id", "title", "context", "type", "noclear", "toast-length", "style", "animate", "message", "notification-instance-id", "css-class", "onClosed"]);
+ }), 128))]);
+}
+// 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/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
- if (binding.value.afterFocus) {
- binding.value.afterFocus();
- }
- }, 5);
- }
-}
-/* harmony default export */ var FocusIf = ({
- mounted: function mounted(el, binding) {
- doFocusIf(el, binding);
+
+/* harmony default export */ var NotificationGroupvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ group: String
},
- updated: function updated(el, binding) {
- doFocusIf(el, binding);
+ components: {
+ Notification: Notification
+ },
+ computed: {
+ notifications: function notifications() {
+ var _this = this;
+
+ return Notifications_store.state.notifications.filter(function (n) {
+ if (_this.group) {
+ return _this.group === n.group;
+ }
+
+ return !n.group;
+ });
+ }
+ },
+ methods: {
+ removeNotification: function removeNotification(id) {
+ Notifications_store.remove(id);
+ }
}
-});
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/FocusIf/FocusIf.adapter.ts
+}));
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/NotificationGroup.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/NotificationGroup.vue
+
+
+
+NotificationGroupvue_type_script_lang_ts.render = NotificationGroupvue_type_template_id_672051da_render
+
+/* harmony default export */ var Notification_NotificationGroup = (NotificationGroupvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/index.ts
/*!
* Matomo - free/libre analytics platform
*
@@ -2098,38 +8800,19 @@ function doFocusIf(el, binding) {
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
-/**
- * If the given expression evaluates to true the element will be focused
- *
- * Example:
- *
- */
-function piwikFocusIf() {
- return {
- restrict: 'A',
- link: function focusIfLink(scope, element, attrs) {
- scope.$watch(attrs.piwikFocusIf, function (newValue) {
- var binding = {
- instance: null,
- arg: newValue ? '1' : undefined,
- value: {
- afterFocus: function afterFocus() {
- return scope.$apply();
- }
- },
- oldValue: null,
- modifiers: {},
- dir: {}
- };
- FocusIf.updated(element[0], binding);
- });
- }
- };
-}
-angular.module('piwikApp.directive').directive('piwikFocusIf', piwikFocusIf);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.ts
+
+
+// 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
*
@@ -2138,174 +8821,149 @@ angular.module('piwikApp.directive').directive('piwikFocusIf', piwikFocusIf);
*/
-function onExpand(element) {
- element.classList.toggle('expanded');
- var positionElement = element.querySelector('.dropdown.positionInViewport');
+var ReportingPages_store_ReportingPagesStore = /*#__PURE__*/function () {
+ function ReportingPagesStore() {
+ var _this = this;
- if (positionElement) {
- Matomo_Matomo.helper.setMarginLeftToBeInViewport(positionElement);
- }
-}
+ ReportingPages_store_classCallCheck(this, ReportingPagesStore);
-function ExpandOnClick_onClickOutsideElement(element, binding, event) {
- var hadUsedScrollbar = binding.value.isMouseDown && binding.value.hasScrolled;
- binding.value.isMouseDown = false;
- binding.value.hasScrolled = false;
+ ReportingPages_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({
+ pages: []
+ }));
- if (hadUsedScrollbar) {
- return;
- }
+ 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);
+ }));
- if (!element.contains(event.target)) {
- element.classList.remove('expanded');
+ 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;
+ }));
}
-}
-function ExpandOnClick_onScroll(binding) {
- binding.value.hasScrolled = true;
-}
+ 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;
-function ExpandOnClick_onMouseDown(binding) {
- binding.value.isMouseDown = true;
- binding.value.hasScrolled = false;
-}
+ 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;
+ });
+ }
-function ExpandOnClick_onEscapeHandler(element, binding, event) {
- if (event.which === 27) {
- binding.value.isMouseDown = false;
- binding.value.hasScrolled = false;
- element.classList.remove('expanded');
- }
-}
+ return this.fetchAllPagesPromise.then(function () {
+ return _this2.pages.value;
+ });
+ }
+ }]);
-var ExpandOnClick_doc = document.documentElement;
-/**
- * Usage (in a component):
- *
- * directives: {
- * ExpandOnClick: ExpandOnClick(), // function call is important since we store state
- * // in this directive
- * }
- */
+ 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(); }
-/* harmony default export */ var ExpandOnClick = ({
- mounted: function mounted(el, binding) {
- binding.value.isMouseDown = false;
- binding.value.hasScrolled = false;
- binding.value.onExpand = onExpand.bind(null, el);
- binding.value.onEscapeHandler = ExpandOnClick_onEscapeHandler.bind(null, el, binding);
- 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); // have to use jquery here since existing code will do $(...).click(). which apparently
- // doesn't work when using addEventListener.
+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; }
- window.$(binding.value.expander).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);
- ExpandOnClick_doc.removeEventListener('keyup', binding.value.onEscapeHandler);
- ExpandOnClick_doc.removeEventListener('mousedown', binding.value.onMouseDown);
- ExpandOnClick_doc.removeEventListener('mouseup', binding.value.onClickOutsideElement);
- ExpandOnClick_doc.removeEventListener('scroll', binding.value.onScroll);
- }
-});
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnClick/ExpandOnClick.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 sortOrderables(menu) {
+ var result = Orderable_toConsumableArray(menu || []);
-function piwikExpandOnClick() {
- return {
- restrict: 'A',
- link: function expandOnClickLink(scope, element) {
- var binding = {
- instance: null,
- value: {
- expander: element.find('.title').first()[0]
- },
- oldValue: null,
- modifiers: {},
- dir: {}
- };
- ExpandOnClick.mounted(element[0], binding);
- element.on('$destroy', function () {
- return ExpandOnClick.unmounted(element[0], binding);
- });
+ result.sort(function (lhs, rhs) {
+ if (lhs.order < rhs.order) {
+ return -1;
}
- };
+
+ if (lhs.order > rhs.order) {
+ return 1;
+ }
+
+ return 0;
+ });
+ return result;
}
-piwikExpandOnClick.$inject = [];
-angular.module('piwikApp').directive('piwikExpandOnClick', piwikExpandOnClick);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.ts
+// 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;
-
-function onMouseEnter(element) {
- element.classList.add('expanded');
- var positionElement = element.querySelector('.dropdown.positionInViewport');
-
- if (positionElement) {
- Matomo_Matomo.helper.setMarginLeftToBeInViewport(positionElement);
- }
-}
-
-function onMouseLeave(element) {
- element.classList.remove('expanded');
-}
-
-function ExpandOnHover_onClickOutsideElement(element, event) {
- if (!element.contains(event.target)) {
- element.classList.remove('expanded');
+ if (container.subcategories) {
+ return container.subcategories;
}
-}
-function ExpandOnHover_onEscapeHandler(element, event) {
- if (event.which === 27) {
- element.classList.remove('expanded');
- }
+ return [];
}
-
-var ExpandOnHover_doc = document.documentElement;
-/**
- * Usage (in a component):
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingMenu/Subcategory.ts
+/*!
+ * Matomo - free/libre analytics platform
*
- * directives: {
- * ExpandOnHover: ExpandOnHover(), // function call is important since we store state
- * // in this directive
- * }
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
+function getSubcategoryChildren(subcategory) {
+ var container = subcategory;
-/* harmony default export */ var ExpandOnHover = ({
- mounted: function mounted(el, binding) {
- binding.value.onMouseEnter = onMouseEnter.bind(null, el);
- 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);
- 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);
- el.removeEventListener('mouseleave', binding.value.onMouseLeave);
- document.removeEventListener('keyup', binding.value.onEscapeHandler);
- document.removeEventListener('mouseup', binding.value.onClickOutsideElement);
+ if (container.subcategories) {
+ return container.subcategories;
}
-});
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ExpandOnHover/ExpandOnHover.adapter.ts
+
+ 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
*
@@ -2314,124 +8972,221 @@ var ExpandOnHover_doc = document.documentElement;
*/
-function piwikExpandOnHover() {
- return {
- restrict: 'A',
- link: function expandOnHoverLink(scope, element) {
- var binding = {
- instance: null,
- value: {
- expander: element.find('.title').first()[0]
- },
- oldValue: null,
- modifiers: {},
- dir: {}
- };
- ExpandOnHover.mounted(element[0], binding);
- element.on('$destroy', function () {
- return ExpandOnHover.unmounted(element[0], binding);
- });
- }
- };
-}
-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=64e27324
-var _hoisted_1 = {
- ref: "root"
-};
-function MatomoDialogvue_type_template_id_64e27324_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]]);
+
+
+
+
+function isNumeric(text) {
+ var n = parseFloat(text);
+ return !Number.isNaN(n) && Number.isFinite(n);
}
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=template&id=64e27324
-// 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
+var ReportingMenu_store_ReportingMenuStore = /*#__PURE__*/function () {
+ function ReportingMenuStore() {
+ var _this = this;
+ ReportingMenu_store_classCallCheck(this, ReportingMenuStore);
-/* harmony default export */ var MatomoDialogvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
- props: {
- /**
- * Whether the modal is displayed or not;
- */
- modelValue: {
- type: Boolean,
- required: true
- },
+ ReportingMenu_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({
+ activeCategoryId: null,
+ activeSubcategoryId: null,
+ activeSubsubcategoryId: null
+ }));
- /**
- * Only here for backwards compatibility w/ AngularJS. If supplied, we use this
- * element to launch the modal instead of the element in the slot. This should not
- * be used for new Vue code.
- *
- * @deprecated
- */
- element: {
- type: HTMLElement,
- required: false
+ 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;
+ });
}
- },
- emits: ['yes', 'no', 'closeEnd', 'close', 'validation', 'update:modelValue'],
- activated: function activated() {
- this.$emit('update:modelValue', false);
- },
- watch: {
- modelValue: function modelValue(newValue, oldValue) {
- var _this = this;
+ }, {
+ key: "reloadMenuItems",
+ value: function reloadMenuItems() {
+ var _this3 = this;
- if (newValue) {
- var slotElement = this.element || this.$refs.root.firstElementChild;
- Matomo_Matomo.helper.modalConfirm(slotElement, {
- yes: function yes() {
- _this.$emit('yes');
- },
- no: function no() {
- _this.$emit('no');
- },
- validation: function validation() {
- _this.$emit('validation');
+ 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;
}
- }, {
- onCloseEnd: function onCloseEnd() {
- // materialize removes the child element, so we move it back to the slot
- if (!_this.element) {
- _this.$refs.root.appendChild(slotElement);
+
+ 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;
}
- _this.$emit('update:modelValue', false);
+ if (isSubcategoryDisplayed) {
+ categoryGroups.name = subcategory.name;
+ }
- _this.$emit('closeEnd');
+ var entityId = page.subcategory.id;
+ subcategory.tooltip = "".concat(subcategory.name, " (id = ").concat(entityId, ")");
+ categoryGroups.subcategories.push(subcategory);
+ return;
}
+
+ category.subcategories.push(subcategory);
});
- } else if (newValue === false && oldValue === true) {
- // the user closed the dialog, e.g. by pressing Esc or clicking away from it
- this.$emit('close');
- }
+
+ 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);
}
- }
-}));
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue?vue&type=script&lang=ts
-
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue
+ }, {
+ 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;
+ }
-MatomoDialogvue_type_script_lang_ts.render = MatomoDialogvue_type_template_id_64e27324_render
+ this.privateState.activeCategoryId = category.id;
+ this.privateState.activeSubcategoryId = subcategory.id;
-/* 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(); }
+ if (subsubcategory) {
+ this.privateState.activeSubsubcategoryId = subsubcategory.id;
+ }
+ }
+ }]);
-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."); }
+ 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 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 Widgets_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
-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 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 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 Widgets_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) Widgets_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) Widgets_store_defineProperties(Constructor, staticProps); return Constructor; }
-function createAngularJsAdapter_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+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
@@ -2441,206 +9196,363 @@ function createAngularJsAdapter_arrayWithHoles(arr) { if (Array.isArray(arr)) re
*/
-var transcludeCounter = 0;
+function getWidgetChildren(widget) {
+ var container = widget;
-function toKebabCase(arg) {
- return arg.substring(0, 1).toLowerCase() + arg.substring(1).replace(/[A-Z]/g, function (s) {
- return "-".concat(s.toLowerCase());
- });
-}
+ if (container.widgets) {
+ return container.widgets;
+ }
-function toAngularJsCamelCase(arg) {
- return arg.substring(0, 1).toLowerCase() + arg.substring(1).replace(/-([a-z])/g, function (s, p) {
- return p.toUpperCase();
- });
+ return [];
}
-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;
+var Widgets_store_WidgetsStore = /*#__PURE__*/function () {
+ function WidgetsStore() {
+ var _this = this;
- if (transclude) {
- transcludeCounter += 1;
+ 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;
+ }));
}
- var angularJsScope = {};
- Object.entries(scope).forEach(function (_ref) {
- var _ref2 = createAngularJsAdapter_slicedToArray(_ref, 2),
- scopeVarName = _ref2[0],
- info = _ref2[1];
+ Widgets_store_createClass(WidgetsStore, [{
+ key: "fetchAvailableWidgets",
+ value: function fetchAvailableWidgets() {
+ var _this2 = this;
- if (!info.vue) {
- info.vue = scopeVarName;
- }
+ // 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);
+ }
- if (info.angularJsBind) {
- angularJsScope[scopeVarName] = info.angularJsBind;
+ 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;
+ }
- function angularJsAdapter() {
- for (var _len = arguments.length, injectedServices = new Array(_len), _key = 0; _key < _len; _key++) {
- injectedServices[_key] = arguments[_key];
+ 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 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 = '';
+ 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
- if (transclude) {
- rootVueTemplate += '
';
- }
+ ReportingMenu_store.enterSubcategory(categoryToLoad, subcategoryToLoad);
- rootVueTemplate += ' '; // build the vue app
+ _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();
+ }
- 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];
+ _this.helpShownCategory = null;
- var value = ngScope[scopeVarName];
+ if (_this.showSubcategoryHelpOnLoad) {
+ _this.showHelp(_this.showSubcategoryHelpOnLoad.category, _this.showSubcategoryHelpOnLoad.subcategory);
- if (typeof value === 'undefined' && typeof info.default !== 'undefined') {
- value = info.default instanceof Function ? info.default.apply(info, [ngScope, ngElement, ngAttrs].concat(injectedServices)) : info.default;
- }
+ _this.showSubcategoryHelpOnLoad = null;
+ }
- if (info.transform) {
- value = info.transform(value);
- }
+ 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
- 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
- };
- }
+ if (category && subcategory) {
+ var found = ReportingMenu_store.findSubcategory(category, subcategory);
- return undefined;
- },
- methods: {
- onEventHandler: function onEventHandler(name, $event) {
- var scopePropertyName = toAngularJsCamelCase(name);
+ 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 (ngScope[scopePropertyName]) {
- ngScope[scopePropertyName]($event);
- }
+ 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;
+ }
- 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
+ Notifications_store.remove(REPORTING_HELP_NOTIFICATION_ID);
- 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
+ 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)
- Object.entries(scope).forEach(function (_ref7) {
- var _ref8 = createAngularJsAdapter_slicedToArray(_ref7, 2),
- scopeVarName = _ref8[0],
- info = _ref8[1];
+ 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 (!info.angularJsBind || info.angularJsBind === '&') {
- 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;
+ }
- ngScope.$watch(scopeVarName, function (newValue) {
- var newValueFinal = newValue;
+ var prefixText = translate('CoreHome_ReportingCategoryHelpPrefix', category.name, subcategory.name);
+ var prefix = "".concat(prefixText, " ");
+ 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
- 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;
- });
- });
+ReportingMenuvue_type_script_lang_ts.render = ReportingMenuvue_type_template_id_0f6008b2_render
- if (transclude) {
- $(vm.transcludeTarget).append(clone);
- }
+/* 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
+ */
- if (postCreate) {
- postCreate.apply(void 0, [vm, ngScope, ngElement, ngAttrs].concat(injectedServices));
- }
- ngElement.on('$destroy', function () {
- app.unmount();
- });
- }
- };
- }
- };
+/* 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
+ */
- if (transclude) {
- adapter.transclude = true;
- adapter.template = "
");
+ // 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;
+}
- return adapter;
- }
+function reportingMenuModelAdapter() {
+ return {
+ get menu() {
+ return ReportingMenu_store.menu.value;
+ },
- angularJsAdapter.$inject = $inject || [];
- angular.module('piwikApp').directive(directiveName, angularJsAdapter);
- return angularJsAdapter;
+ 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));
+ });
+ }
+ };
}
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts
+
+window.angular.module('piwikApp.service').factory('reportingMenuModel', reportingMenuModelAdapter);
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.adapter.ts
/*!
* Matomo - free/libre analytics platform
*
@@ -2649,299 +9561,479 @@ function createAngularJsAdapter(options) {
*/
-/* harmony default export */ var MatomoDialog_adapter = (createAngularJsAdapter({
- component: MatomoDialog,
- scope: {
- show: {
- vue: 'modelValue',
- default: false
- },
- element: {
- default: function _default(scope, element) {
- return element[0];
- }
- }
- },
- events: {
- yes: function yes($event, scope, element, attrs) {
- if (attrs.yes) {
- scope.$eval(attrs.yes);
- setTimeout(function () {
- scope.$apply();
- }, 0);
- }
+
+function reportingPagesModelAdapter() {
+ return {
+ get pages() {
+ return ReportingPages_store.pages.value;
},
- no: function no($event, scope, element, attrs) {
- if (attrs.no) {
- scope.$eval(attrs.no);
- setTimeout(function () {
- scope.$apply();
- }, 0);
- }
+
+ findPageInCategory: function findPageInCategory() {
+ return clone(ReportingPages_store.findPageInCategory.apply(ReportingPages_store, arguments));
},
- validation: function validation($event, scope, element, attrs) {
- if (attrs.no) {
- scope.$eval(attrs.no);
- setTimeout(function () {
- scope.$apply();
- }, 0);
- }
+ findPage: function findPage() {
+ return clone(ReportingPages_store.findPage.apply(ReportingPages_store, arguments));
},
- close: function close($event, scope, element, attrs) {
- if (attrs.close) {
- scope.$eval(attrs.close);
- setTimeout(function () {
- scope.$apply();
- }, 0);
- }
+ reloadAllPages: function reloadAllPages() {
+ return ReportingPages_store.reloadAllPages().then(function (p) {
+ return cloneThenApply(p);
+ });
},
- 'update:modelValue': function updateModelValue(newValue, scope, element, attrs, $parse) {
- setTimeout(function () {
- scope.$apply($parse(attrs.piwikDialog).assign(scope, newValue));
- }, 0);
+ getAllPages: function getAllPages() {
+ return ReportingPages_store.getAllPages().then(function (p) {
+ return cloneThenApply(p);
+ });
}
- },
- $inject: ['$parse'],
- directiveName: 'piwikDialog',
- transclude: true,
- mountPointFactory: function mountPointFactory(scope, element) {
- var vueRootPlaceholder = $('
');
- vueRootPlaceholder.appendTo(element);
- return vueRootPlaceholder[0];
- },
- postCreate: function postCreate(vm, scope, element, attrs) {
- scope.$watch(attrs.piwikDialog, function (newValue, oldValue) {
- if (oldValue !== newValue) {
- vm.modelValue = newValue || false;
+ };
+}
+
+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;
+ });
}
- });
- },
- 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=40f81493
-var EnrichedHeadlinevue_type_template_id_40f81493_hoisted_1 = {
+ 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,
- class: "title",
- tabindex: "6"
+ rel: "noreferrer noopener",
+ target: "_blank",
+ href: "https://matomo.org/faq/troubleshooting/faq_19489/"
};
-var _hoisted_2 = ["href", "title"];
-var _hoisted_3 = {
- class: "iconsBar"
+var WidgetLoadervue_type_template_id_2dfca834_hoisted_4 = {
+ class: "theWidgetContent",
+ ref: "widgetContent"
};
-var _hoisted_4 = ["href", "title"];
+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
-var _hoisted_5 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
- class: "icon-help"
-}, null, -1);
-var _hoisted_6 = [_hoisted_5];
-var _hoisted_7 = ["title"];
-var _hoisted_8 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
- class: "icon-info"
-}, null, -1);
-var _hoisted_9 = [_hoisted_8];
-var _hoisted_10 = {
- class: "ratingIcons"
-};
-var _hoisted_11 = {
- class: "inlineHelp"
-};
-var _hoisted_12 = ["innerHTML"];
-var _hoisted_13 = ["href"];
-function EnrichedHeadlinevue_type_template_id_40f81493_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", {
- class: "enrichedHeadline",
- onMouseenter: _cache[1] || (_cache[1] = function ($event) {
- return _ctx.showIcons = true;
- }),
- onMouseleave: _cache[2] || (_cache[2] = function ($event) {
- 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_40f81493_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,
- title: _ctx.translate('CoreHome_ClickToEditX', _ctx.$sanitize(_ctx.actualFeatureName))
- }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")], 8, _hoisted_2)) : 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", _hoisted_3, [_ctx.helpUrl && !_ctx.actualInlineHelp ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", {
- key: 0,
- rel: "noreferrer noopener",
- target: "_blank",
- class: "helpIcon",
- href: _ctx.helpUrl,
- title: _ctx.translate('CoreHome_ExternalHelp')
- }, _hoisted_6, 8, _hoisted_4)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.actualInlineHelp ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("a", {
- key: 1,
- onClick: _cache[0] || (_cache[0] = function ($event) {
- return _ctx.showInlineHelp = !_ctx.showInlineHelp;
- }),
- class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["helpIcon", {
- 'active': _ctx.showInlineHelp
- }]),
- title: _ctx.translate(_ctx.reportGenerated ? 'General_HelpReport' : 'General_Help')
- }, _hoisted_9, 10, _hoisted_7)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_10, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_RateFeature, {
- 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", {
- key: 0,
- 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);
-}
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue?vue&type=template&id=40f81493
-// 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
- // 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 () {
- var _window = window,
- Feedback = _window.Feedback; // eslint-disable-line
-
- if (Feedback) {
- resolve(Feedback.RateFeature);
- } else {
- // feedback plugin not loaded
- resolve(null);
- }
- });
- });
-});
/**
- * Usage:
- *
- * All Websites Dashboard
- * -> uses "All Websites Dashboard" as featurename
- *
- * All Websites Dashboard (Total:
- * 309 Visits)
- * -> custom featurename
- *
- * All Websites Dashboard
- * -> shows help icon and links to external url
- *
- * All Websites
- * Dashboard
- * -> makes the headline clickable linking to the specified url
- *
- * Pages report
- * -> inlineHelp specified via a attribute shows help icon on headline hover
+ * Loads any custom widget or URL based on the given parameters.
*
- * All Websites Dashboard
- * My inline help
- *
- * -> alternative definition for inline help
- * -> shows help icon to display inline help on click. Note: You can combine inlinehelp and help-url
+ * 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.
*
- * * Pages report
- * -> reportGenerated specified via this attribute shows a clock icon with a tooltip which
- * activated by hover
- * -> the tooltip shows the value of the attribute
+ * Example:
+ *
*/
-/* harmony default export */ var EnrichedHeadlinevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+/* harmony default export */ var WidgetLoadervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
props: {
- helpUrl: {
- type: String,
- default: ''
- },
- editUrl: {
- type: String,
- default: ''
- },
- reportGenerated: String,
- featureName: String,
- inlineHelp: String
+ widgetParams: Object,
+ widgetName: String
},
components: {
- RateFeature: RateFeature
+ ActivityIndicator: ActivityIndicator
},
data: function data() {
return {
- showIcons: false,
- showInlineHelp: false,
- actualFeatureName: this.featureName,
- actualInlineHelp: this.inlineHelp
+ loading: false,
+ loadingFailed: false,
+ changeCounter: 0,
+ currentScope: null,
+ lastWidgetAbortController: null
};
},
watch: {
- inlineHelp: function inlineHelp(newValue) {
- this.actualInlineHelp = newValue;
+ 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);
},
- featureName: function featureName(newValue) {
- this.actualFeatureName = newValue;
+ 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() {
- var _this = this;
+ 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);
- var root = this.$refs.root; // timeout used since angularjs does not fill out the transclude at this point
+ if (this.currentScope) {
+ this.currentScope.$destroy();
+ }
- setTimeout(function () {
- if (!_this.actualInlineHelp) {
- var helpNode = root.querySelector('.title .inlineHelp');
+ 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 (!helpNode && root.parentElement.nextElementSibling) {
- // hack for reports :(
- helpNode = root.parentElement.nextElementSibling.querySelector('.reportDocumentation');
+ if (!(key in fullParameters)) {
+ fullParameters[key] = urlParams[key];
}
+ });
- if (helpNode) {
- // 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();
+ if (Comparisons_store_instance.isComparisonEnabled()) {
+ fullParameters = Object.assign(Object.assign({}, fullParameters), {}, {
+ comparePeriods: urlParams.comparePeriods,
+ compareDates: urlParams.compareDates,
+ compareSegments: urlParams.compareSegments
+ });
+ }
- if (helpDocs.length) {
- _this.actualInlineHelp = "".concat(helpDocs, "
");
- setTimeout(function () {
- return helpNode.remove();
- }, 0);
- }
+ 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;
}
- if (!_this.actualFeatureName) {
- _this.actualFeatureName = root.querySelector('.title').textContent;
+ 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;
}
- 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
- });
- }
- });
+ 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/EnrichedHeadline/EnrichedHeadline.vue?vue&type=script&lang=ts
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue?vue&type=script&lang=ts
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.vue
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue
-EnrichedHeadlinevue_type_script_lang_ts.render = EnrichedHeadlinevue_type_template_id_40f81493_render
+WidgetContainervue_type_script_lang_ts.render = WidgetContainervue_type_template_id_41745e0f_render
-/* harmony default export */ var EnrichedHeadline = (EnrichedHeadlinevue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/EnrichedHeadline/EnrichedHeadline.adapter.ts
+/* 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
*
@@ -2950,155 +10042,142 @@ EnrichedHeadlinevue_type_script_lang_ts.render = EnrichedHeadlinevue_type_templa
*/
-/* harmony default export */ var EnrichedHeadline_adapter = (createAngularJsAdapter({
- component: EnrichedHeadline,
+/* harmony default export */ var WidgetContainer_adapter = (createAngularJsAdapter({
+ component: WidgetContainer,
scope: {
- helpUrl: {
- angularJsBind: '@'
- },
- editUrl: {
- angularJsBind: '@'
- },
- reportGenerated: {
- angularJsBind: '@?'
- },
- featureName: {
- angularJsBind: '@'
- },
- inlineHelp: {
- angularJsBind: '@?'
+ container: {
+ angularJsBind: '=piwikWidgetContainer'
}
},
- directiveName: 'piwikEnrichedHeadline',
- transclude: true
+ 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/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/WidgetByDimensionContainer/WidgetByDimensionContainer.vue?vue&type=template&id=3681f928
-var ContentBlockvue_type_template_id_09ef9e02_hoisted_1 = {
- class: "card",
- ref: "root"
+var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_1 = {
+ class: "reportsByDimensionView"
};
-var ContentBlockvue_type_template_id_09ef9e02_hoisted_2 = {
- class: "card-content"
+var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_2 = {
+ class: "entityList"
};
-var ContentBlockvue_type_template_id_09ef9e02_hoisted_3 = {
- key: 0,
- class: "card-title"
+var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_3 = {
+ class: "listCircle"
};
-var ContentBlockvue_type_template_id_09ef9e02_hoisted_4 = {
- key: 1,
- class: "card-title"
+var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_4 = ["onClick"];
+var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_5 = {
+ class: "dimension"
};
-var ContentBlockvue_type_template_id_09ef9e02_hoisted_5 = {
- ref: "content"
+var WidgetByDimensionContainervue_type_template_id_3681f928_hoisted_6 = {
+ class: "reportContainer"
};
-function ContentBlockvue_type_template_id_09ef9e02_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, {
- "feature-name": _ctx.actualFeature,
- "help-url": _ctx.helpUrl,
- "inline-help": _ctx.actualHelpText
- }, {
- default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
- 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);
+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/ContentBlock/ContentBlock.vue?vue&type=template&id=09ef9e02
+// 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/@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/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."); }
-var adminContent = null;
-/* harmony default export */ var ContentBlockvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+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: {
- contentTitle: String,
- feature: String,
- helpUrl: String,
- helpText: String,
- anchor: String
+ widgets: Array
},
components: {
- EnrichedHeadline: EnrichedHeadline
+ WidgetLoader: WidgetLoader
},
data: function data() {
return {
- actualFeature: this.feature,
- actualHelpText: this.helpText
+ selectedWidget: null
};
},
- watch: {
- feature: function feature(newValue) {
- this.actualFeature = newValue;
- },
- helpText: function helpText(newValue) {
- this.actualHelpText = newValue;
- }
- },
- mounted: function mounted() {
- var _this = this;
-
- var _this$$refs = this.$refs,
- root = _this$$refs.root,
- content = _this$$refs.content;
-
- if (this.anchor) {
- var anchorElement = document.createElement('a');
- anchorElement.id = this.anchor;
- root.parentElement.prepend(anchorElement);
- }
+ created: function created() {
+ var _this$widgetsSorted = WidgetByDimensionContainervue_type_script_lang_ts_slicedToArray(this.widgetsSorted, 1);
- setTimeout(function () {
- var inlineHelp = content.querySelector('.contentHelp');
-
- if (inlineHelp) {
- _this.actualHelpText = inlineHelp.innerHTML;
- inlineHelp.remove();
- }
- }, 0);
+ 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;
- if (this.actualFeature && (this.actualFeature === true || this.actualFeature === 'true')) {
- this.actualFeature = this.contentTitle;
- }
+ var category = (_widget$subcategory = widget.subcategory) === null || _widget$subcategory === void 0 ? void 0 : _widget$subcategory.name;
- if (adminContent === null) {
- // cache admin node for further content blocks
- adminContent = document.querySelector('#content.admin');
- }
+ if (!category) {
+ return;
+ }
- var contentTopPosition;
+ if (!byCategory[category]) {
+ byCategory[category] = {
+ name: category,
+ order: widget.order,
+ widgets: []
+ };
+ }
- if (adminContent) {
- contentTopPosition = adminContent.offsetTop;
+ byCategory[category].widgets.push(widget);
+ });
+ return sortOrderables(Object.values(byCategory));
}
-
- if (contentTopPosition || contentTopPosition === 0) {
- var parents = root.closest('[piwik-widget-loader]'); // 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
- // the widgets on the admin home page
-
- var topThis = parents ? parents.offsetTop : root.offsetTop;
-
- 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;
- }
+ },
+ 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/ContentBlock/ContentBlock.vue?vue&type=script&lang=ts
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue?vue&type=script&lang=ts
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue
-ContentBlockvue_type_script_lang_ts.render = ContentBlockvue_type_template_id_09ef9e02_render
+WidgetByDimensionContainervue_type_script_lang_ts.render = WidgetByDimensionContainervue_type_template_id_3681f928_render
-/* harmony default export */ var ContentBlock = (ContentBlockvue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ContentBlock/ContentBlock.adapter.ts
+/* 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
*
@@ -3107,106 +10186,223 @@ ContentBlockvue_type_script_lang_ts.render = ContentBlockvue_type_template_id_09
*/
-/* harmony default export */ var ContentBlock_adapter = (createAngularJsAdapter({
- component: ContentBlock,
+/* harmony default export */ var WidgetByDimensionContainer_adapter = (createAngularJsAdapter({
+ component: WidgetByDimensionContainer,
scope: {
- contentTitle: {
- angularJsBind: '@'
- },
- feature: {
- angularJsBind: '@'
- },
- helpUrl: {
- angularJsBind: '@'
- },
- helpText: {
- angularJsBind: '@'
- },
- anchor: {
- angularJsBind: '@?'
+ widgets: {
+ angularJsBind: '=piwikWidgetByDimensionContainer',
+ transform: function transform(v) {
+ return v.widgets;
+ }
}
},
- directiveName: 'piwikContentBlock',
- transclude: true
+ directiveName: 'piwikWidgetByDimensionContainer'
}));
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Segmentation/Segments.store.ts
-function Segments_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+// 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
-function Segments_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); } }
+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");
-function Segments_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) Segments_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) Segments_store_defineProperties(Constructor, staticProps); return Constructor; }
+ var _component_WidgetContainer = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("WidgetContainer");
-function Segments_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; }
+ var _component_WidgetByDimensionContainer = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("WidgetByDimensionContainer");
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
+ 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
-var Segments_store_SegmentsStore = /*#__PURE__*/function () {
- function SegmentsStore() {
- var _this = this;
- Segments_store_classCallCheck(this, SegmentsStore);
- Segments_store_defineProperty(this, "segmentState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({
- availableSegments: []
- }));
- Matomo_Matomo.on('piwikSegmentationInited', function () {
- return _this.setSegmentState();
+
+
+
+
+
+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:
+ *
+ * // in this case we will find the correct widget automatically
+ *
+ * // disables rating feature, no initial headline
+ *
+ */
- Segments_store_createClass(SegmentsStore, [{
- key: "state",
- get: function get() {
- return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(this.segmentState);
- }
- }, {
- key: "setSegmentState",
- value: function setSegmentState() {
- try {
- var uiControlObject = $('.segmentEditorPanel').data('uiControlObject');
- this.segmentState.availableSegments = uiControlObject.impl.availableSegments || [];
- } catch (e) {// segment editor is not initialized yet
+
+/* 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, ' '));
}
- }]);
- return SegmentsStore;
-}();
+ return {
+ tooltipContent: tooltipContent
+ };
+ },
+ created: function created() {
+ var _this = this;
-/* harmony default export */ var Segments_store = (new Segments_store_SegmentsStore());
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts
-function Comparisons_store_toConsumableArray(arr) { return Comparisons_store_arrayWithoutHoles(arr) || Comparisons_store_iterableToArray(arr) || Comparisons_store_unsupportedIterableToArray(arr) || Comparisons_store_nonIterableSpread(); }
+ var actualWidget = this.actualWidget;
-function Comparisons_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."); }
+ 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;
-function Comparisons_store_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return Comparisons_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 Comparisons_store_arrayLikeToArray(o, minLen); }
+ var widget = this.widget;
-function Comparisons_store_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
+ if (widget) {
+ var result = Object.assign({}, widget);
-function Comparisons_store_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return Comparisons_store_arrayLikeToArray(arr); }
+ if (widget && widget.isReport && !widget.documentation) {
+ var report = ReportMetadata_store.findReport(widget.module, widget.action);
-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; }
+ if (report && report.documentation) {
+ result.documentation = report.documentation;
+ }
+ }
+
+ return widget;
+ }
-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; }
+ if (this.containerid) {
+ var containerWidget = findContainer(this.allWidgets, this.containerid);
-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; }
+ if (containerWidget) {
+ var _result = Object.assign({}, containerWidget);
-function Comparisons_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+ 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
-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); } }
-function Comparisons_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) Comparisons_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) Comparisons_store_defineProperties(Constructor, staticProps); return Constructor; }
-function Comparisons_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; }
+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
*
@@ -3215,629 +10411,479 @@ function Comparisons_store_defineProperty(obj, key, value) { if (key in obj) { O
*/
+/* 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");
-
-
-var SERIES_COLOR_COUNT = 8;
-var SERIES_SHADE_COUNT = 3;
-
-function wrapArray(values) {
- if (!values) {
- return [];
- }
-
- return values instanceof Array ? values : [values];
+ 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
-var Comparisons_store_ComparisonsStore = /*#__PURE__*/function () {
- // for tests
- function ComparisonsStore() {
- var _this = this;
+// 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"); } }
- Comparisons_store_classCallCheck(this, ComparisonsStore);
+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); } }
- Comparisons_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({
- comparisonsDisabledFor: []
- }));
+function ReportingPage_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) ReportingPage_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) ReportingPage_store_defineProperties(Constructor, staticProps); return Constructor; }
- Comparisons_store_defineProperty(this, "state", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["readonly"])(this.privateState));
+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; }
- Comparisons_store_defineProperty(this, "colors", {});
+function ReportingPage_store_toConsumableArray(arr) { return ReportingPage_store_arrayWithoutHoles(arr) || ReportingPage_store_iterableToArray(arr) || ReportingPage_store_unsupportedIterableToArray(arr) || ReportingPage_store_nonIterableSpread(); }
- Comparisons_store_defineProperty(this, "segmentComparisons", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
- return _this.parseSegmentComparisons();
- }));
+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."); }
- Comparisons_store_defineProperty(this, "periodComparisons", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
- return _this.parsePeriodComparisons();
- }));
+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); }
- Comparisons_store_defineProperty(this, "isEnabled", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
- return _this.checkEnabledForCurrentPage();
- }));
+function ReportingPage_store_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
- this.loadComparisonsDisabledFor();
- $(function () {
- _this.colors = _this.getAllSeriesColors();
- });
- Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () {
- return _this.getComparisons();
- }, function () {
- return Matomo_Matomo.postEvent('piwikComparisonsChanged');
- }, {
- deep: true
- });
- }
+function ReportingPage_store_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return ReportingPage_store_arrayLikeToArray(arr); }
- Comparisons_store_createClass(ComparisonsStore, [{
- key: "getComparisons",
- value: function getComparisons() {
- return this.getSegmentComparisons().concat(this.getPeriodComparisons());
- }
- }, {
- key: "isComparing",
- value: function isComparing() {
- return this.isComparisonEnabled() // first two in each array are for the currently selected segment/period
- && (this.segmentComparisons.value.length > 1 || this.periodComparisons.value.length > 1);
- }
- }, {
- key: "isComparingPeriods",
- value: function isComparingPeriods() {
- return this.getPeriodComparisons().length > 1; // first is currently selected period
- }
- }, {
- key: "getSegmentComparisons",
- value: function getSegmentComparisons() {
- if (!this.isComparisonEnabled()) {
- return [];
- }
+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; }
- return this.segmentComparisons.value;
- }
- }, {
- key: "getPeriodComparisons",
- value: function getPeriodComparisons() {
- if (!this.isComparisonEnabled()) {
- return [];
- }
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
- return this.periodComparisons.value;
- }
- }, {
- key: "getSeriesColor",
- value: function getSeriesColor(segmentComparison, periodComparison) {
- var metricIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
- var seriesIndex = this.getComparisonSeriesIndex(periodComparison.index, segmentComparison.index) % SERIES_COLOR_COUNT;
- if (metricIndex === 0) {
- return this.colors["series".concat(seriesIndex)];
- }
- var shadeIndex = metricIndex % SERIES_SHADE_COUNT;
- return this.colors["series".concat(seriesIndex, "-shade").concat(shadeIndex)];
- }
- }, {
- key: "getSeriesColorName",
- value: function getSeriesColorName(seriesIndex, metricIndex) {
- var colorName = "series".concat(seriesIndex % SERIES_COLOR_COUNT);
- if (metricIndex > 0) {
- colorName += "-shade".concat(metricIndex % SERIES_SHADE_COUNT);
- }
- return colorName;
- }
- }, {
- key: "isComparisonEnabled",
- value: function isComparisonEnabled() {
- return this.isEnabled.value;
- }
- }, {
- key: "getIndividualComparisonRowIndices",
- value: function getIndividualComparisonRowIndices(seriesIndex) {
- var segmentCount = this.getSegmentComparisons().length;
- var segmentIndex = seriesIndex % segmentCount;
- var periodIndex = Math.floor(seriesIndex / segmentCount);
- return {
- segmentIndex: segmentIndex,
- periodIndex: periodIndex
- };
- }
- }, {
- key: "getComparisonSeriesIndex",
- value: function getComparisonSeriesIndex(periodIndex, segmentIndex) {
- var segmentCount = this.getSegmentComparisons().length;
- return periodIndex * segmentCount + segmentIndex;
- }
- }, {
- key: "getAllComparisonSeries",
- value: function getAllComparisonSeries() {
- var _this2 = this;
- var seriesInfo = [];
- var seriesIndex = 0;
- this.getPeriodComparisons().forEach(function (periodComp) {
- _this2.getSegmentComparisons().forEach(function (segmentComp) {
- seriesInfo.push({
- index: seriesIndex,
- params: Comparisons_store_objectSpread(Comparisons_store_objectSpread({}, segmentComp.params), periodComp.params),
- color: _this2.colors["series".concat(seriesIndex)]
- });
- seriesIndex += 1;
- });
- });
- return seriesInfo;
- }
- }, {
- key: "removeSegmentComparison",
- value: function removeSegmentComparison(index) {
- if (!this.isComparisonEnabled()) {
- throw new Error('Comparison disabled.');
- }
+function shouldBeRenderedWithFullWidth(widget) {
+ // rather controller logic
+ if (widget.isContainer && widget.layout && widget.layout === 'ByDimension' || widget.viewDataTable === 'bydimension') {
+ return true;
+ }
- var newComparisons = Comparisons_store_toConsumableArray(this.segmentComparisons.value);
+ if (widget.isWide) {
+ return true;
+ }
- newComparisons.splice(index, 1);
- var extraParams = {};
+ return widget.viewDataTable && (widget.viewDataTable === 'tableAllColumns' || widget.viewDataTable === 'sparklines' || widget.viewDataTable === 'graphEvolution');
+}
- if (index === 0) {
- extraParams.segment = newComparisons[0].params.segment;
- }
+function markWidgetsInFirstRowOfPage(widgets) {
+ if (widgets && widgets[0]) {
+ var newWidgets = ReportingPage_store_toConsumableArray(widgets);
- this.updateQueryParamsFromComparisons(newComparisons, this.periodComparisons.value, extraParams);
- }
- }, {
- key: "addSegmentComparison",
- value: function addSegmentComparison(params) {
- if (!this.isComparisonEnabled()) {
- throw new Error('Comparison disabled.');
- }
+ var groupedWidgets = widgets[0];
- var newComparisons = this.segmentComparisons.value.concat([{
- params: params,
- index: -1,
- title: ''
- }]);
- this.updateQueryParamsFromComparisons(newComparisons, this.periodComparisons.value);
- }
- }, {
- key: "updateQueryParamsFromComparisons",
- value: function updateQueryParamsFromComparisons(segmentComparisons, periodComparisons) {
- var extraParams = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
- // get unique segments/periods/dates from new Comparisons
- var compareSegments = {};
- var comparePeriodDatePairs = {};
- var firstSegment = false;
- var firstPeriod = false;
- segmentComparisons.forEach(function (comparison) {
- if (firstSegment) {
- compareSegments[comparison.params.segment] = true;
- } else {
- firstSegment = true;
- }
- });
- periodComparisons.forEach(function (comparison) {
- if (firstPeriod) {
- comparePeriodDatePairs["".concat(comparison.params.period, "|").concat(comparison.params.date)] = true;
- } else {
- firstPeriod = true;
- }
+ if (groupedWidgets.group) {
+ newWidgets[0] = Object.assign(Object.assign({}, newWidgets[0]), {}, {
+ left: markWidgetsInFirstRowOfPage(groupedWidgets.left || []),
+ right: markWidgetsInFirstRowOfPage(groupedWidgets.right || [])
});
- var comparePeriods = [];
- var compareDates = [];
- Object.keys(comparePeriodDatePairs).forEach(function (pair) {
- var parts = pair.split('|');
- comparePeriods.push(parts[0]);
- compareDates.push(parts[1]);
+ } else {
+ newWidgets[0] = Object.assign(Object.assign({}, newWidgets[0]), {}, {
+ isFirstInPage: true
});
- var compareParams = {
- compareSegments: Object.keys(compareSegments),
- comparePeriods: comparePeriods,
- 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[]'];
+ return newWidgets;
+ }
- if (JSON.stringify(newSearch) !== JSON.stringify(search)) {
- src_MatomoUrl_MatomoUrl.updateHash(newSearch);
- }
+ return widgets;
+}
- return;
- }
+var ReportingPage_store_ReportingPageStore = /*#__PURE__*/function () {
+ function ReportingPageStore() {
+ var _this = this;
- 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
+ ReportingPage_store_classCallCheck(this, ReportingPageStore);
- var url = src_MatomoUrl_MatomoUrl.stringify(extraParams);
- var strHash = src_MatomoUrl_MatomoUrl.stringify(compareParams);
- window.broadcast.propagateNewPage(url, undefined, strHash, paramsToRemove);
- }
- }, {
- key: "getAllSeriesColors",
- value: function getAllSeriesColors() {
- var ColorManager = Matomo_Matomo.ColorManager;
+ ReportingPage_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({}));
- if (!ColorManager) {
- return [];
- }
+ 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);
+ }));
- var seriesColorNames = [];
+ ReportingPage_store_defineProperty(this, "page", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
+ return _this.state.value.page;
+ }));
- for (var i = 0; i < SERIES_COLOR_COUNT; i += 1) {
- seriesColorNames.push("series".concat(i));
+ ReportingPage_store_defineProperty(this, "widgets", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
+ var page = _this.page.value;
- for (var j = 0; j < SERIES_SHADE_COUNT; j += 1) {
- seriesColorNames.push("series".concat(i, "-shade").concat(j));
- }
+ if (!page) {
+ return [];
}
- return ColorManager.getColors('comparison-series-color', seriesColorNames);
- }
- }, {
- key: "loadComparisonsDisabledFor",
- value: function loadComparisonsDisabledFor() {
- var _this3 = this;
-
- var matomoModule = src_MatomoUrl_MatomoUrl.parsed.value.module;
+ var widgets = [];
+ var reportsToIgnore = {};
- if (matomoModule === 'CoreUpdater' || matomoModule === 'Installation') {
- this.privateState.comparisonsDisabledFor = [];
- return;
- }
+ var isIgnoredReport = function isIgnoredReport(widget) {
+ return widget.isReport && reportsToIgnore["".concat(widget.module, ".").concat(widget.action)];
+ };
- AjaxHelper_AjaxHelper.fetch({
- module: 'API',
- method: 'API.getPagesComparisonsDisabledFor'
- }).then(function (result) {
- _this3.privateState.comparisonsDisabledFor = result;
- });
- }
- }, {
- key: "parseSegmentComparisons",
- value: function parseSegmentComparisons() {
- var availableSegments = Segments_store.state.availableSegments;
+ var getRelatedReports = function getRelatedReports(widget) {
+ if (!widget.isReport) {
+ return [];
+ }
- var compareSegments = Comparisons_store_toConsumableArray(wrapArray(src_MatomoUrl_MatomoUrl.parsed.value.compareSegments)); // add base comparisons
+ var report = ReportMetadata_store.findReport(widget.module, widget.action);
+ if (!report || !report.relatedReports) {
+ return [];
+ }
- compareSegments.unshift(src_MatomoUrl_MatomoUrl.parsed.value.segment || '');
- var newSegmentComparisons = [];
- compareSegments.forEach(function (segment, idx) {
- var storedSegment;
- availableSegments.forEach(function (s) {
- if (s.definition === segment || s.definition === decodeURIComponent(segment) || decodeURIComponent(s.definition) === segment) {
- storedSegment = s;
- }
- });
- var segmentTitle = storedSegment ? storedSegment.name : translate('General_Unknown');
+ return report.relatedReports;
+ };
- if (segment.trim() === '') {
- segmentTitle = translate('SegmentEditor_DefaultAllVisits');
+ (page.widgets || []).forEach(function (widget) {
+ if (isIgnoredReport(widget)) {
+ return;
}
- newSegmentComparisons.push({
- params: {
- segment: segment
- },
- title: Matomo_Matomo.helper.htmlDecode(segmentTitle),
- index: idx
+ getRelatedReports(widget).forEach(function (report) {
+ reportsToIgnore["".concat(report.module, ".").concat(report.action)] = true;
});
+ widgets.push(widget);
});
- return newSegmentComparisons;
- }
- }, {
- key: "parsePeriodComparisons",
- value: function parsePeriodComparisons() {
- var comparePeriods = Comparisons_store_toConsumableArray(wrapArray(src_MatomoUrl_MatomoUrl.parsed.value.comparePeriods));
+ widgets = sortOrderables(widgets);
- var compareDates = Comparisons_store_toConsumableArray(wrapArray(src_MatomoUrl_MatomoUrl.parsed.value.compareDates));
+ if (widgets.length === 1) {
+ // if there is only one widget, we always display it full width
+ return markWidgetsInFirstRowOfPage(widgets);
+ }
- comparePeriods.unshift(src_MatomoUrl_MatomoUrl.parsed.value.period);
- compareDates.unshift(src_MatomoUrl_MatomoUrl.parsed.value.date);
- var newPeriodComparisons = [];
+ var groupedWidgets = [];
- for (var i = 0; i < Math.min(compareDates.length, comparePeriods.length); i += 1) {
- var title = void 0;
+ for (var i = 0; i < widgets.length; i += 1) {
+ var widget = widgets[i];
- try {
- title = Periods_Periods.parse(comparePeriods[i], compareDates[i]).getPrettyString();
- } catch (e) {
- title = translate('General_Error');
- }
+ 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]);
+ }
+ }
- newPeriodComparisons.push({
- params: {
- date: compareDates[i],
- period: comparePeriods[i]
- },
- title: title,
- index: i
- });
+ groupedWidgets.push({
+ group: true,
+ left: left,
+ right: right
+ });
+ }
}
- return newPeriodComparisons;
+ 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: "checkEnabledForCurrentPage",
- value: function checkEnabledForCurrentPage() {
- // category/subcategory is not included on top bar pages, so in that case we use module/action
- var category = src_MatomoUrl_MatomoUrl.parsed.value.category || src_MatomoUrl_MatomoUrl.parsed.value.module;
- var subcategory = src_MatomoUrl_MatomoUrl.parsed.value.subcategory || src_MatomoUrl_MatomoUrl.parsed.value.action;
- var id = "".concat(category, ".").concat(subcategory);
- var isEnabled = this.privateState.comparisonsDisabledFor.indexOf(id) === -1 && this.privateState.comparisonsDisabledFor.indexOf("".concat(category, ".*")) === -1;
- document.documentElement.classList.toggle('comparisonsDisabled', !isEnabled);
- return isEnabled;
+ key: "resetPage",
+ value: function resetPage() {
+ this.privateState.page = undefined;
}
}]);
- return ComparisonsStore;
+ 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
-// 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
-var Comparisonsvue_type_template_id_1b8ecdd2_hoisted_1 = {
- key: 0,
- ref: "root",
- class: "matomo-comparisons"
-};
-var Comparisonsvue_type_template_id_1b8ecdd2_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 = {
- 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 = {
- 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) {
- 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", {
- class: "title",
- title: comparison.title + ' ' + 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) {
- 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,
- title: _ctx.getComparisonTooltip(comparison, periodComparison)
- }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
- class: "comparison-dot",
- 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);
- }), 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",
- onClick: function onClick($event) {
- return _ctx.removeSegmentComparison($index);
- }
- }, [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", {
- 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);
-}
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue?vue&type=template&id=1b8ecdd2
-// 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; }
-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 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 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', ""), ' '),
+ type: 'transient'
+ });
+}
+function hideOnlyRawDataNoticifation() {
+ Notifications_store.remove('onlyRawData');
+}
-/* harmony default export */ var Comparisonsvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
- props: {},
+/* 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 {
- comparisonTooltips: null
+ loading: false,
+ hasRawData: false,
+ hasNoVisits: false,
+ dateLastChecked: null,
+ hasNoPage: false
};
},
- setup: function setup() {
- // accessing has to be done through a computed property so we can use the computed
- // instance directly in the template. unfortunately, vue won't register to changes.
- var isComparing = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
- return Comparisons_store_instance.isComparing();
- });
- var segmentComparisons = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
- return Comparisons_store_instance.getSegmentComparisons();
+ 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);
});
- var periodComparisons = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["computed"])(function () {
- return Comparisons_store_instance.getPeriodComparisons();
+ Matomo_Matomo.on('loadPage', function (category, subcategory) {
+ _this.renderPage(category, subcategory);
});
- var getSeriesColor = Comparisons_store_instance.getSeriesColor.bind(Comparisons_store_instance);
- return {
- isComparing: isComparing,
- segmentComparisons: segmentComparisons,
- periodComparisons: periodComparisons,
- getSeriesColor: getSeriesColor
- };
+ },
+ computed: {
+ widgets: function widgets() {
+ return ReportingPage_store.widgets.value;
+ }
},
methods: {
- comparisonHasSegment: function comparisonHasSegment(comparison) {
- return typeof comparison.params.segment !== 'undefined';
- },
- removeSegmentComparison: function removeSegmentComparison(index) {
- // otherwise the tooltip will be stuck on the screen
- window.$(this.$refs.root).tooltip('destroy');
- Comparisons_store_instance.removeSegmentComparison(index);
- },
- getComparisonPeriodType: function getComparisonPeriodType(comparison) {
- var period = comparison.params.period;
+ renderPage: function renderPage(category, subcategory) {
+ var _this2 = this;
- if (period === 'range') {
- return translate('CoreHome_PeriodRange');
+ if (!category || !subcategory) {
+ ReportingPage_store.resetPage();
+ this.loading = false;
+ return;
}
- var periodStr = translate("Intl_Period".concat(period.substring(0, 1).toUpperCase()).concat(period.substring(1)));
- return periodStr.substring(0, 1).toUpperCase() + periodStr.substring(1);
- },
- getComparisonTooltip: function getComparisonTooltip(segmentComparison, periodComparison) {
- if (!this.comparisonTooltips || !Object.keys(this.comparisonTooltips).length) {
- return undefined;
+ 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;
}
- return (this.comparisonTooltips[periodComparison.index] || {})[segmentComparison.index];
- },
- getUrlToSegment: function getUrlToSegment(segment) {
- var hash = Comparisonsvue_type_script_lang_ts_objectSpread({}, src_MatomoUrl_MatomoUrl.hashParsed.value);
+ Notifications_store.remove('invalidDate');
+ Matomo_Matomo.postEvent('piwikPageChange', {});
+ Notifications_store.clearTransientNotifications();
- 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, ' '));
- },
- show: {
- delay: 200,
- duration: 200
- },
- hide: false
- });
- },
- onComparisonsChanged: function onComparisonsChanged() {
- var _this = this;
+ if (Periods_Periods.parse(currentPeriod, currentDate).containsToday()) {
+ this.showOnlyRawDataMessageIfRequired();
+ }
- this.comparisonTooltips = null;
+ var params = {
+ category: category,
+ subcategory: subcategory
+ };
+ Matomo_Matomo.postEvent('ReportingPage.loadPage', params);
- if (!Comparisons_store_instance.isComparing()) {
+ if (params.promise) {
+ this.loading = true;
+ Promise.resolve(params.promise).finally(function () {
+ _this2.loading = false;
+ });
return;
}
- var periodComparisons = Comparisons_store_instance.getPeriodComparisons();
- var segmentComparisons = Comparisons_store_instance.getSegmentComparisons();
- AjaxHelper_AjaxHelper.fetch({
- method: 'API.getProcessedReport',
- apiModule: 'VisitsSummary',
- apiAction: 'get',
- compare: '1',
- compareSegments: src_MatomoUrl_MatomoUrl.getSearchParam('compareSegments'),
- comparePeriods: src_MatomoUrl_MatomoUrl.getSearchParam('comparePeriods'),
- compareDates: src_MatomoUrl_MatomoUrl.getSearchParam('compareDates'),
- format_metrics: '1'
- }).then(function (report) {
- _this.comparisonTooltips = {};
- periodComparisons.forEach(function (periodComp) {
- _this.comparisonTooltips[periodComp.index] = {};
- segmentComparisons.forEach(function (segmentComp) {
- var tooltip = _this.generateComparisonTooltip(report, periodComp, segmentComp);
+ ReportingPage_store.fetchPage(category, subcategory).then(function () {
+ var hasNoPage = !ReportingPage_store.page.value;
- _this.comparisonTooltips[periodComp.index][segmentComp.index] = tooltip;
- });
- });
+ 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;
});
},
- generateComparisonTooltip: function generateComparisonTooltip(visitsSummary, periodComp, segmentComp) {
- if (!visitsSummary.reportData.comparisons) {
- // sanity check
- return '';
+ 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 firstRowIndex = Comparisons_store_instance.getComparisonSeriesIndex(periodComp.index, 0);
- var firstRow = visitsSummary.reportData.comparisons[firstRowIndex];
- var comparisonRowIndex = Comparisons_store_instance.getComparisonSeriesIndex(periodComp.index, segmentComp.index);
- var comparisonRow = visitsSummary.reportData.comparisons[comparisonRowIndex];
- var firstPeriodRow = visitsSummary.reportData.comparisons[segmentComp.index];
- var tooltip = '';
- var visitsPercent = (comparisonRow.nb_visits / firstRow.nb_visits * 100).toFixed(2);
- visitsPercent = "".concat(visitsPercent, "%");
- tooltip += translate('General_ComparisonCardTooltip1', ["'".concat(comparisonRow.compareSegmentPretty, "'"), comparisonRow.comparePeriodPretty, visitsPercent, comparisonRow.nb_visits.toString(), firstRow.nb_visits.toString()]);
+ 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 (periodComp.index > 0) {
- tooltip += ' ';
- tooltip += translate('General_ComparisonCardTooltip2', [comparisonRow.nb_visits_change.toString(), firstPeriodRow.compareSegmentPretty, firstPeriodRow.comparePeriodPretty]);
+ if (subcategoryExceptions.indexOf(subcategory) !== -1 || categoryExceptions.indexOf(category) !== -1 || subcategory.toLowerCase().indexOf('manage') !== -1) {
+ hideOnlyRawDataNoticifation();
+ return;
}
- tooltip += '
';
- return tooltip;
- }
- },
- updated: function updated() {
- var _this2 = this;
+ var minuteInMilliseconds = 60000;
- setTimeout(function () {
- return _this2.setUpTooltips();
- });
- },
- mounted: function mounted() {
- var _this3 = this;
+ if (this.dateLastChecked && new Date().valueOf() - this.dateLastChecked.valueOf() < minuteInMilliseconds) {
+ return;
+ }
- Matomo_Matomo.on('piwikComparisonsChanged', function () {
- _this3.onComparisonsChanged();
- });
- this.onComparisonsChanged();
- setTimeout(function () {
- return _this3.setUpTooltips();
- });
- },
- beforeUnmount: function beforeUnmount() {
- try {
- window.$(this.refs.root).tooltip('destroy');
- } catch (e) {// ignore
+ 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/Comparisons/Comparisons.vue?vue&type=script&lang=ts
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue?vue&type=script&lang=ts
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.vue
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue
-Comparisonsvue_type_script_lang_ts.render = Comparisonsvue_type_template_id_1b8ecdd2_render
+ReportingPagevue_type_script_lang_ts.render = ReportingPagevue_type_template_id_28b6d8b8_render
-/* harmony default export */ var Comparisons = (Comparisonsvue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts
+/* 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
*
@@ -3846,535 +10892,696 @@ Comparisonsvue_type_script_lang_ts.render = Comparisonsvue_type_template_id_1b8e
*/
-
-
-function ComparisonFactory() {
- return Comparisons_store_instance;
-}
-
-ComparisonFactory.$inject = [];
-angular.module('piwikApp.service').factory('piwikComparisonsService', ComparisonFactory);
-/* harmony default export */ var Comparisons_adapter = (createAngularJsAdapter({
- component: Comparisons,
- directiveName: 'piwikComparisons',
- restrict: 'E'
+/* 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/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/ReportExport/ReportExportPopover.vue?vue&type=template&id=3d203950
-var Menudropdownvue_type_template_id_0349d645_hoisted_1 = {
- ref: "root",
- class: "menuDropdown"
+var ReportExportPopovervue_type_template_id_3d203950_hoisted_1 = {
+ class: "report-export-popover row",
+ id: "reportExport"
};
-var Menudropdownvue_type_template_id_0349d645_hoisted_2 = ["title"];
-var Menudropdownvue_type_template_id_0349d645_hoisted_3 = ["innerHTML"];
-
-var Menudropdownvue_type_template_id_0349d645_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 = {
- class: "items"
+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 Menudropdownvue_type_template_id_0349d645_hoisted_6 = {
+var ReportExportPopovervue_type_template_id_3d203950_hoisted_11 = {
key: 0,
- class: "search"
+ name: "filter_limit"
};
-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 _directive_focus_if = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("focus-if");
+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 _directive_focus_anywhere_but_here = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("focus-anywhere-but-here");
+var ReportExportPopovervue_type_template_id_3d203950_hoisted_15 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])("\n ");
- 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", {
- class: "title",
- onClick: _cache[0] || (_cache[0] = function ($event) {
- return _ctx.showItems = !_ctx.showItems;
+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;
}),
- 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", {
- type: "text",
+ "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.searchTerm = $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;
}),
- onKeydown: _cache[2] || (_cache[2] = function ($event) {
- return _ctx.onSearchTermKeydown($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;
}),
- 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", {
- 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", {
- onClick: _cache[3] || (_cache[3] = function ($event) {
- _ctx.searchTerm = '';
-
- _ctx.searchItems('');
+ "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;
}),
- 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", {
- onClick: _cache[4] || (_cache[4] = function ($event) {
- return _ctx.selectItem($event);
- })
- }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "default")])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showItems]])], 512)), [[_directive_focus_anywhere_but_here, {
- blur: _ctx.lostFocus
- }]]);
+ "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', '', ' ', '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/Menudropdown/Menudropdown.vue?vue&type=template&id=0349d645
+// 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/@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/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); }
-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"])({
- props: {
- menuTitle: String,
- tooltip: String,
- showSearch: Boolean,
- menuTitleChangeOnClick: String
+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: {
- FocusAnywhereButHere: FocusAnywhereButHere,
- FocusIf: FocusIf
+ SelectOnFocus: SelectOnFocus
},
- emits: ['afterSelect'],
- watch: {
- menuTitle: function menuTitle() {
- this.actualMenuTitle = this.menuTitle;
+ 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 {
- showItems: false,
- searchTerm: '',
- actualMenuTitle: this.menuTitle
+ 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
};
},
- methods: {
- lostFocus: function lostFocus() {
- this.showItems = false;
- },
- selectItem: function selectItem(event) {
- var targetClasses = event.target.classList;
-
- if (!targetClasses.contains('item') || targetClasses.contains('disabled') || targetClasses.contains('separator')) {
- return;
+ watch: {
+ reportType: function reportType(newVal) {
+ if (!this.availableReportFormats[newVal][this.reportFormat]) {
+ this.reportFormat = 'XML';
}
-
- if (this.menuTitleChangeOnClick !== false) {
- this.actualMenuTitle = event.target.textContent.replace(/[\u0000-\u2666]/g, function (c) {
- return "".concat(c.charCodeAt(0), ";");
- }); // eslint-disable-line
+ },
+ reportLimit: function reportLimit(newVal, oldVal) {
+ if (this.maxFilterLimit && this.maxFilterLimit > 0 && newVal > this.maxFilterLimit) {
+ this.reportLimit = oldVal;
}
-
- this.showItems = false;
- Menudropdownvue_type_script_lang_ts_$(this.$slots.default()).find('.item').removeClass('active');
- targetClasses.add('active');
- this.$emit('afterSelect');
+ }
+ },
+ computed: {
+ filterLimitTooltip: function filterLimitTooltip() {
+ var rowLimit = translate('CoreHome_RowLimit');
+ var computedMetricMax = this.maxFilterLimit ? translate('General_ComputedMetricMax', this.maxFilterLimit.toString()) : '';
+ return "".concat(rowLimit, " (").concat(computedMetricMax, ")");
},
- onSearchTermKeydown: function onSearchTermKeydown() {
- var _this = this;
-
- setTimeout(function () {
- _this.searchItems(_this.searchTerm);
- });
+ exportLink: function exportLink() {
+ return this.getExportLink(true);
},
- 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);
-
- if ($node.text().toLowerCase().indexOf(searchTerm) === -1) {
- $node.hide();
- } else {
- $node.show();
- }
- });
+ exportLinkWithoutToken: function exportLinkWithoutToken() {
+ return this.getExportLink(false);
}
- }
-}));
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue?vue&type=script&lang=ts
-
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue
-
-
-
-Menudropdownvue_type_script_lang_ts.render = Menudropdownvue_type_template_id_0349d645_render
+ },
+ 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;
+ }
-/* harmony default export */ var Menudropdown = (Menudropdownvue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Menudropdown/Menudropdown.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 requestParams = {};
+ var limit = this.reportLimitAll === 'yes' ? -1 : this.reportLimit;
+ if (this.requestParams && typeof this.requestParams === 'string') {
+ requestParams = JSON.parse(this.requestParams);
+ }
-/* harmony default export */ var Menudropdown_adapter = (createAngularJsAdapter({
- component: Menudropdown,
- scope: {
- menuTitle: {
- angularJsBind: '@'
- },
- tooltip: {
- angularJsBind: '@'
- },
- showSearch: {
- angularJsBind: '='
- },
- menuTitleChangeOnClick: {
- angularJsBind: '='
- }
- },
- directiveName: 'piwikMenudropdown',
- transclude: true,
- events: {
- 'after-select': function afterSelect($event, 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
+ 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';
+ }
-var DatePickervue_type_template_id_c8c462d2_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);
-}
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=template&id=c8c462d2
+ if (typeof dataTable.param.dateUsedInGraph !== 'undefined') {
+ date = dataTable.param.dateUsedInGraph;
+ }
-// 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; }
+ var formatsUseDayNotRange = Matomo_Matomo.config.datatable_export_range_as_day.toLowerCase();
-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; }
+ if (formatsUseDayNotRange.indexOf(reportFormat.toLowerCase()) !== -1 && dataTable.param.period === 'range') {
+ period = 'day';
+ } // Below evolution graph, show daily exports
-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; }
+ 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 DEFAULT_STEP_MONTHS = 1;
-var DatePickervue_type_script_lang_ts_window = window,
- DatePickervue_type_script_lang_ts_$ = DatePickervue_type_script_lang_ts_window.$;
-/* harmony default export */ var DatePickervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["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 setup(props, context) {
- var root = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(null);
+ var _apiMethod$split = apiMethod.split('.');
- function setDateCellColor($dateCell, dateValue) {
- var $dateCellLink = $dateCell.children('a');
+ var _apiMethod$split2 = ReportExportPopovervue_type_script_lang_ts_slicedToArray(_apiMethod$split, 2);
- if (props.selectedDateStart && props.selectedDateEnd && dateValue >= props.selectedDateStart && dateValue <= props.selectedDateEnd) {
- $dateCell.addClass('ui-datepicker-current-period');
+ exportUrlParams.apiModule = _apiMethod$split2[0];
+ exportUrlParams.apiAction = _apiMethod$split2[1];
} else {
- $dateCell.removeClass('ui-datepicker-current-period');
+ exportUrlParams.method = apiMethod;
}
- if (props.highlightedDateStart && props.highlightedDateEnd && dateValue >= props.highlightedDateStart && dateValue <= props.highlightedDateEnd) {
- // other-month cells don't have links, so the must have the ui-state-hover class
- var elementToAddClassTo = $dateCellLink.length ? $dateCellLink : $dateCell;
- elementToAddClassTo.addClass('ui-state-hover');
- } else {
- $dateCell.removeClass('ui-state-hover');
- $dateCellLink.removeClass('ui-state-hover');
+ if (dataTable.param.compareDates && dataTable.param.compareDates.length) {
+ exportUrlParams.compareDates = dataTable.param.compareDates;
+ exportUrlParams.compare = '1';
}
- }
- function getCellDate($dateCell, month, year) {
- if ($dateCell.hasClass('ui-datepicker-other-month')) {
- return getOtherMonthDate($dateCell, month, year); // eslint-disable-line
+ if (dataTable.param.comparePeriods && dataTable.param.comparePeriods.length) {
+ exportUrlParams.comparePeriods = dataTable.param.comparePeriods;
+ exportUrlParams.compare = '1';
}
- var day = parseInt($dateCell.children('a,span').text(), 10);
- return new Date(year, month, day);
- }
-
- function getOtherMonthDate($dateCell, month, year) {
- var date;
- var $row = $dateCell.parent();
- var $rowCells = $row.children('td'); // if in the first row, the date cell is before the current month
+ if (dataTable.param.compareSegments && dataTable.param.compareSegments.length) {
+ exportUrlParams.compareSegments = dataTable.param.compareSegments;
+ exportUrlParams.compare = '1';
+ }
- if ($row.is(':first-child')) {
- var $firstDateInMonth = $row.children('td:not(.ui-datepicker-other-month)').first();
- date = getCellDate($firstDateInMonth, month, year);
- date.setDate($rowCells.index($dateCell) - $rowCells.index($firstDateInMonth) + 1);
- return date;
- } // the date cell is after the current month
+ 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;
+ }
- var $lastDateInMonth = $row.children('td:not(.ui-datepicker-other-month)').last();
- date = getCellDate($lastDateInMonth, month, year);
- date.setDate(date.getDate() + $rowCells.index($dateCell) - $rowCells.index($lastDateInMonth));
- return date;
- }
+ 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];
- function getMonthYearDisplayed() {
- var element = DatePickervue_type_script_lang_ts_$(root.value);
- var $firstCellWithMonth = element.find('td[data-month]');
- var month = parseInt($firstCellWithMonth.attr('data-month'), 10);
- var year = parseInt($firstCellWithMonth.attr('data-year'), 10);
- return [month, year];
- }
+ var value = param;
- function setDatePickerCellColors() {
- var element = DatePickervue_type_script_lang_ts_$(root.value);
- var $calendarTable = element.find('.ui-datepicker-calendar');
- var monthYear = getMonthYearDisplayed(); // highlight the rest of the cells by first getting the date for the first cell
- // in the calendar, then just incrementing by one for the rest of the cells.
+ if (value === true) {
+ value = 1;
+ } else if (value === false) {
+ value = 0;
+ }
- var $cells = $calendarTable.find('td');
- var $firstDateCell = $cells.first();
- var currentDate = getCellDate($firstDateCell, monthYear[0], monthYear[1]);
- $cells.each(function setCellColor() {
- setDateCellColor(DatePickervue_type_script_lang_ts_$(this), currentDate);
- currentDate.setDate(currentDate.getDate() + 1);
- });
- }
+ exportUrlParams[index] = value;
+ });
+ }
- function viewDateChanged() {
- var date = props.viewDate;
+ if (this.optionFlat) {
+ exportUrlParams.flat = 1;
- if (!date) {
- return false;
+ if (typeof dataTable.param.include_aggregate_rows !== 'undefined' && dataTable.param.include_aggregate_rows === '1') {
+ exportUrlParams.include_aggregate_rows = 1;
+ }
}
- if (!(date instanceof Date)) {
- try {
- date = parseDate(date);
- } catch (e) {
- return false;
- }
+ if (!this.optionFlat && this.optionExpanded) {
+ exportUrlParams.expanded = 1;
}
- var element = DatePickervue_type_script_lang_ts_$(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.
+ if (this.optionFormatMetrics) {
+ exportUrlParams.format_metrics = 1;
+ }
- var monthYear = getMonthYearDisplayed();
+ if (dataTable.param.pivotBy) {
+ exportUrlParams.pivotBy = dataTable.param.pivotBy;
+ exportUrlParams.pivotByColumnLimit = 20;
- if (monthYear[0] !== date.getMonth() || monthYear[1] !== date.getFullYear()) {
- element.datepicker('setDate', date);
- return true;
+ if (dataTable.props.pivot_by_column) {
+ exportUrlParams.pivotByColumn = dataTable.props.pivot_by_column;
+ }
}
- return false;
- } // remove the ui-state-active class & click handlers for every cell. we bypass
- // the datepicker's date selection logic for smoother browser rendering.
-
+ if (reportFormat === 'CSV' || reportFormat === 'TSV' || reportFormat === 'RSS') {
+ exportUrlParams.translateColumnNames = 1;
+ exportUrlParams.language = Matomo_Matomo.language;
+ }
- function onJqueryUiRenderedPicker() {
- var element = DatePickervue_type_script_lang_ts_$(root.value);
- element.find('td[data-event]').off('click');
- element.find('.ui-state-active').removeClass('ui-state-active');
- element.find('.ui-datepicker-current-day').removeClass('ui-datepicker-current-day'); // add href to left/right nav in calendar so they can be accessed via keyboard
+ if (typeof segment !== 'undefined') {
+ exportUrlParams.segment = decodeURIComponent(segment);
+ } // Export Goals specific reports
- element.find('.ui-datepicker-prev,.ui-datepicker-next').attr('href', '');
- }
- function stepMonthsChanged() {
- var element = DatePickervue_type_script_lang_ts_$(root.value);
- var stepMonths = props.stepMonths || DEFAULT_STEP_MONTHS;
+ if (typeof idGoal !== 'undefined' && idGoal !== '-1') {
+ exportUrlParams.idGoal = idGoal;
+ } // Export Dimension specific reports
- if (element.datepicker('option', 'stepMonths') === stepMonths) {
- return false;
- } // 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.
+ if (typeof idDimension !== 'undefined' && idDimension !== '-1') {
+ exportUrlParams.idDimension = idDimension;
+ }
- var currentMonth = DatePickervue_type_script_lang_ts_$('.ui-datepicker-month', element).val();
- var currentYear = DatePickervue_type_script_lang_ts_$('.ui-datepicker-year', element).val();
- element.datepicker('option', 'stepMonths', stepMonths).datepicker('setDate', new Date(currentYear, currentMonth));
- onJqueryUiRenderedPicker();
- return true;
- }
+ if (label) {
+ var labelParts = label.split(',');
- function enableDisableMonthDropdown() {
- var element = DatePickervue_type_script_lang_ts_$(root.value);
- element.find('.ui-datepicker-month').attr('disabled', props.disableMonthDropdown);
- }
+ if (labelParts.length > 1) {
+ exportUrlParams.label = labelParts;
+ } else {
+ var _labelParts = ReportExportPopovervue_type_script_lang_ts_slicedToArray(labelParts, 1);
- function handleOtherMonthClick() {
- if (!DatePickervue_type_script_lang_ts_$(this).hasClass('ui-state-hover')) {
- return;
+ exportUrlParams.label = _labelParts[0];
+ }
}
- var $row = DatePickervue_type_script_lang_ts_$(this).parent();
- var $tbody = $row.parent();
+ exportUrlParams.token_auth = 'ENTER_YOUR_TOKEN_AUTH_HERE';
- if ($row.is(':first-child')) {
- // click on first of the month
- $tbody.find('a').first().click();
- } else {
- // click on last of month
- $tbody.find('a').last().click();
+ if (withToken === true) {
+ exportUrlParams.token_auth = Matomo_Matomo.token_auth;
+ exportUrlParams.force_api_session = 1;
}
- }
-
- function onCalendarViewChange() {
- // clicking left/right re-enables the month dropdown, so we disable it again
- enableDisableMonthDropdown();
- setDatePickerCellColors();
- } // on a prop change (NOTE: we can't watch just `props`, since then newProps and oldProps will
- // have the same values (since it is a proxy object). Using a copy doesn't quite work, the
- // object it returns will always be different, BUT, since we check what changes it works
- // for our purposes. The only downside is that it runs on every tick basically, but since
- // that is within the context of the date picker component, it's bearable.
+ 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
- Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () {
- return DatePickervue_type_script_lang_ts_objectSpread({}, props);
- }, function (newProps, oldProps) {
- var redraw = false;
- ['selectedDateStart', 'selectedDateEnd', 'highlightedDateStart', 'highlightedDateEnd'].forEach(function (propName) {
- if (redraw) {
- return;
- }
- if (!newProps[propName] && oldProps[propName]) {
- redraw = true;
- }
- if (newProps[propName] && !oldProps[propName]) {
- redraw = true;
- }
+ReportExportPopovervue_type_script_lang_ts.render = ReportExportPopovervue_type_template_id_3d203950_render
- if (newProps[propName] && oldProps[propName] && newProps[propName].getTime() !== oldProps[propName].getTime()) {
- redraw = true;
- }
- });
+/* 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
+ */
- if (newProps.viewDate !== oldProps.viewDate && viewDateChanged()) {
- redraw = true;
- }
- if (newProps.stepMonths !== oldProps.stepMonths) {
- stepMonthsChanged();
- }
- if (newProps.enableDisableMonthDropdown !== oldProps.enableDisableMonthDropdown) {
- enableDisableMonthDropdown();
- } // redraw when selected/highlighted dates change
- if (redraw) {
- setDatePickerCellColors();
+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);
}
- });
- 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), {}, {
- onChangeMonthYear: function onChangeMonthYear() {
- // datepicker renders the HTML after this hook is called, so we use setTimeout
- // to run some code after the render.
- setTimeout(function () {
- onJqueryUiRenderedPicker();
- });
+ 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 ",
+ 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
+ }));
- 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,
- // the originalEvent is null. we don't need to redraw again for that, so
- // we ignore events like that.
- if (event.originalEvent) {
- setDatePickerCellColors();
+ if (binding.value.onClose) {
+ binding.value.onClose();
+ }
+ }, 100);
}
- }); // on hover cell, execute scope.cellHover()
-
- element.on('mouseenter', 'tbody td', function onMouseEnter() {
- var monthYear = getMonthYearDisplayed();
- var $dateCell = DatePickervue_type_script_lang_ts_$(this);
- var dateValue = getCellDate($dateCell, monthYear[0], monthYear[1]);
- context.emit('cellHover', {
- date: dateValue,
- $cell: $dateCell
+ });
+ setTimeout(function () {
+ popover.dialog();
+ ReportExport_$('.exportFullUrl, .btn', popover).tooltip({
+ track: true,
+ show: false,
+ hide: false
});
- }); // overrides jquery UI handler that unhighlights a cell when the mouse leaves it
+ }, 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
+
- element.on('mouseout', 'tbody td a', function () {
- setDatePickerCellColors();
- }); // call scope.cellHoverLeave() when mouse leaves table body (can't do event on tbody, for
- // some reason that fails, so we do two events, one on the table & one on thead)
- element.on('mouseleave', 'table', function () {
- return context.emit('cellHoverLeave');
- }).on('mouseenter', 'thead', function () {
- 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', function (e) {
- e.preventDefault();
- var $target = DatePickervue_type_script_lang_ts_$(e.target).closest('a');
- if (!$target.is('.ui-datepicker-next') && !$target.is('.ui-datepicker-prev')) {
- return;
- }
+/* 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;
+ }
- onCalendarViewChange();
- }); // when a cell is clicked, invoke the onDateSelected function. this, in conjunction
- // with onJqueryUiRenderedPicker(), overrides the date picker's click behavior.
+ return "?".concat(src_MatomoUrl_MatomoUrl.stringify(urlParams));
+ },
+ defaultDate: function defaultDate() {
+ if (Matomo_Matomo.period === 'range') {
+ return "".concat(Matomo_Matomo.startDateString, ",").concat(Matomo_Matomo.endDateString);
+ }
- element.on('click', 'td[data-month]', function (event) {
- var $cell = DatePickervue_type_script_lang_ts_$(event.target).closest('td');
- var month = parseInt($cell.attr('data-month'), 10);
- var year = parseInt($cell.attr('data-year'), 10);
- var day = parseInt($cell.children('a,span').text(), 10);
- context.emit('dateSelect', {
- date: new Date(year, month, day)
- });
- });
- var renderPostProcessed = stepMonthsChanged();
- viewDateChanged();
- enableDisableMonthDropdown();
+ 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 (!renderPostProcessed) {
- onJqueryUiRenderedPicker();
+ if (dateRange[0] < piwikMinDate) {
+ dateRange[0] = piwikMinDate;
}
- setDatePickerCellColors();
- });
- return {
- root: root
- };
+ var startDateStr = format(dateRange[0]);
+ var endDateStr = format(dateRange[1]);
+ return "".concat(startDateStr, ",").concat(endDateStr);
+ }
}
}));
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue?vue&type=script&lang=ts
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Sparkline/Sparkline.vue?vue&type=script&lang=ts
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.vue
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Sparkline/Sparkline.vue
-DatePickervue_type_script_lang_ts.render = DatePickervue_type_template_id_c8c462d2_render
+Sparklinevue_type_script_lang_ts.render = Sparklinevue_type_template_id_693cd955_render
-/* harmony default export */ var DatePicker = (DatePickervue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts
+/* 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
*
@@ -4383,263 +11590,302 @@ DatePickervue_type_script_lang_ts.render = DatePickervue_type_template_id_c8c462
*/
-/* harmony default export */ var DatePicker_adapter = (createAngularJsAdapter({
- component: DatePicker,
+/* harmony default export */ var Sparkline_adapter = (createAngularJsAdapter({
+ component: Sparkline,
scope: {
- selectedDateStart: {
- angularJsBind: '<'
- },
- selectedDateEnd: {
- angularJsBind: '<'
- },
- highlightedDateStart: {
- angularJsBind: '<'
- },
- highlightedDateEnd: {
+ seriesIndices: {
angularJsBind: '<'
},
- viewDate: {
- angularJsBind: '<'
- },
- stepMonths: {
- angularJsBind: '<'
- },
- disableMonthDropdown: {
- angularJsBind: '<'
- },
- options: {
+ params: {
angularJsBind: '<'
- },
- cellHover: {
- angularJsBind: '&'
- },
- cellHoverLeave: {
- angularJsBind: '&'
- },
- dateSelect: {
- angularJsBind: '&'
- }
- },
- directiveName: 'piwikDatePicker',
- events: {
- 'cell-hover': function cellHover(event, scope, element, attrs, $timeout) {
- $timeout(); // trigger new digest
- },
- 'cell-hover-leave': function cellHoverLeave(event, scope, element, attrs, $timeout) {
- $timeout(); // trigger new digest
- },
- 'date-select': function dateSelect(event, scope, element, attrs, $timeout) {
- $timeout(); // trigger new digest
}
},
- $inject: ['$timeout']
+ 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/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/Progressbar/Progressbar.vue?vue&type=template&id=0048ddd7
-var DateRangePickervue_type_template_id_d9f4b538_hoisted_1 = {
- id: "calendarRangeFrom"
+var Progressbarvue_type_template_id_0048ddd7_hoisted_1 = {
+ class: "progressbar"
};
-var DateRangePickervue_type_template_id_d9f4b538_hoisted_2 = {
- id: "calendarRangeTo"
+var Progressbarvue_type_template_id_0048ddd7_hoisted_2 = {
+ class: "progress"
};
-function DateRangePickervue_type_template_id_d9f4b538_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", {
- type: "text",
- id: "inputCalendarFrom",
- name: "inputCalendarFrom",
- class: "browser-default",
- "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
- return _ctx.startDateText = $event;
- }),
- onChange: _cache[1] || (_cache[1] = function ($event) {
- return _ctx.onRangeInputChanged('from', $event);
- }),
- onKeyup: _cache[2] || (_cache[2] = function ($event) {
- return _ctx.handleEnterPress($event);
- })
- }, null, 544), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.startDateText]])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_DatePicker, {
- id: "calendarFrom",
- "view-date": _ctx.startDate,
- "selected-date-start": _ctx.fromPickerSelectedDates[0],
- "selected-date-end": _ctx.fromPickerSelectedDates[1],
- "highlighted-date-start": _ctx.fromPickerHighlightedDates[0],
- "highlighted-date-end": _ctx.fromPickerHighlightedDates[1],
- onDateSelect: _cache[3] || (_cache[3] = function ($event) {
- return _ctx.setStartRangeDate($event.date);
- }),
- onCellHover: _cache[4] || (_cache[4] = function ($event) {
- return _ctx.fromPickerHighlightedDates = _ctx.getNewHighlightedDates($event.date, $event.$cell);
- }),
- 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", {
- type: "text",
- id: "inputCalendarTo",
- name: "inputCalendarTo",
- class: "browser-default",
- "onUpdate:modelValue": _cache[6] || (_cache[6] = function ($event) {
- return _ctx.endDateText = $event;
- }),
- onChange: _cache[7] || (_cache[7] = function ($event) {
- return _ctx.onRangeInputChanged('to', $event);
- }),
- onKeyup: _cache[8] || (_cache[8] = function ($event) {
- return _ctx.handleEnterPress($event);
- })
- }, null, 544), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.endDateText]])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_DatePicker, {
- id: "calendarTo",
- "view-date": _ctx.endDate,
- "selected-date-start": _ctx.toPickerSelectedDates[0],
- "selected-date-end": _ctx.toPickerSelectedDates[1],
- "highlighted-date-start": _ctx.toPickerHighlightedDates[0],
- "highlighted-date-end": _ctx.toPickerHighlightedDates[1],
- onDateSelect: _cache[9] || (_cache[9] = function ($event) {
- return _ctx.setEndRangeDate($event.date);
- }),
- onCellHover: _cache[10] || (_cache[10] = function ($event) {
- return _ctx.toPickerHighlightedDates = _ctx.getNewHighlightedDates($event.date, $event.$cell);
- }),
- 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);
-}
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue?vue&type=template&id=d9f4b538
-// 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
+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 DateRangePickervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+/* harmony default export */ var Progressbarvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
props: {
- startDate: String,
- endDate: String
- },
- components: {
- DatePicker: DatePicker
+ progress: {
+ type: Number,
+ required: true
+ },
+ label: String
},
- data: function data() {
- var startDate = null;
+ computed: {
+ actualProgress: function actualProgress() {
+ if (this.progress > 100) {
+ return 100;
+ }
- try {
- startDate = parseDate(this.startDate);
- } catch (e) {// ignore
+ 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
- var endDate = null;
- try {
- endDate = parseDate(this.endDate);
- } catch (e) {// ignore
- }
- return {
- fromPickerSelectedDates: [startDate, startDate],
- toPickerSelectedDates: [endDate, endDate],
- fromPickerHighlightedDates: [null, null],
- toPickerHighlightedDates: [null, null],
- startDateText: this.startDate,
- endDateText: this.endDate
- };
- },
- emits: ['rangeChange', 'submit'],
- watch: {
- startDate: function startDate() {
- this.startDateText = this.startDate;
- this.setStartRangeDateFromStr(this.startDate);
+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: '='
},
- endDate: function endDate() {
- this.endDateText = this.endDate;
- this.setEndRangeDateFromStr(this.endDate);
+ label: {
+ angularJsBind: '='
}
},
- mounted: function mounted() {
- this.rangeChanged(); // emit with initial range pair
+ 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');
},
- methods: {
- setStartRangeDate: function setStartRangeDate(date) {
- this.fromPickerSelectedDates = [date, date];
- this.rangeChanged();
- },
- setEndRangeDate: function setEndRangeDate(date) {
- this.toPickerSelectedDates = [date, date];
- this.rangeChanged();
- },
- onRangeInputChanged: function onRangeInputChanged(source, event) {
- 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')) {
- return null;
- }
+ 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
+ */
- return [date, date];
- },
- handleEnterPress: function handleEnterPress($event) {
- if ($event.keyCode !== 13) {
- return;
- }
+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
- this.$emit('submit', {
- start: this.startDate,
- end: this.endDate
- });
- },
- setStartRangeDateFromStr: function setStartRangeDateFromStr(dateStr) {
- var startDateParsed;
+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
- try {
- startDateParsed = parseDate(dateStr);
- } catch (e) {
- this.startDateText = this.startDate;
- }
+// 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
- if (startDateParsed) {
- this.fromPickerSelectedDates = [startDateParsed, startDateParsed];
- }
- this.rangeChanged();
+
+
+var AjaxFormvue_type_script_lang_ts_window = window,
+ AjaxFormvue_type_script_lang_ts_$ = AjaxFormvue_type_script_lang_ts_window.$;
+/**
+ * Example usage:
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * 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
},
- setEndRangeDateFromStr: function setEndRangeDateFromStr(dateStr) {
- var endDateParsed;
+ 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;
- try {
- endDateParsed = parseDate(dateStr);
- } catch (e) {
- this.endDateText = this.endDate;
- }
+ // 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;
- if (endDateParsed) {
- this.toPickerSelectedDates = [endDateParsed, endDateParsed];
+ this.successfulPostResponse = null;
+ this.errorPostResponse = null;
+ var postParams = this.formData;
+
+ if (this.sendJsonPayload) {
+ postParams = {
+ data: JSON.stringify(this.formData)
+ };
}
- this.rangeChanged();
- },
- rangeChanged: function rangeChanged() {
- this.$emit('rangeChange', {
- start: format(this.fromPickerSelectedDates[0]),
- end: format(this.toPickerSelectedDates[0])
+ 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/DateRangePicker/DateRangePicker.vue?vue&type=script&lang=ts
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue?vue&type=script&lang=ts
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/AjaxForm/AjaxForm.vue
-DateRangePickervue_type_script_lang_ts.render = DateRangePickervue_type_template_id_d9f4b538_render
+AjaxFormvue_type_script_lang_ts.render = AjaxFormvue_type_template_id_00d5220c_render
-/* harmony default export */ var DateRangePicker = (DateRangePickervue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.adapter.ts
+/* 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
*
@@ -4648,137 +11894,163 @@ DateRangePickervue_type_script_lang_ts.render = DateRangePickervue_type_template
*/
-/* harmony default export */ var DateRangePicker_adapter = (createAngularJsAdapter({
- component: DateRangePicker,
- scope: {
- startDate: {
- angularJsBind: '<'
- },
- endDate: {
- angularJsBind: '<'
- },
- rangeChange: {
- angularJsBind: '&'
- },
- submit: {
- angularJsBind: '&'
- }
- },
- 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=effd17b0
-
-function PeriodDatePickervue_type_template_id_effd17b0_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, {
- "selected-date-start": _ctx.selectedDates[0],
- "selected-date-end": _ctx.selectedDates[1],
- "highlighted-date-start": _ctx.highlightedDates[0],
- "highlighted-date-end": _ctx.highlightedDates[1],
- "view-date": _ctx.viewDate,
- "step-months": _ctx.period === 'year' ? 12 : 1,
- "disable-month-dropdown": _ctx.period === 'year',
- onCellHover: _cache[0] || (_cache[0] = function ($event) {
- return _ctx.onHoverNormalCell($event.date, $event.$cell);
- }),
- onCellHoverLeave: _cache[1] || (_cache[1] = function ($event) {
- return _ctx.onHoverLeaveNormalCells();
- }),
- onDateSelect: _cache[2] || (_cache[2] = function ($event) {
- return _ctx.onDateSelected($event.date);
- })
- }, 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=effd17b0
-// 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
+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:
+ *
+ *
+ * @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 \n \n
\n \n ";
+ 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();
+ });
-var 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,
- date: [String, Date]
- },
- components: {
- DatePicker: DatePicker
- },
- emits: ['select'],
- setup: function setup(props, context) {
- var viewDate = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(props.date);
- var selectedDates = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])([null, null]);
- var highlightedDates = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])([null, null]);
+ function setFormValueFromInput(inputElement, skipScopeApply) {
+ var name = AjaxForm_adapter_$(inputElement).attr('name');
+ var val;
- function getBoundedDateRange(date) {
- var dates = Periods_Periods.get(props.period).parse(date).getDateRange(); // make sure highlighted date range is within min/max date range
+ if (AjaxForm_adapter_$(inputElement).attr('type') === 'checkbox') {
+ val = AjaxForm_adapter_$(inputElement).is(':checked');
+ } else {
+ val = AjaxForm_adapter_$(inputElement).val();
+ }
- dates[0] = piwikMinDate < dates[0] ? dates[0] : piwikMinDate;
- dates[1] = piwikMaxDate > dates[1] ? dates[1] : piwikMaxDate;
- return dates;
- }
+ scope.ajaxForm.data[name] = val;
- 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
- // whitespace. since there are no dates, it's doesn't make sense what you're selecting.
+ if (!skipScopeApply) {
+ setTimeout(function () {
+ scope.$apply();
+ }, 0);
+ }
+ } // on change of any input, change appropriate value in model, but only if requested
- var shouldNotHighlightFromWhitespace = $cell.hasClass('ui-datepicker-other-month') && (props.period === 'month' || props.period === 'day');
- if (isOutOfMinMaxDateRange || shouldNotHighlightFromWhitespace) {
- highlightedDates.value = [null, null];
- return;
- }
+ 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
- highlightedDates.value = getBoundedDateRange(cellDate);
- }
- function onHoverLeaveNormalCells() {
- highlightedDates.value = [null, null];
- }
+ transclude(scope, function (clone, transcludeScope) {
+ if (!transcludeScope.useCustomDataBinding) {
+ var $inputs = clone.find('input,select').not('[type=submit]'); // initialize form data to input values (include s
- function onDateSelected(date) {
- context.emit('select', {
- date: date
- });
- }
+ $inputs.each(function inputEach() {
+ setFormValueFromInput(this, true);
+ });
+ } // eslint-disable-next-line @typescript-eslint/no-explicit-any
- 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);
+ AjaxForm_adapter_$(vm.transcludeTarget).append(clone);
+ });
+ };
}
+ };
+}
- Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(props, onChanges);
- onChanges();
- return {
- selectedDates: selectedDates,
- highlightedDates: highlightedDates,
- viewDate: viewDate,
- onHoverNormalCell: onHoverNormalCell,
- onHoverLeaveNormalCells: onHoverLeaveNormalCells,
- onDateSelected: onDateSelected
- };
- }
-}));
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue?vue&type=script&lang=ts
-
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue
-
-
-
-PeriodDatePickervue_type_script_lang_ts.render = PeriodDatePickervue_type_template_id_effd17b0_render
-
-/* harmony default export */ var PeriodDatePicker = (PeriodDatePickervue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.adapter.ts
+piwikAjaxForm.$inject = ['$parse'];
+window.angular.module('piwikApp').directive('piwikAjaxForm', piwikAjaxForm);
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/getFormattedEvolution.ts
/*!
* Matomo - free/libre analytics platform
*
@@ -4787,64 +12059,30 @@ PeriodDatePickervue_type_script_lang_ts.render = PeriodDatePickervue_type_templa
*/
-/* harmony default export */ var PeriodDatePicker_adapter = (createAngularJsAdapter({
- component: PeriodDatePicker,
- scope: {
- period: {
- angularJsBind: '<'
- },
- date: {
- angularJsBind: '<'
- },
- select: {
- angularJsBind: '&'
- }
- },
- 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
-
-var ActivityIndicatorvue_type_template_id_6af4d064_hoisted_1 = {
- class: "loadingPiwik"
-};
-
-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);
-
-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]]);
-}
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=template&id=6af4d064
-
-// 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
-
+function calculateEvolution(currentValue, pastValue) {
+ var pastValueParsed = parseInt(pastValue, 10);
+ var currentValueParsed = parseInt(currentValue, 10) - pastValueParsed;
+ var evolution;
-/* 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')
- }
+ if (currentValueParsed === 0 || Number.isNaN(currentValueParsed)) {
+ evolution = 0;
+ } else if (pastValueParsed === 0 || Number.isNaN(pastValueParsed)) {
+ evolution = 100;
+ } else {
+ evolution = currentValueParsed / pastValueParsed * 100;
}
-}));
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue?vue&type=script&lang=ts
-
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue
-
+ return evolution;
+}
-ActivityIndicatorvue_type_script_lang_ts.render = ActivityIndicatorvue_type_template_id_6af4d064_render
+function formatEvolution(evolution) {
+ return "".concat(evolution > 0 ? Matomo_Matomo.numbers.symbolPlus : '').concat(Math.round(evolution), "}%");
+}
-/* harmony default export */ var ActivityIndicator = (ActivityIndicatorvue_type_script_lang_ts);
+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
@@ -4873,56 +12111,6 @@ ActivityIndicatorvue_type_script_lang_ts.render = ActivityIndicatorvue_type_temp
$inject: [],
directiveName: 'piwikActivityIndicator'
}));
-// 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/@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
-
-/* 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/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/CookieHelper/CookieHelper.ts
/*
* General utils for managing cookies in Typescript.
@@ -4967,185 +12155,7 @@ function deleteCookie(name) {
document.cookie = "".concat(name, "=; expires=").concat(date.toUTCString(), "; path=/");
}
-// 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 = {
- key: 0
-};
-var Notificationvue_type_template_id_e3d12348_hoisted_2 = ["data-notification-instance-id"];
-var Notificationvue_type_template_id_e3d12348_hoisted_3 = {
- key: 1
-};
-var Notificationvue_type_template_id_e3d12348_hoisted_4 = {
- class: "notification-body"
-};
-var Notificationvue_type_template_id_e3d12348_hoisted_5 = ["innerHTML"];
-var Notificationvue_type_template_id_e3d12348_hoisted_6 = {
- key: 1
-};
-function Notificationvue_type_template_id_e3d12348_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) {
- return _ctx.toastClosed();
- })
- }, {
- 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"], {
- name: _ctx.type === 'toast' ? 'toast-slide-up' : undefined,
- appear: ""
- }, {
- default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
- return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Transition"], {
- name: _ctx.animate ? 'fade-in' : undefined,
- appear: ""
- }, {
- default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
- return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
- class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["notification system", _ctx.cssClasses]),
- style: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeStyle"])(_ctx.style),
- ref: "root",
- "data-notification-instance-id": _ctx.notificationInstanceId
- }, [_ctx.canClose ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("button", {
- key: 0,
- type: "button",
- class: "close",
- "data-dismiss": "alert",
- 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", {
- 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)];
- }),
- _: 3
- }, 8, ["name"])])];
- }),
- _: 3
- }, 8, ["name"])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)];
- }),
- _: 3
- }, 8, ["name"]);
-}
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=template&id=e3d12348
-
-// 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
-
-
-var Notificationvue_type_script_lang_ts_window = window,
- Notificationvue_type_script_lang_ts_$ = Notificationvue_type_script_lang_ts_window.$;
-/* harmony default export */ var Notificationvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
- props: {
- notificationId: String,
- // NOTE: notificationId refers to server side ID for notifications stored in the session.
- // this ID is just so it can be selected outside of this component (just for scrolling).
- notificationInstanceId: String,
- title: String,
- context: String,
- type: String,
- noclear: Boolean,
- toastLength: {
- type: Number,
- default: 12 * 1000
- },
- style: [String, Object],
- animate: Boolean,
- message: String,
- cssClass: String
- },
- computed: {
- cssClasses: function cssClasses() {
- var result = {};
-
- if (this.context) {
- result["notification-".concat(this.context)] = true;
- }
-
- if (this.cssClass) {
- result[this.cssClass] = true;
- }
-
- return result;
- },
- canClose: function canClose() {
- if (this.type === 'persistent') {
- // otherwise it is never possible to dismiss the notification
- return true;
- }
-
- return !this.noclear;
- }
- },
- emits: ['closed'],
- data: function data() {
- return {
- deleted: false
- };
- },
- mounted: function mounted() {
- var _this = this;
-
- var addToastEvent = function addToastEvent() {
- setTimeout(function () {
- _this.deleted = true;
- }, _this.toastLength);
- };
-
- if (this.type === 'toast') {
- addToastEvent();
- }
-
- if (this.style) {
- Notificationvue_type_script_lang_ts_$(this.$refs.root).css(this.style);
- }
- },
- methods: {
- toastClosed: function toastClosed() {
- var _this2 = this;
-
- Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
- _this2.$emit('closed');
- });
- },
- closeNotification: function closeNotification(event) {
- var _this3 = this;
-
- if (this.canClose && event && event.target) {
- this.deleted = true;
- Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
- _this3.$emit('closed');
- });
- }
-
- this.markNotificationAsRead();
- },
- markNotificationAsRead: function markNotificationAsRead() {
- if (!this.notificationId) {
- return;
- }
-
- AjaxHelper_AjaxHelper.fetch({
- module: 'CoreHome',
- action: 'markNotificationAsRead'
- }, {
- postParams: {
- notificationId: this.notificationId
- }
- });
- }
- }
-}));
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.vue?vue&type=script&lang=ts
-
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.vue
-
-
-
-Notificationvue_type_script_lang_ts.render = Notificationvue_type_template_id_e3d12348_render
-
-/* harmony default export */ var Notification = (Notificationvue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notification.adapter.ts
+// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/index.ts
/*!
* Matomo - free/libre analytics platform
*
@@ -5154,377 +12164,63 @@ Notificationvue_type_script_lang_ts.render = Notificationvue_type_template_id_e3
*/
-/* harmony default export */ var Notification_adapter = (createAngularJsAdapter({
- component: Notification,
- scope: {
- notificationId: {
- angularJsBind: '@?'
- },
- title: {
- angularJsBind: '@?notificationTitle'
- },
- context: {
- angularJsBind: '@?'
- },
- type: {
- angularJsBind: '@?'
- },
- noclear: {
- angularJsBind: '@?',
- transform: function transform(v) {
- return !!v;
- }
- },
- toastLength: {
- angularJsBind: '@?'
- }
- },
- directiveName: 'piwikNotification',
- 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); } }
-function Notifications_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) Notifications_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) Notifications_store_defineProperties(Constructor, staticProps); return Constructor; }
-function Notifications_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 Notifications_store_NotificationsStore = /*#__PURE__*/function () {
- function NotificationsStore() {
- Notifications_store_classCallCheck(this, NotificationsStore);
- Notifications_store_defineProperty(this, "privateState", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["reactive"])({
- notifications: []
- }));
- Notifications_store_defineProperty(this, "nextNotificationId", 0);
- }
- Notifications_store_createClass(NotificationsStore, [{
- key: "state",
- get: function get() {
- return this.privateState;
- }
- }, {
- key: "appendNotification",
- value: function appendNotification(notification) {
- this.checkMessage(notification.message); // remove existing notification before adding
- if (notification.id) {
- this.remove(notification.id);
- }
- this.privateState.notifications.push(notification);
- }
- }, {
- key: "prependNotification",
- value: function prependNotification(notification) {
- this.checkMessage(notification.message); // remove existing notification before adding
- if (notification.id) {
- this.remove(notification.id);
- }
- this.privateState.notifications.unshift(notification);
- }
- /**
- * Removes a previously shown notification having the given notification id.
- */
- }, {
- key: "remove",
- value: function remove(id) {
- this.privateState.notifications = this.privateState.notifications.filter(function (n) {
- return n.id !== id;
- });
- }
- }, {
- key: "parseNotificationDivs",
- value: function parseNotificationDivs() {
- var _this = this;
- var $notificationNodes = $('[data-role="notification"]');
- var notificationsToShow = [];
- $notificationNodes.each(function (index, notificationNode) {
- var $notificationNode = $(notificationNode);
- var attributes = $notificationNode.data();
- var message = $notificationNode.html();
- if (message) {
- notificationsToShow.push(Notifications_store_objectSpread(Notifications_store_objectSpread({}, attributes), {}, {
- message: message,
- animate: false
- }));
- }
- $notificationNodes.remove();
- });
- notificationsToShow.forEach(function (n) {
- return _this.show(n);
- });
- }
- }, {
- key: "clearTransientNotifications",
- value: function clearTransientNotifications() {
- this.privateState.notifications = this.privateState.notifications.filter(function (n) {
- return n.type !== 'transient';
- });
- }
- /**
- * Creates a notification and shows it to the user.
- */
- }, {
- key: "show",
- value: function show(notification) {
- this.checkMessage(notification.message);
- var addMethod = this.appendNotification;
- var notificationPosition = '#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
- var modalSelector = '.modal.open .modal-content';
- var modal = document.querySelector(modalSelector);
- if (modal) {
- if (!modal.querySelector('#modalNotificationContainer')) {
- window.$(modal).prepend('
');
- }
- notificationPosition = "".concat(modalSelector, " #modalNotificationContainer");
- addMethod = this.prependNotification;
- }
- }
- 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), {}, {
- noclear: !!notification.noclear,
- group: group,
- notificationId: notification.id,
- notificationInstanceId: notificationInstanceId,
- type: notification.type || 'transient'
- }));
- return notificationInstanceId;
- }
- }, {
- key: "scrollToNotification",
- value: function scrollToNotification(notificationInstanceId) {
- setTimeout(function () {
- var element = document.querySelector("[data-notification-instance-id='".concat(notificationInstanceId, "']"));
- if (element) {
- Matomo_Matomo.helper.lazyScrollTo(element, 250);
- }
- });
- }
- /**
- * Shows a notification at a certain point with a quick upwards animation.
- */
- }, {
- key: "toast",
- value: function toast(notification) {
- this.checkMessage(notification.message);
- var $placeat = $(notification.placeat);
- if (!$placeat.length) {
- throw new Error('A valid selector is required for the placeat option when using Notification.toast().');
- }
- var toastElement = document.createElement('div');
- toastElement.style.position = 'absolute';
- toastElement.style.top = "".concat($placeat.offset().top, "px");
- 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"])({
- render: function render() {
- return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(Notification, Notifications_store_objectSpread(Notifications_store_objectSpread({}, notification), {}, {
- notificationId: notification.id,
- type: 'toast',
- onClosed: function onClosed() {
- app.unmount();
- }
- }));
- }
- });
- 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 ($container.children('.notification-group').length) {
- return;
- } // avoiding a dependency cycle. won't need to do this when NotificationGroup's do not need
- // to be dynamically initialized.
- var NotificationGroup = window.CoreHome.NotificationGroup; // eslint-disable-line
- var app = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createApp"])({
- template: ' ',
- data: function data() {
- return {
- group: group
- };
- }
- });
- app.config.globalProperties.$sanitize = window.vueSanitize;
- app.config.globalProperties.translate = translate;
- app.component('NotificationGroup', NotificationGroup);
- app.mount($container[0]);
- }
- }, {
- key: "checkMessage",
- value: function checkMessage(message) {
- if (!message) {
- throw new Error('No message given, cannot display notification');
- }
- }
- }]);
- return NotificationsStore;
-}();
-var Notifications_store_instance = new Notifications_store_NotificationsStore();
-/* harmony default export */ var Notifications_store = (Notifications_store_instance); // parse notifications on dom load
-$(function () {
- return Notifications_store_instance.parseNotificationDivs();
-});
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/Notifications.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
- */
-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
-var NotificationGroupvue_type_template_id_672051da_hoisted_1 = {
- class: "notification-group"
-};
-var NotificationGroupvue_type_template_id_672051da_hoisted_2 = ["innerHTML"];
-function NotificationGroupvue_type_template_id_672051da_render(_ctx, _cache, $props, $setup, $data, $options) {
- var _component_Notification = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Notification");
- return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", NotificationGroupvue_type_template_id_672051da_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.notifications, function (notification, index) {
- return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Notification, {
- key: notification.id || "no-id-".concat(index),
- "notification-id": notification.id,
- title: notification.title,
- context: notification.context,
- type: notification.type,
- noclear: notification.noclear,
- "toast-length": notification.toastLength,
- style: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeStyle"])(notification.style),
- animate: notification.animate,
- message: notification.message,
- "notification-instance-id": notification.notificationInstanceId,
- "css-class": notification.class,
- onClosed: function onClosed($event) {
- return _ctx.removeNotification(notification.id);
- }
- }, {
- default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
- return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
- innerHTML: _ctx.$sanitize(notification.message)
- }, null, 8, NotificationGroupvue_type_template_id_672051da_hoisted_2)];
- }),
- _: 2
- }, 1032, ["notification-id", "title", "context", "type", "noclear", "toast-length", "style", "animate", "message", "notification-instance-id", "css-class", "onClosed"]);
- }), 128))]);
-}
-// 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
-/* harmony default export */ var NotificationGroupvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
- props: {
- group: String
- },
- components: {
- Notification: Notification
- },
- computed: {
- notifications: function notifications() {
- var _this = this;
- return Notifications_store.state.notifications.filter(function (n) {
- if (_this.group) {
- return _this.group === n.group;
- }
- return !n.group;
- });
- }
- },
- methods: {
- removeNotification: function removeNotification(id) {
- Notifications_store.remove(id);
- }
- }
-}));
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/NotificationGroup.vue?vue&type=script&lang=ts
-
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/NotificationGroup.vue
-NotificationGroupvue_type_script_lang_ts.render = NotificationGroupvue_type_template_id_672051da_render
-/* harmony default export */ var Notification_NotificationGroup = (NotificationGroupvue_type_script_lang_ts);
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/Notification/index.ts
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
-// CONCATENATED MODULE: ./plugins/CoreHome/vue/src/index.ts
-/*!
- * Matomo - free/libre analytics platform
- *
- * @link https://matomo.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */
+
+
diff --git a/app/plugins/CoreHome/vue/dist/CoreHome.umd.min.js b/app/plugins/CoreHome/vue/dist/CoreHome.umd.min.js
index 43f14c681..1cdbf9308 100644
--- a/app/plugins/CoreHome/vue/dist/CoreHome.umd.min.js
+++ b/app/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 Gt})),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;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;r=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=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);n1&&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;n1&&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;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n1&&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;r1?t-1:0),r=1;r1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=new Array(t);n=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;r1&&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;r1&&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(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return this.fetch(e,Object.assign(Object.assign({},n),{},{postParams:t}))}}]),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;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n",u&&(m+='
'),m+="";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='
')),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 Ft={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 Rt(){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:{}};Ft.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",Rt);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 qe(){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.substr(0,i)),o+=r.substr(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 Ge(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",qe);var Ke=document.documentElement,Xe={mounted:function(e,t){t.value.isMouseDown=!1,t.value.hasScrolled=!1,t.value.onExpand=Ge.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),window.$(t.value.expander).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=$('
');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"],Fn=["innerHTML"],Rn=["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,Fn)):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,Rn)):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="".concat(a,"
"),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;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n1||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 "+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," "))}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 Fr={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){}}},Rr=Object(a["defineComponent"])({props:{},directives:{Tooltips:Fr},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," ")):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='',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+=" ",c+=C("General_ComparisonCardTooltip2",[o.nb_visits_change.toString(),l.compareSegmentPretty,l.comparePeriodPretty])),c+="
",c}},mounted:function(){var e=this;S.on("piwikComparisonsChanged",(function(){e.onComparisonsChanged()})),this.onComparisonsChanged()}});Rr.render=Ir;var _r=Rr;
+/*!
+ * 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:Ft},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]=gin[1]?n[1]:vi,n}function l(t,n){var r=tvi,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 Fi=Object(a["defineComponent"])({props:{href:String,allSitesText:String},emits:["click"],methods:{onClick:function(e){this.$emit("click",e)}}});Fi.render=Li;var Ri=Fi;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;n1&&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: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;o1},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,'').concat(this.searchTerm," ").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:Ft},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.substr(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-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 Ra(e)||Fa(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 Fa(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function Ra(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-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);nr?(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]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"],Fo=["onClick"],Ro=Object(a["createElementVNode"])("span",{class:"icon-help"},null,-1),_o=[Ro],$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,Fo)):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 '),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:' ',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","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;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",l&&(p+='
'),p+="";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='
')),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 ');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(){var t=window,n=t.Feedback;e(n?n.RateFeature:null)}))}))})),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="".concat(r,"
"),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);nt.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:Gt,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;ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n1||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 "+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 "))},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='',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+=" ",s+=C("General_ComparisonCardTooltip2",[i.nb_visits_change.toString(),c.compareSegmentPretty,c.comparePeriodPretty])),s+="
",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),Rl(this,"privateState",Object(a["reactive"])({activeCategoryId:null,activeSubcategoryId:null,activeSubsubcategoryId:null})),Rl(this,"state",Object(a["computed"])((function(){return Object(a["readonly"])(t.privateState)}))),Rl(this,"activeCategory",Object(a["computed"])((function(){return t.state.value.activeCategoryId||Ee.parsed.value.category}))),Rl(this,"activeSubcategory",Object(a["computed"])((function(){return t.state.value.activeSubcategoryId||Ee.parsed.value.subcategory}))),Rl(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}))),Rl(this,"menu",Object(a["computed"])((function(){return t.buildMenuFromPages()})))}return Fl(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".concat(o," ");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=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;nn[1]?n[1]:dr,n}function c(t,n){var r=tdr,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(){if(!e.period||!e.date)return r.value=[null,null],void(n.value=null);r.value=i(e.date),n.value=E(e.date)}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);ne.length)&&(t=e.length);for(var n=0,r=new Array(t);n "))}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;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n '),n="".concat(r," #modalNotificationContainer"),t=this.prependNotification)}var o=e.group||(n?n.toString():"");this.initializeNotificationContainer(n,o);var i=(this.nextNotificationId+=1).toString();return t.call(this,Lr(Lr({},e),{},{noclear:!!e.noclear,group:o,notificationId:e.id,notificationInstanceId:i,type:e.type||"transient"})),i}},{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:' ',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}(),Gr=new qr,zr=Gr;$((function(){return Gr.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'),""),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()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"],Fs={class:"col l12"},Rs=["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",""," ","ENTER_YOUR_TOKEN_AUTH_HERE"))},null,8,Ls)],512),[[a["vShow"],e.showUrl]]),Object(a["createElementVNode"])("div",Fs,[Object(a["createElementVNode"])("a",{class:"btn",href:e.exportLink,target:"_new",title:e.translate("CoreHome_ExportTooltip")},Object(a["toDisplayString"])(e.translate("General_Export")),9,Rs),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);n0&&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 ',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]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 \n \n
\n \n ',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/app/plugins/CoreHome/vue/dist/umd.metadata.json b/app/plugins/CoreHome/vue/dist/umd.metadata.json
new file mode 100644
index 000000000..c63babfe1
--- /dev/null
+++ b/app/plugins/CoreHome/vue/dist/umd.metadata.json
@@ -0,0 +1,3 @@
+{
+ "dependsOn": []
+}
\ No newline at end of file
diff --git a/app/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts b/app/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts
index 84cb965fc..614d12805 100644
--- a/app/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue b/app/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue
index a5f27080d..ea3daf5dd 100644
--- a/app/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue
+++ b/app/plugins/CoreHome/vue/src/ActivityIndicator/ActivityIndicator.vue
@@ -14,7 +14,7 @@
diff --git a/app/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.adapter.ts b/app/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.adapter.ts
index c960a4213..59bc1db68 100644
--- a/app/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts b/app/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts
index f128ae6c3..610ede186 100644
--- a/app/plugins/CoreHome/vue/src/AjaxHelper/AjaxHelper.ts
+++ b/app/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;
+ 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 { // eslint-disable-line
*
* @deprecated use the jquery promise API
*/
- errorCallback: AnyFunction;
+ errorCallback: AnyFunction|null;
withToken = false;
@@ -145,25 +162,111 @@ export default class AjaxHelper { // eslint-disable-line
*/
errorElement: HTMLElement|JQuery|JQLite|string = '#ajaxError';
+ /**
+ * Extra headers to add to the request.
+ */
+ headers?: Record;
+
/**
* 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(params: QueryParameters, options: AjaxOptions = {}): Promise { // eslint-disable-line
+ static fetch( // eslint-disable-line
+ params: QueryParameters|QueryParameters[],
+ options: AjaxOptions = {},
+ ): Promise {
const helper = new AjaxHelper();
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(
+ params: QueryParameters,
+ // eslint-disable-next-line
+ postParams: any = {},
+ options: AjaxOptions = {},
+ ): Promise {
+ return this.fetch(params, { ...options, postParams });
}
constructor() {
@@ -184,13 +287,17 @@ export default class AjaxHelper { // 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 +366,7 @@ export default class AjaxHelper { // 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 +377,7 @@ export default class AjaxHelper { // eslint-disable-line
*
* @deprecated use the jquery promise API
*/
- setErrorCallback(callback: AnyFunction): void {
+ setErrorCallback(callback: AnyFunction|null): void {
this.errorCallback = callback;
}
@@ -346,7 +453,7 @@ export default class AjaxHelper { // eslint-disable-line
/**
* Send the request
*/
- send(): Promise {
+ send(): Promise {
if ($(this.errorElement).length) {
$(this.errorElement).hide();
}
@@ -358,15 +465,46 @@ export default class AjaxHelper { // eslint-disable-line
this.requestHandle = this.buildAjaxCall();
window.globalAjaxQueue.push(this.requestHandle);
- return new Promise((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
+ }
- reject(xhr);
+ if (this.abortController) {
+ this.abortController.signal.addEventListener('abort', () => {
+ if (this.requestHandle) {
+ this.requestHandle.abort();
+ }
+ });
+ }
+
+ const result = new Promise((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);
+ }).done(() => {
+ if ($timeout) {
+ $timeout(); // trigger digest
}
});
});
+
+ return result;
}
/**
@@ -408,6 +546,7 @@ export default class AjaxHelper { // 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 +568,8 @@ export default class AjaxHelper { // 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 +639,7 @@ export default class AjaxHelper { // 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 = {
@@ -533,4 +673,8 @@ export default class AjaxHelper { // eslint-disable-line
return params;
}
+
+ getRequestHandle(): jqXHR|null {
+ return this.requestHandle;
+ }
}
diff --git a/app/plugins/CoreHome/vue/src/Alert/alert.less b/app/plugins/CoreHome/vue/src/Alert/alert.less
index 6d1dc174c..4f335d5f1 100644
--- a/app/plugins/CoreHome/vue/src/Alert/alert.less
+++ b/app/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/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts b/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts
index 845c96508..c2133ed48 100644
--- a/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.spec.ts b/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.spec.ts
index 97e1ad3f2..2dc4ef315 100644
--- a/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.spec.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts b/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts
index 6d3b8462d..3c7659dde 100644
--- a/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.store.ts
+++ b/app/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(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,16 @@ 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'
) {
this.privateState.comparisonsDisabledFor = [];
return;
diff --git a/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.vue b/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.vue
index 7639c2e62..d9ab36781 100644
--- a/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.vue
+++ b/app/plugins/CoreHome/vue/src/Comparisons/Comparisons.vue
@@ -5,7 +5,12 @@
-->
-
+
{{ translate('General_Comparisons') }}
>|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, '
'));
+ }
+
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, '
'));
- },
- 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
- }
},
});
diff --git a/app/plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue b/app/plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue
index 12a89d770..6bee7fab9 100644
--- a/app/plugins/CoreHome/vue/src/ContentBlock/ContentBlock.vue
+++ b/app/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/app/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.adapter.ts b/app/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.adapter.ts
new file mode 100644
index 000000000..8669a29b5
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.ts b/app/plugins/CoreHome/vue/src/ContentIntro/ContentIntro.ts
new file mode 100644
index 000000000..ba550ae21
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ContentTable/ContentTable.adapter.ts b/app/plugins/CoreHome/vue/src/ContentTable/ContentTable.adapter.ts
new file mode 100644
index 000000000..a57d53ed4
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ContentTable/ContentTable.ts b/app/plugins/CoreHome/vue/src/ContentTable/ContentTable.ts
new file mode 100644
index 000000000..7d7dfc389
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts b/app/plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts
index 71223d58f..e276e59dc 100644
--- a/app/plugins/CoreHome/vue/src/DatePicker/DatePicker.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/DatePicker/DatePicker.vue b/app/plugins/CoreHome/vue/src/DatePicker/DatePicker.vue
index 784d0d931..1f605c70a 100644
--- a/app/plugins/CoreHome/vue/src/DatePicker/DatePicker.vue
+++ b/app/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
(null);
+ const root = ref(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/app/plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue b/app/plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue
index c2af7ecb1..0a5608d2a 100644
--- a/app/plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue
+++ b/app/plugins/CoreHome/vue/src/DateRangePicker/DateRangePicker.vue
@@ -5,67 +5,81 @@
-->
-
-
- {{ translate('General_DateRangeFrom') }}
-
-
-
-
-
-
-
- {{ translate('General_DateRangeTo') }}
-
-
-
-
+
diff --git a/app/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.adapter.ts b/app/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.adapter.ts
index 348a51cd7..5e272d664 100644
--- a/app/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.ts b/app/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.ts
index dcfb3928f..df31210a8 100644
--- a/app/plugins/CoreHome/vue/src/FocusAnywhereButHere/FocusAnywhereButHere.ts
+++ b/app/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
): 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/app/plugins/CoreHome/vue/src/FocusIf/FocusIf.adapter.ts b/app/plugins/CoreHome/vue/src/FocusIf/FocusIf.adapter.ts
index 2d48e8f25..e02ef6c02 100644
--- a/app/plugins/CoreHome/vue/src/FocusIf/FocusIf.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/FocusIf/FocusIf.ts b/app/plugins/CoreHome/vue/src/FocusIf/FocusIf.ts
index 6a13e46ff..3a79d51e4 100644
--- a/app/plugins/CoreHome/vue/src/FocusIf/FocusIf.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts b/app/plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts
index 5e35cbb8e..9a6da109d 100644
--- a/app/plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts
+++ b/app/plugins/CoreHome/vue/src/Matomo/Matomo.adapter.ts
@@ -19,7 +19,7 @@ function initPiwikService(piwik: PiwikGlobal, $rootScope: IRootScopeService) {
($rootScope as any).$oldEmit = $rootScope.$emit; // eslint-disable-line
$rootScope.$emit = function emitWrapper(name: string, ...args: any[]): IAngularEvent { // eslint-disable-line
Matomo.postEventNoEmit(name, ...args);
- return this.$oldEmit(name, ...args);
+ return (this as any).$oldEmit(name, ...args); // eslint-disable-line
};
($rootScope as any).$oldBroadcast = $rootScope.$broadcast; // eslint-disable-line
diff --git a/app/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts b/app/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts
index ee03ce55c..687bbabfc 100644
--- a/app/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue b/app/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue
index 9fd3feaa1..2b871acf0 100644
--- a/app/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue
+++ b/app/plugins/CoreHome/vue/src/MatomoDialog/MatomoDialog.vue
@@ -42,7 +42,8 @@ export default defineComponent({
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/app/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.adapter.ts b/app/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.adapter.ts
index b82329739..2e3d69cca 100644
--- a/app/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.ts b/app/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.ts
index 11eec228a..9ab1dc54a 100644
--- a/app/plugins/CoreHome/vue/src/MatomoUrl/MatomoUrl.ts
+++ b/app/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;
* 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/app/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.adapter.ts b/app/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.adapter.ts
similarity index 82%
rename from app/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.adapter.ts
rename to app/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.adapter.ts
index f56616f54..99fa4dcaf 100644
--- a/app/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.less b/app/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.less
similarity index 100%
rename from app/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.less
rename to app/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.less
diff --git a/app/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue b/app/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue
similarity index 89%
rename from app/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue
rename to app/plugins/CoreHome/vue/src/MenuItemsDropdown/MenuItemsDropdown.vue
index fdd26bfdb..80b57eaab 100644
--- a/app/plugins/CoreHome/vue/src/Menudropdown/Menudropdown.vue
+++ b/app/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/app/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.adapter.ts b/app/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.adapter.ts
new file mode 100644
index 000000000..3313d4c65
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less b/app/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.less
similarity index 100%
rename from app/plugins/CoreHome/angularjs/multipairfield/multipairfield.directive.less
rename to app/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.less
diff --git a/app/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue b/app/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue
new file mode 100644
index 000000000..87a812d57
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/MultiPairField/MultiPairField.vue
@@ -0,0 +1,211 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/Notification/Notification.adapter.ts b/app/plugins/CoreHome/vue/src/Notification/Notification.adapter.ts
index 584571897..4ff27943e 100644
--- a/app/plugins/CoreHome/vue/src/Notification/Notification.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Notification/Notification.less b/app/plugins/CoreHome/vue/src/Notification/Notification.less
index 9bafc751c..a99d63be1 100644
--- a/app/plugins/CoreHome/vue/src/Notification/Notification.less
+++ b/app/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/app/plugins/CoreHome/vue/src/Notification/Notification.ts b/app/plugins/CoreHome/vue/src/Notification/Notification.ts
new file mode 100644
index 000000000..8ddfcd62f
--- /dev/null
+++ b/app/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;
+
+ /**
+ * 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/app/plugins/CoreHome/vue/src/Notification/Notification.vue b/app/plugins/CoreHome/vue/src/Notification/Notification.vue
index e25dcb171..0047e10ba 100644
--- a/app/plugins/CoreHome/vue/src/Notification/Notification.vue
+++ b/app/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/app/plugins/CoreHome/vue/src/Notification/Notifications.store.adapter.ts b/app/plugins/CoreHome/vue/src/Notification/Notifications.store.adapter.ts
index 95cacccbc..e759836e4 100644
--- a/app/plugins/CoreHome/vue/src/Notification/Notifications.store.adapter.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Notification/Notifications.store.ts b/app/plugins/CoreHome/vue/src/Notification/Notifications.store.ts
index 651cdd127..701bddee1 100644
--- a/app/plugins/CoreHome/vue/src/Notification/Notifications.store.ts
+++ b/app/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;
-
- /**
- * 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({
+ private privateState = reactive({
notifications: [],
});
private nextNotificationId = 0;
get state(): DeepReadonly {
- 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,9 +93,9 @@ 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 {
@@ -174,7 +105,7 @@ class NotificationsStore {
const modal = document.querySelector(modalSelector);
if (modal) {
if (!modal.querySelector('#modalNotificationContainer')) {
- window.$(modal).prepend('
');
+ $(modal).prepend('
');
}
notificationPosition = `${modalSelector} #modalNotificationContainer`;
@@ -203,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);
}
@@ -216,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,
@@ -238,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;
}
@@ -256,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: ' ',
data: () => ({ group }),
});
- app.config.globalProperties.$sanitize = window.vueSanitize;
- app.config.globalProperties.translate = translate;
app.component('NotificationGroup', NotificationGroup);
app.mount($container[0]);
}
diff --git a/app/plugins/CoreHome/vue/src/Notification/index.ts b/app/plugins/CoreHome/vue/src/Notification/index.ts
index abcc74b95..a7a929a5b 100644
--- a/app/plugins/CoreHome/vue/src/Notification/index.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Orderable.ts b/app/plugins/CoreHome/vue/src/Orderable.ts
new file mode 100644
index 000000000..7b8cfd32a
--- /dev/null
+++ b/app/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(menu?: ReadonlyArray): 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/app/plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue b/app/plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue
index dd33f4784..49c05a4a4 100644
--- a/app/plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue
+++ b/app/plugins/CoreHome/vue/src/PeriodDatePicker/PeriodDatePicker.vue
@@ -22,7 +22,6 @@
diff --git a/app/plugins/CoreHome/vue/src/Periods/Day.ts b/app/plugins/CoreHome/vue/src/Periods/Day.ts
index f4150d9a3..f6a49efa0 100644
--- a/app/plugins/CoreHome/vue/src/Periods/Day.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Periods/Month.ts b/app/plugins/CoreHome/vue/src/Periods/Month.ts
index 292474591..ea19981db 100644
--- a/app/plugins/CoreHome/vue/src/Periods/Month.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Periods/Range.ts b/app/plugins/CoreHome/vue/src/Periods/Range.ts
index 07660dae5..144a945c9 100644
--- a/app/plugins/CoreHome/vue/src/Periods/Range.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Periods/Week.ts b/app/plugins/CoreHome/vue/src/Periods/Week.ts
index 4bb45ceed..2045fb4af 100644
--- a/app/plugins/CoreHome/vue/src/Periods/Week.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/Periods/Year.ts b/app/plugins/CoreHome/vue/src/Periods/Year.ts
index 9f9c0c0c8..178781af3 100644
--- a/app/plugins/CoreHome/vue/src/Periods/Year.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/PopoverHandler/PopoverHandler.ts b/app/plugins/CoreHome/vue/src/PopoverHandler/PopoverHandler.ts
new file mode 100644
index 000000000..341cdf868
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/Progressbar/Progressbar.adapter.ts b/app/plugins/CoreHome/vue/src/Progressbar/Progressbar.adapter.ts
new file mode 100644
index 000000000..79cb2049b
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/angularjs/progressbar/progressbar.directive.less b/app/plugins/CoreHome/vue/src/Progressbar/Progressbar.less
similarity index 100%
rename from app/plugins/CoreHome/angularjs/progressbar/progressbar.directive.less
rename to app/plugins/CoreHome/vue/src/Progressbar/Progressbar.less
diff --git a/app/plugins/CoreHome/vue/src/Progressbar/Progressbar.vue b/app/plugins/CoreHome/vue/src/Progressbar/Progressbar.vue
new file mode 100644
index 000000000..985c44dc9
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/Progressbar/Progressbar.vue
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.adapter.ts b/app/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.adapter.ts
new file mode 100644
index 000000000..2818deff0
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/angularjs/quick-access/quick-access.directive.less b/app/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.less
similarity index 98%
rename from app/plugins/CoreHome/angularjs/quick-access/quick-access.directive.less
rename to app/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.less
index 3bad77b9b..1bfdf4285 100644
--- a/app/plugins/CoreHome/angularjs/quick-access/quick-access.directive.less
+++ b/app/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/app/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue b/app/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue
new file mode 100644
index 000000000..c86008c13
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/QuickAccess/QuickAccess.vue
@@ -0,0 +1,481 @@
+
+
+
+
+
+
+
+
+ {{ translate('General_SearchNoResults') }}
+
+
+
+
+ {{ translate('SitesManager_Sites') }}
+
+
+ {{ translate('MultiSites_LoadingWebsites') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/ReportExport/ReportExport.adapter.ts b/app/plugins/CoreHome/vue/src/ReportExport/ReportExport.adapter.ts
new file mode 100644
index 000000000..a949af3a8
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/angularjs/report-export/reportexport.popover.less b/app/plugins/CoreHome/vue/src/ReportExport/ReportExport.less
similarity index 85%
rename from app/plugins/CoreHome/angularjs/report-export/reportexport.popover.less
rename to app/plugins/CoreHome/vue/src/ReportExport/ReportExport.less
index 303340e11..29137514e 100644
--- a/app/plugins/CoreHome/angularjs/report-export/reportexport.popover.less
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportExport/ReportExport.ts b/app/plugins/CoreHome/vue/src/ReportExport/ReportExport.ts
new file mode 100644
index 000000000..f7f8a0743
--- /dev/null
+++ b/app/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;
+ apiMethod: string;
+ maxFilterLimit: number;
+ onClose?: () => void;
+}
+
+const { $ } = window;
+
+export default {
+ mounted(el: HTMLElement, binding: DirectiveBinding): 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: `
+ `,
+ 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/app/plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue b/app/plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue
new file mode 100644
index 000000000..37caea1e2
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/ReportExport/ReportExportPopover.vue
@@ -0,0 +1,444 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.adapter.ts b/app/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.adapter.ts
new file mode 100644
index 000000000..bc1c37f6f
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.ts b/app/plugins/CoreHome/vue/src/ReportMetadata/ReportMetadata.store.ts
new file mode 100644
index 000000000..1839e63ca
--- /dev/null
+++ b/app/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({
+ reports: [],
+ });
+
+ private state = readonly(this.privateState);
+
+ readonly reports = computed(() => this.state.reports);
+
+ private reportsPromise?: Promise;
+
+ // TODO: it used to return an empty array when nothing was found, will that be an issue?
+ findReport(reportModule?: string, reportAction?: string): DeepReadonly|undefined {
+ return this.reports.value.find((r) => r.module === reportModule && r.action === reportAction);
+ }
+
+ fetchReportMetadata(): Promise {
+ 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/app/plugins/CoreHome/vue/src/ReportingMenu/Category.ts b/app/plugins/CoreHome/vue/src/ReportingMenu/Category.ts
new file mode 100644
index 000000000..5e2672b9e
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.adapter.ts b/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.adapter.ts
new file mode 100644
index 000000000..8de6fd465
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.adapter.ts b/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.adapter.ts
new file mode 100644
index 000000000..3407fb694
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.ts b/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.store.ts
new file mode 100644
index 000000000..2241b23d8
--- /dev/null
+++ b/app/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({
+ 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 {
+ return ReportingPagesStoreInstance.getAllPages().then(() => this.menu.value);
+ }
+
+ reloadMenuItems(): Promise {
+ 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 = {};
+ 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/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue b/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue
new file mode 100644
index 000000000..3e60c63c9
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/ReportingMenu/ReportingMenu.vue
@@ -0,0 +1,388 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/ReportingMenu/Subcategory.ts b/app/plugins/CoreHome/vue/src/ReportingMenu/Subcategory.ts
new file mode 100644
index 000000000..b18efea4b
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.adapter.ts b/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.adapter.ts
new file mode 100644
index 000000000..f54501f8e
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.less b/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.less
new file mode 100644
index 000000000..ea7137f68
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.adapter.ts b/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.adapter.ts
new file mode 100644
index 000000000..e9feb2339
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.ts b/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.store.ts
new file mode 100644
index 000000000..869117dfc
--- /dev/null
+++ b/app/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;
+}
+
+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({});
+
+ 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 = {};
+
+ 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 {
+ 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/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue b/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue
new file mode 100644
index 000000000..2cba4525a
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/ReportingPage/ReportingPage.vue
@@ -0,0 +1,293 @@
+
+
+
+
+
+
{{ translate('CoreHome_NoSuchPage') }}
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.adapter.ts b/app/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.adapter.ts
new file mode 100644
index 000000000..0c1981bad
--- /dev/null
+++ b/app/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
+ ) => clone(ReportingPagesStoreInstance.findPageInCategory(...args)),
+ findPage: (...args: Parameters) => 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/app/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.ts b/app/plugins/CoreHome/vue/src/ReportingPages/ReportingPages.store.ts
new file mode 100644
index 000000000..e59986d6f
--- /dev/null
+++ b/app/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({
+ pages: [],
+ });
+
+ private state = computed(() => readonly(this.privateState));
+
+ private fetchAllPagesPromise?: Promise>;
+
+ readonly pages = computed(() => this.state.value.pages);
+
+ findPageInCategory(categoryId: string): DeepReadonly|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|undefined {
+ return this.pages.value.find((p) => p
+ && p.category && p.subcategory && p.category.id === categoryId
+ && `${p.subcategory.id}` === subcategoryId);
+ }
+
+ reloadAllPages(): Promise {
+ delete this.fetchAllPagesPromise;
+ return this.getAllPages();
+ }
+
+ getAllPages(): Promise {
+ 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/app/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.adapter.ts b/app/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.adapter.ts
new file mode 100644
index 000000000..9a8fac6a7
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.ts b/app/plugins/CoreHome/vue/src/SelectOnFocus/SelectOnFocus.ts
new file mode 100644
index 000000000..a1a588336
--- /dev/null
+++ b/app/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, 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) {
+ delete binding.value.focusedElement;
+}
+
+export default {
+ mounted(el: HTMLElement, binding: DirectiveBinding): 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): 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/app/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.adapter.ts b/app/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.adapter.ts
new file mode 100644
index 000000000..24f8186cb
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.ts b/app/plugins/CoreHome/vue/src/ShowSensitiveData/ShowSensitiveData.ts
new file mode 100644
index 000000000..76d5c0c53
--- /dev/null
+++ b/app/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:
+ *
+ */
+export default {
+ mounted(el: HTMLElement, binding: DirectiveBinding): 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.substr(0, showCharacters);
+ }
+ protectedData += sensitiveData.substr(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/app/plugins/CoreHome/vue/src/SideNav/SideNav.adapter.ts b/app/plugins/CoreHome/vue/src/SideNav/SideNav.adapter.ts
new file mode 100644
index 000000000..3778689d9
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/SideNav/SideNav.ts b/app/plugins/CoreHome/vue/src/SideNav/SideNav.ts
new file mode 100644
index 000000000..ba9858506
--- /dev/null
+++ b/app/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:
+ * ...
+ */
+export default {
+ mounted(el: HTMLElement, binding: DirectiveBinding): 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/app/plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue b/app/plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue
new file mode 100644
index 000000000..548a69740
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/SiteSelector/AllSitesLink.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/SiteSelector/Site.ts b/app/plugins/CoreHome/vue/src/SiteSelector/Site.ts
new file mode 100644
index 000000000..ee3d818db
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/SiteSelector/SiteRef.ts b/app/plugins/CoreHome/vue/src/SiteSelector/SiteRef.ts
new file mode 100644
index 000000000..f827f804a
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.adapter.ts b/app/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.adapter.ts
new file mode 100644
index 000000000..a29f6c4a1
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/angularjs/siteselector/siteselector.directive.less b/app/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.less
similarity index 100%
rename from app/plugins/CoreHome/angularjs/siteselector/siteselector.directive.less
rename to app/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.less
diff --git a/app/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue b/app/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue
new file mode 100644
index 000000000..5d115f813
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/SiteSelector/SiteSelector.vue
@@ -0,0 +1,378 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/SiteSelector/SitesStore.adapter.ts b/app/plugins/CoreHome/vue/src/SiteSelector/SitesStore.adapter.ts
new file mode 100644
index 000000000..c454d6062
--- /dev/null
+++ b/app/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) => cloneThenApply(
+ SitesStore.searchSite(...args),
+ ),
+ };
+}
+
+window.angular.module('piwikApp.service').factory('siteSelectorModel', siteSelectorModelAdapter);
diff --git a/app/plugins/CoreHome/vue/src/SiteSelector/SitesStore.ts b/app/plugins/CoreHome/vue/src/SiteSelector/SitesStore.ts
new file mode 100644
index 000000000..4a45b3779
--- /dev/null
+++ b/app/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;
+ isInitialized: boolean;
+}
+
+class SitesStore {
+ private state = reactive({
+ initialSites: [],
+ isInitialized: false,
+ });
+
+ private currentRequestAbort: AbortController | null = null;
+
+ private limitRequest?: Promise<{ value: number|string }>;
+
+ public readonly initialSites = computed(() => readonly(this.state.initialSites));
+
+ loadInitialSites(): Promise|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|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/app/plugins/CoreHome/vue/src/Sparkline/Sparkline.adapter.ts b/app/plugins/CoreHome/vue/src/Sparkline/Sparkline.adapter.ts
new file mode 100644
index 000000000..70dacd306
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/angularjs/sparkline/sparkline.component.less b/app/plugins/CoreHome/vue/src/Sparkline/Sparkline.less
similarity index 100%
rename from app/plugins/CoreHome/angularjs/sparkline/sparkline.component.less
rename to app/plugins/CoreHome/vue/src/Sparkline/Sparkline.less
diff --git a/app/plugins/CoreHome/vue/src/Sparkline/Sparkline.vue b/app/plugins/CoreHome/vue/src/Sparkline/Sparkline.vue
new file mode 100644
index 000000000..37f9008d0
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/Sparkline/Sparkline.vue
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/Tooltips/Tooltips.ts b/app/plugins/CoreHome/vue/src/Tooltips/Tooltips.ts
new file mode 100644
index 000000000..b5cb0010a
--- /dev/null
+++ b/app/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, ' '));
+}
+
+function setupTooltips(el: HTMLElement, binding: DirectiveBinding) {
+ $(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): void {
+ setTimeout(() => setupTooltips(el, binding));
+ },
+ updated(el: HTMLElement, binding: DirectiveBinding): void {
+ setTimeout(() => setupTooltips(el, binding));
+ },
+ beforeUnmount(el: HTMLElement): void {
+ try {
+ window.$(el).tooltip('destroy');
+ } catch (e) {
+ // ignore
+ }
+ },
+};
diff --git a/app/plugins/CoreHome/vue/src/Widget/Widget.adapter.ts b/app/plugins/CoreHome/vue/src/Widget/Widget.adapter.ts
new file mode 100644
index 000000000..c33934c04
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/Widget/Widget.vue b/app/plugins/CoreHome/vue/src/Widget/Widget.vue
new file mode 100644
index 000000000..720970109
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/Widget/Widget.vue
@@ -0,0 +1,187 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/Widget/Widgets.store.ts b/app/plugins/CoreHome/vue/src/Widget/Widgets.store.ts
new file mode 100644
index 000000000..0ef76bee1
--- /dev/null
+++ b/app/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;
+}
+
+export function getWidgetChildren(widget: Widget): Widget[] {
+ const container = widget as WidgetContainer;
+ if (container.widgets) {
+ return container.widgets;
+ }
+ return [];
+}
+
+class WidgetsStore {
+ private privateState = reactive({
+ isFetchedFirstTime: false,
+ categorizedWidgets: {},
+ });
+
+ private state = computed((): DeepReadonly => {
+ 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 {
+ // 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) => {
+ const casted = widgets as unknown as Record;
+ this.privateState.categorizedWidgets = casted;
+ resolve(this.widgets.value);
+ });
+ } catch (e) {
+ reject(e);
+ }
+ });
+ }
+
+ reloadAvailableWidgets(): Promise {
+ 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/app/plugins/CoreHome/vue/src/Widget/types.ts b/app/plugins/CoreHome/vue/src/Widget/types.ts
new file mode 100644
index 000000000..598fe567b
--- /dev/null
+++ b/app/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;
+ subcategory?: Subcategory;
+ isContainer?: boolean;
+ isReport?: boolean;
+ middlewareParameters?: Record;
+ 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/app/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.adapter.ts b/app/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.adapter.ts
new file mode 100644
index 000000000..7f3f2bfb6
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.less b/app/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.less
similarity index 98%
rename from app/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.less
rename to app/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.less
index 7f2e4844f..9f8f6cce9 100644
--- a/app/plugins/CoreHome/angularjs/widget-bydimension-container/widget-bydimension-container.directive.less
+++ b/app/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/app/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue b/app/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue
new file mode 100644
index 000000000..60e87a342
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/WidgetByDimensionContainer/WidgetByDimensionContainer.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+ {{ category.name }}
+
+
+ {{ widget.name }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.adapter.ts b/app/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.adapter.ts
new file mode 100644
index 000000000..3a8a71482
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue b/app/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue
new file mode 100644
index 000000000..5f294cbc0
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/WidgetContainer/WidgetContainer.vue
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.adapter.ts b/app/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.adapter.ts
new file mode 100644
index 000000000..9ec44f317
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue b/app/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue
new file mode 100644
index 000000000..7b42c8ab1
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/WidgetLoader/WidgetLoader.vue
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CoreHome/vue/src/createAngularJsAdapter.ts b/app/plugins/CoreHome/vue/src/createAngularJsAdapter.ts
index b28ee95d3..e6b7b22d5 100644
--- a/app/plugins/CoreHome/vue/src/createAngularJsAdapter.ts
+++ b/app/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 {
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 = {
+ [scopeVarName: string]: SingleScopeVarInfo,
+};
-type AdapterFunction = (
- scope: ng.IScope,
+type AdapterFunction = (
+ scope: any,
element: ng.IAugmentedJQuery,
attrs: ng.IAttributes,
- ...injected: InjectTypes,
+ ...injected: InjectTypes
) => R;
-type EventAdapterFunction = (
- $event: any, // eslint-disable-line
- scope: ng.IScope,
+type EventAdapterFunction = (
+ $event: any,
+ vm: any,
+ scope: any,
element: ng.IAugmentedJQuery,
attrs: ng.IAttributes,
- ...injected: InjectTypes,
+ otherController?: ng.IController,
+ ...injected: InjectTypes
) => R;
-type PostCreateFunction = (
- vm: ComponentPublicInstance,
- scope: ng.IScope,
+type PostCreateFunction = (
+ vm: any,
+ scope: any,
element: ng.IAugmentedJQuery,
attrs: ng.IAttributes,
- ...injected: InjectTypes,
+ otherController?: ng.IController,
+ ...injected: InjectTypes
) => R;
-type EventMapping = { [vueEventName: string]: EventAdapterFunction };
+type EventMapping = {
+ [vueEventName: string]: EventAdapterFunction,
+};
type ComponentType = ReturnType;
@@ -61,9 +79,21 @@ function toAngularJsCamelCase(arg: string): string {
.replace(/-([a-z])/g, (s, p) => p.toUpperCase());
}
-export default function createAngularJsAdapter(options: {
+export function removeAngularJsSpecificProperties(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(options: {
component: ComponentType,
- scope?: ScopeMapping,
+ require?: string,
+ scope?: ScopeMapping,
directiveName: string,
events?: EventMapping,
$inject?: string[],
@@ -72,9 +102,12 @@ export default function createAngularJsAdapter(options: {
postCreate?: PostCreateFunction,
noScope?: boolean,
restrict?: string,
-}): ng.IDirectiveFactory {
+ priority?: number,
+ replace?: boolean,
+}): Injectable {
const {
component,
+ require,
scope = {},
events = {},
$inject,
@@ -84,6 +117,8 @@ export default function createAngularJsAdapter(options: {
postCreate,
noScope,
restrict = 'A',
+ priority,
+ replace,
} = options;
const currentTranscludeCounter = transcludeCounter;
@@ -91,7 +126,8 @@ export default function createAngularJsAdapter(options: {
transcludeCounter += 1;
}
- const angularJsScope = {};
+ const vueToAngular: Record = {};
+ const angularJsScope: Record = {};
Object.entries(scope).forEach(([scopeVarName, info]) => {
if (!info.vue) {
info.vue = scopeVarName;
@@ -99,35 +135,41 @@ export default function createAngularJsAdapter(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 = ' {
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(options: {
rootVueTemplate += ' ';
// build the vue app
- const app = createApp({
+ const app = createVueApp({
template: rootVueTemplate,
data() {
- const initialData = {};
+ const initialData: Record = {};
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(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(options: {
angularJsAdapter.$inject = $inject || [];
- angular.module('piwikApp').directive(directiveName, angularJsAdapter);
+ window.angular.module('piwikApp').directive(
+ directiveName,
+ angularJsAdapter as unknown as Injectable,
+ );
+
+ return angularJsAdapter as unknown as Injectable;
+}
+
+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(p: T): T {
+ if (typeof p === 'undefined') {
+ return p;
+ }
+
+ return JSON.parse(JSON.stringify(p)) as T;
+}
- return angularJsAdapter;
+export function cloneThenApply(p: T): T {
+ const result = clone(p);
+ Matomo.helper.getAngularDependency('$rootScope').$applyAsync();
+ return result;
}
diff --git a/app/plugins/CoreHome/vue/src/createVueApp.ts b/app/plugins/CoreHome/vue/src/createVueApp.ts
new file mode 100644
index 000000000..65caca525
--- /dev/null
+++ b/app/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
+): ReturnType {
+ 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/app/plugins/CoreHome/vue/src/debounce.ts b/app/plugins/CoreHome/vue/src/debounce.ts
new file mode 100644
index 000000000..7a5e2f5af
--- /dev/null
+++ b/app/plugins/CoreHome/vue/src/debounce.ts
@@ -0,0 +1,18 @@
+const DEFAULT_DEBOUNCE_DELAY = 300;
+
+export default function debounce(
+ fn: (this: This, ...args: Args) => void,
+ delayInMs = DEFAULT_DEBOUNCE_DELAY,
+): (this: This, ...args: Args) => void {
+ let timeout: ReturnType;
+
+ return function wrapper(this: This, ...args: Args): void {
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+
+ timeout = setTimeout(() => {
+ fn.call(this, ...args);
+ }, delayInMs);
+ };
+}
diff --git a/app/plugins/CoreHome/vue/src/directiveUtilities.ts b/app/plugins/CoreHome/vue/src/directiveUtilities.ts
new file mode 100644
index 000000000..4ca073fca
--- /dev/null
+++ b/app/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(expander: string | HTMLElement, binding: DirectiveBinding): HTMLElement|null {
+ return expander instanceof HTMLElement
+ ? expander
+ : binding.instance?.$refs[expander] as HTMLElement;
+}
+
+export default {
+ getRef,
+};
diff --git a/app/plugins/CoreHome/vue/src/getFormattedEvolution.ts b/app/plugins/CoreHome/vue/src/getFormattedEvolution.ts
new file mode 100644
index 000000000..84b8e57de
--- /dev/null
+++ b/app/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/app/plugins/CoreHome/vue/src/index.ts b/app/plugins/CoreHome/vue/src/index.ts
index baaada6b9..27fad8fc9 100644
--- a/app/plugins/CoreHome/vue/src/index.ts
+++ b/app/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/app/plugins/CoreHome/vue/src/translate.ts b/app/plugins/CoreHome/vue/src/translate.ts
index 317b5a875..37f9184bf 100644
--- a/app/plugins/CoreHome/vue/src/translate.ts
+++ b/app/plugins/CoreHome/vue/src/translate.ts
@@ -5,14 +5,35 @@
* @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[])[]
): string {
+ if (!translationStringId) {
+ return '';
+ }
+
let pkArgs = values as string[];
// 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 as string[][];
}
return window._pk_translate(translationStringId, pkArgs); // eslint-disable-line
}
+
+export function translateOrDefault(
+ translationStringIdOrText?: string,
+ ...values: (string|string[])[]
+): string {
+ if (!translationStringIdOrText || !window.piwik_translations[translationStringIdOrText]) {
+ return translationStringIdOrText!;
+ }
+
+ let pkArgs = values as string[];
+ // handle variadic args AND single array of values (to match _pk_translate signature)
+ if (values.length === 1 && values[0] && Array.isArray(values[0])) {
+ [pkArgs] = values as string[][];
+ }
+
+ return window._pk_translate(translationStringIdOrText, pkArgs); // eslint-disable-line
+}
diff --git a/app/plugins/CoreHome/vue/src/useExternalPluginComponent.ts b/app/plugins/CoreHome/vue/src/useExternalPluginComponent.ts
new file mode 100644
index 000000000..0829c348d
--- /dev/null
+++ b/app/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
+ }
+ });
+ })));
+}
diff --git a/app/plugins/CorePluginsAdmin/API.php b/app/plugins/CorePluginsAdmin/API.php
index dede5afc0..203b88b81 100644
--- a/app/plugins/CorePluginsAdmin/API.php
+++ b/app/plugins/CorePluginsAdmin/API.php
@@ -12,7 +12,6 @@
use Piwik\Plugin\SettingsProvider;
use Exception;
use Piwik\Plugins\Login\PasswordVerifier;
-use Piwik\Version;
use Piwik\Container\StaticContainer;
use Piwik\Plugins\CoreAdminHome\Emails\SettingsChangedEmail;
use Piwik\Plugins\CoreAdminHome\Emails\SecurityNotificationEmail;
diff --git a/app/plugins/CorePluginsAdmin/Controller.php b/app/plugins/CorePluginsAdmin/Controller.php
index a6b7ae104..4104e6837 100644
--- a/app/plugins/CorePluginsAdmin/Controller.php
+++ b/app/plugins/CorePluginsAdmin/Controller.php
@@ -13,7 +13,6 @@
use Piwik\API\Request;
use Piwik\Common;
use Piwik\Container\StaticContainer;
-use Piwik\ErrorHandler;
use Piwik\Exception\MissingFilePermissionException;
use Piwik\Filechecks;
use Piwik\Filesystem;
@@ -26,7 +25,6 @@
use Piwik\Plugins\Marketplace\Marketplace;
use Piwik\Plugins\Marketplace\Controller as MarketplaceController;
use Piwik\Plugins\Marketplace\Plugins;
-use Piwik\Settings\Storage\Backend\PluginSettingsTable;
use Piwik\SettingsPiwik;
use Piwik\SettingsServer;
use Piwik\Translation\Translator;
diff --git a/app/plugins/CorePluginsAdmin/CorePluginsAdmin.php b/app/plugins/CorePluginsAdmin/CorePluginsAdmin.php
index aeef54b2d..3a08314a5 100644
--- a/app/plugins/CorePluginsAdmin/CorePluginsAdmin.php
+++ b/app/plugins/CorePluginsAdmin/CorePluginsAdmin.php
@@ -13,6 +13,9 @@
use Piwik\Plugin;
use Piwik\Plugins\CoreHome\SystemSummary;
use Piwik\Plugins\CorePluginsAdmin\Model\TagManagerTeaser;
+use Piwik\Changes\Model as ChangesModel;
+use Piwik\Db;
+use Piwik\Plugin\Manager as PluginManager;
class CorePluginsAdmin extends Plugin
{
@@ -26,10 +29,35 @@ public function registerEvents()
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'System.addSystemSummaryItems' => 'addSystemSummaryItems',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
- 'PluginManager.pluginActivated' => 'onPluginActivated'
+ 'PluginManager.pluginActivated' => 'onPluginActivated',
+ 'PluginManager.pluginInstalled' => 'addPluginChanges',
+ 'Updater.componentUpdated' => 'addPluginChanges',
+ 'PluginManager.pluginUninstalled' => 'removePluginChanges'
);
}
+ /**
+ * Add any changes from newly installed or updated plugins to the changes table
+ *
+ * @param string $pluginName The name of the plugin that was updated or installed
+ */
+ public function addPluginChanges(string $pluginName)
+ {
+ $changes = new ChangesModel(Db::get(), PluginManager::getInstance());
+ $changes->addChanges($pluginName);
+ }
+
+ /**
+ * Remove any changes from a plugin that has been uninstalled
+ *
+ * @param string $pluginName The name of the plugin that was uninstalled
+ */
+ public function removePluginChanges(string $pluginName)
+ {
+ $changes = new ChangesModel(Db::get(), PluginManager::getInstance());
+ $changes->removeChanges($pluginName);
+ }
+
public function onPluginActivated($pluginName)
{
if ($pluginName === 'TagManager') {
@@ -48,9 +76,10 @@ public function addSystemSummaryItems(&$systemSummary)
public function getStylesheetFiles(&$stylesheets)
{
$stylesheets[] = "plugins/CorePluginsAdmin/stylesheets/plugins_admin.less";
- $stylesheets[] = "plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.less";
- $stylesheets[] = "plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.less";
- $stylesheets[] = "plugins/CorePluginsAdmin/angularjs/form-field/field-multituple.less";
+ $stylesheets[] = "plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.less";
+ $stylesheets[] = "plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.less";
+ $stylesheets[] = "plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.less";
+ $stylesheets[] = "plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.less";
}
public static function isPluginsAdminEnabled()
diff --git a/app/plugins/CorePluginsAdmin/Menu.php b/app/plugins/CorePluginsAdmin/Menu.php
index be90fca29..cce08378e 100644
--- a/app/plugins/CorePluginsAdmin/Menu.php
+++ b/app/plugins/CorePluginsAdmin/Menu.php
@@ -12,7 +12,6 @@
use Piwik\Menu\MenuAdmin;
use Piwik\Menu\MenuTop;
use Piwik\Piwik;
-use Piwik\Plugin;
use Piwik\Plugins\CorePluginsAdmin\Model\TagManagerTeaser;
use Piwik\Plugins\Marketplace\Marketplace;
use Piwik\Plugins\Marketplace\Plugins;
diff --git a/app/plugins/CorePluginsAdmin/SettingsMetadata.php b/app/plugins/CorePluginsAdmin/SettingsMetadata.php
index 0b1e6723f..ce9647256 100644
--- a/app/plugins/CorePluginsAdmin/SettingsMetadata.php
+++ b/app/plugins/CorePluginsAdmin/SettingsMetadata.php
@@ -113,7 +113,7 @@ public function formatSetting(Setting $setting)
$availableValues = (object) $availableValues;
}
- return array(
+ $result = array(
'name' => $setting->getName(),
'title' => $config->title,
'value' => $setting->getValue(),
@@ -124,10 +124,17 @@ public function formatSetting(Setting $setting)
'availableValues' => $availableValues,
'description' => $config->description,
'inlineHelp' => $config->inlineHelp,
+ // deprecated but kept here for API output BC
'templateFile' => $config->customUiControlTemplateFile,
'introduction' => $config->introduction,
'condition' => $config->condition,
);
+
+ if ($config->customFieldComponent) {
+ $result['component'] = $config->customFieldComponent;
+ }
+
+ return $result;
}
}
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/field/field.directive.html b/app/plugins/CorePluginsAdmin/angularjs/field/field.directive.html
deleted file mode 100644
index 8e9906571..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/field/field.directive.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
- {{ field.myProperty }}
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-checkbox-array.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-checkbox-array.html
deleted file mode 100644
index eff2f55ba..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-checkbox-array.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
{{ formField.title }}
-
-
-
- {{ checkboxModel.value }}
-
- {{ checkboxModel.description }}
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-checkbox.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-checkbox.html
deleted file mode 100644
index 9ea7d9904..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-checkbox.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.html
deleted file mode 100644
index d9f07888a..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- {{ options.group }}
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-field-array.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-field-array.html
deleted file mode 100644
index 8c0f0cf99..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-field-array.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-file.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-file.html
deleted file mode 100644
index b784b4a91..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-file.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-hidden.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-hidden.html
deleted file mode 100644
index d7bb77112..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-hidden.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-multiselect.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-multiselect.html
deleted file mode 100644
index 4f3a173b7..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-multiselect.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-multituple.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-multituple.html
deleted file mode 100644
index 4c7670e43..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-multituple.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-number.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-number.html
deleted file mode 100644
index 9866ab034..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-number.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-radio.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-radio.html
deleted file mode 100644
index 13f93090a..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-radio.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
{{ formField.title }}
-
-
-
-
-
- {{ radioModel.value }}
- {{ radioModel.description }}
-
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-select.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-select.html
deleted file mode 100644
index 41a9a34cf..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-select.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-site.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-site.html
deleted file mode 100644
index 009869ee0..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-site.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-text-array.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-text-array.html
deleted file mode 100644
index 2a127da5c..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-text-array.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-text.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-text.html
deleted file mode 100644
index 34076620d..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-text.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-textarea-array.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-textarea-array.html
deleted file mode 100644
index f65c49cc2..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-textarea-array.html
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-textarea.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/field-textarea.html
deleted file mode 100644
index 97d0b2748..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-textarea.html
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.html b/app/plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.html
deleted file mode 100644
index 86acb985a..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/form-field/form-field.directive.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
diff --git a/app/plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.html b/app/plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.html
deleted file mode 100644
index 4e082e94b..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.html
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
{{ settings.title }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{:: 'UsersManager_ConfirmWithPassword'|translate }}
-
-
-
-
-
-
-
diff --git a/app/plugins/CorePluginsAdmin/angularjs/save-button/save-button.directive.html b/app/plugins/CorePluginsAdmin/angularjs/save-button/save-button.directive.html
deleted file mode 100644
index 61dc11128..000000000
--- a/app/plugins/CorePluginsAdmin/angularjs/save-button/save-button.directive.html
+++ /dev/null
@@ -1,8 +0,0 @@
-
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/config/test.php b/app/plugins/CorePluginsAdmin/config/test.php
deleted file mode 100644
index 04726f428..000000000
--- a/app/plugins/CorePluginsAdmin/config/test.php
+++ /dev/null
@@ -1,19 +0,0 @@
- DI\add(array(
- array('Request.dispatchCoreAndPluginUpdatesScreen', \DI\value(function () {
- $pluginName = 'TagManager';
- $unloadTagManager = \Piwik\Container\StaticContainer::get('test.vars.unloadTagManager');
- $tagManagerTeaser = new \Piwik\Plugins\CorePluginsAdmin\Model\TagManagerTeaser(\Piwik\Piwik::getCurrentUserLogin());
- if ($unloadTagManager) {
- $pluginManager = \Piwik\Plugin\Manager::getInstance();
- if ($pluginManager->isPluginActivated($pluginName)
- && $pluginManager->isPluginLoaded($pluginName)) {
- $pluginManager->unloadPlugin($pluginName);
- }
- $tagManagerTeaser->reset();
- }
- })),
- ))
-);
diff --git a/app/plugins/CorePluginsAdmin/lang/ga.json b/app/plugins/CorePluginsAdmin/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.js b/app/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.js
new file mode 100644
index 000000000..61e6b8e88
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.js
@@ -0,0 +1,3427 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("CoreHome"), require("vue"));
+ else if(typeof define === 'function' && define.amd)
+ define(["CoreHome", ], factory);
+ else if(typeof exports === 'object')
+ exports["CorePluginsAdmin"] = factory(require("CoreHome"), require("vue"));
+ else
+ root["CorePluginsAdmin"] = factory(root["CoreHome"], root["Vue"]);
+})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "plugins/CorePluginsAdmin/vue/dist/";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "fae3");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "19dc":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;
+
+/***/ }),
+
+/***/ "8bbf":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;
+
+/***/ }),
+
+/***/ "fae3":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, "FormField", function() { return /* reexport */ FormField; });
+__webpack_require__.d(__webpack_exports__, "Field", function() { return /* reexport */ Field; });
+__webpack_require__.d(__webpack_exports__, "PluginSettings", function() { return /* reexport */ PluginSettings; });
+__webpack_require__.d(__webpack_exports__, "PluginFilter", function() { return /* reexport */ PluginFilter; });
+__webpack_require__.d(__webpack_exports__, "PluginManagement", function() { return /* reexport */ PluginManagement; });
+__webpack_require__.d(__webpack_exports__, "PluginUpload", function() { return /* reexport */ PluginUpload; });
+__webpack_require__.d(__webpack_exports__, "SaveButton", function() { return /* reexport */ SaveButton; });
+__webpack_require__.d(__webpack_exports__, "Form", function() { return /* reexport */ Form; });
+__webpack_require__.d(__webpack_exports__, "GroupedSettings", function() { return /* reexport */ GroupedSettings; });
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
+// This file is imported into lib/wc client bundles.
+
+if (typeof window !== 'undefined') {
+ var currentScript = window.document.currentScript
+ if (false) { var getCurrentScript; }
+
+ var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
+ if (src) {
+ __webpack_require__.p = src[1] // eslint-disable-line
+ }
+}
+
+// Indicate to webpack that this file can be concatenated
+/* harmony default export */ var setPublicPath = (null);
+
+// EXTERNAL MODULE: external "CoreHome"
+var external_CoreHome_ = __webpack_require__("19dc");
+
+// EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"}
+var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf");
+
+// 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/CorePluginsAdmin/vue/src/FormField/FormField.vue?vue&type=template&id=b3ece69c
+
+var _hoisted_1 = {
+ class: "form-group row matomo-form-field"
+};
+var _hoisted_2 = {
+ key: 0,
+ class: "col s12"
+};
+var _hoisted_3 = {
+ key: 0,
+ class: "form-help"
+};
+var _hoisted_4 = {
+ key: 0,
+ class: "inline-help",
+ ref: "inlineHelp"
+};
+
+var _hoisted_5 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+function 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, [_ctx.formField.introduction ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("h3", _hoisted_2, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.formField.introduction), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["col s12", {
+ 'input-field': _ctx.formField.uiControl !== 'checkbox' && _ctx.formField.uiControl !== 'radio',
+ 'file-field': _ctx.formField.uiControl === 'file',
+ 'm6': !_ctx.formField.fullWidth
+ }])
+ }, [(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDynamicComponent"])(_ctx.childComponent), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])(Object.assign(Object.assign({
+ formField: _ctx.formField
+ }, _ctx.formField), {}, {
+ modelValue: _ctx.processedModelValue,
+ availableOptions: _ctx.availableOptions
+ }, _ctx.extraChildComponentParams), {
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ })
+ }), null, 16))], 2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["col s12", {
+ 'm6': !_ctx.formField.fullWidth
+ }])
+ }, [_ctx.showFormHelp ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ class: "form-description"
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.formField.description), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.formField.description]]), _ctx.formField.inlineHelp || _ctx.hasInlineHelpSlot ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", _hoisted_4, [_ctx.inlineHelpComponent ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDynamicComponent"])(_ctx.inlineHelpComponent), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeProps"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ key: 0
+ }, _ctx.inlineHelpBind)), null, 16)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "inline-help")], 512)) : 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", null, [_hoisted_5, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Default')) + ": ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.defaultValuePrettyTruncated), 1)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showDefaultValue]])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 2)], 512)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showField]]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FormField.vue?vue&type=template&id=b3ece69c
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldCheckbox.vue?vue&type=template&id=c04f97ea
+
+var FieldCheckboxvue_type_template_id_c04f97ea_hoisted_1 = {
+ class: "checkbox"
+};
+var FieldCheckboxvue_type_template_id_c04f97ea_hoisted_2 = ["checked", "id", "name"];
+var FieldCheckboxvue_type_template_id_c04f97ea_hoisted_3 = ["innerHTML"];
+function FieldCheckboxvue_type_template_id_c04f97ea_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", FieldCheckboxvue_type_template_id_c04f97ea_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ onChange: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ })
+ }, _ctx.uiControlAttributes, {
+ value: 1,
+ checked: _ctx.isChecked,
+ type: "checkbox",
+ id: _ctx.name,
+ name: _ctx.name
+ }), null, 16, FieldCheckboxvue_type_template_id_c04f97ea_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldCheckboxvue_type_template_id_c04f97ea_hoisted_3)])]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckbox.vue?vue&type=template&id=c04f97ea
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldCheckbox.vue?vue&type=script&lang=ts
+
+/* harmony default export */ var FieldCheckboxvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ modelValue: [Boolean, Number, String],
+ uiControlAttributes: Object,
+ name: String,
+ title: String
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ methods: {
+ onChange: function onChange(event) {
+ if (this.modelValue !== event.target.checked) {
+ this.$emit('update:modelValue', event.target.checked);
+ }
+ }
+ },
+ computed: {
+ isChecked: function isChecked() {
+ return !!this.modelValue && this.modelValue !== '0';
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckbox.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckbox.vue
+
+
+
+FieldCheckboxvue_type_script_lang_ts.render = FieldCheckboxvue_type_template_id_c04f97ea_render
+
+/* harmony default export */ var FieldCheckbox = (FieldCheckboxvue_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/CorePluginsAdmin/vue/src/FormField/FieldCheckboxArray.vue?vue&type=template&id=b01b8bfc
+
+var FieldCheckboxArrayvue_type_template_id_b01b8bfc_hoisted_1 = ["value", "checked", "onChange", "id", "name"];
+function FieldCheckboxArrayvue_type_template_id_b01b8bfc_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", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ class: "fieldRadioTitle"
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.title), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.title]]), (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.availableOptions, function (checkboxModel, $index) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
+ key: $index,
+ class: "checkbox"
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ value: checkboxModel.key,
+ checked: !!_ctx.checkboxStates[$index],
+ onChange: function onChange($event) {
+ return _ctx.onChange($index);
+ }
+ }, _ctx.uiControlAttributes, {
+ type: "checkbox",
+ id: "".concat(_ctx.name).concat(checkboxModel.key),
+ name: checkboxModel.name
+ }), null, 16, FieldCheckboxArrayvue_type_template_id_b01b8bfc_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(checkboxModel.value), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: "form-description"
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(checkboxModel.description), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], checkboxModel.description]])])]);
+ }), 128))]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckboxArray.vue?vue&type=template&id=b01b8bfc
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldCheckboxArray.vue?vue&type=script&lang=ts
+function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
+
+function _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 _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _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 _arrayLikeToArray(o, minLen); }
+
+function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
+
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
+
+function _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 getCheckboxStates(availableOptions, modelValue) {
+ return (availableOptions || []).map(function (o) {
+ return modelValue && modelValue.indexOf(o.key) !== -1;
+ });
+}
+
+/* harmony default export */ var FieldCheckboxArrayvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ modelValue: Array,
+ name: String,
+ title: String,
+ availableOptions: Array,
+ uiControlAttributes: Object,
+ type: String
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ computed: {
+ checkboxStates: function checkboxStates() {
+ return getCheckboxStates(this.availableOptions, this.modelValue);
+ }
+ },
+ mounted: function mounted() {
+ window.Materialize.updateTextFields();
+ },
+ methods: {
+ onChange: function onChange(changedIndex) {
+ var checkboxStates = _toConsumableArray(this.checkboxStates);
+
+ checkboxStates[changedIndex] = !checkboxStates[changedIndex];
+ var availableOptions = this.availableOptions || {};
+ var newValue = [];
+ Object.values(availableOptions).forEach(function (option, index) {
+ if (checkboxStates[index]) {
+ newValue.push(option.key);
+ }
+ });
+ this.$emit('update:modelValue', newValue);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckboxArray.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckboxArray.vue
+
+
+
+FieldCheckboxArrayvue_type_script_lang_ts.render = FieldCheckboxArrayvue_type_template_id_b01b8bfc_render
+
+/* harmony default export */ var FieldCheckboxArray = (FieldCheckboxArrayvue_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/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.vue?vue&type=template&id=c33fad48
+
+var FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_1 = {
+ class: "expandableSelector"
+};
+
+var FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_2 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("svg", {
+ class: "caret",
+ height: "24",
+ viewBox: "0 0 24 24",
+ width: "24",
+ xmlns: "http://www.w3.org/2000/svg"
+}, [/*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("path", {
+ d: "M7 10l5 5 5-5z"
+}), /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("path", {
+ d: "M0 0h24v24H0z",
+ fill: "none"
+})], -1);
+
+var FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_3 = ["value"];
+var FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_4 = {
+ class: "expandableList z-depth-2"
+};
+var FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_5 = {
+ class: "searchContainer"
+};
+var _hoisted_6 = {
+ class: "collection firstLevel"
+};
+var _hoisted_7 = ["onClick"];
+var _hoisted_8 = {
+ class: "collection secondLevel"
+};
+var _hoisted_9 = ["onClick"];
+var _hoisted_10 = {
+ class: "primary-content"
+};
+var _hoisted_11 = ["title"];
+function FieldExpandableSelectvue_type_template_id_c33fad48_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", FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ onClick: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.showSelect = !_ctx.showSelect;
+ }),
+ class: "select-wrapper"
+ }, [FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_2, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "text",
+ class: "select-dropdown",
+ readonly: "readonly",
+ value: _ctx.modelValueText
+ }, null, 8, FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_3)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FieldExpandableSelectvue_type_template_id_c33fad48_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "text",
+ placeholder: "Search",
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.searchTerm = $event;
+ }),
+ class: "expandableSearch browser-default"
+ }, null, 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.searchTerm], [_directive_focus_if, _ctx.showSelect]])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", _hoisted_6, [(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.availableOptions, function (options, 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: "collection-item",
+ key: index
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h4", {
+ class: "expandableListCategory",
+ onClick: function onClick($event) {
+ return _ctx.onCategoryClicked(options);
+ }
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(options.group) + " ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["secondary-content", {
+ "icon-arrow-right": _ctx.showCategory !== options.group,
+ "icon-arrow-bottom": _ctx.showCategory === options.group
+ }])
+ }, null, 2)], 8, _hoisted_7), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("ul", _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"])(options.values.filter(function (x) {
+ return x.value.toLowerCase().indexOf(_ctx.searchTerm.toLowerCase()) !== -1;
+ }), function (children) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("li", {
+ class: "expandableListItem collection-item valign-wrapper",
+ key: children.key,
+ onClick: function onClick($event) {
+ return _ctx.onValueClicked(children);
+ }
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", _hoisted_10, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(children.value), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ title: children.tooltip,
+ class: "secondary-content icon-help"
+ }, null, 8, _hoisted_11), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], children.tooltip]])], 8, _hoisted_9);
+ }), 128))], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showCategory === options.group || _ctx.searchTerm]])], 512)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], options.values.filter(function (x) {
+ return x.value.toLowerCase().indexOf(_ctx.searchTerm.toLowerCase()) !== -1;
+ }).length]]);
+ }), 128))])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showSelect]])], 512)), [[_directive_focus_anywhere_but_here, {
+ blur: _ctx.onBlur
+ }]]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.vue?vue&type=template&id=c33fad48
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.vue?vue&type=script&lang=ts
+
+
+function getAvailableOptions(availableValues) {
+ var flatValues = [];
+
+ if (!availableValues) {
+ return flatValues;
+ }
+
+ var groups = {};
+ Object.values(availableValues).forEach(function (uncastedValue) {
+ var value = uncastedValue;
+ var group = value.group || '';
+
+ if (!(group in groups) || !groups[group]) {
+ groups[group] = {
+ values: [],
+ group: group
+ };
+ }
+
+ var formatted = {
+ key: value.key,
+ value: value.value
+ };
+
+ if ('tooltip' in value && value.tooltip) {
+ formatted.tooltip = value.tooltip;
+ }
+
+ groups[group].values.push(formatted);
+ });
+ Object.values(groups).forEach(function (group) {
+ if (group.values.length) {
+ flatValues.push(group);
+ }
+ });
+ return flatValues;
+}
+/* harmony default export */ var FieldExpandableSelectvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ modelValue: [Number, String],
+ availableOptions: Array,
+ title: String
+ },
+ directives: {
+ FocusAnywhereButHere: external_CoreHome_["FocusAnywhereButHere"],
+ FocusIf: external_CoreHome_["FocusIf"]
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ data: function data() {
+ return {
+ showSelect: false,
+ searchTerm: '',
+ showCategory: ''
+ };
+ },
+ computed: {
+ modelValueText: function modelValueText() {
+ if (this.title) {
+ return this.title;
+ }
+
+ var key = this.modelValue;
+ var availableOptions = this.availableOptions || [];
+ var keyItem;
+ availableOptions.some(function (option) {
+ keyItem = option.values.find(function (item) {
+ return item.key === key;
+ });
+ return keyItem; // stop iterating if found
+ });
+
+ if (keyItem) {
+ return keyItem.value ? "".concat(keyItem.value) : '';
+ }
+
+ return key ? "".concat(key) : '';
+ }
+ },
+ methods: {
+ onBlur: function onBlur() {
+ this.showSelect = false;
+ },
+ onCategoryClicked: function onCategoryClicked(options) {
+ if (this.showCategory === options.group) {
+ this.showCategory = '';
+ } else {
+ this.showCategory = options.group;
+ }
+ },
+ onValueClicked: function onValueClicked(selectedValue) {
+ this.$emit('update:modelValue', selectedValue.key);
+ this.showSelect = false;
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.vue
+
+
+
+FieldExpandableSelectvue_type_script_lang_ts.render = FieldExpandableSelectvue_type_template_id_c33fad48_render
+
+/* harmony default export */ var FieldExpandableSelect = (FieldExpandableSelectvue_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/CorePluginsAdmin/vue/src/FormField/FieldFieldArray.vue?vue&type=template&id=19925759
+
+var FieldFieldArrayvue_type_template_id_19925759_hoisted_1 = ["for", "innerHTML"];
+function FieldFieldArrayvue_type_template_id_19925759_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_FieldArray = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("FieldArray");
+
+ 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"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldFieldArrayvue_type_template_id_19925759_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_FieldArray, {
+ name: _ctx.name,
+ "model-value": _ctx.modelValue,
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onValueUpdate($event);
+ }),
+ field: _ctx.uiControlAttributes.field
+ }, null, 8, ["name", "model-value", "field"])]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldFieldArray.vue?vue&type=template&id=19925759
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldFieldArray.vue?vue&type=script&lang=ts
+
+
+/* harmony default export */ var FieldFieldArrayvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ components: {
+ FieldArray: external_CoreHome_["FieldArray"]
+ },
+ props: {
+ name: String,
+ title: String,
+ modelValue: null,
+ uiControlAttributes: Object
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ methods: {
+ onValueUpdate: function onValueUpdate(newValue) {
+ this.$emit('update:modelValue', newValue);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldFieldArray.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldFieldArray.vue
+
+
+
+FieldFieldArrayvue_type_script_lang_ts.render = FieldFieldArrayvue_type_template_id_19925759_render
+
+/* harmony default export */ var FieldFieldArray = (FieldFieldArrayvue_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/CorePluginsAdmin/vue/src/FormField/FieldFile.vue?vue&type=template&id=2c0fffb5
+
+var FieldFilevue_type_template_id_2c0fffb5_hoisted_1 = {
+ class: "btn"
+};
+var FieldFilevue_type_template_id_2c0fffb5_hoisted_2 = ["for", "innerHTML"];
+var FieldFilevue_type_template_id_2c0fffb5_hoisted_3 = ["name", "id"];
+var FieldFilevue_type_template_id_2c0fffb5_hoisted_4 = {
+ class: "file-path-wrapper"
+};
+var FieldFilevue_type_template_id_2c0fffb5_hoisted_5 = ["value"];
+function FieldFilevue_type_template_id_2c0fffb5_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", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FieldFilevue_type_template_id_2c0fffb5_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldFilevue_type_template_id_2c0fffb5_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ ref: "fileInput",
+ name: _ctx.name,
+ type: "file",
+ id: _ctx.name,
+ onChange: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ })
+ }, null, 40, FieldFilevue_type_template_id_2c0fffb5_hoisted_3)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FieldFilevue_type_template_id_2c0fffb5_hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ class: "file-path validate",
+ value: _ctx.filePath,
+ type: "text"
+ }, null, 8, FieldFilevue_type_template_id_2c0fffb5_hoisted_5)])]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldFile.vue?vue&type=template&id=2c0fffb5
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldFile.vue?vue&type=script&lang=ts
+
+/* harmony default export */ var FieldFilevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ name: String,
+ title: String,
+ modelValue: [String, File]
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ watch: {
+ modelValue: function modelValue(v) {
+ if (!v || v === '') {
+ var fileInputElement = this.$refs.fileInput;
+ fileInputElement.value = '';
+ }
+ }
+ },
+ methods: {
+ onChange: function onChange(event) {
+ var files = event.target.files;
+
+ if (!files) {
+ return;
+ }
+
+ var file = files.item(0);
+ this.$emit('update:modelValue', file);
+ }
+ },
+ computed: {
+ filePath: function filePath() {
+ if (this.modelValue instanceof File) {
+ return this.$refs.fileInput.value;
+ }
+
+ return undefined;
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldFile.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldFile.vue
+
+
+
+FieldFilevue_type_script_lang_ts.render = FieldFilevue_type_template_id_2c0fffb5_render
+
+/* harmony default export */ var FieldFile = (FieldFilevue_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/CorePluginsAdmin/vue/src/FormField/FieldHidden.vue?vue&type=template&id=20e3ce54
+
+var FieldHiddenvue_type_template_id_20e3ce54_hoisted_1 = ["type", "name", "value"];
+function FieldHiddenvue_type_template_id_20e3ce54_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", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: _ctx.uiControl,
+ name: _ctx.name,
+ value: _ctx.modelValue,
+ onChange: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ })
+ }, null, 40, FieldHiddenvue_type_template_id_20e3ce54_hoisted_1)]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldHidden.vue?vue&type=template&id=20e3ce54
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldHidden.vue?vue&type=script&lang=ts
+
+/* harmony default export */ var FieldHiddenvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ modelValue: null,
+ uiControl: String,
+ name: String
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ methods: {
+ onChange: function onChange(event) {
+ this.$emit('update:modelValue', event.target.value);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldHidden.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldHidden.vue
+
+
+
+FieldHiddenvue_type_script_lang_ts.render = FieldHiddenvue_type_template_id_20e3ce54_render
+
+/* harmony default export */ var FieldHidden = (FieldHiddenvue_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/CorePluginsAdmin/vue/src/FormField/FieldMultituple.vue?vue&type=template&id=7469c188
+
+var FieldMultituplevue_type_template_id_7469c188_hoisted_1 = {
+ class: "fieldMultiTuple"
+};
+var FieldMultituplevue_type_template_id_7469c188_hoisted_2 = ["for", "innerHTML"];
+function FieldMultituplevue_type_template_id_7469c188_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_MultiPairField = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("MultiPairField");
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FieldMultituplevue_type_template_id_7469c188_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldMultituplevue_type_template_id_7469c188_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_MultiPairField, {
+ name: _ctx.name,
+ "model-value": _ctx.modelValue,
+ "onUpdate:modelValue": _ctx.onUpdateValue,
+ field1: _ctx.uiControlAttributes.field1,
+ field2: _ctx.uiControlAttributes.field2,
+ field3: _ctx.uiControlAttributes.field3,
+ field4: _ctx.uiControlAttributes.field4
+ }, null, 8, ["name", "model-value", "onUpdate:modelValue", "field1", "field2", "field3", "field4"])]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.vue?vue&type=template&id=7469c188
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldMultituple.vue?vue&type=script&lang=ts
+
+
+/* harmony default export */ var FieldMultituplevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ name: String,
+ title: String,
+ modelValue: null,
+ uiControlAttributes: Object
+ },
+ inheritAttrs: false,
+ components: {
+ MultiPairField: external_CoreHome_["MultiPairField"]
+ },
+ emits: ['update:modelValue'],
+ methods: {
+ onUpdateValue: function onUpdateValue(newValue) {
+ this.$emit('update:modelValue', newValue);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.vue
+
+
+
+FieldMultituplevue_type_script_lang_ts.render = FieldMultituplevue_type_template_id_7469c188_render
+
+/* harmony default export */ var FieldMultituple = (FieldMultituplevue_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/CorePluginsAdmin/vue/src/FormField/FieldNumber.vue?vue&type=template&id=7aed93b6
+
+var FieldNumbervue_type_template_id_7aed93b6_hoisted_1 = ["type", "id", "name", "value"];
+var FieldNumbervue_type_template_id_7aed93b6_hoisted_2 = ["for", "innerHTML"];
+function FieldNumbervue_type_template_id_7aed93b6_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"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ class: "control_".concat(_ctx.uiControl),
+ type: _ctx.uiControl,
+ id: _ctx.name,
+ name: _ctx.name,
+ value: (_ctx.modelValue || '').toString(),
+ onKeydown: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ }),
+ onChange: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.onChange($event);
+ })
+ }, _ctx.uiControlAttributes), null, 16, FieldNumbervue_type_template_id_7aed93b6_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldNumbervue_type_template_id_7aed93b6_hoisted_2)], 64);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldNumber.vue?vue&type=template&id=7aed93b6
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldNumber.vue?vue&type=script&lang=ts
+
+
+/* harmony default export */ var FieldNumbervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ uiControl: String,
+ name: String,
+ title: String,
+ modelValue: [Number, String],
+ uiControlAttributes: Object
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ created: function created() {
+ this.onChange = Object(external_CoreHome_["debounce"])(this.onChange.bind(this), 50);
+ },
+ methods: {
+ onChange: function onChange(event) {
+ var value = parseFloat(event.target.value);
+ this.$emit('update:modelValue', value);
+ }
+ },
+ mounted: function mounted() {
+ window.Materialize.updateTextFields();
+ },
+ watch: {
+ modelValue: function modelValue() {
+ setTimeout(function () {
+ window.Materialize.updateTextFields();
+ });
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldNumber.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldNumber.vue
+
+
+
+FieldNumbervue_type_script_lang_ts.render = FieldNumbervue_type_template_id_7aed93b6_render
+
+/* harmony default export */ var FieldNumber = (FieldNumbervue_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/CorePluginsAdmin/vue/src/FormField/FieldRadio.vue?vue&type=template&id=e73c5bb0
+
+var FieldRadiovue_type_template_id_e73c5bb0_hoisted_1 = ["value", "id", "name", "disabled", "checked"];
+function FieldRadiovue_type_template_id_e73c5bb0_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", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ class: "fieldRadioTitle"
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.title), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.title]]), (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.availableOptions || [], function (radioModel) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
+ key: radioModel.key,
+ class: "radio"
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ value: radioModel.key,
+ onChange: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ }),
+ type: "radio",
+ id: "".concat(_ctx.name).concat(radioModel.key),
+ name: _ctx.name,
+ disabled: radioModel.disabled || _ctx.disabled
+ }, _ctx.uiControlAttributes, {
+ checked: _ctx.modelValue === radioModel.key || "".concat(_ctx.modelValue) === radioModel.key
+ }), null, 16, FieldRadiovue_type_template_id_e73c5bb0_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(radioModel.value) + " ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: "form-description"
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(radioModel.description), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], radioModel.description]])])])]);
+ }), 128))]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldRadio.vue?vue&type=template&id=e73c5bb0
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldRadio.vue?vue&type=script&lang=ts
+
+/* harmony default export */ var FieldRadiovue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ title: String,
+ availableOptions: Array,
+ name: String,
+ disabled: Boolean,
+ uiControlAttributes: Object,
+ modelValue: [String, Number]
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ methods: {
+ onChange: function onChange(event) {
+ this.$emit('update:modelValue', event.target.value);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldRadio.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldRadio.vue
+
+
+
+FieldRadiovue_type_script_lang_ts.render = FieldRadiovue_type_template_id_e73c5bb0_render
+
+/* harmony default export */ var FieldRadio = (FieldRadiovue_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/CorePluginsAdmin/vue/src/FormField/FieldSelect.vue?vue&type=template&id=65cce678
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || FieldSelectvue_type_template_id_65cce678_unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
+
+function _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 FieldSelectvue_type_template_id_65cce678_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return FieldSelectvue_type_template_id_65cce678_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 FieldSelectvue_type_template_id_65cce678_arrayLikeToArray(o, minLen); }
+
+function FieldSelectvue_type_template_id_65cce678_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 _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 _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+
+var FieldSelectvue_type_template_id_65cce678_hoisted_1 = {
+ key: 0,
+ class: "matomo-field-select"
+};
+var FieldSelectvue_type_template_id_65cce678_hoisted_2 = ["multiple", "name"];
+var FieldSelectvue_type_template_id_65cce678_hoisted_3 = ["label"];
+var FieldSelectvue_type_template_id_65cce678_hoisted_4 = ["value", "selected", "disabled"];
+var FieldSelectvue_type_template_id_65cce678_hoisted_5 = ["for", "innerHTML"];
+var FieldSelectvue_type_template_id_65cce678_hoisted_6 = {
+ key: 1,
+ class: "matomo-field-select"
+};
+var FieldSelectvue_type_template_id_65cce678_hoisted_7 = ["multiple", "name"];
+var FieldSelectvue_type_template_id_65cce678_hoisted_8 = ["value", "selected", "disabled"];
+var FieldSelectvue_type_template_id_65cce678_hoisted_9 = ["for", "innerHTML"];
+function FieldSelectvue_type_template_id_65cce678_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"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, [_ctx.groupedOptions ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FieldSelectvue_type_template_id_65cce678_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("select", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ ref: "select",
+ class: "grouped",
+ multiple: _ctx.multiple,
+ name: _ctx.name,
+ onChange: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ })
+ }, _ctx.uiControlAttributes), [(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.groupedOptions, function (_ref) {
+ var _ref2 = _slicedToArray(_ref, 2),
+ group = _ref2[0],
+ options = _ref2[1];
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("optgroup", {
+ key: group,
+ label: group
+ }, [(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"])(options, function (option) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("option", {
+ key: option.key,
+ value: "string:".concat(option.key),
+ selected: _ctx.multiple ? _ctx.modelValue && _ctx.modelValue.indexOf(option.key) !== -1 : _ctx.modelValue === option.key,
+ disabled: option.disabled
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(option.value), 9, FieldSelectvue_type_template_id_65cce678_hoisted_4);
+ }), 128))], 8, FieldSelectvue_type_template_id_65cce678_hoisted_3);
+ }), 128))], 16, FieldSelectvue_type_template_id_65cce678_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldSelectvue_type_template_id_65cce678_hoisted_5)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !_ctx.groupedOptions && _ctx.options ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FieldSelectvue_type_template_id_65cce678_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("select", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ class: "ungrouped",
+ ref: "select",
+ multiple: _ctx.multiple,
+ name: _ctx.name,
+ onChange: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.onChange($event);
+ })
+ }, _ctx.uiControlAttributes), [(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.options, function (option) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("option", {
+ key: option.key,
+ value: "string:".concat(option.key),
+ selected: _ctx.multiple ? _ctx.modelValue && _ctx.modelValue.indexOf(option.key) !== -1 : _ctx.modelValue === option.key,
+ disabled: option.disabled
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(option.value), 9, FieldSelectvue_type_template_id_65cce678_hoisted_8);
+ }), 128))], 16, FieldSelectvue_type_template_id_65cce678_hoisted_7), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldSelectvue_type_template_id_65cce678_hoisted_9)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 64);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.vue?vue&type=template&id=65cce678
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldSelect.vue?vue&type=script&lang=ts
+function FieldSelectvue_type_script_lang_ts_toConsumableArray(arr) { return FieldSelectvue_type_script_lang_ts_arrayWithoutHoles(arr) || FieldSelectvue_type_script_lang_ts_iterableToArray(arr) || FieldSelectvue_type_script_lang_ts_unsupportedIterableToArray(arr) || FieldSelectvue_type_script_lang_ts_nonIterableSpread(); }
+
+function FieldSelectvue_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 FieldSelectvue_type_script_lang_ts_iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
+
+function FieldSelectvue_type_script_lang_ts_arrayWithoutHoles(arr) { if (Array.isArray(arr)) return FieldSelectvue_type_script_lang_ts_arrayLikeToArray(arr); }
+
+function FieldSelectvue_type_script_lang_ts_slicedToArray(arr, i) { return FieldSelectvue_type_script_lang_ts_arrayWithHoles(arr) || FieldSelectvue_type_script_lang_ts_iterableToArrayLimit(arr, i) || FieldSelectvue_type_script_lang_ts_unsupportedIterableToArray(arr, i) || FieldSelectvue_type_script_lang_ts_nonIterableRest(); }
+
+function FieldSelectvue_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 FieldSelectvue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return FieldSelectvue_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 FieldSelectvue_type_script_lang_ts_arrayLikeToArray(o, minLen); }
+
+function FieldSelectvue_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 FieldSelectvue_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 FieldSelectvue_type_script_lang_ts_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+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 initMaterialSelect(select, modelValue, placeholder) {
+ var uiControlOptions = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
+ var multiple = arguments.length > 4 ? arguments[4] : undefined;
+
+ if (!select) {
+ return;
+ }
+
+ var $select = window.$(select); // reset selected since materialize removes them
+
+ Array.from(select.options).forEach(function (opt) {
+ if (multiple) {
+ opt.selected = !!modelValue && modelValue.indexOf(opt.value.replace(/^string:/, '')) !== -1;
+ } else {
+ opt.selected = "string:".concat(modelValue) === opt.value;
+ }
+ });
+ $select.formSelect(uiControlOptions); // add placeholder to input
+
+ if (placeholder) {
+ var $materialInput = $select.closest('.select-wrapper').find('input');
+ $materialInput.attr('placeholder', placeholder);
+ }
+}
+
+function hasGroupedValues(availableValues) {
+ if (Array.isArray(availableValues) || !(_typeof(availableValues) === 'object')) {
+ return false;
+ }
+
+ return Object.values(availableValues).some(function (v) {
+ return _typeof(v) === 'object';
+ });
+}
+
+function hasOption(flatValues, key) {
+ return flatValues.some(function (f) {
+ return f.key === key;
+ });
+}
+
+function FieldSelectvue_type_script_lang_ts_getAvailableOptions(givenAvailableValues, type, uiControlAttributes) {
+ if (!givenAvailableValues) {
+ return [];
+ }
+
+ var hasGroups = true;
+ var availableValues = givenAvailableValues;
+
+ if (!hasGroupedValues(availableValues)) {
+ availableValues = {
+ '': givenAvailableValues
+ };
+ hasGroups = false;
+ }
+
+ var flatValues = [];
+ Object.entries(availableValues).forEach(function (_ref) {
+ var _ref2 = FieldSelectvue_type_script_lang_ts_slicedToArray(_ref, 2),
+ group = _ref2[0],
+ values = _ref2[1];
+
+ Object.entries(values).forEach(function (_ref3) {
+ var _ref4 = FieldSelectvue_type_script_lang_ts_slicedToArray(_ref3, 2),
+ valueObjKey = _ref4[0],
+ value = _ref4[1];
+
+ if (value && _typeof(value) === 'object' && typeof value.key !== 'undefined') {
+ flatValues.push(value);
+ return;
+ }
+
+ var key = valueObjKey;
+
+ if (type === 'integer' && typeof valueObjKey === 'string') {
+ key = parseInt(valueObjKey, 10);
+ }
+
+ flatValues.push({
+ group: hasGroups ? group : undefined,
+ key: key,
+ value: value
+ });
+ });
+ }); // for selects w/ a placeholder, add an option to unset the select
+
+ if (uiControlAttributes !== null && uiControlAttributes !== void 0 && uiControlAttributes.placeholder && !hasOption(flatValues, '')) {
+ return [{
+ key: '',
+ value: ''
+ }].concat(flatValues);
+ }
+
+ return flatValues;
+}
+
+function handleOldAngularJsValues(value) {
+ if (typeof value === 'string') {
+ return value.replace(/^string:/, '');
+ }
+
+ return value;
+}
+
+/* harmony default export */ var FieldSelectvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ modelValue: null,
+ multiple: Boolean,
+ name: String,
+ title: String,
+ availableOptions: Array,
+ uiControlAttributes: Object,
+ uiControlOptions: Object
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ computed: {
+ options: function options() {
+ // if modelValue is empty, but there is no empty value allowed in availableOptions,
+ // add one temporarily until something is set
+ var availableOptions = this.availableOptions;
+
+ if (availableOptions && !hasOption(availableOptions, '') && (typeof this.modelValue === 'undefined' || this.modelValue === null || this.modelValue === '')) {
+ return [{
+ key: '',
+ value: this.modelValue,
+ group: this.hasGroups ? '' : undefined
+ }].concat(FieldSelectvue_type_script_lang_ts_toConsumableArray(availableOptions));
+ }
+
+ return availableOptions;
+ },
+ hasGroups: function hasGroups() {
+ var availableOptions = this.availableOptions;
+ return availableOptions && availableOptions[0] && typeof availableOptions[0].group !== 'undefined';
+ },
+ groupedOptions: function groupedOptions() {
+ var options = this.options;
+
+ if (!this.hasGroups || !options) {
+ return null;
+ }
+
+ var groups = {};
+ options.forEach(function (entry) {
+ var group = entry.group;
+ groups[group] = groups[group] || [];
+ groups[group].push(entry);
+ });
+ var result = Object.entries(groups);
+ result.sort(function (lhs, rhs) {
+ if (lhs[0] < rhs[0]) {
+ return -1;
+ }
+
+ if (lhs[0] > rhs[0]) {
+ return 1;
+ }
+
+ return 0;
+ });
+ return result;
+ }
+ },
+ methods: {
+ onChange: function onChange(event) {
+ var _this = this;
+
+ var element = event.target;
+ var newValue;
+
+ if (this.multiple) {
+ newValue = Array.from(element.options).filter(function (e) {
+ return e.selected;
+ }).map(function (e) {
+ return e.value;
+ });
+ newValue = newValue.map(function (x) {
+ return handleOldAngularJsValues(x);
+ });
+ } else {
+ newValue = element.value;
+ newValue = handleOldAngularJsValues(newValue);
+ }
+
+ this.$emit('update:modelValue', newValue); // if modelValue does not change, select will still have the changed value, but we
+ // want it to have the value determined by modelValue. so we force an update.
+
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ if (_this.modelValue !== newValue) {
+ _this.onModelValueChange(_this.modelValue);
+ }
+ });
+ },
+ onModelValueChange: function onModelValueChange(newVal) {
+ var _this2 = this;
+
+ window.$(this.$refs.select).val(newVal);
+ setTimeout(function () {
+ var _this2$uiControlAttri;
+
+ initMaterialSelect(_this2.$refs.select, newVal, (_this2$uiControlAttri = _this2.uiControlAttributes) === null || _this2$uiControlAttri === void 0 ? void 0 : _this2$uiControlAttri.placeholder, _this2.uiControlOptions, _this2.multiple);
+ });
+ }
+ },
+ watch: {
+ modelValue: function modelValue(newVal) {
+ this.onModelValueChange(newVal);
+ },
+ 'uiControlAttributes.disabled': {
+ handler: function handler(newVal, oldVal) {
+ var _this3 = this;
+
+ setTimeout(function () {
+ if (newVal !== oldVal) {
+ var _this3$uiControlAttri;
+
+ initMaterialSelect(_this3.$refs.select, _this3.modelValue, (_this3$uiControlAttri = _this3.uiControlAttributes) === null || _this3$uiControlAttri === void 0 ? void 0 : _this3$uiControlAttri.placeholder, _this3.uiControlOptions, _this3.multiple);
+ }
+ });
+ }
+ },
+ availableOptions: function availableOptions(newVal, oldVal) {
+ var _this4 = this;
+
+ if (newVal !== oldVal) {
+ setTimeout(function () {
+ var _this4$uiControlAttri;
+
+ initMaterialSelect(_this4.$refs.select, _this4.modelValue, (_this4$uiControlAttri = _this4.uiControlAttributes) === null || _this4$uiControlAttri === void 0 ? void 0 : _this4$uiControlAttri.placeholder, _this4.uiControlOptions, _this4.multiple);
+ });
+ }
+ }
+ },
+ mounted: function mounted() {
+ var _this5 = this;
+
+ setTimeout(function () {
+ var _this5$uiControlAttri;
+
+ initMaterialSelect(_this5.$refs.select, _this5.modelValue, (_this5$uiControlAttri = _this5.uiControlAttributes) === null || _this5$uiControlAttri === void 0 ? void 0 : _this5$uiControlAttri.placeholder, _this5.uiControlOptions, _this5.multiple);
+ });
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.vue
+
+
+
+FieldSelectvue_type_script_lang_ts.render = FieldSelectvue_type_template_id_65cce678_render
+
+/* harmony default export */ var FieldSelect = (FieldSelectvue_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/CorePluginsAdmin/vue/src/FormField/FieldSite.vue?vue&type=template&id=50ac73cc
+
+var FieldSitevue_type_template_id_50ac73cc_hoisted_1 = ["for", "innerHTML"];
+var FieldSitevue_type_template_id_50ac73cc_hoisted_2 = {
+ class: "sites_autocomplete"
+};
+function FieldSitevue_type_template_id_50ac73cc_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_SiteSelector = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("SiteSelector");
+
+ 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"])("label", {
+ for: _ctx.name,
+ class: "siteSelectorLabel",
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldSitevue_type_template_id_50ac73cc_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FieldSitevue_type_template_id_50ac73cc_hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_SiteSelector, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ "model-value": _ctx.modelValue,
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ }),
+ id: _ctx.name,
+ "show-all-sites-item": _ctx.uiControlAttributes.showAllSitesItem || false,
+ "switch-site-on-select": false,
+ "show-selected-site": true,
+ "only-sites-with-admin-access": _ctx.uiControlAttributes.onlySitesWithAdminAccess || false
+ }, _ctx.uiControlAttributes), null, 16, ["model-value", "id", "show-all-sites-item", "only-sites-with-admin-access"])])]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldSite.vue?vue&type=template&id=50ac73cc
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldSite.vue?vue&type=script&lang=ts
+
+
+/* harmony default export */ var FieldSitevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ name: String,
+ title: String,
+ modelValue: Object,
+ uiControlAttributes: Object
+ },
+ inheritAttrs: false,
+ components: {
+ SiteSelector: external_CoreHome_["SiteSelector"]
+ },
+ emits: ['update:modelValue'],
+ methods: {
+ onChange: function onChange(newValue) {
+ this.$emit('update:modelValue', newValue);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldSite.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldSite.vue
+
+
+
+FieldSitevue_type_script_lang_ts.render = FieldSitevue_type_template_id_50ac73cc_render
+
+/* harmony default export */ var FieldSite = (FieldSitevue_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/CorePluginsAdmin/vue/src/FormField/FieldText.vue?vue&type=template&id=c95daad6
+
+var FieldTextvue_type_template_id_c95daad6_hoisted_1 = ["type", "id", "name", "value"];
+var FieldTextvue_type_template_id_c95daad6_hoisted_2 = ["for", "innerHTML"];
+function FieldTextvue_type_template_id_c95daad6_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"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ class: "control_".concat(_ctx.uiControl),
+ type: _ctx.uiControl,
+ id: _ctx.name,
+ name: _ctx.name,
+ value: _ctx.modelValueText,
+ onKeydown: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onKeydown($event);
+ }),
+ onChange: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.onKeydown($event);
+ })
+ }, _ctx.uiControlAttributes), null, 16, FieldTextvue_type_template_id_c95daad6_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldTextvue_type_template_id_c95daad6_hoisted_2)], 64);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldText.vue?vue&type=template&id=c95daad6
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldText.vue?vue&type=script&lang=ts
+
+
+/* harmony default export */ var FieldTextvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ title: String,
+ name: String,
+ uiControlAttributes: Object,
+ modelValue: [String, Number],
+ uiControl: String
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ computed: {
+ modelValueText: function modelValueText() {
+ if (typeof this.modelValue === 'undefined' || this.modelValue === null) {
+ return '';
+ }
+
+ return this.modelValue.toString();
+ }
+ },
+ created: function created() {
+ // debounce because puppeteer types reeaally fast
+ this.onKeydown = Object(external_CoreHome_["debounce"])(this.onKeydown.bind(this), 50);
+ },
+ mounted: function mounted() {
+ setTimeout(function () {
+ window.Materialize.updateTextFields();
+ });
+ },
+ watch: {
+ modelValue: function modelValue() {
+ setTimeout(function () {
+ window.Materialize.updateTextFields();
+ });
+ }
+ },
+ methods: {
+ onKeydown: function onKeydown(event) {
+ var newValue = event.target.value;
+
+ if (this.modelValue !== newValue) {
+ this.$emit('update:modelValue', newValue);
+ }
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldText.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldText.vue
+
+
+
+FieldTextvue_type_script_lang_ts.render = FieldTextvue_type_template_id_c95daad6_render
+
+/* harmony default export */ var FieldText = (FieldTextvue_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/CorePluginsAdmin/vue/src/FormField/FieldTextArray.vue?vue&type=template&id=32e13f4c
+
+var FieldTextArrayvue_type_template_id_32e13f4c_hoisted_1 = ["for", "innerHTML"];
+var FieldTextArrayvue_type_template_id_32e13f4c_hoisted_2 = ["type", "name", "value"];
+function FieldTextArrayvue_type_template_id_32e13f4c_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", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldTextArrayvue_type_template_id_32e13f4c_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ class: "control_".concat(_ctx.uiControl),
+ type: _ctx.uiControl,
+ name: _ctx.name,
+ onKeydown: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onKeydown($event);
+ }),
+ onChange: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.onKeydown($event);
+ }),
+ value: _ctx.concattedValues
+ }, _ctx.uiControlAttributes), null, 16, FieldTextArrayvue_type_template_id_32e13f4c_hoisted_2)]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextArray.vue?vue&type=template&id=32e13f4c
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldTextArray.vue?vue&type=script&lang=ts
+
+
+/* harmony default export */ var FieldTextArrayvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ name: String,
+ title: String,
+ uiControl: String,
+ modelValue: Array,
+ uiControlAttributes: Object
+ },
+ inheritAttrs: false,
+ computed: {
+ concattedValues: function concattedValues() {
+ if (typeof this.modelValue === 'string') {
+ return this.modelValue;
+ }
+
+ return (this.modelValue || []).join(', ');
+ }
+ },
+ emits: ['update:modelValue'],
+ created: function created() {
+ // debounce because puppeteer types reeaally fast
+ this.onKeydown = Object(external_CoreHome_["debounce"])(this.onKeydown.bind(this), 50);
+ },
+ methods: {
+ onKeydown: function onKeydown(event) {
+ var values = event.target.value.split(',').map(function (v) {
+ return v.trim();
+ });
+
+ if (values.join(', ') !== this.concattedValues) {
+ this.$emit('update:modelValue', values);
+ }
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextArray.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextArray.vue
+
+
+
+FieldTextArrayvue_type_script_lang_ts.render = FieldTextArrayvue_type_template_id_32e13f4c_render
+
+/* harmony default export */ var FieldTextArray = (FieldTextArrayvue_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/CorePluginsAdmin/vue/src/FormField/FieldTextarea.vue?vue&type=template&id=09f09fdb
+
+var FieldTextareavue_type_template_id_09f09fdb_hoisted_1 = ["name", "id", "value"];
+var FieldTextareavue_type_template_id_09f09fdb_hoisted_2 = ["for", "innerHTML"];
+function FieldTextareavue_type_template_id_09f09fdb_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"])(external_commonjs_vue_commonjs2_vue_root_Vue_["Fragment"], null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("textarea", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ name: _ctx.name
+ }, _ctx.uiControlAttributes, {
+ id: _ctx.name,
+ value: _ctx.modelValue,
+ onKeydown: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onKeydown($event);
+ }),
+ onChange: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.onKeydown($event);
+ }),
+ class: "materialize-textarea",
+ ref: "textarea"
+ }), null, 16, FieldTextareavue_type_template_id_09f09fdb_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldTextareavue_type_template_id_09f09fdb_hoisted_2)], 64);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextarea.vue?vue&type=template&id=09f09fdb
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldTextarea.vue?vue&type=script&lang=ts
+
+
+/* harmony default export */ var FieldTextareavue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ name: String,
+ uiControlAttributes: Object,
+ modelValue: String,
+ title: String
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ created: function created() {
+ this.onKeydown = Object(external_CoreHome_["debounce"])(this.onKeydown.bind(this), 50);
+ },
+ methods: {
+ onKeydown: function onKeydown(event) {
+ this.$emit('update:modelValue', event.target.value);
+ }
+ },
+ watch: {
+ modelValue: function modelValue() {
+ var _this = this;
+
+ setTimeout(function () {
+ window.Materialize.textareaAutoResize(_this.$refs.textarea);
+ window.Materialize.updateTextFields();
+ });
+ }
+ },
+ mounted: function mounted() {
+ var _this2 = this;
+
+ setTimeout(function () {
+ window.Materialize.textareaAutoResize(_this2.$refs.textarea);
+ window.Materialize.updateTextFields();
+ });
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextarea.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextarea.vue
+
+
+
+FieldTextareavue_type_script_lang_ts.render = FieldTextareavue_type_template_id_09f09fdb_render
+
+/* harmony default export */ var FieldTextarea = (FieldTextareavue_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/CorePluginsAdmin/vue/src/FormField/FieldTextareaArray.vue?vue&type=template&id=46a970e4
+
+var FieldTextareaArrayvue_type_template_id_46a970e4_hoisted_1 = ["for", "innerHTML"];
+var FieldTextareaArrayvue_type_template_id_46a970e4_hoisted_2 = ["name", "value"];
+function FieldTextareaArrayvue_type_template_id_46a970e4_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", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("label", {
+ for: _ctx.name,
+ innerHTML: _ctx.$sanitize(_ctx.title)
+ }, null, 8, FieldTextareaArrayvue_type_template_id_46a970e4_hoisted_1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("textarea", Object(external_commonjs_vue_commonjs2_vue_root_Vue_["mergeProps"])({
+ ref: "textarea",
+ name: _ctx.name
+ }, _ctx.uiControlAttributes, {
+ value: _ctx.concattedValue,
+ onKeydown: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onKeydown($event);
+ }),
+ onChange: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.onKeydown($event);
+ }),
+ class: "materialize-textarea"
+ }), null, 16, FieldTextareaArrayvue_type_template_id_46a970e4_hoisted_2)]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextareaArray.vue?vue&type=template&id=46a970e4
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldTextareaArray.vue?vue&type=script&lang=ts
+
+
+var SEPARATOR = '\n';
+/* harmony default export */ var FieldTextareaArrayvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ name: String,
+ title: String,
+ uiControlAttributes: Object,
+ modelValue: [Array, String]
+ },
+ inheritAttrs: false,
+ emits: ['update:modelValue'],
+ computed: {
+ concattedValue: function concattedValue() {
+ if (typeof this.modelValue === 'string') {
+ return this.modelValue;
+ }
+
+ return (this.modelValue || []).join(SEPARATOR);
+ }
+ },
+ created: function created() {
+ this.onKeydown = Object(external_CoreHome_["debounce"])(this.onKeydown.bind(this), 50);
+ },
+ methods: {
+ onKeydown: function onKeydown(event) {
+ var value = event.target.value.split(SEPARATOR);
+
+ if (value.join(SEPARATOR) !== this.concattedValue) {
+ this.$emit('update:modelValue', value);
+ }
+ }
+ },
+ watch: {
+ modelValue: function modelValue(newVal, oldVal) {
+ var _this = this;
+
+ if (newVal !== oldVal) {
+ setTimeout(function () {
+ if (_this.$refs.textarea) {
+ window.Materialize.textareaAutoResize(_this.$refs.textarea);
+ }
+
+ window.Materialize.updateTextFields();
+ });
+ }
+ }
+ },
+ mounted: function mounted() {
+ var _this2 = this;
+
+ setTimeout(function () {
+ if (_this2.$refs.textarea) {
+ window.Materialize.textareaAutoResize(_this2.$refs.textarea);
+ }
+
+ window.Materialize.updateTextFields();
+ });
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextareaArray.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldTextareaArray.vue
+
+
+
+FieldTextareaArrayvue_type_script_lang_ts.render = FieldTextareaArrayvue_type_template_id_46a970e4_render
+
+/* harmony default export */ var FieldTextareaArray = (FieldTextareaArrayvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/utilities.ts
+function utilities_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { utilities_typeof = function _typeof(obj) { return typeof obj; }; } else { utilities_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return utilities_typeof(obj); }
+
+function utilities_slicedToArray(arr, i) { return utilities_arrayWithHoles(arr) || utilities_iterableToArrayLimit(arr, i) || utilities_unsupportedIterableToArray(arr, i) || utilities_nonIterableRest(); }
+
+function utilities_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 utilities_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return utilities_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 utilities_arrayLikeToArray(o, minLen); }
+
+function utilities_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 utilities_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 utilities_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
+ */
+function processCheckboxAndRadioAvailableValues(availableValues, type) {
+ if (!availableValues) {
+ return [];
+ }
+
+ var flatValues = [];
+ Object.entries(availableValues).forEach(function (_ref) {
+ var _ref2 = utilities_slicedToArray(_ref, 2),
+ valueObjKey = _ref2[0],
+ value = _ref2[1];
+
+ if (value && utilities_typeof(value) === 'object' && typeof value.key !== 'undefined') {
+ flatValues.push(value);
+ return;
+ }
+
+ var key = valueObjKey;
+
+ if (type === 'integer' && typeof valueObjKey === 'string') {
+ key = parseInt(key, 10);
+ }
+
+ flatValues.push({
+ key: key,
+ value: value
+ });
+ });
+ return flatValues;
+}
+// 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/CorePluginsAdmin/vue/src/FormField/FieldAngularJsTemplate.vue?vue&type=template&id=3f63d972
+
+var FieldAngularJsTemplatevue_type_template_id_3f63d972_hoisted_1 = {
+ ref: "root"
+};
+function FieldAngularJsTemplatevue_type_template_id_3f63d972_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", FieldAngularJsTemplatevue_type_template_id_3f63d972_hoisted_1, null, 512);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldAngularJsTemplate.vue?vue&type=template&id=3f63d972
+
+// 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/CorePluginsAdmin/vue/src/FormField/FieldAngularJsTemplate.vue?vue&type=script&lang=ts
+
+
+
+function clone(obj) {
+ if (typeof obj === 'undefined') {
+ return undefined;
+ }
+
+ return JSON.parse(JSON.stringify(obj));
+}
+
+/* harmony default export */ var FieldAngularJsTemplatevue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ modelValue: null,
+ formField: {
+ type: null,
+ required: true
+ },
+ templateFile: {
+ type: String,
+ required: true
+ }
+ },
+ emits: ['update:modelValue'],
+ inheritAttrs: false,
+ setup: function setup(props, context) {
+ var root = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(null);
+ var $element = window.$("
"));
+ var $timeout = external_CoreHome_["Matomo"].helper.getAngularDependency('$timeout');
+ var $rootScope = external_CoreHome_["Matomo"].helper.getAngularDependency('$rootScope');
+ var scope = $rootScope.$new();
+ scope.formField = Object.assign(Object.assign({}, clone(props.formField)), {}, {
+ value: clone(props.modelValue)
+ });
+ scope.$watch('formField.value', function (newValue, oldValue) {
+ if (newValue !== oldValue && JSON.stringify(newValue) !== JSON.stringify(props.modelValue)) {
+ context.emit('update:modelValue', clone(newValue));
+ }
+ });
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () {
+ return props.modelValue;
+ }, function (newValue) {
+ if (JSON.stringify(newValue) !== JSON.stringify(scope.formField.value)) {
+ $timeout(function () {
+ scope.formField.value = newValue;
+ });
+ }
+ });
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () {
+ return props.formField;
+ }, function (newValue) {
+ $timeout(function () {
+ var currentValue = scope.formField.value;
+ scope.formField = Object.assign(Object.assign({}, clone(newValue)), {}, {
+ value: currentValue
+ });
+ });
+ }, {
+ deep: true
+ }); // append on mount
+
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["onMounted"])(function () {
+ window.$(root.value).append($element);
+ external_CoreHome_["Matomo"].helper.compileAngularComponents($element, {
+ scope: scope,
+ params: {
+ formField: Object.assign(Object.assign({}, clone(props.formField)), {}, {
+ value: props.modelValue
+ })
+ }
+ });
+ });
+ return {
+ root: root
+ };
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldAngularJsTemplate.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FieldAngularJsTemplate.vue
+
+
+
+FieldAngularJsTemplatevue_type_script_lang_ts.render = FieldAngularJsTemplatevue_type_template_id_3f63d972_render
+
+/* harmony default export */ var FieldAngularJsTemplate = (FieldAngularJsTemplatevue_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/CorePluginsAdmin/vue/src/FormField/FormField.vue?vue&type=script&lang=ts
+function FormFieldvue_type_script_lang_ts_typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { FormFieldvue_type_script_lang_ts_typeof = function _typeof(obj) { return typeof obj; }; } else { FormFieldvue_type_script_lang_ts_typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return FormFieldvue_type_script_lang_ts_typeof(obj); }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+var TEXT_CONTROLS = ['password', 'url', 'search', 'email'];
+var CONTROLS_SUPPORTING_ARRAY = ['textarea', 'checkbox', 'text'];
+var CONTROL_TO_COMPONENT_MAP = {
+ checkbox: 'FieldCheckbox',
+ 'expandable-select': 'FieldExpandableSelect',
+ 'field-array': 'FieldFieldArray',
+ file: 'FieldFile',
+ hidden: 'FieldHidden',
+ multiselect: 'FieldSelect',
+ multituple: 'FieldMultituple',
+ number: 'FieldNumber',
+ radio: 'FieldRadio',
+ select: 'FieldSelect',
+ site: 'FieldSite',
+ text: 'FieldText',
+ textarea: 'FieldTextarea'
+};
+var CONTROL_TO_AVAILABLE_OPTION_PROCESSOR = {
+ FieldSelect: FieldSelectvue_type_script_lang_ts_getAvailableOptions,
+ FieldCheckboxArray: processCheckboxAndRadioAvailableValues,
+ FieldRadio: processCheckboxAndRadioAvailableValues,
+ FieldExpandableSelect: getAvailableOptions
+};
+/* harmony default export */ var FormFieldvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ modelValue: null,
+ formField: {
+ type: Object,
+ required: true
+ }
+ },
+ emits: ['update:modelValue'],
+ components: {
+ FieldCheckbox: FieldCheckbox,
+ FieldCheckboxArray: FieldCheckboxArray,
+ FieldExpandableSelect: FieldExpandableSelect,
+ FieldFieldArray: FieldFieldArray,
+ FieldFile: FieldFile,
+ FieldHidden: FieldHidden,
+ FieldMultituple: FieldMultituple,
+ FieldNumber: FieldNumber,
+ FieldRadio: FieldRadio,
+ FieldSelect: FieldSelect,
+ FieldSite: FieldSite,
+ FieldText: FieldText,
+ FieldTextArray: FieldTextArray,
+ FieldTextarea: FieldTextarea,
+ FieldTextareaArray: FieldTextareaArray
+ },
+ setup: function setup(props) {
+ var inlineHelpNode = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["ref"])(null);
+
+ var setInlineHelp = function setInlineHelp(newVal) {
+ var toAppend;
+
+ if (!newVal || !inlineHelpNode.value || typeof newVal.render === 'function') {
+ return;
+ }
+
+ if (typeof newVal === 'string') {
+ if (newVal.indexOf('#') === 0) {
+ toAppend = window.$(newVal);
+ } else {
+ toAppend = window.vueSanitize(newVal);
+ }
+ } else {
+ toAppend = newVal;
+ }
+
+ window.$(inlineHelpNode.value).html('').append(toAppend);
+ };
+
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["watch"])(function () {
+ return props.formField.inlineHelp;
+ }, setInlineHelp);
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["onMounted"])(function () {
+ setInlineHelp(props.formField.inlineHelp);
+ });
+ return {
+ inlineHelp: inlineHelpNode
+ };
+ },
+ computed: {
+ inlineHelpComponent: function inlineHelpComponent() {
+ var formField = this.formField;
+ var inlineHelpRecord = formField.inlineHelp;
+
+ if (inlineHelpRecord && typeof inlineHelpRecord.render === 'function') {
+ return formField.inlineHelp;
+ }
+
+ return undefined;
+ },
+ inlineHelpBind: function inlineHelpBind() {
+ return this.inlineHelpComponent ? this.formField.inlineHelpBind : undefined;
+ },
+ childComponent: function childComponent() {
+ var formField = this.formField;
+
+ if (formField.component) {
+ var component = formField.component;
+
+ if (formField.component.plugin) {
+ var _formField$component = formField.component,
+ plugin = _formField$component.plugin,
+ name = _formField$component.name;
+
+ if (!plugin || !name) {
+ throw new Error('Invalid component property given to piwik-field directive, must be ' + '{plugin: \'...\',name: \'...\'}');
+ }
+
+ component = Object(external_CoreHome_["useExternalPluginComponent"])(plugin, name);
+ }
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["markRaw"])(component);
+ } // backwards compatibility w/ settings that use templateFile property
+
+
+ if (formField.templateFile) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["markRaw"])(FieldAngularJsTemplate);
+ }
+
+ var uiControl = formField.uiControl;
+ var control = CONTROL_TO_COMPONENT_MAP[uiControl];
+
+ if (TEXT_CONTROLS.indexOf(uiControl) !== -1) {
+ control = 'FieldText'; // we use same template for text and password both
+ }
+
+ if (this.formField.type === 'array' && CONTROLS_SUPPORTING_ARRAY.indexOf(uiControl) !== -1) {
+ control = "".concat(control, "Array");
+ }
+
+ return control;
+ },
+ extraChildComponentParams: function extraChildComponentParams() {
+ if (this.formField.uiControl === 'multiselect') {
+ return {
+ multiple: true
+ };
+ }
+
+ return {};
+ },
+ showFormHelp: function showFormHelp() {
+ return this.formField.description || this.formField.inlineHelp || this.showDefaultValue || this.hasInlineHelpSlot;
+ },
+ showDefaultValue: function showDefaultValue() {
+ return this.defaultValuePretty && this.formField.uiControl !== 'checkbox' && this.formField.uiControl !== 'radio';
+ },
+
+ /**
+ * @deprecated here for angularjs BC support. shouldn't be used directly, instead use
+ * GroupedSetting.vue.
+ */
+ showField: function showField() {
+ if (!this.formField || !this.formField.condition || !(this.formField.condition instanceof Function)) {
+ return true;
+ }
+
+ return this.formField.condition();
+ },
+ processedModelValue: function processedModelValue() {
+ var field = this.formField; // convert boolean values since angular 1.6 uses strict equals when determining if a model
+ // value matches the ng-value of an input.
+
+ if (field.type === 'boolean') {
+ var valueIsTruthy = this.modelValue && this.modelValue > 0 && this.modelValue !== '0'; // for checkboxes, the value MUST be either true or false
+
+ if (field.uiControl === 'checkbox') {
+ return valueIsTruthy;
+ }
+
+ if (field.uiControl === 'radio') {
+ return valueIsTruthy ? '1' : '0';
+ }
+ }
+
+ return this.modelValue;
+ },
+ defaultValue: function defaultValue() {
+ var defaultValue = this.formField.defaultValue;
+
+ if (Array.isArray(defaultValue)) {
+ return defaultValue.join(',');
+ }
+
+ return defaultValue;
+ },
+ availableOptions: function availableOptions() {
+ var childComponent = this.childComponent;
+
+ if (typeof childComponent !== 'string') {
+ return null;
+ }
+
+ var formField = this.formField;
+
+ if (!formField.availableValues || !CONTROL_TO_AVAILABLE_OPTION_PROCESSOR[childComponent]) {
+ return null;
+ }
+
+ return CONTROL_TO_AVAILABLE_OPTION_PROCESSOR[childComponent](formField.availableValues, formField.type, formField.uiControlAttributes);
+ },
+ defaultValuePretty: function defaultValuePretty() {
+ var formField = this.formField;
+ var defaultValue = formField.defaultValue;
+ var availableOptions = this.availableOptions;
+
+ if (typeof defaultValue === 'string' && defaultValue) {
+ // eg default value for multi tuple
+ var defaultParsed = null;
+
+ try {
+ defaultParsed = JSON.parse(defaultValue);
+ } catch (e) {// invalid JSON
+ }
+
+ if (defaultParsed !== null && FormFieldvue_type_script_lang_ts_typeof(defaultParsed) === 'object') {
+ return '';
+ }
+ }
+
+ if (!Array.isArray(availableOptions)) {
+ if (Array.isArray(defaultValue)) {
+ return '';
+ }
+
+ return defaultValue ? "".concat(defaultValue) : '';
+ }
+
+ var prettyValues = [];
+
+ if (!Array.isArray(defaultValue)) {
+ defaultValue = [defaultValue];
+ }
+
+ (availableOptions || []).forEach(function (value) {
+ if (typeof value.value !== 'undefined' && defaultValue.indexOf(value.key) !== -1) {
+ prettyValues.push(value.value);
+ }
+ });
+ return prettyValues.join(', ');
+ },
+ defaultValuePrettyTruncated: function defaultValuePrettyTruncated() {
+ return this.defaultValuePretty.substring(0, 50);
+ },
+ hasInlineHelpSlot: function hasInlineHelpSlot() {
+ var _inlineHelpSlot$, _inlineHelpSlot$$chil;
+
+ if (!this.$slots['inline-help']) {
+ return false;
+ }
+
+ var inlineHelpSlot = this.$slots['inline-help']();
+ return !!(inlineHelpSlot !== null && inlineHelpSlot !== void 0 && (_inlineHelpSlot$ = inlineHelpSlot[0]) !== null && _inlineHelpSlot$ !== void 0 && (_inlineHelpSlot$$chil = _inlineHelpSlot$.children) !== null && _inlineHelpSlot$$chil !== void 0 && _inlineHelpSlot$$chil.length);
+ }
+ },
+ methods: {
+ onChange: function onChange(newValue) {
+ this.$emit('update:modelValue', newValue);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FormField.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FormField.vue
+
+
+
+FormFieldvue_type_script_lang_ts.render = render
+
+/* harmony default export */ var FormField = (FormFieldvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/FormField/FormField.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 transformVueComponentRef(value) {
+ if (!value) {
+ return undefined;
+ }
+
+ var plugin = value.plugin,
+ name = value.name;
+
+ if (!plugin || !name) {
+ throw new Error('Invalid component property given to piwik-field directive, must be ' + '{plugin: \'...\',name: \'...\'}');
+ }
+
+ return Object(external_CoreHome_["useExternalPluginComponent"])(plugin, name);
+} // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
+
+function conditionFn(scope, condition) {
+ var values = {};
+ Object.values(scope.allSettings || {}).forEach(function (setting) {
+ if (setting.value === '0') {
+ values[setting.name] = 0;
+ } else {
+ values[setting.name] = setting.value;
+ }
+ });
+ return scope.$eval(condition, values);
+}
+
+/* harmony default export */ var FormField_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: FormField,
+ scope: {
+ modelValue: {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ default: function _default(scope) {
+ var field = scope.piwikFormField; // vue components expect object data as input, so we parse JSON data
+ // for angularjs directives that use JSON.
+
+ if (typeof field.value === 'string' && field.value && (field.type === 'array' || field.uiControl === 'multituple' || field.uiControl === 'field-array' || field.uiControl === 'multiselect' || field.uiControl === 'site')) {
+ field.value = JSON.parse(field.value);
+ }
+
+ if (field.uiControl === 'checkbox') {
+ return Object(external_CoreHome_["transformAngularJsBoolAttr"])(field.value);
+ }
+
+ return field.value;
+ }
+ },
+ piwikFormField: {
+ vue: 'formField',
+ angularJsBind: '=',
+ transform: function transform(v, vm, scope) {
+ var value = v;
+
+ function getComponent() {
+ if (value.templateFile) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["markRaw"])(FieldAngularJsTemplate);
+ }
+
+ var comp = transformVueComponentRef(value.component);
+
+ if (!comp) {
+ return undefined;
+ }
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["markRaw"])(comp);
+ }
+
+ return Object.assign(Object.assign({}, value), {}, {
+ condition: value.condition ? conditionFn.bind(null, scope, value.condition) : value.condition,
+ disabled: Object(external_CoreHome_["transformAngularJsBoolAttr"])(value.disabled),
+ autocomplete: Object(external_CoreHome_["transformAngularJsBoolAttr"])(value.autocomplete),
+ autofocus: Object(external_CoreHome_["transformAngularJsBoolAttr"])(value.autofocus),
+ tabindex: Object(external_CoreHome_["transformAngularJsIntAttr"])(value.tabindex),
+ fullWidth: Object(external_CoreHome_["transformAngularJsBoolAttr"])(value.fullWidth),
+ maxlength: Object(external_CoreHome_["transformAngularJsIntAttr"])(value.maxlength),
+ required: Object(external_CoreHome_["transformAngularJsBoolAttr"])(value.required),
+ rows: Object(external_CoreHome_["transformAngularJsIntAttr"])(value.rows),
+ min: Object(external_CoreHome_["transformAngularJsIntAttr"])(value.min),
+ max: Object(external_CoreHome_["transformAngularJsIntAttr"])(value.max),
+ component: getComponent()
+ });
+ }
+ },
+ allSettings: {
+ angularJsBind: '='
+ }
+ },
+ directiveName: 'piwikFormField',
+ events: {
+ 'update:modelValue': function updateModelValue(newValue, vm, scope, element, attrs, controller, $timeout) {
+ if (newValue !== scope.piwikFormField.value) {
+ $timeout(function () {
+ scope.piwikFormField.value = newValue;
+ });
+ }
+ }
+ },
+ $inject: ['$timeout'],
+ postCreate: function postCreate(vm, scope) {
+ scope.$watch('piwikFormField.value', function (newVal, oldVal) {
+ if (newVal !== oldVal) {
+ vm.modelValue = newVal;
+ }
+ }); // deep watch for all settings, on change trigger change in formfield property
+ // so condition is re-applied
+
+ scope.$watch('allSettings', function () {
+ vm.formField = Object.assign(Object.assign({}, vm.formField), {}, {
+ condition: scope.piwikFormField.condition ? conditionFn.bind(null, scope, scope.piwikFormField.condition) : scope.piwikFormField.condition
+ });
+ }, 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/CorePluginsAdmin/vue/src/Field/Field.vue?vue&type=template&id=91065bf4
+
+function Fieldvue_type_template_id_91065bf4_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_FormField = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("FormField");
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_FormField, {
+ "form-field": _ctx.field,
+ "model-value": _ctx.modelValue,
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onChange($event);
+ })
+ }, {
+ "inline-help": Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["renderSlot"])(_ctx.$slots, "inline-help")];
+ }),
+ _: 3
+ }, 8, ["form-field", "model-value"]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Field/Field.vue?vue&type=template&id=91065bf4
+
+// 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/CorePluginsAdmin/vue/src/Field/Field.vue?vue&type=script&lang=ts
+
+
+var UI_CONTROLS_TO_TYPE = {
+ multiselect: 'array',
+ checkbox: 'boolean',
+ site: 'object',
+ number: 'integer'
+};
+/* harmony default export */ var Fieldvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ modelValue: null,
+ uicontrol: String,
+ name: String,
+ defaultValue: null,
+ options: [Object, Array],
+ description: String,
+ introduction: String,
+ title: String,
+ inlineHelp: [String, Object],
+ inlineHelpBind: Object,
+ disabled: Boolean,
+ uiControlAttributes: {
+ type: Object,
+ default: function _default() {
+ return {};
+ }
+ },
+ uiControlOptions: {
+ type: Object,
+ default: function _default() {
+ return {};
+ }
+ },
+ autocomplete: Boolean,
+ condition: Function,
+ varType: String,
+ autofocus: Boolean,
+ tabindex: Number,
+ fullWidth: Boolean,
+ maxlength: Number,
+ required: Boolean,
+ placeholder: String,
+ rows: Number,
+ min: Number,
+ max: Number,
+ component: null,
+ templateFile: String
+ },
+ emits: ['update:modelValue'],
+ components: {
+ FormField: FormField
+ },
+ computed: {
+ type: function type() {
+ if (this.varType) {
+ return this.varType;
+ }
+
+ var uicontrol = this.uicontrol;
+
+ if (uicontrol && UI_CONTROLS_TO_TYPE[uicontrol]) {
+ return UI_CONTROLS_TO_TYPE[uicontrol];
+ }
+
+ return 'string';
+ },
+ field: function field() {
+ return {
+ uiControl: this.uicontrol,
+ type: this.type,
+ name: this.name,
+ defaultValue: this.defaultValue,
+ availableValues: this.options,
+ description: this.description,
+ introduction: this.introduction,
+ inlineHelp: this.inlineHelp,
+ inlineHelpBind: this.inlineHelpBind,
+ title: this.title,
+ component: this.component,
+ templateFile: this.templateFile,
+ uiControlAttributes: Object.assign(Object.assign({}, this.uiControlAttributes), {}, {
+ disabled: this.disabled,
+ autocomplete: this.autocomplete,
+ tabindex: this.tabindex,
+ autofocus: this.autofocus,
+ rows: this.rows,
+ required: this.required,
+ maxlength: this.maxlength,
+ placeholder: this.placeholder,
+ min: this.min,
+ max: this.max
+ }),
+ fullWidth: this.fullWidth,
+ uiControlOptions: this.uiControlOptions
+ };
+ }
+ },
+ methods: {
+ onChange: function onChange(newValue) {
+ this.$emit('update:modelValue', newValue);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Field/Field.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Field/Field.vue
+
+
+
+Fieldvue_type_script_lang_ts.render = Fieldvue_type_template_id_91065bf4_render
+
+/* harmony default export */ var Field = (Fieldvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Field/Field.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 handleJsonValue(value, varType, uiControl) {
+ if (typeof value === 'string' && value && (varType === 'array' || uiControl === 'multituple' || uiControl === 'field-array' || uiControl === 'multiselect' || uiControl === 'site')) {
+ var result = JSON.parse(value); // the angularjs site field supplied siteid/sitename properties which initializes the
+ // siteselector value. the sitename is assumed to be encoded, and is decoded once.
+ // so the value for 'site' Field's in angularjs is assumed to be encoded.
+
+ if (uiControl === 'site') {
+ result.name = external_CoreHome_["Matomo"].helper.htmlDecode(result.name);
+ }
+
+ return result;
+ }
+
+ if (uiControl === 'checkbox' && varType !== 'array') {
+ return Object(external_CoreHome_["transformAngularJsBoolAttr"])(value);
+ }
+
+ return value;
+}
+
+/* harmony default export */ var Field_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: Field,
+ require: '?ngModel',
+ scope: {
+ uicontrol: {
+ angularJsBind: '@'
+ },
+ name: {
+ angularJsBind: '@'
+ },
+ value: {
+ vue: 'modelValue',
+ angularJsBind: '@',
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ transform: function transform(value, vm, scope) {
+ // vue components expect object data as input, so we parse JSON data
+ // for angularjs directives that use JSON.
+ return handleJsonValue(value, scope.varType, scope.uicontrol);
+ }
+ },
+ default: {
+ vue: 'defaultValue',
+ angularJsBind: '@'
+ },
+ options: {
+ angularJsBind: '='
+ },
+ description: {
+ angularJsBind: '@'
+ },
+ introduction: {
+ angularJsBind: '@'
+ },
+ title: {
+ angularJsBind: '@'
+ },
+ inlineHelp: {
+ angularJsBind: '@'
+ },
+ disabled: {
+ angularJsBind: '=',
+ transform: external_CoreHome_["transformAngularJsBoolAttr"]
+ },
+ uiControlAttributes: {
+ angularJsBind: '='
+ },
+ uiControlOptions: {
+ angularJsBind: '='
+ },
+ autocomplete: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsBoolAttr"]
+ },
+ condition: {
+ angularJsBind: '@',
+ transform: function transform(value, vm, scope) {
+ if (!value) {
+ return undefined;
+ }
+
+ return function (values) {
+ return scope.$eval(value, values);
+ };
+ }
+ },
+ varType: {
+ angularJsBind: '@'
+ },
+ autofocus: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsBoolAttr"]
+ },
+ tabindex: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsIntAttr"]
+ },
+ fullWidth: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsBoolAttr"]
+ },
+ maxlength: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsIntAttr"]
+ },
+ required: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsBoolAttr"]
+ },
+ placeholder: {
+ angularJsBind: '@'
+ },
+ rows: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsIntAttr"]
+ },
+ min: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsIntAttr"]
+ },
+ max: {
+ angularJsBind: '@',
+ transform: external_CoreHome_["transformAngularJsIntAttr"]
+ },
+ component: {
+ angularJsBind: '<',
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ transform: function transform(value, vm, scope) {
+ if (!value) {
+ return undefined;
+ }
+
+ if (scope.templateFile) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["shallowRef"])(FieldAngularJsTemplate);
+ }
+
+ var plugin = value.plugin,
+ name = value.name;
+
+ if (!plugin || !name) {
+ throw new Error('Invalid component property given to piwik-field directive, must ' + 'be {plugin: \'...\',name: \'...\'}');
+ }
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["shallowRef"])(Object(external_CoreHome_["useExternalPluginComponent"])(plugin, name));
+ }
+ }
+ },
+ directiveName: 'piwikField',
+ $inject: ['$timeout'],
+ events: {
+ 'update:modelValue': function updateModelValue(newValue, vm, scope, element, attrs, ngModel, $timeout) {
+ var currentValue = ngModel ? ngModel.$viewValue : scope.value;
+
+ if (newValue !== currentValue) {
+ $timeout(function () {
+ if (!ngModel) {
+ scope.value = newValue;
+ return;
+ } // ngModel being used
+
+
+ ngModel.$setViewValue(newValue);
+ ngModel.$render(); // not detected by the watch for some reason
+ });
+ }
+ }
+ },
+ postCreate: function postCreate(vm, scope, element, attrs, controller) {
+ var ngModel = controller;
+
+ if (!ngModel) {
+ scope.$watch('value', function (newVal) {
+ if (newVal !== vm.modelValue) {
+ var transformed = handleJsonValue(newVal, scope.varType, scope.uicontrol);
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ vm.modelValue = transformed;
+ });
+ }
+ });
+ return;
+ } // ngModel being used
+
+
+ ngModel.$render = function () {
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ vm.modelValue = Object(external_CoreHome_["removeAngularJsSpecificProperties"])(ngModel.$viewValue);
+ });
+ };
+
+ if (typeof scope.value !== 'undefined') {
+ var transformed = handleJsonValue(scope.value, scope.varType, scope.uicontrol);
+ ngModel.$setViewValue(transformed);
+ } else {
+ ngModel.$setViewValue(vm.modelValue);
+ } // to provide same behavior in angularjs/<4.6.0, we trigger a model update to the same
+ // value, but only for 'site' uicontrols. this only happened for site selectors, no others.
+
+
+ if (scope.uicontrol === 'site' && ngModel.$viewValue) {
+ setTimeout(function () {
+ ngModel.$setViewValue(Object.assign({}, 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/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue?vue&type=template&id=a4ce6500
+
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_1 = {
+ class: "pluginSettings",
+ ref: "root"
+};
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_2 = ["id"];
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_3 = {
+ class: "card-content"
+};
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_4 = ["id"];
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_5 = ["onClick", "disabled", "value"];
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_6 = {
+ class: "confirm-password-modal modal"
+};
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_7 = {
+ class: "modal-content"
+};
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_8 = {
+ class: "modal-footer"
+};
+var PluginSettingsvue_type_template_id_a4ce6500_hoisted_9 = ["disabled"];
+function PluginSettingsvue_type_template_id_a4ce6500_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _this = this;
+
+ var _component_GroupedSettings = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("GroupedSettings");
+
+ var _component_ActivityIndicator = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ActivityIndicator");
+
+ 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", PluginSettingsvue_type_template_id_a4ce6500_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.settingsPerPlugin, function (settings) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", {
+ class: "card",
+ id: "".concat(settings.pluginName, "PluginSettings"),
+ key: "".concat(settings.pluginName, "PluginSettings")
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PluginSettingsvue_type_template_id_a4ce6500_hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", {
+ class: "card-title",
+ id: settings.pluginName
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(settings.title), 9, PluginSettingsvue_type_template_id_a4ce6500_hoisted_4), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_GroupedSettings, {
+ "group-name": settings.pluginName,
+ settings: settings.settings,
+ "all-setting-values": _ctx.settingValues,
+ onChange: function onChange($event) {
+ return _ctx.settingValues["".concat(settings.pluginName, ".").concat($event.name)] = $event.value;
+ }
+ }, null, 8, ["group-name", "settings", "all-setting-values", "onChange"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "button",
+ onClick: function onClick($event) {
+ return _ctx.saveSetting(settings.pluginName);
+ },
+ disabled: _ctx.isLoading,
+ class: "pluginsSettingsSubmit btn",
+ value: _ctx.translate('General_Save')
+ }, null, 8, PluginSettingsvue_type_template_id_a4ce6500_hoisted_5), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, {
+ loading: _ctx.isLoading || _ctx.isSaving[settings.pluginName]
+ }, null, 8, ["loading"])])], 8, PluginSettingsvue_type_template_id_a4ce6500_hoisted_2);
+ }), 128)), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PluginSettingsvue_type_template_id_a4ce6500_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PluginSettingsvue_type_template_id_a4ce6500_hoisted_7, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('UsersManager_ConfirmWithPassword')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ modelValue: _ctx.passwordConfirmation,
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.passwordConfirmation = $event;
+ }),
+ uicontrol: 'password',
+ name: 'currentUserPassword',
+ autocomplete: false,
+ "full-width": true,
+ title: _ctx.translate('UsersManager_YourCurrentPassword')
+ }, null, 8, ["modelValue", "title"])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", PluginSettingsvue_type_template_id_a4ce6500_hoisted_8, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", {
+ href: "",
+ class: "modal-action modal-close btn",
+ disabled: !_ctx.passwordConfirmation ? 'disabled' : undefined,
+ onClick: _cache[1] || (_cache[1] = function ($event) {
+ $event.preventDefault();
+
+ _ctx.save(_this.settingsToSave);
+ })
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Yes')), 9, PluginSettingsvue_type_template_id_a4ce6500_hoisted_9), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", {
+ href: "",
+ class: "modal-action modal-close modal-no",
+ onClick: _cache[2] || (_cache[2] = function ($event) {
+ return $event.preventDefault();
+ })
+ }, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_No')), 1)])])], 512);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue?vue&type=template&id=a4ce6500
+
+// 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/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue?vue&type=template&id=566a93cc
+
+function GroupedSettingsvue_type_template_id_566a93cc_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_GroupedSetting = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("GroupedSetting");
+
+ 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"])(_ctx.settings, function (setting) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", {
+ key: "".concat(_ctx.groupPrefix).concat(setting.name)
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_GroupedSetting, {
+ "model-value": _ctx.allSettingValues["".concat(_ctx.groupPrefix).concat(setting.name)],
+ "onUpdate:modelValue": function onUpdateModelValue($event) {
+ return _ctx.$emit('change', {
+ name: setting.name,
+ value: $event
+ });
+ },
+ setting: setting,
+ "condition-values": _ctx.settingValues
+ }, null, 8, ["model-value", "onUpdate:modelValue", "setting", "condition-values"])]);
+ }), 128);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue?vue&type=template&id=566a93cc
+
+// 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/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSetting.vue?vue&type=template&id=17c12cc8
+
+function GroupedSettingvue_type_template_id_17c12cc8_render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_FormField = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("FormField");
+
+ 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", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_FormField, {
+ "model-value": _ctx.modelValue,
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.changeValue($event);
+ }),
+ "form-field": _ctx.settingWithComponent
+ }, null, 8, ["model-value", "form-field"])], 512)), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showField]]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSetting.vue?vue&type=template&id=17c12cc8
+
+// 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/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSetting.vue?vue&type=script&lang=ts
+
+
+
+ // TODO: have to use angularjs here until there's an expression evaluating alternative
+
+var conditionScope;
+/* harmony default export */ var GroupedSettingvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ setting: {
+ type: Object,
+ required: true
+ },
+ modelValue: null,
+ conditionValues: {
+ type: Object,
+ required: true
+ }
+ },
+ components: {
+ FormField: FormField
+ },
+ emits: ['update:modelValue'],
+ computed: {
+ // bc for angularjs field that uses templateFile
+ settingWithComponent: function settingWithComponent() {
+ if (this.setting.templateFile) {
+ return Object.assign(Object.assign({}, this.setting), {}, {
+ component: FieldAngularJsTemplate
+ });
+ }
+
+ return this.setting;
+ },
+ showField: function showField() {
+ var condition = this.setting.condition;
+
+ if (!condition) {
+ return true;
+ }
+
+ if (!conditionScope) {
+ var $rootScope = external_CoreHome_["Matomo"].helper.getAngularDependency('$rootScope');
+ conditionScope = $rootScope.$new(true);
+ }
+
+ return conditionScope.$eval(condition, this.conditionValues);
+ }
+ },
+ methods: {
+ changeValue: function changeValue(newValue) {
+ this.$emit('update:modelValue', newValue);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSetting.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSetting.vue
+
+
+
+GroupedSettingvue_type_script_lang_ts.render = GroupedSettingvue_type_template_id_17c12cc8_render
+
+/* harmony default export */ var GroupedSetting = (GroupedSettingvue_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/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue?vue&type=script&lang=ts
+function GroupedSettingsvue_type_script_lang_ts_slicedToArray(arr, i) { return GroupedSettingsvue_type_script_lang_ts_arrayWithHoles(arr) || GroupedSettingsvue_type_script_lang_ts_iterableToArrayLimit(arr, i) || GroupedSettingsvue_type_script_lang_ts_unsupportedIterableToArray(arr, i) || GroupedSettingsvue_type_script_lang_ts_nonIterableRest(); }
+
+function GroupedSettingsvue_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 GroupedSettingsvue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return GroupedSettingsvue_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 GroupedSettingsvue_type_script_lang_ts_arrayLikeToArray(o, minLen); }
+
+function GroupedSettingsvue_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 GroupedSettingsvue_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 GroupedSettingsvue_type_script_lang_ts_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+
+
+/* harmony default export */ var GroupedSettingsvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ groupName: String,
+ settings: {
+ type: Array,
+ required: true
+ },
+ allSettingValues: {
+ type: Object,
+ required: true
+ }
+ },
+ emits: ['change'],
+ components: {
+ GroupedSetting: GroupedSetting
+ },
+ computed: {
+ settingValues: function settingValues() {
+ var _this = this;
+
+ var entries = Object.entries(this.allSettingValues).filter(function (_ref) {
+ var _ref2 = GroupedSettingsvue_type_script_lang_ts_slicedToArray(_ref, 1),
+ key = _ref2[0];
+
+ if (_this.groupName) {
+ var _key$split = key.split('.'),
+ _key$split2 = GroupedSettingsvue_type_script_lang_ts_slicedToArray(_key$split, 1),
+ groupName = _key$split2[0];
+
+ if (groupName !== _this.groupName) {
+ return false;
+ }
+ }
+
+ return true;
+ }).map(function (_ref3) {
+ var _ref4 = GroupedSettingsvue_type_script_lang_ts_slicedToArray(_ref3, 2),
+ key = _ref4[0],
+ value = _ref4[1];
+
+ return _this.groupName ? [key.split('.')[1], value] : [key, value];
+ });
+ return Object.fromEntries(entries);
+ },
+ groupPrefix: function groupPrefix() {
+ if (!this.groupName) {
+ return '';
+ }
+
+ return "".concat(this.groupName, ".");
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue
+
+
+
+GroupedSettingsvue_type_script_lang_ts.render = GroupedSettingsvue_type_template_id_566a93cc_render
+
+/* harmony default export */ var GroupedSettings = (GroupedSettingsvue_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/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue?vue&type=script&lang=ts
+function PluginSettingsvue_type_script_lang_ts_slicedToArray(arr, i) { return PluginSettingsvue_type_script_lang_ts_arrayWithHoles(arr) || PluginSettingsvue_type_script_lang_ts_iterableToArrayLimit(arr, i) || PluginSettingsvue_type_script_lang_ts_unsupportedIterableToArray(arr, i) || PluginSettingsvue_type_script_lang_ts_nonIterableRest(); }
+
+function PluginSettingsvue_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 PluginSettingsvue_type_script_lang_ts_unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return PluginSettingsvue_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 PluginSettingsvue_type_script_lang_ts_arrayLikeToArray(o, minLen); }
+
+function PluginSettingsvue_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 PluginSettingsvue_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 PluginSettingsvue_type_script_lang_ts_arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+
+
+
+
+var _window = window,
+ $ = _window.$;
+/* harmony default export */ var PluginSettingsvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ mode: String
+ },
+ components: {
+ ActivityIndicator: external_CoreHome_["ActivityIndicator"],
+ Field: Field,
+ GroupedSettings: GroupedSettings
+ },
+ data: function data() {
+ return {
+ isLoading: true,
+ isSaving: {},
+ passwordConfirmation: '',
+ settingsToSave: null,
+ settingsPerPlugin: [],
+ settingValues: {}
+ };
+ },
+ created: function created() {
+ var _this = this;
+
+ external_CoreHome_["AjaxHelper"].fetch({
+ method: this.apiMethod
+ }).then(function (settingsPerPlugin) {
+ _this.isLoading = false;
+ _this.settingsPerPlugin = settingsPerPlugin;
+ settingsPerPlugin.forEach(function (settings) {
+ settings.settings.forEach(function (setting) {
+ _this.settingValues["".concat(settings.pluginName, ".").concat(setting.name)] = setting.value;
+ });
+ });
+ window.anchorLinkFix.scrollToAnchorInUrl();
+
+ _this.addSectionsToTableOfContents();
+ }).catch(function () {
+ _this.isLoading = false;
+ });
+ },
+ computed: {
+ apiMethod: function apiMethod() {
+ return this.mode === 'admin' ? 'CorePluginsAdmin.getSystemSettings' : 'CorePluginsAdmin.getUserSettings';
+ },
+ saveApiMethod: function saveApiMethod() {
+ return this.mode === 'admin' ? 'CorePluginsAdmin.setSystemSettings' : 'CorePluginsAdmin.setUserSettings';
+ }
+ },
+ methods: {
+ addSectionsToTableOfContents: function addSectionsToTableOfContents() {
+ var $toc = $('#generalSettingsTOC');
+
+ if (!$toc.length) {
+ return;
+ }
+
+ var settingsPerPlugin = this.settingsPerPlugin;
+ settingsPerPlugin.forEach(function (settingsForPlugin) {
+ var pluginName = settingsForPlugin.pluginName,
+ settings = settingsForPlugin.settings;
+
+ if (!pluginName) {
+ return;
+ }
+
+ if (pluginName === 'CoreAdminHome' && settings) {
+ settings.filter(function (s) {
+ return s.introduction;
+ }).forEach(function (s) {
+ $toc.append("").concat(s.introduction, " "));
+ });
+ } else {
+ $toc.append("").concat(pluginName.replace(/([A-Z])/g, ' $1').trim(), " "));
+ }
+ });
+ },
+ saveSetting: function saveSetting(requestedPlugin) {
+ if (this.mode === 'admin') {
+ this.showPasswordConfirmModal(requestedPlugin);
+ } else {
+ this.save(requestedPlugin);
+ }
+ },
+ showPasswordConfirmModal: function showPasswordConfirmModal(requestedPlugin) {
+ var _this2 = this;
+
+ this.settingsToSave = requestedPlugin;
+ var root = this.$refs.root;
+ var $root = $(root);
+
+ var onEnter = function onEnter(event) {
+ var keycode = event.keyCode ? event.keyCode : event.which;
+
+ if (keycode === 13) {
+ $root.find('.confirm-password-modal').modal('close');
+
+ _this2.save(requestedPlugin);
+ }
+ };
+
+ $root.find('.confirm-password-modal').modal({
+ dismissible: false,
+ onOpenEnd: function onOpenEnd() {
+ var passwordField = '.modal.open #currentUserPassword';
+ $(passwordField).focus();
+ $(passwordField).off('keypress').keypress(onEnter);
+ }
+ }).modal('open');
+ },
+ save: function save(requestedPlugin) {
+ var _this3 = this;
+
+ var saveApiMethod = this.saveApiMethod;
+ this.isSaving[requestedPlugin] = true;
+ var settingValuesPayload = this.getValuesForPlugin(requestedPlugin);
+ external_CoreHome_["AjaxHelper"].post({
+ method: saveApiMethod
+ }, {
+ settingValues: settingValuesPayload,
+ passwordConfirmation: this.passwordConfirmation
+ }).then(function () {
+ _this3.isSaving[requestedPlugin] = false;
+ var notificationInstanceId = external_CoreHome_["NotificationsStore"].show({
+ message: Object(external_CoreHome_["translate"])('CoreAdminHome_PluginSettingsSaveSuccess'),
+ id: 'generalSettings',
+ context: 'success',
+ type: 'transient'
+ });
+ external_CoreHome_["NotificationsStore"].scrollToNotification(notificationInstanceId);
+ }).catch(function () {
+ _this3.isSaving[requestedPlugin] = false;
+ });
+ this.passwordConfirmation = '';
+ this.settingsToSave = null;
+ },
+ getValuesForPlugin: function getValuesForPlugin(requestedPlugin) {
+ var values = {};
+
+ if (!values[requestedPlugin]) {
+ values[requestedPlugin] = [];
+ }
+
+ Object.entries(this.settingValues).forEach(function (_ref) {
+ var _ref2 = PluginSettingsvue_type_script_lang_ts_slicedToArray(_ref, 2),
+ key = _ref2[0],
+ value = _ref2[1];
+
+ var _key$split = key.split('.'),
+ _key$split2 = PluginSettingsvue_type_script_lang_ts_slicedToArray(_key$split, 2),
+ pluginName = _key$split2[0],
+ settingName = _key$split2[1];
+
+ if (pluginName !== requestedPlugin) {
+ return;
+ }
+
+ var postValue = value;
+
+ if (postValue === false) {
+ postValue = '0';
+ } else if (postValue === true) {
+ postValue = '1';
+ }
+
+ values[pluginName].push({
+ name: settingName,
+ value: postValue
+ });
+ });
+ return values;
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue
+
+
+
+PluginSettingsvue_type_script_lang_ts.render = PluginSettingsvue_type_template_id_a4ce6500_render
+
+/* harmony default export */ var PluginSettings = (PluginSettingsvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.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 PluginSettings_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: PluginSettings,
+ scope: {
+ mode: {
+ angularJsBind: '@'
+ }
+ },
+ directiveName: 'piwikPluginSettings'
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Plugins/PluginManagement.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 PluginManagement_window = window,
+ PluginManagement_$ = PluginManagement_window.$;
+
+function onClickUninstall(binding, event) {
+ event.preventDefault();
+ var link = PluginManagement_$(event.target).attr('href');
+ var pluginName = PluginManagement_$(event.target).attr('data-plugin-name');
+
+ if (!link || !pluginName) {
+ return;
+ }
+
+ if (!binding.value.uninstallConfirmMessage) {
+ binding.value.uninstallConfirmMessage = PluginManagement_$('#uninstallPluginConfirm').text();
+ }
+
+ var messageToDisplay = (binding.value.uninstallConfirmMessage || '').replace('%s', pluginName);
+ PluginManagement_$('#uninstallPluginConfirm').text(messageToDisplay);
+ external_CoreHome_["Matomo"].helper.modalConfirm('#confirmUninstallPlugin', {
+ yes: function yes() {
+ window.location.href = link;
+ }
+ });
+}
+
+function onDonateLinkClick(event) {
+ event.preventDefault();
+ var overlayId = PluginManagement_$(event.target).data('overlay-id');
+ external_CoreHome_["Matomo"].helper.modalConfirm("#".concat(overlayId), {});
+}
+
+/* harmony default export */ var PluginManagement = ({
+ mounted: function mounted(el, binding) {
+ setTimeout(function () {
+ binding.value.uninstallConfirmMessage = '';
+ PluginManagement_$(el).find('.uninstall').click(onClickUninstall.bind(null, binding));
+ PluginManagement_$(el).find('.plugin-donation-link').click(onDonateLinkClick);
+ });
+ }
+});
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Plugins/PluginManagement.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 piwikPluginManagement() {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink(scope, element) {
+ var binding = {
+ instance: null,
+ value: {},
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ };
+ PluginManagement.mounted(element[0], binding);
+ }
+ };
+}
+window.angular.module('piwikApp').directive('piwikPluginManagement', piwikPluginManagement);
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Plugins/PluginUpload.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 PluginUpload_window = window,
+ PluginUpload_$ = PluginUpload_window.$;
+
+function onUploadPlugin(event) {
+ event.preventDefault();
+ external_CoreHome_["Matomo"].helper.modalConfirm('#installPluginByUpload', {});
+}
+
+function onSubmitPlugin(event) {
+ var $zipFile = PluginUpload_$('[name=pluginZip]');
+ var fileName = $zipFile.val();
+
+ if (!fileName || fileName.slice(-4) !== '.zip') {
+ event.preventDefault(); // eslint-disable-next-line no-alert
+
+ alert(Object(external_CoreHome_["translate"])('CorePluginsAdmin_NoZipFileSelected'));
+ } else if ($zipFile.data('maxSize') > 0 && $zipFile[0].files[0].size > $zipFile.data('maxSize') * 1048576) {
+ event.preventDefault(); // eslint-disable-next-line no-alert
+
+ alert(Object(external_CoreHome_["translate"])('CorePluginsAdmin_FileExceedsUploadLimit'));
+ }
+}
+
+/* harmony default export */ var PluginUpload = ({
+ mounted: function mounted() {
+ setTimeout(function () {
+ PluginUpload_$('.uploadPlugin').click(onUploadPlugin);
+ PluginUpload_$('#uploadPluginForm').submit(onSubmitPlugin);
+ });
+ }
+});
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Plugins/PluginUpload.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 piwikPluginUpload() {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink() {
+ PluginUpload.mounted();
+ }
+ };
+}
+window.angular.module('piwikApp').directive('piwikPluginUpload', piwikPluginUpload);
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.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 PluginFilter_window = window,
+ PluginFilter_$ = PluginFilter_window.$;
+
+function getCurrentFilterOrigin(element) {
+ return element.find('.origin a.active').data('filter-origin');
+}
+
+function getCurrentFilterStatus(element) {
+ return element.find('.status a.active').data('filter-status');
+}
+
+function getMatchingNodes(filterOrigin, filterStatus) {
+ var query = '#plugins tr';
+
+ if (filterOrigin === 'all') {
+ query += '[data-filter-origin]';
+ } else {
+ query += "[data-filter-origin=".concat(filterOrigin, "]");
+ }
+
+ if (filterStatus === 'all') {
+ query += '[data-filter-status]';
+ } else {
+ query += "[data-filter-status=".concat(filterStatus, "]");
+ }
+
+ return PluginFilter_$(query);
+}
+
+function updateNumberOfMatchingPluginsInFilter(element, selectorFilterToUpdate, filterOrigin, filterStatus) {
+ var numMatchingNodes = getMatchingNodes(filterOrigin, filterStatus).length;
+ var updatedCounterText = " (".concat(numMatchingNodes, ")");
+ element.find("".concat(selectorFilterToUpdate, " .counter")).text(updatedCounterText);
+}
+
+function updateAllNumbersOfMatchingPluginsInFilter(element) {
+ var filterOrigin = getCurrentFilterOrigin(element);
+ var filterStatus = getCurrentFilterStatus(element);
+ updateNumberOfMatchingPluginsInFilter(element, '[data-filter-status="all"]', filterOrigin, 'all');
+ updateNumberOfMatchingPluginsInFilter(element, '[data-filter-status="active"]', filterOrigin, 'active');
+ updateNumberOfMatchingPluginsInFilter(element, '[data-filter-status="inactive"]', filterOrigin, 'inactive');
+ updateNumberOfMatchingPluginsInFilter(element, '[data-filter-origin="all"]', 'all', filterStatus);
+ updateNumberOfMatchingPluginsInFilter(element, '[data-filter-origin="core"]', 'core', filterStatus);
+ updateNumberOfMatchingPluginsInFilter(element, '[data-filter-origin="official"]', 'official', filterStatus);
+ updateNumberOfMatchingPluginsInFilter(element, '[data-filter-origin="thirdparty"]', 'thirdparty', filterStatus);
+}
+
+function filterPlugins(element) {
+ var filterOrigin = getCurrentFilterOrigin(element);
+ var filterStatus = getCurrentFilterStatus(element);
+ var $nodesToEnable = getMatchingNodes(filterOrigin, filterStatus);
+ PluginFilter_$('#plugins tr[data-filter-origin][data-filter-status]').css('display', 'none');
+ $nodesToEnable.css('display', 'table-row');
+ updateAllNumbersOfMatchingPluginsInFilter(element);
+}
+
+function onClickStatus(element, event) {
+ event.preventDefault();
+ PluginFilter_$(event.target).siblings().removeClass('active');
+ PluginFilter_$(event.target).addClass('active');
+ filterPlugins(element);
+}
+
+function onClickOrigin(element, event) {
+ event.preventDefault();
+ PluginFilter_$(event.target).siblings().removeClass('active');
+ PluginFilter_$(event.target).addClass('active');
+ filterPlugins(element);
+}
+
+/* harmony default export */ var PluginFilter = ({
+ mounted: function mounted(el) {
+ setTimeout(function () {
+ updateAllNumbersOfMatchingPluginsInFilter(PluginFilter_$(el));
+ PluginFilter_$(el).find('.status').on('click', 'a', onClickStatus.bind(null, PluginFilter_$(el)));
+ PluginFilter_$(el).find('.origin').on('click', 'a', onClickOrigin.bind(null, PluginFilter_$(el)));
+ });
+ }
+});
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.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 piwikPluginFilter() {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink(scope, element) {
+ PluginFilter.mounted(element[0]);
+ }
+ };
+}
+window.angular.module('piwikApp').directive('piwikPluginFilter', piwikPluginFilter);
+// 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/CorePluginsAdmin/vue/src/SaveButton/SaveButton.vue?vue&type=template&id=1e391ba1
+
+var SaveButtonvue_type_template_id_1e391ba1_hoisted_1 = {
+ class: "matomo-save-button",
+ style: {
+ "display": "inline-block"
+ }
+};
+var SaveButtonvue_type_template_id_1e391ba1_hoisted_2 = ["disabled", "value"];
+function SaveButtonvue_type_template_id_1e391ba1_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", SaveButtonvue_type_template_id_1e391ba1_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "button",
+ onClick: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.onConfirm($event);
+ }),
+ disabled: _ctx.saving || _ctx.disabled,
+ class: "btn",
+ value: _ctx.value ? _ctx.value : _ctx.translate('General_Save')
+ }, null, 8, SaveButtonvue_type_template_id_1e391ba1_hoisted_2), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, {
+ loading: _ctx.saving
+ }, null, 8, ["loading"])]);
+}
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.vue?vue&type=template&id=1e391ba1
+
+// 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/CorePluginsAdmin/vue/src/SaveButton/SaveButton.vue?vue&type=script&lang=ts
+
+
+/* harmony default export */ var SaveButtonvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ saving: Boolean,
+ value: String,
+ disabled: Boolean
+ },
+ components: {
+ ActivityIndicator: external_CoreHome_["ActivityIndicator"]
+ },
+ emits: ['confirm'],
+ methods: {
+ onConfirm: function onConfirm(event) {
+ this.$emit('confirm', event);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.vue
+
+
+
+SaveButtonvue_type_script_lang_ts.render = SaveButtonvue_type_template_id_1e391ba1_render
+
+/* harmony default export */ var SaveButton = (SaveButtonvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.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 SaveButton_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: SaveButton,
+ scope: {
+ saving: {
+ angularJsBind: '=?'
+ },
+ value: {
+ angularJsBind: '@?'
+ },
+ disabled: {
+ angularJsBind: '=?'
+ },
+ onconfirm: {
+ angularJsBind: '&?',
+ vue: 'confirm'
+ }
+ },
+ events: {
+ confirm: function confirm($event, vm, scope, element, attrs, controller, $timeout) {
+ element[0].click(); // this directive can be used on input's with ng-click specified
+
+ $timeout();
+ }
+ },
+ replace: true,
+ directiveName: 'piwikSaveButton',
+ $inject: ['$timeout']
+}));
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Form/Form.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 Form_window = window,
+ Form_$ = Form_window.$;
+/* harmony default export */ var Form = ({
+ mounted: function mounted(el) {
+ setTimeout(function () {
+ Form_$(el).find('input[type=text]').keypress(function (e) {
+ var key = e.keyCode || e.which;
+
+ if (key === 13) {
+ Form_$(el).find('.matomo-save-button input').triggerHandler('click');
+ }
+ });
+ });
+ }
+});
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/Form/Form.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 piwikForm() {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink(scope, element) {
+ Form.mounted(element[0]);
+ }
+ };
+}
+window.angular.module('piwikApp').directive('piwikForm', piwikForm);
+// CONCATENATED MODULE: ./plugins/CorePluginsAdmin/vue/src/index.ts
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+*/
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js
+
+
+
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=CorePluginsAdmin.umd.js.map
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.min.js b/app/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.min.js
new file mode 100644
index 000000000..0a1caaab3
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/dist/CorePluginsAdmin.umd.min.js
@@ -0,0 +1,71 @@
+(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue")):"function"===typeof define&&define.amd?define(["CoreHome"],t):"object"===typeof exports?exports["CorePluginsAdmin"]=t(require("CoreHome"),require("vue")):e["CorePluginsAdmin"]=t(e["CoreHome"],e["Vue"])})("undefined"!==typeof self?self:this,(function(e,t){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var i=t[o]={i:o,l:!1,exports:{}};return e[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},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 o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(o,i,function(t){return e[t]}.bind(null,i));return o},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/CorePluginsAdmin/vue/dist/",n(n.s="fae3")}({"19dc":function(t,n){t.exports=e},"8bbf":function(e,n){e.exports=t},fae3:function(e,t,n){"use strict";if(n.r(t),n.d(t,"FormField",(function(){return qt})),n.d(t,"Field",(function(){return Qt})),n.d(t,"PluginSettings",(function(){return Tn})),n.d(t,"PluginFilter",(function(){return no})),n.d(t,"PluginManagement",(function(){return Hn})),n.d(t,"PluginUpload",(function(){return Kn})),n.d(t,"SaveButton",(function(){return uo})),n.d(t,"Form",(function(){return mo})),n.d(t,"GroupedSettings",(function(){return wn})),"undefined"!==typeof window){var o=window.document.currentScript,i=o&&o.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);i&&(n.p=i[1])}var r=n("19dc"),l=n("8bbf"),a={class:"form-group row matomo-form-field"},u={key:0,class:"col s12"},c={key:0,class:"form-help"},s={key:0,class:"inline-help",ref:"inlineHelp"},d=Object(l["createElementVNode"])("br",null,null,-1);function m(e,t,n,o,i,r){return Object(l["withDirectives"])((Object(l["openBlock"])(),Object(l["createElementBlock"])("div",a,[e.formField.introduction?(Object(l["openBlock"])(),Object(l["createElementBlock"])("h3",u,Object(l["toDisplayString"])(e.formField.introduction),1)):Object(l["createCommentVNode"])("",!0),Object(l["createElementVNode"])("div",{class:Object(l["normalizeClass"])(["col s12",{"input-field":"checkbox"!==e.formField.uiControl&&"radio"!==e.formField.uiControl,"file-field":"file"===e.formField.uiControl,m6:!e.formField.fullWidth}])},[(Object(l["openBlock"])(),Object(l["createBlock"])(Object(l["resolveDynamicComponent"])(e.childComponent),Object(l["mergeProps"])(Object.assign(Object.assign({formField:e.formField},e.formField),{},{modelValue:e.processedModelValue,availableOptions:e.availableOptions},e.extraChildComponentParams),{"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.onChange(t)})}),null,16))],2),Object(l["createElementVNode"])("div",{class:Object(l["normalizeClass"])(["col s12",{m6:!e.formField.fullWidth}])},[e.showFormHelp?(Object(l["openBlock"])(),Object(l["createElementBlock"])("div",c,[Object(l["withDirectives"])(Object(l["createElementVNode"])("div",{class:"form-description"},Object(l["toDisplayString"])(e.formField.description),513),[[l["vShow"],e.formField.description]]),e.formField.inlineHelp||e.hasInlineHelpSlot?(Object(l["openBlock"])(),Object(l["createElementBlock"])("span",s,[e.inlineHelpComponent?(Object(l["openBlock"])(),Object(l["createBlock"])(Object(l["resolveDynamicComponent"])(e.inlineHelpComponent),Object(l["normalizeProps"])(Object(l["mergeProps"])({key:0},e.inlineHelpBind)),null,16)):Object(l["createCommentVNode"])("",!0),Object(l["renderSlot"])(e.$slots,"inline-help")],512)):Object(l["createCommentVNode"])("",!0),Object(l["withDirectives"])(Object(l["createElementVNode"])("span",null,[d,Object(l["createTextVNode"])(" "+Object(l["toDisplayString"])(e.translate("General_Default"))+": ",1),Object(l["createElementVNode"])("span",null,Object(l["toDisplayString"])(e.defaultValuePrettyTruncated),1)],512),[[l["vShow"],e.showDefaultValue]])])):Object(l["createCommentVNode"])("",!0)],2)],512)),[[l["vShow"],e.showField]])}var f={class:"checkbox"},p=["checked","id","name"],b=["innerHTML"];function v(e,t,n,o,i,r){return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",f,[Object(l["createElementVNode"])("label",null,[Object(l["createElementVNode"])("input",Object(l["mergeProps"])({onChange:t[0]||(t[0]=function(t){return e.onChange(t)})},e.uiControlAttributes,{value:1,checked:e.isChecked,type:"checkbox",id:e.name,name:e.name}),null,16,p),Object(l["createElementVNode"])("span",{innerHTML:e.$sanitize(e.title)},null,8,b)])])}var h=Object(l["defineComponent"])({props:{modelValue:[Boolean,Number,String],uiControlAttributes:Object,name:String,title:String},inheritAttrs:!1,emits:["update:modelValue"],methods:{onChange:function(e){this.modelValue!==e.target.checked&&this.$emit("update:modelValue",e.target.checked)}},computed:{isChecked:function(){return!!this.modelValue&&"0"!==this.modelValue}}});h.render=v;var g=h,O=["value","checked","onChange","id","name"];function j(e,t,n,o,i,r){return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",null,[Object(l["withDirectives"])(Object(l["createElementVNode"])("label",{class:"fieldRadioTitle"},Object(l["toDisplayString"])(e.title),513),[[l["vShow"],e.title]]),(Object(l["openBlock"])(!0),Object(l["createElementBlock"])(l["Fragment"],null,Object(l["renderList"])(e.availableOptions,(function(t,n){return Object(l["openBlock"])(),Object(l["createElementBlock"])("p",{key:n,class:"checkbox"},[Object(l["createElementVNode"])("label",null,[Object(l["createElementVNode"])("input",Object(l["mergeProps"])({value:t.key,checked:!!e.checkboxStates[n],onChange:function(t){return e.onChange(n)}},e.uiControlAttributes,{type:"checkbox",id:"".concat(e.name).concat(t.key),name:t.name}),null,16,O),Object(l["createElementVNode"])("span",null,Object(l["toDisplayString"])(t.value),1),Object(l["withDirectives"])(Object(l["createElementVNode"])("span",{class:"form-description"},Object(l["toDisplayString"])(t.description),513),[[l["vShow"],t.description]])])])})),128))])}function y(e){return S(e)||C(e)||w(e)||V()}function V(){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 w(e,t){if(e){if("string"===typeof e)return k(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)?k(e,t):void 0}}function C(e){if("undefined"!==typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function S(e){if(Array.isArray(e))return k(e)}function k(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);ne.length)&&(t=e.length);for(var n=0,o=new Array(t);ne.length)&&(t=e.length);for(var n=0,o=new Array(t);n3&&void 0!==arguments[3]?arguments[3]:{},i=arguments.length>4?arguments[4]:void 0;if(e){var r=window.$(e);if(Array.from(e.options).forEach((function(e){e.selected=i?!!t&&-1!==t.indexOf(e.value.replace(/^string:/,"")):"string:".concat(t)===e.value})),r.formSelect(o),n){var l=r.closest(".select-wrapper").find("input");l.attr("placeholder",n)}}}function We(e){return!Array.isArray(e)&&"object"===Re(e)&&Object.values(e).some((function(e){return"object"===Re(e)}))}function Ze(e,t){return e.some((function(e){return e.key===t}))}function Ye(e,t,n){if(!e)return[];var o=!0,i=e;We(i)||(i={"":e},o=!1);var r=[];return Object.entries(i).forEach((function(e){var n=Le(e,2),i=n[0],l=n[1];Object.entries(l).forEach((function(e){var n=Le(e,2),l=n[0],a=n[1];if(a&&"object"===Re(a)&&"undefined"!==typeof a.key)r.push(a);else{var u=l;"integer"===t&&"string"===typeof l&&(u=parseInt(l,10)),r.push({group:o?i:void 0,key:u,value:a})}}))})),null!==n&&void 0!==n&&n.placeholder&&!Ze(r,"")?[{key:"",value:""}].concat(r):r}function Qe(e){return"string"===typeof e?e.replace(/^string:/,""):e}var Xe=Object(l["defineComponent"])({props:{modelValue:null,multiple:Boolean,name:String,title:String,availableOptions:Array,uiControlAttributes:Object,uiControlOptions:Object},inheritAttrs:!1,emits:["update:modelValue"],computed:{options:function(){var e=this.availableOptions;return!e||Ze(e,"")||"undefined"!==typeof this.modelValue&&null!==this.modelValue&&""!==this.modelValue?e:[{key:"",value:this.modelValue,group:this.hasGroups?"":void 0}].concat(Je(e))},hasGroups:function(){var e=this.availableOptions;return e&&e[0]&&"undefined"!==typeof e[0].group},groupedOptions:function(){var e=this.options;if(!this.hasGroups||!e)return null;var t={};e.forEach((function(e){var n=e.group;t[n]=t[n]||[],t[n].push(e)}));var n=Object.entries(t);return n.sort((function(e,t){return e[0]t[0]?1:0})),n}},methods:{onChange:function(e){var t,n=this,o=e.target;this.multiple?(t=Array.from(o.options).filter((function(e){return e.selected})).map((function(e){return e.value})),t=t.map((function(e){return Qe(e)}))):(t=o.value,t=Qe(t)),this.$emit("update:modelValue",t),Object(l["nextTick"])((function(){n.modelValue!==t&&n.onModelValueChange(n.modelValue)}))},onModelValueChange:function(e){var t=this;window.$(this.$refs.select).val(e),setTimeout((function(){var n;Ge(t.$refs.select,e,null===(n=t.uiControlAttributes)||void 0===n?void 0:n.placeholder,t.uiControlOptions,t.multiple)}))}},watch:{modelValue:function(e){this.onModelValueChange(e)},"uiControlAttributes.disabled":{handler:function(e,t){var n=this;setTimeout((function(){var o;e!==t&&Ge(n.$refs.select,n.modelValue,null===(o=n.uiControlAttributes)||void 0===o?void 0:o.placeholder,n.uiControlOptions,n.multiple)}))}},availableOptions:function(e,t){var n=this;e!==t&&setTimeout((function(){var e;Ge(n.$refs.select,n.modelValue,null===(e=n.uiControlAttributes)||void 0===e?void 0:e.placeholder,n.uiControlOptions,n.multiple)}))}},mounted:function(){var e=this;setTimeout((function(){var t;Ge(e.$refs.select,e.modelValue,null===(t=e.uiControlAttributes)||void 0===t?void 0:t.placeholder,e.uiControlOptions,e.multiple)}))}});Xe.render=Pe;var et=Xe,tt=["for","innerHTML"],nt={class:"sites_autocomplete"};function ot(e,t,n,o,i,r){var a=Object(l["resolveComponent"])("SiteSelector");return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",null,[Object(l["createElementVNode"])("label",{for:e.name,class:"siteSelectorLabel",innerHTML:e.$sanitize(e.title)},null,8,tt),Object(l["createElementVNode"])("div",nt,[Object(l["createVNode"])(a,Object(l["mergeProps"])({"model-value":e.modelValue,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.onChange(t)}),id:e.name,"show-all-sites-item":e.uiControlAttributes.showAllSitesItem||!1,"switch-site-on-select":!1,"show-selected-site":!0,"only-sites-with-admin-access":e.uiControlAttributes.onlySitesWithAdminAccess||!1},e.uiControlAttributes),null,16,["model-value","id","show-all-sites-item","only-sites-with-admin-access"])])])}var it=Object(l["defineComponent"])({props:{name:String,title:String,modelValue:Object,uiControlAttributes:Object},inheritAttrs:!1,components:{SiteSelector:r["SiteSelector"]},emits:["update:modelValue"],methods:{onChange:function(e){this.$emit("update:modelValue",e)}}});it.render=ot;var rt=it,lt=["type","id","name","value"],at=["for","innerHTML"];function ut(e,t,n,o,i,r){return Object(l["openBlock"])(),Object(l["createElementBlock"])(l["Fragment"],null,[Object(l["createElementVNode"])("input",Object(l["mergeProps"])({class:"control_".concat(e.uiControl),type:e.uiControl,id:e.name,name:e.name,value:e.modelValueText,onKeydown:t[0]||(t[0]=function(t){return e.onKeydown(t)}),onChange:t[1]||(t[1]=function(t){return e.onKeydown(t)})},e.uiControlAttributes),null,16,lt),Object(l["createElementVNode"])("label",{for:e.name,innerHTML:e.$sanitize(e.title)},null,8,at)],64)}var ct=Object(l["defineComponent"])({props:{title:String,name:String,uiControlAttributes:Object,modelValue:[String,Number],uiControl:String},inheritAttrs:!1,emits:["update:modelValue"],computed:{modelValueText:function(){return"undefined"===typeof this.modelValue||null===this.modelValue?"":this.modelValue.toString()}},created:function(){this.onKeydown=Object(r["debounce"])(this.onKeydown.bind(this),50)},mounted:function(){setTimeout((function(){window.Materialize.updateTextFields()}))},watch:{modelValue:function(){setTimeout((function(){window.Materialize.updateTextFields()}))}},methods:{onKeydown:function(e){var t=e.target.value;this.modelValue!==t&&this.$emit("update:modelValue",t)}}});ct.render=ut;var st=ct,dt=["for","innerHTML"],mt=["type","name","value"];function ft(e,t,n,o,i,r){return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",null,[Object(l["createElementVNode"])("label",{for:e.name,innerHTML:e.$sanitize(e.title)},null,8,dt),Object(l["createElementVNode"])("input",Object(l["mergeProps"])({class:"control_".concat(e.uiControl),type:e.uiControl,name:e.name,onKeydown:t[0]||(t[0]=function(t){return e.onKeydown(t)}),onChange:t[1]||(t[1]=function(t){return e.onKeydown(t)}),value:e.concattedValues},e.uiControlAttributes),null,16,mt)])}var pt=Object(l["defineComponent"])({props:{name:String,title:String,uiControl:String,modelValue:Array,uiControlAttributes:Object},inheritAttrs:!1,computed:{concattedValues:function(){return"string"===typeof this.modelValue?this.modelValue:(this.modelValue||[]).join(", ")}},emits:["update:modelValue"],created:function(){this.onKeydown=Object(r["debounce"])(this.onKeydown.bind(this),50)},methods:{onKeydown:function(e){var t=e.target.value.split(",").map((function(e){return e.trim()}));t.join(", ")!==this.concattedValues&&this.$emit("update:modelValue",t)}}});pt.render=ft;var bt=pt,vt=["name","id","value"],ht=["for","innerHTML"];function gt(e,t,n,o,i,r){return Object(l["openBlock"])(),Object(l["createElementBlock"])(l["Fragment"],null,[Object(l["createElementVNode"])("textarea",Object(l["mergeProps"])({name:e.name},e.uiControlAttributes,{id:e.name,value:e.modelValue,onKeydown:t[0]||(t[0]=function(t){return e.onKeydown(t)}),onChange:t[1]||(t[1]=function(t){return e.onKeydown(t)}),class:"materialize-textarea",ref:"textarea"}),null,16,vt),Object(l["createElementVNode"])("label",{for:e.name,innerHTML:e.$sanitize(e.title)},null,8,ht)],64)}var Ot=Object(l["defineComponent"])({props:{name:String,uiControlAttributes:Object,modelValue:String,title:String},inheritAttrs:!1,emits:["update:modelValue"],created:function(){this.onKeydown=Object(r["debounce"])(this.onKeydown.bind(this),50)},methods:{onKeydown:function(e){this.$emit("update:modelValue",e.target.value)}},watch:{modelValue:function(){var e=this;setTimeout((function(){window.Materialize.textareaAutoResize(e.$refs.textarea),window.Materialize.updateTextFields()}))}},mounted:function(){var e=this;setTimeout((function(){window.Materialize.textareaAutoResize(e.$refs.textarea),window.Materialize.updateTextFields()}))}});Ot.render=gt;var jt=Ot,yt=["for","innerHTML"],Vt=["name","value"];function wt(e,t,n,o,i,r){return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",null,[Object(l["createElementVNode"])("label",{for:e.name,innerHTML:e.$sanitize(e.title)},null,8,yt),Object(l["createElementVNode"])("textarea",Object(l["mergeProps"])({ref:"textarea",name:e.name},e.uiControlAttributes,{value:e.concattedValue,onKeydown:t[0]||(t[0]=function(t){return e.onKeydown(t)}),onChange:t[1]||(t[1]=function(t){return e.onKeydown(t)}),class:"materialize-textarea"}),null,16,Vt)])}var Ct="\n",St=Object(l["defineComponent"])({props:{name:String,title:String,uiControlAttributes:Object,modelValue:[Array,String]},inheritAttrs:!1,emits:["update:modelValue"],computed:{concattedValue:function(){return"string"===typeof this.modelValue?this.modelValue:(this.modelValue||[]).join(Ct)}},created:function(){this.onKeydown=Object(r["debounce"])(this.onKeydown.bind(this),50)},methods:{onKeydown:function(e){var t=e.target.value.split(Ct);t.join(Ct)!==this.concattedValue&&this.$emit("update:modelValue",t)}},watch:{modelValue:function(e,t){var n=this;e!==t&&setTimeout((function(){n.$refs.textarea&&window.Materialize.textareaAutoResize(n.$refs.textarea),window.Materialize.updateTextFields()}))}},mounted:function(){var e=this;setTimeout((function(){e.$refs.textarea&&window.Materialize.textareaAutoResize(e.$refs.textarea),window.Materialize.updateTextFields()}))}});St.render=wt;var kt=St;function At(e){return At="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},At(e)}function Ft(e,t){return Tt(e)||Nt(e,t)||Et(e,t)||Bt()}function Bt(){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 Et(e,t){if(e){if("string"===typeof e)return xt(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)?xt(e,t):void 0}}function xt(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);n ")),i=r["Matomo"].helper.getAngularDependency("$timeout"),a=r["Matomo"].helper.getAngularDependency("$rootScope"),u=a.$new();return u.formField=Object.assign(Object.assign({},Jt(e.formField)),{},{value:Jt(e.modelValue)}),u.$watch("formField.value",(function(n,o){n!==o&&JSON.stringify(n)!==JSON.stringify(e.modelValue)&&t.emit("update:modelValue",Jt(n))})),Object(l["watch"])((function(){return e.modelValue}),(function(e){JSON.stringify(e)!==JSON.stringify(u.formField.value)&&i((function(){u.formField.value=e}))})),Object(l["watch"])((function(){return e.formField}),(function(e){i((function(){var t=u.formField.value;u.formField=Object.assign(Object.assign({},Jt(e)),{},{value:t})}))}),{deep:!0}),Object(l["onMounted"])((function(){window.$(n.value).append(o),r["Matomo"].helper.compileAngularComponents(o,{scope:u,params:{formField:Object.assign(Object.assign({},Jt(e.formField)),{},{value:e.modelValue})}})})),{root:n}}});Ht.render=Pt;var Dt=Ht;function It(e){return It="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},It(e)}var Lt=["password","url","search","email"],zt=["textarea","checkbox","text"],Ut={checkbox:"FieldCheckbox","expandable-select":"FieldExpandableSelect","field-array":"FieldFieldArray",file:"FieldFile",hidden:"FieldHidden",multiselect:"FieldSelect",multituple:"FieldMultituple",number:"FieldNumber",radio:"FieldRadio",select:"FieldSelect",site:"FieldSite",text:"FieldText",textarea:"FieldTextarea"},Kt={FieldSelect:Ye,FieldCheckboxArray:$t,FieldRadio:$t,FieldExpandableSelect:z},_t=Object(l["defineComponent"])({props:{modelValue:null,formField:{type:Object,required:!0}},emits:["update:modelValue"],components:{FieldCheckbox:g,FieldCheckboxArray:B,FieldExpandableSelect:K,FieldFieldArray:G,FieldFile:ne,FieldHidden:le,FieldMultituple:de,FieldNumber:ve,FieldRadio:je,FieldSelect:et,FieldSite:rt,FieldText:st,FieldTextArray:bt,FieldTextarea:jt,FieldTextareaArray:kt},setup:function(e){var t=Object(l["ref"])(null),n=function(e){var n;e&&t.value&&"function"!==typeof e.render&&(n="string"===typeof e?0===e.indexOf("#")?window.$(e):window.vueSanitize(e):e,window.$(t.value).html("").append(n))};return Object(l["watch"])((function(){return e.formField.inlineHelp}),n),Object(l["onMounted"])((function(){n(e.formField.inlineHelp)})),{inlineHelp:t}},computed:{inlineHelpComponent:function(){var e=this.formField,t=e.inlineHelp;if(t&&"function"===typeof t.render)return e.inlineHelp},inlineHelpBind:function(){return this.inlineHelpComponent?this.formField.inlineHelpBind:void 0},childComponent:function(){var e=this.formField;if(e.component){var t=e.component;if(e.component.plugin){var n=e.component,o=n.plugin,i=n.name;if(!o||!i)throw new Error("Invalid component property given to piwik-field directive, must be {plugin: '...',name: '...'}");t=Object(r["useExternalPluginComponent"])(o,i)}return Object(l["markRaw"])(t)}if(e.templateFile)return Object(l["markRaw"])(Dt);var a=e.uiControl,u=Ut[a];return-1!==Lt.indexOf(a)&&(u="FieldText"),"array"===this.formField.type&&-1!==zt.indexOf(a)&&(u="".concat(u,"Array")),u},extraChildComponentParams:function(){return"multiselect"===this.formField.uiControl?{multiple:!0}:{}},showFormHelp:function(){return this.formField.description||this.formField.inlineHelp||this.showDefaultValue||this.hasInlineHelpSlot},showDefaultValue:function(){return this.defaultValuePretty&&"checkbox"!==this.formField.uiControl&&"radio"!==this.formField.uiControl},showField:function(){return!(this.formField&&this.formField.condition&&this.formField.condition instanceof Function)||this.formField.condition()},processedModelValue:function(){var e=this.formField;if("boolean"===e.type){var t=this.modelValue&&this.modelValue>0&&"0"!==this.modelValue;if("checkbox"===e.uiControl)return t;if("radio"===e.uiControl)return t?"1":"0"}return this.modelValue},defaultValue:function(){var e=this.formField.defaultValue;return Array.isArray(e)?e.join(","):e},availableOptions:function(){var e=this.childComponent;if("string"!==typeof e)return null;var t=this.formField;return t.availableValues&&Kt[e]?Kt[e](t.availableValues,t.type,t.uiControlAttributes):null},defaultValuePretty:function(){var e=this.formField,t=e.defaultValue,n=this.availableOptions;if("string"===typeof t&&t){var o=null;try{o=JSON.parse(t)}catch(r){}if(null!==o&&"object"===It(o))return""}if(!Array.isArray(n))return Array.isArray(t)?"":t?"".concat(t):"";var i=[];return Array.isArray(t)||(t=[t]),(n||[]).forEach((function(e){"undefined"!==typeof e.value&&-1!==t.indexOf(e.key)&&i.push(e.value)})),i.join(", ")},defaultValuePrettyTruncated:function(){return this.defaultValuePretty.substring(0,50)},hasInlineHelpSlot:function(){var e,t;if(!this.$slots["inline-help"])return!1;var n=this.$slots["inline-help"]();return!(null===n||void 0===n||null===(e=n[0])||void 0===e||null===(t=e.children)||void 0===t||!t.length)}},methods:{onChange:function(e){this.$emit("update:modelValue",e)}}});_t.render=m;var qt=_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 Rt(e){if(e){var t=e.plugin,n=e.name;if(!t||!n)throw new Error("Invalid component property given to piwik-field directive, must be {plugin: '...',name: '...'}");return Object(r["useExternalPluginComponent"])(t,n)}}function Gt(e,t){var n={};return Object.values(e.allSettings||{}).forEach((function(e){"0"===e.value?n[e.name]=0:n[e.name]=e.value})),e.$eval(t,n)}Object(r["createAngularJsAdapter"])({component:qt,scope:{modelValue:{default:function(e){var t=e.piwikFormField;return"string"!==typeof t.value||!t.value||"array"!==t.type&&"multituple"!==t.uiControl&&"field-array"!==t.uiControl&&"multiselect"!==t.uiControl&&"site"!==t.uiControl||(t.value=JSON.parse(t.value)),"checkbox"===t.uiControl?Object(r["transformAngularJsBoolAttr"])(t.value):t.value}},piwikFormField:{vue:"formField",angularJsBind:"=",transform:function(e,t,n){var o=e;function i(){if(o.templateFile)return Object(l["markRaw"])(Dt);var e=Rt(o.component);return e?Object(l["markRaw"])(e):void 0}return Object.assign(Object.assign({},o),{},{condition:o.condition?Gt.bind(null,n,o.condition):o.condition,disabled:Object(r["transformAngularJsBoolAttr"])(o.disabled),autocomplete:Object(r["transformAngularJsBoolAttr"])(o.autocomplete),autofocus:Object(r["transformAngularJsBoolAttr"])(o.autofocus),tabindex:Object(r["transformAngularJsIntAttr"])(o.tabindex),fullWidth:Object(r["transformAngularJsBoolAttr"])(o.fullWidth),maxlength:Object(r["transformAngularJsIntAttr"])(o.maxlength),required:Object(r["transformAngularJsBoolAttr"])(o.required),rows:Object(r["transformAngularJsIntAttr"])(o.rows),min:Object(r["transformAngularJsIntAttr"])(o.min),max:Object(r["transformAngularJsIntAttr"])(o.max),component:i()})}},allSettings:{angularJsBind:"="}},directiveName:"piwikFormField",events:{"update:modelValue":function(e,t,n,o,i,r,l){e!==n.piwikFormField.value&&l((function(){n.piwikFormField.value=e}))}},$inject:["$timeout"],postCreate:function(e,t){t.$watch("piwikFormField.value",(function(t,n){t!==n&&(e.modelValue=t)})),t.$watch("allSettings",(function(){e.formField=Object.assign(Object.assign({},e.formField),{},{condition:t.piwikFormField.condition?Gt.bind(null,t,t.piwikFormField.condition):t.piwikFormField.condition})}),!0)}});function Wt(e,t,n,o,i,r){var a=Object(l["resolveComponent"])("FormField");return Object(l["openBlock"])(),Object(l["createBlock"])(a,{"form-field":e.field,"model-value":e.modelValue,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.onChange(t)})},{"inline-help":Object(l["withCtx"])((function(){return[Object(l["renderSlot"])(e.$slots,"inline-help")]})),_:3},8,["form-field","model-value"])}var Zt={multiselect:"array",checkbox:"boolean",site:"object",number:"integer"},Yt=Object(l["defineComponent"])({props:{modelValue:null,uicontrol:String,name:String,defaultValue:null,options:[Object,Array],description:String,introduction:String,title:String,inlineHelp:[String,Object],inlineHelpBind:Object,disabled:Boolean,uiControlAttributes:{type:Object,default:function(){return{}}},uiControlOptions:{type:Object,default:function(){return{}}},autocomplete:Boolean,condition:Function,varType:String,autofocus:Boolean,tabindex:Number,fullWidth:Boolean,maxlength:Number,required:Boolean,placeholder:String,rows:Number,min:Number,max:Number,component:null,templateFile:String},emits:["update:modelValue"],components:{FormField:qt},computed:{type:function(){if(this.varType)return this.varType;var e=this.uicontrol;return e&&Zt[e]?Zt[e]:"string"},field:function(){return{uiControl:this.uicontrol,type:this.type,name:this.name,defaultValue:this.defaultValue,availableValues:this.options,description:this.description,introduction:this.introduction,inlineHelp:this.inlineHelp,inlineHelpBind:this.inlineHelpBind,title:this.title,component:this.component,templateFile:this.templateFile,uiControlAttributes:Object.assign(Object.assign({},this.uiControlAttributes),{},{disabled:this.disabled,autocomplete:this.autocomplete,tabindex:this.tabindex,autofocus:this.autofocus,rows:this.rows,required:this.required,maxlength:this.maxlength,placeholder:this.placeholder,min:this.min,max:this.max}),fullWidth:this.fullWidth,uiControlOptions:this.uiControlOptions}}},methods:{onChange:function(e){this.$emit("update:modelValue",e)}}});Yt.render=Wt;var Qt=Yt;
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */function Xt(e,t,n){if("string"===typeof e&&e&&("array"===t||"multituple"===n||"field-array"===n||"multiselect"===n||"site"===n)){var o=JSON.parse(e);return"site"===n&&(o.name=r["Matomo"].helper.htmlDecode(o.name)),o}return"checkbox"===n&&"array"!==t?Object(r["transformAngularJsBoolAttr"])(e):e}Object(r["createAngularJsAdapter"])({component:Qt,require:"?ngModel",scope:{uicontrol:{angularJsBind:"@"},name:{angularJsBind:"@"},value:{vue:"modelValue",angularJsBind:"@",transform:function(e,t,n){return Xt(e,n.varType,n.uicontrol)}},default:{vue:"defaultValue",angularJsBind:"@"},options:{angularJsBind:"="},description:{angularJsBind:"@"},introduction:{angularJsBind:"@"},title:{angularJsBind:"@"},inlineHelp:{angularJsBind:"@"},disabled:{angularJsBind:"=",transform:r["transformAngularJsBoolAttr"]},uiControlAttributes:{angularJsBind:"="},uiControlOptions:{angularJsBind:"="},autocomplete:{angularJsBind:"@",transform:r["transformAngularJsBoolAttr"]},condition:{angularJsBind:"@",transform:function(e,t,n){if(e)return function(t){return n.$eval(e,t)}}},varType:{angularJsBind:"@"},autofocus:{angularJsBind:"@",transform:r["transformAngularJsBoolAttr"]},tabindex:{angularJsBind:"@",transform:r["transformAngularJsIntAttr"]},fullWidth:{angularJsBind:"@",transform:r["transformAngularJsBoolAttr"]},maxlength:{angularJsBind:"@",transform:r["transformAngularJsIntAttr"]},required:{angularJsBind:"@",transform:r["transformAngularJsBoolAttr"]},placeholder:{angularJsBind:"@"},rows:{angularJsBind:"@",transform:r["transformAngularJsIntAttr"]},min:{angularJsBind:"@",transform:r["transformAngularJsIntAttr"]},max:{angularJsBind:"@",transform:r["transformAngularJsIntAttr"]},component:{angularJsBind:"<",transform:function(e,t,n){if(e){if(n.templateFile)return Object(l["shallowRef"])(Dt);var o=e.plugin,i=e.name;if(!o||!i)throw new Error("Invalid component property given to piwik-field directive, must be {plugin: '...',name: '...'}");return Object(l["shallowRef"])(Object(r["useExternalPluginComponent"])(o,i))}}}},directiveName:"piwikField",$inject:["$timeout"],events:{"update:modelValue":function(e,t,n,o,i,r,l){var a=r?r.$viewValue:n.value;e!==a&&l((function(){r?(r.$setViewValue(e),r.$render()):n.value=e}))}},postCreate:function(e,t,n,o,i){var a=i;if(a){if(a.$render=function(){Object(l["nextTick"])((function(){e.modelValue=Object(r["removeAngularJsSpecificProperties"])(a.$viewValue)}))},"undefined"!==typeof t.value){var u=Xt(t.value,t.varType,t.uicontrol);a.$setViewValue(u)}else a.$setViewValue(e.modelValue);"site"===t.uicontrol&&a.$viewValue&&setTimeout((function(){a.$setViewValue(Object.assign({},a.$viewValue))}))}else t.$watch("value",(function(n){if(n!==e.modelValue){var o=Xt(n,t.varType,t.uicontrol);Object(l["nextTick"])((function(){e.modelValue=o}))}}))}});var en,tn={class:"pluginSettings",ref:"root"},nn=["id"],on={class:"card-content"},rn=["id"],ln=["onClick","disabled","value"],an={class:"confirm-password-modal modal"},un={class:"modal-content"},cn={class:"modal-footer"},sn=["disabled"];function dn(e,t,n,o,i,r){var a=this,u=Object(l["resolveComponent"])("GroupedSettings"),c=Object(l["resolveComponent"])("ActivityIndicator"),s=Object(l["resolveComponent"])("Field");return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",tn,[(Object(l["openBlock"])(!0),Object(l["createElementBlock"])(l["Fragment"],null,Object(l["renderList"])(e.settingsPerPlugin,(function(t){return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",{class:"card",id:"".concat(t.pluginName,"PluginSettings"),key:"".concat(t.pluginName,"PluginSettings")},[Object(l["createElementVNode"])("div",on,[Object(l["createElementVNode"])("h2",{class:"card-title",id:t.pluginName},Object(l["toDisplayString"])(t.title),9,rn),Object(l["createVNode"])(u,{"group-name":t.pluginName,settings:t.settings,"all-setting-values":e.settingValues,onChange:function(n){return e.settingValues["".concat(t.pluginName,".").concat(n.name)]=n.value}},null,8,["group-name","settings","all-setting-values","onChange"]),Object(l["createElementVNode"])("input",{type:"button",onClick:function(n){return e.saveSetting(t.pluginName)},disabled:e.isLoading,class:"pluginsSettingsSubmit btn",value:e.translate("General_Save")},null,8,ln),Object(l["createVNode"])(c,{loading:e.isLoading||e.isSaving[t.pluginName]},null,8,["loading"])])],8,nn)})),128)),Object(l["createElementVNode"])("div",an,[Object(l["createElementVNode"])("div",un,[Object(l["createElementVNode"])("h2",null,Object(l["toDisplayString"])(e.translate("UsersManager_ConfirmWithPassword")),1),Object(l["createElementVNode"])("div",null,[Object(l["createVNode"])(s,{modelValue:e.passwordConfirmation,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.passwordConfirmation=t}),uicontrol:"password",name:"currentUserPassword",autocomplete:!1,"full-width":!0,title:e.translate("UsersManager_YourCurrentPassword")},null,8,["modelValue","title"])])]),Object(l["createElementVNode"])("div",cn,[Object(l["createElementVNode"])("a",{href:"",class:"modal-action modal-close btn",disabled:e.passwordConfirmation?void 0:"disabled",onClick:t[1]||(t[1]=function(t){t.preventDefault(),e.save(a.settingsToSave)})},Object(l["toDisplayString"])(e.translate("General_Yes")),9,sn),Object(l["createElementVNode"])("a",{href:"",class:"modal-action modal-close modal-no",onClick:t[2]||(t[2]=function(e){return e.preventDefault()})},Object(l["toDisplayString"])(e.translate("General_No")),1)])])],512)}function mn(e,t,n,o,i,r){var a=Object(l["resolveComponent"])("GroupedSetting");return Object(l["openBlock"])(!0),Object(l["createElementBlock"])(l["Fragment"],null,Object(l["renderList"])(e.settings,(function(t){return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",{key:"".concat(e.groupPrefix).concat(t.name)},[Object(l["createVNode"])(a,{"model-value":e.allSettingValues["".concat(e.groupPrefix).concat(t.name)],"onUpdate:modelValue":function(n){return e.$emit("change",{name:t.name,value:n})},setting:t,"condition-values":e.settingValues},null,8,["model-value","onUpdate:modelValue","setting","condition-values"])])})),128)}function fn(e,t,n,o,i,r){var a=Object(l["resolveComponent"])("FormField");return Object(l["withDirectives"])((Object(l["openBlock"])(),Object(l["createElementBlock"])("div",null,[Object(l["createVNode"])(a,{"model-value":e.modelValue,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.changeValue(t)}),"form-field":e.settingWithComponent},null,8,["model-value","form-field"])],512)),[[l["vShow"],e.showField]])}var pn=Object(l["defineComponent"])({props:{setting:{type:Object,required:!0},modelValue:null,conditionValues:{type:Object,required:!0}},components:{FormField:qt},emits:["update:modelValue"],computed:{settingWithComponent:function(){return this.setting.templateFile?Object.assign(Object.assign({},this.setting),{},{component:Dt}):this.setting},showField:function(){var e=this.setting.condition;if(!e)return!0;if(!en){var t=r["Matomo"].helper.getAngularDependency("$rootScope");en=t.$new(!0)}return en.$eval(e,this.conditionValues)}},methods:{changeValue:function(e){this.$emit("update:modelValue",e)}}});pn.render=fn;var bn=pn;function vn(e,t){return yn(e)||jn(e,t)||gn(e,t)||hn()}function hn(){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 gn(e,t){if(e){if("string"===typeof e)return On(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)?On(e,t):void 0}}function On(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,o=new Array(t);ne.length)&&(t=e.length);for(var n=0,o=new Array(t);n').concat(t.introduction," "))})):e.append('').concat(n.replace(/([A-Z])/g," $1").trim()," ")))}))}},saveSetting:function(e){"admin"===this.mode?this.showPasswordConfirmModal(e):this.save(e)},showPasswordConfirmModal:function(e){var t=this;this.settingsToSave=e;var n=this.$refs.root,o=xn(n),i=function(n){var i=n.keyCode?n.keyCode:n.which;13===i&&(o.find(".confirm-password-modal").modal("close"),t.save(e))};o.find(".confirm-password-modal").modal({dismissible:!1,onOpenEnd:function(){var e=".modal.open #currentUserPassword";xn(e).focus(),xn(e).off("keypress").keypress(i)}}).modal("open")},save:function(e){var t=this,n=this.saveApiMethod;this.isSaving[e]=!0;var o=this.getValuesForPlugin(e);r["AjaxHelper"].post({method:n},{settingValues:o,passwordConfirmation:this.passwordConfirmation}).then((function(){t.isSaving[e]=!1;var n=r["NotificationsStore"].show({message:Object(r["translate"])("CoreAdminHome_PluginSettingsSaveSuccess"),id:"generalSettings",context:"success",type:"transient"});r["NotificationsStore"].scrollToNotification(n)})).catch((function(){t.isSaving[e]=!1})),this.passwordConfirmation="",this.settingsToSave=null},getValuesForPlugin:function(e){var t={};return t[e]||(t[e]=[]),Object.entries(this.settingValues).forEach((function(n){var o=Cn(n,2),i=o[0],r=o[1],l=i.split("."),a=Cn(l,2),u=a[0],c=a[1];if(u===e){var s=r;!1===s?s="0":!0===s&&(s="1"),t[u].push({name:c,value:s})}})),t}}});Nn.render=dn;var Tn=Nn,$n=(Object(r["createAngularJsAdapter"])({component:Tn,scope:{mode:{angularJsBind:"@"}},directiveName:"piwikPluginSettings"}),window),Mn=$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 Pn(e,t){t.preventDefault();var n=Mn(t.target).attr("href"),o=Mn(t.target).attr("data-plugin-name");if(n&&o){e.value.uninstallConfirmMessage||(e.value.uninstallConfirmMessage=Mn("#uninstallPluginConfirm").text());var i=(e.value.uninstallConfirmMessage||"").replace("%s",o);Mn("#uninstallPluginConfirm").text(i),r["Matomo"].helper.modalConfirm("#confirmUninstallPlugin",{yes:function(){window.location.href=n}})}}function Jn(e){e.preventDefault();var t=Mn(e.target).data("overlay-id");r["Matomo"].helper.modalConfirm("#".concat(t),{})}var Hn={mounted:function(e,t){setTimeout((function(){t.value.uninstallConfirmMessage="",Mn(e).find(".uninstall").click(Pn.bind(null,t)),Mn(e).find(".plugin-donation-link").click(Jn)}))}};
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */function Dn(){return{restrict:"A",link:function(e,t){var n={instance:null,value:{},oldValue:null,modifiers:{},dir:{}};Hn.mounted(t[0],n)}}}window.angular.module("piwikApp").directive("piwikPluginManagement",Dn);
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+var In=window,Ln=In.$;function zn(e){e.preventDefault(),r["Matomo"].helper.modalConfirm("#installPluginByUpload",{})}function Un(e){var t=Ln("[name=pluginZip]"),n=t.val();n&&".zip"===n.slice(-4)?t.data("maxSize")>0&&t[0].files[0].size>1048576*t.data("maxSize")&&(e.preventDefault(),alert(Object(r["translate"])("CorePluginsAdmin_FileExceedsUploadLimit"))):(e.preventDefault(),alert(Object(r["translate"])("CorePluginsAdmin_NoZipFileSelected")))}var Kn={mounted:function(){setTimeout((function(){Ln(".uploadPlugin").click(zn),Ln("#uploadPluginForm").submit(Un)}))}};
+/*!
+ * 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{restrict:"A",link:function(){Kn.mounted()}}}window.angular.module("piwikApp").directive("piwikPluginUpload",_n);
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+var qn=window,Rn=qn.$;function Gn(e){return e.find(".origin a.active").data("filter-origin")}function Wn(e){return e.find(".status a.active").data("filter-status")}function Zn(e,t){var n="#plugins tr";return n+="all"===e?"[data-filter-origin]":"[data-filter-origin=".concat(e,"]"),n+="all"===t?"[data-filter-status]":"[data-filter-status=".concat(t,"]"),Rn(n)}function Yn(e,t,n,o){var i=Zn(n,o).length,r=" (".concat(i,")");e.find("".concat(t," .counter")).text(r)}function Qn(e){var t=Gn(e),n=Wn(e);Yn(e,'[data-filter-status="all"]',t,"all"),Yn(e,'[data-filter-status="active"]',t,"active"),Yn(e,'[data-filter-status="inactive"]',t,"inactive"),Yn(e,'[data-filter-origin="all"]',"all",n),Yn(e,'[data-filter-origin="core"]',"core",n),Yn(e,'[data-filter-origin="official"]',"official",n),Yn(e,'[data-filter-origin="thirdparty"]',"thirdparty",n)}function Xn(e){var t=Gn(e),n=Wn(e),o=Zn(t,n);Rn("#plugins tr[data-filter-origin][data-filter-status]").css("display","none"),o.css("display","table-row"),Qn(e)}function eo(e,t){t.preventDefault(),Rn(t.target).siblings().removeClass("active"),Rn(t.target).addClass("active"),Xn(e)}function to(e,t){t.preventDefault(),Rn(t.target).siblings().removeClass("active"),Rn(t.target).addClass("active"),Xn(e)}var no={mounted:function(e){setTimeout((function(){Qn(Rn(e)),Rn(e).find(".status").on("click","a",eo.bind(null,Rn(e))),Rn(e).find(".origin").on("click","a",to.bind(null,Rn(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 oo(){return{restrict:"A",link:function(e,t){no.mounted(t[0])}}}window.angular.module("piwikApp").directive("piwikPluginFilter",oo);var io={class:"matomo-save-button",style:{display:"inline-block"}},ro=["disabled","value"];function lo(e,t,n,o,i,r){var a=Object(l["resolveComponent"])("ActivityIndicator");return Object(l["openBlock"])(),Object(l["createElementBlock"])("div",io,[Object(l["createElementVNode"])("input",{type:"button",onClick:t[0]||(t[0]=function(t){return e.onConfirm(t)}),disabled:e.saving||e.disabled,class:"btn",value:e.value?e.value:e.translate("General_Save")},null,8,ro),Object(l["createVNode"])(a,{loading:e.saving},null,8,["loading"])])}var ao=Object(l["defineComponent"])({props:{saving:Boolean,value:String,disabled:Boolean},components:{ActivityIndicator:r["ActivityIndicator"]},emits:["confirm"],methods:{onConfirm:function(e){this.$emit("confirm",e)}}});ao.render=lo;var uo=ao,co=(Object(r["createAngularJsAdapter"])({component:uo,scope:{saving:{angularJsBind:"=?"},value:{angularJsBind:"@?"},disabled:{angularJsBind:"=?"},onconfirm:{angularJsBind:"&?",vue:"confirm"}},events:{confirm:function(e,t,n,o,i,r,l){o[0].click(),l()}},replace:!0,directiveName:"piwikSaveButton",$inject:["$timeout"]}),window),so=co.$,mo={mounted:function(e){setTimeout((function(){so(e).find("input[type=text]").keypress((function(t){var n=t.keyCode||t.which;13===n&&so(e).find(".matomo-save-button input").triggerHandler("click")}))}))}};
+/*!
+ * 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 fo(){return{restrict:"A",link:function(e,t){mo.mounted(t[0])}}}window.angular.module("piwikApp").directive("piwikForm",fo)}})}));
+//# sourceMappingURL=CorePluginsAdmin.umd.min.js.map
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/vue/dist/umd.metadata.json b/app/plugins/CorePluginsAdmin/vue/dist/umd.metadata.json
new file mode 100644
index 000000000..9ecfcc045
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/dist/umd.metadata.json
@@ -0,0 +1,5 @@
+{
+ "dependsOn": [
+ "CoreHome"
+ ]
+}
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Field/Field.adapter.ts b/app/plugins/CorePluginsAdmin/vue/src/Field/Field.adapter.ts
new file mode 100644
index 000000000..209428c76
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Field/Field.adapter.ts
@@ -0,0 +1,238 @@
+/*!
+ * 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, IScope, ITimeoutService } from 'angular';
+import { nextTick, shallowRef } from 'vue';
+import {
+ createAngularJsAdapter,
+ transformAngularJsBoolAttr,
+ transformAngularJsIntAttr,
+ removeAngularJsSpecificProperties,
+ Matomo,
+ useExternalPluginComponent,
+} from 'CoreHome';
+import Field from './Field.vue';
+import FieldAngularJsTemplate from '../FormField/FieldAngularJsTemplate.vue';
+
+function handleJsonValue(value: unknown, varType: string, uiControl: string): unknown {
+ if (typeof value === 'string'
+ && value
+ && (varType === 'array'
+ || uiControl === 'multituple'
+ || uiControl === 'field-array'
+ || uiControl === 'multiselect'
+ || uiControl === 'site')
+ ) {
+ const result = JSON.parse(value);
+
+ // the angularjs site field supplied siteid/sitename properties which initializes the
+ // siteselector value. the sitename is assumed to be encoded, and is decoded once.
+ // so the value for 'site' Field's in angularjs is assumed to be encoded.
+ if (uiControl === 'site') {
+ result.name = Matomo.helper.htmlDecode(result.name);
+ }
+
+ return result;
+ }
+
+ if (uiControl === 'checkbox' && varType !== 'array') {
+ return transformAngularJsBoolAttr(value);
+ }
+
+ return value;
+}
+
+interface ExternalComponentRef {
+ plugin: string;
+ name: string;
+}
+
+export default createAngularJsAdapter<[ITimeoutService]>({
+ component: Field,
+ require: '?ngModel',
+ scope: {
+ uicontrol: {
+ angularJsBind: '@',
+ },
+ name: {
+ angularJsBind: '@',
+ },
+ value: {
+ vue: 'modelValue',
+ angularJsBind: '@',
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ transform(value: unknown, vm: unknown, scope: any): unknown {
+ // vue components expect object data as input, so we parse JSON data
+ // for angularjs directives that use JSON.
+ return handleJsonValue(value, scope.varType, scope.uicontrol);
+ },
+ },
+ default: {
+ vue: 'defaultValue',
+ angularJsBind: '@',
+ },
+ options: {
+ angularJsBind: '=',
+ },
+ description: {
+ angularJsBind: '@',
+ },
+ introduction: {
+ angularJsBind: '@',
+ },
+ title: {
+ angularJsBind: '@',
+ },
+ inlineHelp: {
+ angularJsBind: '@',
+ },
+ disabled: {
+ angularJsBind: '=',
+ transform: transformAngularJsBoolAttr,
+ },
+ uiControlAttributes: {
+ angularJsBind: '=',
+ },
+ uiControlOptions: {
+ angularJsBind: '=',
+ },
+ autocomplete: {
+ angularJsBind: '@',
+ transform: transformAngularJsBoolAttr,
+ },
+ condition: {
+ angularJsBind: '@',
+ transform(
+ value: unknown,
+ vm: unknown,
+ scope: IScope,
+ ): ((values: unknown[]) => boolean)|undefined {
+ if (!value) {
+ return undefined;
+ }
+
+ return (values: unknown[]) => (scope.$eval(value as string, values) as boolean);
+ },
+ },
+ varType: {
+ angularJsBind: '@',
+ },
+ autofocus: {
+ angularJsBind: '@',
+ transform: transformAngularJsBoolAttr,
+ },
+ tabindex: {
+ angularJsBind: '@',
+ transform: transformAngularJsIntAttr,
+ },
+ fullWidth: {
+ angularJsBind: '@',
+ transform: transformAngularJsBoolAttr,
+ },
+ maxlength: {
+ angularJsBind: '@',
+ transform: transformAngularJsIntAttr,
+ },
+ required: {
+ angularJsBind: '@',
+ transform: transformAngularJsBoolAttr,
+ },
+ placeholder: {
+ angularJsBind: '@',
+ },
+ rows: {
+ angularJsBind: '@',
+ transform: transformAngularJsIntAttr,
+ },
+ min: {
+ angularJsBind: '@',
+ transform: transformAngularJsIntAttr,
+ },
+ max: {
+ angularJsBind: '@',
+ transform: transformAngularJsIntAttr,
+ },
+ component: {
+ angularJsBind: '<',
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ transform(value: unknown, vm: unknown, scope: any) {
+ if (!value) {
+ return undefined;
+ }
+
+ if (scope.templateFile) {
+ return shallowRef(FieldAngularJsTemplate);
+ }
+
+ const { plugin, name } = value as ExternalComponentRef;
+ if (!plugin || !name) {
+ throw new Error('Invalid component property given to piwik-field directive, must '
+ + 'be {plugin: \'...\',name: \'...\'}');
+ }
+
+ return shallowRef(useExternalPluginComponent(plugin, name));
+ },
+ },
+ },
+ directiveName: 'piwikField',
+ $inject: ['$timeout'],
+ events: {
+ 'update:modelValue': (newValue, vm, scope, element, attrs, ngModel, $timeout) => {
+ const currentValue = ngModel ? ngModel.$viewValue : scope.value;
+ if (newValue !== currentValue) {
+ $timeout(() => {
+ if (!ngModel) {
+ scope.value = newValue;
+ return;
+ }
+
+ // ngModel being used
+ (ngModel as INgModelController).$setViewValue(newValue);
+ (ngModel as INgModelController).$render(); // not detected by the watch for some reason
+ });
+ }
+ },
+ },
+ postCreate(vm, scope, element, attrs, controller) {
+ const ngModel = controller as INgModelController;
+
+ if (!ngModel) {
+ scope.$watch('value', (newVal: unknown) => {
+ if (newVal !== vm.modelValue) {
+ const transformed = handleJsonValue(newVal, scope.varType, scope.uicontrol);
+
+ nextTick(() => {
+ vm.modelValue = transformed;
+ });
+ }
+ });
+ return;
+ }
+
+ // ngModel being used
+ ngModel.$render = () => {
+ nextTick(() => {
+ vm.modelValue = removeAngularJsSpecificProperties(ngModel.$viewValue);
+ });
+ };
+
+ if (typeof scope.value !== 'undefined') {
+ const transformed = handleJsonValue(scope.value, scope.varType, scope.uicontrol);
+ (ngModel as INgModelController).$setViewValue(transformed);
+ } else {
+ ngModel.$setViewValue(vm.modelValue);
+ }
+
+ // to provide same behavior in angularjs/<4.6.0, we trigger a model update to the same
+ // value, but only for 'site' uicontrols. this only happened for site selectors, no others.
+ if (scope.uicontrol === 'site' && ngModel.$viewValue) {
+ setTimeout(() => {
+ ngModel.$setViewValue({ ...ngModel.$viewValue });
+ });
+ }
+ },
+});
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Field/Field.vue b/app/plugins/CorePluginsAdmin/vue/src/Field/Field.vue
new file mode 100644
index 000000000..b564ec9ac
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Field/Field.vue
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Form/Form.adapter.ts b/app/plugins/CorePluginsAdmin/vue/src/Form/Form.adapter.ts
new file mode 100644
index 000000000..188f64f71
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Form/Form.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 Form from './Form';
+
+export default function piwikForm(): IDirective {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink(scope: IScope, element: JQuery) {
+ Form.mounted(element[0]);
+ },
+ };
+}
+
+window.angular.module('piwikApp').directive('piwikForm', piwikForm);
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Form/Form.ts b/app/plugins/CorePluginsAdmin/vue/src/Form/Form.ts
new file mode 100644
index 000000000..386eb2a6e
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Form/Form.ts
@@ -0,0 +1,21 @@
+/*!
+ * 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 {
+ setTimeout(() => {
+ $(el).find('input[type=text]').keypress((e) => {
+ const key = e.keyCode || e.which;
+ if (key === 13) {
+ $(el).find('.matomo-save-button input').triggerHandler('click');
+ }
+ });
+ });
+ },
+};
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldAngularJsTemplate.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldAngularJsTemplate.vue
new file mode 100644
index 000000000..c608e3368
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldAngularJsTemplate.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckbox.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckbox.vue
new file mode 100644
index 000000000..b07115f98
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckbox.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckboxArray.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckboxArray.vue
new file mode 100644
index 000000000..f6ba55569
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldCheckboxArray.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
{{ title }}
+
+
+
+ {{ checkboxModel.value }}
+
+
+ {{ checkboxModel.description }}
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.less b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.less
similarity index 100%
rename from app/plugins/CorePluginsAdmin/angularjs/form-field/field-expandable-select.less
rename to app/plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.less
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.vue
new file mode 100644
index 000000000..a91b91c37
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldExpandableSelect.vue
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ options.group }}
+
+
+
+
+
+ {{ children.value }}
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldFieldArray.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldFieldArray.vue
new file mode 100644
index 000000000..0ea559cd2
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldFieldArray.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldFile.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldFile.vue
new file mode 100644
index 000000000..bbdb7367d
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldFile.vue
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldHidden.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldHidden.vue
new file mode 100644
index 000000000..38c5ee248
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldHidden.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/angularjs/form-field/field-multituple.less b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.less
similarity index 100%
rename from app/plugins/CorePluginsAdmin/angularjs/form-field/field-multituple.less
rename to app/plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.less
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.vue
new file mode 100644
index 000000000..8a9213bef
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldMultituple.vue
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldNumber.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldNumber.vue
new file mode 100644
index 000000000..9b209d298
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldNumber.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldRadio.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldRadio.vue
new file mode 100644
index 000000000..d48b62a28
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldRadio.vue
@@ -0,0 +1,60 @@
+
+
+
+
+
{{ title }}
+
+
+
+
+
+
+ {{ radioModel.value }}
+
+
+ {{ radioModel.description }}
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.less b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.less
new file mode 100644
index 000000000..f65b95a63
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.less
@@ -0,0 +1,3 @@
+.matomo-field-select label {
+ top: -14px; // compensate for extra div added in vue
+}
\ No newline at end of file
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.vue
new file mode 100644
index 000000000..36b9a4451
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSelect.vue
@@ -0,0 +1,315 @@
+
+
+
+
+
+
+
+ {{ option.value }}
+
+
+
+
+
+
+
+
+ {{ option.value }}
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSite.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSite.vue
new file mode 100644
index 000000000..dedd60eba
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldSite.vue
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldText.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldText.vue
new file mode 100644
index 000000000..c240b3661
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldText.vue
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextArray.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextArray.vue
new file mode 100644
index 000000000..4290e910b
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextArray.vue
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextarea.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextarea.vue
new file mode 100644
index 000000000..2529663f9
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextarea.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextareaArray.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextareaArray.vue
new file mode 100644
index 000000000..bb1d684e7
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FieldTextareaArray.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FormField.adapter.ts b/app/plugins/CorePluginsAdmin/vue/src/FormField/FormField.adapter.ts
new file mode 100644
index 000000000..fad8f05cf
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FormField.adapter.ts
@@ -0,0 +1,150 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import { IScope, ITimeoutService } from 'angular';
+import {
+ createAngularJsAdapter,
+ transformAngularJsBoolAttr,
+ transformAngularJsIntAttr,
+ useExternalPluginComponent,
+} from 'CoreHome';
+import { markRaw } from 'vue';
+import FormField from './FormField.vue';
+import FieldAngularJsTemplate from './FieldAngularJsTemplate.vue';
+
+function transformVueComponentRef(value?: Record) {
+ if (!value) {
+ return undefined;
+ }
+
+ const { plugin, name } = value;
+ if (!plugin || !name) {
+ throw new Error('Invalid component property given to piwik-field directive, must be '
+ + '{plugin: \'...\',name: \'...\'}');
+ }
+
+ return useExternalPluginComponent(plugin, name);
+}
+
+interface Setting {
+ name: string;
+ value: unknown;
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function conditionFn(scope: any, condition: string) {
+ const values: Record = {};
+ Object.values((scope.allSettings || {}) as Record).forEach((setting) => {
+ if (setting.value === '0') {
+ values[setting.name] = 0;
+ } else {
+ values[setting.name] = setting.value;
+ }
+ });
+
+ return scope.$eval(condition, values);
+}
+
+export default createAngularJsAdapter<[ITimeoutService]>({
+ component: FormField,
+ scope: {
+ modelValue: {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ default(scope: any) {
+ const field = scope.piwikFormField;
+
+ // vue components expect object data as input, so we parse JSON data
+ // for angularjs directives that use JSON.
+ if (typeof field.value === 'string'
+ && field.value
+ && (field.type === 'array'
+ || field.uiControl === 'multituple'
+ || field.uiControl === 'field-array'
+ || field.uiControl === 'multiselect'
+ || field.uiControl === 'site')
+ ) {
+ field.value = JSON.parse(field.value);
+ }
+
+ if (field.uiControl === 'checkbox') {
+ return transformAngularJsBoolAttr(field.value);
+ }
+ return field.value;
+ },
+ },
+ piwikFormField: {
+ vue: 'formField',
+ angularJsBind: '=',
+ transform(v: unknown, vm: unknown, scope: IScope) {
+ const value = v as Record;
+
+ function getComponent() {
+ if (value.templateFile) {
+ return markRaw(FieldAngularJsTemplate);
+ }
+
+ const comp = transformVueComponentRef(value.component as Record);
+ if (!comp) {
+ return undefined;
+ }
+
+ return markRaw(comp);
+ }
+
+ return {
+ ...value,
+ condition: value.condition
+ ? conditionFn.bind(null, scope, value.condition as string)
+ : value.condition,
+ disabled: transformAngularJsBoolAttr(value.disabled),
+ autocomplete: transformAngularJsBoolAttr(value.autocomplete),
+ autofocus: transformAngularJsBoolAttr(value.autofocus),
+ tabindex: transformAngularJsIntAttr(value.tabindex),
+ fullWidth: transformAngularJsBoolAttr(value.fullWidth),
+ maxlength: transformAngularJsIntAttr(value.maxlength),
+ required: transformAngularJsBoolAttr(value.required),
+ rows: transformAngularJsIntAttr(value.rows),
+ min: transformAngularJsIntAttr(value.min),
+ max: transformAngularJsIntAttr(value.max),
+ component: getComponent(),
+ };
+ },
+ },
+ allSettings: {
+ angularJsBind: '=',
+ },
+ },
+ directiveName: 'piwikFormField',
+ events: {
+ 'update:modelValue': (newValue, vm, scope, element, attrs, controller, $timeout) => {
+ if (newValue !== scope.piwikFormField.value) {
+ $timeout(() => {
+ scope.piwikFormField.value = newValue;
+ });
+ }
+ },
+ },
+ $inject: ['$timeout'],
+ postCreate(vm, scope) {
+ scope.$watch('piwikFormField.value', (newVal: unknown, oldVal: unknown) => {
+ if (newVal !== oldVal) {
+ vm.modelValue = newVal;
+ }
+ });
+
+ // deep watch for all settings, on change trigger change in formfield property
+ // so condition is re-applied
+ scope.$watch('allSettings', () => {
+ vm.formField = {
+ ...vm.formField,
+ condition: scope.piwikFormField.condition
+ ? conditionFn.bind(null, scope, scope.piwikFormField.condition as string)
+ : scope.piwikFormField.condition,
+ };
+ }, true);
+ },
+});
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/FormField.vue b/app/plugins/CorePluginsAdmin/vue/src/FormField/FormField.vue
new file mode 100644
index 000000000..57186f0d9
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/FormField.vue
@@ -0,0 +1,412 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/FormField/utilities.ts b/app/plugins/CorePluginsAdmin/vue/src/FormField/utilities.ts
new file mode 100644
index 000000000..9a3a3864c
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/FormField/utilities.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
+ */
+
+interface Option {
+ key: string|number;
+ value: unknown;
+}
+
+export function processCheckboxAndRadioAvailableValues(
+ availableValues: Record|null,
+ type: string,
+): Option[] {
+ if (!availableValues) {
+ return [];
+ }
+
+ const flatValues: Option[] = [];
+ Object.entries(availableValues).forEach(([valueObjKey, value]) => {
+ if (value && typeof value === 'object' && typeof (value as Option).key !== 'undefined') {
+ flatValues.push(value as Option);
+ return;
+ }
+
+ let key: number|string = valueObjKey;
+ if (type === 'integer' && typeof valueObjKey === 'string') {
+ key = parseInt(key, 10);
+ }
+
+ flatValues.push({ key, value });
+ });
+
+ return flatValues;
+}
diff --git a/app/plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSetting.vue b/app/plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSetting.vue
new file mode 100644
index 000000000..075903db2
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSetting.vue
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue b/app/plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue
new file mode 100644
index 000000000..d28b7bfd7
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/GroupedSettings/GroupedSettings.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.adapter.ts b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.adapter.ts
new file mode 100644
index 000000000..30dace60e
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.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 'CoreHome';
+import PluginSettings from './PluginSettings.vue';
+
+export default createAngularJsAdapter({
+ component: PluginSettings,
+ scope: {
+ mode: {
+ angularJsBind: '@',
+ },
+ },
+ directiveName: 'piwikPluginSettings',
+});
diff --git a/app/plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.less b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.less
similarity index 100%
rename from app/plugins/CorePluginsAdmin/angularjs/plugin-settings/plugin-settings.directive.less
rename to app/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.less
diff --git a/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue
new file mode 100644
index 000000000..8f35adae0
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/PluginSettings.vue
@@ -0,0 +1,253 @@
+
+
+
+
+
+
+
{{ settings.title }}
+
+
+
+
+
+
+
+
{{ translate('UsersManager_ConfirmWithPassword') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/Setting.ts b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/Setting.ts
new file mode 100644
index 000000000..6f661eff4
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/Setting.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
+ */
+
+interface Setting {
+ name: string;
+ value: any; // eslint-disable-line
+ introduction?: string;
+}
+
+export default Setting;
diff --git a/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/SettingsForSinglePlugin.ts b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/SettingsForSinglePlugin.ts
new file mode 100644
index 000000000..515635709
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/PluginSettings/SettingsForSinglePlugin.ts
@@ -0,0 +1,15 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import Setting from './Setting';
+
+interface SettingsForSinglePlugin {
+ pluginName: string;
+ settings: Setting[];
+}
+
+export default SettingsForSinglePlugin;
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.adapter.ts b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.adapter.ts
new file mode 100644
index 000000000..521477bd7
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.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 PluginFilter from './PluginFilter';
+
+export default function piwikPluginFilter(): IDirective {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink(scope: IScope, element: JQuery) {
+ PluginFilter.mounted(element[0]);
+ },
+ };
+}
+
+window.angular.module('piwikApp').directive('piwikPluginFilter', piwikPluginFilter);
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.ts b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.ts
new file mode 100644
index 000000000..eaa839ab4
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginFilter.ts
@@ -0,0 +1,138 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import ClickEvent = JQuery.ClickEvent;
+
+const { $ } = window;
+
+function getCurrentFilterOrigin(element: JQuery) {
+ return element.find('.origin a.active').data('filter-origin');
+}
+
+function getCurrentFilterStatus(element: JQuery) {
+ return element.find('.status a.active').data('filter-status');
+}
+
+function getMatchingNodes(filterOrigin: string, filterStatus: string): JQuery {
+ let query = '#plugins tr';
+
+ if (filterOrigin === 'all') {
+ query += '[data-filter-origin]';
+ } else {
+ query += `[data-filter-origin=${filterOrigin}]`;
+ }
+
+ if (filterStatus === 'all') {
+ query += '[data-filter-status]';
+ } else {
+ query += `[data-filter-status=${filterStatus}]`;
+ }
+
+ return $(query);
+}
+
+function updateNumberOfMatchingPluginsInFilter(
+ element: JQuery,
+ selectorFilterToUpdate: string,
+ filterOrigin: string,
+ filterStatus: string,
+) {
+ const numMatchingNodes = getMatchingNodes(filterOrigin, filterStatus).length;
+ const updatedCounterText = ` (${numMatchingNodes})`;
+
+ element.find(`${selectorFilterToUpdate} .counter`).text(updatedCounterText);
+}
+
+function updateAllNumbersOfMatchingPluginsInFilter(element: JQuery) {
+ const filterOrigin = getCurrentFilterOrigin(element);
+ const filterStatus = getCurrentFilterStatus(element);
+
+ updateNumberOfMatchingPluginsInFilter(
+ element,
+ '[data-filter-status="all"]',
+ filterOrigin,
+ 'all',
+ );
+ updateNumberOfMatchingPluginsInFilter(
+ element,
+ '[data-filter-status="active"]',
+ filterOrigin,
+ 'active',
+ );
+ updateNumberOfMatchingPluginsInFilter(
+ element,
+ '[data-filter-status="inactive"]',
+ filterOrigin,
+ 'inactive',
+ );
+
+ updateNumberOfMatchingPluginsInFilter(
+ element,
+ '[data-filter-origin="all"]',
+ 'all',
+ filterStatus,
+ );
+ updateNumberOfMatchingPluginsInFilter(
+ element,
+ '[data-filter-origin="core"]',
+ 'core',
+ filterStatus,
+ );
+ updateNumberOfMatchingPluginsInFilter(
+ element,
+ '[data-filter-origin="official"]',
+ 'official',
+ filterStatus,
+ );
+ updateNumberOfMatchingPluginsInFilter(
+ element,
+ '[data-filter-origin="thirdparty"]',
+ 'thirdparty',
+ filterStatus,
+ );
+}
+
+function filterPlugins(element: JQuery) {
+ const filterOrigin = getCurrentFilterOrigin(element);
+ const filterStatus = getCurrentFilterStatus(element);
+
+ const $nodesToEnable = getMatchingNodes(filterOrigin, filterStatus);
+
+ $('#plugins tr[data-filter-origin][data-filter-status]').css('display', 'none');
+ $nodesToEnable.css('display', 'table-row');
+
+ updateAllNumbersOfMatchingPluginsInFilter(element);
+}
+
+function onClickStatus(element: JQuery, event: ClickEvent) {
+ event.preventDefault();
+
+ $(event.target as HTMLElement).siblings().removeClass('active');
+ $(event.target as HTMLElement).addClass('active');
+
+ filterPlugins(element);
+}
+
+function onClickOrigin(element: JQuery, event: ClickEvent) {
+ event.preventDefault();
+
+ $(event.target as HTMLElement).siblings().removeClass('active');
+ $(event.target as HTMLElement).addClass('active');
+
+ filterPlugins(element);
+}
+
+export default {
+ mounted(el: HTMLElement): void {
+ setTimeout(() => {
+ updateAllNumbersOfMatchingPluginsInFilter($(el));
+
+ $(el).find('.status').on('click', 'a', onClickStatus.bind(null, $(el)));
+ $(el).find('.origin').on('click', 'a', onClickOrigin.bind(null, $(el)));
+ });
+ },
+};
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginManagement.adapter.ts b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginManagement.adapter.ts
new file mode 100644
index 000000000..86fc15f31
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginManagement.adapter.ts
@@ -0,0 +1,28 @@
+/*!
+ * 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 PluginManagement from './PluginManagement';
+
+export default function piwikPluginManagement(): IDirective {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink(scope: IScope, element: JQuery) {
+ const binding = {
+ instance: null,
+ value: {},
+ oldValue: null,
+ modifiers: {},
+ dir: {},
+ };
+
+ PluginManagement.mounted(element[0], binding);
+ },
+ };
+}
+
+window.angular.module('piwikApp').directive('piwikPluginManagement', piwikPluginManagement);
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginManagement.ts b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginManagement.ts
new file mode 100644
index 000000000..06fb47e70
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginManagement.ts
@@ -0,0 +1,59 @@
+/*!
+ * 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 { Matomo } from 'CoreHome';
+import ClickEvent = JQuery.ClickEvent;
+
+const { $ } = window;
+
+interface PluginManagementState {
+ uninstallConfirmMessage?: string;
+}
+
+function onClickUninstall(binding: DirectiveBinding, event: ClickEvent) {
+ event.preventDefault();
+
+ const link = $(event.target as HTMLElement).attr('href');
+ const pluginName = $(event.target as HTMLElement).attr('data-plugin-name');
+
+ if (!link || !pluginName) {
+ return;
+ }
+
+ if (!binding.value.uninstallConfirmMessage) {
+ binding.value.uninstallConfirmMessage = $('#uninstallPluginConfirm').text();
+ }
+
+ const messageToDisplay = (binding.value.uninstallConfirmMessage || '').replace('%s', pluginName);
+
+ $('#uninstallPluginConfirm').text(messageToDisplay);
+
+ Matomo.helper.modalConfirm('#confirmUninstallPlugin', {
+ yes: () => {
+ window.location.href = link;
+ },
+ });
+}
+
+function onDonateLinkClick(event: ClickEvent) {
+ event.preventDefault();
+
+ const overlayId = $(event.target as HTMLElement).data('overlay-id') as string;
+ Matomo.helper.modalConfirm(`#${overlayId}`, {});
+}
+
+export default {
+ mounted(el: HTMLElement, binding: DirectiveBinding): void {
+ setTimeout(() => {
+ binding.value.uninstallConfirmMessage = '';
+
+ $(el).find('.uninstall').click(onClickUninstall.bind(null, binding));
+ $(el).find('.plugin-donation-link').click(onDonateLinkClick);
+ });
+ },
+};
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginUpload.adapter.ts b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginUpload.adapter.ts
new file mode 100644
index 000000000..251585ec1
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginUpload.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 } from 'angular';
+import PluginUpload from './PluginUpload';
+
+export default function piwikPluginUpload(): IDirective {
+ return {
+ restrict: 'A',
+ link: function expandOnClickLink() {
+ PluginUpload.mounted();
+ },
+ };
+}
+
+window.angular.module('piwikApp').directive('piwikPluginUpload', piwikPluginUpload);
diff --git a/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginUpload.ts b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginUpload.ts
new file mode 100644
index 000000000..841634375
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/Plugins/PluginUpload.ts
@@ -0,0 +1,43 @@
+/*!
+ * 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, translate } from 'CoreHome';
+import ClickEvent = JQuery.ClickEvent;
+import SubmitEvent = JQuery.SubmitEvent;
+
+const { $ } = window;
+
+function onUploadPlugin(event: ClickEvent) {
+ event.preventDefault();
+ Matomo.helper.modalConfirm('#installPluginByUpload', {});
+}
+
+function onSubmitPlugin(event: SubmitEvent) {
+ const $zipFile = $('[name=pluginZip]') as JQuery;
+ const fileName = $zipFile.val() as string;
+
+ if (!fileName || fileName.slice(-4) !== '.zip') {
+ event.preventDefault();
+ // eslint-disable-next-line no-alert
+ alert(translate('CorePluginsAdmin_NoZipFileSelected'));
+ } else if ($zipFile.data('maxSize') > 0
+ && $zipFile[0].files![0].size > $zipFile.data('maxSize') * 1048576
+ ) {
+ event.preventDefault();
+ // eslint-disable-next-line no-alert
+ alert(translate('CorePluginsAdmin_FileExceedsUploadLimit'));
+ }
+}
+
+export default {
+ mounted(): void {
+ setTimeout(() => {
+ $('.uploadPlugin').click(onUploadPlugin);
+ $('#uploadPluginForm').submit(onSubmitPlugin);
+ });
+ },
+};
diff --git a/app/plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.adapter.ts b/app/plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.adapter.ts
new file mode 100644
index 000000000..b991c2912
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.adapter.ts
@@ -0,0 +1,38 @@
+/*!
+ * 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 'CoreHome';
+import SaveButton from './SaveButton.vue';
+
+export default createAngularJsAdapter<[ITimeoutService]>({
+ component: SaveButton,
+ scope: {
+ saving: {
+ angularJsBind: '=?',
+ },
+ value: {
+ angularJsBind: '@?',
+ },
+ disabled: {
+ angularJsBind: '=?',
+ },
+ onconfirm: {
+ angularJsBind: '&?',
+ vue: 'confirm',
+ },
+ },
+ events: {
+ confirm($event, vm, scope, element, attrs, controller, $timeout) {
+ element[0].click(); // this directive can be used on input's with ng-click specified
+ $timeout();
+ },
+ },
+ replace: true,
+ directiveName: 'piwikSaveButton',
+ $inject: ['$timeout'],
+});
diff --git a/app/plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.vue b/app/plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.vue
new file mode 100644
index 000000000..c3fde0e35
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/SaveButton/SaveButton.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
diff --git a/app/plugins/CorePluginsAdmin/vue/src/index.ts b/app/plugins/CorePluginsAdmin/vue/src/index.ts
new file mode 100644
index 000000000..69a0a8843
--- /dev/null
+++ b/app/plugins/CorePluginsAdmin/vue/src/index.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
+*/
+import './FormField/FormField.adapter';
+import './Field/Field.adapter';
+import './PluginSettings/PluginSettings.adapter';
+import './Plugins/PluginManagement.adapter';
+import './Plugins/PluginUpload.adapter';
+import './Plugins/PluginFilter.adapter';
+import './SaveButton/SaveButton.adapter';
+import './Form/Form.adapter';
+
+export { default as FormField } from './FormField/FormField.vue';
+export { default as Field } from './Field/Field.vue';
+export { default as Setting } from './PluginSettings/Setting';
+export { default as SettingsForSinglePlugin } from './PluginSettings/SettingsForSinglePlugin';
+export { default as PluginSettings } from './PluginSettings/PluginSettings.vue';
+export { default as PluginFilter } from './Plugins/PluginFilter';
+export { default as PluginManagement } from './Plugins/PluginManagement';
+export { default as PluginUpload } from './Plugins/PluginUpload';
+export { default as SaveButton } from './SaveButton/SaveButton.vue';
+export { default as Form } from './Form/Form';
+export { default as GroupedSettings } from './GroupedSettings/GroupedSettings';
diff --git a/app/plugins/CoreUpdater/Commands/Update.php b/app/plugins/CoreUpdater/Commands/Update.php
index e52879668..d3dee15b8 100644
--- a/app/plugins/CoreUpdater/Commands/Update.php
+++ b/app/plugins/CoreUpdater/Commands/Update.php
@@ -18,7 +18,6 @@
use Piwik\Plugin\ConsoleCommand;
use Piwik\Plugins\CoreUpdater\Commands\Update\CliUpdateObserver;
use Piwik\Plugins\CoreUpdater\NoUpdatesFoundException;
-use Piwik\Plugins\UserCountry\LocationProvider;
use Piwik\Updater;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
diff --git a/app/plugins/CoreUpdater/Controller.php b/app/plugins/CoreUpdater/Controller.php
index dcfb7532d..16a2529df 100644
--- a/app/plugins/CoreUpdater/Controller.php
+++ b/app/plugins/CoreUpdater/Controller.php
@@ -24,7 +24,6 @@
use Piwik\Piwik;
use Piwik\Plugin\Manager as PluginManager;
use Piwik\Plugins\CoreVue\CoreVue;
-use Piwik\Plugins\LanguagesManager\LanguagesManager;
use Piwik\Plugins\Marketplace\Plugins;
use Piwik\SettingsPiwik;
use Piwik\SettingsServer;
@@ -301,6 +300,7 @@ public function runUpdaterAndExit($doDryRun = null)
$updater = new DbUpdater();
$componentsWithUpdateFile = $updater->getComponentUpdates();
+
if (empty($componentsWithUpdateFile)) {
throw new NoUpdatesFoundException("Everything is already up to date.");
}
diff --git a/app/plugins/CoreUpdater/CoreUpdater.php b/app/plugins/CoreUpdater/CoreUpdater.php
index 79821d287..af95ae1c0 100644
--- a/app/plugins/CoreUpdater/CoreUpdater.php
+++ b/app/plugins/CoreUpdater/CoreUpdater.php
@@ -41,8 +41,8 @@ public function dispatch()
return;
}
- $module = Common::getRequestVar('module', '', 'string');
- $action = Common::getRequestVar('action', '', 'string');
+ $module = Piwik::getModule();
+ $action = Piwik::getAction();
if ($module == 'CoreUpdater'
// Proxy module is used to redirect users to piwik.org, should still work when Piwik must be updated
diff --git a/app/plugins/CoreUpdater/Diagnostic/HttpsUpdateCheck.php b/app/plugins/CoreUpdater/Diagnostic/HttpsUpdateCheck.php
index 589969d09..dd571b8c1 100644
--- a/app/plugins/CoreUpdater/Diagnostic/HttpsUpdateCheck.php
+++ b/app/plugins/CoreUpdater/Diagnostic/HttpsUpdateCheck.php
@@ -7,7 +7,6 @@
*/
namespace Piwik\Plugins\CoreUpdater\Diagnostic;
-use Piwik\Config;
use Piwik\Plugins\CoreUpdater;
use Piwik\Plugins\Diagnostics\Diagnostic\Diagnostic;
use Piwik\Plugins\Diagnostics\Diagnostic\DiagnosticResult;
diff --git a/app/plugins/CoreUpdater/Updater.php b/app/plugins/CoreUpdater/Updater.php
index 64593a290..40f115430 100644
--- a/app/plugins/CoreUpdater/Updater.php
+++ b/app/plugins/CoreUpdater/Updater.php
@@ -10,17 +10,13 @@
use Exception;
use Piwik\ArchiveProcessor\Rules;
-use Piwik\Cache as PiwikCache;
use Piwik\CliMulti;
use Piwik\Common;
use Piwik\Container\StaticContainer;
-use Piwik\Context;
use Piwik\Filechecks;
use Piwik\Filesystem;
-use Piwik\FrontController;
use Piwik\Http;
use Piwik\Option;
-use Piwik\Piwik;
use Piwik\Plugin\Manager as PluginManager;
use Piwik\Plugin\ReleaseChannels;
use Piwik\Plugins\CorePluginsAdmin\PluginInstaller;
@@ -186,7 +182,7 @@ public function oneClickUpdatePartTwo($newVersion = null)
if (!isset($newVersion)) {
$newVersion = Version::VERSION;
}
-
+
// we also need to make sure to create a new instance here as otherwise we would change the "global"
// environment, but we only want to change piwik version temporarily for this task here
$environment = StaticContainer::getContainer()->make('Piwik\Plugins\Marketplace\Environment');
@@ -300,7 +296,7 @@ private function disableIncompatiblePlugins($version)
foreach ($plugins as $plugin) {
$plugin->reloadPluginInformation();
}
-
+
$incompatiblePlugins = $this->getIncompatiblePlugins($version);
$disabledPluginNames = array();
@@ -322,6 +318,9 @@ private function installNewFiles($extractedArchiveDirectory)
$model = new Model();
+ // Check if the target directories are writable
+ $this->checkFolderPermissions($extractedArchiveDirectory, PIWIK_INCLUDE_PATH);
+
/*
* Copy all files to PIWIK_INCLUDE_PATH.
* These files are accessed through the dispatcher.
@@ -378,4 +377,34 @@ private function getIncompatiblePlugins($piwikVersion)
{
return PluginManager::getInstance()->getIncompatiblePlugins($piwikVersion);
}
+
+
+ /**
+ * check if the target file directory is writeable
+ * @param string $source
+ * @param string $target
+ * @throws Exception
+ */
+ private function checkFolderPermissions($source, $target)
+ {
+ $wrongPermissionDir = [];
+ if (is_dir($source)) {
+ $d = dir($source);
+ while (false !== ($entry = $d->read())) {
+ if ($entry == '.' || $entry == '..') {
+ continue;
+ }
+ $sourcePath = $source . '/' . $entry;
+ if (is_dir($sourcePath) && !is_writable($target . '/' . $entry)) {
+ //add the wrong permission to the array
+ $wrongPermissionDir[] = $target . '/' . $entry;
+ }
+ }
+ }
+
+ if (!empty($wrongPermissionDir)) {
+ throw new Exception($this->translator->translate('CoreUpdater_ExceptionDirWrongPermission',
+ implode(', ', $wrongPermissionDir)));
+ }
+ }
}
diff --git a/app/plugins/CoreUpdater/lang/ga.json b/app/plugins/CoreUpdater/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/CoreUpdater/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/CoreUpdater/lang/ur.json b/app/plugins/CoreUpdater/lang/ur.json
index 390f96276..3727150ee 100644
--- a/app/plugins/CoreUpdater/lang/ur.json
+++ b/app/plugins/CoreUpdater/lang/ur.json
@@ -4,10 +4,10 @@
"ClickHereToViewSqlQueries": "ایس کیو ایل سوالات اور کنسول کمانڈز کی فہرست دیکھنے اور کاپی کرنے کے لئے یہاں کلک کریں جو عمل میں آئیں گے",
"CriticalErrorDuringTheUpgradeProcess": "تازہ کاری کے عمل کے دوران تنقیدی خرابی:",
"DatabaseUpgradeRequired": "ڈیٹا بیس اپ گریڈ کی ضرورت ہے",
- "DisablingIncompatiblePlugins": "متضاد پلگ ان کو غیر فعال کرنا:٪ s",
- "DownloadX": "٪ s ڈاؤن لوڈ کریں",
- "DownloadingUpdateFromX": "s سے اپ ڈیٹ ڈاؤن لوڈ ہو رہا ہے",
- "EmptyDatabaseError": "ڈیٹا بیس٪ s خالی ہے۔ آپ کو اپنی میٹومو کنفیگریشن فائل میں ترمیم یا اسے ہٹانا ہوگا۔",
+ "DisablingIncompatiblePlugins": "متضاد پلگ ان کو غیر فعال کرنا: %s",
+ "DownloadX": "%s ڈاؤن لوڈ کریں",
+ "DownloadingUpdateFromX": "%s سے اپ ڈیٹ ڈاؤن لوڈ ہو رہا ہے",
+ "EmptyDatabaseError": "ڈیٹا بیس%s خالی ہے۔ آپ کو اپنی میٹومو کنفیگریشن فائل میں ترمیم یا اسے ہٹانا ہوگا۔",
"ErrorDIYHelp": "اگر آپ جدید صارف ہیں اور ڈیٹا بیس اپ گریڈ میں خرابی کا سامنا کرتے ہیں تو:",
"ErrorDIYHelp_1": "مسئلے کے ماخذ کی شناخت اور ان کو درست کریں (جیسے میموری_لمیٹ یا زیادہ سے زیادہ_اختیار_ٹائم)",
"ErrorDIYHelp_2": "تازہ کاری میں باقی سوالات پر عمل کریں جو ناکام ہوگئے",
@@ -15,12 +15,11 @@
"ErrorDIYHelp_4": "باقی تازہ کاریوں کو جاری رکھنے کے لئے اپڈیٹر (براؤزر یا کمانڈ لائن کے ذریعے) دوبارہ چلائیں",
"ErrorDIYHelp_5": "مسئلے کی اطلاع دیں (اور حل) تاکہ ماتومو کو بہتر بنایا جاسکے",
"ErrorDuringPluginsUpdates": "پلگ ان اپ ڈیٹس کے دوران خرابی:",
- "ExceptionAlreadyLatestVersion": "آپ کا Matomo ورژن٪ s تازہ ترین ہے۔",
+ "ExceptionAlreadyLatestVersion": "آپ کا Matomo ورژن%s تازہ ترین ہے۔",
"ExceptionArchiveEmpty": "خالی آرکائو۔",
- "ExceptionArchiveIncompatible": "متضاد محفوظ شدہ دستاویزات:٪ s",
- "ExceptionArchiveIncomplete": "محفوظ شدہ دستاویزات نامکمل ہیں: کچھ فائلیں غائب ہیں (جیسے٪ s)",
+ "ExceptionArchiveIncompatible": "متضاد محفوظ شدہ دستاویزات:%s",
+ "ExceptionArchiveIncomplete": "محفوظ شدہ دستاویزات نامکمل ہیں: کچھ فائلیں غائب ہیں (جیسے %s)",
"FeedbackRequest": "یہاں ماتومو ٹیم کے ساتھ اپنے خیالات اور تجاویز کا اشتراک کرنے کے لئے آزاد محسوس کریں:",
- "HelpMessageContent": "Check Matomo FAQ that explains the most common mistakes during the update. Ask your system administrator - they will be able to help you with the error that is more likely than your server or MySQL setup.",
"SkipCacheClear": "کلیئرنگ کیچز چھوڑنا۔",
"UpdateLog": "لاگ اپ ڈیٹ کریں"
}
diff --git a/app/plugins/CoreUpdater/templates/updateSuccess.twig b/app/plugins/CoreUpdater/templates/updateSuccess.twig
index 818c537f5..0b7fb0208 100644
--- a/app/plugins/CoreUpdater/templates/updateSuccess.twig
+++ b/app/plugins/CoreUpdater/templates/updateSuccess.twig
@@ -22,7 +22,7 @@
diff --git a/app/plugins/Events/API.php b/app/plugins/Events/API.php
index 6f48418f4..74519953a 100644
--- a/app/plugins/Events/API.php
+++ b/app/plugins/Events/API.php
@@ -9,9 +9,6 @@
namespace Piwik\Plugins\Events;
use Piwik\Archive;
-use Piwik\DataTable\Row;
-use Piwik\DataTable;
-use Piwik\Metrics;
use Piwik\Piwik;
/**
diff --git a/app/plugins/Events/Archiver.php b/app/plugins/Events/Archiver.php
index b42762c6e..31d6cd914 100644
--- a/app/plugins/Events/Archiver.php
+++ b/app/plugins/Events/Archiver.php
@@ -10,7 +10,6 @@
use Piwik\Config;
use Piwik\DataArray;
-use Piwik\DataTable;
use Piwik\Metrics;
use Piwik\Plugins\Actions\ArchivingHelper;
use Piwik\RankingQuery;
diff --git a/app/plugins/Events/Categories/EventsSubcategory.php b/app/plugins/Events/Categories/EventsSubcategory.php
index f6abe87ee..ae6223937 100644
--- a/app/plugins/Events/Categories/EventsSubcategory.php
+++ b/app/plugins/Events/Categories/EventsSubcategory.php
@@ -20,6 +20,6 @@ class EventsSubcategory extends Subcategory
public function getHelp()
{
return '' . Piwik::translate('Events_EventsSubcategoryHelp1') . '
'
- . '' . Piwik::translate('Events_EventsSubcategoryHelp2') . '
';
+ . '' . Piwik::translate('Events_EventsSubcategoryHelp2') . '
';
}
}
diff --git a/app/plugins/Events/DataTable/Filter/ReplaceEventNameNotSet.php b/app/plugins/Events/DataTable/Filter/ReplaceEventNameNotSet.php
index 687e830e0..d242959e8 100644
--- a/app/plugins/Events/DataTable/Filter/ReplaceEventNameNotSet.php
+++ b/app/plugins/Events/DataTable/Filter/ReplaceEventNameNotSet.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\Events\DataTable\Filter;
use Piwik\DataTable\BaseFilter;
-use Piwik\DataTable\Row;
use Piwik\DataTable;
use Piwik\Piwik;
use Piwik\Plugins\Events\Archiver;
diff --git a/app/plugins/Events/Events.php b/app/plugins/Events/Events.php
index ce36844e8..c50036799 100644
--- a/app/plugins/Events/Events.php
+++ b/app/plugins/Events/Events.php
@@ -11,7 +11,6 @@
use Piwik\Common;
use Piwik\DataTable;
use Piwik\Piwik;
-use Piwik\Plugin\Report;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugin\ReportsProvider;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable\AllColumns;
diff --git a/app/plugins/Events/VisitorDetails.php b/app/plugins/Events/VisitorDetails.php
index 0c0de6132..b88dc9b07 100644
--- a/app/plugins/Events/VisitorDetails.php
+++ b/app/plugins/Events/VisitorDetails.php
@@ -36,7 +36,7 @@ public function extendActionDetails(&$action, $nextAction, $visitorDetails)
$action['subtitle'] .= ', ' . Piwik::translate('General_Value') . ': "' . $action['eventValue'] . '"';
}
- if (strlen($action['pageTitle']) > 0) {
+ if (strlen(strval($action['pageTitle'])) > 0) {
$action['eventName'] = $action['pageTitle'];
}
diff --git a/app/plugins/Events/Widgets/EventsByDimension.php b/app/plugins/Events/Widgets/EventsByDimension.php
index 17658da53..c99cfb318 100644
--- a/app/plugins/Events/Widgets/EventsByDimension.php
+++ b/app/plugins/Events/Widgets/EventsByDimension.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\Events\Widgets;
use Piwik\Plugins\CoreHome\CoreHome;
-use Piwik\Translation\Translator;
use Piwik\Widget\WidgetContainerConfig;
class EventsByDimension extends WidgetContainerConfig
diff --git a/app/plugins/Events/lang/ga.json b/app/plugins/Events/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/Events/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Feedback/API.php b/app/plugins/Feedback/API.php
index 1ab2b6c6d..8eefb6995 100644
--- a/app/plugins/Feedback/API.php
+++ b/app/plugins/Feedback/API.php
@@ -12,7 +12,6 @@
use Piwik\Container\StaticContainer;
use Piwik\DataTable\Renderer\Json;
use Piwik\Date;
-use Piwik\IP;
use Piwik\Mail;
use Piwik\Piwik;
use Piwik\SettingsServer;
@@ -31,11 +30,11 @@ class API extends \Piwik\Plugin\API
* config: "feedback_email_address".
*
* @param string|null $featureName The name of a feature you want to give feedback to.
- * @param int $like Whether you like the feature or not
+ * @param string|null $like Whether you like the feature or not
* @param string|null $choice Multiple choice option chosen
* @param string|null $message A message containing the actual feedback
*/
- public function sendFeedbackForFeature(?string $featureName, int $like, ?string $choice, ?string $message = null)
+ public function sendFeedbackForFeature($featureName, $like = null, $choice = null, $message = null)
{
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasSomeViewAccess();
@@ -100,7 +99,7 @@ public function sendFeedbackForSurvey($question, $message = false)
$featureName = $this->getEnglishTranslationForFeatureName($question);
$body = sprintf("Question: %s\n", $featureName);
$feedbackMessage = "";
-
+
if (!empty($message) && $message !== 'undefined') {
$feedbackMessage = sprintf("Answer:\n%s\n", trim($message));
}
diff --git a/app/plugins/Feedback/Controller.php b/app/plugins/Feedback/Controller.php
index 9464f855f..f98504d30 100644
--- a/app/plugins/Feedback/Controller.php
+++ b/app/plugins/Feedback/Controller.php
@@ -8,13 +8,9 @@
*/
namespace Piwik\Plugins\Feedback;
-use Piwik\Date;
use Piwik\View;
-use Piwik\Piwik;
-use Piwik\Common;
use Piwik\Version;
use Piwik\Container\StaticContainer;
-use Piwik\DataTable\Renderer\Json;
class Controller extends \Piwik\Plugin\Controller
{
diff --git a/app/plugins/Feedback/Feedback.php b/app/plugins/Feedback/Feedback.php
index 9a75c51c9..6764c29f4 100644
--- a/app/plugins/Feedback/Feedback.php
+++ b/app/plugins/Feedback/Feedback.php
@@ -9,13 +9,9 @@
namespace Piwik\Plugins\Feedback;
use Piwik\Date;
-use Piwik\Plugins\UsersManager\API as APIUsersManager;
-use Piwik\Plugins\UsersManager\UsersManager;
-use Piwik\Site;
use Piwik\View;
use Piwik\Piwik;
use Piwik\Common;
-use Piwik\Plugin\Manager as PluginManager;
use Piwik\Plugins\Feedback\FeedbackReminder;
/**
diff --git a/app/plugins/Feedback/lang/ga.json b/app/plugins/Feedback/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/Feedback/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Feedback/stylesheets/feedback.less b/app/plugins/Feedback/stylesheets/feedback.less
index 5f89291d0..2a80d4b71 100644
--- a/app/plugins/Feedback/stylesheets/feedback.less
+++ b/app/plugins/Feedback/stylesheets/feedback.less
@@ -9,7 +9,7 @@
line-height: 18px;
}
- p, h4 {
+ p {
font-size: 13px;
padding-bottom: 4px;
}
@@ -20,6 +20,8 @@
h4 {
font-weight: bold;
+ font-size: 18px;
+ padding-bottom: 4px;
}
.piwik-donate-call {
diff --git a/app/plugins/Feedback/templates/index.twig b/app/plugins/Feedback/templates/index.twig
index 73c149650..5a4cbc70a 100644
--- a/app/plugins/Feedback/templates/index.twig
+++ b/app/plugins/Feedback/templates/index.twig
@@ -23,14 +23,14 @@
{{'Feedback_PopularHelpTopics'|translate}}
{% for helpTopic in popularHelpTopics %}
- • {{helpTopic.title|translate}}
+ • {{helpTopic.title|translate}}
{% endfor %}
{{ 'Feedback_CommunityHelp'|translate }}
- • {{ 'Feedback_UserGuides'|translate }} - {{ 'Feedback_ViewUserGuides'|translate("","") }}.
- • {{ 'Feedback_FAQs'|translate }} - {{ 'Feedback_ViewAnswersToFAQ'|translate("","") }}.
+ • {{ 'Feedback_UserGuides'|translate }} - {{ 'Feedback_ViewUserGuides'|translate("","") }}.
+ • {{ 'Feedback_FAQs'|translate }} - {{ 'Feedback_ViewAnswersToFAQ'|translate("","") }}.
• {{ 'Feedback_Forums'|translate }} - {{ 'Feedback_VisitTheForums'|translate("","") }}.
- • {{ 'API_Glossary'|translate }} - {{ 'API_LearnAboutCommonlyUsedTerms2'|translate }}
+ • {{ 'API_Glossary'|translate }} - {{ 'API_LearnAboutCommonlyUsedTerms2'|translate }}
{{ 'Feedback_ProfessionalHelp'|translate }}
{{ 'Feedback_ProfessionalServicesIntro'|translate }}
@@ -69,16 +69,16 @@
Grow your business, understand your audience better and increase your sales and conversions with a premium plugin:
-
• Users Flow : a visual representation of the most popular paths your users take through your website or app.
-
• A/B Testing : compare different versions of your websites or apps and detect the winning variation.
-
• Funnels : identify and understand where your visitors drop off in your conversion funnels.
-
• Form Analytics : increase conversions and get better leads from your website forms.
-
• Video and Audio Analytics : powerful insights into how your audience watches your videos and listens to your audio.
-
• Roll-Up Reporting : aggregate data from multiple websites, apps and shops into a Roll-Up site to gain new insights.
-
• Search Keywords Performance : all keywords searched by your users on Google+Bing+Yahoo into your Matomo reports.
-
• Audit log : better security and problem diagnostic with a detailed audit log of Matomo user activities.
-
• White Label : give your clients access to their analytics reports where all Matomo-branded widgets are removed.
-
• All premium plugins.
+
• Users Flow : a visual representation of the most popular paths your users take through your website or app.
+
• A/B Testing : compare different versions of your websites or apps and detect the winning variation.
+
• Funnels : identify and understand where your visitors drop off in your conversion funnels.
+
• Form Analytics : increase conversions and get better leads from your website forms.
+
• Video and Audio Analytics : powerful insights into how your audience watches your videos and listens to your audio.
+
• Roll-Up Reporting : aggregate data from multiple websites, apps and shops into a Roll-Up site to gain new insights.
+
• Search Keywords Performance : all keywords searched by your users on Google+Bing+Yahoo into your Matomo reports.
+
• Audit log : better security and problem diagnostic with a detailed audit log of Matomo user activities.
+
• White Label : give your clients access to their analytics reports where all Matomo-branded widgets are removed.
+
• All premium plugins.
diff --git a/app/plugins/Feedback/vue/dist/Feedback.umd.js b/app/plugins/Feedback/vue/dist/Feedback.umd.js
index e2d710196..97d46b5c1 100644
--- a/app/plugins/Feedback/vue/dist/Feedback.umd.js
+++ b/app/plugins/Feedback/vue/dist/Feedback.umd.js
@@ -144,7 +144,7 @@ var external_CoreHome_ = __webpack_require__("19dc");
// EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"}
var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf");
-// 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/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=template&id=ae4ff290
+// 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/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=template&id=bc746c6c
var _hoisted_1 = ["title"];
var _hoisted_2 = {
@@ -258,15 +258,33 @@ var _hoisted_32 = {
"text-align": "left"
}
};
-var _hoisted_33 = ["innerHTML"];
-var _hoisted_34 = ["innerHTML"];
-var _hoisted_35 = ["innerHTML"];
-var _hoisted_36 = ["innerHTML"];
-var _hoisted_37 = ["innerHTML"];
-var _hoisted_38 = ["innerHTML"];
-var _hoisted_39 = ["innerHTML"];
-var _hoisted_40 = ["innerHTML"];
-var _hoisted_41 = ["innerHTML"];
+var _hoisted_33 = {
+ key: 0
+};
+var _hoisted_34 = {
+ key: 1
+};
+var _hoisted_35 = {
+ key: 2
+};
+var _hoisted_36 = {
+ key: 3
+};
+var _hoisted_37 = {
+ key: 4
+};
+var _hoisted_38 = {
+ key: 5
+};
+var _hoisted_39 = {
+ key: 6
+};
+var _hoisted_40 = {
+ key: 7
+};
+var _hoisted_41 = {
+ key: 8
+};
var _hoisted_42 = {
key: 9,
class: "error-text"
@@ -398,34 +416,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
return _ctx.dislikeReason = $event;
}),
class: "rateradio"
- }, null, 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelRadio"], _ctx.dislikeReason]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureOtherReason')), 1)]), _hoisted_31])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.likeReason || _ctx.dislikeReason ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_32, [_ctx.likeReason && _ctx.likeReason == 'useful' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 0,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageLikeExtraUseful')
- }, null, 8, _hoisted_33)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.likeReason && _ctx.likeReason == 'easy' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 1,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageLikeExtraEasy')
- }, null, 8, _hoisted_34)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.likeReason && _ctx.likeReason == 'configurable' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 2,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageLikeExtraConfigurable')
- }, null, 8, _hoisted_35)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.likeReason && _ctx.likeReason == 'likeother' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 3,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageLikeExtra')
- }, null, 8, _hoisted_36)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason == 'missingfeatures' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 4,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtraMissing')
- }, null, 8, _hoisted_37)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason == 'makeeasier' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 5,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtraEasier')
- }, null, 8, _hoisted_38)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason == 'fixbugs' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 6,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtraBugs')
- }, null, 8, _hoisted_39)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason == 'speedup' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 7,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtraSpeed')
- }, null, 8, _hoisted_40)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason == 'dislikeother' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
- key: 8,
- innerHTML: _ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtra')
- }, null, 8, _hoisted_41)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.errorMessage ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_42, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.errorMessage), 1)) : 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"])("textarea", {
+ }, null, 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelRadio"], _ctx.dislikeReason]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureOtherReason')), 1)]), _hoisted_31])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.likeReason || _ctx.dislikeReason ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_32, [_ctx.likeReason && _ctx.likeReason === 'useful' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_33, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageLikeExtraUseful')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.likeReason && _ctx.likeReason === 'easy' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_34, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageLikeExtraEasy')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.likeReason && _ctx.likeReason === 'configurable' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_35, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageLikeExtraConfigurable')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.likeReason && _ctx.likeReason === 'likeother' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_36, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageLikeExtra')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason === 'missingfeatures' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_37, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtraMissing')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason === 'makeeasier' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_38, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtraEasier')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason === 'fixbugs' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_39, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtraBugs')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason === 'speedup' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_40, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtraSpeed')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.dislikeReason && _ctx.dislikeReason === 'dislikeother' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_41, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_RateFeatureLeaveMessageDislikeExtra')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.errorMessage ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_42, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.errorMessage), 1)) : 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"])("textarea", {
ref: "feedbackText",
class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])(["materialize-textarea", {
'has-error': _ctx.errorMessage
@@ -436,7 +427,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
})
}, null, 2), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.feedbackMessage]]), _ctx.likeReason || _ctx.dislikeReason ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", {
key: 10,
- innerHTML: _ctx.translate('Feedback_Policy', "\n
", ' ')
+ innerHTML: _ctx.$sanitize(_ctx.translate('Feedback_Policy', "\n
", ' '))
}, null, 8, _hoisted_43)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
class: "btn",
type: "button",
@@ -458,7 +449,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
}, {
default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_46, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", {
- innerHTML: _ctx.translate('Feedback_ThankYouHeart', "
")
+ innerHTML: _ctx.$sanitize(_ctx.translate('Feedback_ThankYouHeart', "
"))
}, null, 8, _hoisted_47), _ctx.like ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_48, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ReviewLinks)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), !_ctx.like ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("p", _hoisted_49, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Feedback_AppreciateFeedback')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
type: "button",
value: _ctx.translate('General_Close'),
@@ -468,7 +459,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
_: 1
}, 8, ["modelValue"])], 8, _hoisted_1);
}
-// CONCATENATED MODULE: ./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=template&id=ae4ff290
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=template&id=bc746c6c
// 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/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?vue&type=template&id=9a880eb6
@@ -483,7 +474,7 @@ function ReviewLinksvue_type_template_id_9a880eb6_render(_ctx, _cache, $props, $
}
// CONCATENATED MODULE: ./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?vue&type=template&id=9a880eb6
-// 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/Feedback/vue/src/ReviewLinks/ReviewLinks.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/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?vue&type=script&lang=ts
/* harmony default export */ var ReviewLinksvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({}));
// CONCATENATED MODULE: ./plugins/Feedback/vue/src/ReviewLinks/ReviewLinks.vue?vue&type=script&lang=ts
@@ -495,7 +486,7 @@ function ReviewLinksvue_type_template_id_9a880eb6_render(_ctx, _cache, $props, $
ReviewLinksvue_type_script_lang_ts.render = ReviewLinksvue_type_template_id_9a880eb6_render
/* harmony default export */ var ReviewLinks = (ReviewLinksvue_type_script_lang_ts);
-// 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/Feedback/vue/src/RateFeature/RateFeature.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/Feedback/vue/src/RateFeature/RateFeature.vue?vue&type=script&lang=ts
@@ -563,7 +554,7 @@ var _window = window,
external_CoreHome_["AjaxHelper"].fetch({
method: 'Feedback.sendFeedbackForFeature',
featureName: this.title,
- like: this.like ? '1' : '0',
+ like: this.like ? 1 : 0,
choice: this.like ? this.likeReason : this.dislikeReason,
message: this.feedbackMessage
}).then(function (res) {
@@ -605,54 +596,54 @@ RateFeaturevue_type_script_lang_ts.render = render
},
directiveName: 'piwikRateFeature'
}));
-// 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/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue?vue&type=template&id=5ec4eadf
+// 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/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue?vue&type=template&id=4e04fa3c
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_1 = {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_1 = {
key: 0,
class: "bannerHeader"
};
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_2 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("i", {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_2 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("i", {
class: "icon-heart red-text"
}, null, -1);
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_3 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("i", {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_3 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("i", {
class: "icon-close white-text"
}, null, -1);
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_4 = [FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_3];
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_5 = {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_4 = [FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_3];
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_5 = {
class: "ratefeature"
};
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_6 = {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_6 = {
class: "ui-confirm ratefeatureDialog"
};
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_7 = ["innerHTML"];
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_7 = ["innerHTML"];
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_8 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_8 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_9 = {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_9 = {
class: "messageContainer"
};
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_10 = {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_10 = {
key: 0,
class: "error-text"
};
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_11 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_11 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_12 = ["innerHTML"];
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_13 = ["value"];
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_14 = ["value"];
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_15 = {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_12 = ["innerHTML"];
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_13 = ["value"];
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_14 = ["value"];
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_15 = {
class: "ui-confirm ratefeatureDialog"
};
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_16 = ["innerHTML"];
-var FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_17 = ["value"];
-function FeedbackQuestionvue_type_template_id_5ec4eadf_render(_ctx, _cache, $props, $setup, $data, $options) {
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_16 = ["innerHTML"];
+var FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_17 = ["value"];
+function FeedbackQuestionvue_type_template_id_4e04fa3c_render(_ctx, _cache, $props, $setup, $data, $options) {
var _component_MatomoDialog = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("MatomoDialog");
- return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", null, [!_ctx.isHidden ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate("Feedback_FeedbackTitle")) + " ", 1), FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_2]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", null, [!_ctx.isHidden ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate("Feedback_FeedbackTitle")) + " ", 1), FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_2]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", {
onClick: _cache[0] || (_cache[0] = function () {
return _ctx.showQuestion && _ctx.showQuestion.apply(_ctx, arguments);
}),
@@ -662,7 +653,7 @@ function FeedbackQuestionvue_type_template_id_5ec4eadf_render(_ctx, _cache, $pro
onClick: _cache[1] || (_cache[1] = function () {
return _ctx.disableReminder && _ctx.disableReminder.apply(_ctx, arguments);
})
- }, FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_4)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_MatomoDialog, {
+ }, FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_4)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_MatomoDialog, {
modelValue: _ctx.showFeedbackForm,
"onUpdate:modelValue": _cache[3] || (_cache[3] = function ($event) {
return _ctx.showFeedbackForm = $event;
@@ -672,9 +663,9 @@ function FeedbackQuestionvue_type_template_id_5ec4eadf_render(_ctx, _cache, $pro
})
}, {
default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
- return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate("Feedback_Question".concat(_ctx.question))), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", {
- innerHTML: _ctx.translate('Feedback_FeedbackSubtitle', "
")
- }, null, 8, FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_7), FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_8, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_9, [_ctx.errorMessage ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_10, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.errorMessage), 1)) : 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"])("textarea", {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_6, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate("Feedback_Question".concat(_ctx.question))), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", {
+ innerHTML: _ctx.$sanitize(_ctx.translate('Feedback_FeedbackSubtitle', "
"))
+ }, null, 8, FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_7), FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_8, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_9, [_ctx.errorMessage ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_10, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.errorMessage), 1)) : 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"])("textarea", {
id: "message",
class: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["normalizeClass"])({
'has-error': _ctx.errorMessage
@@ -682,17 +673,17 @@ function FeedbackQuestionvue_type_template_id_5ec4eadf_render(_ctx, _cache, $pro
"onUpdate:modelValue": _cache[2] || (_cache[2] = function ($event) {
return _ctx.feedbackMessage = $event;
})
- }, null, 2), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.feedbackMessage]])]), FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_11, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", {
- innerHTML: _ctx.translate('Feedback_Policy', "
", ' ')
- }, null, 8, FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_12), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ }, null, 2), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vModelText"], _ctx.feedbackMessage]])]), FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_11, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", {
+ innerHTML: _ctx.$sanitize(_ctx.feedbackPolicy)
+ }, null, 8, FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_12), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
type: "button",
role: "validation",
value: _ctx.translate('Feedback_SendFeedback')
- }, null, 8, FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_13), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ }, null, 8, FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_13), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
type: "button",
role: "cancel",
value: _ctx.translate('General_Cancel')
- }, null, 8, FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_14)])];
+ }, null, 8, FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_14)])];
}),
_: 1
}, 8, ["modelValue"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_MatomoDialog, {
@@ -702,20 +693,20 @@ function FeedbackQuestionvue_type_template_id_5ec4eadf_render(_ctx, _cache, $pro
})
}, {
default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
- return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_15, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate("Feedback_ThankYou")), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", {
- innerHTML: _ctx.translate('Feedback_ThankYourForFeedback', "
")
- }, null, 8, FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_16), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_15, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate("Feedback_ThankYou")), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", {
+ innerHTML: _ctx.$sanitize(_ctx.translate('Feedback_ThankYourForFeedback', "
"))
+ }, null, 8, FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_16), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
type: "button",
role: "cancel",
value: _ctx.translate('General_Close')
- }, null, 8, FeedbackQuestionvue_type_template_id_5ec4eadf_hoisted_17)])];
+ }, null, 8, FeedbackQuestionvue_type_template_id_4e04fa3c_hoisted_17)])];
}),
_: 1
}, 8, ["modelValue"])])]);
}
-// CONCATENATED MODULE: ./plugins/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue?vue&type=template&id=5ec4eadf
+// CONCATENATED MODULE: ./plugins/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue?vue&type=template&id=4e04fa3c
-// 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/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.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/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue?vue&type=script&lang=ts
var FeedbackQuestionvue_type_script_lang_ts_window = window,
@@ -735,6 +726,9 @@ var cookieName = 'feedback-question';
}
return !!this.hide;
+ },
+ feedbackPolicy: function feedbackPolicy() {
+ return Object(external_CoreHome_["translate"])('Feedback_Policy', '
', ' ');
}
},
data: function data() {
@@ -777,7 +771,7 @@ var cookieName = 'feedback-question';
var nextQuestion = (this.question + 1) % 4;
var sevenDays = 7 * 60 * 60 * 24 * 1000;
- Object(external_CoreHome_["setCookie"])(cookieName, nextQuestion, sevenDays);
+ Object(external_CoreHome_["setCookie"])(cookieName, "".concat(nextQuestion), sevenDays);
},
getRandomIntBetween: function getRandomIntBetween(min, max) {
// eslint-disable-next-line no-param-reassign
@@ -822,7 +816,7 @@ var cookieName = 'feedback-question';
-FeedbackQuestionvue_type_script_lang_ts.render = FeedbackQuestionvue_type_template_id_5ec4eadf_render
+FeedbackQuestionvue_type_script_lang_ts.render = FeedbackQuestionvue_type_template_id_4e04fa3c_render
/* harmony default export */ var FeedbackQuestion = (FeedbackQuestionvue_type_script_lang_ts);
// CONCATENATED MODULE: ./plugins/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.adapter.ts
diff --git a/app/plugins/Feedback/vue/dist/Feedback.umd.min.js b/app/plugins/Feedback/vue/dist/Feedback.umd.min.js
index b8efc2a2d..423148b78 100644
--- a/app/plugins/Feedback/vue/dist/Feedback.umd.min.js
+++ b/app/plugins/Feedback/vue/dist/Feedback.umd.min.js
@@ -1,14 +1,14 @@
-(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue")):"function"===typeof define&&define.amd?define(["CoreHome"],t):"object"===typeof exports?exports["Feedback"]=t(require("CoreHome"),require("vue")):e["Feedback"]=t(e["CoreHome"],e["Vue"])})("undefined"!==typeof self?self:this,(function(e,t){return function(e){var t={};function a(n){if(t[n])return t[n].exports;var l=t[n]={i:n,l:!1,exports:{}};return e[n].call(l.exports,l,l.exports,a),l.l=!0,l.exports}return a.m=e,a.c=t,a.d=function(e,t,n){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},a.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)a.d(n,l,function(t){return e[t]}.bind(null,l));return n},a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="plugins/Feedback/vue/dist/",a(a.s="fae3")}({"19dc":function(t,a){t.exports=e},"8bbf":function(e,a){e.exports=t},fae3:function(e,t,a){"use strict";if(a.r(t),a.d(t,"ReviewLinks",(function(){return ce})),a.d(t,"RateFeature",(function(){return be})),a.d(t,"FeedbackQuestion",(function(){return Te})),"undefined"!==typeof window){var n=window.document.currentScript,l=n&&n.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);l&&(a.p=l[1])}var o=a("19dc"),r=a("8bbf"),i=["title"],c={class:"ui-confirm ratefeatureDialog"},s={key:0},d={key:0},u={key:1},b=Object(r["createElementVNode"])("br",null,null,-1),k={class:"row"},m={style:{"text-align":"left","margin-top":"16px"}},p={for:"useful",class:"ratelabel"},j=Object(r["createElementVNode"])("br",null,null,-1),O={for:"easy",class:"ratelabel"},f=Object(r["createElementVNode"])("br",null,null,-1),v={for:"configurable",class:"ratelabel"},g=Object(r["createElementVNode"])("br",null,null,-1),h={for:"likeother",class:"ratelabel"},F={key:1},V={key:0},N={key:1},y=Object(r["createElementVNode"])("br",null,null,-1),E={class:"row"},R={style:{"text-align":"left"}},M={for:"missingfeatures",class:"ratelabel"},w=Object(r["createElementVNode"])("br",null,null,-1),x={for:"makeeasier",class:"ratelabel"},D=Object(r["createElementVNode"])("br",null,null,-1),B={for:"speedup",class:"ratelabel"},_=Object(r["createElementVNode"])("br",null,null,-1),C={for:"fixbugs",class:"ratelabel"},T=Object(r["createElementVNode"])("br",null,null,-1),L={for:"dislikeother",class:"ratelabel"},H=Object(r["createElementVNode"])("br",null,null,-1),S={key:2,class:"messageContainer",style:{"text-align":"left"}},U=["innerHTML"],q=["innerHTML"],Q=["innerHTML"],I=["innerHTML"],A=["innerHTML"],z=["innerHTML"],P=["innerHTML"],$=["innerHTML"],G=["innerHTML"],J={key:9,class:"error-text"},Y=["innerHTML"],K=["title","value"],W=["value"],X={class:"ui-confirm ratefeatureDialog"},Z=["innerHTML"],ee={key:0},te={key:1},ae=["value"];function ne(e,t,a,n,l,o){var ne=Object(r["resolveComponent"])("MatomoDialog"),le=Object(r["resolveComponent"])("ReviewLinks");return Object(r["openBlock"])(),Object(r["createElementBlock"])("div",{title:e.translate("Feedback_RateFeatureTitle",e.$sanitize(e.title)),class:"ratefeature"},[Object(r["createElementVNode"])("div",{class:"iconContainer",onMouseenter:t[2]||(t[2]=function(t){return e.expanded=!0}),onMouseleave:t[3]||(t[3]=function(t){return e.expanded=!1})},[Object(r["createElementVNode"])("img",{onClick:t[0]||(t[0]=function(t){e.likeFeature()}),class:"like-icon",src:"plugins/Feedback/vue/src/RateFeature/thumbs-up.png"}),Object(r["createElementVNode"])("img",{onClick:t[1]||(t[1]=function(t){e.dislikeFeature()}),class:"dislike-icon",src:"plugins/Feedback/vue/src/RateFeature/thumbs-down.png"})],32),Object(r["createVNode"])(ne,{modelValue:e.showFeedbackForm,"onUpdate:modelValue":t[14]||(t[14]=function(t){return e.showFeedbackForm=t}),onYes:t[15]||(t[15]=function(t){return e.sendFeedback()}),onValidation:t[16]||(t[16]=function(t){return e.sendFeedback()})},{default:Object(r["withCtx"])((function(){return[Object(r["createElementVNode"])("div",c,[e.like?(Object(r["openBlock"])(),Object(r["createElementBlock"])("div",s,[e.title?(Object(r["openBlock"])(),Object(r["createElementBlock"])("h2",d,Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLikeNamedFeature",e.title)),1)):Object(r["createCommentVNode"])("",!0),e.title?Object(r["createCommentVNode"])("",!0):(Object(r["openBlock"])(),Object(r["createElementBlock"])("h2",u,Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLike")),1)),b,Object(r["createElementVNode"])("div",k,[Object(r["createElementVNode"])("div",m,[Object(r["createElementVNode"])("label",p,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"useful",value:"useful","onUpdate:modelValue":t[4]||(t[4]=function(t){return e.likeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.likeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureUsefulInfo")),1)]),j,Object(r["createElementVNode"])("label",O,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"easy",value:"easy","onUpdate:modelValue":t[5]||(t[5]=function(t){return e.likeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.likeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureEasyToUse")),1)]),f,Object(r["createElementVNode"])("label",v,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"configurable",value:"configurable","onUpdate:modelValue":t[6]||(t[6]=function(t){return e.likeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.likeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureConfigurable")),1)]),g,Object(r["createElementVNode"])("label",h,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"likeother",value:"likeother","onUpdate:modelValue":t[7]||(t[7]=function(t){return e.likeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.likeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureOtherReason")),1)])])])])):Object(r["createCommentVNode"])("",!0),e.like?Object(r["createCommentVNode"])("",!0):(Object(r["openBlock"])(),Object(r["createElementBlock"])("div",F,[e.title?(Object(r["openBlock"])(),Object(r["createElementBlock"])("h2",V,Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislikeNamedFeature",e.title)),1)):Object(r["createCommentVNode"])("",!0),e.title?Object(r["createCommentVNode"])("",!0):(Object(r["openBlock"])(),Object(r["createElementBlock"])("h2",N,Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislike")),1)),y,Object(r["createElementVNode"])("div",E,[Object(r["createElementVNode"])("div",R,[Object(r["createElementVNode"])("label",M,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"missingfeatures",value:"missingfeatures","onUpdate:modelValue":t[8]||(t[8]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.dislikeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureDislikeAddMissingFeatures")),1)]),w,Object(r["createElementVNode"])("label",x,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"makeeasier",value:"makeeasier","onUpdate:modelValue":t[9]||(t[9]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.dislikeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureDislikeMakeEasier")),1)]),D,Object(r["createElementVNode"])("label",B,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"speedup",value:"speedup","onUpdate:modelValue":t[10]||(t[10]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.dislikeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureDislikeSpeedUp")),1)]),_,Object(r["createElementVNode"])("label",C,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"fixbugs",value:"fixbugs","onUpdate:modelValue":t[11]||(t[11]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.dislikeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureDislikeFixBugs")),1)]),T,Object(r["createElementVNode"])("label",L,[Object(r["withDirectives"])(Object(r["createElementVNode"])("input",{type:"radio",id:"dislikeother",value:"dislikeother","onUpdate:modelValue":t[12]||(t[12]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[r["vModelRadio"],e.dislikeReason]]),Object(r["createTextVNode"])(" "+Object(r["toDisplayString"])(e.translate("Feedback_RateFeatureOtherReason")),1)]),H])])])),e.likeReason||e.dislikeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("div",S,[e.likeReason&&"useful"==e.likeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:0,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageLikeExtraUseful")},null,8,U)):Object(r["createCommentVNode"])("",!0),e.likeReason&&"easy"==e.likeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:1,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageLikeExtraEasy")},null,8,q)):Object(r["createCommentVNode"])("",!0),e.likeReason&&"configurable"==e.likeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:2,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageLikeExtraConfigurable")},null,8,Q)):Object(r["createCommentVNode"])("",!0),e.likeReason&&"likeother"==e.likeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:3,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageLikeExtra")},null,8,I)):Object(r["createCommentVNode"])("",!0),e.dislikeReason&&"missingfeatures"==e.dislikeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:4,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageDislikeExtraMissing")},null,8,A)):Object(r["createCommentVNode"])("",!0),e.dislikeReason&&"makeeasier"==e.dislikeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:5,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageDislikeExtraEasier")},null,8,z)):Object(r["createCommentVNode"])("",!0),e.dislikeReason&&"fixbugs"==e.dislikeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:6,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageDislikeExtraBugs")},null,8,P)):Object(r["createCommentVNode"])("",!0),e.dislikeReason&&"speedup"==e.dislikeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:7,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageDislikeExtraSpeed")},null,8,$)):Object(r["createCommentVNode"])("",!0),e.dislikeReason&&"dislikeother"==e.dislikeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:8,innerHTML:e.translate("Feedback_RateFeatureLeaveMessageDislikeExtra")},null,8,G)):Object(r["createCommentVNode"])("",!0),e.errorMessage?(Object(r["openBlock"])(),Object(r["createElementBlock"])("div",J,Object(r["toDisplayString"])(e.errorMessage),1)):Object(r["createCommentVNode"])("",!0),Object(r["withDirectives"])(Object(r["createElementVNode"])("textarea",{ref:"feedbackText",class:Object(r["normalizeClass"])(["materialize-textarea",{"has-error":e.errorMessage}]),id:"feedbacktext","onUpdate:modelValue":t[13]||(t[13]=function(t){return e.feedbackMessage=t})},null,2),[[r["vModelText"],e.feedbackMessage]]),e.likeReason||e.dislikeReason?(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",{key:10,innerHTML:e.translate("Feedback_Policy","\n
"," ")},null,8,Y)):Object(r["createCommentVNode"])("",!0)])):Object(r["createCommentVNode"])("",!0),Object(r["createElementVNode"])("input",{class:"btn",type:"button",role:"validation",title:e.translate("Feedback_RateFeatureSendFeedbackInformation"),value:e.translate("Feedback_SendFeedback")},null,8,K),Object(r["createElementVNode"])("input",{type:"button",role:"cancel",value:e.translate("General_Cancel")},null,8,W)])]})),_:1},8,["modelValue"]),Object(r["createVNode"])(ne,{modelValue:e.ratingDone,"onUpdate:modelValue":t[17]||(t[17]=function(t){return e.ratingDone=t})},{default:Object(r["withCtx"])((function(){return[Object(r["createElementVNode"])("div",X,[Object(r["createElementVNode"])("h2",{innerHTML:e.translate("Feedback_ThankYouHeart","
")},null,8,Z),e.like?(Object(r["openBlock"])(),Object(r["createElementBlock"])("div",ee,[Object(r["createVNode"])(le)])):Object(r["createCommentVNode"])("",!0),e.like?Object(r["createCommentVNode"])("",!0):(Object(r["openBlock"])(),Object(r["createElementBlock"])("p",te,Object(r["toDisplayString"])(e.translate("Feedback_AppreciateFeedback")),1)),Object(r["createElementVNode"])("input",{type:"button",value:e.translate("General_Close"),role:"yes"},null,8,ae)])]})),_:1},8,["modelValue"])],8,i)}var le={class:"requestReview"},oe=Object(r["createStaticVNode"])('
',3);function re(e,t,a,n,l,o){return Object(r["openBlock"])(),Object(r["createElementBlock"])("div",le,[Object(r["createElementVNode"])("p",null,Object(r["toDisplayString"])(e.translate("Feedback_PleaseLeaveExternalReviewForMatomo")),1),oe])}var ie=Object(r["defineComponent"])({});ie.render=re;var ce=ie,se=window,de=se.$,ue=Object(r["defineComponent"])({props:{title:String},components:{MatomoDialog:o["MatomoDialog"],ReviewLinks:ce},data:function(){return{like:!1,likeReason:null,dislikeReason:null,ratingDone:!1,expanded:!1,showFeedbackForm:!1,feedbackMessage:"",errorMessage:null}},watch:{likeReason:"doFocusInput",dislikeReason:"doFocusInput"},methods:{dislikeFeature:function(){this.ratingDone=!1,this.like=!1,this.showFeedbackForm=!0,this.errorMessage=null,this.likeReason=null,this.dislikeReason=null,this.feedbackMessage=""},likeFeature:function(){this.ratingDone=!1,this.like=!0,this.showFeedbackForm=!0,this.errorMessage=null,this.likeReason=null,this.dislikeReason=null,this.feedbackMessage=""},doFocusInput:function(){var e=this;this.$nextTick((function(){e.focusInput()}))},focusInput:function(){null!=this.$refs.feedbackText&&this.$refs.feedbackText.focus()},sendFeedback:function(){var e=this;this.errorMessage=null,o["AjaxHelper"].fetch({method:"Feedback.sendFeedbackForFeature",featureName:this.title,like:this.like?"1":"0",choice:this.like?this.likeReason:this.dislikeReason,message:this.feedbackMessage}).then((function(t){"success"===t.value?(de(".modal").modal("close"),e.ratingDone=!0,e.feedbackMessage=""):e.errorMessage=t.value}))}}});ue.render=ne;var be=ue,ke=(Object(o["createAngularJsAdapter"])({component:be,scope:{title:{angularJsBind:"@"}},directiveName:"piwikRateFeature"}),{key:0,class:"bannerHeader"}),me=Object(r["createElementVNode"])("i",{class:"icon-heart red-text"},null,-1),pe=Object(r["createElementVNode"])("i",{class:"icon-close white-text"},null,-1),je=[pe],Oe={class:"ratefeature"},fe={class:"ui-confirm ratefeatureDialog"},ve=["innerHTML"],ge=Object(r["createElementVNode"])("br",null,null,-1),he={class:"messageContainer"},Fe={key:0,class:"error-text"},Ve=Object(r["createElementVNode"])("br",null,null,-1),Ne=["innerHTML"],ye=["value"],Ee=["value"],Re={class:"ui-confirm ratefeatureDialog"},Me=["innerHTML"],we=["value"];
+(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue")):"function"===typeof define&&define.amd?define(["CoreHome"],t):"object"===typeof exports?exports["Feedback"]=t(require("CoreHome"),require("vue")):e["Feedback"]=t(e["CoreHome"],e["Vue"])})("undefined"!==typeof self?self:this,(function(e,t){return function(e){var t={};function a(n){if(t[n])return t[n].exports;var l=t[n]={i:n,l:!1,exports:{}};return e[n].call(l.exports,l,l.exports,a),l.l=!0,l.exports}return a.m=e,a.c=t,a.d=function(e,t,n){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},a.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)a.d(n,l,function(t){return e[t]}.bind(null,l));return n},a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="plugins/Feedback/vue/dist/",a(a.s="fae3")}({"19dc":function(t,a){t.exports=e},"8bbf":function(e,a){e.exports=t},fae3:function(e,t,a){"use strict";if(a.r(t),a.d(t,"ReviewLinks",(function(){return re})),a.d(t,"RateFeature",(function(){return be})),a.d(t,"FeedbackQuestion",(function(){return Se})),"undefined"!==typeof window){var n=window.document.currentScript,l=n&&n.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);l&&(a.p=l[1])}var o=a("19dc"),c=a("8bbf"),i=["title"],r={class:"ui-confirm ratefeatureDialog"},s={key:0},d={key:0},u={key:1},b=Object(c["createElementVNode"])("br",null,null,-1),k={class:"row"},m={style:{"text-align":"left","margin-top":"16px"}},p={for:"useful",class:"ratelabel"},j=Object(c["createElementVNode"])("br",null,null,-1),O={for:"easy",class:"ratelabel"},f=Object(c["createElementVNode"])("br",null,null,-1),g={for:"configurable",class:"ratelabel"},v=Object(c["createElementVNode"])("br",null,null,-1),h={for:"likeother",class:"ratelabel"},F={key:1},V={key:0},y={key:1},N=Object(c["createElementVNode"])("br",null,null,-1),E={class:"row"},R={style:{"text-align":"left"}},w={for:"missingfeatures",class:"ratelabel"},M=Object(c["createElementVNode"])("br",null,null,-1),D={for:"makeeasier",class:"ratelabel"},x=Object(c["createElementVNode"])("br",null,null,-1),B={for:"speedup",class:"ratelabel"},_=Object(c["createElementVNode"])("br",null,null,-1),C={for:"fixbugs",class:"ratelabel"},S=Object(c["createElementVNode"])("br",null,null,-1),T={for:"dislikeother",class:"ratelabel"},L=Object(c["createElementVNode"])("br",null,null,-1),H={key:2,class:"messageContainer",style:{"text-align":"left"}},U={key:0},q={key:1},z={key:2},Q={key:3},$={key:4},I={key:5},P={key:6},A={key:7},G={key:8},J={key:9,class:"error-text"},Y=["innerHTML"],K=["title","value"],W=["value"],X={class:"ui-confirm ratefeatureDialog"},Z=["innerHTML"],ee={key:0},te={key:1},ae=["value"];function ne(e,t,a,n,l,o){var ne=Object(c["resolveComponent"])("MatomoDialog"),le=Object(c["resolveComponent"])("ReviewLinks");return Object(c["openBlock"])(),Object(c["createElementBlock"])("div",{title:e.translate("Feedback_RateFeatureTitle",e.$sanitize(e.title)),class:"ratefeature"},[Object(c["createElementVNode"])("div",{class:"iconContainer",onMouseenter:t[2]||(t[2]=function(t){return e.expanded=!0}),onMouseleave:t[3]||(t[3]=function(t){return e.expanded=!1})},[Object(c["createElementVNode"])("img",{onClick:t[0]||(t[0]=function(t){e.likeFeature()}),class:"like-icon",src:"plugins/Feedback/vue/src/RateFeature/thumbs-up.png"}),Object(c["createElementVNode"])("img",{onClick:t[1]||(t[1]=function(t){e.dislikeFeature()}),class:"dislike-icon",src:"plugins/Feedback/vue/src/RateFeature/thumbs-down.png"})],32),Object(c["createVNode"])(ne,{modelValue:e.showFeedbackForm,"onUpdate:modelValue":t[14]||(t[14]=function(t){return e.showFeedbackForm=t}),onYes:t[15]||(t[15]=function(t){return e.sendFeedback()}),onValidation:t[16]||(t[16]=function(t){return e.sendFeedback()})},{default:Object(c["withCtx"])((function(){return[Object(c["createElementVNode"])("div",r,[e.like?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",s,[e.title?(Object(c["openBlock"])(),Object(c["createElementBlock"])("h2",d,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLikeNamedFeature",e.title)),1)):Object(c["createCommentVNode"])("",!0),e.title?Object(c["createCommentVNode"])("",!0):(Object(c["openBlock"])(),Object(c["createElementBlock"])("h2",u,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLike")),1)),b,Object(c["createElementVNode"])("div",k,[Object(c["createElementVNode"])("div",m,[Object(c["createElementVNode"])("label",p,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"useful",value:"useful","onUpdate:modelValue":t[4]||(t[4]=function(t){return e.likeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.likeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureUsefulInfo")),1)]),j,Object(c["createElementVNode"])("label",O,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"easy",value:"easy","onUpdate:modelValue":t[5]||(t[5]=function(t){return e.likeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.likeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureEasyToUse")),1)]),f,Object(c["createElementVNode"])("label",g,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"configurable",value:"configurable","onUpdate:modelValue":t[6]||(t[6]=function(t){return e.likeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.likeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureConfigurable")),1)]),v,Object(c["createElementVNode"])("label",h,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"likeother",value:"likeother","onUpdate:modelValue":t[7]||(t[7]=function(t){return e.likeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.likeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureOtherReason")),1)])])])])):Object(c["createCommentVNode"])("",!0),e.like?Object(c["createCommentVNode"])("",!0):(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",F,[e.title?(Object(c["openBlock"])(),Object(c["createElementBlock"])("h2",V,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislikeNamedFeature",e.title)),1)):Object(c["createCommentVNode"])("",!0),e.title?Object(c["createCommentVNode"])("",!0):(Object(c["openBlock"])(),Object(c["createElementBlock"])("h2",y,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislike")),1)),N,Object(c["createElementVNode"])("div",E,[Object(c["createElementVNode"])("div",R,[Object(c["createElementVNode"])("label",w,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"missingfeatures",value:"missingfeatures","onUpdate:modelValue":t[8]||(t[8]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.dislikeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureDislikeAddMissingFeatures")),1)]),M,Object(c["createElementVNode"])("label",D,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"makeeasier",value:"makeeasier","onUpdate:modelValue":t[9]||(t[9]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.dislikeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureDislikeMakeEasier")),1)]),x,Object(c["createElementVNode"])("label",B,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"speedup",value:"speedup","onUpdate:modelValue":t[10]||(t[10]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.dislikeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureDislikeSpeedUp")),1)]),_,Object(c["createElementVNode"])("label",C,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"fixbugs",value:"fixbugs","onUpdate:modelValue":t[11]||(t[11]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.dislikeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureDislikeFixBugs")),1)]),S,Object(c["createElementVNode"])("label",T,[Object(c["withDirectives"])(Object(c["createElementVNode"])("input",{type:"radio",id:"dislikeother",value:"dislikeother","onUpdate:modelValue":t[12]||(t[12]=function(t){return e.dislikeReason=t}),class:"rateradio"},null,512),[[c["vModelRadio"],e.dislikeReason]]),Object(c["createTextVNode"])(" "+Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureOtherReason")),1)]),L])])])),e.likeReason||e.dislikeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",H,[e.likeReason&&"useful"===e.likeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",U,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLikeExtraUseful")),1)):Object(c["createCommentVNode"])("",!0),e.likeReason&&"easy"===e.likeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",q,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLikeExtraEasy")),1)):Object(c["createCommentVNode"])("",!0),e.likeReason&&"configurable"===e.likeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",z,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLikeExtraConfigurable")),1)):Object(c["createCommentVNode"])("",!0),e.likeReason&&"likeother"===e.likeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",Q,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageLikeExtra")),1)):Object(c["createCommentVNode"])("",!0),e.dislikeReason&&"missingfeatures"===e.dislikeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",$,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislikeExtraMissing")),1)):Object(c["createCommentVNode"])("",!0),e.dislikeReason&&"makeeasier"===e.dislikeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",I,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislikeExtraEasier")),1)):Object(c["createCommentVNode"])("",!0),e.dislikeReason&&"fixbugs"===e.dislikeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",P,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislikeExtraBugs")),1)):Object(c["createCommentVNode"])("",!0),e.dislikeReason&&"speedup"===e.dislikeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",A,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislikeExtraSpeed")),1)):Object(c["createCommentVNode"])("",!0),e.dislikeReason&&"dislikeother"===e.dislikeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",G,Object(c["toDisplayString"])(e.translate("Feedback_RateFeatureLeaveMessageDislikeExtra")),1)):Object(c["createCommentVNode"])("",!0),e.errorMessage?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",J,Object(c["toDisplayString"])(e.errorMessage),1)):Object(c["createCommentVNode"])("",!0),Object(c["withDirectives"])(Object(c["createElementVNode"])("textarea",{ref:"feedbackText",class:Object(c["normalizeClass"])(["materialize-textarea",{"has-error":e.errorMessage}]),id:"feedbacktext","onUpdate:modelValue":t[13]||(t[13]=function(t){return e.feedbackMessage=t})},null,2),[[c["vModelText"],e.feedbackMessage]]),e.likeReason||e.dislikeReason?(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",{key:10,innerHTML:e.$sanitize(e.translate("Feedback_Policy","\n
"," "))},null,8,Y)):Object(c["createCommentVNode"])("",!0)])):Object(c["createCommentVNode"])("",!0),Object(c["createElementVNode"])("input",{class:"btn",type:"button",role:"validation",title:e.translate("Feedback_RateFeatureSendFeedbackInformation"),value:e.translate("Feedback_SendFeedback")},null,8,K),Object(c["createElementVNode"])("input",{type:"button",role:"cancel",value:e.translate("General_Cancel")},null,8,W)])]})),_:1},8,["modelValue"]),Object(c["createVNode"])(ne,{modelValue:e.ratingDone,"onUpdate:modelValue":t[17]||(t[17]=function(t){return e.ratingDone=t})},{default:Object(c["withCtx"])((function(){return[Object(c["createElementVNode"])("div",X,[Object(c["createElementVNode"])("h2",{innerHTML:e.$sanitize(e.translate("Feedback_ThankYouHeart","
"))},null,8,Z),e.like?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",ee,[Object(c["createVNode"])(le)])):Object(c["createCommentVNode"])("",!0),e.like?Object(c["createCommentVNode"])("",!0):(Object(c["openBlock"])(),Object(c["createElementBlock"])("p",te,Object(c["toDisplayString"])(e.translate("Feedback_AppreciateFeedback")),1)),Object(c["createElementVNode"])("input",{type:"button",value:e.translate("General_Close"),role:"yes"},null,8,ae)])]})),_:1},8,["modelValue"])],8,i)}var le={class:"requestReview"},oe=Object(c["createStaticVNode"])('
',3);function ce(e,t,a,n,l,o){return Object(c["openBlock"])(),Object(c["createElementBlock"])("div",le,[Object(c["createElementVNode"])("p",null,Object(c["toDisplayString"])(e.translate("Feedback_PleaseLeaveExternalReviewForMatomo")),1),oe])}var ie=Object(c["defineComponent"])({});ie.render=ce;var re=ie,se=window,de=se.$,ue=Object(c["defineComponent"])({props:{title:String},components:{MatomoDialog:o["MatomoDialog"],ReviewLinks:re},data:function(){return{like:!1,likeReason:null,dislikeReason:null,ratingDone:!1,expanded:!1,showFeedbackForm:!1,feedbackMessage:"",errorMessage:null}},watch:{likeReason:"doFocusInput",dislikeReason:"doFocusInput"},methods:{dislikeFeature:function(){this.ratingDone=!1,this.like=!1,this.showFeedbackForm=!0,this.errorMessage=null,this.likeReason=null,this.dislikeReason=null,this.feedbackMessage=""},likeFeature:function(){this.ratingDone=!1,this.like=!0,this.showFeedbackForm=!0,this.errorMessage=null,this.likeReason=null,this.dislikeReason=null,this.feedbackMessage=""},doFocusInput:function(){var e=this;this.$nextTick((function(){e.focusInput()}))},focusInput:function(){null!=this.$refs.feedbackText&&this.$refs.feedbackText.focus()},sendFeedback:function(){var e=this;this.errorMessage=null,o["AjaxHelper"].fetch({method:"Feedback.sendFeedbackForFeature",featureName:this.title,like:this.like?1:0,choice:this.like?this.likeReason:this.dislikeReason,message:this.feedbackMessage}).then((function(t){"success"===t.value?(de(".modal").modal("close"),e.ratingDone=!0,e.feedbackMessage=""):e.errorMessage=t.value}))}}});ue.render=ne;var be=ue,ke=(Object(o["createAngularJsAdapter"])({component:be,scope:{title:{angularJsBind:"@"}},directiveName:"piwikRateFeature"}),{key:0,class:"bannerHeader"}),me=Object(c["createElementVNode"])("i",{class:"icon-heart red-text"},null,-1),pe=Object(c["createElementVNode"])("i",{class:"icon-close white-text"},null,-1),je=[pe],Oe={class:"ratefeature"},fe={class:"ui-confirm ratefeatureDialog"},ge=["innerHTML"],ve=Object(c["createElementVNode"])("br",null,null,-1),he={class:"messageContainer"},Fe={key:0,class:"error-text"},Ve=Object(c["createElementVNode"])("br",null,null,-1),ye=["innerHTML"],Ne=["value"],Ee=["value"],Re={class:"ui-confirm ratefeatureDialog"},we=["innerHTML"],Me=["value"];
/*!
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */function xe(e,t,a,n,l,o){var i=Object(r["resolveComponent"])("MatomoDialog");return Object(r["openBlock"])(),Object(r["createElementBlock"])("div",null,[e.isHidden?Object(r["createCommentVNode"])("",!0):(Object(r["openBlock"])(),Object(r["createElementBlock"])("div",ke,[Object(r["createElementVNode"])("span",null,[Object(r["createTextVNode"])(Object(r["toDisplayString"])(e.translate("Feedback_FeedbackTitle"))+" ",1),me]),Object(r["createElementVNode"])("a",{onClick:t[0]||(t[0]=function(){return e.showQuestion&&e.showQuestion.apply(e,arguments)}),class:"btn"},Object(r["toDisplayString"])(e.translate("Feedback_Question".concat(e.question))),1),Object(r["createElementVNode"])("a",{class:"close-btn",onClick:t[1]||(t[1]=function(){return e.disableReminder&&e.disableReminder.apply(e,arguments)})},je)])),Object(r["createElementVNode"])("div",Oe,[Object(r["createVNode"])(i,{modelValue:e.showFeedbackForm,"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.showFeedbackForm=t}),onValidation:t[4]||(t[4]=function(t){return e.sendFeedback()})},{default:Object(r["withCtx"])((function(){return[Object(r["createElementVNode"])("div",fe,[Object(r["createElementVNode"])("h2",null,Object(r["toDisplayString"])(e.translate("Feedback_Question".concat(e.question))),1),Object(r["createElementVNode"])("p",{innerHTML:e.translate("Feedback_FeedbackSubtitle","
")},null,8,ve),ge,Object(r["createElementVNode"])("div",he,[e.errorMessage?(Object(r["openBlock"])(),Object(r["createElementBlock"])("div",Fe,Object(r["toDisplayString"])(e.errorMessage),1)):Object(r["createCommentVNode"])("",!0),Object(r["withDirectives"])(Object(r["createElementVNode"])("textarea",{id:"message",class:Object(r["normalizeClass"])({"has-error":e.errorMessage}),"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.feedbackMessage=t})},null,2),[[r["vModelText"],e.feedbackMessage]])]),Ve,Object(r["createElementVNode"])("p",{innerHTML:e.translate("Feedback_Policy","
"," ")},null,8,Ne),Object(r["createElementVNode"])("input",{type:"button",role:"validation",value:e.translate("Feedback_SendFeedback")},null,8,ye),Object(r["createElementVNode"])("input",{type:"button",role:"cancel",value:e.translate("General_Cancel")},null,8,Ee)])]})),_:1},8,["modelValue"]),Object(r["createVNode"])(i,{modelValue:e.feedbackDone,"onUpdate:modelValue":t[5]||(t[5]=function(t){return e.feedbackDone=t})},{default:Object(r["withCtx"])((function(){return[Object(r["createElementVNode"])("div",Re,[Object(r["createElementVNode"])("h2",null,Object(r["toDisplayString"])(e.translate("Feedback_ThankYou")),1),Object(r["createElementVNode"])("p",{innerHTML:e.translate("Feedback_ThankYourForFeedback","
")},null,8,Me),Object(r["createElementVNode"])("input",{type:"button",role:"cancel",value:e.translate("General_Close")},null,8,we)])]})),_:1},8,["modelValue"])])])}var De=window,Be=De.$,_e="feedback-question",Ce=Object(r["defineComponent"])({props:{showQuestionBanner:String},components:{MatomoDialog:o["MatomoDialog"]},computed:{isHidden:function(){return"0"===this.showQuestionBanner||!!this.hide}},data:function(){return{questionText:"",question:0,hide:null,feedbackDone:!1,expanded:!1,showFeedbackForm:!1,feedbackMessage:null,errorMessage:null}},watch:{showFeedbackForm:function(e){this.questionText=Object(o["translate"])("Feedback_Question".concat(this.question)),e&&setInterval((function(){Be("#message").focus()}),500)}},created:function(){"0"!==this.showQuestionBanner&&this.initQuestion()},methods:{initQuestion:function(){Object(o["getCookie"])(_e)?this.question=parseInt(Object(o["getCookie"])(_e)):this.question=this.getRandomIntBetween(0,4);var e=(this.question+1)%4,t=6048e5;Object(o["setCookie"])(_e,e,t)},getRandomIntBetween:function(e,t){return e=Math.ceil(e),t=Math.floor(t),Math.floor(Math.random()*(t-e+1)+e)},showQuestion:function(){this.showFeedbackForm=!0,this.errorMessage=null},disableReminder:function(){o["AjaxHelper"].fetch({method:"Feedback.updateFeedbackReminderDate"}),this.hide=!0},sendFeedback:function(){var e=this;this.errorMessage=null,o["AjaxHelper"].fetch({method:"Feedback.sendFeedbackForSurvey",question:this.questionText,message:this.feedbackMessage}).then((function(t){"success"===t.value?(Be(".modal").modal("close"),e.feedbackDone=!0,e.hide=!0):e.errorMessage=t.value}))}}});Ce.render=xe;var Te=Ce;
+ */function De(e,t,a,n,l,o){var i=Object(c["resolveComponent"])("MatomoDialog");return Object(c["openBlock"])(),Object(c["createElementBlock"])("div",null,[e.isHidden?Object(c["createCommentVNode"])("",!0):(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",ke,[Object(c["createElementVNode"])("span",null,[Object(c["createTextVNode"])(Object(c["toDisplayString"])(e.translate("Feedback_FeedbackTitle"))+" ",1),me]),Object(c["createElementVNode"])("a",{onClick:t[0]||(t[0]=function(){return e.showQuestion&&e.showQuestion.apply(e,arguments)}),class:"btn"},Object(c["toDisplayString"])(e.translate("Feedback_Question".concat(e.question))),1),Object(c["createElementVNode"])("a",{class:"close-btn",onClick:t[1]||(t[1]=function(){return e.disableReminder&&e.disableReminder.apply(e,arguments)})},je)])),Object(c["createElementVNode"])("div",Oe,[Object(c["createVNode"])(i,{modelValue:e.showFeedbackForm,"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.showFeedbackForm=t}),onValidation:t[4]||(t[4]=function(t){return e.sendFeedback()})},{default:Object(c["withCtx"])((function(){return[Object(c["createElementVNode"])("div",fe,[Object(c["createElementVNode"])("h2",null,Object(c["toDisplayString"])(e.translate("Feedback_Question".concat(e.question))),1),Object(c["createElementVNode"])("p",{innerHTML:e.$sanitize(e.translate("Feedback_FeedbackSubtitle","
"))},null,8,ge),ve,Object(c["createElementVNode"])("div",he,[e.errorMessage?(Object(c["openBlock"])(),Object(c["createElementBlock"])("div",Fe,Object(c["toDisplayString"])(e.errorMessage),1)):Object(c["createCommentVNode"])("",!0),Object(c["withDirectives"])(Object(c["createElementVNode"])("textarea",{id:"message",class:Object(c["normalizeClass"])({"has-error":e.errorMessage}),"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.feedbackMessage=t})},null,2),[[c["vModelText"],e.feedbackMessage]])]),Ve,Object(c["createElementVNode"])("p",{innerHTML:e.$sanitize(e.feedbackPolicy)},null,8,ye),Object(c["createElementVNode"])("input",{type:"button",role:"validation",value:e.translate("Feedback_SendFeedback")},null,8,Ne),Object(c["createElementVNode"])("input",{type:"button",role:"cancel",value:e.translate("General_Cancel")},null,8,Ee)])]})),_:1},8,["modelValue"]),Object(c["createVNode"])(i,{modelValue:e.feedbackDone,"onUpdate:modelValue":t[5]||(t[5]=function(t){return e.feedbackDone=t})},{default:Object(c["withCtx"])((function(){return[Object(c["createElementVNode"])("div",Re,[Object(c["createElementVNode"])("h2",null,Object(c["toDisplayString"])(e.translate("Feedback_ThankYou")),1),Object(c["createElementVNode"])("p",{innerHTML:e.$sanitize(e.translate("Feedback_ThankYourForFeedback","
"))},null,8,we),Object(c["createElementVNode"])("input",{type:"button",role:"cancel",value:e.translate("General_Close")},null,8,Me)])]})),_:1},8,["modelValue"])])])}var xe=window,Be=xe.$,_e="feedback-question",Ce=Object(c["defineComponent"])({props:{showQuestionBanner:String},components:{MatomoDialog:o["MatomoDialog"]},computed:{isHidden:function(){return"0"===this.showQuestionBanner||!!this.hide},feedbackPolicy:function(){return Object(o["translate"])("Feedback_Policy",'
'," ")}},data:function(){return{questionText:"",question:0,hide:null,feedbackDone:!1,expanded:!1,showFeedbackForm:!1,feedbackMessage:null,errorMessage:null}},watch:{showFeedbackForm:function(e){this.questionText=Object(o["translate"])("Feedback_Question".concat(this.question)),e&&setInterval((function(){Be("#message").focus()}),500)}},created:function(){"0"!==this.showQuestionBanner&&this.initQuestion()},methods:{initQuestion:function(){Object(o["getCookie"])(_e)?this.question=parseInt(Object(o["getCookie"])(_e)):this.question=this.getRandomIntBetween(0,4);var e=(this.question+1)%4,t=6048e5;Object(o["setCookie"])(_e,"".concat(e),t)},getRandomIntBetween:function(e,t){return e=Math.ceil(e),t=Math.floor(t),Math.floor(Math.random()*(t-e+1)+e)},showQuestion:function(){this.showFeedbackForm=!0,this.errorMessage=null},disableReminder:function(){o["AjaxHelper"].fetch({method:"Feedback.updateFeedbackReminderDate"}),this.hide=!0},sendFeedback:function(){var e=this;this.errorMessage=null,o["AjaxHelper"].fetch({method:"Feedback.sendFeedbackForSurvey",question:this.questionText,message:this.feedbackMessage}).then((function(t){"success"===t.value?(Be(".modal").modal("close"),e.feedbackDone=!0,e.hide=!0):e.errorMessage=t.value}))}}});Ce.render=De;var Se=Ce;
/*!
* Matomo - free/libre analytics platform
*
* @link https://matomo.org
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- */Object(o["createAngularJsAdapter"])({component:Te,scope:{showQuestionBanner:{angularJsBind:"@"}},directiveName:"piwikFeedbackQuestion"})}})}));
+ */Object(o["createAngularJsAdapter"])({component:Se,scope:{showQuestionBanner:{angularJsBind:"@"}},directiveName:"piwikFeedbackQuestion"})}})}));
//# sourceMappingURL=Feedback.umd.min.js.map
\ No newline at end of file
diff --git a/app/plugins/Feedback/vue/dist/umd.metadata.json b/app/plugins/Feedback/vue/dist/umd.metadata.json
new file mode 100644
index 000000000..9ecfcc045
--- /dev/null
+++ b/app/plugins/Feedback/vue/dist/umd.metadata.json
@@ -0,0 +1,5 @@
+{
+ "dependsOn": [
+ "CoreHome"
+ ]
+}
\ No newline at end of file
diff --git a/app/plugins/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue b/app/plugins/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue
index 60938dcc2..9e8c43c08 100644
--- a/app/plugins/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue
+++ b/app/plugins/Feedback/vue/src/FeedbackQuestion/FeedbackQuestion.vue
@@ -24,8 +24,8 @@
>
{{ translate(`Feedback_Question${question}`) }}
+ v-html="$sanitize(translate('Feedback_FeedbackSubtitle',
+ `
`))">
{{ errorMessage }}
@@ -33,7 +33,7 @@
+ v-html="$sanitize(feedbackPolicy)">
{{ translate(`Feedback_ThankYou`) }}
-
+
',
+ '',
+ );
+ },
},
- data() {
+ data(): FeedbackQuestionState {
return {
questionText: '',
question: 0,
@@ -124,14 +145,14 @@ export default defineComponent({
this.question = this.getRandomIntBetween(0, 4);
} else {
// eslint-disable-next-line radix
- this.question = parseInt(getCookie(cookieName));
+ this.question = parseInt(getCookie(cookieName)!);
}
const nextQuestion = (this.question + 1) % 4;
const sevenDays = 7 * 60 * 60 * 24 * 1000;
- setCookie(cookieName, nextQuestion, sevenDays);
+ setCookie(cookieName, `${nextQuestion}`, sevenDays);
},
- getRandomIntBetween(min, max) {
+ getRandomIntBetween(min: number, max: number) {
// eslint-disable-next-line no-param-reassign
min = Math.ceil(min);
// eslint-disable-next-line no-param-reassign
@@ -154,7 +175,7 @@ export default defineComponent({
method: 'Feedback.sendFeedbackForSurvey',
question: this.questionText,
message: this.feedbackMessage,
- }).then((res) => {
+ }).then((res: SendFeedbackForSurveyResponse) => {
if (res.value === 'success') {
$('.modal').modal('close');
this.feedbackDone = true;
diff --git a/app/plugins/Feedback/vue/src/RateFeature/RateFeature.vue b/app/plugins/Feedback/vue/src/RateFeature/RateFeature.vue
index 3c7ce7117..76ba6bce6 100644
--- a/app/plugins/Feedback/vue/src/RateFeature/RateFeature.vue
+++ b/app/plugins/Feedback/vue/src/RateFeature/RateFeature.vue
@@ -114,33 +114,33 @@
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageLikeExtraUseful') }}
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageLikeExtraEasy') }}
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageLikeExtraConfigurable') }}
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageLikeExtra') }}
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageDislikeExtraMissing') }}
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageDislikeExtraEasier') }}
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageDislikeExtraBugs') }}
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageDislikeExtraSpeed') }}
-
+
+ {{ translate('Feedback_RateFeatureLeaveMessageDislikeExtra') }}
{{ errorMessage }}
@@ -148,8 +148,8 @@
:class="{'has-error':errorMessage}"
v-model="feedbackMessage"/>
+ v-html="$sanitize(translate('Feedback_Policy',`
+ `,' '))">
@@ -175,7 +175,10 @@
-
+
@@ -199,6 +202,17 @@ import ReviewLinks from '../ReviewLinks/ReviewLinks.vue';
const { $ } = window;
+interface RateFeatureState {
+ like: boolean;
+ likeReason: null|string;
+ dislikeReason: null|string;
+ ratingDone: boolean;
+ expanded: boolean;
+ showFeedbackForm: boolean;
+ feedbackMessage: string;
+ errorMessage: string|null;
+}
+
export default defineComponent({
props: {
title: String,
@@ -207,7 +221,7 @@ export default defineComponent({
MatomoDialog,
ReviewLinks,
},
- data() {
+ data(): RateFeatureState {
return {
like: false,
likeReason: null,
@@ -249,7 +263,7 @@ export default defineComponent({
},
focusInput() {
if (this.$refs.feedbackText != null) {
- this.$refs.feedbackText.focus();
+ (this.$refs.feedbackText as HTMLElement).focus();
}
},
sendFeedback() {
@@ -257,7 +271,7 @@ export default defineComponent({
AjaxHelper.fetch({
method: 'Feedback.sendFeedbackForFeature',
featureName: this.title,
- like: this.like ? '1' : '0',
+ like: this.like ? 1 : 0,
choice: this.like ? this.likeReason : this.dislikeReason,
message: this.feedbackMessage,
}).then((res) => {
diff --git a/app/plugins/GeoIp2/GeoIP2AutoUpdater.php b/app/plugins/GeoIp2/GeoIP2AutoUpdater.php
index 29bcafd97..2028e9cb8 100644
--- a/app/plugins/GeoIp2/GeoIP2AutoUpdater.php
+++ b/app/plugins/GeoIp2/GeoIP2AutoUpdater.php
@@ -14,6 +14,7 @@
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Date;
+use Piwik\Filesystem;
use Piwik\Http;
use Piwik\Log;
use Piwik\Option;
@@ -195,7 +196,14 @@ protected function downloadFile($dbType, $url)
public static function getTemporaryFolder($file, $isDownload = false)
{
- return \Piwik\Container\StaticContainer::get('path.tmp') . '/latest/' . $file . ($isDownload ? '.download' : '');
+ $folder = \Piwik\Container\StaticContainer::get('path.tmp') . '/latest/';
+ if (!is_dir($folder)) {
+ Filesystem::mkdir($folder);
+ }
+ if (!is_writable($folder)) {
+ throw new \Exception("GeoIP2AutoUpdater: Can't create temporary file for download.");
+ }
+ return $folder . $file . ($isDownload ? '.download' : '');
}
/**
diff --git a/app/plugins/GeoIp2/GeoIp2.php b/app/plugins/GeoIp2/GeoIp2.php
index 03ccd58b1..273cffeac 100644
--- a/app/plugins/GeoIp2/GeoIp2.php
+++ b/app/plugins/GeoIp2/GeoIp2.php
@@ -24,7 +24,6 @@ class GeoIp2 extends \Piwik\Plugin
public function registerEvents()
{
return array(
- 'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
'Installation.defaultSettingsForm.init' => 'installationFormInit',
'Installation.defaultSettingsForm.submit' => 'installationFormSubmit',
@@ -40,16 +39,10 @@ public function deactivate()
{
// switch to default provider if GeoIP2 provider was in use
if (LocationProvider::getCurrentProvider() instanceof \Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2) {
- LocationProvider::setCurrentProvider(LocationProvider\DefaultProvider::ID);
+ LocationProvider::setCurrentProvider(LocationProvider::getDefaultProviderId());
}
}
- public function getJsFiles(&$jsFiles)
- {
- $jsFiles[] = "plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.controller.js";
- $jsFiles[] = "plugins/GeoIp2/angularjs/geoip2-updater/geoip2-updater.directive.js";
- }
-
public function getClientSideTranslationKeys(&$translationKeys)
{
$translationKeys[] = "GeoIp2_FatalErrorDuringDownload";
@@ -57,6 +50,29 @@ public function getClientSideTranslationKeys(&$translationKeys)
$translationKeys[] = "General_Done";
$translationKeys[] = "General_Save";
$translationKeys[] = "General_Continue";
+ $translationKeys[] = 'GeoIp2_ISPRequiresProviderPlugin';
+ $translationKeys[] = 'GeoIp2_UpdaterWasLastRun';
+ $translationKeys[] = 'GeoIp2_UpdaterIsNotScheduledToRun';
+ $translationKeys[] = 'GeoIp2_GeoIPUpdaterIntro';
+ $translationKeys[] = 'GeoIp2_IWantToDownloadFreeGeoIP';
+ $translationKeys[] = 'General_GetStarted';
+ $translationKeys[] = 'GeoIp2_GeoIPDatabases';
+ $translationKeys[] = 'GeoIp2_NotManagingGeoIPDBs';
+ $translationKeys[] = 'GeoIp2_IPurchasedGeoIPDBs';
+ $translationKeys[] = 'UserCountry_GeoIpDbIpAccuracyNote';
+ $translationKeys[] = 'GeoIp2_GeoIPUpdaterInstructions';
+ $translationKeys[] = 'GeoIp2_GeoLiteCityLink';
+ $translationKeys[] = 'UserCountry_MaxMindLinkExplanation';
+ $translationKeys[] = 'GeoIp2_LocationDatabase';
+ $translationKeys[] = 'Actions_ColumnDownloadURL';
+ $translationKeys[] = 'GeoIp2_LocationDatabaseHint';
+ $translationKeys[] = 'GeoIp2_ISPDatabase';
+ $translationKeys[] = 'GeoIp2_DownloadNewDatabasesEvery';
+ $translationKeys[] = 'GeoIp2_CannotSetupGeoIPAutoUpdating';
+ $translationKeys[] = 'GeoIp2_UpdaterHasNotBeenRun';
+ $translationKeys[] = 'GeoIp2_UpdaterScheduledForNextRun';
+ $translationKeys[] = 'GeoIp2_UpdaterWillRunNext';
+ $translationKeys[] = 'GeoIp2_DownloadingDb';
}
/**
diff --git a/app/plugins/GeoIp2/LocationProvider/GeoIp2/Php.php b/app/plugins/GeoIp2/LocationProvider/GeoIp2/Php.php
index 238782a0f..39ba48706 100644
--- a/app/plugins/GeoIp2/LocationProvider/GeoIp2/Php.php
+++ b/app/plugins/GeoIp2/LocationProvider/GeoIp2/Php.php
@@ -12,13 +12,11 @@
use GeoIp2\Exception\AddressNotFoundException;
use MaxMind\Db\Reader\InvalidDatabaseException;
use Piwik\Date;
-use Piwik\Common;
use Piwik\Log;
use Piwik\Piwik;
use Piwik\Plugin\Manager;
use Piwik\Plugins\GeoIp2\GeoIP2AutoUpdater;
use Piwik\Plugins\GeoIp2\LocationProvider\GeoIp2;
-use Piwik\Plugins\Marketplace\Api\Exception;
use Piwik\Plugins\UserCountry\LocationProvider;
use Piwik\SettingsPiwik;
use Piwik\View;
diff --git a/app/plugins/GeoIp2/config/test.php b/app/plugins/GeoIp2/config/test.php
deleted file mode 100644
index c45c66093..000000000
--- a/app/plugins/GeoIp2/config/test.php
+++ /dev/null
@@ -1,5 +0,0 @@
- DI\string('{path.root}/tests/lib/geoip-files/'),
-];
\ No newline at end of file
diff --git a/app/plugins/GeoIp2/lang/ga.json b/app/plugins/GeoIp2/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/GeoIp2/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/GeoIp2/templates/configuration.twig b/app/plugins/GeoIp2/templates/configuration.twig
index 91ea3dd5d..537b27e7e 100644
--- a/app/plugins/GeoIp2/templates/configuration.twig
+++ b/app/plugins/GeoIp2/templates/configuration.twig
@@ -1,51 +1,17 @@
-
-
-
-
- {% if showGeoIPUpdateSection %}
- {% if not geoIPDatabasesInstalled %}
-
-
-
{{ 'GeoIp2_NotManagingGeoIPDBs'|translate|e('html_attr') }}
-
-
-
-
{{ 'GeoIp2_IWantToDownloadFreeGeoIP'|translate|raw }}*
-
-
-
{{ 'GeoIp2_IPurchasedGeoIPDBs'|translate('',' ','',' ')|raw }}
-
-
-
-
-
-
-
-
-
-
* {{ 'UserCountry_GeoIpDbIpAccuracyNote'|translate('', ' ')|raw }}.
-
-
-
-
-
'~dbipLiteFilename~'') ~ '...')|json_encode }}"
- progress="locationUpdater.progressFreeDownload">
-
-
-
- {% endif %}
-
- {% include "@GeoIp2/_updaterManage.twig" %}
- {% else %}
-
{{ 'GeoIp2_CannotSetupGeoIPAutoUpdating'|translate }}
- {% endif %}
-
-
\ No newline at end of file
+
+
diff --git a/app/plugins/GeoIp2/vue/dist/GeoIp2.umd.js b/app/plugins/GeoIp2/vue/dist/GeoIp2.umd.js
new file mode 100644
index 000000000..31abf9a44
--- /dev/null
+++ b/app/plugins/GeoIp2/vue/dist/GeoIp2.umd.js
@@ -0,0 +1,662 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("CoreHome"), require("vue"), require("CorePluginsAdmin"));
+ else if(typeof define === 'function' && define.amd)
+ define(["CoreHome", , "CorePluginsAdmin"], factory);
+ else if(typeof exports === 'object')
+ exports["GeoIp2"] = factory(require("CoreHome"), require("vue"), require("CorePluginsAdmin"));
+ else
+ root["GeoIp2"] = factory(root["CoreHome"], root["Vue"], root["CorePluginsAdmin"]);
+})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__, __WEBPACK_EXTERNAL_MODULE_a5a2__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "plugins/GeoIp2/vue/dist/";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "fae3");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "19dc":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;
+
+/***/ }),
+
+/***/ "8bbf":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;
+
+/***/ }),
+
+/***/ "a5a2":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__;
+
+/***/ }),
+
+/***/ "fae3":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, "Geoip2Updater", function() { return /* reexport */ Geoip2Updater; });
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
+// This file is imported into lib/wc client bundles.
+
+if (typeof window !== 'undefined') {
+ var currentScript = window.document.currentScript
+ if (false) { var getCurrentScript; }
+
+ var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
+ if (src) {
+ __webpack_require__.p = src[1] // eslint-disable-line
+ }
+}
+
+// Indicate to webpack that this file can be concatenated
+/* harmony default export */ var setPublicPath = (null);
+
+// EXTERNAL MODULE: external "CoreHome"
+var external_CoreHome_ = __webpack_require__("19dc");
+
+// EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"}
+var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf");
+
+// 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/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.vue?vue&type=template&id=23b5cb60
+
+var _hoisted_1 = {
+ key: 0
+};
+var _hoisted_2 = {
+ key: 0
+};
+var _hoisted_3 = {
+ id: "manage-geoip-dbs"
+};
+var _hoisted_4 = {
+ class: "row",
+ id: "geoipdb-screen1"
+};
+var _hoisted_5 = {
+ class: "geoipdb-column-1 col s6"
+};
+
+var _hoisted_6 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("sup", null, [/*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("small", null, "*")], -1);
+
+var _hoisted_7 = {
+ class: "geoipdb-column-2 col s6"
+};
+var _hoisted_8 = ["innerHTML"];
+var _hoisted_9 = {
+ class: "geoipdb-column-1 col s6"
+};
+var _hoisted_10 = ["value"];
+var _hoisted_11 = {
+ class: "geoipdb-column-2 col s6"
+};
+var _hoisted_12 = ["value"];
+var _hoisted_13 = {
+ class: "row"
+};
+
+var _hoisted_14 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])("* ");
+
+var _hoisted_15 = ["innerHTML"];
+var _hoisted_16 = {
+ id: "geoipdb-screen2-download"
+};
+var _hoisted_17 = {
+ key: 1,
+ id: "geoipdb-update-info"
+};
+var _hoisted_18 = ["innerHTML"];
+
+var _hoisted_19 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_20 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_21 = ["innerHTML"];
+var _hoisted_22 = ["innerHTML"];
+
+var _hoisted_23 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_24 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_25 = {
+ id: "locationProviderUpdatePeriodInlineHelp",
+ class: "inline-help-node",
+ ref: "inlineHelpNode"
+};
+var _hoisted_26 = ["innerHTML"];
+var _hoisted_27 = {
+ key: 1
+};
+
+var _hoisted_28 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_29 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_30 = ["innerHTML"];
+var _hoisted_31 = ["value"];
+
+var _hoisted_32 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ id: "done-updating-updater"
+}, null, -1);
+
+var _hoisted_33 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ id: "geoipdb-update-info-error"
+}, null, -1);
+
+var _hoisted_34 = ["innerHTML"];
+var _hoisted_35 = {
+ key: 1
+};
+var _hoisted_36 = {
+ class: "form-description"
+};
+function render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_Progressbar = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Progressbar");
+
+ var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field");
+
+ var _component_ContentBlock = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ContentBlock");
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_ContentBlock, {
+ "content-title": _ctx.contentTitle,
+ id: "geoip-db-mangement"
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [_ctx.showGeoipUpdateSection ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_1, [!_ctx.geoipDatabaseInstalled ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_2, [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_["createElementVNode"])("h3", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('GeoIp2_NotManagingGeoIPDBs')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_3, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_5, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('GeoIp2_IWantToDownloadFreeGeoIP')), 1), _hoisted_6])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_7, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", {
+ innerHTML: _ctx.$sanitize(_ctx.purchasedGeoIpText)
+ }, null, 8, _hoisted_8)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_9, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "button",
+ class: "btn",
+ onClick: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.startDownloadFreeGeoIp();
+ }),
+ value: "".concat(_ctx.translate('General_GetStarted'), "...")
+ }, null, 8, _hoisted_10)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_11, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "button",
+ class: "btn",
+ id: "start-automatic-update-geoip",
+ onClick: _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.startAutomaticUpdateGeoIp();
+ }),
+ value: "".concat(_ctx.translate('General_GetStarted'), "...")
+ }, null, 8, _hoisted_12)])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_13, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("sup", null, [_hoisted_14, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("small", {
+ innerHTML: _ctx.$sanitize(_ctx.accuracyNote)
+ }, null, 8, _hoisted_15)])])])])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showPiwikNotManagingInfo]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(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_Progressbar, {
+ label: _ctx.freeProgressbarLabel,
+ progress: _ctx.progressFreeDownload
+ }, null, 8, ["label", "progress"])])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showFreeDownload]])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.geoipDatabaseInstalled && !_ctx.downloadErrorMessage ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_17, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ innerHTML: _ctx.$sanitize(_ctx.geoIPUpdaterInstructions)
+ }, null, 8, _hoisted_18), _hoisted_19, _hoisted_20, !!_ctx.dbipLiteUrl ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", {
+ key: 0,
+ innerHTML: _ctx.$sanitize(_ctx.geoliteCityLink)
+ }, null, 8, _hoisted_21)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ innerHTML: _ctx.$sanitize(_ctx.maxMindLinkExplanation)
+ }, null, 8, _hoisted_22), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", null, [_hoisted_23, _hoisted_24, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('GeoIp2_GeoIPUpdaterIntro')) + ": ", 1)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.geoipDatabaseInstalled]])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "text",
+ name: "geoip-location-db",
+ introduction: _ctx.translate('GeoIp2_LocationDatabase'),
+ title: _ctx.translate('Actions_ColumnDownloadURL'),
+ "inline-help": _ctx.translate('GeoIp2_LocationDatabaseHint'),
+ modelValue: _ctx.locationDbUrl,
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = function ($event) {
+ return _ctx.locationDbUrl = $event;
+ })
+ }, null, 8, ["introduction", "title", "inline-help", "modelValue"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "text",
+ name: "geoip-isp-db",
+ introduction: _ctx.translate('GeoIp2_ISPDatabase'),
+ title: _ctx.translate('Actions_ColumnDownloadURL'),
+ "inline-help": _ctx.providerPluginHelp,
+ modelValue: _ctx.ispDbUrl,
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = function ($event) {
+ return _ctx.ispDbUrl = $event;
+ }),
+ disabled: !_ctx.isProviderPluginActive
+ }, null, 8, ["introduction", "title", "inline-help", "modelValue", "disabled"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "radio",
+ name: "geoip-update-period",
+ introduction: _ctx.translate('GeoIp2_DownloadNewDatabasesEvery'),
+ modelValue: _ctx.updatePeriod,
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = function ($event) {
+ return _ctx.updatePeriod = $event;
+ }),
+ options: _ctx.updatePeriodOptions
+ }, {
+ "inline-help": Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_25, [_ctx.lastTimeUpdaterRun ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", {
+ key: 0,
+ innerHTML: _ctx.$sanitize(_ctx.translate('GeoIp2_UpdaterWasLastRun', _ctx.lastTimeUpdaterRun))
+ }, null, 8, _hoisted_26)) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", _hoisted_27, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('GeoIp2_UpdaterHasNotBeenRun')), 1)), _hoisted_28, _hoisted_29, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ id: "geoip-updater-next-run-time",
+ innerHTML: _ctx.$sanitize(_ctx.nextRunTimeText)
+ }, null, 8, _hoisted_30)], 512)];
+ }),
+ _: 1
+ }, 8, ["introduction", "modelValue", "options"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "button",
+ class: "btn",
+ onClick: _cache[5] || (_cache[5] = function ($event) {
+ return _ctx.saveGeoIpLinks();
+ }),
+ value: _ctx.buttonUpdateSaveText
+ }, null, 8, _hoisted_31), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [_hoisted_32, _hoisted_33, 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_Progressbar, {
+ progress: _ctx.progressUpdateDownload,
+ label: _ctx.progressUpdateLabel
+ }, null, 8, ["progress", "label"]), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.isUpdatingGeoIpDatabase]])])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.downloadErrorMessage ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", {
+ key: 2,
+ innerHTML: _ctx.$sanitize(_ctx.downloadErrorMessage)
+ }, null, 8, _hoisted_34)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])) : (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_35, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", _hoisted_36, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('GeoIp2_CannotSetupGeoIPAutoUpdating')), 1)]))];
+ }),
+ _: 1
+ }, 8, ["content-title"]);
+}
+// CONCATENATED MODULE: ./plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.vue?vue&type=template&id=23b5cb60
+
+// EXTERNAL MODULE: external "CorePluginsAdmin"
+var external_CorePluginsAdmin_ = __webpack_require__("a5a2");
+
+// 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/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.vue?vue&type=script&lang=ts
+
+
+
+var _window = window,
+ $ = _window.$;
+/* harmony default export */ var Geoip2Updatervue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ props: {
+ geoipDatabaseStartedInstalled: Boolean,
+ showGeoipUpdateSection: {
+ type: Boolean,
+ required: true
+ },
+ dbipLiteUrl: {
+ type: String,
+ required: true
+ },
+ dbipLiteFilename: {
+ type: String,
+ required: true
+ },
+ geoipLocUrl: String,
+ isProviderPluginActive: Boolean,
+ geoipIspUrl: String,
+ lastTimeUpdaterRun: String,
+ geoipUpdatePeriod: String,
+ updatePeriodOptions: {
+ type: Object,
+ required: true
+ },
+ nextRunTime: Number,
+ nextRunTimePretty: String
+ },
+ components: {
+ Progressbar: external_CoreHome_["Progressbar"],
+ Field: external_CorePluginsAdmin_["Field"],
+ ContentBlock: external_CoreHome_["ContentBlock"]
+ },
+ data: function data() {
+ return {
+ geoipDatabaseInstalled: !!this.geoipDatabaseStartedInstalled,
+ showFreeDownload: false,
+ showPiwikNotManagingInfo: true,
+ progressFreeDownload: 0,
+ progressUpdateDownload: 0,
+ buttonUpdateSaveText: Object(external_CoreHome_["translate"])('General_Save'),
+ progressUpdateLabel: '',
+ locationDbUrl: this.geoipLocUrl || '',
+ ispDbUrl: this.geoipIspUrl || '',
+ orgDbUrl: '',
+ updatePeriod: this.geoipUpdatePeriod || 'month',
+ isUpdatingGeoIpDatabase: false,
+ downloadErrorMessage: null,
+ nextRunTimePrettyUpdated: undefined
+ };
+ },
+ methods: {
+ startDownloadFreeGeoIp: function startDownloadFreeGeoIp() {
+ var _this = this;
+
+ this.showFreeDownload = true;
+ this.showPiwikNotManagingInfo = false;
+ this.progressFreeDownload = 0; // start download of free dbs
+
+ this.downloadNextChunk('downloadFreeDBIPLiteDB', function (v) {
+ _this.progressFreeDownload = v;
+ }, false, {}).then(function () {
+ window.location.reload();
+ }).catch(function (e) {
+ _this.geoipDatabaseInstalled = true;
+ _this.downloadErrorMessage = e.message;
+ });
+ },
+ startAutomaticUpdateGeoIp: function startAutomaticUpdateGeoIp() {
+ this.buttonUpdateSaveText = Object(external_CoreHome_["translate"])('General_Continue');
+ this.showGeoIpUpdateInfo();
+ },
+ showGeoIpUpdateInfo: function showGeoIpUpdateInfo() {
+ this.geoipDatabaseInstalled = true; // todo we need to replace this the proper way eventually
+ },
+ saveGeoIpLinks: function saveGeoIpLinks() {
+ var _this2 = this;
+
+ return external_CoreHome_["AjaxHelper"].post({
+ period: this.updatePeriod,
+ module: 'GeoIp2',
+ action: 'updateGeoIPLinks'
+ }, {
+ loc_db: this.locationDbUrl,
+ isp_db: this.ispDbUrl,
+ org_db: this.orgDbUrl
+ }, {
+ withTokenInUrl: true
+ }).then(function (response) {
+ return _this2.downloadNextFileIfNeeded(response, null);
+ }).then(function (response) {
+ _this2.progressUpdateLabel = '';
+ _this2.isUpdatingGeoIpDatabase = false;
+ external_CoreHome_["NotificationsStore"].show({
+ message: Object(external_CoreHome_["translate"])('General_Done'),
+ placeat: '#done-updating-updater',
+ context: 'success',
+ noclear: true,
+ type: 'toast',
+ style: {
+ display: 'inline-block'
+ },
+ id: 'userCountryGeoIpUpdate'
+ });
+ _this2.nextRunTimePrettyUpdated = response.nextRunTime;
+ $(_this2.$refs.inlineHelpNode).effect('highlight', {
+ color: '#FFFFCB'
+ }, 2000);
+ return undefined;
+ }).catch(function (e) {
+ _this2.isUpdatingGeoIpDatabase = false;
+ external_CoreHome_["NotificationsStore"].show({
+ message: e.message,
+ placeat: '#geoipdb-update-info-error',
+ context: 'error',
+ style: {
+ display: 'inline-block'
+ },
+ id: 'userCountryGeoIpUpdate',
+ type: 'transient'
+ });
+ });
+ },
+ downloadNextFileIfNeeded: function downloadNextFileIfNeeded(response, currentDownloading) {
+ var _this3 = this;
+
+ if (response !== null && response !== void 0 && response.to_download) {
+ var continuing = currentDownloading === response.to_download;
+ this.progressUpdateDownload = 0;
+ this.progressUpdateLabel = response.to_download_label;
+ this.isUpdatingGeoIpDatabase = true; // start/continue download
+
+ return this.downloadNextChunk('downloadMissingGeoIpDb', function (v) {
+ _this3.progressUpdateDownload = v;
+ }, continuing, {
+ key: response.to_download
+ }).then(function (r) {
+ return _this3.downloadNextFileIfNeeded(r, response.to_download);
+ });
+ }
+
+ return Promise.resolve(response);
+ },
+ downloadNextChunk: function downloadNextChunk(action, progressBarSet, cont, extraData) {
+ var _this4 = this;
+
+ var data = Object.assign({}, extraData);
+ return external_CoreHome_["AjaxHelper"].post({
+ module: 'GeoIp2',
+ action: action,
+ continue: cont ? 1 : 0
+ }, data, {
+ withTokenInUrl: true
+ }).catch(function () {
+ throw new Error(Object(external_CoreHome_["translate"])('GeoIp2_FatalErrorDuringDownload'));
+ }).then(function (response) {
+ if (response.error) {
+ throw new Error(response.error);
+ } // update progress bar
+
+
+ var newProgressVal = Math.floor(response.current_size / response.expected_file_size * 100); // if incomplete, download next chunk, otherwise, show updater manager
+
+ progressBarSet(Math.min(newProgressVal, 100));
+
+ if (newProgressVal < 100) {
+ return _this4.downloadNextChunk(action, progressBarSet, true, extraData);
+ }
+
+ return response;
+ });
+ }
+ },
+ computed: {
+ nextRunTimeText: function nextRunTimeText() {
+ if (this.nextRunTimePrettyUpdated) {
+ return this.nextRunTimePrettyUpdated;
+ }
+
+ if (!this.nextRunTime) {
+ return Object(external_CoreHome_["translate"])('GeoIp2_UpdaterIsNotScheduledToRun');
+ }
+
+ if (this.nextRunTime * 1000 < Date.now()) {
+ return Object(external_CoreHome_["translate"])('GeoIp2_UpdaterScheduledForNextRun');
+ }
+
+ return Object(external_CoreHome_["translate"])('GeoIp2_UpdaterWillRunNext', "
".concat(this.nextRunTimePretty, " "));
+ },
+ providerPluginHelp: function providerPluginHelp() {
+ if (this.isProviderPluginActive) {
+ return undefined;
+ }
+
+ var text = Object(external_CoreHome_["translate"])('GeoIp2_ISPRequiresProviderPlugin');
+ return "
".concat(text, "
");
+ },
+ contentTitle: function contentTitle() {
+ return Object(external_CoreHome_["translate"])(this.geoipDatabaseInstalled ? 'GeoIp2_SetupAutomaticUpdatesOfGeoIP' : 'GeoIp2_GeoIPDatabases');
+ },
+ accuracyNote: function accuracyNote() {
+ return Object(external_CoreHome_["translate"])('UserCountry_GeoIpDbIpAccuracyNote', '
', ' ');
+ },
+ purchasedGeoIpText: function purchasedGeoIpText() {
+ var maxMindLink = 'http://www.maxmind.com/en/geolocation_landing?rId=piwik';
+ return Object(external_CoreHome_["translate"])('GeoIp2_IPurchasedGeoIPDBs', "
"), ' ', '
', ' ');
+ },
+ geoIPUpdaterInstructions: function geoIPUpdaterInstructions() {
+ return Object(external_CoreHome_["translate"])('GeoIp2_GeoIPUpdaterInstructions', '
', ' ', '
', ' ');
+ },
+ geoliteCityLink: function geoliteCityLink() {
+ var translation = Object(external_CoreHome_["translate"])('GeoIp2_GeoLiteCityLink', "
"), this.dbipLiteUrl, ' ');
+ return "".concat(translation, "
");
+ },
+ maxMindLinkExplanation: function maxMindLinkExplanation() {
+ var link = 'https://matomo.org/faq/how-to/' + 'how-do-i-get-the-geolocation-download-url-for-the-free-maxmind-db/';
+ return Object(external_CoreHome_["translate"])('UserCountry_MaxMindLinkExplanation', "
"), ' ');
+ },
+ freeProgressbarLabel: function freeProgressbarLabel() {
+ return Object(external_CoreHome_["translate"])('GeoIp2_DownloadingDb', "
").concat(this.dbipLiteFilename, " ..."));
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.vue
+
+
+
+Geoip2Updatervue_type_script_lang_ts.render = render
+
+/* harmony default export */ var Geoip2Updater = (Geoip2Updatervue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.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 Geoip2Updater_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: Geoip2Updater,
+ scope: {
+ geoIpDatabasesInstalled: {
+ angularJsBind: '<'
+ },
+ showGeoIpUpdateSection: {
+ angularJsBind: '<'
+ },
+ dbipLiteUrl: {
+ angularJsBind: '<'
+ },
+ dbipLiteFilename: {
+ angularJsBind: '<'
+ },
+ geoipLocUrl: {
+ angularJsBind: '<'
+ },
+ isProviderPluginActive: {
+ angularJsBind: '<'
+ },
+ geoipIspUrl: {
+ angularJsBind: '<'
+ },
+ lastTimeUpdaterRun: {
+ angularJsBind: '<'
+ },
+ geoipUpdatePeriod: {
+ angularJsBind: '<'
+ },
+ updatePeriodOptions: {
+ angularJsBind: '<'
+ },
+ geoipDatabaseStartedInstalled: {
+ angularJsBind: '<'
+ },
+ showGeoipUpdateSection: {
+ angularJsBind: '<'
+ },
+ nextRunTime: {
+ angularJsBind: '<'
+ },
+ nextRunTimePretty: {
+ angularJsBind: '<'
+ }
+ },
+ directiveName: 'piwikGeoip2Updater',
+ transclude: true
+}));
+// CONCATENATED MODULE: ./plugins/GeoIp2/vue/src/index.ts
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js
+
+
+
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=GeoIp2.umd.js.map
\ No newline at end of file
diff --git a/app/plugins/GeoIp2/vue/dist/GeoIp2.umd.min.js b/app/plugins/GeoIp2/vue/dist/GeoIp2.umd.min.js
new file mode 100644
index 000000000..b2cbaa923
--- /dev/null
+++ b/app/plugins/GeoIp2/vue/dist/GeoIp2.umd.min.js
@@ -0,0 +1,8 @@
+(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):"function"===typeof define&&define.amd?define(["CoreHome",,"CorePluginsAdmin"],t):"object"===typeof exports?exports["GeoIp2"]=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):e["GeoIp2"]=t(e["CoreHome"],e["Vue"],e["CorePluginsAdmin"])})("undefined"!==typeof self?self:this,(function(e,t,n){return function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},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 o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},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/GeoIp2/vue/dist/",n(n.s="fae3")}({"19dc":function(t,n){t.exports=e},"8bbf":function(e,n){e.exports=t},a5a2:function(e,t){e.exports=n},fae3:function(e,t,n){"use strict";if(n.r(t),n.d(t,"Geoip2Updater",(function(){return W})),"undefined"!==typeof window){var o=window.document.currentScript,r=o&&o.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);r&&(n.p=r[1])}var a=n("19dc"),i=n("8bbf"),l={key:0},d={key:0},c={id:"manage-geoip-dbs"},s={class:"row",id:"geoipdb-screen1"},p={class:"geoipdb-column-1 col s6"},u=Object(i["createElementVNode"])("sup",null,[Object(i["createElementVNode"])("small",null,"*")],-1),b={class:"geoipdb-column-2 col s6"},m=["innerHTML"],g={class:"geoipdb-column-1 col s6"},f=["value"],j={class:"geoipdb-column-2 col s6"},O=["value"],h={class:"row"},w=Object(i["createTextVNode"])("* "),I=["innerHTML"],v={id:"geoipdb-screen2-download"},U={key:1,id:"geoipdb-update-info"},N=["innerHTML"],D=Object(i["createElementVNode"])("br",null,null,-1),G=Object(i["createElementVNode"])("br",null,null,-1),x=["innerHTML"],k=["innerHTML"],y=Object(i["createElementVNode"])("br",null,null,-1),P=Object(i["createElementVNode"])("br",null,null,-1),V={id:"locationProviderUpdatePeriodInlineHelp",class:"inline-help-node",ref:"inlineHelpNode"},E=["innerHTML"],_={key:1},T=Object(i["createElementVNode"])("br",null,null,-1),L=Object(i["createElementVNode"])("br",null,null,-1),B=["innerHTML"],S=["value"],C=Object(i["createElementVNode"])("div",{id:"done-updating-updater"},null,-1),M=Object(i["createElementVNode"])("div",{id:"geoipdb-update-info-error"},null,-1),H=["innerHTML"],F={key:1},R={class:"form-description"};function A(e,t,n,o,r,a){var A=Object(i["resolveComponent"])("Progressbar"),J=Object(i["resolveComponent"])("Field"),q=Object(i["resolveComponent"])("ContentBlock");return Object(i["openBlock"])(),Object(i["createBlock"])(q,{"content-title":e.contentTitle,id:"geoip-db-mangement"},{default:Object(i["withCtx"])((function(){return[e.showGeoipUpdateSection?(Object(i["openBlock"])(),Object(i["createElementBlock"])("div",l,[e.geoipDatabaseInstalled?Object(i["createCommentVNode"])("",!0):(Object(i["openBlock"])(),Object(i["createElementBlock"])("div",d,[Object(i["withDirectives"])(Object(i["createElementVNode"])("div",null,[Object(i["createElementVNode"])("h3",null,Object(i["toDisplayString"])(e.translate("GeoIp2_NotManagingGeoIPDBs")),1),Object(i["createElementVNode"])("div",c,[Object(i["createElementVNode"])("div",s,[Object(i["createElementVNode"])("div",p,[Object(i["createElementVNode"])("p",null,[Object(i["createTextVNode"])(Object(i["toDisplayString"])(e.translate("GeoIp2_IWantToDownloadFreeGeoIP")),1),u])]),Object(i["createElementVNode"])("div",b,[Object(i["createElementVNode"])("p",{innerHTML:e.$sanitize(e.purchasedGeoIpText)},null,8,m)]),Object(i["createElementVNode"])("div",g,[Object(i["createElementVNode"])("input",{type:"button",class:"btn",onClick:t[0]||(t[0]=function(t){return e.startDownloadFreeGeoIp()}),value:"".concat(e.translate("General_GetStarted"),"...")},null,8,f)]),Object(i["createElementVNode"])("div",j,[Object(i["createElementVNode"])("input",{type:"button",class:"btn",id:"start-automatic-update-geoip",onClick:t[1]||(t[1]=function(t){return e.startAutomaticUpdateGeoIp()}),value:"".concat(e.translate("General_GetStarted"),"...")},null,8,O)])]),Object(i["createElementVNode"])("div",h,[Object(i["createElementVNode"])("p",null,[Object(i["createElementVNode"])("sup",null,[w,Object(i["createElementVNode"])("small",{innerHTML:e.$sanitize(e.accuracyNote)},null,8,I)])])])])],512),[[i["vShow"],e.showPiwikNotManagingInfo]]),Object(i["withDirectives"])(Object(i["createElementVNode"])("div",v,[Object(i["createElementVNode"])("div",null,[Object(i["createVNode"])(A,{label:e.freeProgressbarLabel,progress:e.progressFreeDownload},null,8,["label","progress"])])],512),[[i["vShow"],e.showFreeDownload]])])),e.geoipDatabaseInstalled&&!e.downloadErrorMessage?(Object(i["openBlock"])(),Object(i["createElementBlock"])("div",U,[Object(i["createElementVNode"])("p",null,[Object(i["createElementVNode"])("span",{innerHTML:e.$sanitize(e.geoIPUpdaterInstructions)},null,8,N),D,G,e.dbipLiteUrl?(Object(i["openBlock"])(),Object(i["createElementBlock"])("span",{key:0,innerHTML:e.$sanitize(e.geoliteCityLink)},null,8,x)):Object(i["createCommentVNode"])("",!0),Object(i["createElementVNode"])("span",{innerHTML:e.$sanitize(e.maxMindLinkExplanation)},null,8,k),Object(i["withDirectives"])(Object(i["createElementVNode"])("span",null,[y,P,Object(i["createTextVNode"])(Object(i["toDisplayString"])(e.translate("GeoIp2_GeoIPUpdaterIntro"))+": ",1)],512),[[i["vShow"],e.geoipDatabaseInstalled]])]),Object(i["createElementVNode"])("div",null,[Object(i["createVNode"])(J,{uicontrol:"text",name:"geoip-location-db",introduction:e.translate("GeoIp2_LocationDatabase"),title:e.translate("Actions_ColumnDownloadURL"),"inline-help":e.translate("GeoIp2_LocationDatabaseHint"),modelValue:e.locationDbUrl,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.locationDbUrl=t})},null,8,["introduction","title","inline-help","modelValue"])]),Object(i["createElementVNode"])("div",null,[Object(i["createVNode"])(J,{uicontrol:"text",name:"geoip-isp-db",introduction:e.translate("GeoIp2_ISPDatabase"),title:e.translate("Actions_ColumnDownloadURL"),"inline-help":e.providerPluginHelp,modelValue:e.ispDbUrl,"onUpdate:modelValue":t[3]||(t[3]=function(t){return e.ispDbUrl=t}),disabled:!e.isProviderPluginActive},null,8,["introduction","title","inline-help","modelValue","disabled"])]),Object(i["createElementVNode"])("div",null,[Object(i["createVNode"])(J,{uicontrol:"radio",name:"geoip-update-period",introduction:e.translate("GeoIp2_DownloadNewDatabasesEvery"),modelValue:e.updatePeriod,"onUpdate:modelValue":t[4]||(t[4]=function(t){return e.updatePeriod=t}),options:e.updatePeriodOptions},{"inline-help":Object(i["withCtx"])((function(){return[Object(i["createElementVNode"])("div",V,[e.lastTimeUpdaterRun?(Object(i["openBlock"])(),Object(i["createElementBlock"])("span",{key:0,innerHTML:e.$sanitize(e.translate("GeoIp2_UpdaterWasLastRun",e.lastTimeUpdaterRun))},null,8,E)):(Object(i["openBlock"])(),Object(i["createElementBlock"])("span",_,Object(i["toDisplayString"])(e.translate("GeoIp2_UpdaterHasNotBeenRun")),1)),T,L,Object(i["createElementVNode"])("div",{id:"geoip-updater-next-run-time",innerHTML:e.$sanitize(e.nextRunTimeText)},null,8,B)],512)]})),_:1},8,["introduction","modelValue","options"])]),Object(i["createElementVNode"])("input",{type:"button",class:"btn",onClick:t[5]||(t[5]=function(t){return e.saveGeoIpLinks()}),value:e.buttonUpdateSaveText},null,8,S),Object(i["createElementVNode"])("div",null,[C,M,Object(i["createElementVNode"])("div",null,[Object(i["withDirectives"])(Object(i["createVNode"])(A,{progress:e.progressUpdateDownload,label:e.progressUpdateLabel},null,8,["progress","label"]),[[i["vShow"],e.isUpdatingGeoIpDatabase]])])])])):Object(i["createCommentVNode"])("",!0),e.downloadErrorMessage?(Object(i["openBlock"])(),Object(i["createElementBlock"])("div",{key:2,innerHTML:e.$sanitize(e.downloadErrorMessage)},null,8,H)):Object(i["createCommentVNode"])("",!0)])):(Object(i["openBlock"])(),Object(i["createElementBlock"])("div",F,[Object(i["createElementVNode"])("p",R,Object(i["toDisplayString"])(e.translate("GeoIp2_CannotSetupGeoIPAutoUpdating")),1)]))]})),_:1},8,["content-title"])}var J=n("a5a2"),q=window,$=q.$,z=Object(i["defineComponent"])({props:{geoipDatabaseStartedInstalled:Boolean,showGeoipUpdateSection:{type:Boolean,required:!0},dbipLiteUrl:{type:String,required:!0},dbipLiteFilename:{type:String,required:!0},geoipLocUrl:String,isProviderPluginActive:Boolean,geoipIspUrl:String,lastTimeUpdaterRun:String,geoipUpdatePeriod:String,updatePeriodOptions:{type:Object,required:!0},nextRunTime:Number,nextRunTimePretty:String},components:{Progressbar:a["Progressbar"],Field:J["Field"],ContentBlock:a["ContentBlock"]},data:function(){return{geoipDatabaseInstalled:!!this.geoipDatabaseStartedInstalled,showFreeDownload:!1,showPiwikNotManagingInfo:!0,progressFreeDownload:0,progressUpdateDownload:0,buttonUpdateSaveText:Object(a["translate"])("General_Save"),progressUpdateLabel:"",locationDbUrl:this.geoipLocUrl||"",ispDbUrl:this.geoipIspUrl||"",orgDbUrl:"",updatePeriod:this.geoipUpdatePeriod||"month",isUpdatingGeoIpDatabase:!1,downloadErrorMessage:null,nextRunTimePrettyUpdated:void 0}},methods:{startDownloadFreeGeoIp:function(){var e=this;this.showFreeDownload=!0,this.showPiwikNotManagingInfo=!1,this.progressFreeDownload=0,this.downloadNextChunk("downloadFreeDBIPLiteDB",(function(t){e.progressFreeDownload=t}),!1,{}).then((function(){window.location.reload()})).catch((function(t){e.geoipDatabaseInstalled=!0,e.downloadErrorMessage=t.message}))},startAutomaticUpdateGeoIp:function(){this.buttonUpdateSaveText=Object(a["translate"])("General_Continue"),this.showGeoIpUpdateInfo()},showGeoIpUpdateInfo:function(){this.geoipDatabaseInstalled=!0},saveGeoIpLinks:function(){var e=this;return a["AjaxHelper"].post({period:this.updatePeriod,module:"GeoIp2",action:"updateGeoIPLinks"},{loc_db:this.locationDbUrl,isp_db:this.ispDbUrl,org_db:this.orgDbUrl},{withTokenInUrl:!0}).then((function(t){return e.downloadNextFileIfNeeded(t,null)})).then((function(t){e.progressUpdateLabel="",e.isUpdatingGeoIpDatabase=!1,a["NotificationsStore"].show({message:Object(a["translate"])("General_Done"),placeat:"#done-updating-updater",context:"success",noclear:!0,type:"toast",style:{display:"inline-block"},id:"userCountryGeoIpUpdate"}),e.nextRunTimePrettyUpdated=t.nextRunTime,$(e.$refs.inlineHelpNode).effect("highlight",{color:"#FFFFCB"},2e3)})).catch((function(t){e.isUpdatingGeoIpDatabase=!1,a["NotificationsStore"].show({message:t.message,placeat:"#geoipdb-update-info-error",context:"error",style:{display:"inline-block"},id:"userCountryGeoIpUpdate",type:"transient"})}))},downloadNextFileIfNeeded:function(e,t){var n=this;if(null!==e&&void 0!==e&&e.to_download){var o=t===e.to_download;return this.progressUpdateDownload=0,this.progressUpdateLabel=e.to_download_label,this.isUpdatingGeoIpDatabase=!0,this.downloadNextChunk("downloadMissingGeoIpDb",(function(e){n.progressUpdateDownload=e}),o,{key:e.to_download}).then((function(t){return n.downloadNextFileIfNeeded(t,e.to_download)}))}return Promise.resolve(e)},downloadNextChunk:function(e,t,n,o){var r=this,i=Object.assign({},o);return a["AjaxHelper"].post({module:"GeoIp2",action:e,continue:n?1:0},i,{withTokenInUrl:!0}).catch((function(){throw new Error(Object(a["translate"])("GeoIp2_FatalErrorDuringDownload"))})).then((function(n){if(n.error)throw new Error(n.error);var a=Math.floor(n.current_size/n.expected_file_size*100);return t(Math.min(a,100)),a<100?r.downloadNextChunk(e,t,!0,o):n}))}},computed:{nextRunTimeText:function(){return this.nextRunTimePrettyUpdated?this.nextRunTimePrettyUpdated:this.nextRunTime?1e3*this.nextRunTime
".concat(this.nextRunTimePretty,"")):Object(a["translate"])("GeoIp2_UpdaterIsNotScheduledToRun")},providerPluginHelp:function(){if(!this.isProviderPluginActive){var e=Object(a["translate"])("GeoIp2_ISPRequiresProviderPlugin");return"".concat(e,"
")}},contentTitle:function(){return Object(a["translate"])(this.geoipDatabaseInstalled?"GeoIp2_SetupAutomaticUpdatesOfGeoIP":"GeoIp2_GeoIPDatabases")},accuracyNote:function(){return Object(a["translate"])("UserCountry_GeoIpDbIpAccuracyNote",''," ")},purchasedGeoIpText:function(){var e="http://www.maxmind.com/en/geolocation_landing?rId=piwik";return Object(a["translate"])("GeoIp2_IPurchasedGeoIPDBs",'')," ",''," ")},geoIPUpdaterInstructions:function(){return Object(a["translate"])("GeoIp2_GeoIPUpdaterInstructions",''," ",''," ")},geoliteCityLink:function(){var e=Object(a["translate"])("GeoIp2_GeoLiteCityLink",''),this.dbipLiteUrl," ");return"".concat(e," ")},maxMindLinkExplanation:function(){var e="https://matomo.org/faq/how-to/how-do-i-get-the-geolocation-download-url-for-the-free-maxmind-db/";return Object(a["translate"])("UserCountry_MaxMindLinkExplanation",'')," ")},freeProgressbarLabel:function(){return Object(a["translate"])("GeoIp2_DownloadingDb",'').concat(this.dbipLiteFilename," ..."))}}});z.render=A;var W=z;
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */Object(a["createAngularJsAdapter"])({component:W,scope:{geoIpDatabasesInstalled:{angularJsBind:"<"},showGeoIpUpdateSection:{angularJsBind:"<"},dbipLiteUrl:{angularJsBind:"<"},dbipLiteFilename:{angularJsBind:"<"},geoipLocUrl:{angularJsBind:"<"},isProviderPluginActive:{angularJsBind:"<"},geoipIspUrl:{angularJsBind:"<"},lastTimeUpdaterRun:{angularJsBind:"<"},geoipUpdatePeriod:{angularJsBind:"<"},updatePeriodOptions:{angularJsBind:"<"},geoipDatabaseStartedInstalled:{angularJsBind:"<"},showGeoipUpdateSection:{angularJsBind:"<"},nextRunTime:{angularJsBind:"<"},nextRunTimePretty:{angularJsBind:"<"}},directiveName:"piwikGeoip2Updater",transclude:!0})}})}));
+//# sourceMappingURL=GeoIp2.umd.min.js.map
\ No newline at end of file
diff --git a/app/plugins/GeoIp2/vue/dist/umd.metadata.json b/app/plugins/GeoIp2/vue/dist/umd.metadata.json
new file mode 100644
index 000000000..dce4477a3
--- /dev/null
+++ b/app/plugins/GeoIp2/vue/dist/umd.metadata.json
@@ -0,0 +1,6 @@
+{
+ "dependsOn": [
+ "CoreHome",
+ "CorePluginsAdmin"
+ ]
+}
\ No newline at end of file
diff --git a/app/plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.adapter.ts b/app/plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.adapter.ts
new file mode 100644
index 000000000..4ab8d05aa
--- /dev/null
+++ b/app/plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.adapter.ts
@@ -0,0 +1,59 @@
+/*!
+ * 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 'CoreHome';
+import Geoip2Updater from './Geoip2Updater.vue';
+
+export default createAngularJsAdapter({
+ component: Geoip2Updater,
+ scope: {
+ geoIpDatabasesInstalled: {
+ angularJsBind: '<',
+ },
+ showGeoIpUpdateSection: {
+ angularJsBind: '<',
+ },
+ dbipLiteUrl: {
+ angularJsBind: '<',
+ },
+ dbipLiteFilename: {
+ angularJsBind: '<',
+ },
+ geoipLocUrl: {
+ angularJsBind: '<',
+ },
+ isProviderPluginActive: {
+ angularJsBind: '<',
+ },
+ geoipIspUrl: {
+ angularJsBind: '<',
+ },
+ lastTimeUpdaterRun: {
+ angularJsBind: '<',
+ },
+ geoipUpdatePeriod: {
+ angularJsBind: '<',
+ },
+ updatePeriodOptions: {
+ angularJsBind: '<',
+ },
+ geoipDatabaseStartedInstalled: {
+ angularJsBind: '<',
+ },
+ showGeoipUpdateSection: {
+ angularJsBind: '<',
+ },
+ nextRunTime: {
+ angularJsBind: '<',
+ },
+ nextRunTimePretty: {
+ angularJsBind: '<',
+ },
+ },
+ directiveName: 'piwikGeoip2Updater',
+ transclude: true,
+});
diff --git a/app/plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.vue b/app/plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.vue
new file mode 100644
index 000000000..ceca56f52
--- /dev/null
+++ b/app/plugins/GeoIp2/vue/src/Geoip2Updater/Geoip2Updater.vue
@@ -0,0 +1,475 @@
+
+
+
+
+
+
+
+
{{ translate('GeoIp2_NotManagingGeoIPDBs') }}
+
+
+
+
{{ translate('GeoIp2_IWantToDownloadFreeGeoIP') }}*
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ translate('GeoIp2_GeoIPUpdaterIntro') }}:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ translate('GeoIp2_UpdaterHasNotBeenRun') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ translate('GeoIp2_CannotSetupGeoIPAutoUpdating') }}
+
+
+
+
+
diff --git a/app/plugins/GeoIp2/vue/src/index.ts b/app/plugins/GeoIp2/vue/src/index.ts
new file mode 100644
index 000000000..f7050104d
--- /dev/null
+++ b/app/plugins/GeoIp2/vue/src/index.ts
@@ -0,0 +1,10 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import './Geoip2Updater/Geoip2Updater.adapter';
+
+export { default as Geoip2Updater } from './Geoip2Updater/Geoip2Updater.vue';
diff --git a/app/plugins/Goals/API.php b/app/plugins/Goals/API.php
index 4938b8885..fe69afa1c 100644
--- a/app/plugins/Goals/API.php
+++ b/app/plugins/Goals/API.php
@@ -67,7 +67,7 @@ class API extends \Piwik\Plugin\API
public function getGoal($idSite, $idGoal)
{
Piwik::checkUserHasViewAccess($idSite);
-
+
$goal = $this->getModel()->getActiveGoal($idSite, $idGoal);
if (!empty($goal)) {
@@ -496,7 +496,7 @@ public function get($idSite, $period, $date, $segment = false, $idGoal = false,
'idGoal' => $idGoal,
'columns' => $columns,
'showAllGoalSpecificMetrics' => $showAllGoalSpecificMetrics,
- 'format_metrics' => Common::getRequestVar('format_metrics', 'bc'),
+ 'format_metrics' => !empty($compare) ? 0 : Common::getRequestVar('format_metrics', 'bc'),
), $default = []);
Archiver::$ARCHIVE_DEPENDENT = true;
$tableSegmented->filter('Piwik\Plugins\Goals\DataTable\Filter\AppendNameToColumnNames',
diff --git a/app/plugins/Goals/Archiver.php b/app/plugins/Goals/Archiver.php
index 195e63bb6..de991c310 100644
--- a/app/plugins/Goals/Archiver.php
+++ b/app/plugins/Goals/Archiver.php
@@ -17,8 +17,7 @@
use Piwik\DataTable;
use Piwik\Metrics;
use Piwik\Plugin\Manager;
-use Piwik\Segment;
-use Piwik\Segment\SegmentExpression;
+use Piwik\Site;
use Piwik\Tracker\GoalManager;
use Piwik\Plugins\VisitFrequency\API as VisitFrequencyAPI;
@@ -128,6 +127,22 @@ public function aggregateDayReport()
}
}
+ private function hasAnyGoalOrEcommerce($idSite)
+ {
+ return $this->usesEcommerce($idSite) || !empty(GoalManager::getGoalIds($idSite));
+ }
+
+ private function usesEcommerce($idSite)
+ {
+ return Manager::getInstance()->isPluginActivated('Ecommerce')
+ && Site::isEcommerceEnabledFor($idSite);
+ }
+
+ private function getSiteId()
+ {
+ return $this->getProcessor()->getParams()->getSite()->getId();
+ }
+
protected function aggregateGeneralGoalMetrics()
{
$prefixes = array(
@@ -135,52 +150,72 @@ protected function aggregateGeneralGoalMetrics()
self::DAYS_UNTIL_CONV_RECORD_NAME => 'vdsf',
);
- $selects = array();
- $selects = array_merge($selects, LogAggregator::getSelectsFromRangedColumn(
- self::VISITS_COUNT_FIELD, self::$visitCountRanges, self::LOG_CONVERSION_TABLE, $prefixes[self::VISITS_UNTIL_RECORD_NAME]
- ));
- $selects = array_merge($selects, LogAggregator::getSelectsFromRangedColumn(
- 'FLOOR(log_conversion.' . self::SECONDS_SINCE_FIRST_VISIT_FIELD . ' / 86400)', self::$daysToConvRanges, self::LOG_CONVERSION_TABLE, $prefixes[self::DAYS_UNTIL_CONV_RECORD_NAME]
- ));
-
- $query = $this->getLogAggregator()->queryConversionsByDimension(array(), false, $selects);
- if ($query === false) {
- return;
- }
-
$totalConversions = $totalRevenue = 0;
$goals = new DataArray();
- $visitsToConversions = $daysToConversions = array();
+ $visitsToConversions = $daysToConversions = [];
- $conversionMetrics = $this->getLogAggregator()->getConversionsMetricFields();
- while ($row = $query->fetch()) {
- $idGoal = $row['idgoal'];
- unset($row['idgoal']);
- unset($row['label']);
+ $siteHasEcommerceOrGoals = $this->hasAnyGoalOrEcommerce($this->getSiteId());
- $values = array();
- foreach ($conversionMetrics as $field => $statement) {
- $values[$field] = $row[$field];
- }
- $goals->sumMetrics($idGoal, $values);
+ // Special handling for sites that contain subordinated sites, like in roll up reporting.
+ // A roll up site, might not have ecommerce enabled or any configured goals,
+ // but if a subordinated site has, we calculate the overview conversion metrics nevertheless
+ if ($siteHasEcommerceOrGoals === false) {
+ $idSitesToArchive = $this->getProcessor()->getParams()->getIdSites();
- if (empty($visitsToConversions[$idGoal])) {
- $visitsToConversions[$idGoal] = new DataTable();
+ foreach ($idSitesToArchive as $idSite) {
+ if ($this->hasAnyGoalOrEcommerce($idSite)) {
+ $siteHasEcommerceOrGoals = true;
+ break;
+ }
}
- $array = LogAggregator::makeArrayOneColumn($row, Metrics::INDEX_NB_CONVERSIONS, $prefixes[self::VISITS_UNTIL_RECORD_NAME]);
- $visitsToConversions[$idGoal]->addDataTable(DataTable::makeFromIndexedArray($array));
+ }
- if (empty($daysToConversions[$idGoal])) {
- $daysToConversions[$idGoal] = new DataTable();
+ // try to query goal data only, if goals or ecommerce is actually used
+ // otherwise we simply insert empty records
+ if ($siteHasEcommerceOrGoals) {
+ $selects = [];
+ $selects = array_merge($selects, LogAggregator::getSelectsFromRangedColumn(
+ self::VISITS_COUNT_FIELD, self::$visitCountRanges, self::LOG_CONVERSION_TABLE, $prefixes[self::VISITS_UNTIL_RECORD_NAME]
+ ));
+ $selects = array_merge($selects, LogAggregator::getSelectsFromRangedColumn(
+ 'FLOOR(log_conversion.' . self::SECONDS_SINCE_FIRST_VISIT_FIELD . ' / 86400)', self::$daysToConvRanges, self::LOG_CONVERSION_TABLE, $prefixes[self::DAYS_UNTIL_CONV_RECORD_NAME]
+ ));
+
+ $query = $this->getLogAggregator()->queryConversionsByDimension([], false, $selects);
+ if ($query === false) {
+ return;
}
- $array = LogAggregator::makeArrayOneColumn($row, Metrics::INDEX_NB_CONVERSIONS, $prefixes[self::DAYS_UNTIL_CONV_RECORD_NAME]);
- $daysToConversions[$idGoal]->addDataTable(DataTable::makeFromIndexedArray($array));
-
- // We don't want to sum Abandoned cart metrics in the overall revenue/conversions/converted visits
- // since it is a "negative conversion"
- if ($idGoal != GoalManager::IDGOAL_CART) {
- $totalConversions += $row[Metrics::INDEX_GOAL_NB_CONVERSIONS];
- $totalRevenue += $row[Metrics::INDEX_GOAL_REVENUE];
+
+ $conversionMetrics = $this->getLogAggregator()->getConversionsMetricFields();
+ while ($row = $query->fetch()) {
+ $idGoal = $row['idgoal'];
+ unset($row['idgoal']);
+ unset($row['label']);
+
+ $values = [];
+ foreach ($conversionMetrics as $field => $statement) {
+ $values[$field] = $row[$field];
+ }
+ $goals->sumMetrics($idGoal, $values);
+
+ if (empty($visitsToConversions[$idGoal])) {
+ $visitsToConversions[$idGoal] = new DataTable();
+ }
+ $array = LogAggregator::makeArrayOneColumn($row, Metrics::INDEX_NB_CONVERSIONS, $prefixes[self::VISITS_UNTIL_RECORD_NAME]);
+ $visitsToConversions[$idGoal]->addDataTable(DataTable::makeFromIndexedArray($array));
+
+ if (empty($daysToConversions[$idGoal])) {
+ $daysToConversions[$idGoal] = new DataTable();
+ }
+ $array = LogAggregator::makeArrayOneColumn($row, Metrics::INDEX_NB_CONVERSIONS, $prefixes[self::DAYS_UNTIL_CONV_RECORD_NAME]);
+ $daysToConversions[$idGoal]->addDataTable(DataTable::makeFromIndexedArray($array));
+
+ // We don't want to sum Abandoned cart metrics in the overall revenue/conversions/converted visits
+ // since it is a "negative conversion"
+ if ($idGoal != GoalManager::IDGOAL_CART) {
+ $totalConversions += $row[Metrics::INDEX_GOAL_NB_CONVERSIONS];
+ $totalRevenue += $row[Metrics::INDEX_GOAL_REVENUE];
+ }
}
}
@@ -258,15 +293,20 @@ protected function isStandardGoal($idGoal)
protected function aggregateEcommerceItems()
{
$this->initItemReports();
- foreach ($this->getItemsDimensions() as $dimension) {
- $query = $this->getLogAggregator()->queryEcommerceItems($dimension);
- if ($query !== false) {
- $this->aggregateFromEcommerceItems($query, $dimension);
- }
- $query = $this->queryItemViewsForDimension($dimension);
- if ($query !== false) {
- $this->aggregateFromEcommerceViews($query, $dimension);
+ // try to query ecommerce items only, if ecommerce is actually used
+ // otherwise we simply insert empty records
+ if ($this->usesEcommerce($this->getSiteId())) {
+ foreach ($this->getItemsDimensions() as $dimension) {
+ $query = $this->getLogAggregator()->queryEcommerceItems($dimension);
+ if ($query !== false) {
+ $this->aggregateFromEcommerceItems($query, $dimension);
+ }
+
+ $query = $this->queryItemViewsForDimension($dimension);
+ if ($query !== false) {
+ $this->aggregateFromEcommerceViews($query, $dimension);
+ }
}
}
$this->insertItemReports();
@@ -373,7 +413,10 @@ protected function aggregateFromEcommerceViews($query, $dimension)
}
unset($row['label']);
- $row['avg_price_viewed'] = round($row['avg_price_viewed'], GoalManager::REVENUE_PRECISION);
+
+ if (isset($row['avg_price_viewed'])) {
+ $row['avg_price_viewed'] = round($row['avg_price_viewed'], GoalManager::REVENUE_PRECISION);
+ }
// add views to all types
foreach ($array as $ecommerceType => $dataArray) {
@@ -447,19 +490,21 @@ public function aggregateMultipleReports()
/*
* Archive Ecommerce Items
*/
- $dataTableToSum = $this->dimensionRecord;
- foreach ($this->dimensionRecord as $recordName) {
- $dataTableToSum[] = self::getItemRecordNameAbandonedCart($recordName);
- }
- $columnsAggregationOperation = null;
+ if (Manager::getInstance()->isPluginActivated('Ecommerce')) {
+ $dataTableToSum = $this->dimensionRecord;
+ foreach ($this->dimensionRecord as $recordName) {
+ $dataTableToSum[] = self::getItemRecordNameAbandonedCart($recordName);
+ }
+ $columnsAggregationOperation = null;
- $this->getProcessor()->aggregateDataTableRecords($dataTableToSum,
- $maximumRowsInDataTableLevelZero = $this->productReportsMaximumRows,
- $maximumRowsInSubDataTable = $this->productReportsMaximumRows,
- $columnToSortByBeforeTruncation = Metrics::INDEX_ECOMMERCE_ITEM_REVENUE,
- $columnsAggregationOperation,
- $columnsToRenameAfterAggregation = null,
- $countRowsRecursive = array());
+ $this->getProcessor()->aggregateDataTableRecords($dataTableToSum,
+ $maximumRowsInDataTableLevelZero = $this->productReportsMaximumRows,
+ $maximumRowsInSubDataTable = $this->productReportsMaximumRows,
+ $columnToSortByBeforeTruncation = Metrics::INDEX_ECOMMERCE_ITEM_REVENUE,
+ $columnsAggregationOperation,
+ $columnsToRenameAfterAggregation = null,
+ $countRowsRecursive = []);
+ }
/*
* Archive General Goal metrics
@@ -467,8 +512,10 @@ public function aggregateMultipleReports()
$goalIdsToSum = GoalManager::getGoalIds($this->getProcessor()->getParams()->getSite()->getId());
//Ecommerce
- $goalIdsToSum[] = GoalManager::IDGOAL_ORDER;
- $goalIdsToSum[] = GoalManager::IDGOAL_CART; //bug here if idgoal=1
+ if (Manager::getInstance()->isPluginActivated('Ecommerce')) {
+ $goalIdsToSum = array_merge($goalIdsToSum, $this->getEcommerceIdGoals());
+ }
+
// Overall goal metrics
$goalIdsToSum[] = false;
diff --git a/app/plugins/Goals/Categories/GoalsOverviewSubcategory.php b/app/plugins/Goals/Categories/GoalsOverviewSubcategory.php
index e36954f6a..0fb670ed3 100644
--- a/app/plugins/Goals/Categories/GoalsOverviewSubcategory.php
+++ b/app/plugins/Goals/Categories/GoalsOverviewSubcategory.php
@@ -20,6 +20,7 @@ class GoalsOverviewSubcategory extends Subcategory
public function getHelp()
{
return '' . Piwik::translate('Goals_GoalsOverviewSubcategoryHelp1') . '
'
- . '' . Piwik::translate('Goals_GoalsOverviewSubcategoryHelp2') . '
';
+ . '' . Piwik::translate('Goals_GoalsOverviewSubcategoryHelp2') . '
'
+ . '' . Piwik::translate('Goals_ManageGoalsSubcategoryHelp2') . '
';
}
}
diff --git a/app/plugins/Goals/Categories/ManageGoalsSubcategory.php b/app/plugins/Goals/Categories/ManageGoalsSubcategory.php
index 8ff2deb9e..7741642ab 100644
--- a/app/plugins/Goals/Categories/ManageGoalsSubcategory.php
+++ b/app/plugins/Goals/Categories/ManageGoalsSubcategory.php
@@ -20,6 +20,6 @@ class ManageGoalsSubcategory extends Subcategory
public function getHelp()
{
return '' . Piwik::translate('Goals_ManageGoalsSubcategoryHelp1') . '
'
- . '' . Piwik::translate('Goals_ManageGoalsSubcategoryHelp2') . '
';
+ . '' . Piwik::translate('Goals_ManageGoalsSubcategoryHelp2') . '
';
}
}
diff --git a/app/plugins/Goals/Columns/DaysToConversion.php b/app/plugins/Goals/Columns/DaysToConversion.php
index 9be44fcd1..64f2228aa 100644
--- a/app/plugins/Goals/Columns/DaysToConversion.php
+++ b/app/plugins/Goals/Columns/DaysToConversion.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\Goals\Columns;
use Piwik\Columns\Dimension;
-use Piwik\Piwik;
class DaysToConversion extends Dimension
{
diff --git a/app/plugins/Goals/Columns/VisitsUntilConversion.php b/app/plugins/Goals/Columns/VisitsUntilConversion.php
index e1c883c30..2fbdbd911 100644
--- a/app/plugins/Goals/Columns/VisitsUntilConversion.php
+++ b/app/plugins/Goals/Columns/VisitsUntilConversion.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\Goals\Columns;
use Piwik\Columns\Dimension;
-use Piwik\Piwik;
class VisitsUntilConversion extends Dimension
{
diff --git a/app/plugins/Goals/Controller.php b/app/plugins/Goals/Controller.php
index 02f8ee5c9..247a579cd 100644
--- a/app/plugins/Goals/Controller.php
+++ b/app/plugins/Goals/Controller.php
@@ -16,10 +16,12 @@
use Piwik\FrontController;
use Piwik\Piwik;
use Piwik\Plugin\Manager;
+use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
use Piwik\Plugins\Live\Live;
use Piwik\Plugins\Referrers\API as APIReferrers;
use Piwik\Translation\Translator;
use Piwik\View;
+use Piwik\ViewDataTable\Factory as ViewDataTableFactory;
/**
*
@@ -76,6 +78,7 @@ public function manage()
$this->setGeneralVariablesView($view);
$this->setEditGoalsViewVariables($view);
$this->setGoalOptions($view);
+ $this->execAndSetResultsForTwigEvents($view);
return $view->render();
}
@@ -121,6 +124,8 @@ public function addNewGoal()
$this->setGeneralVariablesView($view);
$this->setGoalOptions($view);
$view->onlyShowAddNewGoal = true;
+ $view->ecommerceEnabled = $this->site->isEcommerceEnabled();
+ $this->execAndSetResultsForTwigEvents($view);
return $view->render();
}
@@ -130,9 +135,39 @@ public function editGoals()
$this->setGeneralVariablesView($view);
$this->setEditGoalsViewVariables($view);
$this->setGoalOptions($view);
+ $this->execAndSetResultsForTwigEvents($view);
return $view->render();
}
+ private function execAndSetResultsForTwigEvents(View $view)
+ {
+ if (empty($view->onlyShowAddGoal)) {
+ $beforeGoalListActionsBody = [];
+
+ if ($view->goals) {
+ foreach ($view->goals as $goal) {
+ $str = '';
+ Piwik::postEvent('Template.beforeGoalListActionsBody', [&$str, $goal]);
+
+ $beforeGoalListActionsBody[$goal['idgoal']] = $str;
+ }
+ }
+
+ $view->beforeGoalListActionsBodyEventResult = $beforeGoalListActionsBody;
+
+ $str = '';
+ Piwik::postEvent('Template.beforeGoalListActionsHead', [&$str]);
+ $view->beforeGoalListActionsHead = $str;
+ }
+
+ if (!empty($view->userCanEditGoals)) {
+ $str = '';
+ Piwik::postEvent('Template.endGoalEditTable', [&$str]);
+
+ $view->endEditTable = $str;
+ }
+ }
+
public function hasConversions()
{
$this->checkSitePermission();
@@ -219,6 +254,29 @@ public function getEvolutionGraph(array $columns = array(), $idGoal = false, arr
return $this->renderView($view);
}
+ public function getSparklines()
+ {
+ $content = "";
+ $goals = Request::processRequest('Goals.getGoals', ['idSite' => $this->idSite, 'filter_limit' => '-1'], []);
+
+ foreach ($goals as $goal) {
+ $params = [
+ 'idGoal' => $goal['idgoal'],
+ 'allow_multiple' => (int) $goal['allow_multiple'],
+ 'only_summary' => 1,
+ ];
+
+ \Piwik\Context::executeWithQueryParameters($params, function() use (&$content) {
+ //load Visualisations Sparkline
+ $view = ViewDataTableFactory::build(Sparklines::ID, 'Goals.getMetrics', 'Goals.' . __METHOD__, true);
+ $view->config->show_title = true;
+ $content .= $view->render();
+ });
+ }
+
+ return $content;
+ }
+
private function getColumnTranslation($nameToLabel, $columnName, $idGoal)
{
$columnTranslation = '';
@@ -349,6 +407,7 @@ private function setEditGoalsViewVariables($view)
if (isset($goal['pattern'])) {
$goal['pattern'] = Common::unsanitizeInputValue($goal['pattern']);
}
+ $goal['revenue_pretty'] = \Piwik\piwik_format_money($goal['revenue'], $this->idSite);
}
$view->goals = $goals;
diff --git a/app/plugins/Goals/Conversions.php b/app/plugins/Goals/Conversions.php
index 27c8352b1..a95417486 100644
--- a/app/plugins/Goals/Conversions.php
+++ b/app/plugins/Goals/Conversions.php
@@ -9,9 +9,6 @@
namespace Piwik\Plugins\Goals;
use Piwik\API\Request;
-use Piwik\Cache;
-use Piwik\Common;
-use Piwik\Db;
class Conversions
{
diff --git a/app/plugins/Goals/DataTable/Filter/AppendNameToColumnNames.php b/app/plugins/Goals/DataTable/Filter/AppendNameToColumnNames.php
index ae2c1669c..83b931742 100644
--- a/app/plugins/Goals/DataTable/Filter/AppendNameToColumnNames.php
+++ b/app/plugins/Goals/DataTable/Filter/AppendNameToColumnNames.php
@@ -10,7 +10,6 @@
use Piwik\DataTable\BaseFilter;
use Piwik\DataTable;
-use Piwik\Metrics;
/**
* Appends a string to each column name in each row of a table. Please note this filter even appends the name to a
diff --git a/app/plugins/Goals/Goals.php b/app/plugins/Goals/Goals.php
index 413eccc6a..3590f4fa4 100644
--- a/app/plugins/Goals/Goals.php
+++ b/app/plugins/Goals/Goals.php
@@ -94,7 +94,6 @@ public static function getGoalColumns($idGoal)
public function registerEvents()
{
$hooks = array(
- 'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'Tracker.Cache.getSiteAttributes' => 'fetchGoalsFromDb',
'API.getReportMetadata.end' => 'getReportMetadataEnd',
@@ -340,13 +339,6 @@ private static function getAllReportsWithGoalMetrics()
return $reportsWithGoals;
}
- public function getJsFiles(&$jsFiles)
- {
- $jsFiles[] = "plugins/Goals/angularjs/common/directives/goal-page-link.js";
- $jsFiles[] = "plugins/Goals/angularjs/manage-goals/manage-goals.controller.js";
- $jsFiles[] = "plugins/Goals/angularjs/manage-goals/manage-goals.directive.js";
- }
-
public function getStylesheetFiles(&$stylesheets)
{
$stylesheets[] = "plugins/Goals/stylesheets/goals.css";
@@ -364,12 +356,60 @@ public function getClientSideTranslationKeys(&$translationKeys)
$translationKeys[] = 'Goals_AddNewGoal';
$translationKeys[] = 'Goals_UpdateGoal';
$translationKeys[] = 'Goals_DeleteGoalConfirm';
- $translationKeys[] = 'Goals_UpdateGoal';
- $translationKeys[] = 'Goals_DeleteGoalConfirm';
$translationKeys[] = 'Goals_Ecommerce';
$translationKeys[] = 'Goals_Optional';
$translationKeys[] = 'Goals_TimeInMinutes';
$translationKeys[] = 'Goals_Pattern';
$translationKeys[] = 'Goals_ClickToViewThisGoal';
+ $translationKeys[] = 'Goals_ManageGoals';
+ $translationKeys[] = 'Goals_GoalName';
+ $translationKeys[] = 'Goals_GoalIsTriggeredWhen';
+ $translationKeys[] = 'Goals_ThereIsNoGoalToManage';
+ $translationKeys[] = 'Goals_ManuallyTriggeredUsingJavascriptFunction';
+ $translationKeys[] = 'Goals_VisitUrl';
+ $translationKeys[] = 'Goals_ClickOutlink';
+ $translationKeys[] = 'Goals_SendEvent';
+ $translationKeys[] = 'Goals_GoalIsTriggered';
+ $translationKeys[] = 'Goals_WhereThe';
+ $translationKeys[] = 'Goals_URL';
+ $translationKeys[] = 'Goals_Contains';
+ $translationKeys[] = 'Goals_IsExactly';
+ $translationKeys[] = 'Goals_MatchesExpression';
+ $translationKeys[] = 'Goals_AllowMultipleConversionsPerVisit';
+ $translationKeys[] = 'Goals_HelpOneConversionPerVisit';
+ $translationKeys[] = 'Goals_DefaultRevenueHelp';
+ $translationKeys[] = 'Goals_DefaultRevenueLabel';
+ $translationKeys[] = 'Goals_GoalRevenue';
+ $translationKeys[] = 'Goals_Filename';
+ $translationKeys[] = 'Goals_ExternalWebsiteUrl';
+ $translationKeys[] = 'Goals_VisitDuration';
+ $translationKeys[] = 'Goals_AtLeastMinutes';
+ $translationKeys[] = 'Goals_VisitPageTitle';
+ $translationKeys[] = 'Intl_NMinutes';
+ $translationKeys[] = 'Goals_PageTitle';
+ $translationKeys[] = 'Goals_UseEventValueAsRevenue';
+ $translationKeys[] = 'Goals_EventValueAsRevenueHelp';
+ $translationKeys[] = 'Goals_EventValueAsRevenueHelp2';
+ $translationKeys[] = 'Events_EventCategory';
+ $translationKeys[] = 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore';
+ $translationKeys[] = 'Goals_LearnMoreAboutGoalTrackingDocumentation';
+ $translationKeys[] = 'Goals_EcommerceReports';
+ $translationKeys[] = 'SitesManager_WebsitesManagement';
+ $translationKeys[] = 'Goals_CaseSensitive';
+ $translationKeys[] = 'Goals_Download';
+ $translationKeys[] = 'Events_EventAction';
+ $translationKeys[] = 'Events_EventCategory';
+ $translationKeys[] = 'Events_EventName';
+ $translationKeys[] = 'Goals_YouCanEnableEcommerceReports';
+ $translationKeys[] = 'General_ForExampleShort';
+ $translationKeys[] = 'General_Id';
+ $translationKeys[] = 'General_Description';
+ $translationKeys[] = 'General_ColumnRevenue';
+ $translationKeys[] = 'General_Edit';
+ $translationKeys[] = 'General_Delete';
+ $translationKeys[] = 'General_OperationGreaterThan';
+ $translationKeys[] = 'General_Yes';
+ $translationKeys[] = 'General_No';
+ $translationKeys[] = 'General_OrCancel';
}
}
diff --git a/app/plugins/Goals/Pages.php b/app/plugins/Goals/Pages.php
index 6b105bfb9..59ebb7b19 100644
--- a/app/plugins/Goals/Pages.php
+++ b/app/plugins/Goals/Pages.php
@@ -54,23 +54,18 @@ public function createGoalsOverviewPage($goals)
$config->setSubcategoryId($subcategory);
$config->setName('');
$config->setOrder(15);
+ $config->setModule('Goals');
+ $config->setAction('getMetrics');
$config->setIsNotWidgetizable();
$widgets[] = $config;
- foreach ($goals as $goal) {
- $name = Common::sanitizeInputValue($goal['name']);
- $goalTranslated = Piwik::translate('Goals_GoalX', array($name));
-
- $config = $this->factory->createWidget();
- $config->setName($goalTranslated);
- $config->setSubcategoryId($subcategory);
- $config->forceViewDataTable(Sparklines::ID);
- $config->setParameters(array('idGoal' => $goal['idgoal']));
- $config->setOrder(25);
- $config->setIsNotWidgetizable();
- $config->addParameters(array('allow_multiple' => (int) $goal['allow_multiple'], 'only_summary' => '1'));
- $widgets[] = $config;
- }
+ // load sparkline
+ $config = $this->factory->createCustomWidget('getSparklines');
+ $config->setSubcategoryId($subcategory);
+ $config->setName('');
+ $config->setOrder(25);
+ $config->setIsNotWidgetizable();
+ $widgets[] = $config;
$container = $this->createWidgetizableWidgetContainer('GoalsOverview', $subcategory, $widgets);
diff --git a/app/plugins/Goals/Reports/Base.php b/app/plugins/Goals/Reports/Base.php
index 969b4f64c..24e6ecc72 100644
--- a/app/plugins/Goals/Reports/Base.php
+++ b/app/plugins/Goals/Reports/Base.php
@@ -11,8 +11,6 @@
use Piwik\API\Request;
use Piwik\Common;
use Piwik\Piwik;
-use Piwik\Plugins\Goals\API;
-use Piwik\Plugins\Goals\Goals;
abstract class Base extends \Piwik\Plugin\Report
{
diff --git a/app/plugins/Goals/Reports/Get.php b/app/plugins/Goals/Reports/Get.php
index c29bdf442..5d0f3b141 100644
--- a/app/plugins/Goals/Reports/Get.php
+++ b/app/plugins/Goals/Reports/Get.php
@@ -11,14 +11,12 @@
use Piwik\API\Request;
use Piwik\Common;
use Piwik\DataTable;
-use Piwik\Metrics\Formatter;
use Piwik\NumberFormatter;
use Piwik\Piwik;
use Piwik\Plugin;
use Piwik\Plugin\ViewDataTable;
use Piwik\Plugins\CoreVisualizations\Visualizations\JqplotGraph\Evolution;
use Piwik\Plugins\CoreVisualizations\Visualizations\Sparklines;
-use Piwik\Plugins\Goals\API;
use Piwik\Plugins\Goals\Goals;
use Piwik\Plugins\Goals\Pages;
use Piwik\Report\ReportWidgetFactory;
@@ -66,7 +64,7 @@ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $
if (empty($idSite)) {
return;
}
-
+
$goals = $this->getGoals();
$reports = Goals::getReportsWithGoalMetrics();
@@ -113,7 +111,7 @@ public function configureView(ViewDataTable $view)
if ($onlySummary && !empty($idGoal)) {
if (is_numeric($idGoal)) {
- $view->config->title_attributes = array('piwik-goal-page-link' => $idGoal);
+ $view->config->title_attributes = array('goal-page-link' => $idGoal);
}
// in Goals overview summary we show proper title for a goal
@@ -193,7 +191,7 @@ public function configureView(ViewDataTable $view)
} else {
$view->config->title = Piwik::translate('General_EvolutionOverPeriod');
}
-
+
if (empty($view->config->columns_to_display)) {
$view->config->columns_to_display = array('nb_conversions');
}
diff --git a/app/plugins/Goals/Reports/GetMetrics.php b/app/plugins/Goals/Reports/GetMetrics.php
index 32cb01980..bf2d1c3ac 100644
--- a/app/plugins/Goals/Reports/GetMetrics.php
+++ b/app/plugins/Goals/Reports/GetMetrics.php
@@ -10,8 +10,10 @@
use Piwik\Piwik;
use Piwik\Plugins\CoreHome\Columns\Metrics\ConversionRate;
+use Piwik\Report\ReportWidgetFactory;
+use Piwik\Widget\WidgetsList;
-class GetMetrics extends Base
+class GetMetrics extends Get
{
protected function init()
{
@@ -26,6 +28,10 @@ protected function init()
$this->parameters = null;
}
+ public function configureWidgets(WidgetsList $widgetsList, ReportWidgetFactory $factory)
+ {
+ }
+
public function configureReportMetadata(&$availableReports, $infos)
{
}
diff --git a/app/plugins/Goals/Updates/3.0.0-b1.php b/app/plugins/Goals/Updates/3.0.0-b1.php
index 42c7d32ad..55d2fbb62 100644
--- a/app/plugins/Goals/Updates/3.0.0-b1.php
+++ b/app/plugins/Goals/Updates/3.0.0-b1.php
@@ -9,7 +9,6 @@
namespace Piwik\Plugins\Goals;
-use Piwik\Common;
use Piwik\Updater;
use Piwik\Updates;
use Piwik\Updater\Migration\Factory as MigrationFactory;
diff --git a/app/plugins/Goals/Visualizations/Goals.php b/app/plugins/Goals/Visualizations/Goals.php
index 0463bde48..02bc042f5 100644
--- a/app/plugins/Goals/Visualizations/Goals.php
+++ b/app/plugins/Goals/Visualizations/Goals.php
@@ -8,16 +8,12 @@
namespace Piwik\Plugins\Goals\Visualizations;
-use Piwik\API\DataTablePostProcessor;
use Piwik\API\Request;
use Piwik\Common;
-use Piwik\DataTable;
use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal;
use Piwik\Piwik;
use Piwik\Plugins\CoreVisualizations\Visualizations\HtmlTable;
-use Piwik\Plugins\Goals\API as APIGoals;
use Piwik\Site;
-use Piwik\View;
require_once PIWIK_INCLUDE_PATH . '/core/Twig.php';
diff --git a/app/plugins/Goals/Widgets/AddNewGoal.php b/app/plugins/Goals/Widgets/AddNewGoal.php
index 65245b63d..d84cce124 100644
--- a/app/plugins/Goals/Widgets/AddNewGoal.php
+++ b/app/plugins/Goals/Widgets/AddNewGoal.php
@@ -10,8 +10,6 @@
use Piwik\API\Request;
use Piwik\Common;
-use Piwik\Piwik;
-use Piwik\Plugins\Goals\API;
use Piwik\Widget\WidgetConfig;
class AddNewGoal extends \Piwik\Widget\Widget
diff --git a/app/plugins/Goals/Widgets/EditGoals.php b/app/plugins/Goals/Widgets/EditGoals.php
index a3f892cd1..10fcc5dbd 100644
--- a/app/plugins/Goals/Widgets/EditGoals.php
+++ b/app/plugins/Goals/Widgets/EditGoals.php
@@ -10,8 +10,6 @@
use Piwik\API\Request;
use Piwik\Common;
-use Piwik\Piwik;
-use Piwik\Plugins\Goals\API;
use Piwik\Widget\WidgetConfig;
class EditGoals extends \Piwik\Widget\Widget
diff --git a/app/plugins/Goals/lang/ga.json b/app/plugins/Goals/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/Goals/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Goals/templates/_addEditGoal.twig b/app/plugins/Goals/templates/_addEditGoal.twig
index 16be9c242..ab1a57acf 100644
--- a/app/plugins/Goals/templates/_addEditGoal.twig
+++ b/app/plugins/Goals/templates/_addEditGoal.twig
@@ -13,22 +13,32 @@
-
-
- {% if onlyShowAddNewGoal is not defined %}
- {% include "@Goals/_listGoalEdit.twig" %}
- {% endif %}
+
+ {% if addNewGoalIntro is defined %}add-new-goal-intro="{{ addNewGoalIntro|json_encode|e('html_attr') }}"{% endif %}
+ goal-trigger-type-options="{{ goalTriggerTypeOptions|json_encode|e('html_attr') }}"
+ goal-match-attribute-options="{{ goalMatchAttributeOptions|json_encode|e('html_attr') }}"
+ event-type-options="{{ eventTypeOptions|json_encode|e('html_attr') }}"
+ pattern-type-options="{{ patternTypeOptions|json_encode|e('html_attr') }}"
+ numeric-comparison-type-options="{{ numericComparisonTypeOptions|json_encode|e('html_attr') }}"
+ allow-multiple-options="{{ allowMultipleOptions|json_encode|e('html_attr') }}"
+ before-goal-list-actions-body="{{ beforeGoalListActionsBodyEventResult|default(null)|json_encode|e('html_attr') }}"
+ end-edit-table="{{ endEditTable|default(null)|json_encode|e('html_attr') }}"
+ before-goal-list-actions-head="{{ beforeGoalListActionsHead|default(null)|json_encode|e('html_attr') }}"
+>
diff --git a/app/plugins/Goals/templates/_formAddGoal.twig b/app/plugins/Goals/templates/_formAddGoal.twig
deleted file mode 100644
index 174a98ce1..000000000
--- a/app/plugins/Goals/templates/_formAddGoal.twig
+++ /dev/null
@@ -1,183 +0,0 @@
-
-
- {% if addNewGoalIntro is defined and addNewGoalIntro %}
- {{ addNewGoalIntro|raw }}
- {% endif %}
-
-
-
-
-
-
-
-
-
-
-
{{ 'Goals_GoalIsTriggered'|translate|e('html_attr') }}
-
-
-
-
-
-
-
- {{ 'Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore'|translate("
"," ")|raw }}
-
-
-
-
-
-
-
-
-
{{ 'Goals_WhereThe'|translate|e('html_attr') }}
-
- {{ 'Goals_URL'|translate }}
-
-
- {{ 'Goals_PageTitle'|translate }}
-
-
- {{ 'Goals_Filename'|translate }}
-
-
- {{ 'Goals_ExternalWebsiteUrl'|translate }}
-
-
- {{ 'Goals_VisitDuration'|translate }}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_Contains'|translate("'checkout/confirmation'") }}
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_IsExactly'|translate("'http://example.com/thank-you.html'") }}
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_MatchesExpression'|translate("'(.*)\\\/demo\\\/(.*)'") }}
-
-
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_Contains'|translate("'Order confirmation'") }}
-
-
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_Contains'|translate("'files/brochure.pdf'") }}
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_IsExactly'|translate("'http://example.com/files/brochure.pdf'") }}
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_MatchesExpression'|translate("'(.*)\\\.zip'") }}
-
-
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_Contains'|translate("'amazon.com'") }}
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_IsExactly'|translate("'http://mypartner.com/landing.html'") }}
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_MatchesExpression'|translate("'http://www.amazon.com\\\/(.*)\\\/yourAffiliateId'") }}
-
-
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_Contains'|translate("'video'") }}
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_IsExactly'|translate("'click'") }}
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_MatchesExpression'|translate("'(.*)_banner'") }}"
-
-
- {{ 'General_ForExampleShort'|translate }} {{ 'Goals_AtLeastMinutes'|translate('5', '0.5') }}
-
-
-
-
-
-
-
-
-
-
-
{{ 'Goals_GoalRevenue'|translate }} {{ 'Goals_Optional'|translate }}
-
-
-
-
-
-
-
- {{ postEvent("Template.endGoalEditTable") }}
-
-
-
-
- {% if onlyShowAddNewGoal is not defined %}
-
- {{ 'General_OrCancel'|translate("
"," ")|raw }}
-
- {% endif %}
-
-
-
diff --git a/app/plugins/Goals/templates/_listGoalEdit.twig b/app/plugins/Goals/templates/_listGoalEdit.twig
deleted file mode 100644
index 1a3054734..000000000
--- a/app/plugins/Goals/templates/_listGoalEdit.twig
+++ /dev/null
@@ -1,122 +0,0 @@
-
-
-
-
-
- {{ 'Goals_LearnMoreAboutGoalTrackingDocumentation'|translate("
"," ")|raw }}
-
- {% if not ecommerceEnabled %}
-
- {% set websiteManageText %}
-
{{ 'SitesManager_WebsitesManagement'|translate }}
- {% endset %}
- {% set ecommerceReportText %}
-
{{ 'Goals_EcommerceReports'|translate }}
- {% endset %}
- {{ 'Goals_Optional'|translate }} {{ 'Goals_Ecommerce'|translate }}: {{ 'Goals_YouCanEnableEcommerceReports'|translate(ecommerceReportText,websiteManageText)|raw }}
- {% endif %}
-
-
-
-
-
- Id
- {{ 'Goals_GoalName'|translate }}
- {{ 'General_Description'|translate }}
- {{ 'Goals_GoalIsTriggeredWhen'|translate }}
- {{ 'General_ColumnRevenue'|translate }}
- {{ postEvent("Template.beforeGoalListActionsHead") }}
- {% if userCanEditGoals %}
- {{ 'General_Edit'|translate }}
- {{ 'General_Delete'|translate }}
- {% endif %}
-
-
- {% if goals is empty %}
-
-
-
- {{ 'Goals_ThereIsNoGoalToManage'|translate(siteName)|rawSafeDecoded }}.
-
-
-
- {% else %}
- {% for goal in goals %}
-
- {{ goal.idgoal }}
- {{ goal.name }}
- {{ goal.description }}
-
- {{ goal.match_attribute }}
- {% if goal.match_attribute == 'visit_duration' %}
- {{ 'General_OperationGreaterThan'|translate|lcfirst }} {{ 'Intl_NMinutes'|translate(goal.pattern) }}
- {% else %}
- {% if goal.pattern_type is defined %}
-
- {{ 'Goals_Pattern'|translate }} {{ goal.pattern_type }}: {{ goal.pattern }}
- {% endif %}
- {% endif %}
-
-
- {% if goal.revenue==0 %}-{% else %}{{ goal.revenue|money(idSite)|raw }}{% endif %}
-
- {{ postEvent("Template.beforeGoalListActionsBody", goal) }}
- {% if userCanEditGoals %}
-
-
-
-
-
-
-
-
-
-
- {% endif %}
-
- {% endfor %}
- {% endif %}
-
-
- {% if userCanEditGoals and onlyShowAddNewGoal is not defined %}
-
-
-
- {{ 'Goals_AddNewGoal'|translate }}
-
-
- {% endif %}
-
-
-
-
-
-
-
-
-
-
diff --git a/app/plugins/Goals/vue/dist/Goals.umd.js b/app/plugins/Goals/vue/dist/Goals.umd.js
new file mode 100644
index 000000000..591472258
--- /dev/null
+++ b/app/plugins/Goals/vue/dist/Goals.umd.js
@@ -0,0 +1,1148 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("CoreHome"), require("vue"), require("CorePluginsAdmin"));
+ else if(typeof define === 'function' && define.amd)
+ define(["CoreHome", , "CorePluginsAdmin"], factory);
+ else if(typeof exports === 'object')
+ exports["Goals"] = factory(require("CoreHome"), require("vue"), require("CorePluginsAdmin"));
+ else
+ root["Goals"] = factory(root["CoreHome"], root["Vue"], root["CorePluginsAdmin"]);
+})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__, __WEBPACK_EXTERNAL_MODULE_a5a2__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "plugins/Goals/vue/dist/";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "fae3");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "19dc":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;
+
+/***/ }),
+
+/***/ "8bbf":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;
+
+/***/ }),
+
+/***/ "a5a2":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE_a5a2__;
+
+/***/ }),
+
+/***/ "fae3":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, "GoalPageLink", function() { return /* reexport */ GoalPageLink_GoalPageLink; });
+__webpack_require__.d(__webpack_exports__, "ManageGoals", function() { return /* reexport */ ManageGoals; });
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
+// This file is imported into lib/wc client bundles.
+
+if (typeof window !== 'undefined') {
+ var currentScript = window.document.currentScript
+ if (false) { var getCurrentScript; }
+
+ var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
+ if (src) {
+ __webpack_require__.p = src[1] // eslint-disable-line
+ }
+}
+
+// Indicate to webpack that this file can be concatenated
+/* harmony default export */ var setPublicPath = (null);
+
+// EXTERNAL MODULE: external "CoreHome"
+var external_CoreHome_ = __webpack_require__("19dc");
+
+// CONCATENATED MODULE: ./plugins/Goals/vue/src/GoalPageLink/GoalPageLink.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 _window = window,
+ GoalPageLink_$ = _window.$; // usage v-goal-page-link="{ idGoal: 5 }"
+
+var GoalPageLink = {
+ mounted: function mounted(el, binding) {
+ if (!external_CoreHome_["Matomo"].helper.isAngularRenderingThePage()) {
+ return;
+ }
+
+ var title = GoalPageLink_$(el).text();
+ var link = GoalPageLink_$('
');
+ link.text(title);
+ link.attr('title', Object(external_CoreHome_["translate"])('Goals_ClickToViewThisGoal'));
+ link.click(function (e) {
+ e.preventDefault();
+ external_CoreHome_["MatomoUrl"].updateHash(Object.assign(Object.assign({}, external_CoreHome_["MatomoUrl"].hashParsed.value), {}, {
+ category: 'Goals_Goals',
+ subcategory: binding.value.idGoal
+ }));
+ });
+ GoalPageLink_$(el).html(link[0]);
+ }
+};
+/* harmony default export */ var GoalPageLink_GoalPageLink = (GoalPageLink); // manually handle occurrence of goal-page-link on datatable html attributes since dataTable.js is
+// not managed by vue.
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+
+external_CoreHome_["Matomo"].on('Matomo.processDynamicHtml', function ($element) {
+ $element.find('[goal-page-link]').each(function (i, e) {
+ if (GoalPageLink_$(e).attr('goal-page-link-handled')) {
+ return;
+ }
+
+ var idGoal = GoalPageLink_$(e).attr('goal-page-link');
+
+ if (idGoal) {
+ GoalPageLink.mounted(e, {
+ instance: null,
+ value: {
+ idGoal: idGoal
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ });
+ }
+
+ GoalPageLink_$(e).attr('goal-page-link-handled', '1');
+ });
+});
+// CONCATENATED MODULE: ./plugins/Goals/vue/src/GoalPageLink/GoalPageLink.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 piwikGoalPageLink() {
+ return {
+ restrict: 'A',
+ link: function piwikGoalPageLinkLink(scope, element, attrs) {
+ var binding = {
+ instance: null,
+ value: {
+ idGoal: attrs.piwikGoalPageLink
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ };
+ GoalPageLink_GoalPageLink.mounted(element[0], binding);
+ }
+ };
+}
+window.angular.module('piwikApp').directive('piwikGoalPageLink', piwikGoalPageLink);
+// EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"}
+var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf");
+
+// 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/Goals/vue/src/ManageGoals/ManageGoals.vue?vue&type=template&id=0e2ceb1f
+
+var _hoisted_1 = {
+ id: "entityEditContainer",
+ feature: "true",
+ class: "managegoals"
+};
+var _hoisted_2 = {
+ class: "contentHelp"
+};
+var _hoisted_3 = ["innerHTML"];
+var _hoisted_4 = {
+ key: 0
+};
+
+var _hoisted_5 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_6 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_7 = ["innerHTML"];
+var _hoisted_8 = {
+ class: "first"
+};
+var _hoisted_9 = {
+ key: 1
+};
+var _hoisted_10 = {
+ key: 2
+};
+var _hoisted_11 = {
+ key: 0
+};
+var _hoisted_12 = {
+ colspan: "8"
+};
+
+var _hoisted_13 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_14 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_15 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_16 = ["id"];
+var _hoisted_17 = {
+ class: "first"
+};
+var _hoisted_18 = {
+ class: "matchAttribute"
+};
+var _hoisted_19 = {
+ key: 0
+};
+var _hoisted_20 = {
+ key: 1
+};
+
+var _hoisted_21 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_22 = ["innerHTML"];
+var _hoisted_23 = {
+ key: 1,
+ style: {
+ "padding-top": "2px"
+ }
+};
+var _hoisted_24 = ["onClick", "title"];
+
+var _hoisted_25 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: "icon-edit"
+}, null, -1);
+
+var _hoisted_26 = [_hoisted_25];
+var _hoisted_27 = {
+ key: 2,
+ style: {
+ "padding-top": "2px"
+ }
+};
+var _hoisted_28 = ["onClick", "title"];
+
+var _hoisted_29 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: "icon-delete"
+}, null, -1);
+
+var _hoisted_30 = [_hoisted_29];
+var _hoisted_31 = {
+ key: 0,
+ class: "tableActionBar"
+};
+
+var _hoisted_32 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ class: "icon-add"
+}, null, -1);
+
+var _hoisted_33 = {
+ class: "ui-confirm",
+ ref: "confirm"
+};
+var _hoisted_34 = ["value"];
+var _hoisted_35 = ["value"];
+var _hoisted_36 = {
+ class: "addEditGoal"
+};
+var _hoisted_37 = ["innerHTML"];
+var _hoisted_38 = {
+ class: "row goalIsTriggeredWhen"
+};
+var _hoisted_39 = {
+ class: "col s12"
+};
+var _hoisted_40 = {
+ class: "row"
+};
+var _hoisted_41 = {
+ class: "col s12 m6 goalTriggerType"
+};
+var _hoisted_42 = {
+ class: "col s12 m6"
+};
+var _hoisted_43 = ["innerHTML"];
+var _hoisted_44 = {
+ class: "row whereTheMatchAttrbiute"
+};
+var _hoisted_45 = {
+ class: "col s12"
+};
+var _hoisted_46 = {
+ class: "row"
+};
+var _hoisted_47 = {
+ class: "col s12 m6 l4"
+};
+var _hoisted_48 = {
+ key: 0,
+ class: "col s12 m6 l4"
+};
+var _hoisted_49 = {
+ key: 1,
+ class: "col s12 m6 l4"
+};
+var _hoisted_50 = {
+ class: "col s12 m6 l4"
+};
+var _hoisted_51 = {
+ id: "examples_pattern",
+ class: "col s12"
+};
+
+var _hoisted_52 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_53 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_54 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_55 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_56 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_57 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_58 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_59 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_60 = {
+ ref: "endedittable"
+};
+
+var _hoisted_61 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ type: "hidden",
+ name: "goalIdUpdate",
+ value: ""
+}, null, -1);
+
+var _hoisted_62 = {
+ key: 0
+};
+var _hoisted_63 = ["innerHTML"];
+
+var _hoisted_64 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", {
+ id: "bottom"
+}, null, -1);
+
+function render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _ctx$goalToDelete;
+
+ var _component_ActivityIndicator = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ActivityIndicator");
+
+ var _component_ContentBlock = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("ContentBlock");
+
+ var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field");
+
+ var _component_Alert = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Alert");
+
+ var _component_SaveButton = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("SaveButton");
+
+ var _directive_content_table = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("content-table");
+
+ var _directive_form = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("form");
+
+ 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_["withDirectives"])(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_["createElementVNode"])("div", _hoisted_1, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ContentBlock, {
+ "content-title": _ctx.translate('Goals_ManageGoals')
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ActivityIndicator, {
+ loading: _ctx.isLoading
+ }, null, 8, ["loading"]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_2, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ innerHTML: _ctx.$sanitize(_ctx.learnMoreAboutGoalTracking)
+ }, null, 8, _hoisted_3), !_ctx.ecommerceEnabled ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", _hoisted_4, [_hoisted_5, _hoisted_6, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Optional')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Ecommerce')) + ": ", 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ innerHTML: _ctx.$sanitize(_ctx.youCanEnableEcommerceReports)
+ }, null, 8, _hoisted_7)])) : 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"])("table", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("thead", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("tr", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", _hoisted_8, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Id')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_GoalName')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Description')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_GoalIsTriggeredWhen')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ColumnRevenue')), 1), _ctx.beforeGoalListActionsHeadComponent ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDynamicComponent"])(_ctx.beforeGoalListActionsHeadComponent), {
+ key: 0
+ })) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.userCanEditGoals ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("th", _hoisted_9, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Edit')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.userCanEditGoals ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("th", _hoisted_10, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_Delete')), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("tbody", null, [!Object.keys(_ctx.goals || {}).length ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("tr", _hoisted_11, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", _hoisted_12, [_hoisted_13, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_ThereIsNoGoalToManage', _ctx.siteName)) + " ", 1), _hoisted_14, _hoisted_15])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), (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.goals || [], function (goal) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("tr", {
+ id: goal.idgoal,
+ key: goal.idgoal
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", _hoisted_17, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(goal.idgoal), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(goal.name), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(goal.description), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", _hoisted_18, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.goalMatchAttributeTranslations[goal.match_attribute] || goal.match_attribute), 1), goal.match_attribute === 'visit_duration' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", _hoisted_19, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.lcfirst(_ctx.translate('General_OperationGreaterThan'))) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Intl_NMinutes', goal.pattern)), 1)) : !!goal.pattern_type ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("span", _hoisted_20, [_hoisted_21, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Pattern')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(goal.pattern_type) + ": " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(goal.pattern), 1)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", {
+ class: "center",
+ innerHTML: _ctx.$sanitize(goal.revenue === 0 || goal.revenue === '0' ? '-' : goal.revenue_pretty)
+ }, null, 8, _hoisted_22), _ctx.beforeGoalListActionsBodyComponent[goal.idgoal] ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDynamicComponent"])(_ctx.beforeGoalListActionsBodyComponent[goal.idgoal]), {
+ key: 0
+ })) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.userCanEditGoals ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("td", _hoisted_23, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("button", {
+ onClick: function onClick($event) {
+ return _ctx.editGoal(goal.idgoal);
+ },
+ class: "table-action",
+ title: _ctx.translate('General_Edit')
+ }, _hoisted_26, 8, _hoisted_24)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.userCanEditGoals ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("td", _hoisted_27, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("button", {
+ onClick: function onClick($event) {
+ return _ctx.deleteGoal(goal.idgoal);
+ },
+ class: "table-action",
+ title: _ctx.translate('General_Delete')
+ }, _hoisted_30, 8, _hoisted_28)])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 8, _hoisted_16);
+ }), 128))])], 512), [[_directive_content_table]]), _ctx.userCanEditGoals && !_ctx.onlyShowAddNewGoal ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_31, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("button", {
+ id: "add-goal",
+ onClick: _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.createGoal();
+ })
+ }, [_hoisted_32, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_AddNewGoal')), 1)])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)];
+ }),
+ _: 1
+ }, 8, ["content-title"])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showGoalList]]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_33, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h2", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_DeleteGoalConfirm', "\"".concat((_ctx$goalToDelete = _ctx.goalToDelete) === null || _ctx$goalToDelete === void 0 ? void 0 : _ctx$goalToDelete.name, "\""))), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ role: "yes",
+ type: "button",
+ value: _ctx.translate('General_Yes')
+ }, null, 8, _hoisted_34), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("input", {
+ role: "no",
+ type: "button",
+ value: _ctx.translate('General_No')
+ }, null, 8, _hoisted_35)], 512)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], !_ctx.onlyShowAddNewGoal]]), 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_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_36, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_ContentBlock, {
+ "content-title": _ctx.goal.idgoal ? _ctx.translate('Goals_UpdateGoal') : _ctx.translate('Goals_AddNewGoal')
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ innerHTML: _ctx.$sanitize(_ctx.addNewGoalIntro)
+ }, null, 8, _hoisted_37), 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_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "text",
+ name: "goal_name",
+ modelValue: _ctx.goal.name,
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = function ($event) {
+ return _ctx.goal.name = $event;
+ }),
+ maxlength: 50,
+ title: _ctx.translate('Goals_GoalName')
+ }, null, 8, ["modelValue", "title"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "text",
+ name: "goal_description",
+ modelValue: _ctx.goal.description,
+ "onUpdate:modelValue": _cache[2] || (_cache[2] = function ($event) {
+ return _ctx.goal.description = $event;
+ }),
+ maxlength: 255,
+ title: _ctx.translate('General_Description')
+ }, null, 8, ["modelValue", "title"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_38, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_39, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h3", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_GoalIsTriggered')), 1)])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_40, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_41, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "select",
+ name: "trigger_type",
+ "model-value": _ctx.triggerType,
+ "onUpdate:modelValue": _cache[3] || (_cache[3] = function ($event) {
+ _ctx.triggerType = $event;
+
+ _ctx.changedTriggerType();
+ }),
+ "full-width": true,
+ options: _ctx.goalTriggerTypeOptions
+ }, null, 8, ["model-value", "options"])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_42, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Alert, {
+ severity: "info"
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("span", {
+ innerHTML: _ctx.$sanitize(_ctx.whereVisitedPageManuallyCallsJsTrackerText)
+ }, null, 8, _hoisted_43)];
+ }),
+ _: 1
+ }, 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.triggerType === 'manually']]), 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_Field, {
+ uicontrol: "radio",
+ name: "match_attribute",
+ "full-width": true,
+ "model-value": _ctx.goal.match_attribute,
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = function ($event) {
+ _ctx.goal.match_attribute = $event;
+
+ _ctx.initPatternType();
+ }),
+ options: _ctx.goalMatchAttributeOptions
+ }, null, 8, ["model-value", "options"]), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.triggerType !== 'manually']])])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_44, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h3", _hoisted_45, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_WhereThe')) + " ", 1), 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('Goals_URL')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === '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('Goals_PageTitle')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'title']]), 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('Goals_Filename')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'file']]), 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('Goals_ExternalWebsiteUrl')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'external_website']]), 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('Goals_VisitDuration')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'visit_duration']])])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.triggerType !== 'manually']]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_46, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_47, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "select",
+ name: "event_type",
+ modelValue: _ctx.eventType,
+ "onUpdate:modelValue": _cache[5] || (_cache[5] = function ($event) {
+ return _ctx.eventType = $event;
+ }),
+ "full-width": true,
+ options: _ctx.eventTypeOptions
+ }, null, 8, ["modelValue", "options"])])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'event']]), !_ctx.isMatchAttributeNumeric ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_48, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "select",
+ name: "pattern_type",
+ modelValue: _ctx.goal.pattern_type,
+ "onUpdate:modelValue": _cache[6] || (_cache[6] = function ($event) {
+ return _ctx.goal.pattern_type = $event;
+ }),
+ "full-width": true,
+ options: _ctx.patternTypeOptions
+ }, null, 8, ["modelValue", "options"])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), _ctx.isMatchAttributeNumeric ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_49, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "select",
+ name: "pattern_type",
+ modelValue: _ctx.goal.pattern_type,
+ "onUpdate:modelValue": _cache[7] || (_cache[7] = function ($event) {
+ return _ctx.goal.pattern_type = $event;
+ }),
+ "full-width": true,
+ options: _ctx.numericComparisonTypeOptions
+ }, null, 8, ["modelValue", "options"])])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_50, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "text",
+ name: "pattern",
+ modelValue: _ctx.goal.pattern,
+ "onUpdate:modelValue": _cache[8] || (_cache[8] = function ($event) {
+ return _ctx.goal.pattern = $event;
+ }),
+ maxlength: 255,
+ title: _ctx.patternFieldLabel,
+ "full-width": true
+ }, null, 8, ["modelValue", "title"])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_51, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Alert, {
+ severity: "info"
+ }, {
+ default: Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withCtx"])(function () {
+ return [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_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Contains', "'checkout/confirmation'")) + " ", 1), _hoisted_52, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_IsExactly', "'http://example.com/thank-you.html'")) + " ", 1), _hoisted_53, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_MatchesExpression', "'(.*)\\\/demo\\\/(.*)'")), 1)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === '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('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Contains', "'Order confirmation'")), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'title']]), 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_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Contains', "'files/brochure.pdf'")) + " ", 1), _hoisted_54, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_IsExactly', "'http://example.com/files/brochure.pdf'")) + " ", 1), _hoisted_55, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_MatchesExpression', "'(.*)\\\.zip'")), 1)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'file']]), 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_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Contains', "'amazon.com'")) + " ", 1), _hoisted_56, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_IsExactly', "'http://mypartner.com/landing.html'")) + " ", 1), _hoisted_57, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.matchesExpressionExternal), 1)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'external_website']]), 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_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Contains', "'video'")) + " ", 1), _hoisted_58, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_IsExactly', "'click'")) + " ", 1), _hoisted_59, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_MatchesExpression', "'(.*)_banner'")) + "\" ", 1)], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'event']]), 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('General_ForExampleShort')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_AtLeastMinutes', '5', '0.5')), 513), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'visit_duration']])];
+ }),
+ _: 1
+ })])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.triggerType !== 'manually']]), 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_Field, {
+ uicontrol: "checkbox",
+ name: "case_sensitive",
+ modelValue: _ctx.goal.case_sensitive,
+ "onUpdate:modelValue": _cache[9] || (_cache[9] = function ($event) {
+ return _ctx.goal.case_sensitive = $event;
+ }),
+ title: _ctx.caseSensitiveTitle
+ }, null, 8, ["modelValue", "title"]), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.triggerType !== 'manually' && !_ctx.isMatchAttributeNumeric]])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [_ctx.goal.match_attribute !== 'visit_duration' ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(_component_Field, {
+ key: 0,
+ uicontrol: "radio",
+ name: "allow_multiple",
+ "model-value": _ctx.goal.allow_multiple ? 1 : 0,
+ "onUpdate:modelValue": _cache[10] || (_cache[10] = function ($event) {
+ return _ctx.goal.allow_multiple = $event;
+ }),
+ options: _ctx.allowMultipleOptions,
+ introduction: _ctx.translate('Goals_AllowMultipleConversionsPerVisit'),
+ "inline-help": _ctx.translate('Goals_HelpOneConversionPerVisit')
+ }, null, 8, ["model-value", "options", "introduction", "inline-help"])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("h3", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_GoalRevenue')) + " " + Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.translate('Goals_Optional')), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "number",
+ name: "revenue",
+ modelValue: _ctx.goal.revenue,
+ "onUpdate:modelValue": _cache[11] || (_cache[11] = function ($event) {
+ return _ctx.goal.revenue = $event;
+ }),
+ placeholder: _ctx.translate('Goals_DefaultRevenueLabel'),
+ "inline-help": _ctx.translate('Goals_DefaultRevenueHelp')
+ }, null, 8, ["modelValue", "placeholder", "inline-help"])]), 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_Field, {
+ uicontrol: "checkbox",
+ name: "use_event_value",
+ modelValue: _ctx.goal.event_value_as_revenue,
+ "onUpdate:modelValue": _cache[12] || (_cache[12] = function ($event) {
+ return _ctx.goal.event_value_as_revenue = $event;
+ }),
+ title: _ctx.translate('Goals_UseEventValueAsRevenue'),
+ "inline-help": _ctx.useEventValueAsRevenueHelp
+ }, null, 8, ["modelValue", "title", "inline-help"]), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.goal.match_attribute === 'event']])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", _hoisted_60, [_ctx.endEditTableComponent ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createBlock"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDynamicComponent"])(_ctx.endEditTableComponent), {
+ key: 0
+ })) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 512), _hoisted_61, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_SaveButton, {
+ saving: _ctx.isLoading,
+ onConfirm: _cache[13] || (_cache[13] = function ($event) {
+ return _ctx.save();
+ }),
+ value: _ctx.submitText
+ }, null, 8, ["saving", "value"]), !_ctx.onlyShowAddNewGoal ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", _hoisted_62, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", {
+ class: "entityCancel",
+ onClick: _cache[14] || (_cache[14] = function ($event) {
+ return _ctx.showListOfReports();
+ }),
+ innerHTML: _ctx.$sanitize(_ctx.cancelText)
+ }, null, 8, _hoisted_63), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showEditGoal]])])) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)], 512), [[_directive_form]])];
+ }),
+ _: 1
+ }, 8, ["content-title"])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.showEditGoal]])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.userCanEditGoals]]), _hoisted_64]);
+}
+// CONCATENATED MODULE: ./plugins/Goals/vue/src/ManageGoals/ManageGoals.vue?vue&type=template&id=0e2ceb1f
+
+// EXTERNAL MODULE: external "CorePluginsAdmin"
+var external_CorePluginsAdmin_ = __webpack_require__("a5a2");
+
+// CONCATENATED MODULE: ./plugins/Goals/vue/src/ManageGoals/PiwikApiMock.ts
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _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 _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function _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
+*/
+// the piwikApi angularjs service is passed in some frontend events to allow plugins to modify
+// a request before it is sent. for the time being in Vue we use this mock, which has the same
+// API as the piwikApi service, to modify the input used with AjaxHelper. this provides BC
+// with for plugins that haven't been converted.
+//
+// should be removed in Matomo 5.
+var PiwikApiMock = /*#__PURE__*/function () {
+ function PiwikApiMock(parameters, options) {
+ _classCallCheck(this, PiwikApiMock);
+
+ _defineProperty(this, "parameters", void 0);
+
+ _defineProperty(this, "options", void 0);
+
+ this.parameters = parameters;
+ this.options = options;
+ }
+
+ _createClass(PiwikApiMock, [{
+ key: "addParams",
+ value: function addParams(params) {
+ Object.assign(this.parameters, params);
+ }
+ }, {
+ key: "withTokenInUrl",
+ value: function withTokenInUrl() {
+ this.options.withTokenInUrl = true;
+ }
+ }, {
+ key: "reset",
+ value: function reset() {
+ var _this = this;
+
+ Object.keys(this.parameters).forEach(function (name) {
+ delete _this.parameters[name];
+ });
+ delete this.options.postParams;
+ }
+ }, {
+ key: "addPostParams",
+ value: function addPostParams(params) {
+ this.options.postParams = Object.assign(Object.assign({}, this.options.postParams), params);
+ }
+ }]);
+
+ return PiwikApiMock;
+}();
+
+
+// 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/Goals/vue/src/ManageGoals/ManageGoals.vue?vue&type=script&lang=ts
+
+
+
+
+/* harmony default export */ var ManageGoalsvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ inheritAttrs: false,
+ props: {
+ onlyShowAddNewGoal: Boolean,
+ userCanEditGoals: Boolean,
+ ecommerceEnabled: Boolean,
+ goals: {
+ type: Object,
+ required: true
+ },
+ addNewGoalIntro: String,
+ goalTriggerTypeOptions: Object,
+ goalMatchAttributeOptions: Array,
+ eventTypeOptions: Array,
+ patternTypeOptions: Array,
+ numericComparisonTypeOptions: Array,
+ allowMultipleOptions: Array,
+ showAddGoal: Boolean,
+ showGoal: Number,
+ beforeGoalListActionsBody: Object,
+ endEditTable: String,
+ beforeGoalListActionsHead: String
+ },
+ data: function data() {
+ return {
+ showEditGoal: false,
+ showGoalList: true,
+ goal: {},
+ isLoading: false,
+ eventType: 'event_category',
+ triggerType: 'visitors',
+ apiMethod: '',
+ submitText: '',
+ goalToDelete: null,
+ addEditTableComponent: false
+ };
+ },
+ components: {
+ SaveButton: external_CorePluginsAdmin_["SaveButton"],
+ ContentBlock: external_CoreHome_["ContentBlock"],
+ ActivityIndicator: external_CoreHome_["ActivityIndicator"],
+ Field: external_CorePluginsAdmin_["Field"],
+ Alert: external_CoreHome_["Alert"]
+ },
+ directives: {
+ ContentTable: external_CoreHome_["ContentTable"],
+ Form: external_CorePluginsAdmin_["Form"]
+ },
+ mounted: function mounted() {
+ var _this = this;
+
+ if (this.showAddGoal) {
+ this.createGoal();
+ } else if (this.showGoal) {
+ this.editGoal(this.showGoal);
+ } else {
+ this.showListOfReports();
+ } // this component can be used in multiple places, one where
+ // Matomo.helper.compileAngularComponents() is already called, one where it's not.
+ // to make sure this function is only applied once to the slot data, we explicitly do not
+ // add it to vue, then on the next update, add it and call compileAngularComponents()
+
+
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ _this.addEditTableComponent = true;
+ Object(external_commonjs_vue_commonjs2_vue_root_Vue_["nextTick"])(function () {
+ var el = _this.$refs.endedittable;
+ var scope = external_CoreHome_["Matomo"].helper.getAngularDependency('$rootScope').$new(true);
+ $(el).data('scope', scope);
+ external_CoreHome_["Matomo"].helper.compileAngularComponents(el, {
+ scope: scope
+ });
+ });
+ });
+ },
+ beforeUnmount: function beforeUnmount() {
+ var el = this.$refs.endedittable;
+ $(el).data('scope').$destroy();
+ },
+ methods: {
+ scrollToTop: function scrollToTop() {
+ setTimeout(function () {
+ external_CoreHome_["Matomo"].helper.lazyScrollTo('.pageWrap', 200);
+ });
+ },
+ initGoalForm: function initGoalForm(goalMethodAPI, submitText, goalName, description, matchAttribute, pattern, patternType, caseSensitive, revenue, allowMultiple, useEventValueAsRevenue, goalId) {
+ external_CoreHome_["Matomo"].postEvent('Goals.beforeInitGoalForm', goalMethodAPI, goalId);
+ this.apiMethod = goalMethodAPI;
+ this.goal = {};
+ this.goal.name = goalName;
+ this.goal.description = description;
+ var actualMatchAttribute = matchAttribute;
+
+ if (actualMatchAttribute === 'manually') {
+ this.triggerType = 'manually';
+ actualMatchAttribute = 'url';
+ } else {
+ this.triggerType = 'visitors';
+ }
+
+ if (actualMatchAttribute.indexOf('event') === 0) {
+ this.eventType = actualMatchAttribute;
+ actualMatchAttribute = 'event';
+ } else {
+ this.eventType = 'event_category';
+ }
+
+ this.goal.match_attribute = actualMatchAttribute;
+ this.goal.allow_multiple = allowMultiple;
+ this.goal.pattern_type = patternType;
+ this.goal.pattern = pattern;
+ this.goal.case_sensitive = caseSensitive;
+ this.goal.revenue = revenue;
+ this.goal.event_value_as_revenue = useEventValueAsRevenue;
+ this.submitText = submitText;
+ this.goal.idgoal = goalId;
+ },
+ showListOfReports: function showListOfReports() {
+ external_CoreHome_["Matomo"].postEvent('Goals.cancelForm');
+ this.showGoalList = true;
+ this.showEditGoal = false;
+ this.scrollToTop();
+ },
+ showAddEditForm: function showAddEditForm() {
+ this.showGoalList = false;
+ this.showEditGoal = true;
+ },
+ createGoal: function createGoal() {
+ var parameters = {
+ isAllowed: true
+ };
+ external_CoreHome_["Matomo"].postEvent('Goals.initAddGoal', parameters);
+
+ if (parameters && !parameters.isAllowed) {
+ return;
+ }
+
+ this.showAddEditForm();
+ this.initGoalForm('Goals.addGoal', Object(external_CoreHome_["translate"])('Goals_AddGoal'), '', '', 'url', '', 'contains', false, 0, false, false, 0);
+ this.scrollToTop();
+ },
+ editGoal: function editGoal(goalId) {
+ this.showAddEditForm();
+ var goal = this.goals["".concat(goalId)];
+ this.initGoalForm('Goals.updateGoal', Object(external_CoreHome_["translate"])('Goals_UpdateGoal'), goal.name, goal.description, goal.match_attribute, goal.pattern, goal.pattern_type, !!goal.case_sensitive && goal.case_sensitive !== '0', parseInt("".concat(goal.revenue), 10), !!goal.allow_multiple && goal.allow_multiple !== '0', !!goal.event_value_as_revenue && goal.event_value_as_revenue !== '0', goalId);
+ this.scrollToTop();
+ },
+ deleteGoal: function deleteGoal(goalId) {
+ var _this2 = this;
+
+ this.goalToDelete = this.goals["".concat(goalId)];
+ external_CoreHome_["Matomo"].helper.modalConfirm(this.$refs.confirm, {
+ yes: function yes() {
+ _this2.isLoading = true;
+ external_CoreHome_["AjaxHelper"].fetch({
+ idGoal: goalId,
+ method: 'Goals.deleteGoal'
+ }).then(function () {
+ window.location.reload();
+ }).finally(function () {
+ _this2.isLoading = false;
+ });
+ }
+ });
+ },
+ save: function save() {
+ var _this3 = this;
+
+ var parameters = {}; // TODO: test removal of encoding, should be handled by ajax request
+
+ parameters.name = this.goal.name;
+ parameters.description = this.goal.description;
+
+ if (this.isManuallyTriggered) {
+ parameters.matchAttribute = 'manually';
+ parameters.patternType = 'regex';
+ parameters.pattern = '.*';
+ parameters.caseSensitive = 0;
+ } else {
+ parameters.matchAttribute = this.goal.match_attribute;
+
+ if (parameters.matchAttribute === 'event') {
+ parameters.matchAttribute = this.eventType;
+ }
+
+ parameters.patternType = this.goal.pattern_type;
+ parameters.pattern = this.goal.pattern;
+ parameters.caseSensitive = this.goal.case_sensitive ? 1 : 0;
+ }
+
+ parameters.revenue = this.goal.revenue || 0;
+ parameters.allowMultipleConversionsPerVisit = this.goal.allow_multiple ? 1 : 0;
+ parameters.useEventValueAsRevenue = this.goal.event_value_as_revenue ? 1 : 0;
+ parameters.idGoal = this.goal.idgoal;
+ parameters.method = this.apiMethod;
+ var isCreate = parameters.method === 'Goals.addGoal';
+ var isUpdate = parameters.method === 'Goals.updateGoal';
+ var options = {};
+ var piwikApiMock = new PiwikApiMock(parameters, options);
+
+ if (isUpdate) {
+ external_CoreHome_["Matomo"].postEvent('Goals.beforeUpdateGoal', parameters, piwikApiMock);
+ } else if (isCreate) {
+ external_CoreHome_["Matomo"].postEvent('Goals.beforeAddGoal', parameters, piwikApiMock);
+ }
+
+ if (parameters !== null && parameters !== void 0 && parameters.cancelRequest) {
+ return;
+ }
+
+ this.isLoading = true;
+ external_CoreHome_["AjaxHelper"].fetch(parameters, options).then(function () {
+ var subcategory = external_CoreHome_["MatomoUrl"].parsed.value.subcategory;
+
+ if (subcategory === 'Goals_AddNewGoal' && external_CoreHome_["Matomo"].helper.isAngularRenderingThePage()) {
+ // when adding a goal for the first time we need to load manage goals page afterwards
+ external_CoreHome_["ReportingMenuStore"].reloadMenuItems().then(function () {
+ external_CoreHome_["MatomoUrl"].updateHash(Object.assign(Object.assign({}, external_CoreHome_["MatomoUrl"].hashParsed.value), {}, {
+ subcategory: 'Goals_ManageGoals'
+ }));
+ _this3.isLoading = false;
+ });
+ } else {
+ window.location.reload();
+ }
+ }).catch(function () {
+ _this3.scrollToTop();
+
+ _this3.isLoading = false;
+ });
+ },
+ changedTriggerType: function changedTriggerType() {
+ if (!this.isManuallyTriggered && !this.goal.pattern_type) {
+ this.goal.pattern_type = 'contains';
+ }
+ },
+ initPatternType: function initPatternType() {
+ if (this.isMatchAttributeNumeric) {
+ this.goal.pattern_type = 'greater_than';
+ } else {
+ this.goal.pattern_type = 'contains';
+ }
+ },
+ lcfirst: function lcfirst(s) {
+ return "".concat(s.substr(0, 1).toLowerCase()).concat(s.substr(1));
+ },
+ ucfirst: function ucfirst(s) {
+ return "".concat(s.substr(0, 1).toUpperCase()).concat(s.substr(1));
+ }
+ },
+ computed: {
+ learnMoreAboutGoalTracking: function learnMoreAboutGoalTracking() {
+ return Object(external_CoreHome_["translate"])('Goals_LearnMoreAboutGoalTrackingDocumentation', '
', ' ');
+ },
+ youCanEnableEcommerceReports: function youCanEnableEcommerceReports() {
+ var link = external_CoreHome_["MatomoUrl"].stringify(Object.assign(Object.assign({}, external_CoreHome_["MatomoUrl"].urlParsed.value), {}, {
+ module: 'SitesManager',
+ action: 'index'
+ }));
+ var ecommerceReportsText = '
".concat(Object(external_CoreHome_["translate"])('Goals_EcommerceReports'), " ");
+ var websiteManageText = "
").concat(Object(external_CoreHome_["translate"])('SitesManager_WebsitesManagement'), " ");
+ return Object(external_CoreHome_["translate"])('Goals_YouCanEnableEcommerceReports', ecommerceReportsText, websiteManageText);
+ },
+ siteName: function siteName() {
+ return external_CoreHome_["Matomo"].helper.htmlDecode(external_CoreHome_["Matomo"].siteName);
+ },
+ whereVisitedPageManuallyCallsJsTrackerText: function whereVisitedPageManuallyCallsJsTrackerText() {
+ var link = 'https://developer.matomo.org/guides/tracking-javascript-guide#manually-trigger-goal-conversions';
+ return Object(external_CoreHome_["translate"])('Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore', "
"), ' ');
+ },
+ caseSensitiveTitle: function caseSensitiveTitle() {
+ return "".concat(Object(external_CoreHome_["translate"])('Goals_CaseSensitive'), " ").concat(Object(external_CoreHome_["translate"])('Goals_Optional'));
+ },
+ useEventValueAsRevenueHelp: function useEventValueAsRevenueHelp() {
+ return "".concat(Object(external_CoreHome_["translate"])('Goals_EventValueAsRevenueHelp'), "
").concat(Object(external_CoreHome_["translate"])('Goals_EventValueAsRevenueHelp2'));
+ },
+ cancelText: function cancelText() {
+ return Object(external_CoreHome_["translate"])('General_OrCancel', '
', ' ');
+ },
+ isMatchAttributeNumeric: function isMatchAttributeNumeric() {
+ return ['visit_duration'].indexOf(this.goal.match_attribute) > -1;
+ },
+ patternFieldLabel: function patternFieldLabel() {
+ return this.goal.match_attribute === 'visit_duration' ? Object(external_CoreHome_["translate"])('Goals_TimeInMinutes') : Object(external_CoreHome_["translate"])('Goals_Pattern');
+ },
+ goalMatchAttributeTranslations: function goalMatchAttributeTranslations() {
+ return {
+ manually: Object(external_CoreHome_["translate"])('Goals_ManuallyTriggeredUsingJavascriptFunction'),
+ file: Object(external_CoreHome_["translate"])('Goals_Download'),
+ url: Object(external_CoreHome_["translate"])('Goals_VisitUrl'),
+ title: Object(external_CoreHome_["translate"])('Goals_VisitPageTitle'),
+ external_website: Object(external_CoreHome_["translate"])('Goals_ClickOutlink'),
+ event_action: "".concat(Object(external_CoreHome_["translate"])('Goals_SendEvent'), " (").concat(Object(external_CoreHome_["translate"])('Events_EventAction'), ")"),
+ event_category: "".concat(Object(external_CoreHome_["translate"])('Goals_SendEvent'), " (").concat(Object(external_CoreHome_["translate"])('Events_EventCategory'), ")"),
+ event_name: "".concat(Object(external_CoreHome_["translate"])('Goals_SendEvent'), " (").concat(Object(external_CoreHome_["translate"])('Events_EventName'), ")"),
+ visit_duration: "".concat(this.ucfirst(Object(external_CoreHome_["translate"])('Goals_VisitDuration')))
+ };
+ },
+ beforeGoalListActionsBodyComponent: function beforeGoalListActionsBodyComponent() {
+ var _this4 = this;
+
+ if (!this.beforeGoalListActionsBody) {
+ return {};
+ }
+
+ var componentsByIdGoal = {};
+ Object.values(this.goals).forEach(function (g) {
+ componentsByIdGoal[g.idgoal] = {
+ template: _this4.beforeGoalListActionsBody[g.idgoal]
+ };
+ });
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["markRaw"])(componentsByIdGoal);
+ },
+ endEditTableComponent: function endEditTableComponent() {
+ if (!this.endEditTable || !this.addEditTableComponent) {
+ return null;
+ }
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["markRaw"])({
+ template: this.endEditTable
+ });
+ },
+ beforeGoalListActionsHeadComponent: function beforeGoalListActionsHeadComponent() {
+ if (!this.beforeGoalListActionsHead) {
+ return null;
+ }
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["markRaw"])({
+ template: this.beforeGoalListActionsHead
+ });
+ },
+ isManuallyTriggered: function isManuallyTriggered() {
+ return this.triggerType === 'manually';
+ },
+ matchesExpressionExternal: function matchesExpressionExternal() {
+ var url = "'http://www.amazon.com\\/(.*)\\/yourAffiliateId'";
+ return Object(external_CoreHome_["translate"])('Goals_MatchesExpression', url);
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/Goals/vue/src/ManageGoals/ManageGoals.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/Goals/vue/src/ManageGoals/ManageGoals.vue
+
+
+
+ManageGoalsvue_type_script_lang_ts.render = render
+
+/* harmony default export */ var ManageGoals = (ManageGoalsvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/Goals/vue/src/ManageGoals/ManageGoals.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 ManageGoals_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: ManageGoals,
+ directiveName: 'piwikManageGoals',
+ scope: {
+ userCanEditGoals: {
+ angularJsBind: '<'
+ },
+ onlyShowAddNewGoal: {
+ angularJsBind: '<'
+ },
+ ecommerceEnabled: {
+ angularJsBind: '<'
+ },
+ goals: {
+ angularJsBind: '<'
+ },
+ showGoal: {
+ angularJsBind: '<'
+ },
+ showAddGoal: {
+ angularJsBind: '<'
+ },
+ addNewGoalIntro: {
+ angularJsBind: '<'
+ },
+ goalTriggerTypeOptions: {
+ angularJsBind: '<'
+ },
+ goalMatchAttributeOptions: {
+ angularJsBind: '<'
+ },
+ eventTypeOptions: {
+ angularJsBind: '<'
+ },
+ patternTypeOptions: {
+ angularJsBind: '<'
+ },
+ numericComparisonTypeOptions: {
+ angularJsBind: '<'
+ },
+ allowMultipleOptions: {
+ angularJsBind: '<'
+ },
+ beforeGoalListActionsBody: {
+ angularJsBind: '<'
+ },
+ endEditTable: {
+ angularJsBind: '<'
+ },
+ beforeGoalListActionsHead: {
+ angularJsBind: '<'
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/Goals/vue/src/index.ts
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+*/
+
+
+
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js
+
+
+
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=Goals.umd.js.map
\ No newline at end of file
diff --git a/app/plugins/Goals/vue/dist/Goals.umd.min.js b/app/plugins/Goals/vue/dist/Goals.umd.min.js
new file mode 100644
index 000000000..dadb18104
--- /dev/null
+++ b/app/plugins/Goals/vue/dist/Goals.umd.min.js
@@ -0,0 +1,21 @@
+(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):"function"===typeof define&&define.amd?define(["CoreHome",,"CorePluginsAdmin"],t):"object"===typeof exports?exports["Goals"]=t(require("CoreHome"),require("vue"),require("CorePluginsAdmin")):e["Goals"]=t(e["CoreHome"],e["Vue"],e["CorePluginsAdmin"])})("undefined"!==typeof self?self:this,(function(e,t,a){return function(e){var t={};function a(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,a),o.l=!0,o.exports}return a.m=e,a.c=t,a.d=function(e,t,n){a.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},a.r=function(e){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,t){if(1&t&&(e=a(e)),8&t)return e;if(4&t&&"object"===typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(a.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)a.d(n,o,function(t){return e[t]}.bind(null,o));return n},a.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return a.d(t,"a",t),t},a.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},a.p="plugins/Goals/vue/dist/",a(a.s="fae3")}({"19dc":function(t,a){t.exports=e},"8bbf":function(e,a){e.exports=t},a5a2:function(e,t){e.exports=a},fae3:function(e,t,a){"use strict";if(a.r(t),a.d(t,"GoalPageLink",(function(){return s})),a.d(t,"ManageGoals",(function(){return De})),"undefined"!==typeof window){var n=window.document.currentScript,o=n&&n.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);o&&(a.p=o[1])}var l=a("19dc"),r=window,i=r.$,c={mounted:function(e,t){if(l["Matomo"].helper.isAngularRenderingThePage()){var a=i(e).text(),n=i("
");n.text(a),n.attr("title",Object(l["translate"])("Goals_ClickToViewThisGoal")),n.click((function(e){e.preventDefault(),l["MatomoUrl"].updateHash(Object.assign(Object.assign({},l["MatomoUrl"].hashParsed.value),{},{category:"Goals_Goals",subcategory:t.value.idGoal}))})),i(e).html(n[0])}}},s=c;
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+function u(){return{restrict:"A",link:function(e,t,a){var n={instance:null,value:{idGoal:a.piwikGoalPageLink},oldValue:null,modifiers:{},dir:{}};s.mounted(t[0],n)}}}l["Matomo"].on("Matomo.processDynamicHtml",(function(e){e.find("[goal-page-link]").each((function(e,t){if(!i(t).attr("goal-page-link-handled")){var a=i(t).attr("goal-page-link");a&&c.mounted(t,{instance:null,value:{idGoal:a},oldValue:null,modifiers:{},dir:{}}),i(t).attr("goal-page-link-handled","1")}}))})),window.angular.module("piwikApp").directive("piwikGoalPageLink",u);var d=a("8bbf"),b={id:"entityEditContainer",feature:"true",class:"managegoals"},p={class:"contentHelp"},m=["innerHTML"],O={key:0},j=Object(d["createElementVNode"])("br",null,null,-1),g=Object(d["createElementVNode"])("br",null,null,-1),h=["innerHTML"],v={class:"first"},y={key:1},f={key:2},_={key:0},G={colspan:"8"},E=Object(d["createElementVNode"])("br",null,null,-1),V=Object(d["createElementVNode"])("br",null,null,-1),N=Object(d["createElementVNode"])("br",null,null,-1),w=["id"],T={class:"first"},S={class:"matchAttribute"},k={key:0},D={key:1},C=Object(d["createElementVNode"])("br",null,null,-1),x=["innerHTML"],A={key:1,style:{"padding-top":"2px"}},M=["onClick","title"],B=Object(d["createElementVNode"])("span",{class:"icon-edit"},null,-1),L=[B],P={key:2,style:{"padding-top":"2px"}},H=["onClick","title"],F=Object(d["createElementVNode"])("span",{class:"icon-delete"},null,-1),U=[F],R={key:0,class:"tableActionBar"},I=Object(d["createElementVNode"])("span",{class:"icon-add"},null,-1),J={class:"ui-confirm",ref:"confirm"},z=["value"],q=["value"],W={class:"addEditGoal"},Y=["innerHTML"],K={class:"row goalIsTriggeredWhen"},Q={class:"col s12"},X={class:"row"},Z={class:"col s12 m6 goalTriggerType"},ee={class:"col s12 m6"},te=["innerHTML"],ae={class:"row whereTheMatchAttrbiute"},ne={class:"col s12"},oe={class:"row"},le={class:"col s12 m6 l4"},re={key:0,class:"col s12 m6 l4"},ie={key:1,class:"col s12 m6 l4"},ce={class:"col s12 m6 l4"},se={id:"examples_pattern",class:"col s12"},ue=Object(d["createElementVNode"])("br",null,null,-1),de=Object(d["createElementVNode"])("br",null,null,-1),be=Object(d["createElementVNode"])("br",null,null,-1),pe=Object(d["createElementVNode"])("br",null,null,-1),me=Object(d["createElementVNode"])("br",null,null,-1),Oe=Object(d["createElementVNode"])("br",null,null,-1),je=Object(d["createElementVNode"])("br",null,null,-1),ge=Object(d["createElementVNode"])("br",null,null,-1),he={ref:"endedittable"},ve=Object(d["createElementVNode"])("input",{type:"hidden",name:"goalIdUpdate",value:""},null,-1),ye={key:0},fe=["innerHTML"],_e=Object(d["createElementVNode"])("a",{id:"bottom"},null,-1);function Ge(e,t,a,n,o,l){var r,i=Object(d["resolveComponent"])("ActivityIndicator"),c=Object(d["resolveComponent"])("ContentBlock"),s=Object(d["resolveComponent"])("Field"),u=Object(d["resolveComponent"])("Alert"),B=Object(d["resolveComponent"])("SaveButton"),F=Object(d["resolveDirective"])("content-table"),$=Object(d["resolveDirective"])("form");return Object(d["openBlock"])(),Object(d["createElementBlock"])("div",null,[Object(d["withDirectives"])(Object(d["createElementVNode"])("div",null,[Object(d["withDirectives"])(Object(d["createElementVNode"])("div",b,[Object(d["createVNode"])(c,{"content-title":e.translate("Goals_ManageGoals")},{default:Object(d["withCtx"])((function(){return[Object(d["createVNode"])(i,{loading:e.isLoading},null,8,["loading"]),Object(d["createElementVNode"])("div",p,[Object(d["createElementVNode"])("span",{innerHTML:e.$sanitize(e.learnMoreAboutGoalTracking)},null,8,m),e.ecommerceEnabled?Object(d["createCommentVNode"])("",!0):(Object(d["openBlock"])(),Object(d["createElementBlock"])("span",O,[j,g,Object(d["createTextVNode"])(" "+Object(d["toDisplayString"])(e.translate("Goals_Optional"))+" "+Object(d["toDisplayString"])(e.translate("Goals_Ecommerce"))+": ",1),Object(d["createElementVNode"])("span",{innerHTML:e.$sanitize(e.youCanEnableEcommerceReports)},null,8,h)]))]),Object(d["withDirectives"])(Object(d["createElementVNode"])("table",null,[Object(d["createElementVNode"])("thead",null,[Object(d["createElementVNode"])("tr",null,[Object(d["createElementVNode"])("th",v,Object(d["toDisplayString"])(e.translate("General_Id")),1),Object(d["createElementVNode"])("th",null,Object(d["toDisplayString"])(e.translate("Goals_GoalName")),1),Object(d["createElementVNode"])("th",null,Object(d["toDisplayString"])(e.translate("General_Description")),1),Object(d["createElementVNode"])("th",null,Object(d["toDisplayString"])(e.translate("Goals_GoalIsTriggeredWhen")),1),Object(d["createElementVNode"])("th",null,Object(d["toDisplayString"])(e.translate("General_ColumnRevenue")),1),e.beforeGoalListActionsHeadComponent?(Object(d["openBlock"])(),Object(d["createBlock"])(Object(d["resolveDynamicComponent"])(e.beforeGoalListActionsHeadComponent),{key:0})):Object(d["createCommentVNode"])("",!0),e.userCanEditGoals?(Object(d["openBlock"])(),Object(d["createElementBlock"])("th",y,Object(d["toDisplayString"])(e.translate("General_Edit")),1)):Object(d["createCommentVNode"])("",!0),e.userCanEditGoals?(Object(d["openBlock"])(),Object(d["createElementBlock"])("th",f,Object(d["toDisplayString"])(e.translate("General_Delete")),1)):Object(d["createCommentVNode"])("",!0)])]),Object(d["createElementVNode"])("tbody",null,[Object.keys(e.goals||{}).length?Object(d["createCommentVNode"])("",!0):(Object(d["openBlock"])(),Object(d["createElementBlock"])("tr",_,[Object(d["createElementVNode"])("td",G,[E,Object(d["createTextVNode"])(" "+Object(d["toDisplayString"])(e.translate("Goals_ThereIsNoGoalToManage",e.siteName))+" ",1),V,N])])),(Object(d["openBlock"])(!0),Object(d["createElementBlock"])(d["Fragment"],null,Object(d["renderList"])(e.goals||[],(function(t){return Object(d["openBlock"])(),Object(d["createElementBlock"])("tr",{id:t.idgoal,key:t.idgoal},[Object(d["createElementVNode"])("td",T,Object(d["toDisplayString"])(t.idgoal),1),Object(d["createElementVNode"])("td",null,Object(d["toDisplayString"])(t.name),1),Object(d["createElementVNode"])("td",null,Object(d["toDisplayString"])(t.description),1),Object(d["createElementVNode"])("td",null,[Object(d["createElementVNode"])("span",S,Object(d["toDisplayString"])(e.goalMatchAttributeTranslations[t.match_attribute]||t.match_attribute),1),"visit_duration"===t.match_attribute?(Object(d["openBlock"])(),Object(d["createElementBlock"])("span",k,Object(d["toDisplayString"])(e.lcfirst(e.translate("General_OperationGreaterThan")))+" "+Object(d["toDisplayString"])(e.translate("Intl_NMinutes",t.pattern)),1)):t.pattern_type?(Object(d["openBlock"])(),Object(d["createElementBlock"])("span",D,[C,Object(d["createTextVNode"])(" "+Object(d["toDisplayString"])(e.translate("Goals_Pattern"))+" "+Object(d["toDisplayString"])(t.pattern_type)+": "+Object(d["toDisplayString"])(t.pattern),1)])):Object(d["createCommentVNode"])("",!0)]),Object(d["createElementVNode"])("td",{class:"center",innerHTML:e.$sanitize(0===t.revenue||"0"===t.revenue?"-":t.revenue_pretty)},null,8,x),e.beforeGoalListActionsBodyComponent[t.idgoal]?(Object(d["openBlock"])(),Object(d["createBlock"])(Object(d["resolveDynamicComponent"])(e.beforeGoalListActionsBodyComponent[t.idgoal]),{key:0})):Object(d["createCommentVNode"])("",!0),e.userCanEditGoals?(Object(d["openBlock"])(),Object(d["createElementBlock"])("td",A,[Object(d["createElementVNode"])("button",{onClick:function(a){return e.editGoal(t.idgoal)},class:"table-action",title:e.translate("General_Edit")},L,8,M)])):Object(d["createCommentVNode"])("",!0),e.userCanEditGoals?(Object(d["openBlock"])(),Object(d["createElementBlock"])("td",P,[Object(d["createElementVNode"])("button",{onClick:function(a){return e.deleteGoal(t.idgoal)},class:"table-action",title:e.translate("General_Delete")},U,8,H)])):Object(d["createCommentVNode"])("",!0)],8,w)})),128))])],512),[[F]]),e.userCanEditGoals&&!e.onlyShowAddNewGoal?(Object(d["openBlock"])(),Object(d["createElementBlock"])("div",R,[Object(d["createElementVNode"])("button",{id:"add-goal",onClick:t[0]||(t[0]=function(t){return e.createGoal()})},[I,Object(d["createTextVNode"])(" "+Object(d["toDisplayString"])(e.translate("Goals_AddNewGoal")),1)])])):Object(d["createCommentVNode"])("",!0)]})),_:1},8,["content-title"])],512),[[d["vShow"],e.showGoalList]]),Object(d["createElementVNode"])("div",J,[Object(d["createElementVNode"])("h2",null,Object(d["toDisplayString"])(e.translate("Goals_DeleteGoalConfirm",'"'.concat(null===(r=e.goalToDelete)||void 0===r?void 0:r.name,'"'))),1),Object(d["createElementVNode"])("input",{role:"yes",type:"button",value:e.translate("General_Yes")},null,8,z),Object(d["createElementVNode"])("input",{role:"no",type:"button",value:e.translate("General_No")},null,8,q)],512)],512),[[d["vShow"],!e.onlyShowAddNewGoal]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("div",null,[Object(d["withDirectives"])(Object(d["createElementVNode"])("div",W,[Object(d["createVNode"])(c,{"content-title":e.goal.idgoal?e.translate("Goals_UpdateGoal"):e.translate("Goals_AddNewGoal")},{default:Object(d["withCtx"])((function(){return[Object(d["createElementVNode"])("div",{innerHTML:e.$sanitize(e.addNewGoalIntro)},null,8,Y),Object(d["withDirectives"])(Object(d["createElementVNode"])("div",null,[Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(s,{uicontrol:"text",name:"goal_name",modelValue:e.goal.name,"onUpdate:modelValue":t[1]||(t[1]=function(t){return e.goal.name=t}),maxlength:50,title:e.translate("Goals_GoalName")},null,8,["modelValue","title"])]),Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(s,{uicontrol:"text",name:"goal_description",modelValue:e.goal.description,"onUpdate:modelValue":t[2]||(t[2]=function(t){return e.goal.description=t}),maxlength:255,title:e.translate("General_Description")},null,8,["modelValue","title"])]),Object(d["createElementVNode"])("div",K,[Object(d["createElementVNode"])("div",Q,[Object(d["createElementVNode"])("h3",null,Object(d["toDisplayString"])(e.translate("Goals_GoalIsTriggered")),1)])]),Object(d["createElementVNode"])("div",X,[Object(d["createElementVNode"])("div",Z,[Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(s,{uicontrol:"select",name:"trigger_type","model-value":e.triggerType,"onUpdate:modelValue":t[3]||(t[3]=function(t){e.triggerType=t,e.changedTriggerType()}),"full-width":!0,options:e.goalTriggerTypeOptions},null,8,["model-value","options"])])]),Object(d["createElementVNode"])("div",ee,[Object(d["withDirectives"])(Object(d["createVNode"])(u,{severity:"info"},{default:Object(d["withCtx"])((function(){return[Object(d["createElementVNode"])("span",{innerHTML:e.$sanitize(e.whereVisitedPageManuallyCallsJsTrackerText)},null,8,te)]})),_:1},512),[[d["vShow"],"manually"===e.triggerType]]),Object(d["createElementVNode"])("div",null,[Object(d["withDirectives"])(Object(d["createVNode"])(s,{uicontrol:"radio",name:"match_attribute","full-width":!0,"model-value":e.goal.match_attribute,"onUpdate:modelValue":t[4]||(t[4]=function(t){e.goal.match_attribute=t,e.initPatternType()}),options:e.goalMatchAttributeOptions},null,8,["model-value","options"]),[[d["vShow"],"manually"!==e.triggerType]])])])]),Object(d["withDirectives"])(Object(d["createElementVNode"])("div",ae,[Object(d["createElementVNode"])("h3",ne,[Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("Goals_WhereThe"))+" ",1),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,Object(d["toDisplayString"])(e.translate("Goals_URL")),513),[[d["vShow"],"url"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,Object(d["toDisplayString"])(e.translate("Goals_PageTitle")),513),[[d["vShow"],"title"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,Object(d["toDisplayString"])(e.translate("Goals_Filename")),513),[[d["vShow"],"file"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,Object(d["toDisplayString"])(e.translate("Goals_ExternalWebsiteUrl")),513),[[d["vShow"],"external_website"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,Object(d["toDisplayString"])(e.translate("Goals_VisitDuration")),513),[[d["vShow"],"visit_duration"===e.goal.match_attribute]])])],512),[[d["vShow"],"manually"!==e.triggerType]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("div",oe,[Object(d["withDirectives"])(Object(d["createElementVNode"])("div",le,[Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(s,{uicontrol:"select",name:"event_type",modelValue:e.eventType,"onUpdate:modelValue":t[5]||(t[5]=function(t){return e.eventType=t}),"full-width":!0,options:e.eventTypeOptions},null,8,["modelValue","options"])])],512),[[d["vShow"],"event"===e.goal.match_attribute]]),e.isMatchAttributeNumeric?Object(d["createCommentVNode"])("",!0):(Object(d["openBlock"])(),Object(d["createElementBlock"])("div",re,[Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(s,{uicontrol:"select",name:"pattern_type",modelValue:e.goal.pattern_type,"onUpdate:modelValue":t[6]||(t[6]=function(t){return e.goal.pattern_type=t}),"full-width":!0,options:e.patternTypeOptions},null,8,["modelValue","options"])])])),e.isMatchAttributeNumeric?(Object(d["openBlock"])(),Object(d["createElementBlock"])("div",ie,[Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(s,{uicontrol:"select",name:"pattern_type",modelValue:e.goal.pattern_type,"onUpdate:modelValue":t[7]||(t[7]=function(t){return e.goal.pattern_type=t}),"full-width":!0,options:e.numericComparisonTypeOptions},null,8,["modelValue","options"])])])):Object(d["createCommentVNode"])("",!0),Object(d["createElementVNode"])("div",ce,[Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(s,{uicontrol:"text",name:"pattern",modelValue:e.goal.pattern,"onUpdate:modelValue":t[8]||(t[8]=function(t){return e.goal.pattern=t}),maxlength:255,title:e.patternFieldLabel,"full-width":!0},null,8,["modelValue","title"])])]),Object(d["createElementVNode"])("div",se,[Object(d["createVNode"])(u,{severity:"info"},{default:Object(d["withCtx"])((function(){return[Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,[Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_Contains","'checkout/confirmation'"))+" ",1),ue,Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_IsExactly","'http://example.com/thank-you.html'"))+" ",1),de,Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_MatchesExpression","'(.*)\\/demo\\/(.*)'")),1)],512),[[d["vShow"],"url"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_Contains","'Order confirmation'")),513),[[d["vShow"],"title"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,[Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_Contains","'files/brochure.pdf'"))+" ",1),be,Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_IsExactly","'http://example.com/files/brochure.pdf'"))+" ",1),pe,Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_MatchesExpression","'(.*)\\.zip'")),1)],512),[[d["vShow"],"file"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,[Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_Contains","'amazon.com'"))+" ",1),me,Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_IsExactly","'http://mypartner.com/landing.html'"))+" ",1),Oe,Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.matchesExpressionExternal),1)],512),[[d["vShow"],"external_website"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,[Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_Contains","'video'"))+" ",1),je,Object(d["createTextVNode"])(" "+Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_IsExactly","'click'"))+" ",1),ge,Object(d["createTextVNode"])(Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_MatchesExpression","'(.*)_banner'"))+'" ',1)],512),[[d["vShow"],"event"===e.goal.match_attribute]]),Object(d["withDirectives"])(Object(d["createElementVNode"])("span",null,Object(d["toDisplayString"])(e.translate("General_ForExampleShort"))+" "+Object(d["toDisplayString"])(e.translate("Goals_AtLeastMinutes","5","0.5")),513),[[d["vShow"],"visit_duration"===e.goal.match_attribute]])]})),_:1})])],512),[[d["vShow"],"manually"!==e.triggerType]]),Object(d["createElementVNode"])("div",null,[Object(d["withDirectives"])(Object(d["createVNode"])(s,{uicontrol:"checkbox",name:"case_sensitive",modelValue:e.goal.case_sensitive,"onUpdate:modelValue":t[9]||(t[9]=function(t){return e.goal.case_sensitive=t}),title:e.caseSensitiveTitle},null,8,["modelValue","title"]),[[d["vShow"],"manually"!==e.triggerType&&!e.isMatchAttributeNumeric]])]),Object(d["createElementVNode"])("div",null,["visit_duration"!==e.goal.match_attribute?(Object(d["openBlock"])(),Object(d["createBlock"])(s,{key:0,uicontrol:"radio",name:"allow_multiple","model-value":e.goal.allow_multiple?1:0,"onUpdate:modelValue":t[10]||(t[10]=function(t){return e.goal.allow_multiple=t}),options:e.allowMultipleOptions,introduction:e.translate("Goals_AllowMultipleConversionsPerVisit"),"inline-help":e.translate("Goals_HelpOneConversionPerVisit")},null,8,["model-value","options","introduction","inline-help"])):Object(d["createCommentVNode"])("",!0)]),Object(d["createElementVNode"])("h3",null,Object(d["toDisplayString"])(e.translate("Goals_GoalRevenue"))+" "+Object(d["toDisplayString"])(e.translate("Goals_Optional")),1),Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(s,{uicontrol:"number",name:"revenue",modelValue:e.goal.revenue,"onUpdate:modelValue":t[11]||(t[11]=function(t){return e.goal.revenue=t}),placeholder:e.translate("Goals_DefaultRevenueLabel"),"inline-help":e.translate("Goals_DefaultRevenueHelp")},null,8,["modelValue","placeholder","inline-help"])]),Object(d["createElementVNode"])("div",null,[Object(d["withDirectives"])(Object(d["createVNode"])(s,{uicontrol:"checkbox",name:"use_event_value",modelValue:e.goal.event_value_as_revenue,"onUpdate:modelValue":t[12]||(t[12]=function(t){return e.goal.event_value_as_revenue=t}),title:e.translate("Goals_UseEventValueAsRevenue"),"inline-help":e.useEventValueAsRevenueHelp},null,8,["modelValue","title","inline-help"]),[[d["vShow"],"event"===e.goal.match_attribute]])]),Object(d["createElementVNode"])("div",he,[e.endEditTableComponent?(Object(d["openBlock"])(),Object(d["createBlock"])(Object(d["resolveDynamicComponent"])(e.endEditTableComponent),{key:0})):Object(d["createCommentVNode"])("",!0)],512),ve,Object(d["createVNode"])(B,{saving:e.isLoading,onConfirm:t[13]||(t[13]=function(t){return e.save()}),value:e.submitText},null,8,["saving","value"]),e.onlyShowAddNewGoal?Object(d["createCommentVNode"])("",!0):(Object(d["openBlock"])(),Object(d["createElementBlock"])("div",ye,[Object(d["withDirectives"])(Object(d["createElementVNode"])("div",{class:"entityCancel",onClick:t[14]||(t[14]=function(t){return e.showListOfReports()}),innerHTML:e.$sanitize(e.cancelText)},null,8,fe),[[d["vShow"],e.showEditGoal]])]))],512),[[$]])]})),_:1},8,["content-title"])],512),[[d["vShow"],e.showEditGoal]])],512),[[d["vShow"],e.userCanEditGoals]]),_e])}var Ee=a("a5a2");function Ve(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function Ne(e,t){for(var a=0;a
',"")},youCanEnableEcommerceReports:function(){var e=l["MatomoUrl"].stringify(Object.assign(Object.assign({},l["MatomoUrl"].urlParsed.value),{},{module:"SitesManager",action:"index"})),t=''.concat(Object(l["translate"])("Goals_EcommerceReports")," "),a="").concat(Object(l["translate"])("SitesManager_WebsitesManagement")," ");return Object(l["translate"])("Goals_YouCanEnableEcommerceReports",t,a)},siteName:function(){return l["Matomo"].helper.htmlDecode(l["Matomo"].siteName)},whereVisitedPageManuallyCallsJsTrackerText:function(){var e="https://developer.matomo.org/guides/tracking-javascript-guide#manually-trigger-goal-conversions";return Object(l["translate"])("Goals_WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore",'')," ")},caseSensitiveTitle:function(){return"".concat(Object(l["translate"])("Goals_CaseSensitive")," ").concat(Object(l["translate"])("Goals_Optional"))},useEventValueAsRevenueHelp:function(){return"".concat(Object(l["translate"])("Goals_EventValueAsRevenueHelp")," ").concat(Object(l["translate"])("Goals_EventValueAsRevenueHelp2"))},cancelText:function(){return Object(l["translate"])("General_OrCancel",""," ")},isMatchAttributeNumeric:function(){return["visit_duration"].indexOf(this.goal.match_attribute)>-1},patternFieldLabel:function(){return"visit_duration"===this.goal.match_attribute?Object(l["translate"])("Goals_TimeInMinutes"):Object(l["translate"])("Goals_Pattern")},goalMatchAttributeTranslations:function(){return{manually:Object(l["translate"])("Goals_ManuallyTriggeredUsingJavascriptFunction"),file:Object(l["translate"])("Goals_Download"),url:Object(l["translate"])("Goals_VisitUrl"),title:Object(l["translate"])("Goals_VisitPageTitle"),external_website:Object(l["translate"])("Goals_ClickOutlink"),event_action:"".concat(Object(l["translate"])("Goals_SendEvent")," (").concat(Object(l["translate"])("Events_EventAction"),")"),event_category:"".concat(Object(l["translate"])("Goals_SendEvent")," (").concat(Object(l["translate"])("Events_EventCategory"),")"),event_name:"".concat(Object(l["translate"])("Goals_SendEvent")," (").concat(Object(l["translate"])("Events_EventName"),")"),visit_duration:"".concat(this.ucfirst(Object(l["translate"])("Goals_VisitDuration")))}},beforeGoalListActionsBodyComponent:function(){var e=this;if(!this.beforeGoalListActionsBody)return{};var t={};return Object.values(this.goals).forEach((function(a){t[a.idgoal]={template:e.beforeGoalListActionsBody[a.idgoal]}})),Object(d["markRaw"])(t)},endEditTableComponent:function(){return this.endEditTable&&this.addEditTableComponent?Object(d["markRaw"])({template:this.endEditTable}):null},beforeGoalListActionsHeadComponent:function(){return this.beforeGoalListActionsHead?Object(d["markRaw"])({template:this.beforeGoalListActionsHead}):null},isManuallyTriggered:function(){return"manually"===this.triggerType},matchesExpressionExternal:function(){var e="'http://www.amazon.com\\/(.*)\\/yourAffiliateId'";return Object(l["translate"])("Goals_MatchesExpression",e)}}});ke.render=Ge;var De=ke;
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */Object(l["createAngularJsAdapter"])({component:De,directiveName:"piwikManageGoals",scope:{userCanEditGoals:{angularJsBind:"<"},onlyShowAddNewGoal:{angularJsBind:"<"},ecommerceEnabled:{angularJsBind:"<"},goals:{angularJsBind:"<"},showGoal:{angularJsBind:"<"},showAddGoal:{angularJsBind:"<"},addNewGoalIntro:{angularJsBind:"<"},goalTriggerTypeOptions:{angularJsBind:"<"},goalMatchAttributeOptions:{angularJsBind:"<"},eventTypeOptions:{angularJsBind:"<"},patternTypeOptions:{angularJsBind:"<"},numericComparisonTypeOptions:{angularJsBind:"<"},allowMultipleOptions:{angularJsBind:"<"},beforeGoalListActionsBody:{angularJsBind:"<"},endEditTable:{angularJsBind:"<"},beforeGoalListActionsHead:{angularJsBind:"<"}}})}})}));
+//# sourceMappingURL=Goals.umd.min.js.map
\ No newline at end of file
diff --git a/app/plugins/Goals/vue/dist/umd.metadata.json b/app/plugins/Goals/vue/dist/umd.metadata.json
new file mode 100644
index 000000000..dce4477a3
--- /dev/null
+++ b/app/plugins/Goals/vue/dist/umd.metadata.json
@@ -0,0 +1,6 @@
+{
+ "dependsOn": [
+ "CoreHome",
+ "CorePluginsAdmin"
+ ]
+}
\ No newline at end of file
diff --git a/app/plugins/Goals/vue/src/Goal.ts b/app/plugins/Goals/vue/src/Goal.ts
new file mode 100644
index 000000000..7609ea75e
--- /dev/null
+++ b/app/plugins/Goals/vue/src/Goal.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 Goal {
+ idgoal: string|number;
+ name: string;
+ allow_multiple: string|number|boolean;
+ case_sensitive: string|number|boolean;
+ deleted: string|number|boolean;
+ description: string;
+ event_value_as_revenue: string|number|boolean;
+ idsite: string|number;
+ match_attribute: string;
+ pattern: string;
+ pattern_type: string;
+ revenue: string|number;
+ revenue_pretty?: string;
+}
+
+export default Goal;
diff --git a/app/plugins/Goals/vue/src/GoalPageLink/GoalPageLink.adapter.ts b/app/plugins/Goals/vue/src/GoalPageLink/GoalPageLink.adapter.ts
new file mode 100644
index 000000000..5966c7f3c
--- /dev/null
+++ b/app/plugins/Goals/vue/src/GoalPageLink/GoalPageLink.adapter.ts
@@ -0,0 +1,30 @@
+/*!
+ * 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 GoalPageLink from './GoalPageLink';
+
+export default function piwikGoalPageLink(): IDirective {
+ return {
+ restrict: 'A',
+ link: function piwikGoalPageLinkLink(scope: IScope, element: JQuery, attrs: IAttributes) {
+ const binding = {
+ instance: null,
+ value: {
+ idGoal: attrs.piwikGoalPageLink,
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {},
+ };
+
+ GoalPageLink.mounted(element[0], binding);
+ },
+ };
+}
+
+window.angular.module('piwikApp').directive('piwikGoalPageLink', piwikGoalPageLink);
diff --git a/app/plugins/Goals/vue/src/GoalPageLink/GoalPageLink.ts b/app/plugins/Goals/vue/src/GoalPageLink/GoalPageLink.ts
new file mode 100644
index 000000000..c4a62da73
--- /dev/null
+++ b/app/plugins/Goals/vue/src/GoalPageLink/GoalPageLink.ts
@@ -0,0 +1,69 @@
+/*!
+ * 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 { Matomo, translate, MatomoUrl } from 'CoreHome';
+
+interface GoalPageLinkArgs {
+ idGoal: string|number;
+}
+
+const { $ } = window;
+
+// usage v-goal-page-link="{ idGoal: 5 }"
+const GoalPageLink = {
+ mounted(el: HTMLElement, binding: DirectiveBinding): void {
+ if (!Matomo.helper.isAngularRenderingThePage()) {
+ return;
+ }
+
+ const title = $(el).text();
+
+ const link = $(' ');
+ link.text(title);
+ link.attr('title', translate('Goals_ClickToViewThisGoal'));
+ link.click((e) => {
+ e.preventDefault();
+
+ MatomoUrl.updateHash({
+ ...MatomoUrl.hashParsed.value,
+ category: 'Goals_Goals',
+ subcategory: binding.value.idGoal,
+ });
+ });
+
+ $(el).html(link[0]);
+ },
+};
+
+export default GoalPageLink;
+
+// manually handle occurrence of goal-page-link on datatable html attributes since dataTable.js is
+// not managed by vue.
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+Matomo.on('Matomo.processDynamicHtml', ($element: JQuery) => {
+ $element.find('[goal-page-link]').each((i, e) => {
+ if ($(e).attr('goal-page-link-handled')) {
+ return;
+ }
+
+ const idGoal = $(e).attr('goal-page-link');
+ if (idGoal) {
+ GoalPageLink.mounted(e, {
+ instance: null,
+ value: {
+ idGoal,
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {},
+ });
+ }
+
+ $(e).attr('goal-page-link-handled', '1');
+ });
+});
diff --git a/app/plugins/Goals/vue/src/ManageGoals/ManageGoals.adapter.ts b/app/plugins/Goals/vue/src/ManageGoals/ManageGoals.adapter.ts
new file mode 100644
index 000000000..72237788a
--- /dev/null
+++ b/app/plugins/Goals/vue/src/ManageGoals/ManageGoals.adapter.ts
@@ -0,0 +1,64 @@
+/*!
+ * 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 'CoreHome';
+import ManageGoals from './ManageGoals.vue';
+
+export default createAngularJsAdapter({
+ component: ManageGoals,
+ directiveName: 'piwikManageGoals',
+ scope: {
+ userCanEditGoals: {
+ angularJsBind: '<',
+ },
+ onlyShowAddNewGoal: {
+ angularJsBind: '<',
+ },
+ ecommerceEnabled: {
+ angularJsBind: '<',
+ },
+ goals: {
+ angularJsBind: '<',
+ },
+ showGoal: {
+ angularJsBind: '<',
+ },
+ showAddGoal: {
+ angularJsBind: '<',
+ },
+ addNewGoalIntro: {
+ angularJsBind: '<',
+ },
+ goalTriggerTypeOptions: {
+ angularJsBind: '<',
+ },
+ goalMatchAttributeOptions: {
+ angularJsBind: '<',
+ },
+ eventTypeOptions: {
+ angularJsBind: '<',
+ },
+ patternTypeOptions: {
+ angularJsBind: '<',
+ },
+ numericComparisonTypeOptions: {
+ angularJsBind: '<',
+ },
+ allowMultipleOptions: {
+ angularJsBind: '<',
+ },
+ beforeGoalListActionsBody: {
+ angularJsBind: '<',
+ },
+ endEditTable: {
+ angularJsBind: '<',
+ },
+ beforeGoalListActionsHead: {
+ angularJsBind: '<',
+ },
+ },
+});
diff --git a/app/plugins/Goals/vue/src/ManageGoals/ManageGoals.vue b/app/plugins/Goals/vue/src/ManageGoals/ManageGoals.vue
new file mode 100644
index 000000000..af3ad41c3
--- /dev/null
+++ b/app/plugins/Goals/vue/src/ManageGoals/ManageGoals.vue
@@ -0,0 +1,821 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ translate('Goals_Optional') }} {{ translate('Goals_Ecommerce') }}:
+
+
+
+
+
+
+
+ {{ translate('General_Id') }}
+ {{ translate('Goals_GoalName') }}
+ {{ translate('General_Description') }}
+ {{ translate('Goals_GoalIsTriggeredWhen') }}
+ {{ translate('General_ColumnRevenue') }}
+
+
+
+ {{ translate('General_Edit') }}
+ {{ translate('General_Delete') }}
+
+
+
+
+
+
+ {{ translate('Goals_ThereIsNoGoalToManage', siteName) }}
+
+
+
+
+ {{ goal.idgoal }}
+ {{ goal.name }}
+ {{ goal.description }}
+
+
+ {{ goalMatchAttributeTranslations[goal.match_attribute]
+ || goal.match_attribute }}
+
+
+ {{ lcfirst(translate('General_OperationGreaterThan')) }}
+ {{ translate('Intl_NMinutes', goal.pattern) }}
+
+
+
+ {{ translate('Goals_Pattern') }} {{ goal.pattern_type }}: {{ goal.pattern }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ translate('Goals_AddNewGoal') }}
+
+
+
+
+
+
+
{{ translate('Goals_DeleteGoalConfirm', `"${goalToDelete?.name}"`) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ translate('Goals_GoalIsTriggered') }}
+
+
+
+
+
+
+
{{ translate('Goals_WhereThe') }}
+
+ {{ translate('Goals_URL') }}
+
+
+ {{ translate('Goals_PageTitle') }}
+
+
+ {{ translate('Goals_Filename') }}
+
+
+ {{ translate('Goals_ExternalWebsiteUrl') }}
+
+
+ {{ translate('Goals_VisitDuration') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_Contains', "'checkout/confirmation'") }}
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_IsExactly', "'http://example.com/thank-you.html'") }}
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_MatchesExpression', "'(.*)\\\/demo\\\/(.*)'") }}
+
+
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_Contains', "'Order confirmation'") }}
+
+
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_Contains', "'files/brochure.pdf'") }}
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_IsExactly', "'http://example.com/files/brochure.pdf'") }}
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_MatchesExpression', "'(.*)\\\.zip'") }}
+
+
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_Contains', "'amazon.com'") }}
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_IsExactly', "'http://mypartner.com/landing.html'") }}
+ {{ translate('General_ForExampleShort') }}
+ {{ matchesExpressionExternal }}
+
+
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_Contains', "'video'") }}
+
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_IsExactly', "'click'") }}
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_MatchesExpression', "'(.*)_banner'") }}"
+
+
+ {{ translate('General_ForExampleShort') }}
+ {{ translate('Goals_AtLeastMinutes', '5', '0.5') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{{ translate('Goals_GoalRevenue') }} {{ translate('Goals_Optional') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/plugins/Goals/vue/src/ManageGoals/PiwikApiMock.ts b/app/plugins/Goals/vue/src/ManageGoals/PiwikApiMock.ts
new file mode 100644
index 000000000..9745fe354
--- /dev/null
+++ b/app/plugins/Goals/vue/src/ManageGoals/PiwikApiMock.ts
@@ -0,0 +1,38 @@
+/*!
+* Matomo - free/libre analytics platform
+*
+* @link https://matomo.org
+* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+*/
+
+import { AjaxOptions } from 'CoreHome';
+
+// the piwikApi angularjs service is passed in some frontend events to allow plugins to modify
+// a request before it is sent. for the time being in Vue we use this mock, which has the same
+// API as the piwikApi service, to modify the input used with AjaxHelper. this provides BC
+// with for plugins that haven't been converted.
+//
+// should be removed in Matomo 5.
+export default class PiwikApiMock {
+ constructor(private parameters: QueryParameters, private options: AjaxOptions) {}
+
+ addParams(params: QueryParameters): void {
+ Object.assign(this.parameters, params);
+ }
+
+ withTokenInUrl(): void {
+ this.options.withTokenInUrl = true;
+ }
+
+ reset(): void {
+ Object.keys(this.parameters).forEach((name) => {
+ delete this.parameters[name];
+ });
+
+ delete this.options.postParams;
+ }
+
+ addPostParams(params: QueryParameters): void {
+ this.options.postParams = { ...this.options.postParams, ...params };
+ }
+}
diff --git a/app/plugins/Goals/vue/src/index.ts b/app/plugins/Goals/vue/src/index.ts
new file mode 100644
index 000000000..a79265133
--- /dev/null
+++ b/app/plugins/Goals/vue/src/index.ts
@@ -0,0 +1,12 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+*/
+
+import './GoalPageLink/GoalPageLink.adapter';
+import './ManageGoals/ManageGoals.adapter';
+
+export { default as GoalPageLink } from './GoalPageLink/GoalPageLink.ts';
+export { default as ManageGoals } from './ManageGoals/ManageGoals.vue';
diff --git a/app/plugins/ImageGraph/API.php b/app/plugins/ImageGraph/API.php
index 0a4863ecc..d326ef423 100644
--- a/app/plugins/ImageGraph/API.php
+++ b/app/plugins/ImageGraph/API.php
@@ -238,8 +238,18 @@ public function get(
$ordinateColumns = array();
if (empty($columns)) {
- $ordinateColumns[] =
- empty($reportColumns[self::DEFAULT_ORDINATE_METRIC]) ? key($metadata['metrics']) : self::DEFAULT_ORDINATE_METRIC;
+ if (!empty($reportColumns[self::DEFAULT_ORDINATE_METRIC])) {
+ $ordinateColumns[] = self::DEFAULT_ORDINATE_METRIC;
+ } else if (!empty($metadata['metrics'])) {
+ $ordinateColumns[] = key($metadata['metrics']);
+ } else {
+ throw new Exception(
+ Piwik::translate(
+ 'ImageGraph_ColumnOrdinateMissing',
+ array(self::DEFAULT_ORDINATE_METRIC, implode(',', array_keys($reportColumns)))
+ )
+ );
+ }
} else {
$ordinateColumns = explode(',', $columns);
foreach ($ordinateColumns as $column) {
diff --git a/app/plugins/ImageGraph/ImageGraph.php b/app/plugins/ImageGraph/ImageGraph.php
index 8669f32ff..f4139c91b 100644
--- a/app/plugins/ImageGraph/ImageGraph.php
+++ b/app/plugins/ImageGraph/ImageGraph.php
@@ -14,7 +14,6 @@
use Piwik\Container\StaticContainer;
use Piwik\Period;
use Piwik\Period\Range;
-use Piwik\Piwik;
use Piwik\Scheduler\Scheduler;
use Piwik\Site;
use Piwik\Url;
diff --git a/app/plugins/ImageGraph/lang/ga.json b/app/plugins/ImageGraph/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/ImageGraph/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Insights/Controller.php b/app/plugins/Insights/Controller.php
index 962790291..546cb783e 100644
--- a/app/plugins/Insights/Controller.php
+++ b/app/plugins/Insights/Controller.php
@@ -11,7 +11,6 @@
use Piwik\API\Request;
use Piwik\Common;
use Piwik\Piwik;
-use Piwik\Plugins\Insights\Visualizations\Insight;
use Piwik\View;
/**
diff --git a/app/plugins/Insights/DataTable/Filter/MinGrowth.php b/app/plugins/Insights/DataTable/Filter/MinGrowth.php
index b30bdf534..7d987909d 100644
--- a/app/plugins/Insights/DataTable/Filter/MinGrowth.php
+++ b/app/plugins/Insights/DataTable/Filter/MinGrowth.php
@@ -8,7 +8,6 @@
*/
namespace Piwik\Plugins\Insights\DataTable\Filter;
-use Piwik\DataTable;
use Piwik\DataTable\BaseFilter;
/**
diff --git a/app/plugins/Insights/Visualizations/Insight/RequestConfig.php b/app/plugins/Insights/Visualizations/Insight/RequestConfig.php
index b22953405..41d90825a 100644
--- a/app/plugins/Insights/Visualizations/Insight/RequestConfig.php
+++ b/app/plugins/Insights/Visualizations/Insight/RequestConfig.php
@@ -10,7 +10,6 @@
namespace Piwik\Plugins\Insights\Visualizations\Insight;
use Piwik\Plugins\Insights\InsightReport;
-use Piwik\Plugins\Insights\Visualizations\Insight;
use Piwik\ViewDataTable\RequestConfig as VisualizationRequestConfig;
class RequestConfig extends VisualizationRequestConfig
diff --git a/app/plugins/Insights/lang/ga.json b/app/plugins/Insights/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/Insights/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Installation/Controller.php b/app/plugins/Installation/Controller.php
index a26a42fe1..91b0283c1 100644
--- a/app/plugins/Installation/Controller.php
+++ b/app/plugins/Installation/Controller.php
@@ -118,6 +118,7 @@ function systemCheck()
/** @var DiagnosticService $diagnosticService */
$diagnosticService = StaticContainer::get('Piwik\Plugins\Diagnostics\DiagnosticService');
$view->diagnosticReport = $diagnosticService->runDiagnostics();
+ $view->isInstallation = true;
$view->showNextStep = !$view->diagnosticReport->hasErrors();
@@ -457,7 +458,6 @@ public function finished()
$view->addForm($form);
$view->showNextStep = false;
- $view->linkToProfessionalServices = StaticContainer::get('Piwik\ProfessionalServices\Advertising')->getPromoUrlForProfessionalServices($medium = 'App_InstallationFinished');
$output = $view->render();
return $output;
diff --git a/app/plugins/Installation/FormSuperUser.php b/app/plugins/Installation/FormSuperUser.php
index a434275ad..9f9799f31 100644
--- a/app/plugins/Installation/FormSuperUser.php
+++ b/app/plugins/Installation/FormSuperUser.php
@@ -11,7 +11,6 @@
use HTML_QuickForm2_DataSource_Array;
use HTML_QuickForm2_Factory;
use HTML_QuickForm2_Rule;
-use Piwik\Container\StaticContainer;
use Piwik\Piwik;
use Piwik\Plugins\UsersManager\UsersManager;
use Piwik\QuickForm2;
diff --git a/app/plugins/Installation/ServerFilesGenerator.php b/app/plugins/Installation/ServerFilesGenerator.php
index 45a072080..9c14da60b 100644
--- a/app/plugins/Installation/ServerFilesGenerator.php
+++ b/app/plugins/Installation/ServerFilesGenerator.php
@@ -44,7 +44,7 @@ public static function createHtAccessFiles()
"\n\n" .
"# Allow to serve static files which are safe\n" .
- "\n" .
+ "\n" .
$allow . "\n" .
" \n";
diff --git a/app/plugins/Installation/Widgets/GetSystemCheck.php b/app/plugins/Installation/Widgets/GetSystemCheck.php
index f79829d1c..23b481709 100644
--- a/app/plugins/Installation/Widgets/GetSystemCheck.php
+++ b/app/plugins/Installation/Widgets/GetSystemCheck.php
@@ -15,7 +15,6 @@
use Piwik\Plugins\Diagnostics\DiagnosticService;
use Piwik\Widget\Widget;
use Piwik\Widget\WidgetConfig;
-use Piwik\View;
class GetSystemCheck extends Widget
{
diff --git a/app/plugins/Installation/lang/ga.json b/app/plugins/Installation/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/Installation/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Installation/templates/_systemCheckSection.twig b/app/plugins/Installation/templates/_systemCheckSection.twig
index 88000e6f1..1fe5d0b3e 100644
--- a/app/plugins/Installation/templates/_systemCheckSection.twig
+++ b/app/plugins/Installation/templates/_systemCheckSection.twig
@@ -41,19 +41,19 @@
-
+
{{ local.diagnosticTable(diagnosticReport.getMandatoryDiagnosticResults()) }}
{{ 'Installation_Optional'|translate }}
-
+
{{ local.diagnosticTable(diagnosticReport.getOptionalDiagnosticResults()) }}
{{ 'Installation_InformationalResults'|translate }}
-
+
diff --git a/app/plugins/Installation/templates/finished.twig b/app/plugins/Installation/templates/finished.twig
index 52d7c8fd4..79d02318d 100644
--- a/app/plugins/Installation/templates/finished.twig
+++ b/app/plugins/Installation/templates/finished.twig
@@ -20,10 +20,10 @@
{% if areAdsForProfessionalServicesEnabled %}
{{ 'Installation_ProfessionalServicesAdTitle'|translate }}
- {{ 'Installation_ProfessionalServicesfessionalServicesAdText'|translate }}
+ {{ 'Installation_ProfessionalServicesfessionalServicesAdText'|translate('',' ','')|raw }}
- {{ 'Installation_ProfessionalServicesfessionalDiscoverHow'|translate('',' ')|raw }}
+ {{ 'Installation_ProfessionalServicesfessionalDiscoverHow'|translate('',' ')|raw }}
{% endif %}
diff --git a/app/plugins/Installation/templates/getSystemCheckWidget.twig b/app/plugins/Installation/templates/getSystemCheckWidget.twig
index ec6fc7242..a59bbebc9 100644
--- a/app/plugins/Installation/templates/getSystemCheckWidget.twig
+++ b/app/plugins/Installation/templates/getSystemCheckWidget.twig
@@ -5,16 +5,32 @@
{% if numErrors %}
- {% for error in errors %}
- {{ error.getLabel }}
+ {% for thisResult in errors %}
+ {% set checkItemMessages = '' %}
+ {% if thisResult.getLongErrorMessage is empty and thisResult.getItems()|length > 1 %}
+ {% for checkItem in thisResult.getItems() %}
+ {% if checkItem.getStatus is same as('warning') %}
+ {% set checkItemMessages = checkItemMessages ~ checkItem.getComment() %}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+ {{ thisResult.getLabel }}
{% endfor %}
{% endif %}
{% if numWarnings %}
- {% for warning in warnings %}
- {{ warning.getLabel }}
+ {% for thisResult in warnings %}
+ {% set checkItemMessages = '' %}
+ {% if thisResult.getLongErrorMessage is empty and thisResult.getItems()|length > 1 %}
+ {% for checkItem in thisResult.getItems() %}
+ {% if checkItem.getStatus is same as('warning') %}
+ {% set checkItemMessages = checkItemMessages ~ checkItem.getComment() %}
+ {% endif %}
+ {% endfor %}
+ {% endif %}
+ {{ thisResult.getLabel }}
{% endfor %}
{% endif %}
@@ -23,12 +39,12 @@
{{ 'Installation_SystemCheckViewFullSystemCheck'|translate }}
+ >{{ 'Installation_SystemCheckViewFullSystemCheck'|translate }}
{% endif %}
+
diff --git a/app/plugins/Intl/Commands/GenerateIntl.php b/app/plugins/Intl/Commands/GenerateIntl.php
index af7ad7903..ec035b40b 100644
--- a/app/plugins/Intl/Commands/GenerateIntl.php
+++ b/app/plugins/Intl/Commands/GenerateIntl.php
@@ -10,7 +10,6 @@
namespace Piwik\Plugins\Intl\Commands;
use DateTimeZone;
-use Piwik\Common;
use Piwik\Container\StaticContainer;
use Piwik\Development;
use Piwik\Filesystem;
@@ -41,6 +40,7 @@ protected function configure()
{
$this->setName('translations:generate-intl-data')
->addOption('language', 'l', InputOption::VALUE_OPTIONAL, 'language that should be fetched')
+ ->addOption('cldr-version', '', InputOption::VALUE_OPTIONAL, 'CLDR version to use for update')
->setDescription('Generates Intl-data for Piwik');
}
@@ -71,15 +71,17 @@ protected function execute(InputInterface $input, OutputInterface $output)
$matomoLanguages = [$input->getOption('language')];
}
+ if ($input->getOption('cldr-version')) {
+ $this->CLDRVersion = $input->getOption('cldr-version');
+ }
+
$aliasesUrl = 'https://raw.githubusercontent.com/unicode-org/cldr-json/%s/cldr-json/cldr-core/supplemental/aliases.json';
$aliasesData = Http::fetchRemoteFile(sprintf($aliasesUrl, $this->CLDRVersion));
$aliasesData = json_decode($aliasesData, true);
- $aliasesData = $aliasesData['supplemental']['metadata']['alias']['languageAlias'];
+ $aliasesData = $aliasesData['supplemental']['metadata']['alias']['languageAlias'] ?? [];
$this->checkCurrencies($output);
- $writePath = Filesystem::getPathToPiwikRoot() . '/plugins/Intl/lang/%s.json';
-
foreach ($matomoLanguages AS $langCode) {
if ($langCode == 'dev') {
@@ -151,7 +153,7 @@ protected function checkCurrencies(OutputInterface $output)
$currencyData = Http::fetchRemoteFile(sprintf($currencyDataUrl, $this->CLDRVersion, 'en'));
$currencyData = json_decode($currencyData, true);
- $currencyData = $currencyData['supplemental']['currencyData']['region'];
+ $currencyData = $currencyData['supplemental']['currencyData']['region'] ?? [];
$cldrCurrencies = array();
foreach ($currencyData as $region) {
@@ -188,7 +190,7 @@ protected function getEnglishLanguageName($code, $alternateCode)
if (empty($languageData)) {
$languageData = Http::fetchRemoteFile(sprintf($languageDataUrl, $this->CLDRVersion, 'en'));
$languageData = json_decode($languageData, true);
- $languageData = $languageData['main']['en']['localeDisplayNames']['languages'];
+ $languageData = $languageData['main']['en']['localeDisplayNames']['languages'] ?? [];
}
if (array_key_exists($code, $languageData) && $languageData[$code] != $code) {
@@ -213,7 +215,7 @@ protected function getEnglishLanguageName($code, $alternateCode)
try {
$territoryData = Http::fetchRemoteFile(sprintf($territoryDataUrl, $this->CLDRVersion, 'en'));
$territoryData = json_decode($territoryData, true);
- $territoryData = $territoryData['main']['en']['localeDisplayNames']['territories'];
+ $territoryData = $territoryData['main']['en']['localeDisplayNames']['territories'] ?? [];
if (array_key_exists($territory, $territoryData)) {
$englishName .= ' ('.$territoryData[$territory].')';
@@ -242,7 +244,7 @@ protected function fetchLanguageData(OutputInterface $output, $langCode, $reques
try {
$languageData = Http::fetchRemoteFile(sprintf($languageDataUrl, $this->CLDRVersion, $requestLangCode));
$languageData = json_decode($languageData, true);
- $languageData = $languageData['main'][$requestLangCode]['localeDisplayNames']['languages'];
+ $languageData = $languageData['main'][$requestLangCode]['localeDisplayNames']['languages'] ?? [];
if (empty($languageData)) {
throw new \Exception();
@@ -274,7 +276,7 @@ protected function fetchLayoutDirection(OutputInterface $output, $langCode, $req
try {
$layoutData = Http::fetchRemoteFile(sprintf($layoutDirectionUrl, $this->CLDRVersion, $requestLangCode));
$layoutData = json_decode($layoutData, true);
- $layoutData = $layoutData['main'][$requestLangCode]['layout']['orientation'];
+ $layoutData = $layoutData['main'][$requestLangCode]['layout']['orientation'] ?? [];
if (empty($layoutData)) {
throw new \Exception();
@@ -312,7 +314,7 @@ protected function fetchTerritoryData(OutputInterface $output, $langCode, $reque
try {
$territoryData = Http::fetchRemoteFile(sprintf($territoryDataUrl, $this->CLDRVersion, $requestLangCode));
$territoryData = json_decode($territoryData, true);
- $territoryData = $territoryData['main'][$requestLangCode]['localeDisplayNames']['territories'];
+ $territoryData = $territoryData['main'][$requestLangCode]['localeDisplayNames']['territories'] ?? [];
if (empty($territoryData)) {
throw new \Exception();
@@ -343,7 +345,7 @@ protected function fetchCalendarData(OutputInterface $output, $langCode, $reques
try {
$calendarData = Http::fetchRemoteFile(sprintf($calendarDataUrl, $this->CLDRVersion, $requestLangCode));
$calendarData = json_decode($calendarData, true);
- $calendarData = $calendarData['main'][$requestLangCode]['dates']['calendars']['gregorian'];
+ $calendarData = $calendarData['main'][$requestLangCode]['dates']['calendars']['gregorian'] ?? [];
if (empty($calendarData)) {
throw new \Exception();
@@ -419,7 +421,7 @@ protected function fetchCalendarData(OutputInterface $output, $langCode, $reques
try {
$dateFieldData = Http::fetchRemoteFile(sprintf($dateFieldsUrl, $this->CLDRVersion, $requestLangCode));
$dateFieldData = json_decode($dateFieldData, true);
- $dateFieldData = $dateFieldData['main'][$requestLangCode]['dates']['fields'];
+ $dateFieldData = $dateFieldData['main'][$requestLangCode]['dates']['fields'] ?? [];
if (empty($dateFieldData)) {
throw new \Exception();
@@ -446,7 +448,7 @@ protected function fetchTimeZoneData(OutputInterface $output, $langCode, $reques
try {
$timeZoneData = Http::fetchRemoteFile(sprintf($timeZoneDataUrl, $this->CLDRVersion, $requestLangCode));
$timeZoneData = json_decode($timeZoneData, true);
- $timeZoneData = $timeZoneData['main'][$requestLangCode]['dates']['timeZoneNames'];
+ $timeZoneData = $timeZoneData['main'][$requestLangCode]['dates']['timeZoneNames'] ?? [];
if (empty($timeZoneData)) {
throw new \Exception();
@@ -509,7 +511,7 @@ protected function fetchNumberFormattingData(OutputInterface $output, $langCode,
try {
$unitsData = Http::fetchRemoteFile(sprintf($unitsUrl, $this->CLDRVersion, $requestLangCode));
$unitsData = json_decode($unitsData, true);
- $unitsData = $unitsData['main'][$requestLangCode]['numbers'];
+ $unitsData = $unitsData['main'][$requestLangCode]['numbers'] ?? [];
if (empty($unitsData)) {
throw new \Exception();
@@ -539,7 +541,7 @@ protected function fetchUnitData(OutputInterface $output, $langCode, $requestLan
try {
$unitsData = Http::fetchRemoteFile(sprintf($unitsUrl, $this->CLDRVersion, $requestLangCode));
$unitsData = json_decode($unitsData, true);
- $unitsData = $unitsData['main'][$requestLangCode]['units'];
+ $unitsData = $unitsData['main'][$requestLangCode]['units'] ?? [];
if (empty($unitsData)) {
throw new \Exception();
@@ -597,7 +599,7 @@ protected function fetchCurrencyData(OutputInterface $output, $langCode, $reques
try {
$currencyData = Http::fetchRemoteFile(sprintf($currenciesUrl, $this->CLDRVersion, $requestLangCode));
$currencyData = json_decode($currencyData, true);
- $currencyData = $currencyData['main'][$requestLangCode]['numbers']['currencies'];
+ $currencyData = $currencyData['main'][$requestLangCode]['numbers']['currencies'] ?? [];
if (empty($currencyData)) {
throw new \Exception();
diff --git a/app/plugins/LanguagesManager/Commands/TranslationBase.php b/app/plugins/LanguagesManager/Commands/TranslationBase.php
index 5e47ae910..6a304f675 100644
--- a/app/plugins/LanguagesManager/Commands/TranslationBase.php
+++ b/app/plugins/LanguagesManager/Commands/TranslationBase.php
@@ -11,10 +11,6 @@
use Piwik\Development;
use Piwik\Plugin\ConsoleCommand;
-use Symfony\Component\Console\Input\ArrayInput;
-use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Input\InputOption;
-use Symfony\Component\Console\Output\OutputInterface;
/**
*/
diff --git a/app/plugins/LanguagesManager/LanguagesManager.php b/app/plugins/LanguagesManager/LanguagesManager.php
index 0dcfe9a29..a52a61303 100644
--- a/app/plugins/LanguagesManager/LanguagesManager.php
+++ b/app/plugins/LanguagesManager/LanguagesManager.php
@@ -11,11 +11,11 @@
use Exception;
use Piwik\API\Request;
+use Piwik\AssetManager\UIAssetFetcher\PluginUmdAssetFetcher;
use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
use Piwik\Cookie;
-use Piwik\Development;
use Piwik\Intl\Locale;
use Piwik\Nonce;
use Piwik\Piwik;
@@ -36,7 +36,6 @@ class LanguagesManager extends \Piwik\Plugin
public function registerEvents()
{
return array(
- 'AssetManager.getJavaScriptFiles' => 'getJsFiles',
'Config.NoConfigurationFile' => 'initLanguage',
'Request.dispatchCoreAndPluginUpdatesScreen' => 'initLanguage',
'Request.dispatch' => 'initLanguage',
@@ -58,13 +57,6 @@ public function getTablesInstalled(&$allTablesInstalled)
$allTablesInstalled[] = Common::prefixTable('user_language');
}
- public function getJsFiles(&$jsFiles)
- {
- $jsFiles[] = "plugins/LanguagesManager/angularjs/languageselector/languageselector.directive.js";
- $jsFiles[] = "plugins/LanguagesManager/angularjs/translationsearch/translationsearch.controller.js";
- $jsFiles[] = "plugins/LanguagesManager/angularjs/translationsearch/translationsearch.directive.js";
- }
-
/**
* Adds the languages drop-down list to topbars other than the main one rendered
* in CoreHome/templates/top_bar.twig. The 'other' topbars are on the Installation
@@ -74,7 +66,8 @@ public function addLanguagesManagerToOtherTopBar(&$str)
{
// piwik object & scripts aren't loaded in 'other' topbars
$str .= "";
- $str .= "";
+ $file = PluginUmdAssetFetcher::getUmdFileToUseForPlugin('LanguagesManager');
+ $str .= "";
$str .= $this->getLanguagesSelector();
}
diff --git a/app/plugins/LanguagesManager/TranslationWriter/Validate/NoScripts.php b/app/plugins/LanguagesManager/TranslationWriter/Validate/NoScripts.php
index 48afa1aad..78a56898e 100644
--- a/app/plugins/LanguagesManager/TranslationWriter/Validate/NoScripts.php
+++ b/app/plugins/LanguagesManager/TranslationWriter/Validate/NoScripts.php
@@ -1,4 +1,5 @@
0) {
$this->message = 'script tags restricted for language files';
return false;
}
diff --git a/app/plugins/LanguagesManager/angularjs/translationsearch/translationsearch.directive.html b/app/plugins/LanguagesManager/angularjs/translationsearch/translationsearch.directive.html
deleted file mode 100644
index e56b0d15e..000000000
--- a/app/plugins/LanguagesManager/angularjs/translationsearch/translationsearch.directive.html
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
- This page helps you to find existing translations that you can reuse in your Plugin.
- If you want to know more about translations have a look at our Internationalization guide .
- Enter a search term to find translations and their corresponding keys:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Key
- English translation
- Compare translation
-
-
-
-
- {{ translation.label }}
- {{ translation.value }}
- {{ translationSearch.compareTranslations[translation.label] }}
-
-
-
-
-
diff --git a/app/plugins/LanguagesManager/lang/ga.json b/app/plugins/LanguagesManager/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/LanguagesManager/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/LanguagesManager/templates/searchTranslation.twig b/app/plugins/LanguagesManager/templates/searchTranslation.twig
index d2b040f1b..c8ed0140d 100644
--- a/app/plugins/LanguagesManager/templates/searchTranslation.twig
+++ b/app/plugins/LanguagesManager/templates/searchTranslation.twig
@@ -4,8 +4,13 @@
{% block content %}
-
-
+
+
{% endblock %}
diff --git a/app/plugins/LanguagesManager/vue/dist/LanguagesManager.umd.js b/app/plugins/LanguagesManager/vue/dist/LanguagesManager.umd.js
new file mode 100644
index 000000000..0273a089d
--- /dev/null
+++ b/app/plugins/LanguagesManager/vue/dist/LanguagesManager.umd.js
@@ -0,0 +1,401 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("CoreHome"), require("vue"));
+ else if(typeof define === 'function' && define.amd)
+ define(["CoreHome", ], factory);
+ else if(typeof exports === 'object')
+ exports["LanguagesManager"] = factory(require("CoreHome"), require("vue"));
+ else
+ root["LanguagesManager"] = factory(root["CoreHome"], root["Vue"]);
+})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__, __WEBPACK_EXTERNAL_MODULE__8bbf__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "plugins/LanguagesManager/vue/dist/";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "fae3");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "19dc":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;
+
+/***/ }),
+
+/***/ "8bbf":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__8bbf__;
+
+/***/ }),
+
+/***/ "fae3":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, "TranslationSearch", function() { return /* reexport */ TranslationSearch; });
+__webpack_require__.d(__webpack_exports__, "LanguageSelector", function() { return /* reexport */ LanguageSelector; });
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
+// This file is imported into lib/wc client bundles.
+
+if (typeof window !== 'undefined') {
+ var currentScript = window.document.currentScript
+ if (false) { var getCurrentScript; }
+
+ var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
+ if (src) {
+ __webpack_require__.p = src[1] // eslint-disable-line
+ }
+}
+
+// Indicate to webpack that this file can be concatenated
+/* harmony default export */ var setPublicPath = (null);
+
+// CONCATENATED MODULE: ./plugins/LanguagesManager/vue/src/LanguageSelector/LanguageSelector.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 _window = window,
+ $ = _window.$;
+
+function postLanguageChange(element, event) {
+ var value = $(event.target).attr('value');
+
+ if (value) {
+ $(element).find('#language').val(value).parents('form').submit();
+ }
+}
+
+/* harmony default export */ var LanguageSelector = ({
+ mounted: function mounted(el, binding) {
+ binding.value.onClick = postLanguageChange.bind(null, el);
+ $(el).on('click', 'a[value]', binding.value.onClick);
+ },
+ unmounted: function unmounted(el, binding) {
+ $(el).off('click', 'a[value]', binding.value.onClick);
+ }
+});
+// CONCATENATED MODULE: ./plugins/LanguagesManager/vue/src/LanguageSelector/LanguageSelector.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 languageSelection() {
+ return {
+ restrict: 'C',
+ link: function languageSelectionLink(scope, element) {
+ var binding = {
+ instance: null,
+ value: {},
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ };
+ LanguageSelector.mounted(element[0], binding);
+ element.on('$destroy', function () {
+ LanguageSelector.unmounted(element[0], binding);
+ });
+ }
+ };
+}
+
+window.angular.module('piwikApp').directive('languageSelection', languageSelection);
+// EXTERNAL MODULE: external "CoreHome"
+var external_CoreHome_ = __webpack_require__("19dc");
+
+// EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"}
+var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf");
+
+// 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/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.vue?vue&type=template&id=3d477584
+
+
+var _hoisted_1 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("p", null, [/*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(" This page helps you to find existing translations that you can reuse in your Plugin. If you want to know more about translations have a look at our "), /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("a", {
+ href: "https://developer.matomo.org/guides/internationalization",
+ rel: "noreferrer noopener",
+ target: "_blank"
+}, "Internationalization guide"), /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createTextVNode"])(". Enter a search term to find translations and their corresponding keys: ")], -1);
+
+var _hoisted_2 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_3 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("br", null, null, -1);
+
+var _hoisted_4 = {
+ style: {
+ "word-break": "break-all"
+ }
+};
+
+var _hoisted_5 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", {
+ style: {
+ "width": "250px"
+ }
+}, "Key", -1);
+
+var _hoisted_6 = /*#__PURE__*/Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, "English translation", -1);
+
+var _hoisted_7 = {
+ key: 0
+};
+function render(_ctx, _cache, $props, $setup, $data, $options) {
+ var _component_Field = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveComponent"])("Field");
+
+ var _directive_content_table = Object(external_commonjs_vue_commonjs2_vue_root_Vue_["resolveDirective"])("content-table");
+
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("div", null, [_hoisted_1, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "text",
+ name: "alias",
+ "inline-help": "Search for English translation. Max 1000 results will be shown.",
+ placeholder: "Search for English translation",
+ modelValue: _ctx.searchTerm,
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = function ($event) {
+ return _ctx.searchTerm = $event;
+ })
+ }, null, 8, ["modelValue"])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("div", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createVNode"])(_component_Field, {
+ uicontrol: "select",
+ name: "translationSearch.compareLanguage",
+ "inline-help": "Optionally select a language to compare the English language with.",
+ "model-value": _ctx.compareLanguage,
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = function ($event) {
+ _ctx.compareLanguage = $event;
+
+ _ctx.doCompareLanguage();
+ }),
+ options: _ctx.languages
+ }, null, 8, ["model-value", "options"])]), _hoisted_2, _hoisted_3, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("table", _hoisted_4, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("thead", null, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("tr", null, [_hoisted_5, _hoisted_6, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["withDirectives"])(Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("th", null, "Compare translation", 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.compareLanguage && _ctx.compareTranslations]])])]), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("tbody", 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.filteredTranslations, function (translation) {
+ return Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("tr", {
+ key: translation.label
+ }, [Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(translation.label), 1), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementVNode"])("td", null, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(translation.value), 1), _ctx.compareLanguage && _ctx.compareTranslations ? (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["openBlock"])(), Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createElementBlock"])("td", _hoisted_7, Object(external_commonjs_vue_commonjs2_vue_root_Vue_["toDisplayString"])(_ctx.compareTranslations[translation.label]), 1)) : Object(external_commonjs_vue_commonjs2_vue_root_Vue_["createCommentVNode"])("", true)]);
+ }), 128))])], 512), [[external_commonjs_vue_commonjs2_vue_root_Vue_["vShow"], _ctx.searchTerm], [_directive_content_table]])]);
+}
+// CONCATENATED MODULE: ./plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.vue?vue&type=template&id=3d477584
+
+// 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/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.vue?vue&type=script&lang=ts
+
+ // loading a component this way since during Installation we don't want to load CorePluginsAdmin
+// just for the language selector directive
+
+var Field = Object(external_CoreHome_["useExternalPluginComponent"])('CorePluginsAdmin', 'Field');
+/* harmony default export */ var TranslationSearchvue_type_script_lang_ts = (Object(external_commonjs_vue_commonjs2_vue_root_Vue_["defineComponent"])({
+ components: {
+ Field: Field
+ },
+ directives: {
+ ContentTable: external_CoreHome_["ContentTable"]
+ },
+ data: function data() {
+ return {
+ compareTranslations: null,
+ existingTranslations: [],
+ languages: [],
+ compareLanguage: '',
+ searchTerm: ''
+ };
+ },
+ created: function created() {
+ this.fetchTranslations('en');
+ this.fetchLanguages();
+ },
+ methods: {
+ fetchTranslations: function fetchTranslations(languageCode) {
+ var _this = this;
+
+ external_CoreHome_["AjaxHelper"].fetch({
+ method: 'LanguagesManager.getTranslationsForLanguage',
+ filter_limit: -1,
+ languageCode: languageCode
+ }).then(function (response) {
+ if (!response) {
+ return;
+ }
+
+ if (languageCode === 'en') {
+ _this.existingTranslations = response;
+ } else {
+ _this.compareTranslations = {};
+ response.forEach(function (translation) {
+ _this.compareTranslations[translation.label] = translation.value;
+ });
+ }
+ });
+ },
+ fetchLanguages: function fetchLanguages() {
+ var _this2 = this;
+
+ external_CoreHome_["AjaxHelper"].fetch({
+ method: 'LanguagesManager.getAvailableLanguagesInfo',
+ filter_limit: -1
+ }).then(function (languages) {
+ _this2.languages = [{
+ key: '',
+ value: 'None'
+ }];
+
+ if (languages) {
+ languages.forEach(function (language) {
+ if (language.code === 'en') {
+ return;
+ }
+
+ _this2.languages.push({
+ key: language.code,
+ value: language.name
+ });
+ });
+ }
+ });
+ },
+ doCompareLanguage: function doCompareLanguage() {
+ if (this.compareLanguage) {
+ this.compareTranslations = null;
+ this.fetchTranslations(this.compareLanguage);
+ }
+ }
+ },
+ computed: {
+ filteredTranslations: function filteredTranslations() {
+ var _this3 = this;
+
+ var filtered = this.existingTranslations.filter(function (t) {
+ return t.label.includes(_this3.searchTerm) || t.value.includes(_this3.searchTerm);
+ });
+ filtered = filtered.slice(0, 1000);
+ return filtered;
+ }
+ }
+}));
+// CONCATENATED MODULE: ./plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.vue?vue&type=script&lang=ts
+
+// CONCATENATED MODULE: ./plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.vue
+
+
+
+TranslationSearchvue_type_script_lang_ts.render = render
+
+/* harmony default export */ var TranslationSearch = (TranslationSearchvue_type_script_lang_ts);
+// CONCATENATED MODULE: ./plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.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 TranslationSearch_adapter = (Object(external_CoreHome_["createAngularJsAdapter"])({
+ component: TranslationSearch,
+ directiveName: 'piwikTranslationSearch'
+}));
+// CONCATENATED MODULE: ./plugins/LanguagesManager/vue/src/index.ts
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js
+
+
+
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=LanguagesManager.umd.js.map
\ No newline at end of file
diff --git a/app/plugins/LanguagesManager/vue/dist/LanguagesManager.umd.min.js b/app/plugins/LanguagesManager/vue/dist/LanguagesManager.umd.min.js
new file mode 100644
index 000000000..e07348f41
--- /dev/null
+++ b/app/plugins/LanguagesManager/vue/dist/LanguagesManager.umd.min.js
@@ -0,0 +1,20 @@
+(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome"),require("vue")):"function"===typeof define&&define.amd?define(["CoreHome"],t):"object"===typeof exports?exports["LanguagesManager"]=t(require("CoreHome"),require("vue")):e["LanguagesManager"]=t(e["CoreHome"],e["Vue"])})("undefined"!==typeof self?self:this,(function(e,t){return function(e){var t={};function n(a){if(t[a])return t[a].exports;var o=t[a]={i:a,l:!1,exports:{}};return e[a].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,a){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:a})},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 a=Object.create(null);if(n.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(a,o,function(t){return e[t]}.bind(null,o));return a},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/LanguagesManager/vue/dist/",n(n.s="fae3")}({"19dc":function(t,n){t.exports=e},"8bbf":function(e,n){e.exports=t},fae3:function(e,t,n){"use strict";if(n.r(t),n.d(t,"TranslationSearch",(function(){return T})),n.d(t,"LanguageSelector",(function(){return c})),"undefined"!==typeof window){var a=window.document.currentScript,o=a&&a.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);o&&(n.p=o[1])}var r=window,l=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 i(e,t){var n=l(t.target).attr("value");n&&l(e).find("#language").val(n).parents("form").submit()}var c={mounted:function(e,t){t.value.onClick=i.bind(null,e),l(e).on("click","a[value]",t.value.onClick)},unmounted:function(e,t){l(e).off("click","a[value]",t.value.onClick)}};
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */function u(){return{restrict:"C",link:function(e,t){var n={instance:null,value:{},oldValue:null,modifiers:{},dir:{}};c.mounted(t[0],n),t.on("$destroy",(function(){c.unmounted(t[0],n)}))}}}window.angular.module("piwikApp").directive("languageSelection",u);var s=n("19dc"),d=n("8bbf"),f=Object(d["createElementVNode"])("p",null,[Object(d["createTextVNode"])(" This page helps you to find existing translations that you can reuse in your Plugin. If you want to know more about translations have a look at our "),Object(d["createElementVNode"])("a",{href:"https://developer.matomo.org/guides/internationalization",rel:"noreferrer noopener",target:"_blank"},"Internationalization guide"),Object(d["createTextVNode"])(". Enter a search term to find translations and their corresponding keys: ")],-1),g=Object(d["createElementVNode"])("br",null,null,-1),m=Object(d["createElementVNode"])("br",null,null,-1),p={style:{"word-break":"break-all"}},b=Object(d["createElementVNode"])("th",{style:{width:"250px"}},"Key",-1),h=Object(d["createElementVNode"])("th",null,"English translation",-1),v={key:0};function j(e,t,n,a,o,r){var l=Object(d["resolveComponent"])("Field"),i=Object(d["resolveDirective"])("content-table");return Object(d["openBlock"])(),Object(d["createElementBlock"])("div",null,[f,Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(l,{uicontrol:"text",name:"alias","inline-help":"Search for English translation. Max 1000 results will be shown.",placeholder:"Search for English translation",modelValue:e.searchTerm,"onUpdate:modelValue":t[0]||(t[0]=function(t){return e.searchTerm=t})},null,8,["modelValue"])]),Object(d["createElementVNode"])("div",null,[Object(d["createVNode"])(l,{uicontrol:"select",name:"translationSearch.compareLanguage","inline-help":"Optionally select a language to compare the English language with.","model-value":e.compareLanguage,"onUpdate:modelValue":t[1]||(t[1]=function(t){e.compareLanguage=t,e.doCompareLanguage()}),options:e.languages},null,8,["model-value","options"])]),g,m,Object(d["withDirectives"])(Object(d["createElementVNode"])("table",p,[Object(d["createElementVNode"])("thead",null,[Object(d["createElementVNode"])("tr",null,[b,h,Object(d["withDirectives"])(Object(d["createElementVNode"])("th",null,"Compare translation",512),[[d["vShow"],e.compareLanguage&&e.compareTranslations]])])]),Object(d["createElementVNode"])("tbody",null,[(Object(d["openBlock"])(!0),Object(d["createElementBlock"])(d["Fragment"],null,Object(d["renderList"])(e.filteredTranslations,(function(t){return Object(d["openBlock"])(),Object(d["createElementBlock"])("tr",{key:t.label},[Object(d["createElementVNode"])("td",null,Object(d["toDisplayString"])(t.label),1),Object(d["createElementVNode"])("td",null,Object(d["toDisplayString"])(t.value),1),e.compareLanguage&&e.compareTranslations?(Object(d["openBlock"])(),Object(d["createElementBlock"])("td",v,Object(d["toDisplayString"])(e.compareTranslations[t.label]),1)):Object(d["createCommentVNode"])("",!0)])})),128))])],512),[[d["vShow"],e.searchTerm],[i]])])}var O=Object(s["useExternalPluginComponent"])("CorePluginsAdmin","Field"),y=Object(d["defineComponent"])({components:{Field:O},directives:{ContentTable:s["ContentTable"]},data:function(){return{compareTranslations:null,existingTranslations:[],languages:[],compareLanguage:"",searchTerm:""}},created:function(){this.fetchTranslations("en"),this.fetchLanguages()},methods:{fetchTranslations:function(e){var t=this;s["AjaxHelper"].fetch({method:"LanguagesManager.getTranslationsForLanguage",filter_limit:-1,languageCode:e}).then((function(n){n&&("en"===e?t.existingTranslations=n:(t.compareTranslations={},n.forEach((function(e){t.compareTranslations[e.label]=e.value}))))}))},fetchLanguages:function(){var e=this;s["AjaxHelper"].fetch({method:"LanguagesManager.getAvailableLanguagesInfo",filter_limit:-1}).then((function(t){e.languages=[{key:"",value:"None"}],t&&t.forEach((function(t){"en"!==t.code&&e.languages.push({key:t.code,value:t.name})}))}))},doCompareLanguage:function(){this.compareLanguage&&(this.compareTranslations=null,this.fetchTranslations(this.compareLanguage))}},computed:{filteredTranslations:function(){var e=this,t=this.existingTranslations.filter((function(t){return t.label.includes(e.searchTerm)||t.value.includes(e.searchTerm)}));return t=t.slice(0,1e3),t}}});y.render=j;var T=y;
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */Object(s["createAngularJsAdapter"])({component:T,directiveName:"piwikTranslationSearch"})}})}));
+//# sourceMappingURL=LanguagesManager.umd.min.js.map
\ No newline at end of file
diff --git a/app/plugins/LanguagesManager/vue/dist/umd.metadata.json b/app/plugins/LanguagesManager/vue/dist/umd.metadata.json
new file mode 100644
index 000000000..9ecfcc045
--- /dev/null
+++ b/app/plugins/LanguagesManager/vue/dist/umd.metadata.json
@@ -0,0 +1,5 @@
+{
+ "dependsOn": [
+ "CoreHome"
+ ]
+}
\ No newline at end of file
diff --git a/app/plugins/LanguagesManager/vue/src/LanguageSelector/LanguageSelector.adapter.ts b/app/plugins/LanguagesManager/vue/src/LanguageSelector/LanguageSelector.adapter.ts
new file mode 100644
index 000000000..bd8076421
--- /dev/null
+++ b/app/plugins/LanguagesManager/vue/src/LanguageSelector/LanguageSelector.adapter.ts
@@ -0,0 +1,31 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import { IScope } from 'angular';
+import LanguageSelector from './LanguageSelector';
+
+function languageSelection() {
+ return {
+ restrict: 'C',
+ link: function languageSelectionLink(scope: IScope, element: JQuery) {
+ const binding = {
+ instance: null,
+ value: {},
+ oldValue: null,
+ modifiers: {},
+ dir: {},
+ };
+
+ LanguageSelector.mounted(element[0], binding);
+ element.on('$destroy', () => {
+ LanguageSelector.unmounted(element[0], binding);
+ });
+ },
+ };
+}
+
+window.angular.module('piwikApp').directive('languageSelection', languageSelection);
diff --git a/app/plugins/LanguagesManager/vue/src/LanguageSelector/LanguageSelector.ts b/app/plugins/LanguagesManager/vue/src/LanguageSelector/LanguageSelector.ts
new file mode 100644
index 000000000..e2f622998
--- /dev/null
+++ b/app/plugins/LanguagesManager/vue/src/LanguageSelector/LanguageSelector.ts
@@ -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
+ */
+
+import { DirectiveBinding } from 'vue';
+import ClickEvent = JQuery.ClickEvent;
+
+const { $ } = window;
+
+interface LanguageSelectorBinding {
+ onClick?: (event: ClickEvent) => void;
+}
+
+function postLanguageChange(element: HTMLElement, event: ClickEvent) {
+ const value = $(event.target).attr('value');
+ if (value) {
+ $(element)
+ .find('#language')
+ .val(value)
+ .parents('form')
+ .submit();
+ }
+}
+
+export default {
+ mounted(el: HTMLElement, binding: DirectiveBinding
): void {
+ binding.value.onClick = postLanguageChange.bind(null, el);
+ $(el).on('click', 'a[value]', binding.value.onClick!);
+ },
+ unmounted(el: HTMLElement, binding: DirectiveBinding): void {
+ $(el).off('click', 'a[value]', binding.value.onClick!);
+ },
+};
diff --git a/app/plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.adapter.ts b/app/plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.adapter.ts
new file mode 100644
index 000000000..c32abdf10
--- /dev/null
+++ b/app/plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.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 'CoreHome';
+import TranslationSearch from './TranslationSearch.vue';
+
+export default createAngularJsAdapter({
+ component: TranslationSearch,
+ directiveName: 'piwikTranslationSearch',
+});
diff --git a/app/plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.vue b/app/plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.vue
new file mode 100644
index 000000000..c84c02df0
--- /dev/null
+++ b/app/plugins/LanguagesManager/vue/src/TranslationSearch/TranslationSearch.vue
@@ -0,0 +1,183 @@
+
+
+
+
+
+ This page helps you to find existing translations that you can reuse in your Plugin.
+ If you want to know more about translations have a look at our
+ Internationalization guide .
+ Enter a search term to find translations and their corresponding keys:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Key
+ English translation
+ Compare translation
+
+
+
+
+ {{ translation.label }}
+ {{ translation.value }}
+
+ {{ compareTranslations[translation.label] }}
+
+
+
+
+
+
+
+
diff --git a/app/plugins/LanguagesManager/vue/src/index.ts b/app/plugins/LanguagesManager/vue/src/index.ts
new file mode 100644
index 000000000..d31cd92ab
--- /dev/null
+++ b/app/plugins/LanguagesManager/vue/src/index.ts
@@ -0,0 +1,12 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import './LanguageSelector/LanguageSelector.adapter';
+import './TranslationSearch/TranslationSearch.adapter';
+
+export { default as TranslationSearch } from './TranslationSearch/TranslationSearch.vue';
+export { default as LanguageSelector } from './LanguageSelector/LanguageSelector.ts';
diff --git a/app/plugins/Live/API.php b/app/plugins/Live/API.php
index 241884af4..0f639a9e8 100644
--- a/app/plugins/Live/API.php
+++ b/app/plugins/Live/API.php
@@ -15,7 +15,6 @@
use Piwik\DataTable;
use Piwik\Date;
use Piwik\Piwik;
-use Piwik\Plugins\SitesManager\API as APISitesManager;
use Piwik\Site;
use Psr\Log\LoggerInterface;
@@ -148,6 +147,12 @@ public function getLastVisitsDetails($idSite, $period = false, $date = false, $s
}
Piwik::checkUserHasViewAccess($idSites);
+ if (is_numeric($minTimestamp)) {
+ $minTimestamp = (int) $minTimestamp;
+ } else {
+ $minTimestamp = false;
+ }
+
if (Request::isCurrentApiRequestTheRootApiRequest() || !in_array(Request::getRootApiRequestMethod(), ['API.getSuggestedValuesForSegment', 'PrivacyManager.findDataSubjects'])) {
if (is_array($idSites)) {
$filteredSites = array_filter($idSites, function($idSite) {
@@ -204,7 +209,7 @@ public function getVisitorProfile($idSite, $visitorId = false, $segment = false,
Piwik::checkUserHasViewAccess($idSite);
Live::checkIsVisitorProfileEnabled($idSite);
- if ($limitVisits <= 0) {
+ if (!is_numeric($limitVisits) || $limitVisits <= 0) {
$limitVisits = VisitorProfile::VISITOR_PROFILE_MAX_VISITS_TO_SHOW;
} else {
$limitVisits = (int) $limitVisits;
diff --git a/app/plugins/Live/Categories/VisitorLogSubcategory.php b/app/plugins/Live/Categories/VisitorLogSubcategory.php
index cba1e00af..52215d49c 100644
--- a/app/plugins/Live/Categories/VisitorLogSubcategory.php
+++ b/app/plugins/Live/Categories/VisitorLogSubcategory.php
@@ -21,7 +21,7 @@ public function getHelp()
{
$help = '' . Piwik::translate('Live_VisitorLogSubcategoryHelp1') . '
';
$help .= '' . Piwik::translate('Live_VisitorLogSubcategoryHelp2') . '
';
- $help .= '' . Piwik::translate('Live_VisitorLogSubcategoryHelp3') . '
';
+ $help .= '' . Piwik::translate('Live_VisitorLogSubcategoryHelp3') . '
';
return $help;
}
}
diff --git a/app/plugins/Live/Controller.php b/app/plugins/Live/Controller.php
index 9d1dbc9a6..c94c4e0d5 100644
--- a/app/plugins/Live/Controller.php
+++ b/app/plugins/Live/Controller.php
@@ -13,7 +13,7 @@
use Piwik\Config;
use Piwik\Piwik;
use Piwik\DataTable;
-use Piwik\Plugins\Goals\API as APIGoals;
+use Piwik\Plugins\Live\Exception\MaxExecutionTimeExceededException;
use Piwik\Plugins\Live\Visualizations\VisitorLog;
use Piwik\Url;
use Piwik\View;
@@ -98,6 +98,7 @@ public function getLastVisitsStart()
$_GET['period'] = 'day';
$view = new View('@Live/getLastVisitsStart');
+ $view->isProfileEnabled = Live::isVisitorProfileEnabled();
$view->idSite = (int) $this->idSite;
$error = '';
$visitors = new DataTable();
@@ -116,20 +117,40 @@ public function getLastVisitsStart()
private function setCounters($view)
{
$segment = Request::getRawSegmentFromRequest();
- $last30min = Request::processRequest('Live.getCounters', [
- 'idSite' => $this->idSite,
- 'lastMinutes' => 30,
- 'segment' => $segment,
- 'showColumns' => 'visits,actions',
- ], $default = []);
- $last30min = $last30min[0];
- $today = Request::processRequest('Live.getCounters', [
- 'idSite' => $this->idSite,
- 'lastMinutes' => 24 * 60,
- 'segment' => $segment,
- 'showColumns' => 'visits,actions',
- ], $default = []);
- $today = $today[0];
+ $executeTodayQuery = true;
+ $view->countErrorToday = '';
+ $view->countErrorHalfHour = '';
+ try {
+ $last30min = Request::processRequest('Live.getCounters', [
+ 'idSite' => $this->idSite,
+ 'lastMinutes' => 30,
+ 'segment' => $segment,
+ 'showColumns' => 'visits,actions',
+ ], $default = []);
+ $last30min = $last30min[0];
+ } catch (MaxExecutionTimeExceededException $e) {
+ $last30min = ['visits' => '-', 'actions' => '-'];
+ $today = ['visits' => '-', 'actions' => '-'];
+ $view->countErrorToday = $e->getMessage();
+ $view->countErrorHalfHour = $e->getMessage();
+ $executeTodayQuery = false; // if query for last 30 min failed, we also expect the 24 hour query to fail
+ }
+
+ try {
+ if ($executeTodayQuery) {
+ $today = Request::processRequest('Live.getCounters', [
+ 'idSite' => $this->idSite,
+ 'lastMinutes' => 24 * 60,
+ 'segment' => $segment,
+ 'showColumns' => 'visits,actions',
+ ], $default = []);
+ $today = $today[0];
+ }
+ } catch (MaxExecutionTimeExceededException $e) {
+ $today = ['visits' => '-', 'actions' => '-'];
+ $view->countErrorToday = $e->getMessage();
+ }
+
$view->visitorsCountHalfHour = $last30min['visits'];
$view->visitorsCountToday = $today['visits'];
$view->pisHalfhour = $last30min['actions'];
diff --git a/app/plugins/Live/Live.php b/app/plugins/Live/Live.php
index 3995d5df7..2fde5cd4e 100644
--- a/app/plugins/Live/Live.php
+++ b/app/plugins/Live/Live.php
@@ -1,4 +1,5 @@
'getJsFiles',
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys',
@@ -33,7 +35,7 @@ public function registerEvents()
'Live.renderVisitorIcons' => 'renderVisitorIcons',
'Template.jsGlobalVariables' => 'addJsGlobalVariables',
'API.getPagesComparisonsDisabledFor' => 'getPagesComparisonsDisabledFor',
- );
+ ];
}
public function getPagesComparisonsDisabledFor(&$pages)
@@ -46,8 +48,8 @@ public function addJsGlobalVariables(&$out)
{
$actionsToDisplayCollapsed = (int)StaticContainer::get('Live.pageViewActionsToDisplayCollapsed');
$out .= "
- piwik.visitorLogEnabled = ".json_encode(self::isVisitorLogEnabled()).";
- piwik.visitorProfileEnabled = ".json_encode(self::isVisitorProfileEnabled()).";
+ piwik.visitorLogEnabled = " . json_encode(self::isVisitorLogEnabled()) . ";
+ piwik.visitorProfileEnabled = " . json_encode(self::isVisitorProfileEnabled()) . ";
piwik.visitorLogActionsToDisplayCollapsed = $actionsToDisplayCollapsed;
";
}
@@ -77,7 +79,7 @@ public static function checkIsVisitorLogEnabled($idSite = null): void
$settings = new MeasurableSettings($idSite);
if ($settings->disableVisitorLog->getValue() === true) {
- throw new \Exception('Visits log is deactivated in website settings. A user with at least admin access can enable this feature in the settings for this website (idSite='.$idSite.').');
+ throw new \Exception('Visits log is deactivated in website settings. A user with at least admin access can enable this feature in the settings for this website (idSite=' . $idSite . ').');
}
}
}
@@ -126,7 +128,7 @@ public static function checkIsVisitorProfileEnabled($idSite = null): void
$settings = new MeasurableSettings($idSite);
if ($settings->disableVisitorProfile->getValue() === true) {
- throw new \Exception('Visitor profile is deactivated in website settings. A user with at least admin access can enable this feature in the settings for this website (idSite='.$idSite.').');
+ throw new \Exception('Visitor profile is deactivated in website settings. A user with at least admin access can enable this feature in the settings for this website (idSite=' . $idSite . ').');
}
}
}
@@ -164,7 +166,6 @@ public function getJsFiles(&$jsFiles)
$jsFiles[] = "plugins/Live/javascripts/visitorProfile.js";
$jsFiles[] = "plugins/Live/javascripts/visitorLog.js";
$jsFiles[] = "plugins/Live/javascripts/rowaction.js";
- $jsFiles[] = "plugins/Live/angularjs/live-widget-refresh/live-widget-refresh.directive.js";
}
public function getClientSideTranslationKeys(&$translationKeys)
@@ -201,11 +202,11 @@ public function renderActionTooltip(&$tooltip, $action, $visitInfo)
$detailEntries = array_merge($detailEntries, $instance->renderActionTooltip($action, $visitInfo));
}
- usort($detailEntries, function($a, $b) {
+ usort($detailEntries, function ($a, $b) {
return version_compare($a[0], $b[0]);
});
- foreach ($detailEntries AS $detailEntry) {
+ foreach ($detailEntries as $detailEntry) {
$tooltip .= $detailEntry[1];
}
}
@@ -219,11 +220,11 @@ public function renderVisitorDetails(&$renderedDetails, $visitorDetails)
$detailEntries = array_merge($detailEntries, $instance->renderVisitorDetails($visitorDetails));
}
- usort($detailEntries, function($a, $b) {
+ usort($detailEntries, function ($a, $b) {
return version_compare($a[0], $b[0]);
});
- foreach ($detailEntries AS $detailEntry) {
+ foreach ($detailEntries as $detailEntry) {
$renderedDetails .= $detailEntry[1];
}
}
@@ -268,4 +269,4 @@ public static function getSegmentWithVisitorId()
return $result;
}
-}
\ No newline at end of file
+}
diff --git a/app/plugins/Live/Model.php b/app/plugins/Live/Model.php
index 604ce0a39..b8a127418 100644
--- a/app/plugins/Live/Model.php
+++ b/app/plugins/Live/Model.php
@@ -27,6 +27,11 @@
class Model
{
+ /**
+ * @internal for tests only
+ */
+ public $queryAndWhereSleepTestsOnly = false;
+
/**
* @param $idSite
* @param $period
@@ -371,6 +376,11 @@ public function getNumVisitors($idSite, $lastMinutes, $segment)
);
}
+ private function shouldQuerySleepInTests()
+ {
+ return $this->queryAndWhereSleepTestsOnly && defined('PIWIK_TEST_MODE') && PIWIK_TEST_MODE;
+ }
+
private function getLastMinutesCounterForQuery($idSite, $lastMinutes, $segment, $select, $from, $where)
{
$lastMinutes = (int)$lastMinutes;
@@ -394,11 +404,31 @@ private function getLastMinutesCounterForQuery($idSite, $lastMinutes, $segment,
$bind[] = $startDate->toString('Y-m-d H:i:s');
$where = $whereIdSites . "AND " . $where;
+ if ($this->shouldQuerySleepInTests()) {
+ $where = ' SLEEP(1)';
+ }
$segment = new Segment($segment, $idSite, $startDate, $endDate = null);
$query = $segment->getSelectQuery($select, $from, $where, $bind);
- $numVisitors = Db::getReader()->fetchOne($query['sql'], $query['bind']);
+ if ($this->shouldQuerySleepInTests()) {
+ $query['bind'] = [];
+ }
+
+ $query['sql'] = trim($query['sql']);
+ if (0 === stripos($query['sql'], 'SELECT')) {
+ $query['sql'] = 'SELECT /* Live.getCounters */' . mb_substr($query['sql'], strlen('SELECT'));
+ }
+
+ $query['sql'] = DbHelper::addMaxExecutionTimeHintToQuery($query['sql'], $this->getLiveQueryMaxExecutionTime());
+
+ $readerDb = Db::getReader();
+ try {
+ $numVisitors = $readerDb->fetchOne($query['sql'], $query['bind']);
+ } catch (Exception $e) {
+ $this->handleMaxExecutionTimeError($readerDb, $e, $segment->getOriginalString(), $startDate, Date::now(), null, 0, $query);
+ throw $e;
+ }
return $numVisitors;
}
@@ -460,15 +490,35 @@ public function queryAdjacentVisitorId($idSite, $visitorId, $visitLastActionTime
$orderBy = "MAX(log_visit.visit_last_action_time) $orderByDir";
$groupBy = "log_visit.idvisitor";
+ if ($this->shouldQuerySleepInTests()) {
+ $where = ' SLEEP(1)';
+ $visitLastActionTimeCondition = 'SLEEP(1)';
+ }
+
$segment = new Segment($segment, $idSite, $dateOneDayAgo, $dateOneDayInFuture);
$queryInfo = $segment->getSelectQuery($select, $from, $where, $whereBind, $orderBy, $groupBy);
- $sql = "SELECT sub.idvisitor, sub.visit_last_action_time FROM ({$queryInfo['sql']}) as sub
+ $sql = "SELECT /* Live.queryAdjacentVisitorId */ sub.idvisitor, sub.visit_last_action_time FROM ({$queryInfo['sql']}) as sub
WHERE $visitLastActionTimeCondition
LIMIT 1";
$bind = array_merge($queryInfo['bind'], array($visitLastActionTime));
- $visitorId = Db::getReader()->fetchOne($sql, $bind);
+ if ($this->shouldQuerySleepInTests()) {
+ $bind = [];
+ }
+
+ $sql = DbHelper::addMaxExecutionTimeHintToQuery($sql, $this->getLiveQueryMaxExecutionTime());
+
+ $readerDb = Db::getReader();
+ try {
+ $visitorId = $readerDb->fetchOne($sql, $bind);
+ } catch (Exception $e) {
+ $this->handleMaxExecutionTimeError($readerDb, $e, $segment->getOriginalString(), Date::now(), Date::now(), null, 1, [
+ 'sql' => $sql, 'bind' => $bind
+ ]);
+ throw $e;
+ }
+
if (!empty($visitorId)) {
$visitorId = bin2hex($visitorId);
}
@@ -529,7 +579,9 @@ public function makeLogVisitsQueryString($idSite, $startDate, $endDate, $segment
if (!$visitorId) {
// for now let's not apply when looking for a specific visitor
- $innerQuery['sql'] = DbHelper::addMaxExecutionTimeHintToQuery($innerQuery['sql'], Config::getInstance()->General['live_query_max_execution_time']);
+ $innerQuery['sql'] = DbHelper::addMaxExecutionTimeHintToQuery($innerQuery['sql'],
+ $this->getLiveQueryMaxExecutionTime()
+ );
}
return array($innerQuery['sql'], $bind);
@@ -656,4 +708,9 @@ private function getWhereClauseAndBind($whereClause, $bindIdSites, $startDate, $
}
return array($whereBind, $where);
}
+
+ private function getLiveQueryMaxExecutionTime()
+ {
+ return Config::getInstance()->General['live_query_max_execution_time'];
+ }
}
diff --git a/app/plugins/Live/ProfileSummary/Summary.php b/app/plugins/Live/ProfileSummary/Summary.php
index 9f864f3bd..c08cec750 100644
--- a/app/plugins/Live/ProfileSummary/Summary.php
+++ b/app/plugins/Live/ProfileSummary/Summary.php
@@ -12,7 +12,6 @@
use Piwik\Common;
use Piwik\Piwik;
use Piwik\View;
-use Piwik\Plugins\Goals\API as APIGoals;
/**
* Class Summary
diff --git a/app/plugins/Live/Reports/GetSimpleLastVisitCount.php b/app/plugins/Live/Reports/GetSimpleLastVisitCount.php
index 469618f90..5ea442d50 100644
--- a/app/plugins/Live/Reports/GetSimpleLastVisitCount.php
+++ b/app/plugins/Live/Reports/GetSimpleLastVisitCount.php
@@ -11,9 +11,9 @@
use Piwik\Config;
use Piwik\Metrics\Formatter;
use Piwik\Piwik;
-use Piwik\Plugin\Report;
use Piwik\Plugins\Live\Controller;
use Piwik\API\Request;
+use Piwik\Plugins\Live\Exception\MaxExecutionTimeExceededException;
use Piwik\Report\ReportWidgetFactory;
use Piwik\View;
use Piwik\Widget\WidgetsList;
@@ -38,16 +38,26 @@ public function render()
$lastMinutes = Config::getInstance()->General[Controller::SIMPLE_VISIT_COUNT_WIDGET_LAST_MINUTES_CONFIG_KEY];
$params = array('lastMinutes' => $lastMinutes, 'showColumns' => array('visits', 'visitors', 'actions'));
- $lastNData = Request::processRequest('Live.getCounters', $params);
+ $refereshAfterSeconds = Config::getInstance()->General['live_widget_refresh_after_seconds'];
+
+ $error = '';
+ try {
+ $lastNData = Request::processRequest('Live.getCounters', $params);
+ } catch (MaxExecutionTimeExceededException $e) {
+ $error = $e->getMessage();
+ $lastNData = [0 => ['visitors' => '-', 'visits' => '-', 'actions' => '-']];
+ $refereshAfterSeconds = 999999999; // we don't want it to refresh again any time soon as same issue would happen again
+ }
$formatter = new Formatter();
$view = new View('@Live/getSimpleLastVisitCount');
+ $view->error = $error;
$view->lastMinutes = $lastMinutes;
$view->visitors = $formatter->getPrettyNumber($lastNData[0]['visitors']);
$view->visits = $formatter->getPrettyNumber($lastNData[0]['visits']);
$view->actions = $formatter->getPrettyNumber($lastNData[0]['actions']);
- $view->refreshAfterXSecs = Config::getInstance()->General['live_widget_refresh_after_seconds'];
+ $view->refreshAfterXSecs = $refereshAfterSeconds;
$view->translations = array(
'one_visitor' => Piwik::translate('Live_NbVisitor'),
'visitors' => Piwik::translate('Live_NbVisitors'),
@@ -61,4 +71,4 @@ public function render()
return $view->render();
}
-}
\ No newline at end of file
+}
diff --git a/app/plugins/Live/Visitor.php b/app/plugins/Live/Visitor.php
index 388be7772..e0c4192d2 100644
--- a/app/plugins/Live/Visitor.php
+++ b/app/plugins/Live/Visitor.php
@@ -12,12 +12,9 @@
use Piwik\CacheId;
use Piwik\Config;
use Piwik\DataTable\Filter\ColumnDelete;
-use Piwik\Date;
-use Piwik\Metrics\Formatter;
use Piwik\Plugin;
use Piwik\Piwik;
use Piwik\Plugins\Live\Visualizations\VisitorLog;
-use Piwik\Tracker\GoalManager;
class Visitor implements VisitorInterface
{
diff --git a/app/plugins/Live/VisitorDetails.php b/app/plugins/Live/VisitorDetails.php
index 97f78d255..e709ffbb3 100644
--- a/app/plugins/Live/VisitorDetails.php
+++ b/app/plugins/Live/VisitorDetails.php
@@ -1,4 +1,5 @@
getCurrency();
$currencies = APISitesManager::getInstance()->getCurrencySymbols();
- $visitor += array(
+ $visitor += [
'idSite' => $idSite,
'idVisit' => $this->getIdVisit(),
'visitIp' => $this->getIp(),
@@ -49,7 +51,7 @@ public function extendVisitorDetails(&$visitor)
'visitServerHour' => $this->getVisitServerHour(),
'lastActionTimestamp' => $this->getTimestampLastAction(),
'lastActionDateTime' => $this->getDateTimeLastAction(),
- );
+ ];
$visitor['siteCurrency'] = $currency;
$visitor['siteCurrencySymbol'] = @$currencies[$visitor['siteCurrency']];
@@ -121,6 +123,7 @@ public function renderActionTooltip($action, $visitInfo)
public function renderVisitorDetails($visitorDetails)
{
$view = new View('@Live/_visitorDetails.twig');
+ $view->isProfileEnabled = Live::isVisitorProfileEnabled();
$view->sendHeadersWhenRendering = false;
$view->visitInfo = $visitorDetails;
return [[ 0, $view->render() ]];
@@ -129,6 +132,7 @@ public function renderVisitorDetails($visitorDetails)
public function renderIcons($visitorDetails)
{
$view = new View('@Live/_visitorLogIcons.twig');
+ $view->isProfileEnabled = Live::isVisitorProfileEnabled();
$view->sendHeadersWhenRendering = false;
$view->visitor = $visitorDetails;
return $view->render();
@@ -247,17 +251,16 @@ private function getVisitorProfileVisitSummary($visit)
$today = Date::today();
$serverDate = $visit->getColumn('firstActionTimestamp');
- return array(
+ return [
'date' => $serverDate,
'prettyDate' => Date::factory($serverDate)->getLocalized(Date::DATE_FORMAT_LONG),
'daysAgo' => (int)Date::secondsToDays($today->getTimestamp() - Date::factory($serverDate)->getTimestamp()),
'referrerType' => $visit->getColumn('referrerType'),
'referrerUrl' => $visit->getColumn('referrerUrl') ?: '',
'referralSummary' => self::getReferrerSummaryForVisit($visit),
- );
+ ];
}
-
/**
* Returns a summary for a visit's referral.
*
@@ -267,7 +270,8 @@ private function getVisitorProfileVisitSummary($visit)
public static function getReferrerSummaryForVisit($visit)
{
$referrerType = $visit->getColumn('referrerType');
- if ($referrerType === false
+ if (
+ $referrerType === false
|| $referrerType == 'direct'
) {
return Piwik::translate('Referrers_DirectEntry');
@@ -277,7 +281,8 @@ public static function getReferrerSummaryForVisit($visit)
$referrerName = $visit->getColumn('referrerName');
$keyword = $visit->getColumn('referrerKeyword');
- if ($keyword !== false
+ if (
+ $keyword !== false
&& $keyword != APIReferrers::getKeywordNotDefinedString()
) {
$referrerName .= ' (' . $keyword . ')';
@@ -286,7 +291,6 @@ public static function getReferrerSummaryForVisit($visit)
}
if ($referrerType == 'campaign') {
-
$summary = Piwik::translate('Referrers_ColumnCampaign') . ': ' . $visit->getColumn('referrerName');
$keyword = $visit->getColumn('referrerKeyword');
if (!empty($keyword)) {
diff --git a/app/plugins/Live/VisitorProfile.php b/app/plugins/Live/VisitorProfile.php
index 12b99d72c..9c6ed1a7a 100644
--- a/app/plugins/Live/VisitorProfile.php
+++ b/app/plugins/Live/VisitorProfile.php
@@ -11,6 +11,7 @@
use Exception;
use Piwik\DataTable;
+use Piwik\Plugins\Live\Exception\MaxExecutionTimeExceededException;
class VisitorProfile
{
@@ -90,10 +91,19 @@ private function handleAdjacentVisitorIds(DataTable $visits, $visitorId, $segmen
$rows = $visits->getRows();
$latestVisitTime = reset($rows)->getColumn('lastActionDateTime');
- $model = new Model();
- $this->profile['nextVisitorId'] = $model->queryAdjacentVisitorId($this->idSite, $visitorId,
- $latestVisitTime, $segment, $getNext = true);
- $this->profile['previousVisitorId'] = $model->queryAdjacentVisitorId($this->idSite, $visitorId,
- $latestVisitTime, $segment, $getNext = false);
+ $model = new Model();
+ try {
+ $this->profile['nextVisitorId'] = $model->queryAdjacentVisitorId($this->idSite, $visitorId, $latestVisitTime, $segment, $getNext = true);
+ } catch (MaxExecutionTimeExceededException $e) {
+ $this->profile['nextVisitorId'] = false;
+ $this->profile['previousVisitorId'] = false; // if query for next visitor is too slow, we assume query for previous visitor is too slow too
+ return;
+ }
+ try {
+ $this->profile['previousVisitorId'] = $model->queryAdjacentVisitorId($this->idSite, $visitorId, $latestVisitTime, $segment, $getNext = false);
+ } catch (MaxExecutionTimeExceededException $e) {
+ // we simply assume there is no previous visitor in that case
+ $this->profile['previousVisitorId'] = false;
+ }
}
}
diff --git a/app/plugins/Live/lang/ga.json b/app/plugins/Live/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/Live/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Live/stylesheets/live.less b/app/plugins/Live/stylesheets/live.less
index 5f121dce8..7d4d87ea3 100644
--- a/app/plugins/Live/stylesheets/live.less
+++ b/app/plugins/Live/stylesheets/live.less
@@ -223,17 +223,7 @@ ol.actionList > li:not(.pageviewActions) {
margin-top: 2px;
float: left;
margin-right: 5px;
-
- // copied frim [class^=icon-] style
- font-family: 'matomo' !important;
- speak: none;
- font-style: normal;
- font-weight: normal;
- font-variant: normal;
- text-transform: none;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
+ .matomo-icon();
}
}
}
diff --git a/app/plugins/Live/stylesheets/visitor_profile.less b/app/plugins/Live/stylesheets/visitor_profile.less
index 0fd91fb8f..aa199cdfd 100644
--- a/app/plugins/Live/stylesheets/visitor_profile.less
+++ b/app/plugins/Live/stylesheets/visitor_profile.less
@@ -78,12 +78,12 @@
margin-right: 5px;
&:before {
+ .matomo-icon();
color: #000;
background-color: #fff;
font-size: 16px;
line-height: 16px;
font-weight: 400;
- font-family: matomo;
padding: 1px;
height: 18px;
display: block;
diff --git a/app/plugins/Live/templates/_totalVisitors.twig b/app/plugins/Live/templates/_totalVisitors.twig
index 665617e92..70e37b3c7 100644
--- a/app/plugins/Live/templates/_totalVisitors.twig
+++ b/app/plugins/Live/templates/_totalVisitors.twig
@@ -16,13 +16,13 @@
{{ 'Live_LastHours'|translate(24) }}
- {{ visitorsCountToday|number }}
- {{ pisToday|number }}
+ {{ visitorsCountToday|number }}
+ {{ pisToday|number }}
{{ 'Live_LastMinutes'|translate(30) }}
- {{ visitorsCountHalfHour|number }}
- {{ pisHalfhour|number }}
+ {{ visitorsCountHalfHour|number }}
+ {{ pisHalfhour|number }}
diff --git a/app/plugins/Live/templates/_visitorDetails.twig b/app/plugins/Live/templates/_visitorDetails.twig
index f0e22943c..18b23d1be 100644
--- a/app/plugins/Live/templates/_visitorDetails.twig
+++ b/app/plugins/Live/templates/_visitorDetails.twig
@@ -3,7 +3,7 @@
{% if isWidget %} {% else %}-{% endif %} {{ visitInfo.getColumn('serverTimePrettyFirstAction') }}
{% if visitInfo.getColumn('visitIp') is not empty %}
diff --git a/app/plugins/Live/templates/getSimpleLastVisitCount.twig b/app/plugins/Live/templates/getSimpleLastVisitCount.twig
index 8f167544e..3d4fd5360 100644
--- a/app/plugins/Live/templates/getSimpleLastVisitCount.twig
+++ b/app/plugins/Live/templates/getSimpleLastVisitCount.twig
@@ -3,6 +3,7 @@
{{ visitors }}
+ {% if error is not empty %}{{ error }}
{% endif %}
{% set visitsMessage %}
@@ -18,4 +19,4 @@
{{ 'Live_SimpleRealTimeWidget_Message'|translate(visitsMessage,actionsMessage,minutesMessage) | raw }}
-
\ No newline at end of file
+
diff --git a/app/plugins/Live/vue/dist/Live.umd.js b/app/plugins/Live/vue/dist/Live.umd.js
new file mode 100644
index 000000000..2f2411628
--- /dev/null
+++ b/app/plugins/Live/vue/dist/Live.umd.js
@@ -0,0 +1,225 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("CoreHome"));
+ else if(typeof define === 'function' && define.amd)
+ define(["CoreHome"], factory);
+ else if(typeof exports === 'object')
+ exports["Live"] = factory(require("CoreHome"));
+ else
+ root["Live"] = factory(root["CoreHome"]);
+})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__19dc__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ }
+/******/ };
+/******/
+/******/ // define __esModule on exports
+/******/ __webpack_require__.r = function(exports) {
+/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ }
+/******/ Object.defineProperty(exports, '__esModule', { value: true });
+/******/ };
+/******/
+/******/ // create a fake namespace object
+/******/ // mode & 1: value is a module id, require it
+/******/ // mode & 2: merge all properties of value into the ns
+/******/ // mode & 4: return value when already ns object
+/******/ // mode & 8|1: behave like require
+/******/ __webpack_require__.t = function(value, mode) {
+/******/ if(mode & 1) value = __webpack_require__(value);
+/******/ if(mode & 8) return value;
+/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ var ns = Object.create(null);
+/******/ __webpack_require__.r(ns);
+/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ return ns;
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "plugins/Live/vue/dist/";
+/******/
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = "fae3");
+/******/ })
+/************************************************************************/
+/******/ ({
+
+/***/ "19dc":
+/***/ (function(module, exports) {
+
+module.exports = __WEBPACK_EXTERNAL_MODULE__19dc__;
+
+/***/ }),
+
+/***/ "fae3":
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+// ESM COMPAT FLAG
+__webpack_require__.r(__webpack_exports__);
+
+// EXPORTS
+__webpack_require__.d(__webpack_exports__, "LiveWidgetRefresh", function() { return /* reexport */ LiveWidgetRefresh; });
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
+// This file is imported into lib/wc client bundles.
+
+if (typeof window !== 'undefined') {
+ var currentScript = window.document.currentScript
+ if (false) { var getCurrentScript; }
+
+ var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
+ if (src) {
+ __webpack_require__.p = src[1] // eslint-disable-line
+ }
+}
+
+// Indicate to webpack that this file can be concatenated
+/* harmony default export */ var setPublicPath = (null);
+
+// EXTERNAL MODULE: external "CoreHome"
+var external_CoreHome_ = __webpack_require__("19dc");
+
+// CONCATENATED MODULE: ./plugins/Live/vue/src/LiveWidget/LiveWidgetRefresh.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 _window = window,
+ $ = _window.$;
+/* harmony default export */ var LiveWidgetRefresh = ({
+ mounted: function mounted(el, binding) {
+ setTimeout(function () {
+ var segment = external_CoreHome_["MatomoUrl"].parsed.value.segment; // eslint-disable-next-line @typescript-eslint/no-explicit-any
+
+ $(el).find('#visitsLive').liveWidget({
+ interval: binding.value.liveRefreshAfterMs,
+ onUpdate: function onUpdate() {
+ // updates the numbers of total visits in startbox
+ external_CoreHome_["AjaxHelper"].fetch({
+ module: 'Live',
+ action: 'ajaxTotalVisitors',
+ segment: segment
+ }, {
+ format: 'html'
+ }).then(function (r) {
+ $(el).find('#visitsTotal').replaceWith(r);
+ });
+ },
+ maxRows: 10,
+ fadeInSpeed: 600,
+ dataUrlParams: {
+ module: 'Live',
+ action: 'getLastVisitsStart',
+ segment: segment
+ }
+ });
+ });
+ }
+});
+// CONCATENATED MODULE: ./plugins/Live/vue/src/LiveWidget/LiveWidgetRefresh.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 piwikLiveWidgetRefresh() {
+ return {
+ restrict: 'A',
+ scope: {
+ liveRefreshAfterMs: '@'
+ },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ link: function link(scope, element) {
+ LiveWidgetRefresh.mounted(element[0], {
+ instance: null,
+ value: {
+ liveRefreshAfterMs: parseInt(scope.liveRefreshAfterMs, 10)
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {}
+ });
+ }
+ };
+}
+
+piwikLiveWidgetRefresh.$inject = ['piwik', '$timeout'];
+window.angular.module('piwikApp').directive('piwikLiveWidgetRefresh', piwikLiveWidgetRefresh);
+// CONCATENATED MODULE: ./plugins/Live/vue/src/index.ts
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+
+// CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/entry-lib-no-default.js
+
+
+
+
+/***/ })
+
+/******/ });
+});
+//# sourceMappingURL=Live.umd.js.map
\ No newline at end of file
diff --git a/app/plugins/Live/vue/dist/Live.umd.min.js b/app/plugins/Live/vue/dist/Live.umd.min.js
new file mode 100644
index 000000000..de0f12955
--- /dev/null
+++ b/app/plugins/Live/vue/dist/Live.umd.min.js
@@ -0,0 +1,9 @@
+(function(e,t){"object"===typeof exports&&"object"===typeof module?module.exports=t(require("CoreHome")):"function"===typeof define&&define.amd?define(["CoreHome"],t):"object"===typeof exports?exports["Live"]=t(require("CoreHome")):e["Live"]=t(e["CoreHome"])})("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/Live/vue/dist/",n(n.s="fae3")}({"19dc":function(t,n){t.exports=e},fae3:function(e,t,n){"use strict";if(n.r(t),n.d(t,"LiveWidgetRefresh",(function(){return l})),"undefined"!==typeof window){var r=window.document.currentScript,i=r&&r.src.match(/(.+\/)[^/]+\.js(\?.*)?$/);i&&(n.p=i[1])}var o=n("19dc"),u=window,f=u.$,l={mounted:function(e,t){setTimeout((function(){var n=o["MatomoUrl"].parsed.value.segment;f(e).find("#visitsLive").liveWidget({interval:t.value.liveRefreshAfterMs,onUpdate:function(){o["AjaxHelper"].fetch({module:"Live",action:"ajaxTotalVisitors",segment:n},{format:"html"}).then((function(t){f(e).find("#visitsTotal").replaceWith(t)}))},maxRows:10,fadeInSpeed:600,dataUrlParams:{module:"Live",action:"getLastVisitsStart",segment: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(){return{restrict:"A",scope:{liveRefreshAfterMs:"@"},link:function(e,t){l.mounted(t[0],{instance:null,value:{liveRefreshAfterMs:parseInt(e.liveRefreshAfterMs,10)},oldValue:null,modifiers:{},dir:{}})}}}s.$inject=["piwik","$timeout"],window.angular.module("piwikApp").directive("piwikLiveWidgetRefresh",s)}})}));
+//# sourceMappingURL=Live.umd.min.js.map
\ No newline at end of file
diff --git a/app/plugins/Live/vue/dist/umd.metadata.json b/app/plugins/Live/vue/dist/umd.metadata.json
new file mode 100644
index 000000000..9ecfcc045
--- /dev/null
+++ b/app/plugins/Live/vue/dist/umd.metadata.json
@@ -0,0 +1,5 @@
+{
+ "dependsOn": [
+ "CoreHome"
+ ]
+}
\ No newline at end of file
diff --git a/app/plugins/Live/vue/src/LiveWidget/LiveWidgetRefresh.adapter.ts b/app/plugins/Live/vue/src/LiveWidget/LiveWidgetRefresh.adapter.ts
new file mode 100644
index 000000000..9e13fd94a
--- /dev/null
+++ b/app/plugins/Live/vue/src/LiveWidget/LiveWidgetRefresh.adapter.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 LiveWidgetRefresh from './LiveWidgetRefresh';
+
+function piwikLiveWidgetRefresh() {
+ return {
+ restrict: 'A',
+ scope: {
+ liveRefreshAfterMs: '@',
+ },
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ link(scope: any, element: JQuery) {
+ LiveWidgetRefresh.mounted(element[0], {
+ instance: null,
+ value: {
+ liveRefreshAfterMs: parseInt(scope.liveRefreshAfterMs, 10),
+ },
+ oldValue: null,
+ modifiers: {},
+ dir: {},
+ });
+ },
+ };
+}
+
+piwikLiveWidgetRefresh.$inject = ['piwik', '$timeout'];
+
+window.angular.module('piwikApp').directive('piwikLiveWidgetRefresh', piwikLiveWidgetRefresh);
diff --git a/app/plugins/Live/vue/src/LiveWidget/LiveWidgetRefresh.ts b/app/plugins/Live/vue/src/LiveWidget/LiveWidgetRefresh.ts
new file mode 100644
index 000000000..35d6b5723
--- /dev/null
+++ b/app/plugins/Live/vue/src/LiveWidget/LiveWidgetRefresh.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 { MatomoUrl, AjaxHelper } from 'CoreHome';
+import { DirectiveBinding } from 'vue';
+
+interface LiveWidgetRefreshBinding {
+ liveRefreshAfterMs: number;
+}
+
+const { $ } = window;
+
+export default {
+ mounted(el: HTMLElement, binding: DirectiveBinding): void {
+ setTimeout(() => {
+ const segment = MatomoUrl.parsed.value.segment as string;
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ($(el).find('#visitsLive') as any).liveWidget({
+ interval: binding.value.liveRefreshAfterMs,
+ onUpdate: () => {
+ // updates the numbers of total visits in startbox
+ AjaxHelper.fetch(
+ {
+ module: 'Live',
+ action: 'ajaxTotalVisitors',
+ segment,
+ },
+ {
+ format: 'html',
+ },
+ ).then((r) => {
+ $(el).find('#visitsTotal').replaceWith(r);
+ });
+ },
+ maxRows: 10,
+ fadeInSpeed: 600,
+ dataUrlParams: {
+ module: 'Live',
+ action: 'getLastVisitsStart',
+ segment,
+ },
+ });
+ });
+ },
+};
diff --git a/app/plugins/Live/vue/src/index.ts b/app/plugins/Live/vue/src/index.ts
new file mode 100644
index 000000000..179e998c6
--- /dev/null
+++ b/app/plugins/Live/vue/src/index.ts
@@ -0,0 +1,10 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+import './LiveWidget/LiveWidgetRefresh.adapter';
+
+export { default as LiveWidgetRefresh } from './LiveWidget/LiveWidgetRefresh';
diff --git a/app/plugins/Login/Commands/UnblockBlockedIps.php b/app/plugins/Login/Commands/UnblockBlockedIps.php
index d736f2fb9..de781b4ea 100644
--- a/app/plugins/Login/Commands/UnblockBlockedIps.php
+++ b/app/plugins/Login/Commands/UnblockBlockedIps.php
@@ -11,7 +11,6 @@
use Piwik\API\Request;
use Piwik\Piwik;
use Piwik\Plugin\ConsoleCommand;
-use Piwik\Plugins\Login\API;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
diff --git a/app/plugins/Login/Controller.php b/app/plugins/Login/Controller.php
index b13f3f823..fff60e74d 100644
--- a/app/plugins/Login/Controller.php
+++ b/app/plugins/Login/Controller.php
@@ -9,18 +9,14 @@
namespace Piwik\Plugins\Login;
use Exception;
-use Piwik\Access;
-use Piwik\Auth\Password;
use Piwik\Common;
use Piwik\Config;
use Piwik\Container\StaticContainer;
-use Piwik\Date;
use Piwik\Log;
use Piwik\Nonce;
use Piwik\Piwik;
use Piwik\Plugins\Login\Security\BruteForceDetection;
use Piwik\Plugins\UsersManager\Model AS UsersModel;
-use Piwik\Plugins\UsersManager\UserUpdater;
use Piwik\QuickForm2;
use Piwik\Session;
use Piwik\Url;
diff --git a/app/plugins/Login/Emails/PasswordResetEmail.php b/app/plugins/Login/Emails/PasswordResetEmail.php
new file mode 100644
index 000000000..bdded77c4
--- /dev/null
+++ b/app/plugins/Login/Emails/PasswordResetEmail.php
@@ -0,0 +1,68 @@
+login = $login;
+ $this->ip = $ip;
+ $this->resetUrl = $resetUrl;
+
+ $this->setUpEmail();
+ }
+
+ private function setUpEmail()
+ {
+ $replytoEmailName = Config::getInstance()->General['login_password_recovery_replyto_email_name'];
+ $replytoEmailAddress = Config::getInstance()->General['login_password_recovery_replyto_email_address'];
+
+ $this->setSubject($this->getDefaultSubject());
+ $this->addReplyTo($replytoEmailAddress, $replytoEmailName);
+ $this->setWrappedHtmlBody($this->getDefaultBodyText());
+ }
+
+ private function getDefaultSubject()
+ {
+ return Piwik::translate('Login_MailTopicPasswordChange');
+ }
+
+ private function getDefaultBodyText()
+ {
+ return '' . str_replace(
+ "\n\n",
+ "
",
+ Piwik::translate('Login_MailPasswordChangeBody2', [Common::sanitizeInputValue($this->login), Common::sanitizeInputValue($this->ip), Common::sanitizeInputValue($this->resetUrl)])
+ ) . "
";
+ }
+}
\ No newline at end of file
diff --git a/app/plugins/Login/Login.php b/app/plugins/Login/Login.php
index 8b0c29935..df2e74065 100644
--- a/app/plugins/Login/Login.php
+++ b/app/plugins/Login/Login.php
@@ -175,8 +175,8 @@ public function beforeSessionStart()
private function shouldHandleRememberMe()
{
- $module = Common::getRequestVar('module', false);
- $action = Common::getRequestVar('action', false);
+ $module = Piwik::getModule();
+ $action = Piwik::getAction();
return ($module == 'Login' || $module == 'CoreHome') && (empty($action) || $action == 'index' || $action == 'login');
}
@@ -221,8 +221,7 @@ private function getUsernameUsedInPasswordLogin()
$login = StaticContainer::get(\Piwik\Auth::class)->getLogin();
if (empty($login) || $login == 'anonymous') {
$login = Common::getRequestVar('form_login', false);
- $action = Common::getRequestVar('action', false);
- if ($action == 'logme') {
+ if (Piwik::getAction() === 'logme') {
$login = Common::getRequestVar('login', $login);
}
}
diff --git a/app/plugins/Login/PasswordResetter.php b/app/plugins/Login/PasswordResetter.php
index db93ddc2b..7b6a5efa2 100644
--- a/app/plugins/Login/PasswordResetter.php
+++ b/app/plugins/Login/PasswordResetter.php
@@ -11,11 +11,10 @@
use Piwik\Access;
use Piwik\Auth\Password;
use Piwik\Common;
-use Piwik\Config;
use Piwik\IP;
-use Piwik\Mail;
use Piwik\Option;
use Piwik\Piwik;
+use Piwik\Plugins\Login\Emails\PasswordResetEmail;
use Piwik\Plugins\UsersManager\Model;
use Piwik\Plugins\UsersManager\UsersManager;
use Piwik\Plugins\UsersManager\API as UsersManagerAPI;
@@ -440,15 +439,8 @@ private function sendEmailConfirmationLink($user, $keySuffix)
. "&resetToken=" . urlencode($resetToken);
// send email with new password
- $mail = new Mail();
+ $mail = new PasswordResetEmail($login, $ip, $url);
$mail->addTo($email, $login);
- $mail->setSubject(Piwik::translate('Login_MailTopicPasswordChange'));
- $bodyText = '' . str_replace(
- "\n\n",
- "
",
- Piwik::translate('Login_MailPasswordChangeBody2', [Common::sanitizeInputValue($login), Common::sanitizeInputValue($ip), Common::sanitizeInputValue($url)])
- ) . "
";
- $mail->setWrappedHtmlBody($bodyText);
if ($this->emailFromAddress || $this->emailFromName) {
$mail->setFrom($this->emailFromAddress, $this->emailFromName);
@@ -456,10 +448,6 @@ private function sendEmailConfirmationLink($user, $keySuffix)
$mail->setDefaultFromPiwik();
}
- $replytoEmailName = Config::getInstance()->General['login_password_recovery_replyto_email_name'];
- $replytoEmailAddress = Config::getInstance()->General['login_password_recovery_replyto_email_address'];
- $mail->addReplyTo($replytoEmailAddress, $replytoEmailName);
-
@$mail->send();
}
diff --git a/app/plugins/Login/Security/BruteForceDetection.php b/app/plugins/Login/Security/BruteForceDetection.php
index ab94491d7..8ada5e920 100644
--- a/app/plugins/Login/Security/BruteForceDetection.php
+++ b/app/plugins/Login/Security/BruteForceDetection.php
@@ -12,12 +12,10 @@
use Piwik\Container\StaticContainer;
use Piwik\Date;
use Piwik\Db;
-use Piwik\Option;
use Piwik\Plugins\Login\Emails\SuspiciousLoginAttemptsInLastHourEmail;
use Piwik\Plugins\Login\Model;
use Piwik\Plugins\Login\SystemSettings;
use Piwik\Updater;
-use Piwik\Version;
use Psr\Log\LoggerInterface;
class BruteForceDetection {
diff --git a/app/plugins/Login/SessionInitializer.php b/app/plugins/Login/SessionInitializer.php
index 64d24d177..03fee4260 100644
--- a/app/plugins/Login/SessionInitializer.php
+++ b/app/plugins/Login/SessionInitializer.php
@@ -13,8 +13,6 @@
use Piwik\AuthResult;
use Piwik\Config;
use Piwik\Cookie;
-use Piwik\Db;
-use Piwik\Log;
use Piwik\Piwik;
use Piwik\Plugins\UsersManager\API as UsersManagerAPI;
use Piwik\ProxyHttp;
diff --git a/app/plugins/Login/config/test.php b/app/plugins/Login/config/test.php
deleted file mode 100644
index 9342d07d9..000000000
--- a/app/plugins/Login/config/test.php
+++ /dev/null
@@ -1,36 +0,0 @@
- DI\decorate(function ($settings, \Psr\Container\ContainerInterface $c) {
- /** @var \Piwik\Plugins\Login\SystemSettings $settings */
-
- \Piwik\Access::doAsSuperUser(function () use ($settings, $c) {
- if ($c->get('test.vars.bruteForceBlockIps')) {
- $settings->blacklistedBruteForceIps->setValue(array('10.2.3.4'));
- } elseif (\Piwik\SettingsPiwik::isMatomoInstalled()) {
- $settings->blacklistedBruteForceIps->setValue(array());
- }
- });
-
- return $settings;
- }),
- 'Piwik\Plugins\Login\Security\BruteForceDetection' => DI\decorate(function ($detection, \Psr\Container\ContainerInterface $c) {
- /** @var \Piwik\Plugins\Login\Security\BruteForceDetection $detection */
-
- if ($c->get('test.vars.bruteForceBlockIps')) {
- for ($i = 0; $i < 30; $i++) {
- // we block a random IP
- $detection->addFailedAttempt('10.55.66.77');
- }
- } else if ($c->get('test.vars.bruteForceBlockThisIp')) {
- for ($i = 0; $i < 30; $i++) {
- // we block this IP
- $detection->addFailedAttempt(\Piwik\IP::getIpFromHeader());
- }
- } elseif (\Piwik\SettingsPiwik::isMatomoInstalled()) {
- // prevent tests from blocking other tests
- $detection->deleteAll();
- }
-
- return $detection;
- }),
-);
\ No newline at end of file
diff --git a/app/plugins/Login/lang/ga.json b/app/plugins/Login/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/Login/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Marketplace/Commands/SetLicenseKey.php b/app/plugins/Marketplace/Commands/SetLicenseKey.php
index 7af3389f6..bb3e52958 100644
--- a/app/plugins/Marketplace/Commands/SetLicenseKey.php
+++ b/app/plugins/Marketplace/Commands/SetLicenseKey.php
@@ -9,11 +9,10 @@
namespace Piwik\Plugins\Marketplace\Commands;
use Piwik\Plugin\ConsoleCommand;
-use Piwik\Plugins\Marketplace\LicenseKey;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
-use Piwik\Plugins\Marketplace\Api;
+use Piwik\Plugins\Marketplace\API;
/**
* marketplace:set-license-key console command
@@ -32,12 +31,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
$licenseKey = $input->getOption('license-key');
if (empty(trim($licenseKey))) {
- Api::getInstance()->deleteLicenseKey();
+ API::getInstance()->deleteLicenseKey();
$output->writeln("License key removed.");
return;
}
- Api::getInstance()->saveLicenseKey($licenseKey);
+ API::getInstance()->saveLicenseKey($licenseKey);
$output->writeln("License key set.");
}
}
diff --git a/app/plugins/Marketplace/Controller.php b/app/plugins/Marketplace/Controller.php
index f138a5b49..3436e34b0 100644
--- a/app/plugins/Marketplace/Controller.php
+++ b/app/plugins/Marketplace/Controller.php
@@ -209,7 +209,7 @@ public function overview()
$view = $this->configureViewAndCheckPermission('@Marketplace/overview');
$show = Common::getRequestVar('show', 'plugins', 'string');
- $query = Common::getRequestVar('query', '', 'string', $_POST);
+ $query = Common::getRequestVar('query', '', 'string');
$sort = new Sort();
$sort = $sort->getSort();
diff --git a/app/plugins/Marketplace/Marketplace.php b/app/plugins/Marketplace/Marketplace.php
index a07ef9b1d..8be0a63ae 100644
--- a/app/plugins/Marketplace/Marketplace.php
+++ b/app/plugins/Marketplace/Marketplace.php
@@ -9,10 +9,7 @@
namespace Piwik\Plugins\Marketplace;
use Piwik\Container\StaticContainer;
-use Piwik\Piwik;
use Piwik\Plugin;
-use Piwik\Plugins\Marketplace\Widgets\GetNewPlugins;
-use Piwik\Plugins\Marketplace\Widgets\GetPremiumFeatures;
use Piwik\SettingsPiwik;
use Piwik\Widget\WidgetsList;
@@ -58,17 +55,29 @@ public function getStylesheetFiles(&$stylesheets)
public function getJsFiles(&$jsFiles)
{
$jsFiles[] = "node_modules/iframe-resizer/js/iframeResizer.min.js";
-
- $jsFiles[] = "plugins/Marketplace/angularjs/plugins/plugin-name.directive.js";
- $jsFiles[] = "plugins/Marketplace/angularjs/licensekey/licensekey.controller.js";
- $jsFiles[] = "plugins/Marketplace/angularjs/marketplace/marketplace.controller.js";
- $jsFiles[] = "plugins/Marketplace/angularjs/marketplace/marketplace.directive.js";
}
public function getClientSideTranslationKeys(&$translationKeys)
{
$translationKeys[] = 'Marketplace_LicenseKeyActivatedSuccess';
$translationKeys[] = 'Marketplace_LicenseKeyDeletedSuccess';
+ $translationKeys[] = 'Marketplace_Show';
+ $translationKeys[] = 'Marketplace_Sort';
+ $translationKeys[] = 'General_Plugins';
+ $translationKeys[] = 'Marketplace_PaidPluginsNoLicenseKeyIntro';
+ $translationKeys[] = 'Marketplace_PaidPluginsWithLicenseKeyIntro';
+ $translationKeys[] = 'Marketplace_RemoveLicenseKey';
+ $translationKeys[] = 'Marketplace_ViewSubscriptions';
+ $translationKeys[] = 'Marketplace_InstallPurchasedPlugins';
+ $translationKeys[] = 'Marketplace_InstallAllPurchasedPlugins';
+ $translationKeys[] = 'Marketplace_InstallThesePlugins';
+ $translationKeys[] = 'Marketplace_InstallAllPurchasedPluginsAction';
+ $translationKeys[] = 'Marketplace_ConfirmRemoveLicense';
+ $translationKeys[] = 'Marketplace_PaidPluginsNoLicenseKeyIntroNoSuperUserAccess';
+ $translationKeys[] = 'Marketplace_LicenseKeyIsValidShort';
+ $translationKeys[] = 'Marketplace_LicenseKey';
+ $translationKeys[] = 'CoreUpdater_UpdateTitle';
+ $translationKeys[] = 'Marketplace_ActivateLicenseKey';
}
/**
diff --git a/app/plugins/Marketplace/Widgets/GetPremiumFeatures.php b/app/plugins/Marketplace/Widgets/GetPremiumFeatures.php
index 8f27f8745..35a35766f 100644
--- a/app/plugins/Marketplace/Widgets/GetPremiumFeatures.php
+++ b/app/plugins/Marketplace/Widgets/GetPremiumFeatures.php
@@ -8,9 +8,7 @@
*/
namespace Piwik\Plugins\Marketplace\Widgets;
-use Piwik\Common;
use Piwik\Piwik;
-use Piwik\Plugin;
use Piwik\Plugins\Marketplace\Api\Client;
use Piwik\Plugins\Marketplace\Input\PurchaseType;
use Piwik\Plugins\Marketplace\Input\Sort;
@@ -45,8 +43,9 @@ public function render()
$plugins = $this->marketplaceApiClient->searchForPlugins('', '', Sort::METHOD_LAST_UPDATED, PurchaseType::TYPE_PAID);
- $plugins = array_filter($plugins, function ($plugin) {
- return empty($plugin['isBundle']);
+ //sort array by bundle first
+ usort($plugins, function ($item1, $item2) {
+ return $item1['isBundle'] < $item2['isBundle'] ? 1 : -1;
});
if (empty($plugins)) {
diff --git a/app/plugins/Marketplace/Widgets/Marketplace.php b/app/plugins/Marketplace/Widgets/Marketplace.php
index 678ae31ee..b662be032 100644
--- a/app/plugins/Marketplace/Widgets/Marketplace.php
+++ b/app/plugins/Marketplace/Widgets/Marketplace.php
@@ -8,11 +8,7 @@
*/
namespace Piwik\Plugins\Marketplace\Widgets;
-use Piwik\Common;
use Piwik\Piwik;
-use Piwik\Plugins\Marketplace\Api\Client;
-use Piwik\Plugins\Marketplace\Input\PurchaseType;
-use Piwik\Plugins\Marketplace\Input\Sort;
use Piwik\Widget\Widget;
use Piwik\Widget\WidgetConfig;
diff --git a/app/plugins/Marketplace/config/test.php b/app/plugins/Marketplace/config/test.php
deleted file mode 100644
index 94dba1508..000000000
--- a/app/plugins/Marketplace/config/test.php
+++ /dev/null
@@ -1,144 +0,0 @@
- function (ContainerInterface $c) {
- // if you wonder why this here is configured here again, and the same as in `config.php`,
- // it is because someone might have overwritten MarketplaceEndpoit in local config.php and we want
- // to make sure system tests of marketplace are ran against plugins.piwik.org
- $domain = 'http://plugins.piwik.org';
- $updater = $c->get('Piwik\Plugins\CoreUpdater\Updater');
-
- if ($updater->isUpdatingOverHttps()) {
- $domain = str_replace('http://', 'https://', $domain);
- }
-
- return $domain;
- },
- 'Piwik\Plugins\Marketplace\Consumer' => function (ContainerInterface $c) {
- $consumerTest = $c->get('test.vars.consumer');
- $licenseKey = new LicenseKey();
-
- if ($consumerTest == 'validLicense') {
- $consumer = MockConsumer::buildValidLicense();
- $licenseKey->set('123456789');
- } elseif ($consumerTest == 'exceededLicense') {
- $consumer = MockConsumer::buildExceededLicense();
- $licenseKey->set('1234567891');
- } elseif ($consumerTest == 'expiredLicense') {
- $consumer = MockConsumer::buildExpiredLicense();
- $licenseKey->set('1234567892');
- } else {
- $consumer = MockConsumer::buildNoLicense();
- $licenseKey->set(null);
- }
-
- return $consumer;
- },
- 'Piwik\Plugins\Marketplace\Plugins' => DI\decorate(function ($previous, ContainerInterface $c) {
- /** @var \Piwik\Plugins\Marketplace\Plugins $previous */
- $previous->setPluginsHavingUpdateCache(null);
-
- $pluginNames = $c->get('test.vars.mockMarketplaceAssumePluginNamesActivated');
-
- if (!empty($pluginNames)) {
- /** @var \Piwik\Plugins\Marketplace\Plugins $previous */
- $previous->setActivatedPluginNames($pluginNames);
- }
-
- return $previous;
- }),
- 'Piwik\Plugins\Marketplace\Api\Client' => DI\decorate(function ($previous) {
- /** @var \Piwik\Plugins\Marketplace\Api\Client $previous */
- $previous->clearAllCacheEntries();
-
- return $previous;
- }),
- 'Piwik\Plugins\Marketplace\Plugins\InvalidLicenses' => DI\decorate(function ($previous, ContainerInterface $c) {
-
- $pluginNames = $c->get('test.vars.mockMarketplaceAssumePluginNamesActivated');
-
- if (!empty($pluginNames)) {
- /** @var \Piwik\Plugins\Marketplace\Plugins\InvalidLicenses $previous */
- $previous->setActivatedPluginNames($pluginNames);
- $previous->clearCache();
- }
-
- return $previous;
-
- }),
- 'Piwik\Plugins\Marketplace\Api\Service' => DI\decorate(function ($previous, ContainerInterface $c) {
- if (!$c->get('test.vars.mockMarketplaceApiService')) {
- return $previous;
- }
-
- // for ui tests
- $service = new MockService();
-
- $key = new LicenseKey();
- $accessToken = $key->get();
-
- $service->authenticate($accessToken);
-
- function removeReviewsUrl($content)
- {
- $content = json_decode($content, true);
- if (!empty($content['shop']['reviews']['embedUrl'])) {
- $content['shop']['reviews']['embedUrl'] = '';
- }
- return json_encode($content);
- }
-
- $isExceededUser = $c->get('test.vars.consumer') === 'exceededLicense';
- $isExpiredUser = $c->get('test.vars.consumer') === 'expiredLicense';
- $isValidUser = $c->get('test.vars.consumer') === 'validLicense';
-
- $service->setOnDownloadCallback(function ($action, $params) use ($service, $isExceededUser, $isValidUser, $isExpiredUser) {
- if ($action === 'info') {
- return $service->getFixtureContent('v2.0_info.json');
- } elseif ($action === 'consumer' && $service->getAccessToken() === 'valid') {
- return $service->getFixtureContent('v2.0_consumer-access_token-consumer2_paid1.json');
- } elseif ($action === 'consumer/validate' && $service->getAccessToken() === 'valid') {
- return $service->getFixtureContent('v2.0_consumer_validate-access_token-consumer2_paid1.json');
- } elseif ($action === 'consumer' && $service->getAccessToken() === 'invalid') {
- return $service->getFixtureContent('v2.0_consumer-access_token-notexistingtoken.json');
- } elseif ($action === 'consumer/validate' && $service->getAccessToken() === 'invalid') {
- return $service->getFixtureContent('v2.0_consumer_validate-access_token-notexistingtoken.json');
- } elseif ($action === 'plugins' && empty($params['purchase_type']) && empty($params['query'])) {
- return $service->getFixtureContent('v2.0_plugins.json');
- } elseif ($action === 'plugins' && $isExceededUser && !empty($params['purchase_type']) && $params['purchase_type'] === PurchaseType::TYPE_PAID && empty($params['query'])) {
- return $service->getFixtureContent('v2.0_plugins-purchase_type-paid-num_users-201-access_token-consumer2_paid1.json');
- } elseif ($action === 'plugins' && $isExpiredUser && !empty($params['purchase_type']) && $params['purchase_type'] === PurchaseType::TYPE_PAID && empty($params['query'])) {
- return $service->getFixtureContent('v2.0_plugins-purchase_type-paid-access_token-consumer1_paid2_custom1.json');
- } elseif ($action === 'plugins' && ($service->hasAccessToken() || $isValidUser) && !empty($params['purchase_type']) && $params['purchase_type'] === PurchaseType::TYPE_PAID && empty($params['query'])) {
- return $service->getFixtureContent('v2.0_plugins-purchase_type-paid-access_token-consumer2_paid1.json');
- } elseif ($action === 'plugins' && !$service->hasAccessToken() && !empty($params['purchase_type']) && $params['purchase_type'] === PurchaseType::TYPE_PAID && empty($params['query'])) {
- return $service->getFixtureContent('v2.0_plugins-purchase_type-paid-access_token-notexistingtoken.json');
- } elseif ($action === 'themes' && empty($params['purchase_type']) && empty($params['query'])) {
- return $service->getFixtureContent('v2.0_themes.json');
- } elseif ($action === 'plugins/Barometer/info') {
- return $service->getFixtureContent('v2.0_plugins_Barometer_info.json');
- } elseif ($action === 'plugins/TreemapVisualization/info') {
- return $service->getFixtureContent('v2.0_plugins_TreemapVisualization_info.json');
- } elseif ($action === 'plugins/PaidPlugin1/info' && $service->hasAccessToken() && $isExceededUser) {
- $content = $service->getFixtureContent('v2.0_plugins_PaidPlugin1_info-purchase_type-paid-num_users-201-access_token-consumer2_paid1.json');
- return removeReviewsUrl($content);
- } elseif ($action === 'plugins/PaidPlugin1/info' && $service->hasAccessToken()) {
- $content = $service->getFixtureContent('v2.0_plugins_PaidPlugin1_info-access_token-consumer3_paid1_custom2.json');
- return removeReviewsUrl($content);
- } elseif ($action === 'plugins/PaidPlugin1/info' && !$service->hasAccessToken()) {
- $content = $service->getFixtureContent('v2.0_plugins_PaidPlugin1_info.json');
- return removeReviewsUrl($content);
- } elseif ($action === 'plugins/checkUpdates') {
- return $service->getFixtureContent('v2.0_plugins_checkUpdates-pluginspluginsnameAnonymousPi.json');
- }
- });
-
- return $service;
- })
-);
\ No newline at end of file
diff --git a/app/plugins/Marketplace/lang/ga.json b/app/plugins/Marketplace/lang/ga.json
new file mode 100644
index 000000000..0967ef424
--- /dev/null
+++ b/app/plugins/Marketplace/lang/ga.json
@@ -0,0 +1 @@
+{}
diff --git a/app/plugins/Marketplace/templates/getPremiumFeatures.twig b/app/plugins/Marketplace/templates/getPremiumFeatures.twig
index 3663ff69c..c0cc82747 100644
--- a/app/plugins/Marketplace/templates/getPremiumFeatures.twig
+++ b/app/plugins/Marketplace/templates/getPremiumFeatures.twig
@@ -1,14 +1,20 @@
-
{{ 'Marketplace_SupportMatomoThankYou'|translate }}
+
{{ 'Marketplace_TrialHints'|translate(""," ")|raw }}
+
{{ 'Marketplace_SupportMatomoThankYou'|translate }}
{% for plugin in plugins %}
{{ plugin.displayName }}
+ {% if plugin.specialOffer !='' %}
+
+ {{ 'Marketplace_SpecialOffer'|translate }}: {{ plugin.specialOffer }}
+
+ {% endif %}
- {{ plugin.description }}
+ {% if plugin.isBundle %} {{ 'Marketplace_SpecialOffer'|translate }}: {% endif %}{{ plugin.description }}
{{ 'General_MoreDetails'|translate }}
diff --git a/app/plugins/Marketplace/templates/licenseform.twig b/app/plugins/Marketplace/templates/licenseform.twig
index 9e5b9ab59..5c4f41a6c 100644
--- a/app/plugins/Marketplace/templates/licenseform.twig
+++ b/app/plugins/Marketplace/templates/licenseform.twig
@@ -1,75 +1,10 @@
-{% set defaultLicenseKeyFields %}
-
-
-
-{% endset %}
-
-
-
- {% if isValidConsumer %}
- {% if isSuperUser %}
- {{ 'Marketplace_PaidPluginsWithLicenseKeyIntro'|translate('')|raw }}
-
-
-
-
-
- {% endif %}
-
- {% else %}
- {% if isSuperUser %}
- {{ 'Marketplace_PaidPluginsNoLicenseKeyIntro'|translate("
", " ")|raw }}
-
-
-
-
- {{ defaultLicenseKeyFields|raw }}
-
-
-
-
- {% else %}
- {{ 'Marketplace_PaidPluginsNoLicenseKeyIntroNoSuperUserAccess'|translate("
", " ")|raw }}
- {% endif %}
-
- {% endif %}
-
-
-
-
-
-
{{ 'Marketplace_ConfirmRemoveLicense'|translate }}
-
-
-
+
diff --git a/app/plugins/Marketplace/templates/overview.twig b/app/plugins/Marketplace/templates/overview.twig
index c55c047a9..81c43d97e 100644
--- a/app/plugins/Marketplace/templates/overview.twig
+++ b/app/plugins/Marketplace/templates/overview.twig
@@ -4,7 +4,7 @@
{% block content %}
-
+
', '')|raw }}
{% endif %}
-
{% include '@Marketplace/licenseform.twig' %}
{% include '@Marketplace/uploadPluginDialog.twig' %}
-
-
-
-
-
-
-
- {# Hide filters and search for themes because we don't have many of them #}
- {% if (pluginsToShow|length) > 20 or query %}
-
- {% endif %}
-
+
{% include '@Marketplace/plugin-list.twig' %}
diff --git a/app/plugins/Marketplace/templates/paid-plugins-install-list.twig b/app/plugins/Marketplace/templates/paid-plugins-install-list.twig
deleted file mode 100644
index 6c2feb475..000000000
--- a/app/plugins/Marketplace/templates/paid-plugins-install-list.twig
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
{{ 'Marketplace_InstallAllPurchasedPlugins'|translate }}
-
- {{ 'Marketplace_InstallThesePlugins'|translate }}
-
-
-
- {% for pluginName in paidPluginsToInstallAtOnce %}
- {{ pluginName }}
- {% endfor %}
-
-
-
-
-
-
-
diff --git a/app/plugins/Marketplace/templates/plugin-details.twig b/app/plugins/Marketplace/templates/plugin-details.twig
index 1cdfc2a07..794e6fed0 100644
--- a/app/plugins/Marketplace/templates/plugin-details.twig
+++ b/app/plugins/Marketplace/templates/plugin-details.twig
@@ -123,6 +123,7 @@
{% if plugin.shop.variations|length %}
+
{{ 'Marketplace_TryFreeTrialTitle'|translate }}