{% extends "layout.html" %}

{% block header_before_site_js %}
<link
  type="text/css"
  rel="stylesheet"
  href="{{ url_for('static', filename='ext/bootstrap-vue.2.21.2.min.css')}}"
/>

{% if False | env_override('FLASK_DEBUG') %}
<script src="{{ url_for('static', filename='ext/vue.2.6.14.js')}}"></script>
{% else %}
<script src="{{ url_for('static', filename='ext/vue.2.6.14.min.js')}}"></script>
{% endif %}
<script src="{{ url_for('static', filename='ext/bootstrap-vue.2.21.2.min.js')}}"></script>
<script src="{{ url_for('static', filename='ext/vue-router.2.0.0.min.js')}}"></script>
<script src="{{ url_for('static', filename='ext/vue-i18n.8.25.0.min.js')}}"></script>
<script src="{{ url_for('static', filename='ext/axios.0.21.1.min.js')}}"></script>
<script src="{{ url_for('static', filename='ext/lodash.4.17.21.min.js')}}"></script>
<script src="{{ url_for('static', filename='ext/portal-vue.2.1.7.umd.min.js')}}"></script>
<link
  href="{{ url_for('static', filename='ext/VueTypeaheadBootstrap.2.12.0.css')}}"
  rel="stylesheet"
/>
<script src="{{ url_for('static', filename='ext/VueTypeaheadBootstrap.2.12.0.umd.min.js')}}"></script>
<script src="{{ url_for('static', filename='ext/vee-validate.full.3.4.11.min.js')}}"></script>
<script src="{{ url_for('static', filename='vue/common/typeahead.vue.js')}}"></script>
<script src="{{ url_for('static', filename='vue/common/validated-input.vue.js')}}"></script>
<script src="{{ url_for('static', filename='vue/common/validated-switch.vue.js')}}"></script>
<script src="{{ url_for('static', filename='vue/common/validated-textarea.vue.js')}}"></script>
<script src="{{ url_for('static', filename='vue/common/event-warning-pills.vue.js')}}"></script>

{% block component_scripts %}
{% endblock %}
{% endblock %}

