Skip to content
Snippets Groups Projects
main.js 8.36 KiB
Newer Older
// Importing necessary libraries and components
const axios = require('axios'); // Axios for HTTP requests
import Vue from 'vue'; // Vue.js framework

import App from './App.vue'; // Main Vue component
import './registerServiceWorker'; // Service worker registration
import router from '@/router'; // Application router
import store from '@/store'; // Vuex store for state management

// Importing CSS for styling
import './assets/styles/base.css'; // Base styles
import './assets/resources/semantic-ui-2.4.2/semantic.min.css'; // Semantic UI for UI components
import '@fortawesome/fontawesome-free/css/all.css'; // Font Awesome for icons
import '@fortawesome/fontawesome-free/js/all.js'; // Font Awesome JS
import 'ol/ol.css'; // OpenLayers CSS for maps
import '@/assets/styles/openlayers-custom.css'; // Custom styles for OpenLayers
import '@/assets/styles/sidebar-layers.css'; // Styles for sidebar layers

// Font Awesome library setup
Florent's avatar
Florent committed
import { library } from '@fortawesome/fontawesome-svg-core';
import { fas } from '@fortawesome/free-solid-svg-icons'; // Importing solid icons
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'; // Font Awesome component

// Vue Multiselect CSS
import 'vue-multiselect/dist/vue-multiselect.min.css'; // Multiselect component styles
Florent's avatar
Florent committed

// Adding Font Awesome icons to the library
library.add(fas);
Florent's avatar
Florent committed

// Registering Font Awesome as a Vue component for use in templates
Florent's avatar
Florent committed

