diff --git a/package.json b/package.json
index fc9e693..5861f04 100644
--- a/package.json
+++ b/package.json
@@ -15,8 +15,12 @@
"dependencies": {
"@gouvfr/dsfr": "^1.11.2",
"@gouvminint/vue-dsfr": "^5.14.2",
+ "@vueuse/components": "^10.9.0",
+ "@vueuse/core": "^10.9.0",
"geoportal-extensions-openlayers": "./geoportal-extensions-openlayers-1.0.0-beta.32-52.tgz",
- "ol": "8.2.0"
+ "ol": "8.2.0",
+ "vue": "^3.4.21",
+ "vue-router": "^4.3.0"
},
"devDependencies": {
"@antfu/eslint-config": "^2.11.6",
@@ -37,6 +41,7 @@
"oh-vue-icons": "1.0.0-rc3",
"pinia": "^2.1.7",
"rimraf": "^5.0.5",
+ "sass": "^1.76.0",
"typescript": "~5.4.0",
"unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.27.0",
diff --git a/src/App.vue b/src/App.vue
index be23775..9a83a1e 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -5,8 +5,6 @@ import { useMatchMedia } from '@/composables/matchMedia';
import { useHeaderParams } from '@/composables/headerParams';
import { useFooterParams } from '@/composables/footerParams';
-import StoreDataLoading from './components/StoreDataLoading.vue';
-
useScheme()
import { useModel } from 'vue';
@@ -85,36 +83,54 @@ const navItems: DsfrNavigationProps['navItems'] = [
-
-
+
-
-
-
-
-
- Loading...
-
-
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/src/components.d.ts b/src/components.d.ts
index 8a15dba..85be902 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -8,15 +8,29 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
Attributions: typeof import('./components/carte/control/Attributions.vue')['default']
+ Carto: typeof import('./components/carte/Carto.vue')['default']
Control: typeof import('./components/carte/Control.vue')['default']
+ DsfrCheckboxSet: typeof import('@gouvminint/vue-dsfr')['DsfrCheckboxSet']
DsfrFooter: typeof import('@gouvminint/vue-dsfr')['DsfrFooter']
DsfrHeader: typeof import('@gouvminint/vue-dsfr')['DsfrHeader']
DsfrModal: typeof import('@gouvminint/vue-dsfr')['DsfrModal']
DsfrNavigation: typeof import('@gouvminint/vue-dsfr')['DsfrNavigation']
DsfrRadioButtonSet: typeof import('@gouvminint/vue-dsfr')['DsfrRadioButtonSet']
+ DsfrSideMenu: typeof import('@gouvminint/vue-dsfr')['DsfrSideMenu']
+ Layer: typeof import('./components/carte/Layer/Layer.vue')['default']
+ LayerManager: typeof import('./components/carte/Layer/LayerManager.vue')['default']
+ LayerSwitcher: typeof import('./components/carte/control/LayerSwitcher.vue')['default']
+ LeftMenu: typeof import('./components/menu/LeftMenu.vue')['default']
Map: typeof import('./components/carte/Map.vue')['default']
- MenuControl: typeof import('./components/carte/MenuControl.vue')['default']
+ MenuCatalogue: typeof import('./components/menu/MenuCatalogue.vue')['default']
+ MenuControl: typeof import('./components/menu/MenuControl.vue')['default']
+ MenuLateralContent: typeof import('./components/menu/MenuLateralContent.vue')['default']
+ MenuLateralNavButton: typeof import('./components/menu/MenuLateralNavButton.vue')['default']
+ MenuLateralWrapper: typeof import('./components/menu/MenuLateralWrapper.vue')['default']
+ MenuObject: typeof import('./components/menu/MenuObject.vue')['default']
OverviewMap: typeof import('./components/carte/control/OverviewMap.vue')['default']
+ Patience: typeof import('./components/utils/Patience.vue')['default']
+ RightMenu: typeof import('./components/menu/RightMenu.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
ScaleLine: typeof import('./components/carte/control/ScaleLine.vue')['default']
diff --git a/src/components/StoreDataLoading.vue b/src/components/StoreDataLoading.vue
index 39c35eb..70b236e 100644
--- a/src/components/StoreDataLoading.vue
+++ b/src/components/StoreDataLoading.vue
@@ -1,27 +1,23 @@
-
+
\ No newline at end of file
diff --git a/src/components/carte/Carto.vue b/src/components/carte/Carto.vue
new file mode 100644
index 0000000..9a14798
--- /dev/null
+++ b/src/components/carte/Carto.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/carte/Control.vue b/src/components/carte/Control.vue
index e9ce039..dc7c582 100644
--- a/src/components/carte/Control.vue
+++ b/src/components/carte/Control.vue
@@ -8,6 +8,7 @@ import ScaleLine from './control/ScaleLine.vue'
import OverviewMap from './control/OverviewMap.vue'
import Zoom from './control/Zoom.vue'
import Attributions from './control/Attributions.vue'
+import LayerSwitcher from './control/LayerSwitcher.vue'
import { useControls } from '@/composables/controls'
@@ -15,6 +16,16 @@ const props = defineProps({
controlOptions: Array
})
+const layerSwitcherOptions = {
+ options : {
+ // FIXME
+ // position : "top-right",
+ collapsed : true,
+ panel : true,
+ counter : true
+ }
+}
+
const scaleLineOptions = {
units: 'metric',
bar: false,
@@ -31,6 +42,7 @@ const searchEngineOptions = {
search: true
},
searchOptions: {
+ addToMap : false,
serviceOptions : {
services: "WMTS,WMS,TMS"
}
@@ -55,6 +67,10 @@ const attributionsOptions = {}
+
+// FIXME c'est pour l'exemple car les couches sont gérées par les extensions !
+// cf. LayerManager
+import TileLayer from 'ol/layer/Tile.js'
+
+const props = defineProps({
+ layerOptions: Object
+})
+
+const map = inject('map')
+const layer = ref(new TileLayer(props.layerOptions))
+
+onMounted(() => {
+ map?.addLayer(layer.value)
+})
+
+
+onUnmounted(() => {
+ map?.removeLayer(layer.value)
+})
+
+
+
+
+
+
+
+
diff --git a/src/components/carte/Layer/LayerManager.vue b/src/components/carte/Layer/LayerManager.vue
new file mode 100644
index 0000000..6507a32
--- /dev/null
+++ b/src/components/carte/Layer/LayerManager.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
diff --git a/src/components/carte/Map.vue b/src/components/carte/Map.vue
index b726034..107ccdd 100644
--- a/src/components/carte/Map.vue
+++ b/src/components/carte/Map.vue
@@ -56,8 +56,7 @@ provide('map', map)
diff --git a/src/components/carte/View.vue b/src/components/carte/View.vue
index 21f7b48..4e8db04 100644
--- a/src/components/carte/View.vue
+++ b/src/components/carte/View.vue
@@ -7,7 +7,6 @@ const store = useMapStore()
const props = defineProps({
zoom : Number,
center : Array,
- layers : Array
})
// recuperation de l'objet 'map' du composant parent
@@ -26,7 +25,8 @@ const view = new View({
* pour mise à jour du centre de la carte
*/
view.on("change:center", (e) => {
- store.setCenter(e.target.getCenter());
+ store.lat = e.target.getCenter()[0]
+ store.long = e.target.getCenter()[1]
})
/**
@@ -34,19 +34,14 @@ view.on("change:center", (e) => {
* pour mise à jour du zoom de la carte
*/
view.on("change:resolution", (e) => {
- store.setZoom(view.getZoom())
+ store.zoom = view.getZoom()
})
onMounted(() => {
if (map) {
- // ajout des couches
- props.layers.forEach((layer) => {
- map.addLayer(layer)
- })
- // ajout de la vue
map.setView(view)
// enregistrement
- store.setMap(map)
+ store.map = map
}
})
diff --git a/src/components/carte/control/LayerSwitcher.vue b/src/components/carte/control/LayerSwitcher.vue
new file mode 100644
index 0000000..b282bb4
--- /dev/null
+++ b/src/components/carte/control/LayerSwitcher.vue
@@ -0,0 +1,102 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/carte/control/SearchEngine.vue b/src/components/carte/control/SearchEngine.vue
index 91b1651..0b5aa71 100644
--- a/src/components/carte/control/SearchEngine.vue
+++ b/src/components/carte/control/SearchEngine.vue
@@ -1,10 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/menu/MenuCatalogue.vue b/src/components/menu/MenuCatalogue.vue
new file mode 100644
index 0000000..6dffe43
--- /dev/null
+++ b/src/components/menu/MenuCatalogue.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/carte/MenuControl.vue b/src/components/menu/MenuControl.vue
similarity index 55%
rename from src/components/carte/MenuControl.vue
rename to src/components/menu/MenuControl.vue
index 662b31c..7db6571 100644
--- a/src/components/carte/MenuControl.vue
+++ b/src/components/menu/MenuControl.vue
@@ -1,12 +1,16 @@
+
+ :model-value="selectedControls"
+ />
diff --git a/src/components/menu/MenuLateralWrapper.vue b/src/components/menu/MenuLateralWrapper.vue
new file mode 100644
index 0000000..8fa4768
--- /dev/null
+++ b/src/components/menu/MenuLateralWrapper.vue
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/menu/RightMenu.vue b/src/components/menu/RightMenu.vue
new file mode 100644
index 0000000..58b9065
--- /dev/null
+++ b/src/components/menu/RightMenu.vue
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/utils/Patience.vue b/src/components/utils/Patience.vue
new file mode 100644
index 0000000..9a0e1ed
--- /dev/null
+++ b/src/components/utils/Patience.vue
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/composables/controls.ts b/src/composables/controls.ts
index d68fe81..eaed9b2 100644
--- a/src/composables/controls.ts
+++ b/src/composables/controls.ts
@@ -2,7 +2,8 @@ export const useControls = {
OverviewMap: 'OverviewMap',
SearchEngine: 'SearchEngine',
ScaleLine: 'ScaleLine',
- Zoom: 'Zoom',
+ LayerSwitcher: 'LayerSwitcher'
+ // Zoom: 'Zoom',
// Attributions: 'Attributions'
// Rotate: 'Rotate'
}
diff --git a/src/composables/layers.ts b/src/composables/layers.ts
new file mode 100644
index 0000000..af88e4a
--- /dev/null
+++ b/src/composables/layers.ts
@@ -0,0 +1,26 @@
+// FIXME le nom du composable !?
+// ex useResolutionsGeographic()
+export const resolutions = [
+ 156543.03392804103,
+ 78271.5169640205,
+ 39135.75848201024,
+ 19567.879241005125,
+ 9783.939620502562,
+ 4891.969810251281,
+ 2445.9849051256406,
+ 1222.9924525628203,
+ 611.4962262814101,
+ 305.74811314070485,
+ 152.87405657035254,
+ 76.43702828517625,
+ 38.218514142588134,
+ 19.109257071294063,
+ 9.554628535647034,
+ 4.777314267823517,
+ 2.3886571339117584,
+ 1.1943285669558792,
+ 0.5971642834779396,
+ 0.29858214173896974,
+ 0.14929107086948493,
+ 0.07464553543474241
+];
\ No newline at end of file
diff --git a/src/icons.ts b/src/icons.ts
index a4be0b2..831e9e4 100644
--- a/src/icons.ts
+++ b/src/icons.ts
@@ -11,3 +11,15 @@ export {
export {
FaUserCircle
} from 'oh-vue-icons/icons/fa/index.js'
+
+export {
+ BiChevronDoubleRight
+} from 'oh-vue-icons/icons/bi/index.js'
+
+export {
+ CoListLowPriority
+} from 'oh-vue-icons/icons/co/index.js'
+
+export {
+ IoSettingsSharp
+} from 'oh-vue-icons/icons/io/index.js'
diff --git a/src/router/index.ts b/src/router/index.ts
index 7d40609..1ff82be 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -4,8 +4,11 @@ import {
createWebHistory }
from 'vue-router'
-import Carto from '../views/Carto.vue';
-import Login from '../views/Login.vue';
+import AsyncStorageInit from '../views/AsyncStorageInit.vue'
+import Catalogue from '../views/Catalogue.vue'
+import Login from '../views/Login.vue'
+import Presentation from '../views/Presentation.vue'
+import Accueil from '../views/Accueil.vue'
const MAIN_TITLE = 'Carte.gouv'
@@ -13,7 +16,7 @@ const routes: Array = [
{
path: '/',
name: 'Carte',
- component: Carto,
+ component: AsyncStorageInit,
},
{
path: '/login',
diff --git a/src/stores/dataStore.js b/src/stores/dataStore.js
index f6a6d39..60f1dcb 100644
--- a/src/stores/dataStore.js
+++ b/src/stores/dataStore.js
@@ -1,4 +1,6 @@
-import { defineStore } from 'pinia'
+import {
+ defineStore
+} from 'pinia';
/**
* Store des couches
@@ -6,70 +8,212 @@ import { defineStore } from 'pinia'
* - utilisation des informations éditoriales : fonds de carte, thématique...
* - ressources additionnelles : metadonnées, vignettes, ...
*/
-export const useDataStore = defineStore('data', {
- // state
- state: () => ({
- data: {},
- isLoaded: false
- }),
- // getters
- getters: {
- // TODO getters :
- // - recherche des param tech pour une couche
- getLayers : (state) => state.data.layers,
- getLayerByID : (state) => { return (id) => state.data.layers[id]; },
- getLayerByName : (state) => {
- // Ex. OCSGE.COUVERTURE.2011$GEOPORTAIL:OGC:WMS
- // ID : {name}$GEOPORTAIL:(OGC|GPP):(WMTS|WMS|TMS|WFS)
- return (name, service) => {
- var id = null;
- for (const key in state.data.layers) {
- if (Object.hasOwnProperty.call(state.data.layers, key)) {
- const l = state.data.layers[key];
- if (l.name === name && l.serviceParams.id.split(":")[1] === service) {
- id = l.name + "$GEOPORTAIL:" + l.serviceParams.id
- return state.data.layers[id];
- }
- }
+export const useDataStore = defineStore('data', () => {
+ const m_layers = ref({});
+ const m_generalOptions = ref({});
+ const m_tileMatrixSets = ref({});
+ const isLoaded = ref(false);
+ const error = ref("");
+
+
+ async function fetchData() {
+ try {
+
+ const techUrl =
+ import.meta.env.VITE_GPF_CONF_TECH_URL || "data/layers.json";
+ const editoUrl =
+ import.meta.env.VITE_GPF_CONF_EDITO_URL || "data/edito.json";
+
+ const editoRes = await fetch(editoUrl);
+ const techRes = await fetch(techUrl);
+
+ const tech = await techRes.json();
+ const edito = await editoRes.json();
+
+ const editoWithTech = Object.fromEntries(Object.keys(edito.layers).map(id => {
+ return [id, {
+ ...tech.layers[id],
+ ...edito.layers[id]
+ }]
+ }));
+
+ const res = {
+ ...tech.layers,
+ ...editoWithTech
+ }; // merge
+
+ m_layers.value = res;
+ m_generalOptions.value = tech.generalOptions;
+ m_tileMatrixSets.value = tech.tileMatrixSets;
+ this.isLoaded = true;
+ return res;
+
+ } catch (err) {
+ console.log(err);
+ this.isLoaded = false;
+ error.value = err.message;
+ }
+
+ }
+
+ function getLayers() {
+ return m_layers.value;
+ }
+
+ function getLayerIdByName(name, service) {
+ // Ex. OCSGE.COUVERTURE.2011$GEOPORTAIL:OGC:WMS
+ // ID : {name}$GEOPORTAIL:(OGC|GPP):(WMTS|WMS|TMS|WFS)
+ for (const key in m_layers.value) {
+ if (Object.hasOwnProperty.call(m_layers.value, key)) {
+ const l = m_layers.value[key];
+ if (l.name === name && l.serviceParams.id.split(":")[1] === service) {
+ const id = l.name + "$GEOPORTAIL:" + l.serviceParams.id
+ return id;
}
}
- },
- getTileMatrixSets : (state) => state.data.tileMatrixSets,
- getTileMatrixSetByID : (state) => { return (id) => state.data.tileMatrixSets[id]; }
- },
- // methodes
- methods: {
-
- },
- // actions
- actions: {
- /**
- * Téléchargement de l'aggregation des GetCapabilities
- * avec fusion avec les informations editoriales
- * /!\ opération asynchrone && initialisation de la carte /!\
- */
- async fetchData() {
- var techUrl = import.meta.env.VITE_GPF_CONF_TECH_URL || "data/layers.json";
- var editoUrl = import.meta.env.VITE_GPF_CONF_EDITO_URL || "data/edito.json";
- var urls = [
- techUrl,
- editoUrl
- ];
- return Promise.all(
- urls.map((url) => fetch(url)
- .then((response) => response.json())))
- .then((jsons) => {
- var techs = jsons[0];
- var edito = jsons[1];
- Object.keys(edito.layers).forEach(id => {
- Object.assign(techs.layers[id], edito.layers[id]); // merge
- });
- this.data = techs;
- this.isLoaded = true;
- })
- .catch((e) => {
- console.error('An error occurred:', e);
- });
}
}
-})
+
+ function getLayerByName(name, service) {
+ const id = this.getLayerIdByName(name, service);
+ return this.getLayerByID(id);
+ }
+
+ function getLayerByID(id) {
+ return m_layers.value[id];
+ }
+
+ function getLayerKeysByID(id) {
+ var layerKeys = [];
+ var resourcesByKey = m_generalOptions.value.apiKeys;
+ for (var key in resourcesByKey) {
+ var resourcesArray = resourcesByKey[key];
+ resourcesArray.forEach(function (layerId) {
+ if (layerId === id) {
+ layerKeys.push(key);
+ }
+ });
+ }
+ return layerKeys;
+ }
+
+ function getLayerParamsByName(name, service) {
+ var params = null;
+ if ((service === "WMS" || Object.keys(this.getTileMatrixSets()).length !== 0) && Object.keys(this.getLayers()).length !== 0) {
+ var id = this.getLayerIdByName(name, service);
+ params = this.getLayerParamsByID(id);
+ }
+ return params;
+ }
+
+ function getLayerParamsByID(id) {
+ var params = null;
+ if (id) {
+ params = {};
+ // get the layer Conf Object
+ var l = this.getLayerByID(id);
+
+ var keys = this.getLayerKeysByID(id);
+ if (keys.length === 0) {
+ return;
+ }
+
+ // get services params
+ for (var i = 0; i < keys.length; i++) {
+ // only one serverUrl is saved in Gp.Config : with multiKeys, we have to retrieve the key used in the serverUrl property
+ if (l.serviceParams.serverUrl[keys[i]]) {
+ params.url = l.serviceParams.serverUrl[keys[i]];
+ }
+ }
+
+ const wmsTypeRegex = /\/v\//;
+ // WMS vector style always empty (not in getCap)
+ if (wmsTypeRegex.test(params.url)) {
+ params.styles = " ";
+ } else {
+ // WMS raster style is defined in getCap
+ params.styles = l.styles[0].name;
+ }
+
+ params.version = l.serviceParams.version;
+ params.format = l.formats[0].name;
+ params.projection = l.defaultProjection;
+
+ // get layer info and constraints
+ params.minScale = l.globalConstraint.minScaleDenominator;
+ params.maxScale = l.globalConstraint.maxScaleDenominator;
+ params.extent = l.globalConstraint.bbox;
+ params.legends = l.legends;
+ params.title = l.title;
+ params.description = l.description;
+
+ // Informations non disponibles avec les getCap
+ // params.metadata = l.getMetadata();
+ // params.originators = l.getOriginators();
+ // params.quicklookUrl = l.getQuicklookUrl();
+
+ // WMTS : get the tileMatrixSetLimits
+ if (l.wmtsOptions) {
+ params.tileMatrixSetLimits = l.wmtsOptions.tileMatrixSetLimits;
+ var TMSLink = l.wmtsOptions.tileMatrixSetLink;
+ if (TMSLink) {
+ params.TMSLink = TMSLink;
+ var tmsConf = this.getTileMatrixSetByID(TMSLink);
+ // Get matrix origin : Gp.Point = Object{x:Float, y:Float}
+ // params.matrixOrigin = tmsConf.getTopLeftCorner();
+ params.matrixIds = Object.keys(tmsConf.tileMatrices);
+ params.tileMatrices = tmsConf.tileMatrices;
+ // by default, pseudo mercator resolutions
+ params.nativeResolutions = tmsConf.nativeResolutions || this.getTMSConf("PM").nativeResolutions;
+ }
+ }
+ }
+ return params;
+ }
+
+ function getGlobalConstraintsByID(id) {
+ var params = null;
+
+ if (id) {
+ // get layer configuration object
+ var l = this.getLayerByID(id);
+ params = {};
+ params.projection = l.defaultProjection;
+ params.minScale = l.globalConstraint.minScaleDenominator;
+ params.maxScale = l.globalConstraint.maxScaleDenominator;
+ params.extent = l.globalConstraint.bbox;
+ }
+
+ return params;
+ }
+
+ function getGlobalConstraintsByName(name, service) {
+ var id = this.getLayerIdByName(name, service);
+ return this.getGlobalConstraintsByID(id);
+ }
+
+ function getTileMatrixSets() {
+ return m_tileMatrixSets.value;
+ }
+
+ function getTileMatrixSetByID(id) {
+ return m_tileMatrixSets.value[id];
+ }
+
+ return {
+ error,
+ isLoaded,
+ fetchData,
+ getLayers,
+ getLayerKeysByID,
+ getLayerIdByName,
+ getLayerByName,
+ getLayerByID,
+ getTileMatrixSets,
+ getTileMatrixSetByID,
+ getLayerParamsByName,
+ getLayerParamsByID,
+ getGlobalConstraintsByID,
+ getGlobalConstraintsByName
+ }
+})
\ No newline at end of file
diff --git a/src/stores/mapStore.js b/src/stores/mapStore.js
index e75953c..13ee5f5 100644
--- a/src/stores/mapStore.js
+++ b/src/stores/mapStore.js
@@ -1,32 +1,41 @@
-import { defineStore } from 'pinia'
+import {
+ defineStore
+} from 'pinia';
+
+
+import {
+ useStorage
+} from '@vueuse/core';
/**
* Store des objets de la carte
* Enregistrement dans le LocalStorage
- * @todo à completer
+ *
*/
-export const useMapStore = defineStore('map', {
- state: () => ({
- map: null,
- zoom: 0,
- center: []
- }),
- getters: {
- getMap: (state) => state.map,
- getZoom: (state) => state.zoom,
- getCenter: (state) => state.center
- },
- actions: {
- setMap(map) {
- this.map = map;
- },
- setZoom(zoom) {
- this.zoom = zoom;
- localStorage.setItem('zoom', zoom)
- },
- setCenter(center) {
- this.center = center;
- localStorage.setItem('center', center)
- }
+export const useMapStore = defineStore('map', () => {
+ const map = ref({});
+ const zoom = useStorage('zoom', 12);
+ const lat = useStorage('lat', 283734.248995);
+ const long = useStorage('long', 5655117.100650);
+ const center = computed(() => {
+ return [lat.value, long.value];
+ });
+
+ watch(zoom, () => {
+ localStorage.setItem('zoom', zoom.value);
+ })
+ watch(lat, () => {
+ localStorage.setItem('lat', lat.value);
+ })
+ watch(long, () => {
+ localStorage.setItem('long', long.value);
+ })
+
+ return {
+ map,
+ zoom,
+ center,
+ lat,
+ long
}
-});
+})
\ No newline at end of file
diff --git a/src/views/AsyncStorageInit.vue b/src/views/AsyncStorageInit.vue
new file mode 100644
index 0000000..7893f49
--- /dev/null
+++ b/src/views/AsyncStorageInit.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/Carto.vue b/src/views/Carto.vue
deleted file mode 100644
index e7dbc0d..0000000
--- a/src/views/Carto.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
diff --git a/src/views/CartoAndTools.vue b/src/views/CartoAndTools.vue
new file mode 100644
index 0000000..002a70a
--- /dev/null
+++ b/src/views/CartoAndTools.vue
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file