Skip to content

3. Utilidades

Álvaro Ramírez edited this page May 9, 2024 · 11 revisions

Diálogos

API-CNIG permite crear cuadros de diálogo modales que aparecen superpuestos a toda la página actual y que se cierran cuando el usuario pincha en el botón de aceptar. Existen tres tipos de diálogos: informativos, de error o de éxito de operación.

Cada diálogo tiene asociado un color diferente (info: azul, error: rojo, success: verde), y permite utilizar los siguientes parámetros:

  • message: Mensaje que se mostrará en el diálogo.
  • title: Título del diálogo. Por defecto, su valor será INFORMACIÓN/ERROR/ÉXITO dependiendo del tipo del diálogo.
  • order: Indica el orden (para acceder mediante la tabulación) de accesibilidad del diálogo creado.
  • configuration: Configuración para el diálogo. Permite activar la inteligencia transformando el contenido en texto inteligente. Cuando hablamos de texto inteligente nos referimos a que es capaz de transformar un enlace de una imagen en una etiqueta HTML IMG permitiendo la visualización de la misma, para un video añadir la etiqueta HTML VIDEO, enlace PDF en etiqueta HTML IFRAME... (*)
// Diálogo de tipo info de color azul con el mensaje "Mensaje informativo".
M.dialog.info('Mensaje informativo'); 
// Diálogo de tipo error de color rojo con el mensaje "Mensaje de error".
M.dialog.error('Mensaje de error');
// Diálogo de tipo success de color verde con el mensaje "Mensaje de éxito".
M.dialog.success('Mensaje de éxito');
// Diálogo de tipo info con el mensaje "Mensaje informativo" y título "Diálogo informativo".
M.dialog.info('Mensaje informativo', 'Diálogo informativo');
// Diálogo de tipo error con el mensaje "Mensaje de error", título "Diálogo de error" y orden 1.
M.dialog.info('Mensaje de error', 'Diálogo de error', 1);

Ejemplo de uso:

// Al hacer click sobre el mapa se mostrará un diálogo de tipo info 
// con el mensaje 'Se ha pulsado en el mapa'.
mapa.on(M.evt.CLICK, (m) => {
  M.dialog.info('Se ha pulsado en el mapa');
});

Activando la inteligencia:

M.dialog.info( 'Texto https://www.google.es texto', 'Título', 1, {
   intelligence: true
});

Toasts

API-CNIG también permite crear notificaciones que solo se muestran durante un determinado tiempo cuando se realiza una operación. También pueden cerrarse cuando el usuario pulsa en el botón de cerrar. Existen cuatro tipos de toasts: informativos, de error, de éxito o de aviso de operación.

Cada toast tiene asociado un color y un icono diferente (info: azul, error: rojo, success: verde, warning: amarillo), y permite utilizar los siguientes parámetros:

  • message: Mensaje que se mostrará en el toast.
  • order: Indica el orden (para acceder mediante la tabulación) de accesibilidad del toast creado. Por defecto, 300.
  • time: Tiempo de aparición del toast. Por defecto, 4000 (4 segundos).
// Toast de tipo info de color azul con el mensaje "Notificación informativa".
M.toast.info('Notificación informativa'); 
// Toast de tipo error de color rojo con el mensaje "Notificación de error".
M.toast.error('Notificación de error');
// Toast de tipo warning de color amarillo con el mensaje "Notificación de aviso".
M.toast.warning('Notificación de aviso');
// Toast de tipo success de color verde con el mensaje "Notificación de éxito".
M.toast.success('Notificación de éxito');
// Toast de tipo info con el mensaje "Notificación informativa", orden 1 y duración de 6 segundos.
M.toast.info('Notificación informativa', 1, 6000); 
// Toast de tipo error con el mensaje "Notificación de error" y duración de 8 segundos.
M.toast.error('Notificación de error', null, 8000);

Ejemplo de uso:

// Al hacer click sobre el mapa se mostrará una notificación durante 4 segundos de tipo info 
// con el mensaje 'Se ha pulsado en el mapa'.
mapa.on(M.evt.CLICK, (m) => {
  M.toast.info('Se ha pulsado en el mapa');
});

Desplazamiento plugins

