| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| var DataTable_RowActions_Registry = { |
|
|
| registry: [], |
|
|
| register: function (action) { |
| var createInstance = action.createInstance; |
| action.createInstance = function (dataTable, param) { |
| var instance = createInstance(dataTable, param); |
| instance.actionName = action.name; |
| return instance; |
| }; |
|
|
| this.registry.push(action); |
| }, |
|
|
| getAvailableActionsForReport: function (dataTableParams, tr) { |
| if (dataTableParams.disable_row_actions == '1') { |
| return []; |
| } |
|
|
| var available = []; |
| for (var i = 0; i < this.registry.length; i++) { |
| if (this.registry[i].isAvailableOnReport(dataTableParams, tr)) { |
| available.push(this.registry[i]); |
| } |
| } |
| available.sort(function (a, b) { |
| return b.order - a.order; |
| }); |
| return available; |
| }, |
|
|
| getActionByName: function (name) { |
| for (var i = 0; i < this.registry.length; i++) { |
| if (this.registry[i].name == name) { |
| return this.registry[i]; |
| } |
| } |
| return false; |
| } |
|
|
| }; |
|
|
| |
| DataTable_RowActions_Registry.register({ |
|
|
| name: 'RowEvolution', |
|
|
| dataTableIcon: 'icon-evolution', |
|
|
| order: 50, |
|
|
| dataTableIconTooltip: [ |
| _pk_translate('General_RowEvolutionRowActionTooltipTitle'), |
| _pk_translate('General_RowEvolutionRowActionTooltip') |
| ], |
|
|
| createInstance: function (dataTable, param) { |
| if (dataTable !== null && typeof dataTable.rowEvolutionActionInstance != 'undefined') { |
| return dataTable.rowEvolutionActionInstance; |
| } |
|
|
| if (dataTable === null && param) { |
| |
| |
| |
| |
| |
| |
| |
| var report = param.split(':')[0]; |
| var div = $(require('piwik/UI').DataTable.getDataTableByReport(report)); |
| if (div.length && div.data('uiControlObject')) { |
| dataTable = div.data('uiControlObject'); |
| if (typeof dataTable.rowEvolutionActionInstance != 'undefined') { |
| return dataTable.rowEvolutionActionInstance; |
| } |
| } |
| } |
|
|
| var instance = new DataTable_RowActions_RowEvolution(dataTable); |
| if (dataTable !== null) { |
| dataTable.rowEvolutionActionInstance = instance; |
| } |
| return instance; |
| }, |
|
|
| isAvailableOnReport: function (dataTableParams) { |
| return ( |
| typeof dataTableParams.disable_row_evolution == 'undefined' |
| || dataTableParams.disable_row_evolution == "0" |
| ); |
| }, |
|
|
| isAvailableOnRow: function (dataTableParams, tr) { |
| return !tr.hasClass('totalsRow'); |
| } |
|
|
| }); |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
|
|
| function DataTable_RowAction(dataTable) { |
| this.dataTable = dataTable; |
|
|
| |
| this.trEventName = 'piwikTriggerRowAction'; |
|
|
| |
| this.actionName = 'RowAction'; |
| } |
|
|
| |
| DataTable_RowAction.prototype.initTr = function (tr) { |
| var self = this; |
|
|
| |
| |
| |
| |
| |
| tr.unbind(self.trEventName).bind(self.trEventName, function (e, params) { |
| self.trigger($(this), params.originalEvent, params.label, params.originalRow); |
| }); |
| }; |
|
|
| |
| |
| |
| |
| DataTable_RowAction.prototype.trigger = function (tr, e, subTableLabel, originalRow) { |
| var label = this.getLabelFromTr(tr); |
|
|
| |
| if (subTableLabel) { |
| var separator = ' > '; |
| label += separator + subTableLabel; |
| } |
|
|
| |
| var subtable = tr.closest('table'); |
| if (subtable.is('.subDataTable')) { |
| subtable.closest('tr').prev().trigger(this.trEventName, { |
| label: label, |
| originalEvent: e, |
| originalRow: tr |
| }); |
| return; |
| } |
|
|
| |
| var $dataTable = subtable.closest('div.dataTable'); |
| if ($dataTable.hasClass('dataTableActions') |
| || $dataTable.data('table-type') === 'ActionsDataTable' |
| ) { |
| var allClasses = tr.attr('class'); |
| var matches = allClasses.match(/level[0-9]+/); |
| var level = parseInt(matches[0].substring(5, matches[0].length), 10); |
| if (level > 0) { |
| |
| var findLevel = 'level' + (level - 1); |
| var ptr = tr; |
| while ((ptr = ptr.prev()).length) { |
| if (!ptr.hasClass(findLevel) || ptr.hasClass('nodata')) { |
| continue; |
| } |
| ptr.trigger(this.trEventName, { |
| label: label, |
| originalEvent: e, |
| originalRow: tr |
| }); |
| return; |
| } |
| } |
| } |
|
|
| this.performAction(label, tr, e, originalRow); |
| }; |
|
|
| |
| DataTable_RowAction.prototype.getLabelFromTr = function (tr) { |
| if (tr.data('label')) { |
| return tr.data('label'); |
| } |
|
|
| var rowMetadata = this.getRowMetadata(tr); |
| if (rowMetadata.combinedLabel) { |
| return '@' + rowMetadata.combinedLabel; |
| } |
|
|
| var label = tr.find('span.label'); |
|
|
| |
| var value = label.data('originalText'); |
|
|
| if (!value) { |
| value = label.text(); |
| } |
| value = value.trim(); |
| value = encodeURIComponent(value); |
|
|
| |
| if (!tr.hasClass('subDataTable')) { |
| value = '@' + value; |
| } |
|
|
| return value; |
| }; |
|
|
| |
| DataTable_RowAction.prototype.getRowMetadata = function (tr) { |
| return tr.data('row-metadata') || {}; |
| }; |
|
|
| |
| |
| |
| |
| DataTable_RowAction.prototype.openPopover = function (parameter) { |
| broadcast.propagateNewPopoverParameter('RowAction', this.actionName + ':' + parameter); |
| }; |
|
|
| broadcast.addPopoverHandler('RowAction', function (param) { |
| var paramParts = param.split(':'); |
| var rowActionName = paramParts[0]; |
| paramParts.shift(); |
| param = paramParts.join(':'); |
|
|
| var rowAction = DataTable_RowActions_Registry.getActionByName(rowActionName); |
| if (rowAction) { |
| rowAction.createInstance(null, param).doOpenPopover(param); |
| } |
| }); |
|
|
| |
| DataTable_RowAction.prototype.performAction = function (label, tr, e) { |
| }; |
| DataTable_RowAction.prototype.doOpenPopover = function (parameter) { |
| }; |
|
|
| |
| |
| |
|
|
| function DataTable_RowActions_RowEvolution(dataTable) { |
| this.dataTable = dataTable; |
| this.trEventName = 'piwikTriggerRowEvolution'; |
|
|
| |
| this.multiEvolutionRows = []; |
| this.multiEvolutionRowsPretty = []; |
| this.multiEvolutionRowsSeries = []; |
| this.popoverRequestParams = null; |
| this._popoverRequest = null; |
| this._themeModeChangeListener = null; |
| this._popoverRequestSequence = 0; |
| } |
|
|
| |
| DataTable_RowActions_RowEvolution.launch = function (apiMethod, label) { |
| var param = 'RowEvolution:' + apiMethod + ':0:' + label; |
| broadcast.propagateNewPopoverParameter('RowAction', param); |
| }; |
|
|
| DataTable_RowActions_RowEvolution.prototype = new DataTable_RowAction; |
|
|
| DataTable_RowActions_RowEvolution.prototype.performAction = function (label, tr, e, originalRow) { |
| if (e.shiftKey) { |
| |
| this.addMultiEvolutionRow(label, $(originalRow || tr).data('comparison-series'), originalRow || tr); |
| return; |
| } |
|
|
| this.addMultiEvolutionRow(label, $(originalRow || tr).data('comparison-series'), originalRow || tr); |
|
|
| |
| var extraParams = $.extend({}, $(originalRow || tr).data('param-override')); |
| if (typeof extraParams !== 'object') { |
| extraParams = {}; |
| } |
|
|
| if (this.multiEvolutionRows.length > 1) { |
| extraParams.action = 'getMultiRowEvolutionPopover'; |
| label = this.multiEvolutionRows.join(','); |
|
|
| labelPretty = this.multiEvolutionRowsPretty.join(','); |
| if (label != labelPretty) { |
| extraParams.labelPretty = labelPretty; |
| } |
|
|
| if (this.multiEvolutionRowsSeries.length > 1) { |
| var MatomoUrl = window.CoreHome.MatomoUrl; |
| extraParams.compareDates = MatomoUrl.parsed.value.compareDates; |
| extraParams.comparePeriods = MatomoUrl.parsed.value.comparePeriods; |
| extraParams.compareSegments = MatomoUrl.parsed.value.compareSegments; |
| extraParams.labelSeries = this.multiEvolutionRowsSeries.join(','); |
|
|
| |
| |
| delete extraParams.period; |
| delete extraParams.date; |
| delete extraParams.segment; |
| } |
| } else { |
| var labelPretty = this.getPrettyLabel(originalRow || tr); |
| if (labelPretty && labelPretty != label) { |
| extraParams['labelPretty'] = labelPretty; |
| } |
| } |
|
|
| $.each(this.dataTable.param, function (index, value) { |
| |
| if (DataTable_RowActions_RowEvolution.isAllowedIdExtraParam(index, value)) { |
| extraParams[index] = value; |
| } |
| }); |
|
|
| if (this.dataTable && this.dataTable.jsViewDataTable === 'tableGoals') { |
| |
| |
| if (extraParams['idGoal']) { |
| extraParams['showGoalMetricsForGoal'] = extraParams['idGoal']; |
| delete(extraParams['idGoal']); |
| } |
| |
| |
| else { |
| extraParams['showGoalMetricsForGoal'] = -1; |
| } |
| } |
|
|
| |
| if (this.dataTable.param.abandonedCarts !== undefined) { |
| extraParams['abandonedCarts'] = this.dataTable.param.abandonedCarts; |
| } |
|
|
| if (this.dataTable.param.secondaryDimension !== undefined) { |
| extraParams['secondaryDimension'] = this.dataTable.param.secondaryDimension; |
| } |
|
|
| if (this.dataTable.param.flat !== undefined) { |
| var unflattenActionLabel = function(label) { |
| |
| |
| |
| |
| |
| |
| |
| |
| return label.split(',').map(function(item) { |
| var startsWithAt = item.startsWith('@'); |
| if (startsWithAt ) { |
| item = item.slice(1); |
| } |
|
|
| item = decodeURIComponent(item); |
|
|
| if (item === '/') { |
| return (startsWithAt ? '@' : '') + encodeURIComponent('/index'); |
| } |
|
|
| var isIndex = false; |
|
|
| if (item.endsWith('/')) { |
| item = item.slice(0, -1); |
| isIndex = true; |
| } |
| if (item.startsWith('/')) { |
| item = item.slice(1); |
| } |
|
|
| var parts = item.split('/').map(encodeURIComponent); |
|
|
| if (isIndex) { |
| parts.push(encodeURIComponent('/index')); |
| } else { |
| parts[parts.length - 1] = '/' + parts[parts.length - 1]; |
| } |
|
|
| if (startsWithAt ) { |
| parts[parts.length - 1] = '@' + parts[parts.length - 1]; |
| } |
|
|
| return parts.join(' > '); |
| }).join(','); |
| }; |
|
|
| if ( |
| this.dataTable.param.module === 'Actions' && this.dataTable.param.action === 'getPageUrls' |
| && this.dataTable.param.flat && label.indexOf(' > ') === -1 |
| ) { |
| |
| |
| |
| |
| |
| |
| |
| label = unflattenActionLabel(label); |
| extraParams['flat'] = 0; |
| } else { |
| extraParams['flat'] = this.dataTable.param.flat; |
| } |
| } |
|
|
| var apiMethod = this.dataTable.param.module + '.' + this.dataTable.param.action; |
| this.openPopover(apiMethod, extraParams, label); |
| }; |
|
|
| DataTable_RowActions_RowEvolution.prototype.getPrettyLabel = function getPrettyLabel(tr) { |
| if (!this.dataTable.props.row_identifier || this.dataTable.props.row_identifier === 'label') { |
| return null; |
| } |
|
|
| var prettyLabel = []; |
|
|
| var row = $(tr); |
| while (row.length) { |
| var label = row.data('label-pretty') || this.getLabelFromTr(row); |
| prettyLabel.unshift(label); |
|
|
| var subtable = row.closest('table'); |
| if (subtable.is('.subDataTable')) { |
| row = subtable.closest('tr').prev(); |
| } else { |
| break; |
| } |
| } |
|
|
| return prettyLabel.join(' > '); |
| }; |
|
|
| DataTable_RowActions_RowEvolution.prototype.addMultiEvolutionRow = function (label, seriesIndex, tr) { |
| if (typeof seriesIndex !== 'undefined') { |
| var self = this; |
|
|
| var found = false; |
| this.multiEvolutionRows.forEach(function (rowLabel, index) { |
| var rowSeriesIndex = self.multiEvolutionRowsSeries[index]; |
| if (label === rowLabel && seriesIndex === rowSeriesIndex) { |
| found = true; |
| return false; |
| } |
| }); |
|
|
| if (!found) { |
| this.multiEvolutionRows.push(label); |
| this.multiEvolutionRowsPretty.push(this.getPrettyLabel(tr)); |
| this.multiEvolutionRowsSeries.push(seriesIndex); |
| } |
| } else if ($.inArray(label, this.multiEvolutionRows) === -1) { |
| this.multiEvolutionRows.push(label); |
| this.multiEvolutionRowsPretty.push(this.getPrettyLabel(tr)) |
|
|
| this.multiEvolutionRowsSeries = []; |
| } |
| }; |
|
|
| DataTable_RowActions_RowEvolution.prototype.openPopover = function (apiMethod, extraParams, label) { |
| var urlParam = apiMethod + ':' + encodeURIComponent(JSON.stringify(extraParams)) + ':' + label; |
| DataTable_RowAction.prototype.openPopover.apply(this, [urlParam]); |
| }; |
|
|
| |
| |
| DataTable_RowActions_RowEvolution.allowedExtraParamKeys = [ |
| 'column', |
| 'action', |
| 'labelPretty', |
| 'labelSeries', |
| 'showGoalMetricsForGoal', |
| 'abandonedCarts', |
| 'secondaryDimension', |
| 'flat', |
| 'compareDates', |
| 'comparePeriods', |
| 'compareSegments', |
| 'segment', |
| 'period', |
| 'date' |
| ]; |
|
|
| |
| |
| |
| DataTable_RowActions_RowEvolution.isAllowedIdExtraParam = function (key, value) { |
| return key !== 'idSite' |
| && key.indexOf('id') === 0 |
| && ($.isNumeric(value) || (typeof value === 'string' && value.indexOf('ecommerce') === 0)); |
| }; |
|
|
| |
| |
| |
| |
| DataTable_RowActions_RowEvolution.filterAllowedExtraParams = function (parsed) { |
| var result = {}; |
| var allowed = DataTable_RowActions_RowEvolution.allowedExtraParamKeys; |
|
|
| for (var key in parsed) { |
| if (!Object.prototype.hasOwnProperty.call(parsed, key)) { |
| continue; |
| } |
|
|
| var value = parsed[key]; |
|
|
| |
| |
| |
| if (key === 'action' && value !== 'getMultiRowEvolutionPopover') { |
| continue; |
| } |
|
|
| if (allowed.indexOf(key) !== -1 |
| || DataTable_RowActions_RowEvolution.isAllowedIdExtraParam(key, value)) { |
| result[key] = value; |
| } |
| } |
|
|
| return result; |
| }; |
|
|
| DataTable_RowActions_RowEvolution.prototype.doOpenPopover = function (urlParam) { |
| var urlParamParts = urlParam.split(':'); |
| var apiMethod = urlParamParts.shift(); |
| var extraParamsString = urlParamParts.shift(); |
| var label = urlParamParts.join(':'); |
|
|
| var extraParams = {}; |
| try { |
| var parsed = JSON.parse(decodeURIComponent(extraParamsString)); |
| if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) { |
| throw new Error('extraParams must be a JSON object'); |
| } |
| extraParams = DataTable_RowActions_RowEvolution.filterAllowedExtraParams(parsed); |
| } catch (e) { |
| |
| if (extraParamsString == '1') { |
| extraParams.action = 'getMultiRowEvolutionPopover'; |
| } else if (extraParamsString != '0') { |
| extraParams.action = 'getMultiRowEvolutionPopover'; |
| extraParams.column = String(extraParamsString); |
| } |
| } |
|
|
| this.showRowEvolution(apiMethod, label, extraParams); |
| }; |
|
|
| DataTable_RowActions_RowEvolution.prototype.fetchRowEvolution = function (requestParams, callback) { |
| var ajaxRequest = new ajaxHelper(); |
| ajaxRequest.addParams(requestParams, 'get'); |
| ajaxRequest.withTokenInUrl(); |
| ajaxRequest.setCallback(callback); |
| ajaxRequest.setFormat('html'); |
| ajaxRequest.send(); |
| return ajaxRequest; |
| }; |
|
|
| DataTable_RowActions_RowEvolution.prototype.abortPopoverRequest = function () { |
| if (this._popoverRequest) { |
| this._popoverRequest.abort(); |
| this._popoverRequest = null; |
| } |
| }; |
|
|
| DataTable_RowActions_RowEvolution.prototype.loadLatestPopover = function (requestParams, callback) { |
| var self = this; |
| var requestSequence; |
|
|
| this.abortPopoverRequest(); |
| requestSequence = ++this._popoverRequestSequence; |
| this._popoverRequest = this.fetchRowEvolution(requestParams, function (html) { |
| self._popoverRequest = null; |
|
|
| if (!Piwik_Popover.isOpen() || requestSequence !== self._popoverRequestSequence) { |
| return; |
| } |
|
|
| callback(html); |
| }); |
| }; |
|
|
| |
| DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMethod, label, extraParams) { |
|
|
| var self = this; |
|
|
| |
| var box = Piwik_Popover.showLoading('Row Evolution'); |
| box.addClass('rowEvolutionPopover'); |
|
|
| |
| var requestParams = { |
| apiMethod: apiMethod, |
| label: label, |
| disableLink: 1 |
| }; |
|
|
| var callback = function (html) { |
| Piwik_Popover.setContent(html); |
|
|
| |
| var title = box.find('div.popover-title'); |
| if (title.length) { |
| Piwik_Popover.setTitle(title.html()); |
| title.remove(); |
| } |
|
|
| Piwik_Popover.onClose(function () { |
| if (!Piwik_Popover.isOpen()) { |
| |
| self.multiEvolutionRows = []; |
| self.multiEvolutionRowsPretty = []; |
| self.multiEvolutionRowsSeries = []; |
| self.popoverRequestParams = null; |
| self._popoverRequestSequence++; |
| self.abortPopoverRequest(); |
|
|
| if (self._themeModeChangeListener) { |
| window.removeEventListener('themeModeChange', self._themeModeChangeListener); |
| self._themeModeChangeListener = null; |
| } |
| } |
| }); |
|
|
| if (self.dataTable !== null) { |
| |
| box.find('.rowevolution-startmulti').click(function () { |
| Piwik_Popover.onClose(false); |
| broadcast.propagateNewPopoverParameter(false); |
| return false; |
| }); |
| } else { |
| |
| |
| |
| box.find('.compare-container, .rowevolution-startmulti').remove(); |
| } |
|
|
| |
| box.find('select.multirowevoltion-metric').change(function () { |
| var metric = $(this).val(); |
| Piwik_Popover.onClose(false); |
| extraParams.column = metric; |
| self.openPopover(apiMethod, extraParams, label); |
| return true; |
| }); |
| }; |
|
|
| requestParams.colors = JSON.stringify(piwik.getSparklineColors()); |
|
|
| var idDimension; |
|
|
| if (broadcast.getValueFromUrl('module') === 'Widgetize') { |
| idDimension = broadcast.getValueFromUrl('subcategory'); |
| } else { |
| idDimension = broadcast.getValueFromHash('subcategory'); |
| } |
|
|
| if (idDimension && ('' + idDimension).indexOf('customdimension') === 0) { |
| idDimension = ('' + idDimension).replace('customdimension', ''); |
| idDimension = parseInt(idDimension, 10); |
| if (idDimension > 0) { |
| requestParams.idDimension = idDimension; |
| } |
| } |
|
|
| var wantMultiRowEvolution = extraParams && extraParams.action === 'getMultiRowEvolutionPopover'; |
|
|
| $.extend(requestParams, extraParams); |
|
|
| |
| requestParams.module = 'CoreHome'; |
| requestParams.action = wantMultiRowEvolution ? 'getMultiRowEvolutionPopover' : 'getRowEvolutionPopover'; |
|
|
| this.popoverRequestParams = $.extend(true, {}, requestParams); |
|
|
| if (this._themeModeChangeListener) { |
| window.removeEventListener('themeModeChange', this._themeModeChangeListener); |
| } |
|
|
| this._themeModeChangeListener = function () { |
| if (!self.popoverRequestParams) { |
| return; |
| } |
|
|
| self.popoverRequestParams.colors = JSON.stringify(piwik.getSparklineColors()); |
| self.loadLatestPopover(self.popoverRequestParams, callback); |
| }; |
|
|
| window.addEventListener('themeModeChange', this._themeModeChangeListener); |
|
|
| this.loadLatestPopover(requestParams, callback); |
| }; |
|
|