diff --git a/api/collections/democol.yml b/api/collections/democol.yml
index 706fd45..5e195dd 100644
--- a/api/collections/democol.yml
+++ b/api/collections/democol.yml
@@ -17,8 +17,10 @@ fields:
# Auf die möglichen Definitionen wird im Kapitel "fields"
# eingegangen.
- !include fields/title.yml
- - !include fields/date.yml
- !include fields/type.yml
+ - !include fields/date.yml
+ - !include fields/content.yml
+ - !include fields/info.yml
# Neben der Definition der Indexe innerhalbd des Feld-Objektes selbst,
# ist die Index-Definition global für die Kollektion auch hier möglich.
@@ -26,8 +28,8 @@ fields:
# Außerdem sind hier feinere Einstellungen für den Index möglich.
# Mehr dazu im "indexes" Kapitel
-indexes:
- - !include democol/textindex.yml
+# indexes:
+ # - !include democol/textindex.yml
# Standardsprache für Text-Index in der Datenbank
defaultLanguage: de
@@ -90,7 +92,7 @@ hooks:
# aktualisiert wird.
update:
type: javascript
- file: hooks/democol/put_create.js
+ file: hooks/democol/put_update.js
# "return" wird auch hier vor der Serverantwort ausgeführt.
return:
type: javascript
diff --git a/api/collections/democol/meta.yml b/api/collections/democol/meta.yml
index 220994f..8bf43ff 100644
--- a/api/collections/democol/meta.yml
+++ b/api/collections/democol/meta.yml
@@ -38,13 +38,37 @@ subNavigation:
- # Jede Unternavigation braucht einen eindeutigen Namen um diese später
# in z.B. Javascript-Code wieder erkennen zu können.
name: pages
+
+ # Die Angabe des "label" ist optional. Wird sie nicht angegeben, wird
+ # wird diese Unternavigation nicht in der Navigation angezeigt.
+ # Ohne "label" kann die Unternavigation aber weiterhin für die Referenzierung
+ # z.B. in der Mediathek-Ansicht des ContentBuilders verwendet werden.
label:
de: Seiten
en: Pages
+
muiIcon: page-layout-body
+
defaultSort:
field: titel
order: ASC
+
+ # Standardmäßig wird man beim Klick auf einen Eintrag der Kollektion
+ # (z.B. Zeile in der Tabelle) direkt zum Editieren des Datensatzes weitergeleitet.
+ # Möchte man das nicht, so kann hier ein alternatives Verhalten definiert werden.
+ # Mögliche Werte sind:
+ # - "edit" (Standard)
+ # - "view" (Anzeigen des Datensatzes)
+ # - Objekt mit "eval"-Attribut
+ #
+ # Beim Objekt mit "eval"-Attribut wird der Code mit dem Javascript-Kontext für
+ # Kollektionen im tibi-admin ausgeführt. Das Ergebnis kann hierbei wieder "edit"
+ # oder "view" sein.
+ # Außerdem ist es möglich, eine eigene Funktion zu definieren, die den Datensatz
+ # als Parameter erhält. Diese Funktion wird dann für den jweiligen Datensatz
+ # ausgeführt, auf den geklickt wurde. Mehr dazu unter dem Widget "ContentBuilder".
+ defaultCallback: view
+
views:
- !include simpleList.yml
- !include table.yml
@@ -63,6 +87,7 @@ subNavigation:
defaultSort:
field: date
order: DESC
+ defaultCallback: edit
views:
- !include simpleList.yml
- !include table.yml
@@ -74,4 +99,4 @@ subNavigation:
# Um diese Anordnung in Tabs zu strukturieren, ist die Verwendung von "tablist"
# vorgesehen.
# Die Definition befindet sich in einem gesonderten Kapitel
-tablist: !include democol/tablist.yml
\ No newline at end of file
+tablist: !include tablist.yml
\ No newline at end of file
diff --git a/api/collections/democol/tablist.yml b/api/collections/democol/tablist.yml
index 4bf71c4..541e8e6 100644
--- a/api/collections/democol/tablist.yml
+++ b/api/collections/democol/tablist.yml
@@ -14,11 +14,18 @@ tabs:
# Welche Felder dieser Tab anzeigen soll, wird über "subFields"
# beschrieben.
subFields:
+ - source: type
- source: title
- source: date
- - name: meta
+ - name: content
label:
- de: Metaangaben
- en: Meta data
+ de: Inhalt
+ en: Content
subFields:
- - source: meta.author
+ - source: content
+ - name: info
+ label:
+ de: Informationen
+ en: Information
+ subFields:
+ - source: info
diff --git a/api/collections/fields/content.yml b/api/collections/fields/content.yml
new file mode 100644
index 0000000..6fbd607
--- /dev/null
+++ b/api/collections/fields/content.yml
@@ -0,0 +1,113 @@
+# Der Name des Feldes ist natürlich beliebig wählbar.
+name: content
+
+# "string" als Datentyp ist zwingend.
+type: string
+
+meta:
+ label:
+ de: Inhalt
+ en: content
+
+ # Die Bezeichnung des ContentBuilder-Widgets ist "contentbuilder".
+ widget: contentbuilder
+
+ # Die Anzeige des ContentBuilder im tibi-admin geschieht innerhalb
+ # eines iframes. Das ist notwendig, da der ContentBuilder eigene
+ # Styles mitbringet, die sich nicht mit den Styles des tibi-admin
+ # vermischen sollten.
+
+ # Via "baseHref" wird der -Tag im iframe gesetzt.
+ # somit können alle relativen Pfade im ContentBuilder (z.B. Bilder)
+ # aufgelöst werden.
+ # Wie man hier sieht, ist die Angabe via "eval" mittels möglich.
+ # Der Kontext ist auf Feldebene, wie bei "dependsOn" und "defaultValue".
+ # Alternativ kann die Angabe auch direkt als String erfolgend.
+ # Dann natürlich ohne die Evaluierung der Variable "$projectBase", wie hier.
+ baseHref:
+ eval: $projectBase
+
+ # Sollen weitere CSS-Datei in das iframe geladen werden, können diese
+ # hier aufgelistet werden.
+ # Die Angabe kann direkt als Array erfolgen oder via "eval", dessen
+ # Code das Array der Strings mit den Dateipfaden zurückgibt.
+ # Auch zu beachten ist hier die relative Angabe. Da "baseHref" gesetzt
+ # ist, wird der Pfad relativ zu dieser Projekt-Basis innerhalb des
+ # tibi-server aufgelöst.
+ # Die Auslieferung der CSS-Dateien direkt über den tibi-server kann
+ # nur funktionieren, wenn "_dist_" in der "assets" Konfiguration der
+ # "config.yml" definiert ist.
+ cssHref:
+ - _/assets/_dist_/index.css
+
+ # Um eine Kollektion stellvertretend als Mediathek anzubinden, sind die
+ # Angaben unter "imageSelect", "fileSelect" und "videoSelect" zu tätigen.
+ # "imageSelect" betrifft die Einbindung von Bildern, "fileSelect" die
+ # Einbindung von Dateien, "videoSelect" die Einbindung von Videos.
+ imageSelect:
+
+ # Die Angabe "collection" ist zwingend. Hier wird die Kollektion
+ # definiert, die als Sammlung für die Bilder/Datei dient.
+ # Der Aufbau der Kollektion ist dabei frei, solange ein Upload-Feld
+ # für die Dateien existiert, welches die URL zur Datei zurückgibt.
+ collection: medialib
+
+ # Optional kann ein Filter und View für die Einbindung der Bilder/Dateien
+ # definiert werden. Dies geschieht über einen "subNavigation"
+ # Eintrag innerhalb des "meta.subNavigation" Arrays, der Kollektion
+ # (hier bei "medialib").
+ # Die Angabe hier ist die auszuwählende Navigation per Index des Arrays.
+ subNavigation: 0
+
+ fileSelect:
+ collection: medialib
+ subNavigation: 0
+ videoSelect:
+ collection: medialib
+ subNavigation: 0
+
+ # "customTags" des ContentBuilder können verwendet werden um die Einbindung
+ # von Modulen ins HTML zu ermöglichen.
+ # Die folgende Auflistung ist dabei ein Beispiel für ein Modul.
+ customTags:
+
+ - # Der Platzhalter wird 1:1 ins HTML übernommen und ist dabei frei
+ # definierbar.
+ # Die eigentliche Funktion eines Modul-Systems muss dann später
+ # im Frontend implementiert werden.
+ placeholder: "Mein Modul"
+
+ # Die Benennung für die UI des ContentBuilder geschieht über die
+ # "label" Angabe, die mehrsprachig erfolgen kann.
+ label:
+ de: "Mein Modul"
+ en: "My Module"
+
+ # Um direkt Style-Angaben in das iframe des ContentBuilder zu übernehmen,
+ # werden diese hier angegeben.
+ # Natürlich ist auch hier wieder die Angabe via "eval" möglich.
+ # Nachfolgendes Beispiel erzeugt im ContentBuilder eine deutliche Darstellung
+ # des eingebundenen Moduls.
+ style: |
+ /*css*/
+ .tibi-module {
+ padding: 10px;
+ border: 3px dashed #c4c4c4;
+ display: block;
+ text-align: center;
+ font-size: 14px;
+ color: black;
+ }
+ .tibi-module::before {
+ content: "\1F5BD ";
+ font-size: 16px;
+ color: black;
+ }
+ .tibi-module::after {
+ content: " title=\"" attr(title) "\" description=\"" attr(description) "\"";
+ font-size: 10px;
+ color: #555;
+ display: block;
+ padding-top: 5px;
+ }
+ /*!css*/
\ No newline at end of file
diff --git a/api/collections/fields/date.yml b/api/collections/fields/date.yml
index 9065b7b..b21d4b8 100644
--- a/api/collections/fields/date.yml
+++ b/api/collections/fields/date.yml
@@ -38,7 +38,7 @@ meta:
# Abgelkeitet vom "type" gibt es Standard-Widgets. für spezielle
# Aufgaben stehen aber eine Hand voll Widgets bereit, die später
# beschrieben werden.
- widget: text
+ widget: date
# Standardwerte für neue Enträge können entweder direkt angegeben
# werden oder via Javascript client-seitig generiert werden.
@@ -54,4 +54,4 @@ meta:
# Das Feld wird nur eingeblendet wenn der Wert von "type"
# (auf gleicher Ebene wie das Feld "date" selbst)
# gleich "news" ist.
- eval: $parent.type == "news"
+ eval: $parent?.type == "news"
diff --git a/api/collections/fields/info.yml b/api/collections/fields/info.yml
new file mode 100644
index 0000000..4fa3c9a
--- /dev/null
+++ b/api/collections/fields/info.yml
@@ -0,0 +1,13 @@
+name: info
+type: object
+meta:
+ label:
+ de: Info
+ en: Info
+subFields:
+ - name: author
+ type: string
+ meta:
+ label:
+ de: Autor
+ en: Author
diff --git a/api/collections/fields/title.yml b/api/collections/fields/title.yml
index e69de29..d7531d7 100644
--- a/api/collections/fields/title.yml
+++ b/api/collections/fields/title.yml
@@ -0,0 +1,6 @@
+name: title
+type: string
+meta:
+ label:
+ de: Titel
+ en: Title
diff --git a/api/collections/fields/type.yml b/api/collections/fields/type.yml
index e69de29..cc6e752 100644
--- a/api/collections/fields/type.yml
+++ b/api/collections/fields/type.yml
@@ -0,0 +1,16 @@
+name: type
+type: string
+meta:
+ label:
+ de: Typ
+ en: Type
+ widget: select
+ choices:
+ - name:
+ de: Standardseite
+ en: Standard page
+ id: page
+ - name:
+ de: News
+ en: News
+ id: news
diff --git a/api/collections/medialib.yml b/api/collections/medialib.yml
new file mode 100644
index 0000000..1efdf0e
--- /dev/null
+++ b/api/collections/medialib.yml
@@ -0,0 +1,100 @@
+# Der Name der Kollektion ist beliebig, aber wird in unserem
+# Beispiel vom ContentBuilder als "medialib" referenziert.
+name: medialib
+uploadPath: ../media/medialib
+
+fields:
+ - !include fields/title.yml
+
+ # Ein Feld vom Typ "file" wird für die Mediathek natürlich
+ # benötigt.
+ - name: file
+ type: file
+ meta:
+ label:
+ de: Datei
+ en: File
+
+permissions:
+ public:
+ methods:
+ get: true
+ post: false
+ put: false
+ delete: false
+ user:
+ methods:
+ get: true
+ post: true
+ put: true
+ delete: true
+
+meta:
+ label:
+ de: Medienbibliothek
+ en: Media Library
+ muiIcon: multimedia
+ defaultSort:
+ field: title
+ order: ASC
+
+ # "defaultImageFilter" dient auch hier nur zur Reduzierung der
+ # Bildgröße bei der Anzeige im tibi-admin (Listen).
+ # Die Bildgröße für die Einbindung ins erzeugte HTML des ContentBuilder
+ # hat hiermit nix zu tun.
+ defaultImageFilter: s
+
+ # Wird unter "image-/file-/videoSelect" im ContentBuilder Feld kein
+ # "subNavigation" Index definiert, werden auch folgende "views"
+ # verwendet.
+ views:
+ - type: table
+ mediaQuery: "(min-width: 0px)"
+ columns:
+ - source: updateTime
+ label: letztes Update
+ type: datetime
+ - source: title
+ filter: true
+ - source: file
+
+ # Wird ein "subNavigation" Index für "image-/file-/videoSelect" definiert,
+ # wird die entsprechende Navigation aus folgender Liste angesprochen.
+ # "0" ist dabei der Index für das erste Element dieser Liste.
+ subNavigation:
+ - # Der "name" der Navigation ist für die Mediathek nicht von Bedeutung,
+ # kann aber für "eval"-Code interessant sein.
+ name: modal
+
+ # Auf "label" wurde hier verzichtet, damit dieses Element nicht in der
+ # Hauptnavigation des tibi-admin auftaucht.
+
+ # Folgende Ansicht wird für unsere Auswahl der Datei im ContentBuilder
+ # angeboten.
+ views:
+ - type: table
+ mediaQuery: "(min-width: 0px)"
+ columns:
+ - source: title
+ filter: true
+ - source: file
+
+ # Damit der ContentBuilder weiß, welche Datei ausgewählt wurde, ist
+ # ist folgender "defaultCallback" notwendig.
+ # Die Funktion wird beim Klick auf die entsprechende Datei aufgerufen.
+ # Als Funktionsparameter steht der gesamte Datensatz der Auswahl zur
+ # Verfügung.
+ # Die Funktionen "parent.selectAsset" und "parent.focus" sind ContentBuilder
+ # spezifisch und schließen die Listenansicht direkt nach Übergabe der
+ # Datei-URL.
+ # Die URL setzt sich aus dem Pfad zur Datei und dem Filter "l" zusammen.
+ # Es wurde eine relative URL konstruiert, da das ContentBuilder-Widget
+ # mit "baseHref" zur Projekt-URL erstellt wird.
+ defaultCallback:
+ eval: |
+ //js
+ (entry) => {
+ parent.selectAsset("medialib/" + entry.id + "/" + entry.file?.src + "?filter=l")
+ parent.focus()
+ }
+ //!js
diff --git a/api/config.yml b/api/config.yml
index ff98d8c..a3ad37f 100644
--- a/api/config.yml
+++ b/api/config.yml
@@ -9,28 +9,29 @@ namespace: demo
# Das "meta"-Objekt ist frei definierbar, wird aber vom tibi-admin in spezieller Form erwartet.
# Mögliche Angaben, die der tibi-admin versteht, sind hier mit aufgeführt.
meta:
- # Pfad zu einer Bilddatei die als Projektbild im tibi-admin verwendet wird
- imageUrl: https://testversion.online/demo.png
-
- # Liste möglicher Berechtigungen, die Benutzern zugeordnet werden können
- permissions:
- - # Name der Berechtigung
- name: news
- # Label für die Anzeige im Admin
- # (kann string oder object mit Sprachen als keys sein)
- label:
- de: Neuigkeiten
- en: News
-
- - name: pages
- label:
- de: Seiten
- en: Pages
-
-# "collections" ist eine Auflistung von Kollektions-Konfigurationen.
+ # Pfad zu einer Bilddatei die als Projektbild im tibi-admin verwendet wird
+ imageUrl: https://testversion.online/demo.png
+
+ # Liste möglicher Berechtigungen, die Benutzern zugeordnet werden können
+ permissions:
+ - # Name der Berechtigung
+ name: news
+ # Label für die Anzeige im Admin
+ # (kann string oder object mit Sprachen als keys sein)
+ label:
+ de: Neuigkeiten
+ en: News
+
+ - name: pages
+ label:
+ de: Seiten
+ en: Pages
+
+# "collections" ist eine Auflistung von Kollektions-Konfigurationen.
# Hier bietet sich eine Auslagerung und Einbindung via YAML-Tag "!include" an.
collections:
- - !include collections/democol.yml
+ - !include collections/democol.yml
+ - !include collections/medialib.yml
# Unter "jobs" können Jobs definiert werden, die regelmäßig ausgeführt werden sollen.
jobs:
@@ -39,4 +40,4 @@ jobs:
# Werden Dateien innerhalb vom tibi-admin benötigt, bietet es sich an diese über
# "assets"-Pfade erreichbar zu machen.
assets:
- - !include assets/demoasset.yml
+ - !include assets/demoassets.yml
diff --git a/api/hooks/democol/delete_delete.js b/api/hooks/democol/delete_delete.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/delete_return.js b/api/hooks/democol/delete_return.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/post_bind.js b/api/hooks/democol/post_bind.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/post_create.js b/api/hooks/democol/post_create.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/post_return.js b/api/hooks/democol/post_return.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/post_validate.js b/api/hooks/democol/post_validate.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/put_bind.js b/api/hooks/democol/put_bind.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/put_return.js b/api/hooks/democol/put_return.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/put_update.js b/api/hooks/democol/put_update.js
new file mode 100644
index 0000000..e69de29
diff --git a/api/hooks/democol/put_validate.js b/api/hooks/democol/put_validate.js
new file mode 100644
index 0000000..e69de29
diff --git a/docs/README.md b/docs/README.md
index 32a04de..b7db39e 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -16,6 +16,7 @@
- [fields](projektkonfig/collections/fields.md)
- [Datentypen](projektkonfig/collections/fields/datentypen.md)
- [Admin Widgets](projektkonfig/collections/fields/widgets.md)
+ - [· ContentBuilder](projektkonfig/collections/fields/widgets/contentbuilder.md)
- [indexes](projektkonfig/collections/indexes.md)
- [hooks](projektkonfig/collections/hooks.md)
- [imageFilter](projektkonfig/collections/imageFilter.md)
diff --git a/docs/projektkonfig/collections/dependsOn.webm b/docs/projektkonfig/collections/dependsOn.webm
new file mode 100644
index 0000000..144b7da
Binary files /dev/null and b/docs/projektkonfig/collections/dependsOn.webm differ
diff --git a/docs/projektkonfig/collections/fields.md b/docs/projektkonfig/collections/fields.md
index 7c53205..fd19b2a 100644
--- a/docs/projektkonfig/collections/fields.md
+++ b/docs/projektkonfig/collections/fields.md
@@ -10,6 +10,12 @@ Zunächst folgt der grundlegende Aufbau des Feld-Objektes:
## validator Objekt
+
+
+Wie im Beispiel von **fields/date.yml** unter `validator` zu sehen ist, wird dort ein Datum nach dem aktuellen erwartet. Wie der Validator sich auf die UI auswirkt, ist im obigen Video zu sehen.
+
Das `validator` Objekt wird *tibi-server* seitig genutzt um die Daten zu validieren. Da das `validator` Objekt dem *tibi-admin* ebenso zur Verfügung steht, kann vorab eine client-seitige Validierung zusätzlich durchgeführt werden.
Attribute des Objektes:
@@ -43,6 +49,53 @@ Sollte der `eval` Code im *tibi-admin* nicht lauffähig sein (nicht abgefangene
## dependsOn
+
+
+Obige Darstellung wie im Video wird beispielsweise durch folgende Feld-Konfiguration erreicht:
+
+```yaml
+# in einer Kollektions-Konfiguration
+fields:
+ - name: type
+ type: string
+ meta:
+ label:
+ de: Typ
+ en: Type
+ widget: select
+ choices:
+ - name:
+ de: Standardseite
+ en: Standard page
+ id: page
+ - name:
+ de: News
+ en: News
+ id: news
+
+ - name: title
+ type: string
+ meta:
+ label:
+ de: Titel
+ en: Title
+
+ - name: date
+ type: date
+ meta:
+ label:
+ de: Titel
+ en: title
+ widget: date
+ defaultValue:
+ eval: new Date()
+ dependsOn:
+ eval: $parent?.type == "news"
+
+```
+
`meta.dependsOn` kann als Objekt mit `eval`-Attribut für Javascript oder als `string` mit dem Feldnamen (Punktschreibweise, z.B. `"additionalData.author"`) angegeben werden.
Wird der Feldname verwendet wird nur geprüft, ob das Feld belegt ist. TODO
@@ -60,6 +113,7 @@ Die Rückgabe des Javascript-Codes beeinflusst die Einblendung des betroffenen F
| `true` | Das Feld wird angezeigt |
| `false` | Das Feld wird ausgeblendet |
+
## defaultValue
Für die Vorlegung neu anzulegender Datensätze kann in `field.meta.defaultValue` direkt der Standardwert hinterlegt werden, oder über `field.meta.defaultValue.eval` ein Javascript-Code angegeben werden, der den Wert ermittelt. Die Rückgabe des Javascript-Codes, sowie auch die direkte Vergabe des Wertes muss dem Datentyp des Feldes entsprechen.
diff --git a/docs/projektkonfig/collections/fields/widgets.md b/docs/projektkonfig/collections/fields/widgets.md
index 40ec4ca..56161e8 100644
--- a/docs/projektkonfig/collections/fields/widgets.md
+++ b/docs/projektkonfig/collections/fields/widgets.md
@@ -34,4 +34,6 @@ Nicht jedes Widget kann mit jedem Datentyp umgehen, die möglichen Datentypen we
## tabs
-## contentbuilder
\ No newline at end of file
+## contentbuilder
+
+siehe: [ContentBuilder](./widgets/contentbuilder.md)
diff --git a/docs/projektkonfig/collections/fields/widgets/contentbuilder-module.webm b/docs/projektkonfig/collections/fields/widgets/contentbuilder-module.webm
new file mode 100644
index 0000000..4963686
Binary files /dev/null and b/docs/projektkonfig/collections/fields/widgets/contentbuilder-module.webm differ
diff --git a/docs/projektkonfig/collections/fields/widgets/contentbuilder.md b/docs/projektkonfig/collections/fields/widgets/contentbuilder.md
new file mode 100644
index 0000000..f08cfe2
--- /dev/null
+++ b/docs/projektkonfig/collections/fields/widgets/contentbuilder.md
@@ -0,0 +1,31 @@
+# contentbuilder
+
+> Der ContentBuilder ist ein Drittanbieter-Produkt und steht nicht in jeder Lizenz zur Verfügung. Bitte kontaktieren Sie uns, wenn Sie Interesse an diesem Widget haben.
+
+Für die Gestaltung von HTML-Inhalten ist der ContentBuilder eine einfache und intuitive Lösung. Es sind Layout-Hilfmittel wie Spalten und Zeilen ebenso verfügbar, wie die Möglichkeit Dateien (Bilder, Video, Downloads) direkt in den HTML-Code einzubinden.
+
+Wie der ContentBuilder an einem Feld konfiguriert wird verdeutlicht folgendes Beispiel:
+
+!!!include(api/collections/fields/content.yml)!!!
+
+## Mediathek Kollektion
+
+Wie aus der obigen Definition unterhalb von z.B. "imageSelect" zu lesen, bedarf es einer eigenen Kollektion für Bilder und andere Dateien. Diese Kollektion könnte wie folgt aussehen:
+
+> Die Bedeutung der nicht beschriebenen Eigenschaften ist unter [collections](./../../../collections.md) beschrieben.
+
+!!!include(api/collections/medialib.yml)!!!
+
+## Module (customTags)
+
+Die Einbindung des konfigurierten Beispiel-Moduls aus obiger Definition erfolgt im ContentBuilder wie im folgenden Video zu sehen ist:
+
+
+
+Wie oben schon erwähnt, sind die `placeholder` frei wählbar. Eine HTML5-Schreibweise bietet sich aber sowohl für das Styling, als auch für die spätere Einbindung in ein Frontend an.
+
+In unserem Beispiel hier wurden zusättzlich zum eigentlichen Modul-Tag noch Attribute (`title` und `description`) definiert. Diese können dann im Frontend das eigentliche Modul beeinflussen.
+
+Im Frontend könnte ein Modul dann später als "Custom Element" implementiert werden oder es wird ein HTML-Parser verwendet, der die Tags durch eigene Komponenten ersetzt, wie er im Anhang [TODO] zu finden ist.
\ No newline at end of file
diff --git a/docs/projektkonfig/collections/validator.webm b/docs/projektkonfig/collections/validator.webm
new file mode 100644
index 0000000..6a34e05
Binary files /dev/null and b/docs/projektkonfig/collections/validator.webm differ
diff --git a/frontend/_dist_/empty b/frontend/_dist_/empty
new file mode 100644
index 0000000..e69de29