API-CNIG incluye en el módulo M/utils el método draggabillyPlugin para el desplazamiento de cualquier plugin sobre el mapa. Este método utiliza la librería de javascript Draggabilly que añade la clase '.is-pointer-down' cuando el usuario presiona el cursor sobre el elemento y '.is-dragging' cuando el elemento empieza a arrastrarse.

draggabillyPlugin consta de los siguientes parámetros:

  • panel: Panel del plugin.
  • handleEl: Elemento o selector en el que comienza la interacción del arrastre (Identificador).

💡 Se recomienda utilizar el título del panel como elemento o selector de arrastre puesto que el plugin puede contener botones y eventos e interferir en su funcionamiento.

En el siguiente ejemplo, creamos un plugin cerrado de entrada y llamamos al método draggabillyPlugin, pero el desplazamiento del plugin no se activará hasta que se abra.

// Creamos el plugin
const infocoord = new M.plugin.Infocoordinates({
  collapsed: true
});
// Añadimos el plugin al mapa
map.addPlugin(infocoord);
// Activamos el desplazamiento del plugin 
M.utils.draggabillyPlugin(infocoord.panel_, '#titleInfo');

En este caso, al estar abierto de entrada podemos arrastrar directamente el plugin.

// Creamos el plugin
const infocoord = new M.plugin.Infocoordinates({
  collapsed: false
});
// Añadimos el plugin al mapa
map.addPlugin(infocoord);
// Activamos el desplazamiento del plugin 
M.utils.draggabillyPlugin(infocoord.panel_, '#titleInfo');

En los ejemplos anteriores, el plugin es colapsable por lo que al cerrarlo volverá a su posición inicial.

En este ejemplo, creamos un plugin no colapsable y llamamos a draggabillyPlugin pudiendo mover el plugin directamente, pero este no volverá a su posición inicial automáticamente.

// Creamos el plugin
const infocoord = new M.plugin.Infocoordinates({
  collapsible: false
});
// Añadimos el plugin al mapa
map.addPlugin(infocoord);
// Activamos el desplazamiento del plugin 
M.utils.draggabillyPlugin(infocoord.panel_, '#titleInfo');

Popups

Los popups representan bocadillos, asociados a unas coordenadas, que ofrecen información al usuario, por ejemplo cuando se pincha en un punto del mapa donde existe información vectorial. Este objeto puede gestionarse de la siguiente manera:

// Obtenemos objeto Popup añadido al mapa
const popup = mapa.getPopup();
// Eliminamos popup del mapa
mapa.removePopup();

Para construir un popup, necesitamos una pestaña con el contenido y unas coordenadas para añadirlo al mapa.

// Creamos un objeto Tab (pestaña)
const featureTabOpts = {
  'icon': 'g-cartografia-pin', // icono para mostrar en la pestaña
  'title': 'Título de la pestaña', // título de la pestaña
  'content': 'Código html que se quiere mostrar en la pestaña', // contenido para mostrar
  'intelligence': true // activa la inteligencia para transformar el contenido en texto inteligente
  // Cuando hablamos de texto inteligente nos referimos a que es capaz de transformar un enlace de una imagen en una etiqueta HTML IMG 
  // permitiendo la visualización de la misma, para un video añadir la etiqueta HTML VIDEO, enlace PDF en etiqueta HTML IFRAME... (*)
};
// Creamos el Popup
popup = new M.Popup();
// Añadimos la pestaña al popup
popup.addTab(featureTabOpts);
// Finalmente se añade al mapa, especificando las coordenadas
mapa.addPopup(popup, [240829,4143088]);

El anterior ejemplo, mostrará un popup en las coordenadas indicadas con el contenido indicado.

Un popup puede tener tantas pestañas como se desee. En el siguiente ejemplo, vamos a añadir una pestaña más al popup anterior:

// Creamos una nueva pestaña
const featureTabOpts2 = {
  'icon': 'g-cartografia-pin', // icono para mostrar en la pestaña
  'title': 'Título de la pestaña 2', // título de la pestaña
  'content': 'Código html que se quiere mostrar en la pestaña 2' // contenido para mostrar
};
// Añadimos la nueva pestaña al popup anterior
popup.addTab(featureTabOpts2);

Al tener más de una pestaña se muestran tantas como tenga el popup añadiéndolas con sus iconos, títulos y contenidos correspondientes en cada una de ellas.

Ejemplo de uso:

