File: D:/web/matomo.vdk/plugins/ScheduledReports/vue/src/ManageScheduledReport/ManageScheduledReport.vue
<!--
Matomo - free/libre analytics platform
@link https://matomo.org
@license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
-->
<template>
<div class="emailReports" ref="root">
<div ref="reportSentSuccess" />
<div ref="reportUpdatedSuccess" />
<div>
<div id="ajaxError" style="display:none"></div>
<div id="ajaxLoadingDiv" style="display:none;">
<div class="loadingPiwik">
<MatomoLoader />
{{ translate('General_LoadingData') }}
</div>
<div class="loadingSegment">
{{ translate('SegmentEditor_LoadingSegmentedDataMayTakeSomeTime') }}
</div>
</div>
<ListReports
v-show="showReportsList"
:content-title="contentTitle"
:user-login="userLogin"
:login-module="loginModule"
:reports="reports"
:site-name="decodedSiteName"
:segment-editor-activated="segmentEditorActivated"
:saved-segments-by-id="savedSegmentsById"
:periods="periods"
:report-types="reportTypes"
:download-output-type="downloadOutputType"
:language="language"
:report-formats-by-report-type="reportFormatsByReportType"
:sending-reports="sendingReports"
@create="createReport()"
@edit="editReport($event)"
@delete="deleteReport($event)"
@sendnow="sendReportNow($event)"
/>
<AddReport
v-if="showReportForm"
:report="report"
:periods="periods"
:param-periods="paramPeriods"
:report-type-options="reportTypeOptions"
:report-formats-by-report-type-options="reportFormatsByReportTypeOptions"
:display-formats="displayFormats"
:reports-by-category-by-report-type="reportsByCategoryByReportType"
:allow-multiple-reports-by-report-type="allowMultipleReportsByReportType"
:count-websites="countWebsites"
:site-name="decodedSiteName"
:selected-reports="selectedReports"
:selected-reports-order="selectedReportsOrder"
:report-types="reportTypes"
:segment-editor-activated="segmentEditorActivated"
:saved-segments-by-id="savedSegmentsById"
@toggle-selected-report="toggleSelectedReport($event.reportType, $event.uniqueId)"
@reorder-selected-reports="onReorderSelectedReports($event.reportType, $event.order)"
@change="onChangeProperty($event.prop, $event.value)"
@submit="submitReport()"
>
<template v-slot:report-parameters>
<slot name="report-parameters"></slot>
</template>
</AddReport>
<a id="bottom" />
</div>
</div>
</template>
<script lang="ts">
import { defineComponent, nextTick } from 'vue';
import {
AjaxHelper,
ContentTable,
Matomo,
MatomoLoader,
NotificationsStore,
translate,
} from 'CoreHome';
import { Form } from 'CorePluginsAdmin';
import AddReport from '../AddReport/AddReport.vue';
import ListReports from '../ListReports/ListReports.vue';
import { Report } from '../types';
import { adjustHourToTimezone } from '../utilities';
interface ManageScheduledReportState {
showReportsList: boolean;
report: Report;
selectedReports: Record<string, Record<string, boolean>>;
selectedReportsOrder: Record<string, string[]>;
sendingReports: Array<string|number>;
}
function scrollToTop() {
Matomo.helper.lazyScrollTo('.emailReports', 200);
}
function updateParameters(reportType: string, report: Report) {
if (window.updateReportParametersFunctions?.[reportType]) {
window.updateReportParametersFunctions[reportType](report);
}
}
function resetParameters(reportType: string, report: Report) {
if (window.resetReportParametersFunctions?.[reportType]) {
window.resetReportParametersFunctions[reportType](report);
}
}
window.resetReportParametersFunctions = window.resetReportParametersFunctions || {};
window.updateReportParametersFunctions = window.updateReportParametersFunctions || {};
window.getReportParametersFunctions = window.getReportParametersFunctions || {};
const { $ } = window;
const PENDING_NOTIFICATION_KEY = 'scheduledReports.pendingNotification';
const timeZoneDifferenceInHours = Matomo.timezoneOffset / 3600;
export default defineComponent({
props: {
contentTitle: {
type: String,
required: true,
},
userLogin: {
type: String,
required: true,
},
loginModule: {
type: String,
required: true,
},
reports: {
type: Array,
required: true,
},
siteName: {
type: String,
required: true,
},
segmentEditorActivated: Boolean,
savedSegmentsById: Object,
periods: {
type: Object,
required: true,
},
downloadOutputType: {
type: Number,
required: true,
},
language: {
type: String,
required: true,
},
reportFormatsByReportType: {
type: Object,
required: true,
},
paramPeriods: {
type: Object,
required: true,
},
reportTypeOptions: {
type: Object,
required: true,
},
reportFormatsByReportTypeOptions: {
type: Object,
required: true,
},
displayFormats: {
type: Object,
required: true,
},
reportsByCategoryByReportType: {
type: Object,
required: true,
},
allowMultipleReportsByReportType: {
type: Object,
required: true,
},
countWebsites: {
type: Number,
required: true,
},
reportTypes: {
type: Object,
required: true,
},
},
components: {
MatomoLoader,
AddReport,
ListReports,
},
directives: {
ContentTable,
Form,
},
mounted() {
$(this.$refs.root as HTMLElement).on('click', 'a.entityCancelLink', () => {
this.showListOfReports();
});
Matomo.postEvent('ScheduledReports.ManageScheduledReport.mounted', {
element: this.$refs.root,
});
const pendingMessage = typeof sessionStorage !== 'undefined'
? sessionStorage.getItem(PENDING_NOTIFICATION_KEY)
: null;
if (pendingMessage && this.$refs.reportUpdatedSuccess) {
sessionStorage.removeItem(PENDING_NOTIFICATION_KEY);
this.fadeInOutSuccessMessage(
this.$refs.reportUpdatedSuccess as HTMLElement,
pendingMessage,
false,
);
}
},
unmounted() {
Matomo.postEvent('ScheduledReports.ManageScheduledReport.unmounted', {
element: this.$refs.root,
});
},
data(): ManageScheduledReportState {
return {
showReportsList: true,
report: {} as unknown as Report,
selectedReports: {},
selectedReportsOrder: {},
sendingReports: [],
};
},
methods: {
sendReportNow(idReport: string|number) {
if (this.sendingReports.includes(idReport)) {
return;
}
scrollToTop();
this.sendingReports.push(idReport);
AjaxHelper.post(
{
method: 'ScheduledReports.sendReport',
},
{
idReport,
force: true,
},
).then(() => {
this.fadeInOutSuccessMessage(
this.$refs.reportSentSuccess as HTMLElement,
translate('ScheduledReports_ReportSent'),
false,
);
}).finally(() => {
this.sendingReports = this.sendingReports.filter(
(report: string | number) => report !== idReport,
);
});
},
formSetEditReport(idReport: number) {
const { ReportPlugin } = window;
let report: Report = {
idreport: idReport,
type: ReportPlugin.defaultReportType,
format: ReportPlugin.defaultReportFormat,
description: '',
period: ReportPlugin.defaultPeriod,
hour: ReportPlugin.defaultHour,
reports: [],
idsegment: '',
evolutionPeriodFor: 'prev',
evolutionPeriodN: ReportPlugin.defaultEvolutionPeriodN,
periodParam: ReportPlugin.defaultPeriod,
} as unknown as Report;
if (idReport > 0) {
report = ReportPlugin.reportList[idReport];
updateParameters(report.type, report);
} else {
resetParameters(report.type, report);
}
report.hour = adjustHourToTimezone(report.hour as string, timeZoneDifferenceInHours);
this.selectedReports = {};
this.selectedReportsOrder = {};
Object.values(report.reports).forEach((reportId) => {
this.selectedReports[report.type] = this.selectedReports[report.type] || {};
this.selectedReports[report.type][reportId] = true;
});
this.selectedReportsOrder[report.type] = Object.values(report.reports).map(
(reportId) => reportId as string,
);
report[`format${report.type}`] = report.format;
if (!report.idsegment) {
report.idsegment = '';
}
this.report = report;
this.report.description = Matomo.helper.htmlDecode(report.description);
},
fadeInOutSuccessMessage(selector: HTMLElement, message: string, reload = true) {
NotificationsStore.show({
message,
placeat: selector,
context: 'success',
noclear: true,
type: 'toast',
style: {
display: 'inline-block',
marginTop: '10px',
width: '100%',
},
id: 'scheduledReportSuccess',
});
if (reload) {
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem(PENDING_NOTIFICATION_KEY, message);
}
Matomo.helper.refreshAfter(2);
}
},
changedReportType() {
resetParameters(this.report.type, this.report);
},
deleteReport(idReport: string|number) {
Matomo.helper.modalConfirm('#confirm', {
yes: () => {
AjaxHelper.post(
{
method: 'ScheduledReports.deleteReport',
},
{
idReport,
},
{
redirectOnSuccess: true,
},
);
},
});
},
showListOfReports(shouldScrollToTop?: boolean) {
this.showReportsList = true;
Matomo.helper.hideAjaxError();
if (typeof shouldScrollToTop === 'undefined' || shouldScrollToTop) {
scrollToTop();
}
},
createReport() {
this.showReportsList = false;
// in nextTick so global report function records get manipulated before individual
// entries are used
nextTick(() => {
this.formSetEditReport(0);
});
},
editReport(reportId: number) {
this.showReportsList = false;
// in nextTick so global report function records get manipulated before individual
// entries are used
nextTick(() => {
this.formSetEditReport(reportId);
});
},
submitReport() {
const apiParameters: QueryParameters = {
idReport: this.report.idreport,
description: this.report.description,
idSegment: this.report.idsegment,
reportType: this.report.type,
reportFormat: this.report[`format${this.report.type}`] as string,
periodParam: this.report.periodParam,
evolutionPeriodFor: this.report.evolutionPeriodFor,
};
if (apiParameters.evolutionPeriodFor !== 'each') {
apiParameters.evolutionPeriodN = this.report.evolutionPeriodN;
}
const { period } = this.report;
const hour = adjustHourToTimezone(this.report.hour as string, -timeZoneDifferenceInHours);
const reportType = apiParameters.reportType as string;
const selectedReports = this.selectedReports[reportType] || {};
let reports = (this.selectedReportsOrder[reportType] || []).filter(
(name) => selectedReports[name],
);
if (!reports.length) {
reports = Object.keys(selectedReports).filter(
(name) => selectedReports[name],
);
}
if (reports.length > 0) {
apiParameters.reports = reports;
}
const reportParams = window.getReportParametersFunctions[this.report.type](this.report);
apiParameters.parameters = reportParams as unknown as QueryParameters;
const isUpdate = this.report.idreport > 0;
AjaxHelper.post(
{
method: isUpdate ? 'ScheduledReports.updateReport' : 'ScheduledReports.addReport',
period,
hour,
},
apiParameters,
).then(() => {
scrollToTop();
this.fadeInOutSuccessMessage(
this.$refs.reportUpdatedSuccess as HTMLElement,
isUpdate
? translate('ScheduledReports_ReportUpdated')
: translate('ScheduledReports_ReportAdded'),
);
});
return false;
},
onChangeProperty(propName: string, value: unknown) {
this.report[propName] = value;
if (propName === 'type') {
this.changedReportType();
}
},
toggleSelectedReport(reportType: string, uniqueId: string) {
this.selectedReports[reportType] = this.selectedReports[reportType] || {};
const newValue = !this.selectedReports[reportType][uniqueId];
this.selectedReports[reportType][uniqueId] = newValue;
this.selectedReportsOrder[reportType] = this.selectedReportsOrder[reportType] || [];
if (newValue) {
if (this.selectedReportsOrder[reportType].indexOf(uniqueId) === -1) {
this.selectedReportsOrder[reportType].push(uniqueId);
}
} else {
this.selectedReportsOrder[reportType] = this.selectedReportsOrder[reportType].filter(
(reportId) => reportId !== uniqueId,
);
}
},
onReorderSelectedReports(reportType: string, order: string[]) {
this.selectedReportsOrder[reportType] = order.filter(
(uniqueId) => this.selectedReports[reportType]?.[uniqueId],
);
},
},
computed: {
showReportForm() {
return !this.showReportsList;
},
decodedSiteName() {
return Matomo.helper.htmlDecode(this.siteName);
},
},
});
</script>