diff --git a/src/BackOffice/BackOffice.csproj b/src/BackOffice/BackOffice.csproj index 4511f4e..1e007e9 100644 --- a/src/BackOffice/BackOffice.csproj +++ b/src/BackOffice/BackOffice.csproj @@ -138,7 +138,7 @@ - + diff --git a/src/BackOffice/Common/Configure/ConfigureService.cs b/src/BackOffice/Common/Configure/ConfigureService.cs index ee4b7b3..70ee6b6 100644 --- a/src/BackOffice/Common/Configure/ConfigureService.cs +++ b/src/BackOffice/Common/Configure/ConfigureService.cs @@ -27,6 +27,7 @@ using CMSMicroservice.Protobuf.Protos.BlogPost; using CMSMicroservice.Protobuf.Protos.BlogCategory; using CMSMicroservice.Protobuf.Protos.BlogPostImage; using CMSMicroservice.Protobuf.Protos.SitePage; +using CMSMicroservice.Protobuf.Protos.SitePageSettings; using CMSMicroservice.Protobuf.Protos.UserContract; using CMSMicroservice.Protobuf.Protos.UserWallet; using CMSMicroservice.Protobuf.Protos.UserWalletChangeLog; @@ -91,6 +92,7 @@ public static class ConfigureServices services.AddScoped(); services.AddScoped(); services.AddScoped(); + services.AddScoped(); return services; } @@ -158,6 +160,7 @@ public static class ConfigureServices services.AddTransient(sp => new BlogCategoryContract.BlogCategoryContractClient(sp.GetRequiredService())); services.AddTransient(sp => new BlogPostImageContract.BlogPostImageContractClient(sp.GetRequiredService())); services.AddTransient(sp => new SitePageContract.SitePageContractClient(sp.GetRequiredService())); + services.AddTransient(sp => new SitePageSettingsContract.SitePageSettingsContractClient(sp.GetRequiredService())); // User Contracts Service services.AddTransient(sp => new UserContractContract.UserContractContractClient(sp.GetRequiredService())); diff --git a/src/BackOffice/Pages/Content/Components/PageImageEditDialog.razor b/src/BackOffice/Pages/Content/Components/PageImageEditDialog.razor new file mode 100644 index 0000000..5882f8f --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/PageImageEditDialog.razor @@ -0,0 +1,100 @@ +@using BackOffice.Services.Content +@using Microsoft.AspNetCore.Components.Forms +@using BackOffice.Common.BaseComponents + + + + + + + + @foreach (var group in GetAvailableGroups()) + { + @group.Value + } + + + + + + + + + + + + + + + تصویر + + @if (!string.IsNullOrWhiteSpace(_imagePreview)) + { + + } + else if (!string.IsNullOrEmpty(ExistingImagePath)) + { + + } + else + { + + تصویری انتخاب نشده است + + } + + + + + انتخاب تصویر + + + + @if (context != null) + { + @context.Name + } + + + + + + + فعال + + + + + + + @(IsNew ? "افزودن" : "ذخیره تغییرات") + + + انصراف + + + diff --git a/src/BackOffice/Pages/Content/Components/PageImageEditDialog.razor.cs b/src/BackOffice/Pages/Content/Components/PageImageEditDialog.razor.cs new file mode 100644 index 0000000..38937df --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/PageImageEditDialog.razor.cs @@ -0,0 +1,112 @@ +using BackOffice.Services.Content; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using MudBlazor; + +namespace BackOffice.Pages.Content.Components; + +public partial class PageImageEditDialog +{ + [CascadingParameter] IMudDialogInstance DialogInstance { get; set; } = default!; + [Inject] public ISitePageSettingsService PageSettingsService { get; set; } = default!; + + [Parameter] public SavePageImageDto Model { get; set; } = new(); + [Parameter] public string PageKey { get; set; } = string.Empty; + [Parameter] public bool IsNew { get; set; } + [Parameter] public string? ExistingImagePath { get; set; } + + private MudForm? _form; + private bool _isValid = true; + private bool _loading; + + private IBrowserFile? _imageFile; + private byte[]? _imageBuffer; + private string? _imagePreview; + private readonly long _maxAllowedSize = (1024 * 1024) * 5; + + private async Task OnImageSelected(IBrowserFile? file) + { + _imageFile = file; + if (file != null) + { + using var ms = new MemoryStream(); + await file.OpenReadStream(_maxAllowedSize).CopyToAsync(ms); + _imageBuffer = ms.ToArray(); + _imagePreview = $"data:{file.ContentType};base64," + Convert.ToBase64String(_imageBuffer); + StateHasChanged(); + } + } + + private async Task SubmitAsync() + { + if (_form != null) + { + await _form.Validate(); + if (!_isValid) return; + } + + _loading = true; + + if (_imageFile != null && _imageBuffer != null) + { + Model.ImageFile = _imageBuffer; + Model.ImageMime = _imageFile.ContentType; + Model.ImageFileName = Path.GetFileNameWithoutExtension(_imageFile.Name); + } + else if (IsNew && _imageBuffer == null) + { + Snackbar.Add("لطفاً یک تصویر انتخاب کنید", Severity.Warning); + _loading = false; + return; + } + + try + { + var result = await PageSettingsService.SaveImageAsync(Model); + if (result.Success) + { + DialogInstance.Close(DialogResult.Ok(true)); + } + else + { + Snackbar.Add("خطا در ذخیره تصویر", Severity.Error); + } + } + catch (Exception ex) + { + Snackbar.Add($"خطا: {ex.Message}", Severity.Error); + } + finally + { + _loading = false; + } + } + + private Dictionary GetAvailableGroups() => PageKey switch + { + "about" => new Dictionary + { + { "team", "اعضای تیم" }, + { "values", "ارزش‌ها" } + }, + "licenses" => new Dictionary + { + { "licenses", "مجوزها" } + }, + "landing" => new Dictionary + { + { "values", "ارزش‌ها" } + }, + _ => new Dictionary + { + { "values", "ارزش‌ها" }, + { "team", "اعضای تیم" }, + { "licenses", "مجوزها" } + } + }; + + private void Cancel() + { + DialogInstance.Cancel(); + } +} diff --git a/src/BackOffice/Pages/Content/Components/PageImagesDialog.razor b/src/BackOffice/Pages/Content/Components/PageImagesDialog.razor new file mode 100644 index 0000000..943caba --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/PageImagesDialog.razor @@ -0,0 +1,88 @@ +@using BackOffice.Services.Content +@using BackOffice.Common.BaseComponents + + + + + + تصاویر صفحه «@PageTitle» + + افزودن تصویر + + + + @if (!Images.Any()) + { + + تصویری ثبت نشده است. + + } + else + { + + + + + @if (!string.IsNullOrWhiteSpace(context.Item.ThumbnailPath)) + { + + } + else if (!string.IsNullOrWhiteSpace(context.Item.ImagePath)) + { + + } + else + { + + } + + + + + + + + + @(context.Item.IsActive ? "فعال" : "غیرفعال") + + + + + + + + + + + + + + + + + + } + + + + + بستن + + + diff --git a/src/BackOffice/Pages/Content/Components/PageImagesDialog.razor.cs b/src/BackOffice/Pages/Content/Components/PageImagesDialog.razor.cs new file mode 100644 index 0000000..4ba787c --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/PageImagesDialog.razor.cs @@ -0,0 +1,133 @@ +using BackOffice.Services.Content; +using Microsoft.AspNetCore.Components; +using MudBlazor; + +namespace BackOffice.Pages.Content.Components; + +public partial class PageImagesDialog +{ + [CascadingParameter] IMudDialogInstance DialogInstance { get; set; } = default!; + [Inject] public ISitePageSettingsService PageSettingsService { get; set; } = default!; + + [Parameter] public long PageId { get; set; } + [Parameter] public string PageKey { get; set; } = string.Empty; + [Parameter] public string PageTitle { get; set; } = string.Empty; + [Parameter] public List Images { get; set; } = new(); + + private bool _hasChanges; + + private async Task AddImage() + { + var dto = new SavePageImageDto + { + SitePageSettingsId = PageId, + ImageGroup = GetDefaultImageGroup(), + IsActive = true, + SortOrder = Images.Count + 1 + }; + + var parameters = new DialogParameters + { + { nameof(PageImageEditDialog.Model), dto }, + { nameof(PageImageEditDialog.PageKey), PageKey }, + { nameof(PageImageEditDialog.IsNew), true } + }; + + var dialog = await DialogService.ShowAsync( + "افزودن تصویر", parameters, + new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Medium, FullWidth = true }); + + var result = await dialog.Result; + if (result is { Canceled: false }) + { + Snackbar.Add("تصویر با موفقیت اضافه شد", Severity.Success); + _hasChanges = true; + await ReloadImages(); + } + } + + private async Task EditImage(PageImageItemDto item) + { + var dto = new SavePageImageDto + { + Id = item.Id, + SitePageSettingsId = PageId, + ImageGroup = item.ImageGroup, + Title = item.Title, + Subtitle = item.Subtitle, + Description = item.Description, + LinkUrl = item.LinkUrl, + IconName = item.IconName, + SortOrder = item.SortOrder, + IsActive = item.IsActive + }; + + var parameters = new DialogParameters + { + { nameof(PageImageEditDialog.Model), dto }, + { nameof(PageImageEditDialog.PageKey), PageKey }, + { nameof(PageImageEditDialog.IsNew), false }, + { nameof(PageImageEditDialog.ExistingImagePath), item.ImagePath } + }; + + var dialog = await DialogService.ShowAsync( + "ویرایش تصویر", parameters, + new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Medium, FullWidth = true }); + + var result = await dialog.Result; + if (result is { Canceled: false }) + { + Snackbar.Add("تصویر با موفقیت ویرایش شد", Severity.Success); + _hasChanges = true; + await ReloadImages(); + } + } + + private async Task DeleteImage(PageImageItemDto item) + { + var confirm = await DialogService.ShowMessageBox( + "تایید حذف", + $"آیا از حذف تصویر «{item.Title ?? item.ImageGroup}» اطمینان دارید؟", + yesText: "بله، حذف شود", + cancelText: "انصراف"); + + if (confirm != true) return; + + try + { + await PageSettingsService.DeleteImageAsync(item.Id); + Snackbar.Add("تصویر با موفقیت حذف شد", Severity.Success); + _hasChanges = true; + await ReloadImages(); + } + catch (Exception ex) + { + Snackbar.Add($"خطا در حذف تصویر: {ex.Message}", Severity.Error); + } + } + + private async Task ReloadImages() + { + var details = await PageSettingsService.GetByKeyAsync(PageKey); + if (details != null) + { + Images = details.Images; + StateHasChanged(); + } + } + + private string GetDefaultImageGroup() => PageKey switch + { + "about" => "team", + "licenses" => "licenses", + _ => "values" + }; + + private void Close() + { + if (_hasChanges) + DialogInstance.Close(DialogResult.Ok(true)); + else + DialogInstance.Cancel(); + } +} diff --git a/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor b/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor new file mode 100644 index 0000000..899e7be --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor @@ -0,0 +1,88 @@ +@using BackOffice.Services.Content +@using Microsoft.AspNetCore.Components.Forms +@using BackOffice.Common.BaseComponents + + + + + + + + + + + + + + تصویر هیرو + + @if (!string.IsNullOrWhiteSpace(_imagePreview)) + { + + } + else if (!string.IsNullOrEmpty(ExistingHeroImagePath)) + { + + } + else + { + + تصویری انتخاب نشده است + + } + + + + + انتخاب تصویر هیرو + + + + @if (context != null) + { + @context.Name + } + + + + + + + تنظیمات اختصاصی (JSON) + + + + + فعال + + + + + + + ذخیره تغییرات + + + انصراف + + + diff --git a/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor.cs b/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor.cs new file mode 100644 index 0000000..028a351 --- /dev/null +++ b/src/BackOffice/Pages/Content/Components/PageSettingsEditDialog.razor.cs @@ -0,0 +1,82 @@ +using BackOffice.Services.Content; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Forms; +using MudBlazor; + +namespace BackOffice.Pages.Content.Components; + +public partial class PageSettingsEditDialog +{ + [CascadingParameter] IMudDialogInstance DialogInstance { get; set; } = default!; + [Inject] public ISitePageSettingsService PageSettingsService { get; set; } = default!; + + [Parameter] public SavePageSettingsDto Model { get; set; } = new(); + [Parameter] public string? ExistingHeroImagePath { get; set; } + [Parameter] public string PageTitle { get; set; } = string.Empty; + + private MudForm? _form; + private bool _isValid = true; + private bool _loading; + + private IBrowserFile? _imageFile; + private byte[]? _imageBuffer; + private string? _imagePreview; + private readonly long _maxAllowedSize = (1024 * 1024) * 5; + + private async Task OnImageSelected(IBrowserFile? file) + { + _imageFile = file; + if (file != null) + { + using var ms = new MemoryStream(); + await file.OpenReadStream(_maxAllowedSize).CopyToAsync(ms); + _imageBuffer = ms.ToArray(); + _imagePreview = $"data:{file.ContentType};base64," + Convert.ToBase64String(_imageBuffer); + StateHasChanged(); + } + } + + private async Task SubmitAsync() + { + if (_form != null) + { + await _form.Validate(); + if (!_isValid) return; + } + + _loading = true; + + if (_imageFile != null && _imageBuffer != null) + { + Model.ImageFile = _imageBuffer; + Model.ImageMime = _imageFile.ContentType; + Model.ImageFileName = Path.GetFileNameWithoutExtension(_imageFile.Name); + } + + try + { + var result = await PageSettingsService.SaveSettingsAsync(Model); + if (result.Success) + { + DialogInstance.Close(DialogResult.Ok(true)); + } + else + { + Snackbar.Add("خطا در ذخیره تنظیمات", Severity.Error); + } + } + catch (Exception ex) + { + Snackbar.Add($"خطا: {ex.Message}", Severity.Error); + } + finally + { + _loading = false; + } + } + + private void Cancel() + { + DialogInstance.Cancel(); + } +} diff --git a/src/BackOffice/Pages/Content/PageSettingsManagementPage.razor b/src/BackOffice/Pages/Content/PageSettingsManagementPage.razor new file mode 100644 index 0000000..8a99432 --- /dev/null +++ b/src/BackOffice/Pages/Content/PageSettingsManagementPage.razor @@ -0,0 +1,74 @@ +@page "/content/page-settings" + +@using BackOffice.Services.Content + +@inject ISitePageSettingsService PageSettingsService + +
+ + مدیریت تنظیمات صفحات + تنظیمات ۴ صفحه ثابت سایت: صفحه اصلی، درباره ما، تماس با ما و مجوزها + + @if (_loading) + { + + } + else + { + + @foreach (var item in _pages) + { + + + + + + + + @item.Title + @item.PageKey + + + + + + @(item.IsActive ? "فعال" : "غیرفعال") + + + + + + + + @item.ImageCount تصویر + + + آخرین ویرایش: @item.LastModified.MiladiToJalaliWithTime() + + + + + + ویرایش + + + تصاویر + + + + + } + + } + +
diff --git a/src/BackOffice/Pages/Content/PageSettingsManagementPage.razor.cs b/src/BackOffice/Pages/Content/PageSettingsManagementPage.razor.cs new file mode 100644 index 0000000..6c77e93 --- /dev/null +++ b/src/BackOffice/Pages/Content/PageSettingsManagementPage.razor.cs @@ -0,0 +1,119 @@ +using BackOffice.Services.Content; +using BackOffice.Pages.Content.Components; +using Microsoft.AspNetCore.Components; +using MudBlazor; + +namespace BackOffice.Pages.Content; + +public partial class PageSettingsManagementPage +{ + private List _pages = new(); + private bool _loading = true; + + protected override async Task OnInitializedAsync() + { + await LoadPagesAsync(); + } + + private async Task LoadPagesAsync() + { + _loading = true; + try + { + _pages = await PageSettingsService.GetAllAsync(); + } + catch (Exception ex) + { + Snackbar.Add($"خطا در دریافت صفحات: {ex.Message}", Severity.Error); + } + finally + { + _loading = false; + } + } + + private async Task EditPageSettings(PageSettingsSummaryDto summary) + { + var details = await PageSettingsService.GetByKeyAsync(summary.PageKey); + if (details == null) + { + Snackbar.Add("خطا در دریافت تنظیمات صفحه", Severity.Error); + return; + } + + var dto = new SavePageSettingsDto + { + PageKey = details.PageKey, + Title = details.Title, + MetaDescription = details.MetaDescription, + HeroTitle = details.HeroTitle, + HeroSubtitle = details.HeroSubtitle, + IsActive = details.IsActive, + SettingsJson = details.SettingsJson + }; + + var parameters = new DialogParameters + { + { nameof(PageSettingsEditDialog.Model), dto }, + { nameof(PageSettingsEditDialog.ExistingHeroImagePath), details.HeroImagePath }, + { nameof(PageSettingsEditDialog.PageTitle), GetPageDisplayName(summary.PageKey) } + }; + + var dialog = await DialogService.ShowAsync( + $"ویرایش تنظیمات «{GetPageDisplayName(summary.PageKey)}»", parameters, + new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Medium, FullWidth = true }); + + var result = await dialog.Result; + if (result is { Canceled: false }) + { + Snackbar.Add("تنظیمات صفحه با موفقیت ذخیره شد", Severity.Success); + await LoadPagesAsync(); + } + } + + private async Task ManageImages(PageSettingsSummaryDto summary) + { + var details = await PageSettingsService.GetByKeyAsync(summary.PageKey); + if (details == null) + { + Snackbar.Add("خطا در دریافت اطلاعات صفحه", Severity.Error); + return; + } + + var parameters = new DialogParameters + { + { nameof(PageImagesDialog.PageId), details.Id }, + { nameof(PageImagesDialog.PageKey), details.PageKey }, + { nameof(PageImagesDialog.PageTitle), GetPageDisplayName(summary.PageKey) }, + { nameof(PageImagesDialog.Images), details.Images } + }; + + var dialog = await DialogService.ShowAsync( + $"مدیریت تصاویر «{GetPageDisplayName(summary.PageKey)}»", parameters, + new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Large, FullWidth = true }); + + var result = await dialog.Result; + if (result is { Canceled: false }) + { + await LoadPagesAsync(); + } + } + + private static string GetPageIcon(string pageKey) => pageKey switch + { + "landing" => Icons.Material.Filled.Home, + "about" => Icons.Material.Filled.Info, + "contact" => Icons.Material.Filled.ContactMail, + "licenses" => Icons.Material.Filled.VerifiedUser, + _ => Icons.Material.Filled.Article + }; + + private static string GetPageDisplayName(string pageKey) => pageKey switch + { + "landing" => "صفحه اصلی", + "about" => "درباره ما", + "contact" => "تماس با ما", + "licenses" => "مجوزها", + _ => pageKey + }; +} diff --git a/src/BackOffice/Services/Content/ISitePageSettingsService.cs b/src/BackOffice/Services/Content/ISitePageSettingsService.cs new file mode 100644 index 0000000..dca372c --- /dev/null +++ b/src/BackOffice/Services/Content/ISitePageSettingsService.cs @@ -0,0 +1,96 @@ +namespace BackOffice.Services.Content; + +public interface ISitePageSettingsService +{ + Task> GetAllAsync(); + Task GetByKeyAsync(string pageKey); + Task SaveSettingsAsync(SavePageSettingsDto dto); + Task SaveImageAsync(SavePageImageDto dto); + Task DeleteImageAsync(long id); +} + +// ── Summary DTO (لیست صفحات) ── +public class PageSettingsSummaryDto +{ + public long Id { get; set; } + public string PageKey { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public bool IsActive { get; set; } + public int ImageCount { get; set; } + public DateTime LastModified { get; set; } +} + +// ── Details DTO (تنظیمات کامل + تصاویر) ── +public class PageSettingsDetailsDto +{ + public long Id { get; set; } + public string PageKey { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public string? MetaDescription { get; set; } + public string? HeroTitle { get; set; } + public string? HeroSubtitle { get; set; } + public string? HeroImagePath { get; set; } + public bool IsActive { get; set; } + public string? SettingsJson { get; set; } + public List Images { get; set; } = new(); +} + +// ── Image Item DTO ── +public class PageImageItemDto +{ + public long Id { get; set; } + public string ImageGroup { get; set; } = string.Empty; + public string? Title { get; set; } + public string? Subtitle { get; set; } + public string? Description { get; set; } + public string ImagePath { get; set; } = string.Empty; + public string? ThumbnailPath { get; set; } + public string? LinkUrl { get; set; } + public string? IconName { get; set; } + public int SortOrder { get; set; } + public bool IsActive { get; set; } +} + +// ── Save Settings DTO ── +public class SavePageSettingsDto +{ + public string PageKey { get; set; } = string.Empty; + public string Title { get; set; } = string.Empty; + public string? MetaDescription { get; set; } + public string? HeroTitle { get; set; } + public string? HeroSubtitle { get; set; } + public bool IsActive { get; set; } = true; + public string? SettingsJson { get; set; } + + // Hero image upload + public byte[]? ImageFile { get; set; } + public string? ImageMime { get; set; } + public string? ImageFileName { get; set; } +} + +// ── Save Image DTO ── +public class SavePageImageDto +{ + public long Id { get; set; } // 0 = جدید + public long SitePageSettingsId { get; set; } + public string ImageGroup { get; set; } = string.Empty; + public string? Title { get; set; } + public string? Subtitle { get; set; } + public string? Description { get; set; } + public string? LinkUrl { get; set; } + public string? IconName { get; set; } + public int SortOrder { get; set; } + public bool IsActive { get; set; } = true; + + // Image upload + public byte[]? ImageFile { get; set; } + public string? ImageMime { get; set; } + public string? ImageFileName { get; set; } +} + +// ── Save Result ── +public class SaveResultDto +{ + public long Id { get; set; } + public bool Success { get; set; } +} diff --git a/src/BackOffice/Services/Content/SitePageSettingsService.cs b/src/BackOffice/Services/Content/SitePageSettingsService.cs new file mode 100644 index 0000000..40f94f4 --- /dev/null +++ b/src/BackOffice/Services/Content/SitePageSettingsService.cs @@ -0,0 +1,131 @@ +using CMSMicroservice.Protobuf.Protos.SitePageSettings; + +namespace BackOffice.Services.Content; + +public class SitePageSettingsService : ISitePageSettingsService +{ + private readonly SitePageSettingsContract.SitePageSettingsContractClient _client; + + public SitePageSettingsService(SitePageSettingsContract.SitePageSettingsContractClient client) + { + _client = client; + } + + public async Task> GetAllAsync() + { + var response = await _client.GetAllPageSettingsAsync(new GetAllPageSettingsRequest()); + + return response.Pages.Select(m => new PageSettingsSummaryDto + { + Id = m.Id, + PageKey = m.PageKey, + Title = m.Title, + IsActive = m.IsActive, + ImageCount = m.ImageCount, + LastModified = m.LastModified?.ToDateTime() ?? DateTime.MinValue + }).ToList(); + } + + public async Task GetByKeyAsync(string pageKey) + { + var response = await _client.GetPageSettingsAsync( + new GetPageSettingsRequest { PageKey = pageKey }); + + if (response == null || response.Id <= 0) return null; + + var dto = new PageSettingsDetailsDto + { + Id = response.Id, + PageKey = response.PageKey, + Title = response.Title, + MetaDescription = response.MetaDescription, + HeroTitle = response.HeroTitle, + HeroSubtitle = response.HeroSubtitle, + HeroImagePath = response.HeroImagePath, + IsActive = response.IsActive, + SettingsJson = response.SettingsJson + }; + + foreach (var img in response.Images) + { + dto.Images.Add(new PageImageItemDto + { + Id = img.Id, + ImageGroup = img.ImageGroup, + Title = img.Title, + Subtitle = img.Subtitle, + Description = img.Description, + ImagePath = img.ImagePath, + ThumbnailPath = img.ThumbnailPath, + LinkUrl = img.LinkUrl, + IconName = img.IconName, + SortOrder = img.SortOrder, + IsActive = img.IsActive + }); + } + + return dto; + } + + public async Task SaveSettingsAsync(SavePageSettingsDto dto) + { + var request = new SavePageSettingsRequest + { + PageKey = dto.PageKey, + Title = dto.Title, + MetaDescription = dto.MetaDescription ?? string.Empty, + HeroTitle = dto.HeroTitle ?? string.Empty, + HeroSubtitle = dto.HeroSubtitle ?? string.Empty, + IsActive = dto.IsActive, + SettingsJson = dto.SettingsJson ?? string.Empty + }; + + if (dto.ImageFile != null && !string.IsNullOrEmpty(dto.ImageMime) && !string.IsNullOrEmpty(dto.ImageFileName)) + { + request.HeroImageFile = new PageSettingsImageFile + { + File = Google.Protobuf.ByteString.CopyFrom(dto.ImageFile), + Mime = dto.ImageMime, + FileName = dto.ImageFileName + }; + } + + var response = await _client.SavePageSettingsAsync(request); + return new SaveResultDto { Id = response.Id, Success = response.Success }; + } + + public async Task SaveImageAsync(SavePageImageDto dto) + { + var request = new SavePageImageRequest + { + Id = dto.Id, + SitePageSettingsId = dto.SitePageSettingsId, + ImageGroup = dto.ImageGroup, + Title = dto.Title ?? string.Empty, + Subtitle = dto.Subtitle ?? string.Empty, + Description = dto.Description ?? string.Empty, + LinkUrl = dto.LinkUrl ?? string.Empty, + IconName = dto.IconName ?? string.Empty, + SortOrder = dto.SortOrder, + IsActive = dto.IsActive + }; + + if (dto.ImageFile != null && !string.IsNullOrEmpty(dto.ImageMime) && !string.IsNullOrEmpty(dto.ImageFileName)) + { + request.ImageFile = new PageSettingsImageFile + { + File = Google.Protobuf.ByteString.CopyFrom(dto.ImageFile), + Mime = dto.ImageMime, + FileName = dto.ImageFileName + }; + } + + var response = await _client.SavePageImageAsync(request); + return new SaveResultDto { Id = response.Id, Success = response.Success }; + } + + public async Task DeleteImageAsync(long id) + { + await _client.DeletePageImageAsync(new DeletePageImageRequest { Id = id }); + } +} diff --git a/src/BackOffice/Shared/NavMenu.razor b/src/BackOffice/Shared/NavMenu.razor index 44f964a..6a61a93 100644 --- a/src/BackOffice/Shared/NavMenu.razor +++ b/src/BackOffice/Shared/NavMenu.razor @@ -231,9 +231,9 @@ @if (CanManageSitePages) { - صفحات سایت + تنظیمات صفحات }