// Al hacer click sobre el mapa se mostrará un popup con el
// contenido 'Se ha hecho click en las coordenadas...' indicando
// las coordenadas devueltas por el evento click.
mapa.on(M.evt.CLICK, (m) => {
  // Creamos la pestaña
  const featureTabOpts = {
    'icon': 'g-cartografia-pin', // icono para mostrar en la pestaña
    'title': 'Título de la pestaña', // título de la pestaña
    'content': `Se ha hecho click en las coordenadas ${m.coord}` // contenido para mostrar
  };
  // Creamos el popup
  popup = new M.Popup();
  // Añadimos la pestaña al popup
  popup.addTab(featureTabOpts);
  // Añadimos el popup en las coordenadas devueltas por el evento click
  mapa.addPopup(popup, m.coord);
});

Además, existe la posibilidad de poder habilitar o deshabilitar el movimiento del mapa cuando se crea un popup, ya sea mediante el parámetro "extract" en capas vectoriales, "queryable" para servicios ráster, o mediante la creación explicada con anterioridad de un popup a través de new M.Popup() , a través de la configuración de la API-CNIG:

M.config("MOVE_MAP_EXTRACT",false)

Remote

API-CNIG incluye un mecanismo para realizar peticiones AJAX tanto GET como POST, haciendo uso de un proxy si este está configurado, evitando de esta forma tener que escribir todo el código para hacer la petición o tener que hacer uso de más librerías que faciliten esta tarea.

En el siguiente ejemplo se mostrará un diálogo de tipo informativo al realizar una petición GET a catastro cuando se hace click en el mapa en las coordenadas devueltas por el evento click.

mapa.on(M.evt.CLICK, (e) => {
  // Hacemos una petición get con M.remote indicando la URL de catastro y los parámetros a enviar
  M.remote.get("http://ovc.catastro.meh.es/ovcservweb/OVCSWLocalizacionRC/OVCCoordenadas.asmx/Consulta_RCCOOR",
    {
      'SRS': mapa.getProjection().code,
      'Coordenada_X': e.coord[0],
      'Coordenada_Y': e.coord[1]
    }
  ).then(function (res) {
    // Muestra un diálogo informativo con el resultado de la petición get
    M.dialog.info(res.text);
  });
});

Formateador WKT

La API incluye un formateador WKT para pasar de features a WKT y viceversa.

Para transformar un objeto geográfico (Feature) a WKT utilizamos el método write que cuenta con los siguientes parámetros:

  • feature: Objeto geográfico a transformar en formato WKT.
  • options: Opciones de la transformación (opcional). Realizar la reproyección no es obligatorio, es decir, si no se le pasa el objeto de opciones el WKT será devuelto en la proyección original.
    • dataProjection: Proyección de destino.
    • featureProjection: Proyección de origen.
// Creamos el constructor del formateador
const formatter = new M.format.WKT();

// Creamos el Feature (objeto geográfico) a transformar
const f1 = new M.Feature('id1', {
  "type": "Feature",
  "properties": {},
  "geometry": {
    "type": "Point",
    "coordinates": [
      -4.5703125,
      37.16031654673677
    ]
  }
});

// Pasamos de M.Feature a WKT
// Si queremos realizar la reproyección tanto dataProjection como featureProjection son obligatorios
const wkt1 = formatter.write(f1, { dataProjection: 'EPSG:3857', featureProjection: 'EPSG:4326' });

Para realizar la transformación de WKT a un objeto geográfico (Feature) se utiliza el método read. Incluye los siguientes parámetros:

  • wkt: WKT a transformar en objeto geográfico.
  • options: Opciones de la transformación (opcional). Si no se pasa como parámetro el objeto de opciones, el feature será devuelto en la proyección original, por lo tanto no se realizará la reproyección.
    • dataProjection: Proyección de destino.
    • featureProjection: Proyección de origen.

Una vez realizada la transformación se puede añadir el/los feature/s a una capa.

// Creamos el constructor
const formatter = new M.format.WKT();

// WKT de ejemplo
const wktEj = "POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30))";

// Pasamos de WKT a Feature
// En caso de querer reproyectar tanto dataProjection como featureProjection son obligatorios.
const feature = formatter.read(wktEj, { dataProjection: 'EPSG:3857', featureProjection: 'EPSG:4326' });

