Add EditMarkup and SectionView/EditableText helpers for the editor
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
using System.Text.Encodings.Web;
|
||||
using Microsoft.AspNetCore.Html;
|
||||
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>
|
||||
/// Erzeugt die data-Attribute, an denen der Editor die bearbeitbaren Stellen
|
||||
/// erkennt. Ausserhalb des Edit-Modus kommt nichts zurueck, damit das Markup
|
||||
/// der oeffentlichen Seite unveraendert bleibt.
|
||||
/// (Razor laesst Attribute mit null-Wert nicht weg, deshalb dieser Weg.)
|
||||
/// </summary>
|
||||
public static class EditMarkup
|
||||
{
|
||||
private static readonly HtmlEncoder Encoder = HtmlEncoder.Default;
|
||||
|
||||
private static IHtmlContent Attributes(bool editMode, string markup) =>
|
||||
editMode ? new HtmlString(markup) : HtmlString.Empty;
|
||||
|
||||
/// <summary>Kennzeichnet einen Bereich.</summary>
|
||||
public static IHtmlContent Section(bool editMode, string name) =>
|
||||
Attributes(editMode, $"data-section=\"{Encoder.Encode(name)}\"");
|
||||
|
||||
/// <summary>
|
||||
/// Kennzeichnet ein bearbeitbares Textfeld. <paramref name="max"/> kommt aus
|
||||
/// <see cref="ContentLimits"/> und landet als data-max im Markup, wo es der
|
||||
/// Editor (page-editor.js) fuer den Live-Zaehler und die Eingabegrenze liest.
|
||||
/// </summary>
|
||||
public static IHtmlContent Field(bool editMode, string name, bool multiline = false, int? max = null) =>
|
||||
Attributes(editMode,
|
||||
$"data-field=\"{Encoder.Encode(name)}\"" +
|
||||
(multiline ? " data-multiline=\"true\"" : string.Empty) +
|
||||
(max.HasValue ? $" data-max=\"{max}\"" : string.Empty) +
|
||||
" contenteditable=\"true\"");
|
||||
|
||||
/// <summary>Macht ein Element bearbeitbar, ohne ihm ein eigenes Feld zuzuordnen.</summary>
|
||||
public static IHtmlContent Editable(bool editMode, int? max = null) =>
|
||||
Attributes(editMode,
|
||||
"contenteditable=\"true\"" + (max.HasValue ? $" data-max=\"{max}\"" : string.Empty));
|
||||
|
||||
/// <summary>Kennzeichnet einen Listencontainer.</summary>
|
||||
public static IHtmlContent List(bool editMode, string name) =>
|
||||
Attributes(editMode, $"data-list=\"{Encoder.Encode(name)}\"");
|
||||
|
||||
/// <summary>Kennzeichnet eine Liste aus reinen Texten.</summary>
|
||||
public static IHtmlContent StringList(bool editMode, string name) =>
|
||||
Attributes(editMode, $"data-list=\"{Encoder.Encode(name)}\" data-string-list=\"true\"");
|
||||
|
||||
/// <summary>Kennzeichnet einen Listeneintrag.</summary>
|
||||
public static IHtmlContent Item(bool editMode) =>
|
||||
Attributes(editMode, "data-item=\"true\"");
|
||||
|
||||
/// <summary>Kennzeichnet ein verschachteltes Objekt.</summary>
|
||||
public static IHtmlContent Object(bool editMode, string name) =>
|
||||
Attributes(editMode, $"data-object=\"{Encoder.Encode(name)}\"");
|
||||
|
||||
/// <summary>Kennzeichnet ein austauschbares Bild und haelt dessen gespeicherten Pfad fest.</summary>
|
||||
public static IHtmlContent Image(bool editMode, string name, string path) =>
|
||||
Attributes(editMode,
|
||||
$"data-image=\"{Encoder.Encode(name)}\" data-value=\"{Encoder.Encode(path ?? string.Empty)}\"");
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
namespace BewerbungsSeite.Models.SiteContent;
|
||||
|
||||
/// <summary>
|
||||
/// Modell eines Section-Partials: der Inhalt des Bereichs und die Angabe,
|
||||
/// ob die Seite im Bearbeitungsmodus gerendert wird. Dasselbe Partial wird
|
||||
/// so von der oeffentlichen Seite und von der Admin-Seite benutzt.
|
||||
/// </summary>
|
||||
public class SectionView<T>(T section, bool editMode)
|
||||
{
|
||||
public T Section { get; } = section;
|
||||
public bool EditMode { get; } = editMode;
|
||||
}
|
||||
|
||||
public static class SectionView
|
||||
{
|
||||
public static SectionView<T> For<T>(T section, bool editMode) => new(section, editMode);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ein Textstueck, das im Edit-Modus in ein bearbeitbares Element eingepackt wird
|
||||
/// und im normalen Modus als reiner Text erscheint. So bleibt das oeffentliche
|
||||
/// Markup unveraendert, auch wenn der Text mit anderen Elementen eine Zeile teilt.
|
||||
/// </summary>
|
||||
public class EditableText(string text, string field, bool editMode, int? max = null)
|
||||
{
|
||||
public string Text { get; } = text;
|
||||
public string Field { get; } = field;
|
||||
public bool EditMode { get; } = editMode;
|
||||
public int? Max { get; } = max;
|
||||
}
|
||||
Reference in New Issue
Block a user