212 lines
6.5 KiB
C#
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; } }
|