nav mobile

This commit is contained in:
Tykayn 2025-11-03 00:14:52 +01:00 committed by tykayn
parent f8abb4d11a
commit 912b4da08e
8 changed files with 234 additions and 52 deletions

View file

@ -15,24 +15,33 @@
<div class="content">
<header>
<nav>
<a [routerLink]="['/']" routerLinkActive="active"><h1>
<div class="nav-header">
<a [routerLink]="['/']" routerLinkActive="active" class="logo-link">
<img src="/static/oedb.png" alt="OEDB" style="width: 20px; height: 20px;">
OEDB
</h1>
<h1>OEDB</h1>
</a>
<!-- <button class="login">login OSM</button> -->
<button
class="burger-menu-toggle"
(click)="toggleNavMenu()"
[attr.aria-expanded]="isNavMenuOpen"
aria-label="Toggle navigation menu">
<span class="burger-line"></span>
<span class="burger-line"></span>
<span class="burger-line"></span>
</button>
</div>
<a routerLink="/agenda" routerLinkActive="active">agenda</a>
<a routerLink="/unlocated-events" routerLinkActive="active">événements non localisés</a>
<a routerLink="/batch-edit" routerLinkActive="active">batch edit</a>
<a routerLink="/events-docs" routerLinkActive="active">events docs</a>
<a routerLink="/research" routerLinkActive="active">research</a>
<a routerLink="/nouvelles-categories" routerLinkActive="active">nouvelles catégories</a>
<a href="/stats" routerLinkActive="active">stats</a>
<a href="https://source.cipherbliss.com/tykayn/oedb-backend" routerLinkActive="active">sources</a>
<div class="nav-links" [class.nav-open]="isNavMenuOpen">
<a routerLink="/agenda" routerLinkActive="active" (click)="closeNavMenu()">📅 agenda</a>
<a routerLink="/unlocated-events" routerLinkActive="active" (click)="closeNavMenu()">📍 événements non localisés</a>
<a routerLink="/batch-edit" routerLinkActive="active" (click)="closeNavMenu()">⚡ batch edit</a>
<a routerLink="/events-docs" routerLinkActive="active" (click)="closeNavMenu()">📚 events docs</a>
<a routerLink="/research" routerLinkActive="active" (click)="closeNavMenu()">🔍 research</a>
<a routerLink="/nouvelles-categories" routerLinkActive="active" (click)="closeNavMenu()">🏷️ nouvelles catégories</a>
<a href="/stats" routerLinkActive="active" (click)="closeNavMenu()">📊 stats</a>
<a href="https://source.cipherbliss.com/tykayn/oedb-backend" routerLinkActive="active" target="_blank" (click)="closeNavMenu()">💻 sources</a>
</div>
</nav>
</header>
<main>

View file

@ -22,4 +22,13 @@ export function momentAdapterFactory() {
})
export class App {
protected readonly title = signal('frontend');
isNavMenuOpen = false;
toggleNavMenu() {
this.isNavMenuOpen = !this.isNavMenuOpen;
}
closeNavMenu() {
this.isNavMenuOpen = false;
}
}

View file

