Skip to content
Snippets Groups Projects
index.js 8.67 KiB
import Vue from 'vue';
import VueRouter from 'vue-router';
import ProjectsList from '../views/Projects/ProjectsList.vue';
import store from '@/store';
import featureAPI from '@/services/feature-api';

Vue.use(VueRouter);

let projectBase = 'projet';
if (window.location.pathname.includes('projet-partage')) {
  projectBase = 'projet-partage';
}

const routes = [
  {
    path: '/',
    name: 'index',
    component: ProjectsList
  },
  {
    path: `${projectBase === 'projet' ? '': `/${projectBase}/:slug`}/connexion/`,
    name: 'login',
    component: () => import('../views/Login.vue')
  },
  {
    path: `${projectBase === 'projet' ? '': `/${projectBase}/:slug`}/my_account/`,
    name: 'my_account',
    component: () => import('../views/Account.vue')
  },
  {
    path: `${projectBase === 'projet' ? '': '/' + projectBase}/mentions/`,
    name: 'mentions',
    component: () => import('../views/FlatPages/LegalMentions.vue')
  },
  {
    path: `${projectBase === 'projet' ? '': '/' + projectBase}/aide/`,
    name: 'aide',
    component: () => import('../views/FlatPages/Help.vue')
  },
  // * PROJECT
  {
    path: '/creer-projet/',
    name: 'project_create',
    component: () => import('../views/Project/ProjectEdit.vue')
  },
  {
    path: `/${projectBase}/:slug`,
    name: 'project_detail',
    props: true,
    component: () => import('../views/Project/ProjectDetail.vue'),
  },
  {
    path: `/${projectBase}/:slug/signalement/lister/`,
    name: 'liste-signalements',
    component: () => import('../views/Project/FeaturesListAndMap.vue')
  },
  {
    path: `/${projectBase}/:slug/editer`,
    name: 'project_edit',
    component: () => import('../views/Project/ProjectEdit.vue')
  },
  {
    path: '/projet-type/',
    name: 'project_type_list',
    component: () => import('../views/Projects/ProjectsTypes.vue')
  },
  {
    path: '/creer-projet/create_from/:slug/',
    name: 'project_create_from',
    component: () => import('../views/Project/ProjectEdit.vue')
  },
  {
    path: `/${projectBase}/:slug/administration-carte/`,
    name: 'project_mapping',
    component: () => import('../views/Project/ProjectBasemaps.vue')
  },
  {
    path: `/${projectBase}/:slug/membres/`,
    name: 'project_members',
    component: () => import('../views/Project/ProjectMembers.vue')
  },
  {
    path: `/${projectBase}/:slug/signalement-filtre/`,
    name: 'details-signalement-filtre',
    component: () => import('../views/Feature/FeatureDetail.vue')
  },
  // * FEATURE TYPE 
  {
    path: `/${projectBase}/:slug/type-signalement/ajouter/`,
    name: 'ajouter-type-signalement',
    props: true,
    component: () => import('../views/FeatureType/FeatureTypeEdit.vue')
  },
  {
    path: `/${projectBase}/:slug/type-signalement/ajouter/create_from/:slug_type_signal`,
    name: 'dupliquer-type-signalement',
    component: () => import('../views/FeatureType/FeatureTypeEdit.vue')
  },
  {
    path: `/${projectBase}/:slug/type-signalement/:feature_type_slug/`,
    name: 'details-type-signalement',
    component: () => import('../views/FeatureType/FeatureTypeDetail.vue')
  },
  {
    path: `/${projectBase}/:slug/type-signalement/:slug_type_signal/editer/`,
    name: 'editer-type-signalement',
    component: () => import('../views/FeatureType/FeatureTypeEdit.vue')
  },
  {
    path: `/${projectBase}/:slug/type-signalement/:slug_type_signal/affichage/`,
    name: 'editer-affichage-signalement',
    component: () => import('../views/FeatureType/FeatureTypeDisplay.vue')
  },
  // * FEATURE 
  {
    path: `/${projectBase}/:slug/type-signalement/:slug_type_signal/signalement/ajouter/`,
    name: 'ajouter-signalement',
    component: () => import('../views/Feature/FeatureEdit.vue')
  },
  {
    path: `/${projectBase}/:slug/type-signalement/:slug_type_signal/signalement/:slug_signal`,
    name: 'details-signalement',
    component: () => import('../views/Feature/FeatureDetail.vue'),
    /**
     * Handles routing logic before entering the details-signalement route.
     * This function manages access and navigation based on user permissions and feature data.
     */
    beforeEnter: async (to, from, next) => {
      try {
        const { slug, slug_type_signal, slug_signal } = to.params;
        // Retrieve the project details from the store
        const project = await store.dispatch('projects/GET_PROJECT', slug);
        // Prepare query based on the project settings for feature browsing
        const query = { ordering: project.feature_browsing_default_sort };
        // Check if the default filter of the project is set to feature_type and apply it
        if (project.feature_browsing_default_filter) { // when feature_type is the default filter of the project,
          query['feature_type_slug'] = slug_type_signal; // set feature_type slug in query
        }
        
        // Get the feature's position based on the feature slug and query settings
        const offset = await featureAPI.getFeaturePosition(slug, slug_signal, query);
  
        // Decide next routing based on the offset result
        if (offset >= 0) {
          next({ 
            name: 'details-signalement-filtre', 
            params: { slug }, 
            query: { ...query, offset } 
          });        
        } else if (offset === 'No Content') {
          // API return no content when user is not allowed to see the feature or isn't connected
          if (store.state.user) {
            // If the user is connected, display information that he's not allowed to view the feature
            store.commit('DISPLAY_MESSAGE', { comment: 'Vous n\'avez pas accès à ce signalement avec cet utilisateur', level: 'negative' });
            // and redirect to main page
            next({ path: '/' });
          } else {
            // If the user is not connected, remove other messages to avoid displaying twice that the user is not connected
            store.commit('CLEAR_MESSAGES');
            // display information that user need to be connected
            store.commit('DISPLAY_MESSAGE', { comment: 'Vous n\'avez pas accès à ce signalement hors connexion, veuillez-vous connecter au préalable', level: 'negative' });
            // Then redirect to login page
            if (store.state.configuration.VUE_APP_LOGIN_URL) {
              // If the login is through SSO, redirect to external login page (if the instance accepts a redirect_url it would be caught before when requesting user_info with GET_USER_INFO)
              setTimeout(() => { // delay switching page to allow the info message to be read by user
                window.open(store.state.configuration.VUE_APP_LOGIN_URL);
              }, 1500);
            } else {
              // In a classic installation, redirect to the login page of this application
              next({ name: 'login' });
            }
          }
        } else {
          store.commit('DISPLAY_MESSAGE', { comment: 'Désolé, une erreur est survenue pendant la recherche du signalement', level: 'negative' });
          next({ path: '/' });
        }
      } catch (error) {
        console.error('error', error);
        store.commit('DISPLAY_MESSAGE', { comment: `Désolé, une erreur est survenue pendant la recherche du signalement   -   ${error}`, level: 'negative' });
        next({ path: '/' });
      }
    }
  },
  {
    path: `/${projectBase}/:slug/type-signalement/:slug_type_signal/offline`,
    name: 'offline-signalement',
    component: () => import('../views/Feature/FeatureOffline.vue')
  },
  {
    path: `/${projectBase}/:slug/type-signalement/:slug_type_signal/signalement/:slug_signal/editer/`,
    name: 'editer-signalement',
    component: () => import('../views/Feature/FeatureEdit.vue')
  },
  {
    path: `/${projectBase}/:slug/type-signalement/:slug_type_signal/editer-signalements-attributs/`,
    name: 'editer-attribut-signalement',
    component: () => import('../views/Feature/FeatureEdit.vue')
  },

  {
    path: '/projet/:slug/catalog/:feature_type_slug',
    name: 'catalog-import',
    component: () => import('../views/Catalog.vue')
  },

  {
    path: '/projet/:slug/type-signalement/:slug_type_signal/signalement/:slug_signal/attachment-preview/',
    name: 'attachment-preview',
    component: () => import('../views/AttachmentPreview.vue')
  },

  { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('../views/NotFound.vue') },
];

const router = new VueRouter({
  mode: 'history',
  base: '/geocontrib/',
  routes,
  routerHistory: [],
  scrollBehavior(to, from, savedPosition) { //* record each route change to keep scroll position
    const fromHistory = Boolean(savedPosition);

    if (fromHistory && this.options.routerHistory.length > 0) {
      this.options.routerHistory.splice(-1, 1);
    } else {
      this.options.routerHistory.push(from);
    }
    return savedPosition || { x: 0, y: 0 };
  },
});

export default router;