mirror of
https://forge.chapril.org/tykayn/libre-charge-map
synced 2025-06-20 01:34:43 +02:00
ajout des suggestions osmose
This commit is contained in:
parent
522f48f887
commit
e0a042c28b
8 changed files with 429 additions and 769 deletions
12
README.md
12
README.md
|
@ -10,8 +10,14 @@ développé par tykayn - https://www.cipherbliss.com - à partir d'un squelette
|
||||||
Mastodon: https://mastodon.cipherbliss.com/@tykayn
|
Mastodon: https://mastodon.cipherbliss.com/@tykayn
|
||||||
|
|
||||||
# Fonctionnalités
|
# Fonctionnalités
|
||||||
Affichage des stations de recharge colorées selon leur puissance maximale délivrée sur un totem.
|
- Affichage des stations de recharge colorées selon leur puissance maximale délivrée sur un totem.
|
||||||
Changement de fond de carte.
|
- Changement de fond de carte.
|
||||||
|
- Voir les restaurants.
|
||||||
|
- Recherche d'un lieu.
|
||||||
|
- Visite d'une des villes les plus peuplées de France au hasard.
|
||||||
|
- Affichage des bornes suggérées à l'intégration par Osmose.
|
||||||
|
- Proposition de correction dans JOSM.
|
||||||
|
- Voir la zone dans Panoramax.
|
||||||
|
|
||||||
# comment ça marche ?
|
# comment ça marche ?
|
||||||
Avec une lib qui affiche un fond de carte sur lequel on peut naviguer et des marqueurs, on demande poliment à un site web, Overpass Turbo, quels sont les points et polygones d'OpenStreetMap correspondant à plusieurs types de restaurants et lieux où l'on peut trouver à manger et à boire à consommer sur place ou à emporter.
|
Avec une lib qui affiche un fond de carte sur lequel on peut naviguer et des marqueurs, on demande poliment à un site web, Overpass Turbo, quels sont les points et polygones d'OpenStreetMap correspondant à plusieurs types de restaurants et lieux où l'on peut trouver à manger et à boire à consommer sur place ou à emporter.
|
||||||
|
@ -32,6 +38,8 @@ Gnu Affero 3+
|
||||||
|
|
||||||
# servir le site localement
|
# servir le site localement
|
||||||
Ouvrir la page index.html dans votre navigateur préféré, ou utiliser le paquet npm `serve`.
|
Ouvrir la page index.html dans votre navigateur préféré, ou utiliser le paquet npm `serve`.
|
||||||
|
Recomplilez les styles scss avec `bash styles.sh`.
|
||||||
|
|
||||||
# Requête overpass
|
# Requête overpass
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
|
346
js/lcm_main.js
346
js/lcm_main.js
|
@ -7,7 +7,7 @@
|
||||||
import lcm_config from './lcm_config.js'
|
import lcm_config from './lcm_config.js'
|
||||||
import lcm_utils from './lcm_utils.js'
|
import lcm_utils from './lcm_utils.js'
|
||||||
import lcm_color_utils from './lcm_color_utils.js'
|
import lcm_color_utils from './lcm_color_utils.js'
|
||||||
import {sendToJOSM, createJOSMEditLink} from './lcm_editor.js'
|
import { sendToJOSM, createJOSMEditLink } from './lcm_editor.js'
|
||||||
|
|
||||||
let geojsondata;
|
let geojsondata;
|
||||||
let lastLatLng;
|
let lastLatLng;
|
||||||
|
@ -115,7 +115,7 @@ let overlays = {
|
||||||
stations: all_stations_markers
|
stations: all_stations_markers
|
||||||
}
|
}
|
||||||
|
|
||||||
const layerControl = L.control.layers(baseLayers, overlays, {collapsed: true}).addTo(map)
|
const layerControl = L.control.layers(baseLayers, overlays, { collapsed: true }).addTo(map)
|
||||||
tileGrey.addTo(map)
|
tileGrey.addTo(map)
|
||||||
|
|
||||||
|
|
||||||
|
@ -286,17 +286,35 @@ function displayStatsFromGeoJson(resultAsGeojson) {
|
||||||
$('#bars_power').html(bar_powers);
|
$('#bars_power').html(bar_powers);
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindEventsOnJosmRemote() {
|
// Modifier bindEventsOnJosmRemote pour cibler les boutons dans un contexte (la popup)
|
||||||
let josm_remote_buttons = $(`#sendToJOSM`)
|
function bindEventsOnJosmRemote(popupElement) {
|
||||||
$(josm_remote_buttons[0]).on('click', () => {
|
// Cible tous les liens JOSM à l'intérieur de l'élément popup fourni
|
||||||
let josm_link = $(josm_remote_buttons[0]).attr('data-href')
|
$(popupElement).find('.edit-button.josm').each(function () {
|
||||||
$.get(josm_link, (res) => {
|
// Utiliser .off().on() pour éviter les liaisons multiples si la popup est rouverte
|
||||||
console.log('res', res)
|
$(this).off('click').on('click', (event) => {
|
||||||
})
|
event.preventDefault(); // Empêcher le comportement par défaut du lien
|
||||||
})
|
let josm_link = $(this).attr('data-href');
|
||||||
|
console.log('Sending command to JOSM:', josm_link);
|
||||||
|
// Utiliser fetch pour la requête GET vers JOSM (plus moderne que $.get)
|
||||||
|
fetch(josm_link)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
// Gérer les erreurs de communication avec JOSM
|
||||||
|
console.error('JOSM remote control error:', response.status, response.statusText);
|
||||||
|
alert('Erreur de communication avec JOSM. Assurez-vous que JOSM est lancé et que le contrôle à distance est activé.');
|
||||||
|
} else {
|
||||||
|
console.log('JOSM command sent successfully.');
|
||||||
|
// Optionnel: Afficher une notification de succès
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Failed to send command to JOSM:', error);
|
||||||
|
alert('Impossible d\'envoyer la commande à JOSM. Est-il lancé et le contrôle à distance activé ?');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function displayPointsFromApi(points, convert_to_osm_json) {
|
function displayPointsFromApi(points, convert_to_osm_json) {
|
||||||
if (points && convert_to_osm_json) {
|
if (points && convert_to_osm_json) {
|
||||||
geojsondata = osmtogeojson(points);
|
geojsondata = osmtogeojson(points);
|
||||||
|
@ -306,7 +324,7 @@ function displayPointsFromApi(points, convert_to_osm_json) {
|
||||||
|
|
||||||
let resultLayer = L.geoJson(geojsondata, {
|
let resultLayer = L.geoJson(geojsondata, {
|
||||||
style: function (feature) {
|
style: function (feature) {
|
||||||
return {color: '#f00'};
|
return { color: '#f00' };
|
||||||
},
|
},
|
||||||
filter: function (feature, layer) {
|
filter: function (feature, layer) {
|
||||||
let isPolygon = (feature.geometry) && (feature.geometry.type !== undefined) && (feature.geometry.type === 'Polygon');
|
let isPolygon = (feature.geometry) && (feature.geometry.type !== undefined) && (feature.geometry.type === 'Polygon');
|
||||||
|
@ -475,8 +493,7 @@ function eachFeature(feature, layer) {
|
||||||
circle_alert.on({
|
circle_alert.on({
|
||||||
mouseover: function () {
|
mouseover: function () {
|
||||||
this.openPopup();
|
this.openPopup();
|
||||||
bindEventsOnJosmRemote();
|
bindEventsOnJosmRemote(this.getPopup().getElement());
|
||||||
updateExternalEditorsLinks();
|
|
||||||
bindFullDetails(feature);
|
bindFullDetails(feature);
|
||||||
},
|
},
|
||||||
mouseout: function () {
|
mouseout: function () {
|
||||||
|
@ -484,8 +501,7 @@ function eachFeature(feature, layer) {
|
||||||
},
|
},
|
||||||
click: function () {
|
click: function () {
|
||||||
this.openPopup();
|
this.openPopup();
|
||||||
bindEventsOnJosmRemote();
|
bindEventsOnJosmRemote(this.getPopup().getElement());
|
||||||
updateExternalEditorsLinks();
|
|
||||||
bindFullDetails(feature);
|
bindFullDetails(feature);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -519,7 +535,7 @@ function eachFeature(feature, layer) {
|
||||||
circle.on({
|
circle.on({
|
||||||
mouseover: function () {
|
mouseover: function () {
|
||||||
this.openPopup();
|
this.openPopup();
|
||||||
bindEventsOnJosmRemote();
|
bindEventsOnJosmRemote(this.getPopup().getElement());
|
||||||
bindFullDetails(feature);
|
bindFullDetails(feature);
|
||||||
},
|
},
|
||||||
mouseout: function () {
|
mouseout: function () {
|
||||||
|
@ -527,7 +543,7 @@ function eachFeature(feature, layer) {
|
||||||
},
|
},
|
||||||
click: function () {
|
click: function () {
|
||||||
this.openPopup();
|
this.openPopup();
|
||||||
bindEventsOnJosmRemote();
|
bindEventsOnJosmRemote(this.getPopup().getElement());
|
||||||
bindFullDetails(feature);
|
bindFullDetails(feature);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -543,12 +559,12 @@ function bindFullDetails(feature) {
|
||||||
let content = '<table>' +
|
let content = '<table>' +
|
||||||
'<tbody>' + ''
|
'<tbody>' + ''
|
||||||
|
|
||||||
let ii=0
|
let ii = 0
|
||||||
let keys = Object.keys(feature.properties.tags)
|
let keys = Object.keys(feature.properties.tags)
|
||||||
keys.forEach( (elem, val) => {
|
keys.forEach((elem, val) => {
|
||||||
console.log('elem, val', elem, val)
|
console.log('elem, val', elem, val)
|
||||||
content += '<tr><td>'+elem+'</td><td>'+feature.properties.tags[elem]+'</td></tr>';
|
content += '<tr><td>' + elem + '</td><td>' + feature.properties.tags[elem] + '</td></tr>';
|
||||||
ii++;
|
ii++;
|
||||||
})
|
})
|
||||||
content += '</tbody>' +
|
content += '</tbody>' +
|
||||||
'</table>'
|
'</table>'
|
||||||
|
@ -660,6 +676,16 @@ function onMapMoveEnd() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ajout d'un log pour déboguer
|
||||||
|
console.log("Zoom actuel:", map.getZoom());
|
||||||
|
|
||||||
|
if (map.getZoom() > 12) {
|
||||||
|
console.log("Recherche des issues Osmose...");
|
||||||
|
searchOsmoseIssues(map);
|
||||||
|
} else {
|
||||||
|
console.log("Zoom trop faible pour les issues Osmose");
|
||||||
|
osmose_markers.clearLayers();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setCoordinatesOfLeafletMapFromQueryParameters()
|
setCoordinatesOfLeafletMapFromQueryParameters()
|
||||||
|
@ -784,12 +810,10 @@ function searchFoodPlaces(map) {
|
||||||
const query = `
|
const query = `
|
||||||
[out:json][timeout:25];
|
[out:json][timeout:25];
|
||||||
(
|
(
|
||||||
node["amenity"="restaurant"](${bbox});
|
nwr["amenity"="restaurant"](${bbox});
|
||||||
node["amenity"="cafe"](${bbox});
|
nwr["amenity"="cafe"](${bbox});
|
||||||
);
|
);
|
||||||
out body;
|
out center;`;
|
||||||
>;
|
|
||||||
out skel qt;`;
|
|
||||||
|
|
||||||
const url = `https://overpass-api.de/api/interpreter?data=${encodeURIComponent(query)}`;
|
const url = `https://overpass-api.de/api/interpreter?data=${encodeURIComponent(query)}`;
|
||||||
|
|
||||||
|
@ -798,21 +822,21 @@ function searchFoodPlaces(map) {
|
||||||
fetch(url)
|
fetch(url)
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const geojson = osmtogeojson(data);
|
data.elements.forEach(element => {
|
||||||
geojson.features.forEach(feature => {
|
// Utiliser les coordonnées du centre pour les ways et relations
|
||||||
const coords = feature.geometry.coordinates;
|
const lat = element.lat || element.center.lat;
|
||||||
const properties = feature.properties;
|
const lon = element.lon || element.center.lon;
|
||||||
const name = properties.tags.name || 'Sans nom';
|
const name = element.tags.name || 'Sans nom';
|
||||||
const type = properties.tags.amenity;
|
const type = element.tags.amenity;
|
||||||
|
|
||||||
const marker = L.marker([coords[1], coords[0]], {
|
const marker = L.marker([lat, lon], {
|
||||||
icon: foodIcon
|
icon: foodIcon
|
||||||
});
|
});
|
||||||
|
|
||||||
marker.bindPopup(`
|
marker.bindPopup(`
|
||||||
<strong>${name}</strong><br>
|
<strong>${name}</strong><br>
|
||||||
Type: ${type}<br>
|
Type: ${type}<br>
|
||||||
${properties.tags.cuisine ? 'Cuisine: ' + properties.tags.cuisine : ''}
|
${element.tags.cuisine ? 'Cuisine: ' + element.tags.cuisine : ''}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
food_places_markers.addLayer(marker);
|
food_places_markers.addLayer(marker);
|
||||||
|
@ -821,16 +845,150 @@ function searchFoodPlaces(map) {
|
||||||
.catch(error => console.error('Erreur lors de la recherche des restaurants:', error));
|
.catch(error => console.error('Erreur lors de la recherche des restaurants:', error));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modifier la fonction init pour ajouter le contrôle des couches
|
// Ajouter après la déclaration des autres variables globales
|
||||||
|
let osmose_markers = L.layerGroup();
|
||||||
|
const osmoseIcon = L.divIcon({
|
||||||
|
className: 'osmose-marker-drop',
|
||||||
|
html: '<div class="osmose-marker-inner">⚡</div>',
|
||||||
|
iconSize: [30, 40],
|
||||||
|
iconAnchor: [15, 40]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Ajouter cette nouvelle fonction
|
||||||
|
function searchOsmoseIssues(map) {
|
||||||
|
const bounds = map.getBounds();
|
||||||
|
const zoom = map.getZoom();
|
||||||
|
// Construction de la bbox avec l'ordre correct : ouest,sud,est,nord
|
||||||
|
const bbox = `${bounds.getWest()}%2C${bounds.getSouth()}%2C${bounds.getEast()}%2C${bounds.getNorth()}`;
|
||||||
|
|
||||||
|
// URL formatée selon l'exemple fourni
|
||||||
|
const url = `https://osmose.openstreetmap.fr/api/0.3/issues?zoom=${zoom}&item=8410%2C8411&level=1%2C2%2C3&limit=500&bbox=${bbox}`;
|
||||||
|
|
||||||
|
console.log("Recherche des issues Osmose (liste) avec l'URL :", url);
|
||||||
|
osmose_markers.clearLayers();
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
return response.text().then(text => { throw new Error(`Erreur HTTP ${response.status}: ${response.statusText}. Réponse : ${text}`); });
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(data => {
|
||||||
|
if (!data || !Array.isArray(data.issues)) {
|
||||||
|
console.warn("Réponse Osmose (liste) inattendue ou pas d'issues:", data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const issuesList = data.issues;
|
||||||
|
console.log(`Nombre d'issues Osmose (liste) trouvées: ${issuesList.length}`);
|
||||||
|
|
||||||
|
issuesList.forEach(issueInfo => {
|
||||||
|
// Vérifier si les coordonnées sont valides
|
||||||
|
if (issueInfo.lat == null || issueInfo.lon == null) {
|
||||||
|
console.warn("Issue Osmose sans coordonnées ignorée:", issueInfo);
|
||||||
|
return; // Ignorer cette issue
|
||||||
|
}
|
||||||
|
|
||||||
|
const lat = parseFloat(issueInfo.lat);
|
||||||
|
const lon = parseFloat(issueInfo.lon);
|
||||||
|
const issueId = issueInfo.id; // C'est l'UUID
|
||||||
|
|
||||||
|
// Vérifier si l'UUID est valide
|
||||||
|
if (!issueId) {
|
||||||
|
console.warn("Issue Osmose sans ID (UUID) ignorée:", issueInfo);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const osmoseMarker = L.circle([lat, lon], {
|
||||||
|
color: "purple",
|
||||||
|
fillColor: "purple",
|
||||||
|
fillOpacity: 0.8,
|
||||||
|
radius: 10,
|
||||||
|
className: 'leaflet-osmose-layer',
|
||||||
|
pane: 'markerPane',
|
||||||
|
issueId: issueId
|
||||||
|
});
|
||||||
|
|
||||||
|
// Préparer une popup de chargement simple
|
||||||
|
osmoseMarker.bindPopup("Chargement des détails...");
|
||||||
|
|
||||||
|
osmoseMarker.on('click', function (e) {
|
||||||
|
const clickedMarker = e.target;
|
||||||
|
const storedIssueId = clickedMarker.options.issueId;
|
||||||
|
|
||||||
|
// Afficher immédiatement la popup de chargement
|
||||||
|
clickedMarker.openPopup();
|
||||||
|
|
||||||
|
const detailUrl = `https://osmose.openstreetmap.fr/api/0.3/issue/${storedIssueId}?langs=auto`;
|
||||||
|
console.log("Récupération des détails pour l'issue:", detailUrl);
|
||||||
|
|
||||||
|
fetch(detailUrl)
|
||||||
|
.then(response => {
|
||||||
|
if (!response.ok) {
|
||||||
|
return response.text().then(text => { throw new Error(`Erreur HTTP ${response.status}: ${response.statusText}. Réponse : ${text}`); });
|
||||||
|
}
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(issueDetails => {
|
||||||
|
// Construire le contenu de la popup avec les détails
|
||||||
|
let popupContent = `<strong>${issueDetails.title?.auto || 'Titre non disponible'}</strong><br>`;
|
||||||
|
if (issueDetails.subtitle?.auto) {
|
||||||
|
popupContent += `<p>${issueDetails.subtitle.auto}</p>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let proposedTags = '';
|
||||||
|
if (issueDetails.new_elems && issueDetails.new_elems[0] && issueDetails.new_elems[0].add) {
|
||||||
|
proposedTags = '<table class="proposed-tags">';
|
||||||
|
issueDetails.new_elems[0].add.forEach(tag => {
|
||||||
|
proposedTags += `<tr><td>${tag.k}</td><td>${tag.v}</td></tr>`;
|
||||||
|
});
|
||||||
|
proposedTags += '</table>';
|
||||||
|
popupContent += `<div class="proposed-tags-container"><h4>Tags proposés :</h4>${proposedTags}</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construire le lien JOSM /import
|
||||||
|
const josmFixUrl = `http://localhost:8111/import?url=https://osmose.openstreetmap.fr/api/0.3/issue/${storedIssueId}/fix/0`;
|
||||||
|
|
||||||
|
popupContent += `
|
||||||
|
<div class="action-buttons">
|
||||||
|
<a class="edit-button josm" data-href="${josmFixUrl}" href="#" title="Ouvre JOSM et charge la correction proposée">⚡ Réparer dans JOSM</a>
|
||||||
|
<a href="https://osmose.openstreetmap.fr/fr/issue/${storedIssueId}" target="_blank" title="Voir les détails de l'alerte sur le site Osmose">Voir sur Osmose</a>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
// Mettre à jour le contenu de la popup et s'assurer qu'elle est ouverte
|
||||||
|
clickedMarker.setPopupContent(popupContent);
|
||||||
|
clickedMarker.openPopup(); // Rouvrir pour ajuster la taille si nécessaire
|
||||||
|
|
||||||
|
// Lier l'événement au bouton JOSM DANS la popup
|
||||||
|
bindEventsOnJosmRemote(clickedMarker.getPopup().getElement());
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error("Erreur lors de la récupération des détails de l'issue Osmose:", error);
|
||||||
|
clickedMarker.setPopupContent(`Erreur lors du chargement des détails.<br><a href="https://osmose.openstreetmap.fr/fr/issue/${storedIssueId}" target="_blank">Voir sur Osmose</a>`);
|
||||||
|
clickedMarker.openPopup();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
osmose_markers.addLayer(osmoseMarker);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Erreur détaillée lors de la recherche de la liste des issues Osmose:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modifier la fonction init pour ajouter le nouveau calque
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
food_places_markers.addTo(map);
|
food_places_markers.addTo(map);
|
||||||
$('#found_charging_stations').hide();
|
$('#found_charging_stations').hide();
|
||||||
|
|
||||||
// Ajouter le contrôle des couches
|
// Mettre à jour le contrôle des calques
|
||||||
const overlayMaps = {
|
const overlayMaps = {
|
||||||
"Stations de recharge": all_stations_markers,
|
"Stations de recharge": all_stations_markers,
|
||||||
"Restaurants et cafés": food_places_markers
|
"Restaurants et cafés": food_places_markers,
|
||||||
|
"Bornes potentielles (Osmose)": osmose_markers
|
||||||
};
|
};
|
||||||
|
|
||||||
L.control.layers(null, overlayMaps).addTo(map);
|
L.control.layers(null, overlayMaps).addTo(map);
|
||||||
|
@ -851,23 +1009,25 @@ function init() {
|
||||||
console.log('Données envoyées à JOSM avec succès !');
|
console.log('Données envoyées à JOSM avec succès !');
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
alert('Erreur : JOSM doit être ouvert avec l\'option "Contrôle à distance" activée');
|
alert('Erreur : JOSM doit être ouvert avec l\'option de télécommande "Contrôle à distance" activée dans ses paramètres (accédez-y avec F12)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#searchButton').on('click', searchLocation);
|
$('#searchButton').on('click', searchLocation);
|
||||||
$('#shareUrl').on('click', copyCurrentUrl);
|
$('#shareUrl').on('click', copyCurrentUrl);
|
||||||
|
|
||||||
|
|
||||||
$('#searchResults').on('change', function() {
|
$('#searchResults').on('change', function () {
|
||||||
const selectedIndex = $(this).val();
|
const selectedIndex = $(this).val();
|
||||||
if (selectedIndex !== null) {
|
if (selectedIndex !== null) {
|
||||||
const selectedPlace = $(this).find('option:selected').data('place');
|
const selectedPlace = $(this).find('option:selected').data('place');
|
||||||
moveToLocation(selectedPlace);
|
moveToLocation(selectedPlace);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById('searchButton').addEventListener('click', searchLocation);
|
document.getElementById('searchButton').addEventListener('click', searchLocation);
|
||||||
|
|
||||||
|
osmose_markers.addTo(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -882,52 +1042,56 @@ function copyCurrentUrl() {
|
||||||
document.execCommand('copy');
|
document.execCommand('copy');
|
||||||
document.body.removeChild(dummy);
|
document.body.removeChild(dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function searchLocation() {
|
|
||||||
const location = $('#searchLocation').val();
|
|
||||||
if (!location) {
|
|
||||||
alert('Veuillez entrer un lieu à rechercher.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(location)}`;
|
|
||||||
|
|
||||||
fetch(url)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
const resultsDropdown = $('#searchResults');
|
|
||||||
resultsDropdown.empty(); // Clear previous results
|
|
||||||
|
|
||||||
if (data.length === 0) {
|
|
||||||
alert('Lieu non trouvé. Veuillez essayer un autre terme de recherche.');
|
|
||||||
resultsDropdown.hide();
|
|
||||||
} else if (data.length === 1) {
|
|
||||||
const place = data[0];
|
|
||||||
moveToLocation(place);
|
|
||||||
resultsDropdown.hide();
|
|
||||||
} else {
|
|
||||||
data.forEach((place, index) => {
|
|
||||||
const option = $('<option></option>')
|
|
||||||
.val(index)
|
|
||||||
.text(`${place.display_name} (${place.lat}, ${place.lon})`);
|
|
||||||
resultsDropdown.append(option);
|
|
||||||
});
|
|
||||||
resultsDropdown.show();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Erreur lors de la recherche du lieu :', error);
|
|
||||||
alert('Erreur lors de la recherche du lieu.');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveToLocation(place) {
|
|
||||||
const lat = parseFloat(place.lat);
|
|
||||||
const lon = parseFloat(place.lon);
|
|
||||||
map.setView([lat, lon], 13); // Ajustez le niveau de zoom selon vos besoins
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
init()
|
|
||||||
|
function searchLocation() {
|
||||||
|
const location = $('#searchLocation').val();
|
||||||
|
if (!location) {
|
||||||
|
alert('Veuillez entrer un lieu à rechercher.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(location)}`;
|
||||||
|
|
||||||
|
fetch(url)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
const resultsDropdown = $('#searchResults');
|
||||||
|
resultsDropdown.empty(); // Clear previous results
|
||||||
|
|
||||||
|
if (data.length === 0) {
|
||||||
|
alert('Lieu non trouvé. Veuillez essayer un autre terme de recherche.');
|
||||||
|
resultsDropdown.hide();
|
||||||
|
} else if (data.length === 1) {
|
||||||
|
const place = data[0];
|
||||||
|
moveToLocation(place);
|
||||||
|
resultsDropdown.hide();
|
||||||
|
} else {
|
||||||
|
data.forEach((place, index) => {
|
||||||
|
const option = $('<option></option>')
|
||||||
|
.val(index)
|
||||||
|
.text(`${place.display_name} (${place.lat}, ${place.lon})`);
|
||||||
|
resultsDropdown.append(option);
|
||||||
|
});
|
||||||
|
resultsDropdown.show();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Erreur lors de la recherche du lieu :', error);
|
||||||
|
alert('Erreur lors de la recherche du lieu.');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveToLocation(place) {
|
||||||
|
const lat = parseFloat(place.lat);
|
||||||
|
const lon = parseFloat(place.lon);
|
||||||
|
map.setView([lat, lon], 13); // Ajustez le niveau de zoom selon vos besoins
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
init()
|
||||||
|
|
||||||
|
// Créer un nouveau pane pour les marqueurs Osmose avec un zIndex plus élevé
|
||||||
|
map.createPane('osmosePane');
|
||||||
|
map.getPane('osmosePane').style.zIndex = 1000;
|
|
@ -31,7 +31,7 @@ const lcm_utils = {
|
||||||
if (value && tag.toLowerCase().indexOf('output') !== -1) {
|
if (value && tag.toLowerCase().indexOf('output') !== -1) {
|
||||||
value = '' + value
|
value = '' + value
|
||||||
if (value.indexOf(';') !== -1) {
|
if (value.indexOf(';') !== -1) {
|
||||||
console.log('value output multiple', value)
|
// console.log('value output multiple', value)
|
||||||
let explode = value.split(';')
|
let explode = value.split(';')
|
||||||
explode.forEach(elem => {
|
explode.forEach(elem => {
|
||||||
if (value.replace) {
|
if (value.replace) {
|
||||||
|
@ -56,7 +56,7 @@ const lcm_utils = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
feature.properties.outputPower = outputPower
|
feature.properties.outputPower = outputPower
|
||||||
return outputPower
|
return outputPower
|
||||||
},
|
},
|
||||||
|
@ -65,26 +65,26 @@ const lcm_utils = {
|
||||||
* villes les plus peuplées de France
|
* villes les plus peuplées de France
|
||||||
*/
|
*/
|
||||||
cities: [
|
cities: [
|
||||||
{name: 'Paris', coords: [48.8566, 2.3522]},
|
{ name: 'Paris', coords: [48.8566, 2.3522] },
|
||||||
{name: 'Marseille', coords: [43.2965, 5.3698]},
|
{ name: 'Marseille', coords: [43.2965, 5.3698] },
|
||||||
{name: 'Lyon', coords: [45.7640, 4.8357]},
|
{ name: 'Lyon', coords: [45.7640, 4.8357] },
|
||||||
{name: 'Toulouse', coords: [43.6042, 1.4437]},
|
{ name: 'Toulouse', coords: [43.6042, 1.4437] },
|
||||||
{name: 'Nice', coords: [43.7101, 7.2620]},
|
{ name: 'Nice', coords: [43.7101, 7.2620] },
|
||||||
{name: 'Nantes', coords: [47.2184, -1.5536]},
|
{ name: 'Nantes', coords: [47.2184, -1.5536] },
|
||||||
{name: 'Strasbourg', coords: [48.5831, 7.7521]},
|
{ name: 'Strasbourg', coords: [48.5831, 7.7521] },
|
||||||
{name: 'Montpellier', coords: [43.6167, 3.8742]},
|
{ name: 'Montpellier', coords: [43.6167, 3.8742] },
|
||||||
{name: 'Bordeaux', coords: [44.8378, -0.5792]},
|
{ name: 'Bordeaux', coords: [44.8378, -0.5792] },
|
||||||
{name: 'Lille', coords: [50.6293, 3.1466]},
|
{ name: 'Lille', coords: [50.6293, 3.1466] },
|
||||||
{name: 'Rennes', coords: [48.1120, -1.6823]},
|
{ name: 'Rennes', coords: [48.1120, -1.6823] },
|
||||||
{name: 'Toulon', coords: [43.1230, 5.9291]},
|
{ name: 'Toulon', coords: [43.1230, 5.9291] },
|
||||||
{name: 'Le Havre', coords: [49.4943, 0.1079]},
|
{ name: 'Le Havre', coords: [49.4943, 0.1079] },
|
||||||
{name: 'Saint-Etienne', coords: [45.4380, 4.3841]},
|
{ name: 'Saint-Etienne', coords: [45.4380, 4.3841] },
|
||||||
{name: 'Grenoble', coords: [45.1667, 5.7295]},
|
{ name: 'Grenoble', coords: [45.1667, 5.7295] },
|
||||||
{name: 'Rouen', coords: [49.4431, 1.0820]},
|
{ name: 'Rouen', coords: [49.4431, 1.0820] },
|
||||||
{name: 'Dijon', coords: [47.3221, 5.0446]},
|
{ name: 'Dijon', coords: [47.3221, 5.0446] },
|
||||||
{name: 'Angers', coords: [47.4786, -0.5551]},
|
{ name: 'Angers', coords: [47.4786, -0.5551] },
|
||||||
{name: 'Nîmes', coords: [43.8366, 4.3623]},
|
{ name: 'Nîmes', coords: [43.8366, 4.3623] },
|
||||||
{name: 'Reims', coords: [49.2500, 4.0333]}
|
{ name: 'Reims', coords: [49.2500, 4.0333] }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
export default lcm_utils
|
export default lcm_utils
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
sass styles/main.scss styles/style.css
|
sass styles/main.scss styles/style.css --style compressed
|
||||||
|
|
8
styles/main.css
Normal file
8
styles/main.css
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.leaflet-osmose-layer {
|
||||||
|
z-index: 1000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.leaflet-marker-icon.osmose-marker-drop,
|
||||||
|
.leaflet-marker-shadow.osmose-marker-drop {
|
||||||
|
z-index: 1000 !important;
|
||||||
|
}
|
140
styles/main.scss
140
styles/main.scss
|
@ -130,7 +130,10 @@ img.leaflet-marker-icon.tag-socket\:type2_yes {
|
||||||
border-width: 3px;
|
border-width: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.rounded-button, .navigation-link, .panoramax-link, .edit-button {
|
.rounded-button,
|
||||||
|
.navigation-link,
|
||||||
|
.panoramax-link,
|
||||||
|
.edit-button {
|
||||||
background: var(--button-background);
|
background: var(--button-background);
|
||||||
padding: 0.5em 1em;
|
padding: 0.5em 1em;
|
||||||
border-radius: 2em;
|
border-radius: 2em;
|
||||||
|
@ -318,23 +321,28 @@ marqueurs
|
||||||
background: #36423d;
|
background: #36423d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-power-lesser-than-50, .map-marker-circle-demo.color-2 {
|
.color-power-lesser-than-50,
|
||||||
|
.map-marker-circle-demo.color-2 {
|
||||||
background: #4e8a8d;
|
background: #4e8a8d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-power-lesser-than-100, .map-marker-circle-demo.color-3 {
|
.color-power-lesser-than-100,
|
||||||
|
.map-marker-circle-demo.color-3 {
|
||||||
background: #2999b3;
|
background: #2999b3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-power-lesser-than-200, .map-marker-circle-demo.color-4 {
|
.color-power-lesser-than-200,
|
||||||
|
.map-marker-circle-demo.color-4 {
|
||||||
background: #1782dd;
|
background: #1782dd;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-power-lesser-than-300, .map-marker-circle-demo.color-5 {
|
.color-power-lesser-than-300,
|
||||||
|
.map-marker-circle-demo.color-5 {
|
||||||
background: #2900ff;
|
background: #2900ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-power-lesser-than-max, .map-marker-circle-demo.color-6 {
|
.color-power-lesser-than-max,
|
||||||
|
.map-marker-circle-demo.color-6 {
|
||||||
background: #8000ff;
|
background: #8000ff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +401,7 @@ button {
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
button + button {
|
button+button {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,6 +620,119 @@ header {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.leaflet-popup-content {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.osmose-marker {
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 20px;
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2px solid #ff6b6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.osmose-marker-drop {
|
||||||
|
position: relative;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.osmose-marker-inner {
|
||||||
|
position: absolute;
|
||||||
|
width: 30px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: #8B00FF;
|
||||||
|
border-radius: 50% 50% 50% 0;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
box-shadow: 0 0 5px rgba(0, 0, 0, 0.3);
|
||||||
|
border: 2px solid white;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '⚡';
|
||||||
|
transform: rotate(45deg);
|
||||||
|
color: white;
|
||||||
|
font-size: 16px;
|
||||||
|
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
padding-left: 1ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Animation au survol plus visible */
|
||||||
|
|
||||||
|
.osmose-marker-drop:hover .osmose-marker-inner {
|
||||||
|
animation: bounce 0.5s ease infinite;
|
||||||
|
background-color: #9F2BFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposed-tags-container {
|
||||||
|
max-height: 200px;
|
||||||
|
overflow-y: auto;
|
||||||
|
margin: 10px 0;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposed-tags {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposed-tags tr:nth-child(even) {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposed-tags td {
|
||||||
|
padding: 2px 5px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.proposed-tags td:first-child {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons {
|
||||||
|
margin-top: 10px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons a {
|
||||||
|
padding: 5px 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons .edit-button.josm {
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-buttons a:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes bounce {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: rotate(-45deg) translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
transform: rotate(-45deg) translateY(-5px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
overrides leaflet
|
overrides leaflet
|
||||||
*/
|
*/
|
||||||
|
@ -648,7 +769,8 @@ overrides leaflet
|
||||||
transform: none;
|
transform: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.side-panel-open #map, #map {
|
.side-panel-open #map,
|
||||||
|
#map {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -691,4 +813,4 @@ overrides leaflet
|
||||||
100% {
|
100% {
|
||||||
border-left-color: #ff0000;
|
border-left-color: #ff0000;
|
||||||
}
|
}
|
||||||
}
|
}
|
644
styles/style.css
644
styles/style.css
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
{"version":3,"sourceRoot":"","sources":["main.scss"],"names":[],"mappings":"AAAA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;EACA;EACA;;;AAGF;EAOE;;AANA;EACE;EACA;EACA;;;AAMJ;EACE;;;AAGF;EACE;IACE;;EAGF;IACE;;;AAIJ;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAIF;EACE;EACA;EACA;;AAEA;EACE;;;AAIJ;AAAA;AAAA;AAIA;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EACE;;;AAIJ;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAIA;EACE;EACA;EACA;EACA;;AAGF;EACE;EACA;EACA;;;AAIJ;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;;;AAIJ;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;AAEA;EACE;EACA;;;AAIJ;EACE;;;AAKA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;AAEF;EACE;;AAIA;EACE;EACA;;;AAKN;AAAA;AAAA;AAIA;EACE;;;AAGF;AACA;EACE;IACE;IACA;;EAGF;IACE;IACA;;EAGF;AACE;;EAGF;IACE;IACA;IACA;IACA;IACA;;EAGF;IACE;;EAGF;IACE;IACA;IACA;IACA;IACA;IACA;;EAIF;IACE;;;AAIJ;EACE;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE;;EAGF;IACE","file":"style.css"}
|
{"version":3,"sourceRoot":"","sources":["main.scss"],"names":[],"mappings":"CAAA,MACE,yBACA,mBACA,yBACA,8BACA,6BACA,mCACA,2BACA,mBACA,0BACA,oDACA,+BACA,uCACA,6BACA,iCACA,0BAGF,EACE,sBAGF,KACE,YACA,WACA,mCACA,UACA,SAGF,KACE,YACA,WACA,mCACA,UACA,SACA,UACA,SAGF,KACE,+CACA,eAGF,EACE,+CACA,eACA,eAGF,KACE,YACA,WACA,SACA,iBAME,YACE,6BAKJ,0BACE,mBAKJ,QACE,aAGF,SACE,gBACA,wBACA,cACA,YACA,WACA,iBAGF,MACE,wBACA,yBACA,qBACA,kBACA,kCACA,mBACA,eACA,mBACA,WACA,gCAGF,OACE,iBACA,mBAGF,GACE,mBAGF,uBACE,eACA,YACA,SACA,aACA,+BACA,SACA,WAEA,yBACE,eAIJ,8BACE,6BAGF,8CACE,4BACA,qBACA,iBAGF,8DAIE,oCACA,iBACA,kBACA,sBACA,sCACA,YAGF,gBACE,SACA,kBACA,WAEA,oBACE,WACA,YAIJ,mBACE,eACA,mBAGF,iBACE,gBACA,oBACA,WACA,kBACA,QACA,cAEA,uBACE,YACA,mBAIJ,aACE,0CACA,yBACA,eAGF,aAOE,gBANA,mBACE,0CACA,yBACA,eAMJ,WACE,WAGF,gBACE,GACE,uBAGF,KACE,0BAIJ,EACE,wBAGF,wBACE,aACA,mCAGF,eACE,eACA,MACA,OACA,WACA,gBACA,eAEA,mBACE,eACA,UACA,WACA,gBACA,mBACA,WACA,YACA,kCAIJ,QACE,eACA,cAGF,uBACE,gBACA,qBACA,qBAGF,eACE,WACA,cACA,cACA,gBACA,gBACA,gBACA,iBAGF,WACE,UACA,qBAGF,aACE,UACA,iBACA,qBACA,mBAGF,gBACE,oBAGF,MACE,WAGF,kBACE,aACA,mBACA,cACA,kBACA,UACA,WACA,2BACA,YACA,eACA,eACA,YAIF,SACE,4CACA,iBACA,gBAEA,WACE,gCAQJ,aACE,kBAGF,wBACE,mBACA,qBACA,WACA,YACA,gBAGF,eACE,8CAGF,gCACE,mBAGF,4DAEE,mBAGF,6DAEE,mBAGF,6DAEE,mBAGF,6DAEE,mBAGF,6DAEE,mBAGF,yBACE,gBAGF,OACE,eACA,cACA,gBAGF,YACE,cACA,YAGF,KACE,WACA,iBACA,oCACA,WAGF,YACE,gBACA,cACA,WACA,cAGF,UACE,WACA,YACA,UAGF,cACE,kBAGF,gBACE,mBACA,gBACA,qBACA,mBACA,eAGF,qBACE,sBAGF,aACE,eAGF,cACE,iBAGF,qBACE,kBACA,qBAEA,2BACE,kBACA,YACA,UACA,SACA,eAGF,6CACE,iBACA,WAGF,6CACE,kBACA,YAGF,iDACE,6BACA,aAGF,uCACE,gBAGF,uCACE,YAGF,2CACE,aAIJ,+BACE,wBAGF,oBACE,gBAGF,YACE,eACA,eACA,OACA,MACA,WACA,YACA,gBACA,qCACA,gBACA,kBACA,qBACA,aACA,kBACA,WACA,WAGF,iBACE,eACA,SACA,WACA,WACA,gBACA,kBACA,kBACA,oCAGF,OACE,kBACA,WAIA,6BACE,mBACA,WACA,4BACA,YAGF,sBACE,mBACA,YACA,aAIJ,aACE,WAGF,aACE,eACA,YACA,SACA,2BACA,0CACA,kBACA,kBACA,oCACA,kBACA,WACA,iDACA,4CAGF,OACE,gBACA,eACA,WAEA,UACE,YACA,iBAGF,WACE,WACA,kBAIJ,KACE,UACA,YAGF,iBACE,iBAGF,gBACE,oBACA,mBACA,uBACA,eACA,eACA,gCAEA,sBACE,yBAIJ,cACE,WACA,aACA,mBACA,sCACA,kBAGF,qBACE,eACA,YACA,WACA,WACA,gBACA,aACA,kBAGF,eACE,kBAGF,aACE,gBACA,aACA,WAEA,6BACE,kBACA,mBAIJ,cACE,kBAKA,SACE,mBACA,mBACA,YACA,UACA,gBACA,qBACA,kBAGF,eACE,UAIA,qBACE,UACA,mCAKN,uBACE,iBACA,cAGF,eACE,eACA,kBACA,iBACA,oCACA,kBACA,yBAGF,oBACE,kBACA,aAGF,qBACE,kBACA,WACA,YACA,yBACA,4BACA,yBACA,aACA,mBACA,uBACA,kCACA,sBAEA,6BACE,YACA,wBACA,WACA,eACA,uCACA,iBAMJ,+CACE,mCACA,yBAGF,yBACE,iBACA,gBACA,cACA,YACA,yBACA,kBAGF,eACE,WACA,yBAGF,kCACE,sBAGF,kBACE,gBACA,eAGF,8BACE,iBACA,WAGF,gBACE,gBACA,aACA,sBACA,QAGF,kBACE,iBACA,qBACA,kBACA,kBAGF,kCACE,yBACA,WAGF,wBACE,WAIF,kBAEE,QAEE,uCAGF,IACE,2CAQJ,+BACE,iBAIF,0BACE,UACE,YACA,iBAGF,iBACE,WACA,WAOF,6BACE,gBACA,eACA,qCACA,gBACA,YAGF,mBACE,eAGF,2BAEE,SACA,OACA,MACA,YACA,YACA,YAIF,OACE,iBAIJ,0BACE,GACE,sBAGF,IACE,0BAGF,IACE,uBAGF,IACE,uBAGF,IACE,uBAGF,IACE,0BAGF,KACE","file":"style.css"}
|
Loading…
Add table
Add a link
Reference in a new issue