// Setting Vue's production tip configuration
Vue.config.productionTip = false;
Vue.config.ignoredElements = ['geor-header'];
// Handling service worker updates and precaching
var refreshing = false; // Flag to prevent multiple refreshes
if (navigator.serviceWorker) {
  navigator.serviceWorker.addEventListener('controllerchange', () => {
    // Check if the page is already refreshing to prevent duplicate refreshes
Florent Lavelle's avatar
Florent Lavelle committed
    if (refreshing) {
      return;
    }
    refreshing = true;
    // Reload the page to activate the new service worker
    window.location.reload();
  });
 * Dynamically loads a font from Google Fonts and sets CSS variables.
 * @param {string} fontNames - A comma-separated list of font names, where the first font is the one to be imported and others are fallbacks.
 * @param {string} headerColor - The color to be used for headers.
 * @param {string} primaryColor - The primary color for the application.
 * @param {string} primaryHighlightColor - The primary color to highlight elements in the application.
const setAppTheme = (fontNames, headerColor, primaryColor, primaryHighlightColor) => {
  // Set CSS variables for header and primary color.
  if (headerColor) {
    document.documentElement.style.setProperty('--header-color', headerColor);
  }
  if (primaryColor) {
    document.documentElement.style.setProperty('--primary-color', primaryColor);
  }
  if (primaryHighlightColor) {
    document.documentElement.style.setProperty('--primary-highlight-color', primaryHighlightColor);
  }

  // Proceed to load the font if fontNames is provided.
  if (fontNames) {
    const fontNameToImport = fontNames.split(',')[0].trim();
    const link = document.createElement('link');
    link.href = `https://fonts.googleapis.com/css?family=${fontNameToImport.replace(/ /g, '+')}:400,700&display=swap`;
    link.rel = 'stylesheet';
    document.head.appendChild(link);
    // Set the CSS variable for font family.
    document.documentElement.style.setProperty('--font-family', fontNames);
  }
};

/**
 * Sets the favicon of the application.
 * @param {string} favicoUrl - The URL of the favicon to be set.
 */
const setFavicon = (favicoUrl) => {
Florent Lavelle's avatar
Florent Lavelle committed
  const link = document.createElement('link');
DESPRES Damien's avatar
DESPRES Damien committed
  link.id = 'dynamic-favicon';
  link.rel = 'shortcut icon';
  link.href = favicoUrl;
DESPRES Damien's avatar
DESPRES Damien committed
  document.head.appendChild(link);
/**
 * Regularly updates the online status of the application.
 */
const updateOnlineStatus = () => {
  setInterval(() => {
    store.commit('SET_IS_ONLINE', navigator.onLine);
  }, 2000);
};

/**
 * Regularly updates the user status if using external auth to keep the frontend updated with backend.
 */
function handleLogout() {
  if (store.state.user) {
    store.dispatch('LOGOUT');
    store.commit('DISPLAY_MESSAGE', {
      level: 'negative',
      comment: `Vous avez été déconnecté du service d'authentification.
        Reconnectez-vous ou continuez en mode anonyme.`
    });
    store.dispatch('GET_USER_LEVEL_PROJECTS');
  }
}

const updateUserStatus = () => {
  setInterval(() => {
    if (navigator.onLine) {
      axios
        .get(`${store.state.configuration.VUE_APP_DJANGO_API_BASE}user_info/`)
        .then((response) => {
          const user = response.data?.user || null;
          
          if (response.status === 302) {
            console.warn("Redirection détectée vers :", response.headers.location || response.request.responseURL);
          }
      
          if (response.status === 200 && user) {
            // Cas où l'utilisateur est bien authentifié
            if (!store.state.user) {
              store.commit('SET_USER', user);
              store.commit('DISPLAY_MESSAGE', {
                level: 'positive',
                comment: 'Bienvenue à nouveau ! Vous êtes reconnecté au service d\'authentification'
              });
              store.dispatch('GET_USER_LEVEL_PERMISSIONS');
              store.dispatch('GET_USER_LEVEL_PROJECTS');
            }
          } else if (!user) {
            // Lorsqu'un utilisateur est déconnecté du SSO, la requête de vérification de session envoyée à l'API de l'application échoue avec une erreur 400.  
            // On force la déconnexion de l'utilisateur dans ce cas.
        .catch(error => {
          console.error("Erreur API :", error);
          handleLogout();
/**
 * Fetches initial data for the application and initializes the Vue instance.
 */
const fetchDataAndInitializeApp = async () => {
  await Promise.all([
    store.dispatch('GET_USER_INFO'),
Timothee P's avatar
Timothee P committed
    store.dispatch('GET_STATIC_PAGES'),
    store.dispatch('map/GET_AVAILABLE_LAYERS'),
    store.dispatch('GET_LEVELS_PERMISSIONS'),
    store.dispatch('GET_PROJECT_ATTRIBUTES'),
  new Vue({
    router,
    store,
    render: h => h(App)
  }).$mount('#app');
/**
 * Initializes the application configuration.
 * @param {object} config - Configuration object with application settings.
 */
const onConfigLoaded = async (config) => {
  // Set application configuration in the store.
  store.commit('SET_CONFIG', config);

  // Update the online status at regular intervals.
  updateOnlineStatus();

  // Update the user status at regular intervals to check if backend session expired.
  updateUserStatus();
  // Set the document title and favicon from the configuration.
  document.title = `${config.VUE_APP_APPLICATION_NAME} ${config.VUE_APP_APPLICATION_ABSTRACT}`;
  setFavicon(config.VUE_APP_APPLICATION_FAVICO);

  // Apply the application theme settings using values specified in the configuration.
  setAppTheme(
    config.VUE_APP_FONT_FAMILY,
    config.VUE_APP_HEADER_COLOR,
    config.VUE_APP_PRIMARY_COLOR,
    config.VUE_APP_PRIMARY_HIGHLIGHT_COLOR
  );

  // Set a global proxy URL based on the configuration.
  window.proxy_url = config.VUE_APP_DJANGO_API_BASE + 'proxy/';

  // Fetch initial data and initialize the Vue application.
  await fetchDataAndInitializeApp();
};

// Attempt to load the application configuration from an external JSON file.
axios.get('./config/config.json')
  .catch((error) => {
    // Log an error if the configuration file cannot be loaded.
    console.error(error);
    console.log('Attempting to get config from Localstorage');

    // Attempt to retrieve the configuration from local storage as a fallback.
    const conf = localStorage.getItem('geontrib_conf');
Florent Lavelle's avatar
Florent Lavelle committed
    if (conf) {
      // If a configuration is found in local storage, parse it and load the config.
      onConfigLoaded(JSON.parse(conf));
    // Check if the response is valid and the request was successful.
      // Store the retrieved configuration in local storage for future use.
      localStorage.setItem('geontrib_conf', JSON.stringify(response.data));

      // Load the configuration into the application.
      onConfigLoaded(response.data);
DESPRES Damien's avatar
DESPRES Damien committed
    }
  })
  .catch((error) => {
    // Throw an error if there are issues processing the response.
DESPRES Damien's avatar
DESPRES Damien committed
    throw error;