@ -50,6 +50,7 @@ export class EmbedView implements OnInit {
if (params.what) apiParams.what = params.what;
if (params.start) apiParams.start = params.start;
if (params.end) apiParams.end = params.end;
if (params.bbox) apiParams.bbox = params.bbox;
this.oedbApi.getEvents(apiParams).subscribe({
next: (response: any) => {

View file

@ -1,6 +1,7 @@
import { Component, signal } from '@angular/core';
import { Component, signal, OnInit, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ActivatedRoute } from '@angular/router';
import { Menu } from '../home/menu/menu';
interface EmbedConfig {
@ -13,6 +14,7 @@ interface EmbedConfig {
height: string;
theme: string;
embedType: 'script' | 'iframe';
bbox?: string;
}
@Component({
@ -22,10 +24,12 @@ interface EmbedConfig {
templateUrl: './embed.html',
styleUrl: './embed.scss'
})
export class Embed {
export class Embed implements OnInit {
private route = inject(ActivatedRoute);
config = signal<EmbedConfig>({
apiUrl: 'https://api.openeventdatabase.org',
what: 'culture',
what: '',
start: '',
end: '',
limit: 50,
@ -40,6 +44,38 @@ export class Embed {
constructor() {
this.updateConfig();
}
ngOnInit() {
// Lire les query params pour pré-remplir la configuration
this.route.queryParams.subscribe(params => {
const currentConfig = this.config();
const updatedConfig: EmbedConfig = { ...currentConfig };
if (params['what']) {
updatedConfig.what = params['what'];
}
if (params['start']) {
updatedConfig.start = params['start'];
}
if (params['end']) {
updatedConfig.end = params['end'];
}
if (params['limit']) {
updatedConfig.limit = parseInt(params['limit'], 10) || 50;
}
if (params['bbox']) {
// Bbox sera passé dans les paramètres de l'API
(updatedConfig as any).bbox = params['bbox'];
}
this.config.set(updatedConfig);
this.updateConfig();
});
}
updateConfig() {
const config = this.config();
const code = this.generateEmbedCode(config);
@ -52,6 +88,7 @@ export class Embed {
if (config.start) params.set('start', config.start);
if (config.end) params.set('end', config.end);
if (config.limit) params.set('limit', config.limit.toString());
if (config.bbox) params.set('bbox', config.bbox);
const queryString = params.toString();
@ -71,13 +108,15 @@ export class Embed {
} else {
// Code script (ancienne méthode)
const scriptUrl = `${window.location.origin}/embed.js`;
const paramsObj = queryString ?
queryString.split('&').map(param => {
const [key, value] = param.split('=');
return ` '${key}': '${decodeURIComponent(value || '')}'`;
}).join(',\n') : '';
// Construire l'objet params pour le script
const paramsObj: string[] = [];
if (config.what) paramsObj.push(` 'what': '${config.what}'`);
if (config.start) paramsObj.push(` 'start': '${config.start}'`);
if (config.end) paramsObj.push(` 'end': '${config.end}'`);
if (config.limit) paramsObj.push(` 'limit': '${config.limit}'`);
if (config.bbox) paramsObj.push(` 'bbox': '${config.bbox}'`);
const paramsCode = paramsObj ? ` params: {\n${paramsObj}\n },\n` : '';
const paramsCode = paramsObj.length > 0 ? ` params: {\n${paramsObj.join(',\n')}\n },\n` : '';
return `<!-- OpenEventDatabase Embed (script) -->
<div id="oedb-events" style="width: ${config.width}; height: ${config.height}; border: 1px solid #ddd; border-radius: 8px; overflow: hidden;"></div>

View file

@ -5,7 +5,7 @@
@if (isLoading) {
<span class="loading-indicator"></span>
}
<a routerLink="/embed" class="btn-share" title="Partager et intégrer les événements">
<a [routerLink]="['/embed']" [queryParams]="getShareQueryParams()" class="btn-share" title="Partager et intégrer les événements">
🔗 Partager
</a>
</div>

View file

@ -852,4 +852,31 @@ export class Home implements OnInit, OnDestroy {
onMapMove(bbox: { minLng: number, minLat: number, maxLng: number, maxLat: number }) {
this.setCurrentBbox(bbox);
}
getShareQueryParams(): any {
const params: any = {};
// Récupérer les paramètres de filtrage actuels
if (this.selectedWhatFilter) {
params.what = this.selectedWhatFilter;
}
if (this.startDateStr) {
params.start = this.startDateStr;
}
if (this.endDateStr) {
params.end = this.endDateStr;
}
// Ajouter bbox si disponible
if (this.useBboxFilter && this.currentBbox) {
params.bbox = `${this.currentBbox.minLng},${this.currentBbox.minLat},${this.currentBbox.maxLng},${this.currentBbox.maxLat}`;
}
// Limite par défaut pour l'embed
params.limit = 50;
return params;
}
}

View file

@ -39,6 +39,7 @@
<div class="nav-section">
<h3>Communauté</h3>
<a routerLink="/community-upcoming" class="link" (click)="closeMenu()">👥 Community à venir</a>
<a href="https://community.openstreetmap.org/" class="link" target="_blank" (click)="closeMenu()">💬 Forum OpenStreetMap</a>
<a href="https://source.cipherbliss.com/tykayn/oedb-backend" class="link" target="_blank" (click)="closeMenu()">💻 Sources</a>
</div>
</nav>

View file

@ -190,26 +190,7 @@ pre{
white-space: nowrap;
}
}
nav{
display: flex;
flex-direction: row;
gap: 10px;
padding: 10px;
a {
padding: 10px;
border-radius: 10px;
border: 1px solid rgba(0,0,0,0.08);
display: inline-block;
margin-bottom: 10px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
&:hover{
background-color: #f0f0f0;
}
}
}
// Styles nav génériques (remplacés par .main nav dans la section suivante)
.row, .filters, .controls{
input{
@ -256,14 +237,129 @@ nav{
.main{
nav{
background: $color-text ;
a {
background: $color-text;
position: relative;
.nav-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
gap: 1rem;
.logo-link {
display: flex;
align-items: center;
gap: 8px;
text-decoration: none;
color: white;
h1 {
margin: 0;
font-size: 1.2rem;
font-weight: 600;
}
&:hover {
opacity: 0.9;
}
}
}
.burger-menu-toggle {
display: none;
flex-direction: column;
justify-content: space-around;
width: 28px;
height: 28px;
background: transparent;
border: none;
cursor: pointer;
padding: 0;
z-index: 1001;
transition: all 0.3s ease;
@media (max-width: 800px) {
display: flex;
}
&:focus {
outline: 2px solid white;
outline-offset: 2px;
}
}
.burger-line {
width: 100%;
height: 3px;
background: white;
border-radius: 2px;
transition: all 0.3s ease;
transform-origin: center;
}
.burger-menu-toggle[aria-expanded="true"] {
.burger-line:nth-child(1) {
transform: rotate(45deg) translate(7px, 7px);
}
.burger-line:nth-child(2) {
opacity: 0;
}
.burger-line:nth-child(3) {
transform: rotate(-45deg) translate(7px, -7px);
}
}
.nav-links {
display: flex;
flex-direction: row;
gap: 10px;
padding: 0 10px 10px 10px;
flex-wrap: wrap;
transition: all 0.3s ease;
@media (max-width: 800px) {
flex-direction: column;
max-height: 0;
overflow: hidden;
opacity: 0;
padding: 0 10px;
gap: 0;
&.nav-open {
max-height: 1000px;
opacity: 1;
padding: 0 10px 10px 10px;
gap: 5px;
}
}
}
a {
padding: 10px;
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.2);
display: inline-block;
color: white;
text-decoration: none;
white-space: nowrap;
@media (max-width: 800px) {
width: 100%;
margin-bottom: 5px;
}
&:hover{
background: white;
color: $color-text;
}
&.router-link-active, &.active {
background: rgba(255, 255, 255, 0.2);
font-weight: 600;
}
}
}
.content {