Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,138 @@ und dieses Projekt folgt [Semantic Versioning](https://semver.org/spec/v2.0.0.ht

---

## [2.41.0] — 2026-08-27

Fünf Punkte aus dem Usability-Test. Hilfetexte haben jetzt je einen Ort, die Definition zeigt
ihre Struktur und verweist auf den Standard — und wo ein Feld eine feste Auswahl hat, ist es
auch eine Auswahl und kein Textfeld, das seine Optionen erst nach dem Tippen preisgibt.

### ✨ Added
- **Merkmalsliste über jeder Definition.** Das „Mehr erfahren"-Panel nennt oben in zwei Zeilen
die DCAT-AP-Eigenschaft und die Multiplizität, darunter folgen wie bisher Alltagssprache und
Definition. Der Tester hatte bemerkt, dass die Definitionstexte einer festen Struktur folgen,
diese aber nur im Fließtext steht.
- **`cardinality` als eigenes Feld im Katalog** — für alle 53 Einträge. Zwei neue Tests halten
den strukturierten Wert und die Angabe im Definitionstext zusammen; ohne sie laufen beide
auseinander, sobald jemand nur eine Seite anfasst.
- **Link auf die Spezifikation je Profil-Klasse.** Am Fuß jedes Panels steht „Im Standard
nachlesen: Datensatz" bzw. „: Distribution" mit Verweis auf den passenden Abschnitt von
DCAT-AP.de 3.0. Bewusst je Klasse und nicht je Feld: Die feldgenauen Anker ließen sich von
hier aus nicht überprüfen — bei den drei Klassen-Ankern führt ein Irrtum schlimmstenfalls an
den Anfang des richtigen Dokuments. Die Zuordnung der 12 Distributions-Felder stammt aus
`odw_build_distribution_node()` und wird von einem Test dagegen gehalten.
- **`entity` als eigenes Feld im Katalog** — 41 Datensatz-, 12 Distributions-Felder,
gegengeprüft gegen die Registry.

### ✨ Added (Fortsetzung)
- **Thema ist eine Mehrfachauswahl.** `dcat:theme` erlaubt laut Profil 0..n Themen; das Formular
bot ein Auswahlfeld in Tab 1 und ein Tipp-Feld unter „Erweiterte Angaben" — zusammen höchstens
zwei, auf zwei verschiedene Arten. Beide sind durch ein Mehrfachfeld mit den EU-Themen ersetzt.
Der Batch-Import nimmt jetzt ebenfalls mehrere Themen an (Komma- oder Zeilentrennung).
- **Engagementfeld ist eine Mehrfachauswahl, Contributor-ID ein Auswahlfeld.** Beide waren
Textfelder mit einer `<datalist>` dahinter — man musste erst tippen, um überhaupt zu sehen,
dass es eine Auswahl gibt, und wer daneben tippte, bekam einen Wert ohne URI. 16 bzw. 69
Einträge passen in eine Liste. `dct:subject` erlaubt 0..n, deshalb ist das Engagementfeld
mehrfach wählbar; die Contributor-ID bleibt einfach.
- **Die CESSDA-Vorschläge öffnen sich beim Anklicken.** Mit mehreren hundert Konzepten bleibt
hier eine Vorschlagsliste richtig — aber eine, die zeigt, was zur Auswahl steht. Sie ersetzt
das native `<datalist>` durch eine eigene Liste mit Tastaturbedienung (Pfeiltasten, Enter,
Escape). Nebeneffekt: Das Verhalten ist in allen Browsern dasselbe und im E2E-Test überhaupt
prüfbar — ein datalist-Popup ist Browser-Chrome und für Playwright unsichtbar.

### 🎨 Changed
- **Tooltip und „Mehr erfahren" haben getrennte Rollen.** Das ⓘ trägt nur noch den DCAT-AP-Begriff,
alles Erklärende steht im Panel. Vorher stand beides an beiden Orten — beim Herausgeber sogar
mit unterschiedlichen Beispielen. Betrifft 42 Felder.
- **Fünf Felder hatten gar keinen Fachbegriff im Tooltip**, sondern schon dort Prosa: die drei
Kontaktfelder, die eigene Lizenz-URI und die HVD-Kennzeichnung. Sie tragen jetzt ihren
tatsächlich ausgegebenen Begriff (`vcard:fn`, `vcard:hasEmail`, `vcard:hasURL`, `dct:license`,
`dcatap:applicableLegislation`).
- **Das Schlagwort-Beispiel widersprach seiner eigenen Regel.** Der Text verlangte ein Wort je
Zeile und nannte dann ein Beispiel mit Kommas — wer nur den Katalog las, tippte genau die
falsche Form.

### 🐛 Fixed
- **Migration der Themen, damit nichts verlorengeht.** Carbon Fields legt Mehrfachwerte unter
eigenen Meta-Keys ab (`_odw_theme|||0|value`), die alten flachen Zeilen wären unsichtbar
geworden. Eine einmalige Umschreibung überführt beim ersten Aufruf des Backends alle
Datensätze — über `carbon_set_post_meta()`, nicht über selbstgebaute Schlüssel, weil deren
Format ein Interna der Bibliothek ist.
- **Themenfilter und Sortierung wären still kaputtgegangen.** Beide fragten die Datenbank auf
`_odw_theme` ab und hätten Mehrfachwerte nicht mehr gefunden. Das Plugin schreibt die Auswahl
deshalb zusätzlich flach: `_odw_theme_index` (eine Zeile je Thema) für den Katalogfilter,
`_odw_theme_sort` für die Spaltensortierung. Der bestehende E2E-Test auf `?theme=Bildung`
prüft das mit — und fand dabei gleich noch, dass der Katalogfilter den Parameter anders
auflöste als der Index geschrieben wird: `resolve_theme_uri()` kennt nur die EU-Bezeichnungen,
und „Bildung" heißt dort „Bildung, Kultur und Sport". Der Filter nimmt jetzt dieselbe
Auflösung wie das Speichern, damit Harvester mit dem alten deutschen Kurznamen weiter
Treffer bekommen.
- **Das Engagementfeld hätte seinen Wert verloren.** Wie beim Thema ändert die Mehrfachauswahl
das Speicherformat; dieselbe einmalige Umschreibung überführt jetzt beide Felder und löst
dabei einen von Hand eingetippten Namen zur Vokabular-URI auf.
- **`bin/check-i18n.py` übersah `config/`.** `mqa-metrics.php` und `dcat-ap-fields.php` führen
ihre Beschriftungen über `__()`, standen aber nicht in der Dateiliste der Prüfung — für 31
Zeichenketten hätte eine fehlende Übersetzung also nie jemand gemeldet. Aufgefallen ist es,
weil ich beim Aufräumen der Kataloge beinahe genau diese Einträge gelöscht hätte.

### 🧹 Removed
- **Das generische Vokabular-Autosuggest (`data-odw-vocab`) ist entfallen** — mit Thema,
Engagementfeld und Contributor-ID hatte es keine Nutzer mehr. Damit entfällt auch die
Auslieferung der drei Vokabulare an jede Admin-Seite; die Optionen stehen jetzt im Formular
selbst. Die Vokabulardateien unter `config/vocabularies/` bleiben unverändert.

### ℹ️ Eine Ausnahme mit Begründung
Das Wiederholfeld für weitere Distributionen behält seinen Hilfetext: Für dieses Feld gibt es
keinen Katalogeintrag, das Panel erscheint dort also gar nicht — der Tooltip ist die einzige
Erklärung, die es hat.

---

## [2.40.3] — 2026-08-27

Vier Punkte aus einem Usability-Test — und was beim Nachprüfen sonst noch auffiel.

### 🐛 Fixed
- **`dct:subject` war fälschlich als DCAT-AP-Definition ausgewiesen.** Die Eigenschaft (CESSDA-
Themenklassifikation, ZiviZ-Engagementfeld) gehört nicht zum Profil — in den mitgelieferten
offiziellen SHACL-Shapes taucht sie für Datensätze nirgends auf. Zulässig ist sie trotzdem,
RDF erlaubt zusätzliche Aussagen, und sie bleibt bewusst erhalten; die Feld-Referenz sagt jetzt
aber dazu, dass streng profilkonforme Portale sie ignorieren dürfen. Beim systematischen
Abgleich aller 43 Katalog-Eigenschaften gegen die Shapes fiel ein zweiter Fall auf:
`dcatap:hvdCategory` stammt aus der HVD-Erweiterung (EU-Verordnung 2023/138), nicht aus dem
Kernprofil DCAT-AP 3.0. Auch vermerkt.
- **Die Verwaltungsebene nannte Optionen, die es nicht gibt.** Die Beschreibung sprach von
„Kreis" und „Kommune", die Auswahlliste bietet „Landkreis" und „Gemeinde". Betraf beide
Beschreibungstexte, den allgemeinverständlichen und den fachlichen.

### 🎨 Changed
- **Pflichtfeld-Hinweis umformuliert:** „* Pflichtfeld für die Veröffentlichung. Als Entwurf
können Sie den Datensatz jederzeit speichern." Der bisherige Satz stolperte über sich selbst.
- **Beispiele aus den Tooltips fester Auswahllisten entfernt.** Ein Beispiel, das nur die
Optionen des Dropdowns wiederholt, hilft niemandem. Der Tester fand einen Fall — es waren
acht: Thema, Sprache, Format, Lizenz, Verfügbarkeit, Aktualisierungsfrequenz, Verwaltungsebene
und HVD-Kategorie. Erklärende Sätze sind geblieben, gestrichen wurde nur der Beispielteil.
- **„Kardinalität" heißt jetzt durchgängig „Multiplizität"** — den Begriff verwendet die
deutsche Spezifikation DCAT-AP.de. Betrifft 52 Stellen im Feld-Katalog, die daraus generierte
Feld-Referenz und `TECHNICAL-SPEC.md`. Dort auch die Spaltenabkürzung „Norm-Kard." →
„Norm-Mult.": Eine reine Wortersetzung hätte sie nicht erfasst, und eine Legende, die eine
Abkürzung auf ein anderes Wort auflöst, ist schlimmer als der alte Begriff.
- **Der neue Pflichtfeld-Wortlaut gilt jetzt überall.** Beim ersten Anlauf hatte ich nur die
Legende unter dem Formular geändert; „Als Entwurf können Sie jederzeit unvollständig
speichern" stand weiter in der Meldung nach blockierter Veröffentlichung, auf der
Einstiegsseite und im README.
- **Die Einstiegsseite versprach Beispiele, die es nicht mehr gibt.** „Jedes Feld hat hilfreiche
Beispiele, die Sie über das ⓘ-Symbol einblenden" stimmte nach dem Entfernen der acht Beispiele
nicht mehr. Der Satz benennt jetzt die tatsächliche Aufteilung: ⓘ zeigt den DCAT-AP-Begriff,
„Mehr erfahren" die ausführliche Erklärung.

### 🧹 Aufgeräumt
- Zehn verwaiste Übersetzungseinträge entfernt, die durch die Textänderungen ohne Fundstelle
im Code zurückgeblieben waren. `bin/check-i18n.py` prüft nur auf fehlende, nicht auf
überzählige Einträge — die CI hätte das nicht gemeldet.

---

## [2.40.2] — 2026-08-23

Zwei Rückmeldungen aus dem Backend.
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<p align="center">
<img src="https://img.shields.io/github/license/daimpad/OpenDataWizard?style=flat-square&color=03FF9A&labelColor=101010&label=Lizenz" alt="Lizenz">
<img src="https://img.shields.io/badge/Version-2.40.2-03FF9A?style=flat-square&labelColor=101010" alt="Version">
<img src="https://img.shields.io/badge/Version-2.41.0-03FF9A?style=flat-square&labelColor=101010" alt="Version">
<img src="https://img.shields.io/badge/DCAT--AP-3.0-03FF9A?style=flat-square&labelColor=101010" alt="DCAT-AP 3.0">
<img src="https://img.shields.io/badge/PHP-%3E%3D%208.1-03FF9A?style=flat-square&labelColor=101010&logo=php&logoColor=white" alt="PHP >= 8.1">
<img src="https://img.shields.io/badge/WordPress-6.4%2B-03FF9A?style=flat-square&labelColor=101010&logo=wordpress&logoColor=white" alt="WordPress 6.4+">
Expand Down Expand Up @@ -85,12 +85,12 @@ Eigener Bereich im WordPress-Backend mit Übersicht, Filterung und Statusverwalt
### 😊 Benutzerfreundliche Formularsprache
Das Wizard-Formular wurde vollständig überarbeitet, um es auch ohne DCAT-AP-Kenntnisse intuitiv zu machen:
- **Klare Fragen statt technischer Begriffe:** Statt „Herausgebende Organisation (dct:publisher)" fragt das Plugin: „Wer gibt diese Daten heraus?"
- **Hilfreiche Beispiele:** Jedes Feld hat konkrete, praxisnahe Beispiele
- **Ursprüngliche Labels in Hilfetexten:** DCAT-AP Bezeichnungen und technische Details bleiben in den Hilfetexten sichtbar
- **Zwei Hilfen mit klaren Rollen:** Das ⓘ-Symbol zeigt den DCAT-AP-Begriff des Feldes — der schnelle Blick für alle, die wissen wollen, was das im Standard ist. „Mehr erfahren" klappt die ausführliche Erklärung auf: die DCAT-AP-Eigenschaft und ihre Multiplizität als Kurzangabe, darunter eine Erklärung in Alltagssprache mit Beispiel und die normkonforme Definition
- **Jede Information an genau einem Ort:** Dadurch können Kurzhilfe und Langtext sich nicht mehr widersprechen
- **Validierungsmeldungen in Klartext, mit Ort:** Wird die Veröffentlichung blockiert, nennt die Meldung den Tab und den verständlichen Feldnamen (der technische DCAT-AP-Begriff steht nur klein daneben) — ein Klick auf „Zum Feld springen" öffnet den passenden Tab und hebt das Feld hervor

### 🧭 Geführter Wizard
Fünf-Tab-Assistent mit praktischen Beispielen. Pflichtfelder sind mit einem roten Sternchen (`*`) gekennzeichnet; als **Entwurf** lässt sich jederzeit unvollständig speichern — erst zum **Veröffentlichen** müssen alle Pflichtangaben ausgefüllt sein.
Fünf-Tab-Assistent mit praktischen Beispielen. Pflichtfelder sind mit einem roten Sternchen (`*`) gekennzeichnet; als **Entwurf** lässt sich der Datensatz jederzeit speichern — erst zum **Veröffentlichen** müssen alle Pflichtangaben ausgefüllt sein.

1. **Grundlegende Informationen** — „Wer gibt diese Daten heraus?", „Worum geht es in diesem Datensatz?", „Welchem Thema ist dieser Datensatz zugeordnet?", „Mit welchen Schlagworten finde ich diese Daten?". Weniger häufige Einordnungen (CESSDA-Themenklassifikation, ZiviZ-Engagementfeld) liegen in einer aufklappbaren Untergruppe am Tab-Ende.
2. **Sprache & Übersetzungen** — die Sprache der Daten sowie Titel, Beschreibung und Schlagworte in weiteren Sprachen
Expand Down
27 changes: 15 additions & 12 deletions TECHNICAL-SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Bausatz:

| Baustein (piveau) | Inhalt | ODW-Pendant |
|---|---|---|
| `input-definition.ts` | Alle Felder: Typ, DCAT-Prädikat, Kardinalität, Validierung, Vokabular | `config/dcat-ap-fields.php` (erweiterbar) |
| `input-definition.ts` | Alle Felder: Typ, DCAT-Prädikat, Multiplizität, Validierung, Vokabular | `config/dcat-ap-fields.php` (erweiterbar) |
| `page-content-config.js` | Zuordnung Feld → Wizard-Schritt (Essentials/Additionals) | Tab-Zuordnung in `class-fields.php` |
| `prefixes.js` | Namespace-Präfixe für JSON-LD | `odw_build_dataset_jsonld()` (`@context`) |
| `vocab-prefixes.js` | Basis-URIs der kontrollierten Vokabulare | `dct-format-list.php`, `licenses.txt`, CESSDA-RDF |
Expand Down Expand Up @@ -99,19 +99,22 @@ DCAT-AP verlangt für viele Felder URIs aus EU-Authority-Tables statt Freitext.
| `corporate-body` | `http://publications.europa.eu/resource/authority/corporate-body/` | `dct:publisher` | ⚠️ Freitext |
| `iana-media-types` | `https://www.iana.org/assignments/media-types/` | `dcat:mediaType` | ❌ |

> **Wiederverwendbares Muster:** Der bestehende CESSDA-Auto-Suggest (`odw-admin-fields.js` + SKOS/RDF) ist die
> Blaupause für ein generisches „Vokabular-Autosuggest"-Widget, das künftig `data-theme`, `access-right`,
> `planned-availability` etc. aus lokal gebündelten Vokabulardateien bedient (keine externe Abhängigkeit).
> **Muster nach Vokabulargröße (Stand v2.41.0):** Ein Vokabular mit überschaubar vielen Konzepten wird ein
> Auswahlfeld (`select`/`multiselect`, Optionen aus der gebündelten JSON-Datei) — `data-theme` (13),
> `engagementfeld` (16), `contributors` (69), `access-right` (3), `language` (24). Nur wo die Liste zu lang
> für ein Auswahlfeld ist, bleibt eine Vorschlagsliste: CESSDA mit mehreren hundert Konzepten. Diese Liste
> klappt seit v2.41.0 beim Anklicken auf (`odw-suggest` in `odw-admin-fields.js`) statt erst beim Tippen —
> ein `<datalist>` verrät sonst nicht, dass es überhaupt eine Auswahl gibt.

### 4. Vollständiger DCAT-AP-Feldkatalog & Gap-Analyse

**Legende** — Profil: `AP` = DCAT-AP 3.0 · `DE` = DCAT-AP.de 2.0 · `HVD` = High-Value-Dataset-Pflicht ·
Norm-Kard.: Kardinalität laut Standard (`M`andatory/`R`ecommended/`O`ptional) ·
Norm-Mult.: Multiplizität laut Standard (`M`andatory/`R`ecommended/`O`ptional) ·
ODW: ✅ vorhanden · ⚠️ teilweise/Freitext · ❌ fehlt.

#### 4.1 Dataset (`dcat:Dataset`)

| DCAT-Prädikat | Range | Profil | Norm-Kard. | ODW |
| DCAT-Prädikat | Range | Profil | Norm-Mult. | ODW |
|---|---|---|---|---|
| `dct:title` | lang-Literal | AP | M (1..n) | ✅ |
| `dct:description` | lang-Literal | AP | M (1..n) | ✅ |
Expand Down Expand Up @@ -139,7 +142,7 @@ ODW: ✅ vorhanden · ⚠️ teilweise/Freitext · ❌ fehlt.
| `dcatde:politicalGeocodingLevelURI` | URI | DE | R (DE) | ✅ |
| `dcatde:politicalGeocodingURI` | URI | DE | O (0..n) | ✅ |
| `dcatde:geocodingDescription` | lang-Literal | DE | O | ❌ |
| `dcatde:contributorID` | URI (`contributors`) | DE | R (DE) | ✅ (Autosuggest) |
| `dcatde:contributorID` | URI (`contributors`) | DE | R (DE) | ✅ (Auswahlfeld) |
| `dcatde:legalBasis` | lang-Literal | DE | O | ✅ |
| `dcatde:qualityProcessURI` | URI | DE | O | ✅ |
| `dcatde:originator` / `dcatde:maintainer` | `foaf:Agent` | DE | O | ✅ |
Expand All @@ -149,7 +152,7 @@ ODW: ✅ vorhanden · ⚠️ teilweise/Freitext · ❌ fehlt.

#### 4.2 Distribution (`dcat:Distribution`)

| DCAT-Prädikat | Range | Profil | Norm-Kard. | ODW |
| DCAT-Prädikat | Range | Profil | Norm-Mult. | ODW |
|---|---|---|---|---|
| `dcat:accessURL` | URI | AP | M (1..n) | ✅ |
| `dcat:downloadURL` | URI | AP | O (0..n) | ✅ |
Expand Down Expand Up @@ -184,7 +187,7 @@ unterstützt; `dct:license`, `dct:language`, `dcat:themeTaxonomy` und `dct:spati

Jeder Registry-Eintrag trägt die Basis-Schlüssel `key`, `meta_key`, `dcat_prop`, `label`, `points`, `required`
sowie seit v2.5.1 die **deklarativen Schema-Metadaten** `profile`, `tier`, `range`, `cardinality`, `entity`, `vocab`.
Damit ist die Registry die dokumentierte Single Source of Truth für Pflichtigkeit, Kardinalität und Wertform
Damit ist die Registry die dokumentierte Single Source of Truth für Pflichtigkeit, Multiplizität und Wertform
(wie piveaus `input-definition.ts`). Die Metadaten sind **abwärtskompatibel** — bestehende Konsumenten
(Qualität, Validierung) lesen weiterhin nur die Basis-Schlüssel; das 0–100-Punkteschema bleibt unverändert.
Eine Schema-Validierung sichert die Invarianten (`tests/test-registry-schema.php`):
Expand All @@ -211,7 +214,7 @@ array(

- `profile`/`tier`/`cardinality` steuern Validierung und Qualitäts-Scoring deklarativ.
- `range` steuert die JSON-LD-Serialisierung (`uri` → `{"@id": …}`, `literal-lang` → `{"@value":…,"@language":…}`).
- `vocab` aktiviert das Vokabular-Autosuggest-Widget.
- `vocab` benennt das gebündelte Vokabular, aus dem die Optionen des Feldes stammen.
- `tab`/`entity` steuern die automatische Einsortierung im Carbon-Fields-Formular.

### 6. Mapping piveau-FormKit → Carbon Fields
Expand All @@ -223,7 +226,7 @@ array(
| `text` / `simpleInput` | `Field::make( 'text', … )` | mit Sanitization |
| `textarea` | `Field::make( 'textarea', … )` | |
| `select` / `simpleSelect` | `Field::make( 'select', … )` | Optionen aus Vokabular |
| `auto` (Vokabular-Autocomplete) | `text` + Autosuggest-JS | CESSDA-Muster generalisieren |
| `auto` (Vokabular-Autocomplete) | `select`/`multiselect` aus dem Vokabular | Vorschlagsliste nur bei sehr großen Vokabularen (CESSDA) |
| `repeatable` (group) | `Field::make( 'complex', … )` | wiederholbare Gruppen |
| `group` / `formkitGroup` | `complex` (max. 1) | strukturierter Knoten |
| `simpleConditional` | `text/select` + `->set_conditional_logic()` | Vokabular ODER manuell |
Expand All @@ -248,7 +251,7 @@ Priorisiert nach Nutzen/Aufwand; jede Phase ist eigenständig auslieferbar.

#### Phase B — DCAT-AP.de & Vokabulare (v2.5) — ✅ weitgehend umgesetzt
- ✅ DCAT-AP.de-Felder: `dcatde:contributorID`, `dcatde:originator`, `dcatde:maintainer`, `dcatap:availability` (zzgl. `dcatde:politicalGeocodingLevelURI` aus v2.3).
- ✅ Generisches Vokabular-Autosuggest (`data-odw-vocab="<id>"`) + lokal gebündelte Vokabulardateien unter `config/vocabularies/` (Start: `contributors`, 69 Einträge).
- ✅ Generisches Vokabular-Autosuggest (`data-odw-vocab="<id>"`) + lokal gebündelte Vokabulardateien unter `config/vocabularies/` (Start: `contributors`, 69 Einträge). Das Autosuggest ist in v2.41.0 durch Auswahlfelder ersetzt worden (siehe Abschnitt 3); die Vokabulardateien sind geblieben.
- ✅ DCAT-AP.de-Felder `politicalGeocodingURI`, `legalBasis`, `qualityProcessURI` (v2.6.0).
- ✅ Gebündelte Vokabulare `access-right` (Feld `dct:accessRights`) und `data-theme` (Zusatz-Theme) (v2.7.0).
- ☐ Offen (optional): vollständige EU-Sprachliste als Autosuggest (bewusst zurückgestellt).
Expand Down
Loading