Files
DbFirst/DbFirst.API/Controllers/LayoutsController.cs
OlgunR d78fd5e3d1 Add user-specific persistent grid/band layouts support
Implemented user-customizable, persistent grid and band layouts for CatalogsGrid and MassDataGrid. Added backend API, database entity, and repository for storing layouts per user. Refactored grids to support dynamic band/column rendering, layout management UI, and per-user storage via localStorage and the new API. Registered all necessary services and updated data context. Enables flexible, user-specific grid experiences with saved layouts.
2026-02-06 14:07:52 +01:00

95 lines
3.2 KiB
C#

using System.Text;
using DbFirst.Application.Repositories;
using DbFirst.Domain.Entities;
using Microsoft.AspNetCore.Mvc;
namespace DbFirst.API.Controllers;
[ApiController]
[Route("api/[controller]")]
public class LayoutsController : ControllerBase
{
private readonly ILayoutRepository _repository;
public LayoutsController(ILayoutRepository repository)
{
_repository = repository;
}
[HttpGet]
public async Task<ActionResult<LayoutDto>> Get([FromQuery] string layoutType, [FromQuery] string layoutKey, [FromQuery] string userName, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(layoutType) || string.IsNullOrWhiteSpace(layoutKey) || string.IsNullOrWhiteSpace(userName))
{
return BadRequest("layoutType, layoutKey und userName sind erforderlich.");
}
var entity = await _repository.GetAsync(layoutType, layoutKey, userName, cancellationToken);
if (entity == null)
{
return NotFound();
}
return Ok(Map(entity));
}
[HttpPost]
public async Task<ActionResult<LayoutDto>> Upsert(LayoutDto dto, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(dto.LayoutType) || string.IsNullOrWhiteSpace(dto.LayoutKey) || string.IsNullOrWhiteSpace(dto.UserName))
{
return BadRequest("LayoutType, LayoutKey und UserName sind erforderlich.");
}
var data = string.IsNullOrWhiteSpace(dto.LayoutData)
? Array.Empty<byte>()
: Encoding.UTF8.GetBytes(dto.LayoutData);
try
{
var entity = await _repository.UpsertAsync(dto.LayoutType, dto.LayoutKey, dto.UserName, data, cancellationToken);
return Ok(Map(entity));
}
catch (Exception ex)
{
var detail = ex.InnerException?.Message ?? ex.Message;
return Problem(detail: detail, statusCode: StatusCodes.Status500InternalServerError);
}
}
[HttpDelete]
public async Task<IActionResult> Delete([FromQuery] string layoutType, [FromQuery] string layoutKey, [FromQuery] string userName, CancellationToken cancellationToken)
{
if (string.IsNullOrWhiteSpace(layoutType) || string.IsNullOrWhiteSpace(layoutKey) || string.IsNullOrWhiteSpace(userName))
{
return BadRequest("layoutType, layoutKey und userName sind erforderlich.");
}
var deleted = await _repository.DeleteAsync(layoutType, layoutKey, userName, cancellationToken);
return deleted ? NoContent() : NotFound();
}
private static LayoutDto Map(SmfLayout entity)
{
var layoutData = entity.LayoutData.Length == 0
? string.Empty
: Encoding.UTF8.GetString(entity.LayoutData);
return new LayoutDto
{
LayoutType = entity.LayoutType,
LayoutKey = entity.LayoutKey,
UserName = entity.UserName,
LayoutData = layoutData
};
}
public sealed class LayoutDto
{
public string LayoutType { get; set; } = string.Empty;
public string LayoutKey { get; set; } = string.Empty;
public string UserName { get; set; } = string.Empty;
public string LayoutData { get; set; } = string.Empty;
}
}