HEX
Server: Microsoft-IIS/10.0
System: Windows NT ITPWINWEBSVR22 10.0 build 20348 (Windows Server 2022) AMD64
User: www.conferencesearch.co.uk (0)
PHP: 8.3.30
Disabled: NONE
Upload Files
File: D:/web/matomo.vdk/plugins/PrivacyManager/vue/src/AnonymizeLogData/AnonymizeLogData.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="anonymizeLogData">
    <div class="form-group row">
      <div class="col s12 input-field">
        <div>
          <label
            for="anonymizeSite"
            class="siteSelectorLabel"
          >{{ translate('PrivacyManager_AnonymizeSites') }}</label>
          <div class="sites_autocomplete">
            <SiteSelector
              id="anonymizeSite"
              v-model="site"
              :show-all-sites-item="true"
              :switch-site-on-select="false"
              :show-selected-site="true"
            />
          </div>
        </div>
      </div>
    </div>
    <div class="form-group row">
      <div class="col s6 input-field">
        <div>
          <label
            for="anonymizeStartDate"
            class="active"
          >{{ translate('PrivacyManager_AnonymizeRowDataFrom') }}</label>
          <input
            type="text"
            id="anonymizeStartDate"
            class="anonymizeStartDate"
            ref="anonymizeStartDate"
            name="anonymizeStartDate"
            :value="startDate"
            @keydown="onKeydownStartDate($event)"
            @change="onKeydownStartDate($event)"
          />
        </div>
      </div>
      <div class="col s6 input-field">
        <div>
          <label
            for="anonymizeEndDate"
            class="active"
          >{{ translate('PrivacyManager_AnonymizeRowDataTo') }}</label>
          <input
            type="text"
            class="anonymizeEndDate"
            id="anonymizeEndDate"
            ref="anonymizeEndDate"
            name="anonymizeEndDate"
            :value="endDate"
            @keydown="onKeydownEndDate($event)"
            @change="onKeydownEndDate($event)"
          />
        </div>
      </div>
    </div>
    <div name="anonymizeIp">
      <Field
        uicontrol="checkbox"
        name="anonymizeIp"
        :title="translate('PrivacyManager_AnonymizeIp')"
        v-model="anonymizeIp"
        :introduction="translate('General_Visit')"
        :inline-help="translate('PrivacyManager_AnonymizeIpHelp')"
      >
      </Field>
    </div>
    <div name="anonymizeLocation">
      <Field
        uicontrol="checkbox"
        name="anonymizeLocation"
        :title="translate('PrivacyManager_AnonymizeLocation')"
        v-model="anonymizeLocation"
        :inline-help="translate('PrivacyManager_AnonymizeLocationHelp')"
      >
      </Field>
    </div>
    <div name="anonymizeTheUserId">
      <Field
        uicontrol="checkbox"
        name="anonymizeTheUserId"
        :title="translate('PrivacyManager_AnonymizeUserId')"
        v-model="anonymizeUserId"
        :inline-help="translate('PrivacyManager_AnonymizeUserIdHelp')"
      >
      </Field>
    </div>
    <div class="form-group row">
      <div class="col s12 m6">
        <div>
          <label for="visit_columns">{{ translate('PrivacyManager_UnsetVisitColumns') }}</label>
          <div
            :class="`selectedVisitColumns selectedVisitColumns${index} multiple valign-wrapper`"
            v-for="(visitColumn, index) in selectedVisitColumns"
            :key="index"
          >
            <div class="innerFormField" name="visit_columns">
              <Field
                uicontrol="select"
                name="visit_columns"
                :model-value="visitColumn.column"
                @update:model-value="visitColumn.column = $event; onVisitColumnChange()"
                :full-width="true"
                :options="availableVisitColumns"
              >
              </Field>
            </div>
            <span
              class="icon-minus valign"
              @click="removeVisitColumn(index)"
              v-show="index + 1 !== selectedVisitColumns.length"
              :title="translate('General_Remove')"
            />
          </div>
        </div>
      </div>
      <div class="col s12 m6">
        <div class="form-help">
          <span class="inline-help">{{ translate('PrivacyManager_UnsetVisitColumnsHelp') }}</span>
        </div>
      </div>
    </div>
    <div class="form-group row">
      <div class="col s12">
        <h3>{{ translate('General_Action') }}</h3>
      </div>
    </div>
    <div class="form-group row">
      <div class="col s12 m6">
        <div>
          <label for="action_columns">{{ translate('PrivacyManager_UnsetActionColumns') }}</label>
          <div
            :class="`selectedActionColumns selectedActionColumns${index} multiple valign-wrapper`"
            v-for="(actionColumn, index) in selectedActionColumns"
            :key="index"
          >
            <div class="innerFormField" name="action_columns">
              <Field
                uicontrol="select"
                name="action_columns"
                :model-value="actionColumn.column"
                @update:model-value="actionColumn.column = $event; onActionColumnChange()"
                :full-width="true"
                :options="availableActionColumns"
              >
              </Field>
            </div>
            <span
              class="icon-minus valign"
              @click="removeActionColumn(index)"
              v-show="index + 1 !== selectedActionColumns.length"
              :title="translate('General_Remove')"
            />
          </div>
        </div>
      </div>
      <div class="col s12 m6">
        <div class="form-help">
          <span class="inline-help">{{ translate('PrivacyManager_UnsetActionColumnsHelp') }}</span>
        </div>
      </div>
    </div>
    <p><span class="icon-info" /> {{ translate('PrivacyManager_AnonymizeProcessInfo') }}</p>
    <SaveButton
      class="anonymizePastData"
      @confirm="showPasswordConfirmModal = true"
      :disabled="isAnonymizePastDataDisabled"
      :value="translate('PrivacyManager_AnonymizeDataNow')"
    >
    </SaveButton>
    <PasswordConfirmation
      v-model="showPasswordConfirmModal"
      @confirmed="scheduleAnonymization"
    >
      <h2>{{ translate('PrivacyManager_AnonymizeDataConfirm') }}</h2>
    </PasswordConfirmation>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import {
  Matomo,
  AjaxHelper,
  SiteSelector,
  debounce,
} from 'CoreHome';
import { PasswordConfirmation, Field, SaveButton } from 'CorePluginsAdmin';

