afficher évènement sélectionné dans le panel de gauche
This commit is contained in:
parent
800d0682c4
commit
7accbe0b13
4 changed files with 217 additions and 50 deletions
|
@ -1,9 +1,13 @@
|
||||||
<form (ngSubmit)="onSubmit()" [formGroup]="form">
|
<form (ngSubmit)="onSubmit()" [formGroup]="form">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>What</label>
|
<label>What</label>
|
||||||
<input class="input" type="text" formControlName="what" placeholder="ex: traffic.roadwork" />
|
<input class="input" type="text" formControlName="what" placeholder="ex: traffic.roadwork" (keyup)="onWhatKeyup()" />
|
||||||
<div class="presets under-field">
|
<div class="presets under-field">
|
||||||
<h4>Presets</h4>
|
<h4>
|
||||||
|
Presets
|
||||||
|
<span class="muted" style="cursor:pointer;" title="Réinitialiser le filtre"
|
||||||
|
(click)="resetPresetFilter()">({{filteredPresetCount()}})</span>
|
||||||
|
</h4>
|
||||||
<div class="preset-groups">
|
<div class="preset-groups">
|
||||||
@for (g of filteredGroups(); track g.category) {
|
@for (g of filteredGroups(); track g.category) {
|
||||||
<div class="group">
|
<div class="group">
|
||||||
|
@ -48,19 +52,33 @@
|
||||||
<div class="prop-row">
|
<div class="prop-row">
|
||||||
<label>{{entry.spec?.label || entry.key}}</label>
|
<label>{{entry.spec?.label || entry.key}}</label>
|
||||||
@if (entry.spec?.values; as vs) {
|
@if (entry.spec?.values; as vs) {
|
||||||
<select class="input" [disabled]="entry.spec?.writable === false" (change)="onPresetValueChange(entry.key, $any($event.target).value)">
|
<select class="input" [disabled]="entry.spec?.writable === false" [formControlName]="entry.key">
|
||||||
@for (v of vs; track v) {
|
@for (v of vs; track v) {
|
||||||
<option [value]="v" [selected]="(presetValues()[entry.key] ?? entry.spec?.default) === v">{{v}}</option>
|
<option [value]="v">{{v}}</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
} @else {
|
} @else {
|
||||||
<input class="input" type="text" [disabled]="entry.spec?.writable === false" [value]="presetValues()[entry.key] ?? entry.spec?.default ?? ''" (input)="onPresetValueChange(entry.key, $any($event.target).value)"/>
|
<input class="input" type="text" [disabled]="entry.spec?.writable === false" [formControlName]="entry.key" />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<!-- Propriétés supplémentaires détectées dans l'évènement sélectionné -->
|
||||||
|
@if (extraPropertyKeys().length > 0) {
|
||||||
|
<div class="row">
|
||||||
|
<div class="preset-properties">
|
||||||
|
@for (key of extraPropertyKeys(); track key) {
|
||||||
|
<div class="prop-row">
|
||||||
|
<label>{{key}}</label>
|
||||||
|
<input class="input" type="text" [formControlName]="key" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<pre>
|
<pre>
|
||||||
{{currentPreset() | json}}
|
{{currentPreset() | json}}
|
||||||
</pre>
|
</pre>
|
||||||
|
@ -77,6 +95,11 @@
|
||||||
<label>Where</label>
|
<label>Where</label>
|
||||||
<input class="input" type="text" formControlName="where" />
|
<input class="input" type="text" formControlName="where" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" formControlName="noLocation" /> Évènement en ligne / sans lieu (accepte sans coordonnées)
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label>Wikidata</label>
|
<label>Wikidata</label>
|
||||||
<input class="input" type="text" formControlName="wikidata" />
|
<input class="input" type="text" formControlName="wikidata" />
|
||||||
|
@ -93,11 +116,12 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="btn" type="submit">{{ featureId() ? 'Mettre à jour' : 'Créer' }}</button>
|
|
||||||
@if (featureId()) {
|
@if (featureId()) {
|
||||||
<button class="btn btn-ghost" type="button" (click)="onDelete()">Supprimer</button>
|
<button class="btn btn-ghost btn-danger" type="button" (click)="onDelete()">Supprimer</button>
|
||||||
}
|
}
|
||||||
<button class="btn btn-ghost" type="button" (click)="onCancelEdit()">Quitter l’édition</button>
|
<button class="btn btn-ghost" type="button" (click)="onCancelEdit()">Quitter l’édition</button>
|
||||||
|
<button class="btn btn-primary" type="submit">{{ featureId() ? 'Mettre à jour' : 'Valider' }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (status().state !== 'idle') {
|
@if (status().state !== 'idle') {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Component, EventEmitter, Input, Output, OnChanges, SimpleChanges, computed, effect, signal } from '@angular/core';
|
import { Component, EventEmitter, Input, Output, OnChanges, SimpleChanges, computed, effect, signal } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormBuilder, FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import oedb from '../../../oedb-types';
|
import oedb from '../../../oedb-types';
|
||||||
import { OedbApi } from '../../services/oedb-api';
|
import { OedbApi } from '../../services/oedb-api';
|
||||||
import { JsonPipe } from '@angular/common';
|
import { JsonPipe } from '@angular/common';
|
||||||
|
@ -32,6 +32,10 @@ export class EditForm implements OnChanges {
|
||||||
});
|
});
|
||||||
|
|
||||||
presetValues = signal<Record<string, any>>({});
|
presetValues = signal<Record<string, any>>({});
|
||||||
|
extraPropertyKeys = signal<string[]>([]);
|
||||||
|
private readonly defaultFormKeys = new Set([
|
||||||
|
'label','description','what','where','lat','lon','noLocation','wikidata','featureType','type','start','stop'
|
||||||
|
]);
|
||||||
|
|
||||||
status = signal<{ state: 'idle' | 'saving' | 'saved' | 'error', message?: string, what?: string }>({ state: 'idle' });
|
status = signal<{ state: 'idle' | 'saving' | 'saved' | 'error', message?: string, what?: string }>({ state: 'idle' });
|
||||||
|
|
||||||
|
@ -46,6 +50,7 @@ export class EditForm implements OnChanges {
|
||||||
where: [''],
|
where: [''],
|
||||||
lat: ['', Validators.required],
|
lat: ['', Validators.required],
|
||||||
lon: ['', Validators.required],
|
lon: ['', Validators.required],
|
||||||
|
noLocation: [false],
|
||||||
wikidata: [''],
|
wikidata: [''],
|
||||||
featureType: ['point'],
|
featureType: ['point'],
|
||||||
type: ['unscheduled'],
|
type: ['unscheduled'],
|
||||||
|
@ -110,17 +115,22 @@ export class EditForm implements OnChanges {
|
||||||
stop: this.toLocalInputValue(p.stop || new Date(new Date().getTime() + 24 * 3600 * 1000))
|
stop: this.toLocalInputValue(p.stop || new Date(new Date().getTime() + 24 * 3600 * 1000))
|
||||||
}, { emitEvent: false });
|
}, { emitEvent: false });
|
||||||
|
|
||||||
// hydrate presetValues from selected properties for known keys
|
// Ajouter des contrôles pour les propriétés du preset courant
|
||||||
const current = this.currentPreset();
|
const current = this.currentPreset();
|
||||||
const result: Record<string, any> = {};
|
const presetKeys = new Set<string>(
|
||||||
if (current && current.properties) {
|
current && current.properties ? Object.keys(current.properties) : []
|
||||||
Object.keys(current.properties).forEach(key => {
|
);
|
||||||
if (Object.prototype.hasOwnProperty.call(p, key)) {
|
presetKeys.forEach(key => this.ensureControl(key, p[key] ?? current?.properties?.[key]?.default ?? ''));
|
||||||
result[key] = p[key];
|
|
||||||
}
|
// Ajouter des contrôles pour les autres propriétés présentes dans l'événement sélectionné
|
||||||
});
|
const extra: string[] = [];
|
||||||
}
|
Object.keys(p).forEach((key) => {
|
||||||
this.presetValues.set(result);
|
if (this.defaultFormKeys.has(key)) return;
|
||||||
|
if (presetKeys.has(key)) return;
|
||||||
|
this.ensureControl(key, p[key]);
|
||||||
|
extra.push(key);
|
||||||
|
});
|
||||||
|
this.extraPropertyKeys.set(extra);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,13 +144,12 @@ export class EditForm implements OnChanges {
|
||||||
description: preset.description || this.form.value.description
|
description: preset.description || this.form.value.description
|
||||||
});
|
});
|
||||||
|
|
||||||
// initialize presetValues with defaults if any
|
// Créer/mettre à jour les contrôles dynamiques pour les propriétés du preset
|
||||||
const result: Record<string, any> = {};
|
|
||||||
const props = preset.properties || {};
|
const props = preset.properties || {};
|
||||||
Object.keys(props).forEach(k => {
|
Object.keys(props).forEach(k => {
|
||||||
if (Object.prototype.hasOwnProperty.call(props[k], 'default')) result[k] = props[k].default;
|
const initial = Object.prototype.hasOwnProperty.call(props[k], 'default') ? props[k].default : '';
|
||||||
|
this.ensureControl(k, (this.selected?.properties?.[k] ?? initial));
|
||||||
});
|
});
|
||||||
this.presetValues.set(result);
|
|
||||||
|
|
||||||
// adjust stop based on preset duration
|
// adjust stop based on preset duration
|
||||||
const startIso = this.toIsoFromLocalInput(this.form.value.start);
|
const startIso = this.toIsoFromLocalInput(this.form.value.start);
|
||||||
|
@ -149,6 +158,18 @@ export class EditForm implements OnChanges {
|
||||||
const stop = new Date(start.getTime() + preset.durationHours * 3600 * 1000);
|
const stop = new Date(start.getTime() + preset.durationHours * 3600 * 1000);
|
||||||
this.form.patchValue({ stop: this.toLocalInputValue(stop) }, { emitEvent: true });
|
this.form.patchValue({ stop: this.toLocalInputValue(stop) }, { emitEvent: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recalculer les extra properties (non définies par le preset)
|
||||||
|
const presetKeys = new Set<string>(Object.keys(props));
|
||||||
|
const currentProps = this.selected?.properties || {};
|
||||||
|
const extra: string[] = [];
|
||||||
|
Object.keys(currentProps).forEach((k) => {
|
||||||
|
if (this.defaultFormKeys.has(k)) return;
|
||||||
|
if (presetKeys.has(k)) return;
|
||||||
|
this.ensureControl(k, currentProps[k]);
|
||||||
|
extra.push(k);
|
||||||
|
});
|
||||||
|
this.extraPropertyKeys.set(extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
private groupPresets(query: string): Array<{ category: string, items: Array<{ key: string, label: string, emoji: string }> }> {
|
private groupPresets(query: string): Array<{ category: string, items: Array<{ key: string, label: string, emoji: string }> }> {
|
||||||
|
@ -177,7 +198,46 @@ export class EditForm implements OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
const val = this.form.value;
|
const val = this.form.value as any;
|
||||||
|
|
||||||
|
// Validation minimale: what obligatoire; coordonnées lat/lon obligatoires si non en ligne/sans lieu
|
||||||
|
if (!val.what || String(val.what).trim() === '') {
|
||||||
|
this.status.set({ state: 'error', what: val.what, message: 'Le champ "what" est requis' });
|
||||||
|
setTimeout(() => this.status.set({ state: 'idle' }), 3000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isNoLocation = !!val.noLocation;
|
||||||
|
const numLat = Number(val.lat);
|
||||||
|
const numLon = Number(val.lon);
|
||||||
|
const haveCoords = Number.isFinite(numLat) && Number.isFinite(numLon);
|
||||||
|
if (!isNoLocation && !haveCoords) {
|
||||||
|
this.status.set({ state: 'error', what: val.what, message: 'Latitude et longitude sont requises' });
|
||||||
|
setTimeout(() => this.status.set({ state: 'idle' }), 3000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construire la géométrie selon le mode
|
||||||
|
let geometry: any;
|
||||||
|
if (isNoLocation) {
|
||||||
|
// Polygone englobant le monde (bbox globale)
|
||||||
|
geometry = {
|
||||||
|
type: 'Polygon',
|
||||||
|
coordinates: [[
|
||||||
|
[-180, -90],
|
||||||
|
[-180, 90],
|
||||||
|
[180, 90],
|
||||||
|
[180, -90],
|
||||||
|
[-180, -90]
|
||||||
|
]]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
geometry = {
|
||||||
|
type: 'Point',
|
||||||
|
coordinates: [Number(val.lon), Number(val.lat)]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const feature: any = {
|
const feature: any = {
|
||||||
type: 'Feature',
|
type: 'Feature',
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -188,32 +248,40 @@ export class EditForm implements OnChanges {
|
||||||
wikidata: val.wikidata,
|
wikidata: val.wikidata,
|
||||||
type: val.type,
|
type: val.type,
|
||||||
start: this.toIsoFromLocalInput(val.start),
|
start: this.toIsoFromLocalInput(val.start),
|
||||||
stop: this.toIsoFromLocalInput(val.stop)
|
stop: this.toIsoFromLocalInput(val.stop),
|
||||||
|
...(isNoLocation ? { no_location: true } : {})
|
||||||
},
|
},
|
||||||
geometry: {
|
geometry
|
||||||
type: 'Point',
|
|
||||||
coordinates: [Number(val.lon), Number(val.lat)]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Apply default duration from preset when creating a new event
|
// Apply default duration from preset when creating a new event
|
||||||
const preset = (oedb.presets.what as any)[val.what];
|
const durationPreset = (oedb.presets.what as any)[val.what];
|
||||||
if ((!this.featureId()) && preset && typeof preset.durationHours === 'number') {
|
if ((!this.featureId()) && durationPreset && typeof durationPreset.durationHours === 'number') {
|
||||||
// already set from form; ensure consistency if empty
|
// already set from form; ensure consistency if empty
|
||||||
if (!feature.properties.start || !feature.properties.stop) {
|
if (!feature.properties.start || !feature.properties.stop) {
|
||||||
const start = new Date();
|
const start = new Date();
|
||||||
const stop = new Date(start.getTime() + preset.durationHours * 3600 * 1000);
|
const stop = new Date(start.getTime() + durationPreset.durationHours * 3600 * 1000);
|
||||||
feature.properties.start = start.toISOString();
|
feature.properties.start = start.toISOString();
|
||||||
feature.properties.stop = stop.toISOString();
|
feature.properties.stop = stop.toISOString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = this.featureId();
|
const id = this.featureId();
|
||||||
// merge dynamic preset properties
|
// Ajouter les propriétés issues du preset (contrôles dynamiques)
|
||||||
const extra = this.presetValues();
|
const submitPreset = (oedb.presets.what as any)[val.what];
|
||||||
Object.keys(extra || {}).forEach(k => {
|
if (submitPreset && submitPreset.properties) {
|
||||||
feature.properties[k] = extra[k];
|
Object.keys(submitPreset.properties).forEach((k: string) => {
|
||||||
});
|
if (this.form.contains(k)) {
|
||||||
|
feature.properties[k] = this.form.get(k)?.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Ajouter les propriétés extra (non définies par le preset)
|
||||||
|
for (const k of this.extraPropertyKeys()) {
|
||||||
|
if (this.form.contains(k)) {
|
||||||
|
feature.properties[k] = this.form.get(k)?.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.status.set({ state: 'saving', what: val.what, message: 'Envoi en cours…' });
|
this.status.set({ state: 'saving', what: val.what, message: 'Envoi en cours…' });
|
||||||
|
|
||||||
|
@ -222,6 +290,8 @@ export class EditForm implements OnChanges {
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
this.status.set({ state: 'saved', what: val.what, message: 'Évènement mis à jour' });
|
this.status.set({ state: 'saved', what: val.what, message: 'Évènement mis à jour' });
|
||||||
this.saved.emit(res);
|
this.saved.emit(res);
|
||||||
|
// Quitter l'édition après succès
|
||||||
|
this.canceled.emit();
|
||||||
setTimeout(() => this.status.set({ state: 'idle' }), 3000);
|
setTimeout(() => this.status.set({ state: 'idle' }), 3000);
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
|
@ -235,6 +305,8 @@ export class EditForm implements OnChanges {
|
||||||
next: (res) => {
|
next: (res) => {
|
||||||
this.status.set({ state: 'saved', what: val.what, message: 'Évènement créé' });
|
this.status.set({ state: 'saved', what: val.what, message: 'Évènement créé' });
|
||||||
this.created.emit(res);
|
this.created.emit(res);
|
||||||
|
// Quitter l'édition après succès
|
||||||
|
this.canceled.emit();
|
||||||
setTimeout(() => this.status.set({ state: 'idle' }), 3000);
|
setTimeout(() => this.status.set({ state: 'idle' }), 3000);
|
||||||
},
|
},
|
||||||
error: (err) => {
|
error: (err) => {
|
||||||
|
@ -247,9 +319,8 @@ export class EditForm implements OnChanges {
|
||||||
}
|
}
|
||||||
|
|
||||||
onPresetValueChange(key: string, value: any) {
|
onPresetValueChange(key: string, value: any) {
|
||||||
const current = { ...this.presetValues() };
|
// Conservé pour compat, plus utilisé avec formControlName
|
||||||
current[key] = value;
|
if (this.form.contains(key)) this.form.get(key)?.setValue(value);
|
||||||
this.presetValues.set(current);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onDelete() {
|
onDelete() {
|
||||||
|
@ -270,6 +341,26 @@ export class EditForm implements OnChanges {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onWhatKeyup() {
|
||||||
|
// Le filtrage se base déjà sur filteredGroups() qui lit form.what,
|
||||||
|
// donc un keyup déclenche le recalcul via Angular forms.
|
||||||
|
// On garde cette méthode pour des actions annexes si besoin.
|
||||||
|
}
|
||||||
|
|
||||||
|
filteredPresetCount() {
|
||||||
|
try {
|
||||||
|
const groups = this.filteredGroups();
|
||||||
|
return groups.reduce((acc, g) => acc + (g.items?.length || 0), 0);
|
||||||
|
} catch {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPresetFilter() {
|
||||||
|
// Réinitialise le champ what pour afficher tous les presets
|
||||||
|
this.form.patchValue({ what: '' });
|
||||||
|
}
|
||||||
|
|
||||||
onCancelEdit() {
|
onCancelEdit() {
|
||||||
this.selected = null;
|
this.selected = null;
|
||||||
this.featureId.set(null);
|
this.featureId.set(null);
|
||||||
|
@ -312,6 +403,15 @@ export class EditForm implements OnChanges {
|
||||||
return date.toISOString();
|
return date.toISOString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ensureControl(key: string, initial: any) {
|
||||||
|
if (!this.form.contains(key)) {
|
||||||
|
this.form.addControl(key, new FormControl(initial));
|
||||||
|
} else {
|
||||||
|
// Mettre à jour sans émettre pour éviter des boucles
|
||||||
|
this.form.get(key)?.setValue(initial, { emitEvent: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private humanDuration(startIso: string, stopIso: string): string {
|
private humanDuration(startIso: string, stopIso: string): string {
|
||||||
const a = new Date(startIso).getTime();
|
const a = new Date(startIso).getTime();
|
||||||
const b = new Date(stopIso).getTime();
|
const b = new Date(stopIso).getTime();
|
||||||
|
|
|
@ -79,25 +79,61 @@
|
||||||
<app-edit-form [selected]="selected" (saved)="onSaved($event)" (created)="onCreated($event)" (deleted)="onDeleted($event)" (canceled)="onCanceled()"></app-edit-form>
|
<app-edit-form [selected]="selected" (saved)="onSaved($event)" (created)="onCreated($event)" (deleted)="onDeleted($event)" (canceled)="onCanceled()"></app-edit-form>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if(selected !== null){
|
|
||||||
<div class="selected">
|
|
||||||
|
|
||||||
<h3> sélectionné:</h3>
|
|
||||||
|
|
||||||
{{selected.properties.label}}
|
|
||||||
{{selected.properties.name}}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<div id="fixed_actions">
|
<div id="fixed_actions">
|
||||||
<button class="button btn btn-primary" (click)="createEvent()" title="Créer un évènement">+</button>
|
<button class="button btn btn-primary" (click)="createEvent()" title="Créer un évènement">+ nouvel évènement</button>
|
||||||
<button class="button" (click)="toggleView()" title="Basculer carte / tableau">📊</button>
|
<button class="button" (click)="toggleView()" title="Basculer carte / tableau">📊</button>
|
||||||
<div class="downloaders">
|
<div class="downloaders">
|
||||||
<button class="button" (click)="downloadGeoJSON()" title="Télécharger GeoJSON">📥 GeoJSON</button>
|
<button class="button" (click)="downloadGeoJSON()" title="Télécharger GeoJSON">📥 GeoJSON</button>
|
||||||
<button class="button" (click)="downloadCSV()" title="Télécharger CSV">📥 CSV</button>
|
<button class="button" (click)="downloadCSV()" title="Télécharger CSV">📥 CSV</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
@if(selected !== null){
|
||||||
|
<div class="selected">
|
||||||
|
|
||||||
|
<h3> sélectionné: {{selected.properties.name}}</h3>
|
||||||
|
|
||||||
|
{{selected.properties.label}}
|
||||||
|
<br>
|
||||||
|
{{selected.properties.label}}
|
||||||
|
<br>
|
||||||
|
{{selected.properties.what}}
|
||||||
|
<br>
|
||||||
|
{{selected.properties.where}}
|
||||||
|
<br>
|
||||||
|
{{selected.properties.lat}}
|
||||||
|
<br>
|
||||||
|
{{selected.properties.lon}}
|
||||||
|
|
||||||
|
<br>
|
||||||
|
{{selected.properties.wikidata}}
|
||||||
|
<br>
|
||||||
|
{{selected.properties.featureType}}
|
||||||
|
<br>
|
||||||
|
{{selected.properties.type}}
|
||||||
|
<br>
|
||||||
|
start:
|
||||||
|
{{selected.properties.start}}
|
||||||
|
<br>
|
||||||
|
end:
|
||||||
|
{{selected.properties.stop}}
|
||||||
|
<br>
|
||||||
|
source
|
||||||
|
{{selected.properties.source}}
|
||||||
|
<br>
|
||||||
|
description:
|
||||||
|
{{selected.properties.description}}
|
||||||
|
<br>
|
||||||
|
createdate:
|
||||||
|
{{selected.properties.createdate}}
|
||||||
|
<br>
|
||||||
|
lastupdate:
|
||||||
|
{{selected.properties.lastupdate}}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
@if (!showTable) {
|
@if (!showTable) {
|
||||||
<div class="map">
|
<div class="map">
|
||||||
|
|
|
@ -131,6 +131,13 @@ label { font-size: 0.85rem; color: $color-muted; }
|
||||||
|
|
||||||
.aside{
|
.aside{
|
||||||
padding-bottom: 150px;
|
padding-bottom: 150px;
|
||||||
|
.selected{
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid rgba(0,0,0,0.08);
|
||||||
|
margin-bottom: 10px;
|
||||||
|
background: #f0f0f0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.actions{
|
.actions{
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue