view client/src/store/importschedule.js @ 5388:60bba8e6322b extented-report

Add import for updating stats. Rationale: Due to performance optimization it seems advised to decouple updating the stats for the DQL report from the actual consumption while generating the report. -- Therefore we have a new import kind "statsupdate" which is selectable for sysadmins only. It could be scheduled as any other import. The available names for which stats to update are dynamically queried from the backend.
author Thomas Junk <thomas.junk@intevation.de>
date Fri, 02 Jul 2021 13:56:51 +0200
parents 1695e17c5a83
children 064ac1014713
line wrap: on
line source

/* This is Free Software under GNU Affero General Public License v >= 3.0
 * without warranty, see README.md and license for details.
 *
 * SPDX-License-Identifier: AGPL-3.0-or-later
 * License-Filename: LICENSES/AGPL-3.0.txt
 *
 * Copyright (C) 2018 by via donau
 *   – Österreichische Wasserstraßen-Gesellschaft mbH
 * Software engineering by Intevation GmbH
 *
 * Author(s):
 * Thomas Junk <thomas.junk@intevation.de>
 */

import { HTTP } from "@/lib/http";
import Vue from "vue";

/* eslint-disable no-unused-vars */
/* eslint-disable no-unreachable */

const IMPORTTYPES = {
  BOTTLENECK: "bottleneck",
  WATERWAYAXIS: "waterwayaxis",
  GAUGEMEASUREMENT: "gaugemeasurement",
  FAIRWAYAVAILABILITY: "fairwayavailability",
  WATERWAYAREA: "waterwayarea",
  FAIRWAYDIMENSION: "fairwaydimension",
  WATERWAYGAUGES: "waterwaygauges",
  DISTANCEMARKSVIRTUAL: "distancemarksvirtual",
  DISTANCEMARKSASHORE: "distancemarksashore",
  SOUNDINGRESULTS: "soundingresults",
  APPROVEDGAUGEMEASUREMENTS: "approvedgaugemeasurements",
  WATERWAYPROFILES: "waterwayprofiles",
  FAIRWAYMARKS: "fairwaymarks",
  REPORT: "report",
  STATSUPDATE: "statsupdate"
};

const KINDIMPORTTYPE = {
  bn: "bottleneck",
  fa: "fairwayavailability",
  fm: "fairwaymarks",
  gm: "gaugemeasurement",
  wx: "waterwayaxis",
  wa: "waterwayarea",
  fd: "fairwaydimension",
  wg: "waterwaygauges",
  dmv: "distancemarksvirtual",
  dma: "distancemarksashore",
  report: "report",
  statsupdate: "statsupdate"
};

const IMPORTTYPEKIND = {
  bottleneck: "bn",
  fairwayavailability: "fa",
  fairwaymarks: "fm",
  gaugemeasurement: "gm",
  waterwayaxis: "wx",
  waterwayarea: "wa",
  fairwaydimension: "fd",
  waterwaygauges: "wg",
  distancemarksvirtual: "dmv",
  distancemarksashore: "dma",
  report: "report",
  statsupdate: "statsupdate"
};

const FAIRWAYMARKKINDS = {
  fm_bcnisd: "BCNISD",
  fm_bcnlat_hydro: "BCNLAT_hydro",
  fm_bcnlat_ienc: "bcnlat_ienc",
  fm_boycar: "BOYCAR",
  fm_boyisd: "BOYISD",
  fm_boylat_hydro: "BOYLAT_hydro",
  fm_boylat_ienc: "boylat_ienc",
  fm_boysaw: "BOYSAW",
  fm_boyspp: "BOYSPP",
  fm_daymar_hydro: "DAYMAR_hydro",
  fm_daymar_ienc: "daymar_ienc",
  fm_lights: "LIGHTS",
  fm_rtpbcn: "RTPBCN",
  fm_topmar: "TOPMAR",
  fm_notmrk: "notmrk"
};

const initializeCurrentSchedule = () => {
  return {
    id: null,
    importType: null,
    schedule: null,
    importSource: null,
    eMailNotification: false,
    scheduled: false,
    easyCron: true,
    cronString: "0 */15 * * * *",
    cronMode: "15minutes",
    minutes: 0,
    month: 1,
    hour: 0,
    day: 0,
    dayOfMonth: 1,
    simple: null,
    url: null,
    insecure: false,
    triggerActive: true,
    featureType: null,
    sortBy: "",
    tolerance: 5,
    username: "",
    password: "",
    LOS: 3,
    minWidth: null,
    maxWidth: null,
    depth: null,
    sourceOrganization: null,
    trys: null,
    waitRetry: null,
    selectedMark: null,
    statsUpdate: null
  };
};

