list notes

This commit is contained in:
Tykayn 2025-06-01 23:35:15 +02:00 committed by tykayn
parent 0f5ff6ed45
commit cb90be8ff2
10 changed files with 119 additions and 36 deletions

View file

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250601212218 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE place ADD note_content VARCHAR(255) DEFAULT NULL
SQL);
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE place DROP note_content
SQL);
}
}

View file

@ -78,6 +78,19 @@ final class AdminController extends AbstractController
]);
}
#[Route('/admin/placeType/{osm_kind}/{osm_id}', name: 'app_admin_by_osm_id')]
public function placeType(string $osm_kind, string $osm_id): Response
{
$place = $this->entityManager->getRepository(Place::class)->findOneBy(['osm_kind' => $osm_kind, 'osmId' => $osm_id]);
if($place) {
return $this->redirectToRoute('app_admin_commerce', ['id' => $place->getId()]);
} else {
$this->addFlash('error', 'Le lieu n\'existe pas.');
return $this->redirectToRoute('app_public_index');
}
}
#[Route('/admin/commerce/{id}', name: 'app_admin_commerce')]
public function commerce(int $id): Response
{
@ -221,7 +234,8 @@ final class AdminController extends AbstractController
->setHasAddress(($result['tags'] && isset($result['tags']['address']) || $result['tags'] && isset($result['tags']['contact:address'])) ? isset($result['tags']['address']) : null)
->setHasWebsite($result['tags'] && isset($result['tags']['website']) ? $result['tags']['website'] : null)
->setHasWheelchair($result['tags'] && isset($result['tags']['wheelchair']) ? $result['tags']['wheelchair'] : null)
->setHasNote($result['tags'] && isset($result['tags']['note']) ? $result['tags']['note'] : null)
->setHasNote($result['tags'] && isset($result['tags']['note']) ? $result['tags']['note'] : null)
->setNoteContent($result['tags'] && isset($result['tags']['note']) ? $result['tags']['note'] : null)
;
$this->entityManager->persist($commerce);
}

View file