En caso de querer pasar una lista de Features (objetos geográficos) a WKTCollection utilizamos el método writeCollection con los siguientes parámetros:

  • Array<M.Feature>: Lista de objetos geográficos a transformar en WKTCollection.
  • options: Opciones de la transformación (opcional). Al igual que en los métodos anteriores si no se le pasa el objeto de opciones el WKTCollection será devuelto en la proyección original.
    • dataProjection: Proyección de destino.
    • featureProjection: Proyección de origen.
// Creamos el constructor
const formatter = new M.format.WKT();

// Creamos primer feature (objeto geográfico) a transformar
const feature1 = new M.Feature('id1', {
  "type": "Feature",
  "properties": {},
  "geometry": {
    "type": "Point",
    "coordinates": [
      -4.5703125,
      37.16031654673677
    ]
  }
});

// Creamos segundo feature (objeto geográfico) a transformar
const feature2 = new M.Feature('id2', {
  "type": "Feature",
  "properties": {},
  "geometry": {
    "type": "Point",
    "coordinates": [
      -2.3421134,
      40.33453245521455
    ]
  }
});

// Pasamos una lista de features a WKTCollection
// En caso de querer reproyectar tanto dataProjection como featureProjection son obligatorios
const wktCollection = formatter.writeCollection([feature1, feature2], { 
  dataProjection: 'EPSG:3857', 
  featureProjection: 'EPSG:4326' 
});

Para pasar de WKTCollection a una lista de features se utiliza el método readCollection con los siguientes parámetros:

  • WKTCollection: WKTCollection a transformar en una lista de objetos geográficos.
  • options: Opciones de la transformación (opcional). Si no se le pasa el objeto de opciones el Array<M.Feature> será devuelto en la proyección original.
    • dataProjection: Proyección de destino.
    • featureProjection: Proyección de origen.
// Creamos el constructor
const formatter = new M.format.WKT();

// WKTCollection de ejemplo
const wktEj2 = "GEOMETRYCOLLECTION (POINT (40 10),LINESTRING(10 10, 20 20, 10 40),POLYGON((40 40, 20 45, 45 30, 40 40)))";

// Pasamos de WKTCollection a M.Feature
// En caso de querer reproyectar tanto dataProjection como featureProjection son obligatorios
const feature = formatter.readCollection(wktEj2, { 
  dataProjection: 'EPSG:3857', 
  featureProjection: 'EPSG:4326' 
});

Codificador/Decodificador en Base64

La API dispone de un método en utilidades que permite codificar un objeto JSON en Base64.

M.utils.encodeBase64(contenido);

y de otro método que permite la decodificación:

M.utils.decodeBase64(contenido)

Este método se suele usar en los plugins para codificar las opciones que se le manda al constructor para generar la sintaxis para añadir el plugin por API-REST. Ejemplo:

  getAPIRestBase64() {
    return `${this.name}=base64=${M.utils.encodeBase64(this.options)}`;
  }

O para visualizar una capa GeoJSON por API-REST: Ejemplo:

// Codificamos la fuente
M.utils.encodeBase64({"type":"FeatureCollection","totalFeatures":8,"features":[{"type":"Feature","id":"provincias_pob.7","geometry":{"type":"Point","coordinates":[558168.25229024,4116978.43564967]},"geometry_name":"the_geom","properties":{"u_cod_prov":"04","nombre":"Almería","es_0_15":104194,"es_16_45":219575,"es_45_65":155307,"es_65":89821,"es_total":568897,"ex_0_15":24124,"ex_16_45":73969,"ex_45_65":27666,"ex_65":10811,"ex_total":136570,"to_0_15":128318,"to_16_45":293544,"to_45_65":182973,"to_65":100632,"to_total":705467}}],"crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:EPSG::25830"}}})