const MODES = {
  LIST: "list",
  EDIT: "edit"
};

// initial state
const init = () => {
  return {
    schedules: [],
    importScheduleDetailVisible: false,
    currentSchedule: initializeCurrentSchedule(),
    mode: MODES.LIST
  };
};

const importschedule = {
  init,
  namespaced: true,
  state: init(),
  mutations: {
    setEditMode: state => {
      state.mode = MODES.EDIT;
    },
    setListMode: state => {
      state.currentSchedule = initializeCurrentSchedule();
      state.mode = MODES.LIST;
    },
    setImportType: (state, type) => {
      Vue.set(state.currentSchedule, "importType", type);
    },
    clearCurrentSchedule: state => {
      state.currentSchedule = initializeCurrentSchedule();
    },
    setImportScheduleDetailInvisible: state => {
      state.importScheduleDetailVisible = false;
    },
    setImportScheduleDetailVisible: state => {
      state.importScheduleDetailVisible = true;
    },
    setSchedules: (state, schedules) => {
      state.schedules = schedules;
    },
    unmarshallCurrentSchedule: (state, payload) => {
      const { kind, config, id } = payload;
      const eMailNotification = config["send-email"];
      const { cron, url } = config;
      if (FAIRWAYMARKKINDS[kind]) {
        Vue.set(state.currentSchedule, "importType", "fairwaymarks");
        debugger;
        Vue.set(state.currentSchedule, "selectedMark", FAIRWAYMARKKINDS[kind]);
      } else {
        Vue.set(state.currentSchedule, "importType", KINDIMPORTTYPE[kind]);
      }

      Vue.set(state.currentSchedule, "id", id);
      Vue.set(state.currentSchedule, "trys", config["trys"]);
      Vue.set(state.currentSchedule, "waitRetry", config["wait-retry"]);
      if (cron) {
        Vue.set(state.currentSchedule, "scheduled", true);
        Vue.set(state.currentSchedule, "cronString", cron);
        // simple weekly  or monthly?
        if (cron === "0 0 0 * * 0") {
          Vue.set(state.currentSchedule, "simple", "weekly");
          Vue.set(state.currentSchedule, "easyCron", true);
        } else if (cron === "0 0 0 1 * *") {
          Vue.set(state.currentSchedule, "simple", "monthly");
          Vue.set(state.currentSchedule, "easyCron", true);
        } else {
          Vue.set(state.currentSchedule, "easyCron", false);
        }

        // set cronMode from cronString
        Vue.set(state.currentSchedule, "cronMode", null);
        if (cron === "0 */15 * * * *")
          Vue.set(state.currentSchedule, "cronMode", "15minutes");
        else if (/^0 \d{1,2} \* \* \* \*$/.test(cron))
          Vue.set(state.currentSchedule, "cronMode", "hour");
        else if (/^0 \d{1,2} \d{1,2} \* \* \*$/.test(cron))
          Vue.set(state.currentSchedule, "cronMode", "day");
        else if (/^0 \d{1,2} \d{1,2} \* \* \d{1}$/.test(cron))
          Vue.set(state.currentSchedule, "cronMode", "week");
        else if (/^0 \d{1,2} \d{1,2} \d{1,2} \* \*$/.test(cron))
          Vue.set(state.currentSchedule, "cronMode", "month");
        else if (/^0 \d{1,2} \d{1,2} \d{1,2} \d{1,2} \*$/.test(cron))
          Vue.set(state.currentSchedule, "cronMode", "year");

        // set minute, hour, etc from cronString
        let cronConf = cron.match(
          /0 (\d{1,2}|\*) (\d{1,2}|\*) (\d{1,2}|\*) (\d{1,2}|\*) (\d{1}|\*)/
        );

        // if cronString could not be parsed/matched (cronConf is null),
        // skip prefilling those values
        if (cronConf) {
          // remove first element which is the whole matched string
          cronConf.shift();
          cronConf = cronConf.map(field =>
            field === "*" ? null : Number(field)
          );
          Vue.set(state.currentSchedule, "minutes", cronConf[0]);
          Vue.set(state.currentSchedule, "hour", cronConf[1]);
          Vue.set(state.currentSchedule, "dayOfMonth", cronConf[2]);
          Vue.set(state.currentSchedule, "month", cronConf[3]);
          Vue.set(state.currentSchedule, "day", cronConf[4]);
        }
      }
      if (eMailNotification) {
        Vue.set(state.currentSchedule, "eMailNotification", eMailNotification);
      }
      if (url) {
        Vue.set(state.currentSchedule, "url", url);
      }
      let { insecure, user, password, los, depth } = config;
      let sortBy = config["sort-by"];
      let minWidth = config["min-width"];
      let maxWidth = config["max-width"];
      let sourceOrganization = config["source-organization"];
      const featureType = config["feature-type"];
      const tolerance = config["tolerance"];
      insecure = insecure == "true";
      if (insecure) {
        Vue.set(state.currentSchedule, "insecure", insecure);
      }
      if (featureType) {
        Vue.set(state.currentSchedule, "featureType", featureType);
      }
      if (sortBy) {
        Vue.set(state.currentSchedule, "sortBy", sortBy);
      }
      if (tolerance) {
        Vue.set(state.currentSchedule, "tolerance", tolerance);
      }
      if (user) {
        Vue.set(state.currentSchedule, "username", user);
      }
      if (password) {
        Vue.set(state.currentSchedule, "password", password);
      }
      if (los) {
        Vue.set(state.currentSchedule, "LOS", los);
      }
      if (minWidth) {
        Vue.set(state.currentSchedule, "minWidth", minWidth);
      }
      if (maxWidth) {
        Vue.set(state.currentSchedule, "maxWidth", maxWidth);
      }
      if (depth) {
        Vue.set(state.currentSchedule, "depth", depth);
      }
      if (sourceOrganization) {
        Vue.set(
          state.currentSchedule,
          "sourceOrganization",
          sourceOrganization
        );
      }
      if (kind === IMPORTTYPES.STATSUPDATE) {
        const { name } = config;
        Vue.set(state.currentSchedule, "statsUpdate", name);
      }
    }
  },
  actions: {
    loadSchedule({ commit }, id) {
      return new Promise((resolve, reject) => {
        HTTP.get("/imports/config/" + id, {
          headers: { "X-Gemma-Auth": localStorage.getItem("token") }
        })
          .then(response => {
            commit("unmarshallCurrentSchedule", response.data);
            resolve(response);
          })
          .catch(error => {
            reject(error);
          });
      });
    },
    updateCurrentSchedule({ commit }, payload) {
      const { data, id } = payload;
      return new Promise((resolve, reject) => {
        HTTP.patch("imports/config/" + id, data, {
          headers: {
            "X-Gemma-Auth": localStorage.getItem("token")
          }
        })
          .then(response => {
            resolve(response);
          })
          .catch(error => {
            reject(error);
          });
      });
    },
    saveCurrentSchedule({ commit }, data) {
      return new Promise((resolve, reject) => {
        HTTP.post("imports/config", data, {
          headers: {
            "X-Gemma-Auth": localStorage.getItem("token")
          }
        })
          .then(response => {
            resolve(response);
          })
          .catch(error => {
            reject(error);
          });
      });
    },
    loadSchedules({ commit }) {
      return new Promise((resolve, reject) => {
        HTTP.get("/imports/config", {
          headers: { "X-Gemma-Auth": localStorage.getItem("token") }
        })
          .then(response => {
            commit("setSchedules", response.data);
            resolve(response);
          })
          .catch(error => {
            reject(error);
          });
      });
    },
    deleteSchedule({ commit }, id) {
      return new Promise((resolve, reject) => {
        HTTP.delete("imports/config/" + id, {
          headers: {
            "X-Gemma-Auth": localStorage.getItem("token")
          }
        })
          .then(response => {
            resolve(response);
          })
          .catch(error => {
            reject(error);
          });
      });
    },
    triggerImport({ commit }, { type, data }) {
      return new Promise((resolve, reject) => {
        HTTP.post("imports/" + type, data, {
          headers: {
            "X-Gemma-Auth": localStorage.getItem("token")
          }
        })
          .then(response => {
            resolve(response);
          })
          .catch(error => {
            reject(error);
          });
      });
    }
  }
};

export {
  importschedule,
  initializeCurrentSchedule,
  IMPORTTYPES,
  IMPORTTYPEKIND,
  MODES
};