@ -152,6 +152,7 @@ class PublicController extends AbstractController
'commerce_overpass' => $commerce_overpass,
'name' => $name,
'commerce' => $place,
'zone' => $zipcode,
'completion_percentage' => $place->getCompletionPercentage(),
'hide_filled_inputs' => $this->hide_filled_inputs,
'excluded_tags_to_render' => $this->motocultrice->excluded_tags_to_render,
@ -416,7 +417,8 @@ class PublicController extends AbstractController
#[Route('/places_with_note', name: 'app_public_places_with_note')]
public function places_with_note(): Response
{
$places = $this->entityManager->getRepository(Place::class)->findBy(['note' => '']);
// Récupérer tous les commerces ayant une note
$places = $this->entityManager->getRepository(Place::class)->findBy(['has_note' => true]);
return $this->render('public/places_with_note.html.twig', [
'controller_name' => 'PublicController',
'places' => $places

View file

@ -49,7 +49,7 @@ class HistoryFixtures extends Fixture
// Créer des statistiques de test
for ($i = 0; $i < 3; $i++) {
$stat = new Stats();
$stat->setZone($faker->city . ' (mock)')
$stat->setZone($faker->numberBetween(10000, 99999) )
->setCompletionPercent($faker->numberBetween(0, 100))
->addPlace( $faker->randomElement($places_list))
->addPlace( $faker->randomElement($places_list))

View file

@ -79,6 +79,9 @@ class Place
#[ORM\Column(nullable: true)]
private ?string $main_tag = null;
#[ORM\Column(length: 255, nullable: true)]
private ?string $note_content = null;
public function getMainTag(): ?string
{
return $this->main_tag;
@ -416,4 +419,16 @@ class Place
return $this;
}
public function getNoteContent(): ?string
{
return $this->note_content;
}
public function setNoteContent(?string $note_content): static
{
$this->note_content = $note_content;
return $this;
}
}

View file

@ -128,17 +128,17 @@ class Motocultrice
area["postal_code"="{$zone}"]->.searchArea;
(
// Recherche des commerces et services avec email
nw["amenity"]["contact:email"](area.searchArea);
nw["amenity"]["email"](area.searchArea);
nw["shop"]["contact:email"](area.searchArea);
nw["shop"]["email"](area.searchArea);
nw["office"]["contact:email"](area.searchArea);
nw["office"]["email"](area.searchArea);
nw["amenity"]["contact:email"][name](area.searchArea);
nw["amenity"]["email"][name](area.searchArea);
nw["shop"]["contact:email"][name](area.searchArea);
nw["shop"]["email"][name](area.searchArea);
nw["office"]["contact:email"][name](area.searchArea);
nw["office"]["email"][name](area.searchArea);
// Recherche des commerces et services sans email pour référence
nw["amenity"](area.searchArea);
nw["shop"](area.searchArea);
nw["office"](area.searchArea);
nw["amenity"][name](area.searchArea);
nw["shop"][name](area.searchArea);
nw["office"][name](area.searchArea);
);
out body;
>;

View file

@ -36,10 +36,12 @@
<thead>
<tr>
<th>Nom ({{ stats.getPlacesCount() }})</th>
<th>Type</th>
<th>Adresse ({{ stats.getAvecAdresse() }} / {{ stats.getPlacesCount() }})</th>
<th>Site web ({{ stats.getAvecSite() }} / {{ stats.getPlacesCount() }})</th>
<th>Accessibilité ({{ stats.getAvecAccessibilite() }} / {{ stats.getPlacesCount() }})</th>
<th>Note ({{ stats.getAvecNote() }} / {{ stats.getPlacesCount() }})</th>
<th>Note ({{ stats.getAvecNote() }} / {{ stats.getPlacesCount() }})</th>
</tr>
</thead>
<tbody>
@ -48,10 +50,12 @@
<td style="background-color: {{ commerce.hasAddress() ? 'yellowgreen' : 'transparent' }};">
<a href="{{ path('app_admin_commerce', {'id': commerce.id}) }}">{{ commerce.name }}</a>
</td>
<td style="background-color: {{ commerce.mainTag ? 'yellowgreen' : 'transparent' }};">{{ commerce.mainTag }}</td>
<td style="background-color: {{ commerce.hasAddress() ? 'yellowgreen' : 'transparent' }};">{{ commerce.address }}</td>
<td style="background-color: {{ commerce.hasWebsite() ? 'yellowgreen' : 'transparent' }};">{{ commerce.website }}</td>
<td style="background-color: {{ commerce.hasWheelchair() ? 'yellowgreen' : 'transparent' }};">{{ commerce.wheelchair }}</td>
<td style="background-color: {{ commerce.hasNote() ? 'yellowgreen' : 'transparent' }};">{{ commerce.note }}</td>
<td style="background-color: {{ commerce.hasNote() ? 'yellowgreen' : 'transparent' }};">{{ commerce.note }}</td>
<td style="background-color: {{ commerce.hasNote() ? 'yellowgreen' : 'transparent' }};">{{ commerce.noteContent }}</td>
</tr>
{% endfor %}
</tbody>
@ -88,9 +92,15 @@
});
map.on('load', () => {
console.log(data.elements);
console.log('map chargé',data.elements);
data.elements.forEach(element => {
if (element.lat && element.lon) {
if(element.tags){
console.log('element', element.tags['name'] , element);
}
if (element.lat && element.lon && element.tags && element.tags['name']) {
const el = document.createElement('div');
el.className = 'marker';
el.style.width = '20px';
@ -105,10 +115,26 @@
}
tagstable += '</table>';
// Créer un élément div pour le texte du nom
const nameDiv = document.createElement('div');
nameDiv.className = 'marker-name';
nameDiv.style.position = 'absolute';
nameDiv.style.backgroundColor = 'white';
nameDiv.style.padding = '2px 5px';
nameDiv.style.borderRadius = '3px';
nameDiv.style.fontSize = '12px';
nameDiv.style.whiteSpace = 'nowrap';
nameDiv.style.transform = 'translate(-50%, -150%)';
nameDiv.textContent = element.tags?.name || 'Sans nom';
el.appendChild(nameDiv);
new maplibregl.Marker(el)
.setLngLat([element.lon, element.lat])
.setPopup(new maplibregl.Popup({ offset: 25 })
.setHTML(`<a href="https://openstreetmap.org/${element.type}/${element.id}" target="_blank"><h3>${element.tags?.name || 'Sans nom'}</h3></a> <br> ${tagstable}`))
.setHTML(
`<a href="/admin/placeType/${element.type}/${element.id}" ><h3>${element.tags?.name || 'Sans nom'}</h3></a> <br><a href="https://openstreetmap.org/${element.type}/${element.id}" target="_blank">OSM</a> ${tagstable}`
)
)
.addTo(map);
}
});

View file

@ -21,7 +21,8 @@
{{ parent() }}
<script src='https://cdn.jsdelivr.net/npm/maplibre-gl@3.6.2/dist/maplibre-gl.js'></script>
<script>
<script >
// Définir la fonction labourer dans le scope global
function labourer() {
window.location.href = '/admin/labourer/' + document.getElementById('app_admin_labourer').value;
@ -45,7 +46,7 @@
// Attendre le chargement du DOM
document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('DOMContentLoaded', async function() {
// Récupérer le bouton labourer
const btnLabourer = document.querySelector('#labourer');
if (btnLabourer) {
@ -58,30 +59,29 @@
});
}
const postalCodes = [{% for stat in stats %}'{{ stat.zone }}'{% if not loop.last %}, {% endif %}{% endfor %}];
const postalCodes = [{% for stat in stats %}'{{ stat.zone }}'{% if not loop.last %}, {% endif %}{% endfor %}];
console.log(postalCodes);
let postalLines = ``;
postalCodes.forEach(code => {
if (/^\d+$/.test(code)) {
postalLines += `nwr["boundary"="postal_code"][postal_code=${code}]["name"~"."];`;
postalLines += `\nnode[place=city]["addr:postcode"=${code}][name];`
}
});
const query = `[out:json];
const query = `[out:json][timeout:25];
(
${postalLines}
);
out center;` ;
console.log(query);
console.log('https://overpass-api.de/api/interpreter');
const response = await fetch('https://overpass-api.de/api/interpreter', {
method: 'POST',
body: query
});
const data = await response.json();
console.log(data);
console.log('data',data);
// Ajouter un marqueur pour chaque point de la réponse
const bounds = new maplibregl.LngLatBounds();
@ -111,15 +111,6 @@ const postalCodes = [{% for stat in stats %}'{{ stat.zone }}'{% if not loop.last
padding: 50
});
}
return data.elements.reduce((acc, element) => {
if (element.tags?.['postal_code']) {
acc[element.tags['postal_code']] = [element.lon, element.lat];
}
return acc;
}, {});
});
</script>
{% endblock %}

View file

@ -147,7 +147,7 @@
<a href="{{ path('app_admin_stats', {'zip_code': commerce_overpass['tags_converted']['addr:postcode'] ?? '-1'}) }}" class="btn btn-outline-secondary">
<a href="{{ path('app_admin_stats', {'zip_code': zone ?? '-1'}) }}" class="btn btn-outline-secondary">
<i class="bi bi-bar-chart"></i>
{{ 'display.view_stats'|trans }}
</a>
@ -225,7 +225,7 @@
new mapboxgl.Marker()
.setLngLat([{{ commerce_overpass['@attributes'].lon }}, {{ commerce_overpass['@attributes'].lat }}])
.setPopup(new mapboxgl.Popup({ offset: 25 }).setHTML('<h1>{{ commerce_overpass.tags_converted.name }}</h1><p>Completion:{{completion_percentage}}%</p>'))
.setPopup(new mapboxgl.Popup({ offset: 25 }).setHTML('<h1>{{ commerce_overpass.tags_converted.name }}</h1>'))
.addTo(map);
{% endif %}

View file

@ -25,7 +25,7 @@
<td>
{{place.zipcode}}
</td>
<td>{{ place.note }}</td>
<td>{{ place.noteContent }}</td>
<td><a class="btn btn-primary" href="{{ path('app_admin_commerce', {'id': place.id}) }}">
<i class="bi bi-pencil"></i>
</a></td>