feat(admin): manually edit scene inputs (content elements)
Scene content elements (the editable Text/Media/Color/… inputs inside a scene) had no CRUD — only AEP-import created them, so admins couldn't define or edit them. Added full management: content-svc: - SceneElementsController: GET/POST/PUT/DELETE /v1/scene-elements?scene_id= - SceneColorService: Get/Create/Update/DeleteContentElementAsync - ContentElementResponse + SaveContentElementRequest (key, title, type, default_value, hint, position, text-box/font/media flags) gateway: route /v1/scene-elements/*path → content frontend: SceneColorEditor scenes tab → per-scene "ورودیها" expander with full add/edit/delete of inputs (15 element types: Text/Media/Color/Number/…) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -174,6 +174,63 @@ public class SceneColorService(ContentDbContext db)
|
||||
p.Items.OrderBy(i => i.Sort).Select(i => new ColorPresetItemResponse(i.Id, i.ElementKey, i.Value, i.Sort)).ToList()))
|
||||
.FirstAsync();
|
||||
|
||||
// ── Scene content elements (editable inputs) ────────────────────────────
|
||||
|
||||
public async Task<List<ContentElementResponse>> GetContentElementsAsync(Guid sceneId) =>
|
||||
await db.SceneContentElements.Where(e => e.SceneId == sceneId)
|
||||
.OrderBy(e => e.PositionInContainer)
|
||||
.Select(e => ToElementResponse(e)).ToListAsync();
|
||||
|
||||
public async Task<ContentElementResponse> CreateContentElementAsync(SaveContentElementRequest req)
|
||||
{
|
||||
var e = new SceneContentElement { SceneId = req.SceneId };
|
||||
ApplyElement(e, req);
|
||||
db.SceneContentElements.Add(e);
|
||||
await db.SaveChangesAsync();
|
||||
return ToElementResponse(e);
|
||||
}
|
||||
|
||||
public async Task<ContentElementResponse> UpdateContentElementAsync(Guid id, SaveContentElementRequest req)
|
||||
{
|
||||
var e = await db.SceneContentElements.FindAsync(id)
|
||||
?? throw new KeyNotFoundException($"Element {id} not found");
|
||||
ApplyElement(e, req);
|
||||
await db.SaveChangesAsync();
|
||||
return ToElementResponse(e);
|
||||
}
|
||||
|
||||
public async Task DeleteContentElementAsync(Guid id)
|
||||
{
|
||||
var e = await db.SceneContentElements.FindAsync(id)
|
||||
?? throw new KeyNotFoundException($"Element {id} not found");
|
||||
db.SceneContentElements.Remove(e);
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
private static void ApplyElement(SceneContentElement e, SaveContentElementRequest req)
|
||||
{
|
||||
e.Key = req.Key;
|
||||
e.Title = req.Title;
|
||||
e.Hint = req.Hint;
|
||||
e.Type = Enum.TryParse<ContentElementType>(req.Type, true, out var t) ? t : ContentElementType.Text;
|
||||
e.DefaultValue = req.DefaultValue;
|
||||
e.PositionInContainer = req.PositionInContainer;
|
||||
e.IsTextBox = req.IsTextBox;
|
||||
e.MaxSize = req.MaxSize;
|
||||
e.FontSize = req.FontSize;
|
||||
e.IsFontChangeable = req.IsFontChangeable;
|
||||
e.IsFontSizeChangeable = req.IsFontSizeChangeable;
|
||||
e.VideoSupport = req.VideoSupport;
|
||||
e.Width = req.Width;
|
||||
e.Height = req.Height;
|
||||
e.Thumbnail = req.Thumbnail;
|
||||
}
|
||||
|
||||
private static ContentElementResponse ToElementResponse(SceneContentElement e) => new(
|
||||
e.Id, e.SceneId, e.Key, e.Title, e.Hint, e.Type.ToString(), e.DefaultValue,
|
||||
e.PositionInContainer, e.IsTextBox, e.MaxSize, e.FontSize, e.IsFontChangeable,
|
||||
e.IsFontSizeChangeable, e.VideoSupport, e.Width, e.Height, e.Thumbnail);
|
||||
|
||||
// ── helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
private static SceneResponse ToSceneResponse(Scene s) => new(
|
||||
|
||||
Reference in New Issue
Block a user