diff --git a/Moonlight.Api/Http/Controllers/Admin/ThemesController.cs b/Moonlight.Api/Http/Controllers/Admin/Themes/ThemesController.cs similarity index 98% rename from Moonlight.Api/Http/Controllers/Admin/ThemesController.cs rename to Moonlight.Api/Http/Controllers/Admin/Themes/ThemesController.cs index 8c9b08e9..ef8bac6a 100644 --- a/Moonlight.Api/Http/Controllers/Admin/ThemesController.cs +++ b/Moonlight.Api/Http/Controllers/Admin/Themes/ThemesController.cs @@ -11,7 +11,7 @@ using Moonlight.Shared.Http.Requests.Admin.Themes; using Moonlight.Shared.Http.Responses; using Moonlight.Shared.Http.Responses.Admin.Themes; -namespace Moonlight.Api.Http.Controllers.Admin; +namespace Moonlight.Api.Http.Controllers.Admin.Themes; [ApiController] [Route("api/admin/themes")] diff --git a/Moonlight.Api/Http/Controllers/Admin/Themes/TransferController.cs b/Moonlight.Api/Http/Controllers/Admin/Themes/TransferController.cs new file mode 100644 index 00000000..448aba94 --- /dev/null +++ b/Moonlight.Api/Http/Controllers/Admin/Themes/TransferController.cs @@ -0,0 +1,76 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Moonlight.Api.Database; +using Moonlight.Api.Database.Entities; +using Moonlight.Api.Mappers; +using Moonlight.Api.Models; +using Moonlight.Shared; +using Moonlight.Shared.Http.Responses.Admin.Themes; +using VYaml.Serialization; + +namespace Moonlight.Api.Http.Controllers.Admin.Themes; + +[ApiController] +[Route("api/admin/themes")] +[Authorize(Policy = Permissions.Themes.View)] +public class TransferController : Controller +{ + private readonly DatabaseRepository ThemeRepository; + + public TransferController(DatabaseRepository themeRepository) + { + ThemeRepository = themeRepository; + } + + [HttpGet("{id:int}/export")] + public async Task ExportAsync([FromRoute] int id) + { + var theme = await ThemeRepository + .Query() + .FirstOrDefaultAsync(x => x.Id == id); + + if (theme == null) + return Problem("No theme with that id found", statusCode: 404); + + var yml = YamlSerializer.Serialize(new ThemeTransferModel() + { + Name = theme.Name, + Author = theme.Author, + CssContent = theme.CssContent, + Version = theme.Version + }); + + return File(yml.ToArray(), "text/yaml", $"{theme.Name}.yml"); + } + + [HttpPost("import")] + public async Task> ImportAsync() + { + var themeToImport = await YamlSerializer.DeserializeAsync(Request.Body); + + var existingTheme = await ThemeRepository + .Query() + .FirstOrDefaultAsync(x => x.Name == themeToImport.Name && x.Author == themeToImport.Author); + + if (existingTheme == null) + { + var finalTheme = await ThemeRepository.AddAsync(new Theme() + { + Name = themeToImport.Name, + Author = themeToImport.Author, + CssContent = themeToImport.CssContent, + Version = themeToImport.Version + }); + + return ThemeMapper.ToDto(finalTheme); + } + + existingTheme.CssContent = themeToImport.CssContent; + existingTheme.Version = themeToImport.Version; + + await ThemeRepository.UpdateAsync(existingTheme); + + return ThemeMapper.ToDto(existingTheme); + } +} \ No newline at end of file diff --git a/Moonlight.Api/Models/ThemeTransferModel.cs b/Moonlight.Api/Models/ThemeTransferModel.cs new file mode 100644 index 00000000..af816550 --- /dev/null +++ b/Moonlight.Api/Models/ThemeTransferModel.cs @@ -0,0 +1,12 @@ +using VYaml.Annotations; + +namespace Moonlight.Api.Models; + +[YamlObject] +public partial class ThemeTransferModel +{ + public string Name { get; set; } + public string Version { get; set; } + public string Author { get; set; } + public string CssContent { get; set; } +} \ No newline at end of file diff --git a/Moonlight.Api/Moonlight.Api.csproj b/Moonlight.Api/Moonlight.Api.csproj index a4ed8ba1..9d1fc83a 100644 --- a/Moonlight.Api/Moonlight.Api.csproj +++ b/Moonlight.Api/Moonlight.Api.csproj @@ -30,6 +30,7 @@ + diff --git a/Moonlight.Frontend/UI/Admin/Views/Sys/Themes/Index.razor b/Moonlight.Frontend/UI/Admin/Views/Sys/Themes/Index.razor index c90c0dfd..d8683e27 100644 --- a/Moonlight.Frontend/UI/Admin/Views/Sys/Themes/Index.razor +++ b/Moonlight.Frontend/UI/Admin/Views/Sys/Themes/Index.razor @@ -18,6 +18,8 @@ @inject IAuthorizationService AuthorizationService @inject HttpClient HttpClient +