El contenido generado se añade por API-REST, obteniendo el siguiente enlace: https://componentes.cnig.es/api-core/?layers=OSM,GEOJSON*Capa*eyJ0eXBlIjoiRmVhdHVyZUNvbGxlY3Rpb24iLCJ0b3RhbEZlYXR1cmVzIjo4LCJmZWF0dXJlcyI6W3sidHlwZSI6IkZlYXR1cmUiLCJpZCI6InByb3ZpbmNpYXNfcG9iLjciLCJnZW9tZXRyeSI6eyJ0eXBlIjoiUG9pbnQiLCJjb29yZGluYXRlcyI6WzU1ODE2OC4yNTIyOTAyNCw0MTE2OTc4LjQzNTY0OTY3XX0sImdlb21ldHJ5X25hbWUiOiJ0aGVfZ2VvbSIsInByb3BlcnRpZXMiOnsidV9jb2RfcHJvdiI6IjA0Iiwibm9tYnJlIjoiQWxtZXLDrWEiLCJlc18wXzE1IjoxMDQxOTQsImVzXzE2XzQ1IjoyMTk1NzUsImVzXzQ1XzY1IjoxNTUzMDcsImVzXzY1Ijo4OTgyMSwiZXNfdG90YWwiOjU2ODg5NywiZXhfMF8xNSI6MjQxMjQsImV4XzE2XzQ1Ijo3Mzk2OSwiZXhfNDVfNjUiOjI3NjY2LCJleF82NSI6MTA4MTEsImV4X3RvdGFsIjoxMzY1NzAsInRvXzBfMTUiOjEyODMxOCwidG9fMTZfNDUiOjI5MzU0NCwidG9fNDVfNjUiOjE4Mjk3MywidG9fNjUiOjEwMDYzMiwidG9fdG90YWwiOjcwNTQ2N319XSwiY3JzIjp7InR5cGUiOiJuYW1lIiwicHJvcGVydGllcyI6eyJuYW1lIjoidXJuOm9nYzpkZWY6Y3JzOkVQU0c6OjI1ODMwIn19fQ==

Ejemplo de uso en un visualizador: https://www.ign.es/iberpix/?center=-428106.86611520057,4334472.25393817&zoom=5&srs=EPSG:3857&layers=GeoJSON*Husos*eyJ0eXBlIjoiRmVhdHVyZUNvbGxlY3Rpb24iLCJmZWF0dXJlcyI6W3sidHlwZSI6IkZlYXR1cmUiLCJwcm9wZXJ0aWVzIjp7Ikh1c28iOjMwfSwiZ2VvbWV0cnkiOnsiY29vcmRpbmF0ZXMiOltbWy02LDUwXSxbMCw1MF0sWzAsMjBdLFstNiwyMF0sWy02LDUwXV1dLCJ0eXBlIjoiUG9seWdvbiJ9fSx7InR5cGUiOiJGZWF0dXJlIiwicHJvcGVydGllcyI6eyJIdXNvIjozMX0sImdlb21ldHJ5Ijp7ImNvb3JkaW5hdGVzIjpbW1swLDUwXSxbNiw1MF0sWzYsMjBdLFswLDIwXSxbMCw1MF1dXSwidHlwZSI6IlBvbHlnb24ifX0seyJ0eXBlIjoiRmVhdHVyZSIsInByb3BlcnRpZXMiOnsiSHVzbyI6Mjl9LCJnZW9tZXRyeSI6eyJjb29yZGluYXRlcyI6W1tbLTEyLDUwXSxbLTYsNTBdLFstNiwyMF0sWy0xMiwyMF0sWy0xMiw1MF1dXSwidHlwZSI6IlBvbHlnb24ifX0seyJ0eXBlIjoiRmVhdHVyZSIsInByb3BlcnRpZXMiOnsiSHVzbyI6Mjd9LCJnZW9tZXRyeSI6eyJjb29yZGluYXRlcyI6W1tbLTE4LDUwXSxbLTEyLDUwXSxbLTEyLDIwXSxbLTE4LDIwXSxbLTE4LDUwXV1dLCJ0eXBlIjoiUG9seWdvbiJ9fV19

Podemos decodificar el contenido usando el método decodeBase64. Ejemplo

