Files

212 lines
6.5 KiB
C#

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NoticeBoard.Data;
using NoticeBoard.Models;
namespace NoticeBoard.Controllers;
[Authorize]
public class DevicesController : Controller
{
private readonly AppDbContext _db;
public DevicesController(AppDbContext db)
{
_db = db;
}
public async Task<IActionResult> Index()
{
var devices = await _db.Devices
.Include(d => d.DeviceSlides)
.OrderBy(d => d.Name)
.ToListAsync();
return View(devices);
}
public IActionResult Create()
{
return View(new Device());
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Device device)
{
if (string.IsNullOrWhiteSpace(device.Slug))
device.Slug = device.Name.ToLower().Replace(" ", "").Replace("-", "");
device.Slug = device.Slug.ToLower().Trim();
if (await _db.Devices.AnyAsync(d => d.Slug == device.Slug))
{
ModelState.AddModelError("Slug", "This slug is already in use.");
return View(device);
}
if (!ModelState.IsValid) return View(device);
device.CreatedAt = DateTime.UtcNow;
_db.Devices.Add(device);
await _db.SaveChangesAsync();
TempData["Success"] = $"Device '{device.Name}' created. URL: /{device.Slug}";
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> Edit(int id)
{
var device = await _db.Devices.FindAsync(id);
if (device == null) return NotFound();
return View(device);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, Device device)
{
if (id != device.Id) return NotFound();
device.Slug = device.Slug.ToLower().Trim();
if (await _db.Devices.AnyAsync(d => d.Slug == device.Slug && d.Id != id))
{
ModelState.AddModelError("Slug", "This slug is already in use.");
return View(device);
}
if (!ModelState.IsValid) return View(device);
var existing = await _db.Devices.FindAsync(id);
if (existing == null) return NotFound();
existing.Name = device.Name;
existing.Slug = device.Slug;
existing.ResolutionWidth = device.ResolutionWidth;
existing.ResolutionHeight = device.ResolutionHeight;
existing.Transition = device.Transition;
await _db.SaveChangesAsync();
TempData["Success"] = $"Device '{device.Name}' updated.";
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> Delete(int id)
{
var device = await _db.Devices
.Include(d => d.DeviceSlides)
.FirstOrDefaultAsync(d => d.Id == id);
if (device == null) return NotFound();
return View(device);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var device = await _db.Devices.FindAsync(id);
if (device == null) return NotFound();
_db.Devices.Remove(device);
await _db.SaveChangesAsync();
TempData["Success"] = $"Device '{device.Name}' deleted.";
return RedirectToAction(nameof(Index));
}
public async Task<IActionResult> Playlist(int id)
{
var device = await _db.Devices
.Include(d => d.DeviceSlides.OrderBy(ds => ds.DisplayOrder))
.ThenInclude(ds => ds.Slide)
.FirstOrDefaultAsync(d => d.Id == id);
if (device == null) return NotFound();
var assignedSlideIds = device.DeviceSlides.Select(ds => ds.SlideId).ToHashSet();
ViewBag.AvailableSlides = await _db.Slides
.Where(s => !assignedSlideIds.Contains(s.Id))
.OrderBy(s => s.Name)
.ToListAsync();
return View(device);
}
[HttpPost]
public async Task<IActionResult> AddToPlaylist(int id, int slideId, int durationSeconds = 30)
{
var device = await _db.Devices.Include(d => d.DeviceSlides).FirstOrDefaultAsync(d => d.Id == id);
if (device == null) return NotFound();
var maxOrder = device.DeviceSlides.Any() ? device.DeviceSlides.Max(ds => ds.DisplayOrder) : 0;
var ds = new DeviceSlide
{
DeviceId = id,
SlideId = slideId,
DisplayOrder = maxOrder + 1,
DurationSeconds = durationSeconds,
Enabled = true
};
_db.DeviceSlides.Add(ds);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Playlist), new { id });
}
[HttpPost]
public async Task<IActionResult> RemoveFromPlaylist(int id, int deviceSlideId)
{
var ds = await _db.DeviceSlides.FindAsync(deviceSlideId);
if (ds == null) return NotFound();
_db.DeviceSlides.Remove(ds);
await _db.SaveChangesAsync();
return RedirectToAction(nameof(Playlist), new { id });
}
[HttpPost]
public async Task<IActionResult> ReorderPlaylist([FromBody] ReorderRequest request)
{
if (request?.ItemIds == null) return BadRequest();
var deviceSlides = await _db.DeviceSlides
.Where(ds => request.ItemIds.Contains(ds.Id))
.ToListAsync();
for (int i = 0; i < request.ItemIds.Length; i++)
{
var ds = deviceSlides.FirstOrDefault(x => x.Id == request.ItemIds[i]);
if (ds != null) ds.DisplayOrder = i + 1;
}
await _db.SaveChangesAsync();
return Ok();
}
[HttpPost]
public async Task<IActionResult> UpdateDuration([FromBody] UpdateDurationRequest request)
{
var ds = await _db.DeviceSlides.FindAsync(request.DeviceSlideId);
if (ds == null) return NotFound();
ds.DurationSeconds = request.DurationSeconds;
await _db.SaveChangesAsync();
return Ok();
}
[HttpPost]
public async Task<IActionResult> ToggleEnabled([FromBody] ToggleEnabledRequest request)
{
var ds = await _db.DeviceSlides.FindAsync(request.DeviceSlideId);
if (ds == null) return NotFound();
ds.Enabled = request.Enabled;
await _db.SaveChangesAsync();
return Ok();
}
}
public class ReorderRequest { public int[]? ItemIds { get; set; } }
public class UpdateDurationRequest { public int DeviceSlideId { get; set; } public int DurationSeconds { get; set; } }
public class ToggleEnabledRequest { public int DeviceSlideId { get; set; } public bool Enabled { get; set; } }