{% block content %}
{% block vue_container %}
<div id="vue-container"{% block vue_container_attribs %}{% endblock vue_container_attribs %}><router-view></router-view></div>
{% endblock %}
<script>
  Vue.component("vue-typeahead-bootstrap", VueTypeaheadBootstrap);
  Vue.component("ValidationObserver", VeeValidate.ValidationObserver);
  Vue.component("ValidationProvider", VeeValidate.ValidationProvider);

  Vue.component("custom-typeahead", CustomTypeahead);
  Vue.component("validated-input", ValidatedInput);
  Vue.component("validated-switch", ValidatedSwitch);
  Vue.component("validated-textarea", ValidatedTextarea);
  Vue.component("event-warning-pills", EventWarningPills);

  {% block component_definitions %}
  {% endblock %}

  const sharedMessages = {
    en: {
      shared: {
        models: {
          adminUnit: {
            className: "Organization",
            listName: "Organizations",
            name: "Name",
            shortName: "Short name",
          },
          adminUnitRelation: {
            targetOrganization: "Other organization",
            autoVerifyEventReferenceRequests: "Verify reference requests automatically",
            autoVerifyEventReferenceRequestsDescription: "If set, all upcoming reference requests of the other organization are verified automatically.",
            verify: "Verify other organization",
            verifyDescription: "If set, events of the other organization are publicly visible.",
          },
          adminUnitInvitation: {
            email: "Email",
            emailDescription: "The invitation will be sent to this email address.",
            organizationName: "New organization's name",
            relationAutoVerifyEventReferenceRequests: "Verify reference requests automatically",
            relationAutoVerifyEventReferenceRequestsDescription: "If set, all upcoming reference requests of the new organization are verified automatically.",
            relationVerify: "Verify new organization",
            relationVerifyDescription: "If set, events of the new organization are publicly visible.",
          },
          customWidget: {
            className: "Custom widget",
            listName: "Custom widgets",
            widgetType: "Type",
            widgetTypeSearch: "Search",
            widgetTypeCalendar: "Calendar",
            name: "Name",
          },
          event: {
            className: "Event",
            listName: "Events",
            name: "Name",
          },
          eventList: {
            className: "Event list",
            listName: "Event lists",
            name: "Name",
          },
          eventReport: {
            contactName: "Name",
            contactEmail: "Email",
            contactNameDescription: "First and last name",
            message: "Message",
            messageDescription: "Briefly describe in your words why the event is objectionable.",
          },
        },
        cancel: "Cancel",
        close: "Close",
        decline: "Decline",
        docs: "Docs",
        save: "Save",
        submit: "Submit",
        view: "View",
        edit: "Edit",
        delete: "Delete",
        remove: "Remove",
        emptyData: "No data available",
        errors: {
          uniqueViolation:
            "An entry with the entered values ​​already exists. Duplicate entries are not allowed.",
          unprocessableEntity:
            "The request was well-formed but was unable to be followed due to semantic errors.",
        },
        toast: {
          errorTitle: "Error",
          successTitle: "Success",
        },
        autocomplete: {
          instruction: "Type to search",
        },
        validation: {
          alpha: "The {_field_} field may only contain alphabetic characters",
          alpha_num:
            "The {_field_} field may only contain alpha-numeric characters",
          alpha_dash:
            "The {_field_} field may contain alpha-numeric characters as well as dashes and underscores",
          alpha_spaces:
            "The {_field_} field may only contain alphabetic characters as well as spaces",
          between: "The {_field_} field must be between {min} and {max}",
          confirmed: "The {_field_} field confirmation does not match",
          digits:
            "The {_field_} field must be numeric and exactly contain {length} digits",
          dimensions:
            "The {_field_} field must be {width} pixels by {height} pixels",
          email: "The {_field_} field must be a valid email",
          excluded: "The {_field_} field is not a valid value",
          ext: "The {_field_} field is not a valid file",
          image: "The {_field_} field must be an image",
          integer: "The {_field_} field must be an integer",
          length: "The {_field_} field must be {length} long",
          max_value: "The {_field_} field must be {max} or less",
          max: "The {_field_} field may not be greater than {length} characters",
          mimes: "The {_field_} field must have a valid file type",
          min_value: "The {_field_} field must be {min} or more",
          min: "The {_field_} field must be at least {length} characters",
          numeric: "The {_field_} field may only contain numeric characters",
          oneOf: "The {_field_} field is not a valid value",
          regex: "The {_field_} field format is invalid",
          required_if: "The {_field_} field is required",
          required: "The {_field_} field is required",
          size: "The {_field_} field size must be less than {size}KB",
          double: "The {_field_} field must be a valid decimal",
          uniqueOrganizationName: "Name is already taken",
          url: "The {_field_} field must be a valid URL",
        },
      },
    },
    de: {
      shared: {
        models: {
          adminUnit: {
            className: "Organisation",
            listName: "Organisationen",
            name: "Name",
            shortName: "Kurzname",
          },
          adminUnitRelation: {
            targetOrganization: "Andere Organisation",
            autoVerifyEventReferenceRequests:
              "Empfehlungsanfragen automatisch verifizieren",
            autoVerifyEventReferenceRequestsDescription: "Wenn gesetzt, werden alle zukünftigen Empfehlungsanfragen der anderen Organisation automatisch verifiziert.",
            verify: "Andere Organisation verifizieren",
            verifyDescription: "Wenn gesetzt, sind Veranstaltungen der anderen Organisation öffentlich sichtbar.",
          },
          adminUnitInvitation: {
            email: "Email",
            emailDescription: "An diese Email-Adresse wird die Einladung gesendet.",
            organizationName: "Name der neuen Organisation",
            relationAutoVerifyEventReferenceRequests: "Empfehlungsanfragen automatisch verifizieren",
            relationAutoVerifyEventReferenceRequestsDescription: "Wenn gesetzt, werden alle zukünftigen Empfehlungsanfragen der neuen Organisation automatisch verifiziert.",
            relationVerify: "Neue Organisation verifizieren",
            relationVerifyDescription: "Wenn gesetzt, sind Veranstaltungen der neuen Organisation öffentlich sichtbar.",
          },
          customWidget: {
            className: "Custom widget",
            listName: "Custom widgets",
            widgetTypeSearch: "Suche",
            widgetTypeCalendar: "Kalender",
            widgetType: "Typ",
            name: "Name",
          },
          event: {
            className: "Veranstaltung",
            listName: "Veranstaltungen",
            name: "Name",
          },
          eventList: {
            className: "Veranstaltungsliste",
            listName: "Veranstaltungslisten",
            name: "Name",
          },
          eventReport: {
            contactName: "Name",
            contactNameDescription: "Vor- und Nachname",
            contactEmail: "Email-Adresse",
            message: "Mitteilung",
            messageDescription: "Beschreibe kurz in deinen Worten, warum die Veranstaltung zu beanstanden ist.",
          },
        },
        cancel: "Abbrechen",
        close: "Schließen",
        decline: "Ablehnen",
        docs: "Doku",
        save: "Speichern",
        submit: "Senden",
        view: "Anzeigen",
        edit: "Bearbeiten",
        delete: "Löschen",
        remove: "Entfernen",
        emptyData: "Keine Daten vorhanden",
        errors: {
          uniqueViolation:
            "Ein Eintrag mit den eingegebenen Werten existiert bereits. Doppelte Einträge sind nicht erlaubt.",
          unprocessableEntity:
            "Die Anfrage konnte aufgrund von semantischen Fehlern nicht beantwortet werden.",
        },
        toast: {
          errorTitle: "Fehler",
          successTitle: "Erfolg",
        },
        autocomplete: {
          instruction: "Tippen um zu suchen",
        },
        validation: {
          alpha: "{_field_} darf nur alphabetische Zeichen enthalten",
          alpha_dash:
            "{_field_} darf alphanumerische Zeichen sowie Striche und Unterstriche enthalten",
          alpha_num: "{_field_} darf nur alphanumerische Zeichen enthalten",
          alpha_spaces:
            "{_field_} darf nur alphanumerische Zeichen und Leerzeichen enthalten",
          between: "{_field_} muss zwischen {min} und {max} liegen",
          confirmed: "Die Bestätigung von {_field_} stimmt nicht überein",
          digits:
            "{_field_} muss numerisch sein und exakt {length} Ziffern enthalten",
          dimensions: "{_field_} muss {width} x {height} Bildpunkte groß sein",
          email: "{_field_} muss eine gültige E-Mail-Adresse sein",
          excluded: "{_field_} muss ein gültiger Wert sein",
          ext: "{_field_} muss eine gültige Datei sein",
          image: "{_field_} muss eine Grafik sein",
          oneOf: "{_field_} muss ein gültiger Wert sein",
          integer: "{_field_} muss eine ganze Zahl sein",
          length: "Die Länge von {_field_} muss {length} sein",
          max: "{_field_} darf nicht länger als {length} Zeichen sein",
          max_value: "{_field_} darf maximal {max} sein",
          mimes: "{_field_} muss einen gültigen Dateityp haben",
          min: "{_field_} muss mindestens {length} Zeichen lang sein",
          min_value: "{_field_} muss mindestens {min} sein",
          numeric: "{_field_} darf nur numerische Zeichen enthalten",
          regex: "Das Format von {_field_} ist ungültig",
          required: "{_field_} ist ein Pflichtfeld",
          required_if: "{_field_} ist ein Pflichtfeld",
          size: "{_field_} muss kleiner als {size}KB sein",
          double: "Das Feld {_field_} muss eine gültige Dezimalzahl sein",
          uniqueOrganizationName: "Der Name ist bereits vergeben",
          url: "Das Feld {_field_} muss eine gültige URL sein",
        },
      },
    },
  };
  const i18n = new VueI18n({
    locale: "de",
    messages: sharedMessages,
    silentFallbackWarn: true,
  });

  VeeValidate.configure({
    defaultMessage: (field, values) => {
      return i18n.t(`shared.validation.${values._rule_}`, values);
    }
  });

  Object.keys(VeeValidate.Rules).forEach((rule) => {
    VeeValidate.extend(rule, VeeValidate.Rules[rule]);
  });

  VeeValidate.extend('uniqueOrganizationName', {
    validate: async value => {
      try {
        const response = await axios.get(
          `/api/v1/organizations?keyword=${value}`, {
            withCredentials: true,
          }
        );
        return !response.data.items.some(o => o.name == value);
      } catch (err) {
        return true;
      }
    }
  }, {
    immediate: false
  });

  VeeValidate.extend('url', {
    validate: value => {
      if (value) {
        return /^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/.test(value);
      }

      return false;
    }
  });

  {% block vue_routes %}
  const routes = [];
  {% endblock %}

  const router = new VueRouter({
    routes: routes,
    mode: "history",
    base: "/",
  });

  axios.defaults.baseURL = "{{ get_base_url() }}";
  axios.interceptors.request.use(
    function (config) {
      if (config) {
        this.app.handleAxiosStart(config);
      }
      return config;
    },
    function (error) {
      this.app.handleAxiosError(error);
      return Promise.reject(error);
    }
  );
  axios.interceptors.response.use(
    function (response) {
      if (response && response.config) {
        this.app.handleAxiosFinish(response.config);
      }
      return response;
    },
    function (error) {
      this.app.handleAxiosError(error);
      return Promise.reject(error);
    }
  );

  {% block vue_app_data %}
  var vue_app_data = {};
  {% endblock %}

  {% if config["DOCS_URL"] %}
  vue_app_data["docsUrl"] = "{{ config["DOCS_URL"] }}";
  {% endif %}

  var app = new Vue({
    el: "#vue-container",
    i18n,
    router: router,
    data: vue_app_data,
    methods: {
      handleAxiosStart(config) {
        if (
          config &&
          config.handler &&
          config.handler.hasOwnProperty("handleRequestStart")
        ) {
          config.handler.handleRequestStart();
        }

        if (
          config &&
          config.hasOwnProperty("handleLoading")
        ) {
          config.handleLoading(true);
        }
      },
      handleAxiosFinish(config) {
        if (
          config &&
          config.handler &&
          config.handler.hasOwnProperty("handleRequestFinish")
        ) {
          config.handler.handleRequestFinish();
        }

        if (
          config &&
          config.hasOwnProperty("handleLoading")
        ) {
          config.handleLoading(false);
        }
      },
      handleAxiosError(error) {
        if (error && error.config) {
          this.handleAxiosFinish(error.config);
        }

        const status = error && error.response && error.response.status;
        let message = error.message || error;

        if (status == 400 || status == 422) {
          message =
            (error &&
              error.response &&
              error.response.data &&
              error.response.data.message) ||
            error;
          errorName =
            error &&
            error.response &&
            error.response.data &&
            error.response.data.name;

          if (errorName == "Unique Violation") {
            message = this.$t("shared.errors.uniqueViolation");
          }
          else if (errorName == "Unprocessable Entity") {
            message = this.$t("shared.errors.unprocessableEntity");
          }
        }

        if (
          error.config &&
          error.config.handler &&
          error.config.handler.hasOwnProperty("handleRequestError")
        ) {
          error.config.handler.handleRequestError(error, message);
        } else {
          this.makeErrorToast(message);
        }
      },
      makeErrorToast(message) {
        this.makeToast(message, "danger", this.$t("shared.toast.errorTitle"));
      },
      makeSuccessToast(message) {
        this.makeToast(
          message,
          "success",
          this.$t("shared.toast.successTitle")
        );
      },
      makeToast(message, variant, title) {
        this.$bvToast.toast(message, {
          title: title,
          variant: variant,
          toaster: "b-toaster-top-center",
          noCloseButton: true,
          solid: true,
        });
      },
      goBack(fallbackPath) {
        window.history.length > 1 ? this.$router.go(-1) : this.$router.push({ path: fallbackPath })
      },
      render_event_date_instance(value, allday, format = "dd. DD.MM.YYYY LT", alldayFormat = "dd. DD.MM.YYYY") {
          const instance = moment(value);

          if (allday) {
              return instance.format(alldayFormat);
          }

          return instance.format(format);
      },
      url_for_image(image, size) {
          return `${axios.defaults.baseURL}${image.image_url}?s=${size}`
      },
    },
  });
</script>
{% endblock %}