M.utils.decodeBase64('eyJ0eXBlIjoiRmVhdHVyZUNvbGxlY3Rpb24iLCJmZWF0dXJlcyI6W3sidHlwZSI6IkZlYXR1cmUiLCJwcm9wZXJ0aWVzIjp7Ikh1c28iOjMwfSwiZ2VvbWV0cnkiOnsiY29vcmRpbmF0ZXMiOltbWy02LDUwXSxbMCw1MF0sWzAsMjBdLFstNiwyMF0sWy02LDUwXV1dLCJ0eXBlIjoiUG9seWdvbiJ9fSx7InR5cGUiOiJGZWF0dXJlIiwicHJvcGVydGllcyI6eyJIdXNvIjozMX0sImdlb21ldHJ5Ijp7ImNvb3JkaW5hdGVzIjpbW1swLDUwXSxbNiw1MF0sWzYsMjBdLFswLDIwXSxbMCw1MF1dXSwidHlwZSI6IlBvbHlnb24ifX0seyJ0eXBlIjoiRmVhdHVyZSIsInByb3BlcnRpZXMiOnsiSHVzbyI6Mjl9LCJnZW9tZXRyeSI6eyJjb29yZGluYXRlcyI6W1tbLTEyLDUwXSxbLTYsNTBdLFstNiwyMF0sWy0xMiwyMF0sWy0xMiw1MF1dXSwidHlwZSI6IlBvbHlnb24ifX0seyJ0eXBlIjoiRmVhdHVyZSIsInByb3BlcnRpZXMiOnsiSHVzbyI6Mjd9LCJnZW9tZXRyeSI6eyJjb29yZGluYXRlcyI6W1tbLTE4LDUwXSxbLTEyLDUwXSxbLTEyLDIwXSxbLTE4LDIwXSxbLTE4LDUwXV1dLCJ0eXBlIjoiUG9seWdvbiJ9fV19')

(*) Parámetro intelligence: este parámetro se usa en las utilidades de dialog y popup.

Se puede activar de los siguientes modos:

  1. Indicando valor booleano: {... intelligence: true ... }
  2. Objeto:
   intelligence: {
     activate: true,
   }
  1. Objeto con características sobre las etiquetas HTML, permite especificar los tamaños de los contenedores:
   intelligence: {
     activate: true,
     sizes: {
       images: ['20px', '20px'],
       documents: ['50px', '50px'],
       videos: ['100px', '100px'],
       audios: ['200px', '20px'],
     }
   }

Método getImageMap: Te devuelve una captura del mapa.

M.utils.getImageMap(map, type, canva);

Parámetros:

  • map: Mapa.
  • type: Formato de la imagen, por defecto "image/jpeg".
  • canva: Por defecto cogerá el del mapa.

Ejemplo:

M.utils.getImageMap(map);

1.INICIO
   1.1. Componentes de la API-CNIG
   1.2. Documentación y Puntos de acceso
   1.3. Primeros pasos
   1.4. Diagrama API CNIG

2. MAPA
2.1. Capas

 ■ 2.1.1. Fuentes
   • 2.1.1.1. Capas vectoriales
     + Vector
     + WFS
     + GeoJSON
     + KML
     + MVT
     + OGCAPIFeatures
     + MBTilesVector
     + GenericVector
   • 2.1.1.2. Capas ráster
     + WMS
     + WMTS
     + TMS
     + XYZ
     + OSM
     + MBTiles
     + GenericRaster
   • 2.1.1.3. Capas rápidas

 ■ 2.1.2. Simbolización
   • 2.1.2.1. Genérica
     + Puntos
     + Líneas
     + Polígonos
   • 2.1.2.2. Básica
     + Puntos
     + Líneas
     + Polígonos
   • 2.1.2.3. Avanzada
     + Coropletas
     + Proporcional
     + Categorías
     + Estadísticos
     + Mapas de Calor
     + Cluster
     + Línea de flujo
     + Composición

 ■ 2.1.3. Filtros

    2.3. Plugins

2.4. Paneles

  ■ Creación de panel desde cero sin controles

  ■ Tutorial Panel de un único control

  ■ Tutorial Panel de un único control con más de un botón

  ■ Tutorial Panel con más de un control

2.5. Eventos

  ■ Gestión de eventos
  ■ Gestión de eventos en controles personalizados

    2.6. Internacionalización

    2.7. Configuración

    2.8. Acceso librerías base

3. UTILIDADES

4. PROXY

5. API REST
 5.1. Parametrización API-REST
 5.2. Base de Datos API-REST
 5.3. API REST Actions
 5.4. Servicio de correos electrónicos
 5.5. Capas rápidas

6. PARAMETRIZACIÓN VISUALIZADORES

7. SOLUCIÓN DE PROBLEMAS

8. PROCESO DE VERSIONADO

9. GUÍA DE DESARROLLO
  > Guía de desarrollo de plugins
  > Guía de desarrollo de visualizadores con React
  > Guía de desarrollo de componentes
  > Guía para el desarrollo de API-CNIG
  > Compilación proyecto API-CNIG

Clone this wiki locally