interface Option {
  key: string;
  value: string;
}

interface AnonymizeLogDataState {
  isLoading: boolean;
  isDeleting: boolean;
  anonymizeIp: boolean;
  anonymizeLocation: boolean;
  anonymizeUserId: boolean;
  site: Record<string, string>;
  availableVisitColumns: Option[];
  availableActionColumns: Option[];
  selectedVisitColumns: Record<string, string>[];
  selectedActionColumns: Record<string, string>[];
  startDate: string;
  endDate: string;
  showPasswordConfirmModal: boolean;
}

function sub(value: number) {
  if (value < 10) {
    return `0${value}`;
  }
  return value;
}

export default defineComponent({
  components: {
    PasswordConfirmation,
    SiteSelector,
    Field,
    SaveButton,
  },
  data(): AnonymizeLogDataState {
    const now = new Date();
    const startDate = `${now.getFullYear()}-${sub(now.getMonth() + 1)}-${sub(now.getDay() + 1)}`;
    return {
      isLoading: false,
      isDeleting: false,
      anonymizeIp: false,
      anonymizeLocation: false,
      anonymizeUserId: false,
      site: {
        id: 'all',
        name: 'All Websites',
      },
      availableVisitColumns: [],
      availableActionColumns: [],
      selectedVisitColumns: [{
        column: '',
      }],
      selectedActionColumns: [{
        column: '',
      }],
      startDate,
      endDate: startDate,
      showPasswordConfirmModal: false,
    };
  },
  created() {
    this.onKeydownStartDate = debounce(this.onKeydownStartDate, 50);
    this.onKeydownEndDate = debounce(this.onKeydownEndDate, 50);

    AjaxHelper.fetch<{ column_name: string }[]>({
      method: 'PrivacyManager.getAvailableVisitColumnsToAnonymize',
    }).then((columns) => {
      this.availableVisitColumns = [];
      columns.forEach((column) => {
        this.availableVisitColumns.push({
          key: column.column_name,
          value: column.column_name,
        });
      });
    });

    AjaxHelper.fetch<{ column_name: string }[]>({
      method: 'PrivacyManager.getAvailableLinkVisitActionColumnsToAnonymize',
    }).then((columns) => {
      this.availableActionColumns = [];
      columns.forEach((column) => {
        this.availableActionColumns.push({
          key: column.column_name,
          value: column.column_name,
        });
      });
    });

    setTimeout(() => {
      const options1 = Matomo.getBaseDatePickerOptions(null);
      const options2 = Matomo.getBaseDatePickerOptions(null);
      $(this.$refs.anonymizeStartDate as HTMLElement).datepicker(options1);
      $(this.$refs.anonymizeEndDate as HTMLElement).datepicker(options2);
    });
  },
  methods: {
    onVisitColumnChange() {
      const hasAll = this.selectedVisitColumns.every((col) => !!col?.column);
      if (hasAll) {
        this.addVisitColumn();
      }
    },
    addVisitColumn() {
      this.selectedVisitColumns.push({ column: '' });
    },
    removeVisitColumn(index: number) {
      if (index > -1) {
        const lastIndex = this.selectedVisitColumns.length - 1;

        if (lastIndex === index) {
          this.selectedVisitColumns[index] = { column: '' };
        } else {
          this.selectedVisitColumns.splice(index, 1);
        }
      }
    },
    onActionColumnChange() {
      const hasAll = this.selectedActionColumns.every((col) => !!col?.column);
      if (hasAll) {
        this.addActionColumn();
      }
    },
    addActionColumn() {
      this.selectedActionColumns.push({ column: '' });
    },
    removeActionColumn(index: number) {
      if (index > -1) {
        const lastIndex = this.selectedActionColumns.length - 1;

        if (lastIndex === index) {
          this.selectedActionColumns[index] = {
            column: '',
          };
        } else {
          this.selectedActionColumns.splice(index, 1);
        }
      }
    },
    scheduleAnonymization(password: string) {
      let date = `${this.startDate},${this.endDate}`;

      if (this.startDate === this.endDate) {
        date = this.startDate;
      }

      const params: QueryParameters = { date };
      params.idSites = this.site.id;
      params.anonymizeIp = this.anonymizeIp ? '1' : '0';
      params.anonymizeLocation = this.anonymizeLocation ? '1' : '0';
      params.anonymizeUserId = this.anonymizeUserId ? '1' : '0';
      params.unsetVisitColumns = this.selectedVisitColumns.filter(
        (c) => !!c?.column,
      ).map((c) => c.column);
      params.unsetLinkVisitActionColumns = this.selectedActionColumns.filter(
        (c) => !!c?.column,
      ).map((c) => c.column);
      params.passwordConfirmation = password;

      AjaxHelper.post({
        method: 'PrivacyManager.anonymizeSomeRawData',
      }, params).then(() => {
        window.location.reload(true);
      });
    },
    onKeydownStartDate(event: Event) {
      this.startDate = (event.target as HTMLInputElement).value;
    },
    onKeydownEndDate(event: Event) {
      this.endDate = (event.target as HTMLInputElement).value;
    },
  },
  computed: {
    isAnonymizePastDataDisabled(): boolean {
      return !this.anonymizeIp && !this.anonymizeLocation && !this.selectedVisitColumns
        && !this.selectedActionColumns;
    },
  },
});
</script>