merge
commit
0fea79efe6
|
@ -1,8 +1,9 @@
|
|||
@inject IJSRuntime JsRuntime
|
||||
@implements IAsyncDisposable
|
||||
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="css/content-styles.css" />
|
||||
<link rel="stylesheet" href="assets/vendor/ckeditor5-content.css" />
|
||||
</head>
|
||||
<style>
|
||||
.ck-content * {
|
||||
|
@ -15,65 +16,9 @@
|
|||
|
||||
</style>
|
||||
<div class="editor"></div>
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
function destroyEditor() {
|
||||
// document.querySelector('.editor').ckeditorInstance.destroy();
|
||||
window.editor = null;
|
||||
}
|
||||
function lunchEditor(data) {
|
||||
if (!document.querySelector('.editor')) return
|
||||
if (window.editor) return
|
||||
ClassicEditor.create(document.querySelector('.editor'), {
|
||||
htmlSupport: {
|
||||
allow: [
|
||||
{
|
||||
name: 'iframe',
|
||||
attributes: true,
|
||||
classes: true,
|
||||
styles: true
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
.then(editor => {
|
||||
window.editor = editor;
|
||||
window.editor.setData(data);
|
||||
editor.editing.view.document.on('blur', () => {
|
||||
GLOBAL.DotNetReference.invokeMethodAsync('MyMethod', window.editor.getData());
|
||||
});
|
||||
})
|
||||
.catch(handleSampleError);
|
||||
}
|
||||
var GLOBAL = {};
|
||||
GLOBAL.DotNetReference = null;
|
||||
GLOBAL.SetDotnetReference = function (pDotNetReference) {
|
||||
GLOBAL.DotNetReference = pDotNetReference;
|
||||
};
|
||||
|
||||
|
||||
function handleSampleError(error) {
|
||||
const issueUrl = 'https://github.com/ckeditor/ckeditor5/issues';
|
||||
|
||||
const message = [
|
||||
'Oops, something went wrong!',
|
||||
`Please, report the following error on ${issueUrl} with the build id "pws0dnpd0jqj-zi42lsl7aqxa" and the error stack trace:`
|
||||
].join('\n');
|
||||
|
||||
console.error(message);
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
function setData(data) {
|
||||
if (!!window.editor.date && window.editor.data != data) {
|
||||
window.editor.setData(data);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@code {
|
||||
@code
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
@ -100,7 +45,7 @@
|
|||
{
|
||||
try
|
||||
{
|
||||
await JsRuntime.InvokeVoidAsync("window.setData", Text);
|
||||
await JsRuntime.InvokeVoidAsync("setData", Text);
|
||||
isTextSeted = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -114,20 +59,23 @@
|
|||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
|
||||
var lDotNetReference = DotNetObjectReference.Create(this);
|
||||
await JsRuntime.InvokeVoidAsync("GLOBAL.SetDotnetReference", lDotNetReference);
|
||||
await JsRuntime.InvokeVoidAsync("window.lunchEditor", Text);
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
if (firstRender)
|
||||
{
|
||||
var lDotNetReference = DotNetObjectReference.Create(this);
|
||||
await JsRuntime.InvokeVoidAsync("GLOBAL.SetDotnetReference", lDotNetReference);
|
||||
await JsRuntime.InvokeVoidAsync("initializeCKEditor", Text);
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
JsRuntime.InvokeVoidAsync("window.destroyEditor", Text);
|
||||
JsRuntime.InvokeVoidAsync("destroyEditor", Text);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await JsRuntime.InvokeVoidAsync("window.destroyEditor", Text);
|
||||
await JsRuntime.InvokeVoidAsync("destroyEditor", Text);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -40,7 +40,12 @@
|
|||
<MudNavGroup Title="مدیریت برگه ها" Expanded="false"
|
||||
Icon="@Icons.Material.Outlined.Pages">
|
||||
<MudNavLink Href="management/pages" Icon="@Icons.Material.Filled.Pageview">برگه ها</MudNavLink>
|
||||
<MudNavLink Href="management/faqs" Icon="@Icons.Material.Filled.ManageAccounts">سوالات متداول</MudNavLink>
|
||||
<MudNavLink Href="setting/faq" Icon="@Icons.Material.Filled.ManageAccounts">سوالات متداول</MudNavLink>
|
||||
<MudNavLink Href="setting/pages" Icon="@Icons.Material.Outlined.Folder">تنظیماتــ برگه ها</MudNavLink>
|
||||
</MudNavGroup>
|
||||
|
||||
<MudNavGroup Title="شخصی سازی" Expanded="false" Icon="@Icons.Material.Filled.SettingsSystemDaydream">
|
||||
<MudNavLink Href="personaliztion/main" Icon="@Icons.Material.Filled.SettingsBrightness">کاتالوگ و بنرها</MudNavLink>
|
||||
</MudNavGroup>
|
||||
|
||||
@if (isShop)
|
||||
|
|
|
@ -1,236 +1,180 @@
|
|||
@using Netina.AdminPanel.PWA.Models.Api
|
||||
@using Netina.AdminPanel.PWA.Models
|
||||
@using Netina.Domain.Entities.Brands
|
||||
|
||||
@inject ISnackbar Snackbar
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IRestWrapper RestWrapper
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IDialogService DialogService
|
||||
|
||||
<MudDialog class="mx-auto">
|
||||
<DialogContent>
|
||||
<MudStack>
|
||||
<MudDivider class="-mt-3" />
|
||||
<MudStack Spacing="0">
|
||||
<MudContainer class="h-full p-0">
|
||||
<MudTabs Outlined="true" Elevation="0" Rounded="true" Centered="true">
|
||||
<MudTabPanel Text="اطلاعات کلی" Icon="@Icons.Material.Outlined.Info">
|
||||
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="نام فارسی برند" @bind-Value="@_persianName" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="نام انگلیسی برند" @bind-Value="@_englishName" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudSelect T="bool" Label="آیا صفحه شخصی دارد ؟" @bind-Value="@_hasSpecialPage" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="bool" Value="true"></MudSelectItem>
|
||||
<MudSelectItem T="bool" Value="false" />
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="لینک صفحه شخصی برند" @bind-Value="@_pageUrl" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="12" md="12">
|
||||
<MudTextField T="string" Label="توضیحاتــ" @bind-Value="@_description" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" md="12" lg="12">
|
||||
<MudStack class="mt-1 mb-4" Spacing="0">
|
||||
<MudStack>
|
||||
<MudStack Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">تصاویر برند</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید برای برند چند تصویر اپلود کنید</MudText>
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="نام فارسی برند" @bind-Value="@ViewModel.PageDto.PersianName" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="نام انگلیسی برند" @bind-Value="@ViewModel.PageDto.EnglishName" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudSelect T="bool" Label="آیا صفحه شخصی دارد ؟" @bind-Value="@ViewModel.PageDto.HasSpecialPage" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="bool" Value="true"></MudSelectItem>
|
||||
<MudSelectItem T="bool" Value="false" />
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem lg="6" md="6">
|
||||
<MudTextField T="string" Label="لینک صفحه شخصی برند" @bind-Value="@ViewModel.PageDto.PageUrl" Variant="Variant.Outlined"></MudTextField>
|
||||
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12" md="12" lg="12">
|
||||
<MudStack class="mt-1 mb-4" Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">تصاویر برند</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید برای برند چند تصویر اپلود کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton HtmlTag="label"
|
||||
Color="Color.Info"
|
||||
Variant="Variant.Outlined"
|
||||
class="w-28 h-28"
|
||||
Size="Size.Large"
|
||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||
OnClick="async () => await ViewModel.SelectFileAsync()" />
|
||||
|
||||
@foreach (var item in ViewModel.PageDto.Files)
|
||||
{
|
||||
<div class="w-28 h-28">
|
||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||
|
||||
<MudIconButton DisableElevation="true"
|
||||
class="absolute m-1.5"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Filled"
|
||||
OnClick="() => ViewModel.PageDto.Files.Remove(item)"
|
||||
Color="@Color.Error"
|
||||
Icon="@Icons.Material.Outlined.Delete" />
|
||||
@if (item.IsHeader)
|
||||
{
|
||||
<p class="bg-pink-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">هدر</p>
|
||||
}
|
||||
@if (item.IsPrimary)
|
||||
{
|
||||
<p class="bg-blue-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">اصلی</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="12" md="12">
|
||||
<RichTextEditorUi @bind-Text="@ViewModel.PageDto.Description" ></RichTextEditorUi>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton HtmlTag="label"
|
||||
Color="Color.Info"
|
||||
Variant="Variant.Outlined"
|
||||
class="w-28 h-28"
|
||||
Size="Size.Large"
|
||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||
OnClick="async () => await SelectFileAsync()">
|
||||
</MudIconButton>
|
||||
@foreach (var item in Files)
|
||||
{
|
||||
<div class="w-28 h-28">
|
||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||
</MudTabPanel>
|
||||
|
||||
<MudIconButton DisableElevation="true"
|
||||
class="absolute m-1.5"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Filled"
|
||||
OnClick="() => RemoveFile(item)"
|
||||
Color="@Color.Error"
|
||||
Icon="@Icons.Material.Outlined.Delete" />
|
||||
@if (item.IsHeader)
|
||||
{
|
||||
<p class="bg-pink-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">هدر</p>
|
||||
}
|
||||
@if (item.IsPrimary)
|
||||
{
|
||||
<p class="bg-blue-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">اصلی</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
<MudTabPanel Text="متاتگ و سوالات متداول">
|
||||
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
<MudText Typo="Typo.h6">سوالات متداول</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید سوالات متداول شهر موردنظر را وارد کنید</MudText>
|
||||
<MudGrid class="mt-1">
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqQuestion" T="string" Label="سوال" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqAnswer" T="string" Label="پاسخ" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="2" md="12">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info"
|
||||
class="mt-2 w-full py-3"
|
||||
OnClick="ViewModel.AddFaq"
|
||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12">
|
||||
<MudExpansionPanels class="mt-1" Elevation="2">
|
||||
@foreach (var item in ViewModel.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="() => ViewModel.Faqs.Remove(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudTabPanel>
|
||||
</MudTabs>
|
||||
</MudContainer>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||
|
||||
@if (_isEditing)
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="ثبت ویرایش" OnClickCallback="SubmitEditAsync" />
|
||||
Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@_isProcessing"
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید" OnClickCallback="SubmitCreateAsync" />
|
||||
Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" />
|
||||
}
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="ViewModel.Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
@code {
|
||||
[CascadingParameter] MudDialogInstance MudDialog { get; set; }
|
||||
[CascadingParameter]
|
||||
MudDialogInstance MudDialog { get; set; }
|
||||
[Parameter]
|
||||
public BrandSDto? Brand { get; set; }
|
||||
|
||||
void Cancel() => MudDialog.Cancel();
|
||||
public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();
|
||||
private bool _isProcessing = false;
|
||||
private string _persianName = string.Empty;
|
||||
private string _englishName = string.Empty;
|
||||
private string _description = string.Empty;
|
||||
private bool _hasSpecialPage;
|
||||
private bool _isEditing;
|
||||
private string _pageUrl = string.Empty;
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
public BrandActionDialogBoxViewModel ViewModel { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (Brand != null)
|
||||
{
|
||||
_isEditing = true;
|
||||
try
|
||||
{
|
||||
_isProcessing = true;
|
||||
var response = await RestWrapper.CrudDtoApiRest<Brand, BrandLDto, Guid>(Address.BrandController).ReadOne(Brand.Id);
|
||||
var brandLDto = response;
|
||||
brandLDto.Files.ForEach(f => Files.Add(f));
|
||||
|
||||
_hasSpecialPage = brandLDto.HasSpecialPage;
|
||||
_description = brandLDto.Description;
|
||||
_englishName = brandLDto.EnglishName;
|
||||
_persianName = brandLDto.PersianName;
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
Snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
MudDialog.Cancel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Snackbar.Add(e.Message, Severity.Error);
|
||||
MudDialog.Cancel();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
_isProcessing = false;
|
||||
}
|
||||
|
||||
}
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
private async Task SubmitCreateAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_englishName.IsNullOrEmpty())
|
||||
throw new AppException("لطفا نام برند را وارد کنید");
|
||||
_isProcessing = true;
|
||||
var token = await UserUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new AppException("Token is null");
|
||||
var request = new CreateBrandCommand(_persianName, _englishName, _description, _hasSpecialPage, _pageUrl, Files.ToList());
|
||||
await RestWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Create<CreateBrandCommand>(request, token);
|
||||
MudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
Snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private async Task SubmitEditAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Brand == null)
|
||||
throw new AppException("برند به درستی ارسال نشده است");
|
||||
if (_englishName.IsNullOrEmpty())
|
||||
throw new AppException("لطفا نام برند را وارد کنید");
|
||||
_isProcessing = true;
|
||||
var token = await UserUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new AppException("Token is null");
|
||||
var request = new UpdateBrandCommand(Brand.Id, _persianName, _englishName, _description, _hasSpecialPage, _pageUrl, Files.ToList());
|
||||
await RestWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Update<UpdateBrandCommand>(request, token);
|
||||
MudDialog.Close();
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
Snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
MudDialog.Cancel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Snackbar.Add(e.Message, Severity.Error);
|
||||
MudDialog.Cancel();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
_isProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task SelectFileAsync()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
var dialog = await DialogService.ShowAsync<StorageDialogBox>("انتخاب عکس برند", maxWidth);
|
||||
var result = await dialog.Result;
|
||||
var file = result.Data;
|
||||
if (file is StorageFileSDto storageFile)
|
||||
Files.Add(storageFile);
|
||||
}
|
||||
|
||||
public void RemoveFile(StorageFileSDto file)
|
||||
{
|
||||
Files.Remove(file);
|
||||
ViewModel = Brand == null ? new BrandActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog) :
|
||||
new BrandActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Brand);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
using Netina.Domain.Entities.Brands;
|
||||
|
||||
namespace Netina.AdminPanel.PWA.Dialogs;
|
||||
|
||||
public class BrandActionDialogBoxViewModel : BaseViewModel<BrandLDto>
|
||||
{
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
private readonly IUserUtility _userUtility;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly MudDialogInstance _mudDialog;
|
||||
|
||||
public BrandActionDialogBoxViewModel(ISnackbar snackbar,
|
||||
IRestWrapper restWrapper,
|
||||
IUserUtility userUtility,
|
||||
IDialogService dialogService,
|
||||
MudDialogInstance mudDialog) : base(userUtility)
|
||||
{
|
||||
_snackbar = snackbar;
|
||||
_restWrapper = restWrapper;
|
||||
_userUtility = userUtility;
|
||||
_dialogService = dialogService;
|
||||
_mudDialog = mudDialog;
|
||||
}
|
||||
public BrandActionDialogBoxViewModel(ISnackbar snackbar,
|
||||
IRestWrapper restWrapper,
|
||||
IUserUtility userUtility,
|
||||
IDialogService dialogService,
|
||||
MudDialogInstance mudDialog,
|
||||
BrandSDto brand) : base(userUtility)
|
||||
{
|
||||
_snackbar = snackbar;
|
||||
_restWrapper = restWrapper;
|
||||
_userUtility = userUtility;
|
||||
_dialogService = dialogService;
|
||||
_mudDialog = mudDialog;
|
||||
Brand = brand;
|
||||
}
|
||||
|
||||
private BrandSDto? _brand = null;
|
||||
public BrandSDto? Brand
|
||||
{
|
||||
get => _brand;
|
||||
set
|
||||
{
|
||||
_brand = value;
|
||||
if (_brand != null)
|
||||
{
|
||||
IsEditing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Cancel() => _mudDialog.Cancel();
|
||||
|
||||
public bool IsEditing = false;
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
{
|
||||
if (Brand != null)
|
||||
{
|
||||
IsEditing = true;
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var response = await _restWrapper.CrudDtoApiRest<Brand, BrandLDto, Guid>(Address.BrandController).ReadOne(Brand.Id);
|
||||
var brandLDto = response;
|
||||
PageDto = brandLDto;
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
|
||||
}
|
||||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task SubmitCreateAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (PageDto.EnglishName.IsNullOrEmpty())
|
||||
throw new AppException("لطفا نام برند را وارد کنید");
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new AppException("Token is null");
|
||||
var request = new CreateBrandCommand(PageDto.PersianName,
|
||||
PageDto.EnglishName,
|
||||
PageDto.Description,
|
||||
PageDto.HasSpecialPage,
|
||||
PageDto.PageUrl,
|
||||
PageDto.Files,
|
||||
Faqs,
|
||||
new Dictionary<string, string>());
|
||||
await _restWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Create<CreateBrandCommand>(request, token);
|
||||
_mudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task SubmitEditAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Brand == null)
|
||||
throw new AppException("برند به درستی ارسال نشده است");
|
||||
if (PageDto.EnglishName.IsNullOrEmpty())
|
||||
throw new AppException("لطفا نام برند را وارد کنید");
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new AppException("Token is null");
|
||||
var request = new UpdateBrandCommand(
|
||||
PageDto.Id,
|
||||
PageDto.PersianName,
|
||||
PageDto.EnglishName,
|
||||
PageDto.Description,
|
||||
PageDto.HasSpecialPage,
|
||||
PageDto.PageUrl,
|
||||
PageDto.Files,
|
||||
Faqs,
|
||||
new Dictionary<string, string>());
|
||||
|
||||
await _restWrapper.CrudApiRest<Brand, Guid>(Address.BrandController).Update<UpdateBrandCommand>(request, token);
|
||||
_mudDialog.Close();
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public string FaqQuestion { get; set; } = string.Empty;
|
||||
public string FaqAnswer { get; set; } = string.Empty;
|
||||
public Dictionary<string, string> Faqs = new();
|
||||
public void AddFaq()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (FaqAnswer.IsNullOrEmpty())
|
||||
throw new Exception("لطفا پاسخ را وارد کنید");
|
||||
|
||||
if (FaqQuestion.IsNullOrEmpty())
|
||||
throw new Exception("لطفا سوال را وارد کنید");
|
||||
|
||||
Faqs.Add(FaqQuestion, FaqAnswer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task SelectFileAsync()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
var dialog = await _dialogService.ShowAsync<StorageDialogBox>("انتخاب عکس برند", maxWidth);
|
||||
var result = await dialog.Result;
|
||||
var file = result.Data;
|
||||
if (file is StorageFileSDto storageFile)
|
||||
PageDto.Files.Add(storageFile);
|
||||
}
|
||||
|
||||
public void RemoveFile(StorageFileSDto file)
|
||||
{
|
||||
PageDto.Files.Remove(file);
|
||||
}
|
||||
}
|
|
@ -311,9 +311,9 @@ public class DiscountActionDialogBoxViewModel : BaseViewModel<DiscountLDto>
|
|||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
if (product.IsNullOrEmpty())
|
||||
response = await _restWrapper.ProductRestApi.ReadAll(0,null,null,null);
|
||||
response = await _restWrapper.ProductRestApi.ReadAll(0,null,null,null,token);
|
||||
else
|
||||
response = await _restWrapper.ProductRestApi.ReadAll(product);
|
||||
response = await _restWrapper.ProductRestApi.ReadAll(product,token);
|
||||
_products = response.Products;
|
||||
return _products;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
@inject ISnackbar Snackbar
|
||||
@inject IRestWrapper RestWrapper
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IDialogService DialogService
|
||||
|
||||
<MudDialog class="mx-auto">
|
||||
<DialogContent>
|
||||
<MudStack>
|
||||
<MudDivider class="-mt-3" />
|
||||
<MudStack Spacing="0">
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem sm="12" lg="6" md="6">
|
||||
<MudTextField T="string" Label="عنوان صفحه سوالات متداول" @bind-Value="@ViewModel.PageDto.Title" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="6" md="6">
|
||||
<MudTextField T="string" Label="اسلاگ صفحه سوالات متداول" @bind-Value="@ViewModel.PageDto.Slug" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="12" md="12">
|
||||
<MudText Typo="Typo.h6">سوالات متداول</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید سوالات متداول شهر موردنظر را وارد کنید</MudText>
|
||||
<MudGrid>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.Question" T="string" Label="سوال" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.Answer" T="string" Label="پاسخ" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="2" md="12">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info"
|
||||
class="mt-2 w-full py-3"
|
||||
OnClick="ViewModel.AddFaq"
|
||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12">
|
||||
<MudExpansionPanels class="mt-1" Elevation="2">
|
||||
@foreach (var item in ViewModel.PageDto.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="()=>ViewModel.PageDto.Faqs.Remove(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="mx-4 mb-2 w-full">
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Info"
|
||||
Content="ثبت ویرایش" OnClickCallback="@ViewModel.SubmitUpdateAsync" />
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید" OnClickCallback="@ViewModel.SubmitAsync" />
|
||||
}
|
||||
<MudSpacer/>
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code
|
||||
{
|
||||
[CascadingParameter]
|
||||
MudDialogInstance MudDialog { get; set; }
|
||||
|
||||
void Cancel() => MudDialog.Cancel();
|
||||
[Parameter]
|
||||
public BaseFaq? Faq { get; set; }
|
||||
|
||||
public FaqActionDialogBoxViewModel ViewModel;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (Faq != null)
|
||||
ViewModel = new FaqActionDialogBoxViewModel(Faq,UserUtility, Snackbar, RestWrapper, MudDialog);
|
||||
else
|
||||
ViewModel = new FaqActionDialogBoxViewModel(UserUtility, Snackbar, RestWrapper, MudDialog);
|
||||
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
using Netina.Domain.MartenEntities.Faqs;
|
||||
|
||||
namespace Netina.AdminPanel.PWA.Dialogs;
|
||||
|
||||
public class FaqActionDialogBoxViewModel : BaseViewModel<BaseFaq>
|
||||
{
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly MudDialogInstance _dialogInstance;
|
||||
public bool IsEditing = false;
|
||||
|
||||
public FaqActionDialogBoxViewModel(IUserUtility userUtility, ISnackbar snackbar, IRestWrapper restWrapper, MudDialogInstance dialogInstance) : base(userUtility)
|
||||
{
|
||||
_snackbar = snackbar;
|
||||
_restWrapper = restWrapper;
|
||||
_dialogInstance = dialogInstance;
|
||||
}
|
||||
|
||||
public FaqActionDialogBoxViewModel(BaseFaq faq,IUserUtility userUtility, ISnackbar snackbar, IRestWrapper restWrapper, MudDialogInstance dialogInstance) : base(userUtility)
|
||||
{
|
||||
PageDto = faq;
|
||||
IsEditing = true;
|
||||
_snackbar = snackbar;
|
||||
_restWrapper = restWrapper;
|
||||
_dialogInstance = dialogInstance;
|
||||
}
|
||||
|
||||
public string Question { get; set; } = string.Empty;
|
||||
public string Answer { get; set; } = string.Empty;
|
||||
|
||||
public void AddFaq()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Question.IsNullOrEmpty())
|
||||
throw new Exception("سوال را وارد کنید");
|
||||
if (Answer.IsNullOrEmpty())
|
||||
throw new Exception("پاسخ را وارد کنید");
|
||||
PageDto.Faqs.Add(Question,Answer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
public async Task SubmitAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("token is null");
|
||||
if (PageDto.Slug.IsNullOrEmpty())
|
||||
throw new Exception("اسلاگ صفحه سوال متداول را وارد کنید");
|
||||
if (PageDto.Title.IsNullOrEmpty())
|
||||
throw new Exception("عنوان صفحه سوالات متداول را وارد کنید");
|
||||
|
||||
await _restWrapper.FaqApiRest.Create(PageDto, token);
|
||||
_snackbar.Add("تغییر سوالات متداول با موفقیت انجام شد", Severity.Success);
|
||||
_dialogInstance.Close(DialogResult.Ok(true));
|
||||
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
public async Task SubmitUpdateAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("token is null");
|
||||
if (PageDto.Slug.IsNullOrEmpty())
|
||||
throw new Exception("اسلاگ صفحه سوال متداول را وارد کنید");
|
||||
if (PageDto.Title.IsNullOrEmpty())
|
||||
throw new Exception("عنوان صفحه سوالات متداول را وارد کنید");
|
||||
if (PageDto.Id == default)
|
||||
throw new Exception("ای دی معتبر نمی باشد");
|
||||
|
||||
await _restWrapper.FaqApiRest.Update(PageDto, token);
|
||||
_snackbar.Add("تغییر سوالات متداول با موفقیت انجام شد", Severity.Success);
|
||||
_dialogInstance.Close(DialogResult.Ok(true));
|
||||
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -199,6 +199,7 @@
|
|||
<BaseButtonUi class="h-12 w-full rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.RemoveCircle"
|
||||
Variant="Variant.Outlined" Color="Color.Error"
|
||||
OnClickCallback="ViewModel.CancelAsync"
|
||||
Content="لغو سفارش" />
|
||||
</MudItem>
|
||||
|
||||
|
|
|
@ -259,4 +259,41 @@ public class OrderActionDialogBoxViewModel : BaseViewModel<OrderLDto>
|
|||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public async Task CancelAsync()
|
||||
{
|
||||
var reference = await _dialogService.ShowQuestionDialog($"ایا از کنسل کردن سفارش اطمینان دارید ?");
|
||||
var result = await reference.Result;
|
||||
if (!result.Canceled)
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
IsProcessing = true;
|
||||
|
||||
|
||||
await _restWrapper.OrderRestApi.CancelOrderStepAsync(PageDto.Id, token);
|
||||
_snackbar.Add($"سفارش {PageDto.FactorCode} کنسل شد", Severity.Warning);
|
||||
_mudDialog.Close(true);
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,6 +106,7 @@
|
|||
</MudGrid>
|
||||
</div>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudTabPanel Text="ویژگی های کلی" Icon="@Icons.Material.Outlined.AutoGraph">
|
||||
<div class="min-h-[33rem]">
|
||||
|
||||
|
@ -157,6 +158,7 @@
|
|||
</MudGrid>
|
||||
</div>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudTabPanel Text="توضیحات تکمیلی" Icon="@Icons.Material.Outlined.Article">
|
||||
|
||||
<div class="min-h-[33rem]">
|
||||
|
@ -174,6 +176,62 @@
|
|||
</MudGrid>
|
||||
</div>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudTabPanel Text="متاتگ و سوالات متداول">
|
||||
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
|
||||
<MudText Typo="Typo.h6">سوالات متداول</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید سوالات متداول شهر موردنظر را وارد کنید</MudText>
|
||||
<MudGrid class="mt-1">
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqQuestion" T="string" Label="سوال" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqAnswer" T="string" Label="پاسخ" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="2" md="12">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info"
|
||||
class="mt-2 w-full py-3"
|
||||
OnClick="ViewModel.AddFaq"
|
||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12">
|
||||
<MudExpansionPanels class="mt-1" Elevation="2">
|
||||
@foreach (var item in ViewModel.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="()=>ViewModel.Faqs.Remove(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudTabPanel Text="تـــــصاویر" Icon="@Icons.Material.Outlined.ImageSearch">
|
||||
|
||||
<div class="min-h-[33rem]">
|
||||
|
@ -235,7 +293,12 @@
|
|||
|
||||
<MudItem xs="12" md="4">
|
||||
|
||||
<MudSelect Disabled="@ViewModel.IsSpecialOffer.Not()" T="DiscountAmountType" ValueChanged="@ViewModel.AmountTypeChanged" Label="نوع تخفیفـــ" ToStringFunc="b=>b.ToDisplay()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelect Disabled="@ViewModel.IsSpecialOffer.Not()" T="DiscountAmountType"
|
||||
ValueChanged="@ViewModel.AmountTypeChanged"
|
||||
Label="نوع تخفیفـــ" ToStringFunc="b=>b.ToDisplay()"
|
||||
Variant="Variant.Outlined"
|
||||
Value="@ViewModel.Discount.AmountType"
|
||||
AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="DiscountAmountType" Value="DiscountAmountType.Percent" />
|
||||
<MudSelectItem T="DiscountAmountType" Value="DiscountAmountType.Amount" />
|
||||
</MudSelect>
|
||||
|
@ -251,11 +314,11 @@
|
|||
|
||||
|
||||
<MudItem xs="12" sm="6">
|
||||
<MudDatePicker Disabled="@ViewModel.IsSpecialOffer.Not()" @bind-Date="@ViewModel.StartDate" UseShortNames="false" TitleDateFormat="dddd, dd MMMM" Label="تاریخ شروع تخفیفــ" Variant="Variant.Outlined" Culture="@PersianCultureInfo.GetPersianCulture()" />
|
||||
|
||||
<MudDatePicker Disabled="@ViewModel.IsSpecialOffer.Not()" @bind-Date="@ViewModel.StartDate" DisableToolbar="true" UseShortNames="false" TitleDateFormat="dddd, dd MMMM" Label="تاریخ شروع تخفیفــ" Variant="Variant.Outlined" Culture="@PersianCultureInfo.GetPersianCulture()" />
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" sm="6">
|
||||
<MudDatePicker Disabled="@ViewModel.IsSpecialOffer.Not()" @bind-Date="@ViewModel.ExpireDate" UseShortNames="false" TitleDateFormat="dddd, dd MMMM" Label="تاریخ پایان تخفیفــ" Variant="Variant.Outlined" Culture="@PersianCultureInfo.GetPersianCulture()" />
|
||||
<MudDatePicker Disabled="@ViewModel.IsSpecialOffer.Not()" @bind-Date="@ViewModel.ExpireDate" DisableToolbar="true" UseShortNames="false" TitleDateFormat="dddd, dd MMMM" Label="تاریخ پایان تخفیفــ" Variant="Variant.Outlined" Culture="@PersianCultureInfo.GetPersianCulture()" />
|
||||
|
||||
</MudItem>
|
||||
|
||||
|
|
|
@ -61,11 +61,13 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
{
|
||||
_isSpecialOffer = value;
|
||||
PageDto.IsSpecialOffer = value;
|
||||
if(!value)
|
||||
if (!value)
|
||||
{
|
||||
IsAmountType = value;
|
||||
IsPercentType = value;
|
||||
}
|
||||
else if(!IsAmountType)
|
||||
IsPercentType = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,6 +93,14 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
SelectedBrand = new BrandSDto { Id = productLDto.BrandId, PersianName = productLDto.BrandName };
|
||||
PageDto.IsSpecialOffer = productLDto.IsSpecialOffer;
|
||||
IsSpecialOffer = PageDto.IsSpecialOffer;
|
||||
|
||||
if (!PageDto.Slug.IsNullOrEmpty())
|
||||
{
|
||||
var faq = await _restWrapper.FaqApiRest.ReadOne(PageDto.GetWebSiteUrl());
|
||||
foreach (var pair in faq.Faqs)
|
||||
Faqs.Add(pair.Key, pair.Value);
|
||||
}
|
||||
|
||||
if (productLDto.SpecialOffer != null)
|
||||
{
|
||||
Discount = productLDto.SpecialOffer;
|
||||
|
@ -108,6 +118,7 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
|
||||
ExpireDate = Discount.ExpireDate;
|
||||
StartDate = Discount.StartDate;
|
||||
IsSpecialOffer = true;
|
||||
}
|
||||
}
|
||||
catch (ApiException ex)
|
||||
|
@ -158,7 +169,29 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
Discount.StartDate = StartDate.Value;
|
||||
PageDto.SpecialOffer = Discount;
|
||||
}
|
||||
var request = PageDto.Adapt<UpdateProductCommand>();
|
||||
|
||||
var request = new UpdateProductCommand(PageDto.Id,
|
||||
PageDto.PersianName,
|
||||
PageDto.EnglishName,
|
||||
PageDto.Summery,
|
||||
PageDto.ExpertCheck,
|
||||
PageDto.Tags,
|
||||
PageDto.Warranty,
|
||||
PageDto.BeDisplayed,
|
||||
PageDto.Cost,
|
||||
PageDto.PackingCost,
|
||||
PageDto.Stock,
|
||||
PageDto.HasExpressDelivery,
|
||||
PageDto.MaxOrderCount,
|
||||
PageDto.IsSpecialOffer,
|
||||
PageDto.BrandId,
|
||||
PageDto.CategoryId,
|
||||
PageDto.SpecialOffer ?? new DiscountSDto(),
|
||||
PageDto.Specifications,
|
||||
PageDto.Files,
|
||||
Faqs,
|
||||
new Dictionary<string, string>());
|
||||
|
||||
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Update<UpdateProductCommand>(request, token);
|
||||
_snackbar.Add($"ویرایش محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
|
||||
_mudDialog.Close();
|
||||
|
@ -202,7 +235,27 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
Discount.StartDate = StartDate.Value;
|
||||
PageDto.SpecialOffer = Discount;
|
||||
}
|
||||
var request = PageDto.Adapt<CreateProductCommand>();
|
||||
var request = new CreateProductCommand(
|
||||
PageDto.PersianName,
|
||||
PageDto.EnglishName,
|
||||
PageDto.Summery,
|
||||
PageDto.ExpertCheck,
|
||||
PageDto.Tags,
|
||||
PageDto.Warranty,
|
||||
PageDto.BeDisplayed,
|
||||
PageDto.Cost,
|
||||
PageDto.PackingCost,
|
||||
PageDto.Stock,
|
||||
PageDto.HasExpressDelivery,
|
||||
PageDto.MaxOrderCount,
|
||||
PageDto.IsSpecialOffer,
|
||||
PageDto.BrandId,
|
||||
PageDto.CategoryId,
|
||||
PageDto.SpecialOffer ?? new DiscountSDto(),
|
||||
PageDto.Specifications,
|
||||
PageDto.Files,
|
||||
Faqs,
|
||||
new Dictionary<string, string>());
|
||||
await _restWrapper.CrudApiRest<Product, Guid>(Address.ProductController).Create<CreateProductCommand>(request, token);
|
||||
|
||||
_snackbar.Add($"ساخت محصول {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
|
||||
|
@ -236,10 +289,12 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
case DiscountAmountType.Amount:
|
||||
IsAmountType = true;
|
||||
IsPercentType = false;
|
||||
Discount.AmountType = DiscountAmountType.Amount;
|
||||
break;
|
||||
case DiscountAmountType.Percent:
|
||||
IsAmountType = false;
|
||||
IsPercentType = true;
|
||||
Discount.AmountType = DiscountAmountType.Percent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -297,6 +352,28 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
}
|
||||
|
||||
|
||||
public string FaqQuestion { get; set; } = string.Empty;
|
||||
public string FaqAnswer { get; set; } = string.Empty;
|
||||
public Dictionary<string, string> Faqs = new();
|
||||
public void AddFaq()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (FaqAnswer.IsNullOrEmpty())
|
||||
throw new Exception("لطفا پاسخ را وارد کنید");
|
||||
|
||||
if (FaqQuestion.IsNullOrEmpty())
|
||||
throw new Exception("لطفا سوال را وارد کنید");
|
||||
|
||||
Faqs.Add(FaqQuestion, FaqAnswer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void AddSpecification()
|
||||
{
|
||||
try
|
||||
|
@ -315,7 +392,6 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveSpecification(SpecificationSDto specification)
|
||||
{
|
||||
var spec = Specifications.FirstOrDefault(s => s.Value == specification.Value && s.Title == specification.Title);
|
||||
|
@ -332,7 +408,6 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
if (file is StorageFileSDto storageFile)
|
||||
Files.Add(storageFile);
|
||||
}
|
||||
|
||||
public void RemoveFile(StorageFileSDto file)
|
||||
{
|
||||
Files.Remove(file);
|
||||
|
|
|
@ -6,122 +6,180 @@
|
|||
<MudDialog class="mx-auto" DisableSidePadding="true">
|
||||
<DialogContent>
|
||||
<MudContainer class="h-full">
|
||||
<MudDivider class="-mt-3" />
|
||||
<MudStack Spacing="0">
|
||||
<MudTabs Outlined="true" Elevation="0" Rounded="true" Centered="true">
|
||||
<MudTabPanel Text="اطلاعات کلی" Icon="@Icons.Material.Outlined.Info">
|
||||
<MudStack Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack class="mx-5 overflow-x-hidden overflow-y-hidden">
|
||||
<MudGrid>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.Name" Label="نام دسته بندی" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudSelect T="bool" @bind-Value="@ViewModel.IsMain" Label="آیا دسته بندی اصلی است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="bool" Value="true" />
|
||||
<MudSelectItem T="bool" Value="false" />
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedCategory"
|
||||
SearchFunc="ViewModel.SearchCategory"
|
||||
T="ProductCategorySDto"
|
||||
Label="دسته پدر"
|
||||
Variant="Variant.Outlined">
|
||||
<ProgressIndicatorInPopoverTemplate>
|
||||
<MudList Clickable="false">
|
||||
<MudListItem>
|
||||
<div class="flex flex-row w-full mx-auto">
|
||||
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
||||
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
||||
<MudText Typo="Typo.h6">اطلاعات کلی</MudText>
|
||||
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی محصول را به دقت وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack class="overflow-x-hidden overflow-y-hidden">
|
||||
<MudGrid>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.Name" Label="نام دسته بندی" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudSelect T="bool" @bind-Value="@ViewModel.IsMain" Label="آیا دسته بندی اصلی است ؟" ToStringFunc="b=>b.ToPersianString()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
|
||||
<MudSelectItem T="bool" Value="true" />
|
||||
<MudSelectItem T="bool" Value="false" />
|
||||
</MudSelect>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="4" md="6">
|
||||
<MudAutocomplete Required="true" ToStringFunc="dto => dto.Name" @bind-Value="@ViewModel.SelectedCategory"
|
||||
SearchFunc="ViewModel.SearchCategory"
|
||||
T="ProductCategorySDto"
|
||||
Label="دسته پدر"
|
||||
Variant="Variant.Outlined">
|
||||
<ProgressIndicatorInPopoverTemplate>
|
||||
<MudList Clickable="false">
|
||||
<MudListItem>
|
||||
<div class="flex flex-row w-full mx-auto">
|
||||
<MudProgressCircular class="my-auto mr-1 -ml-4" Size="Size.Small" Indeterminate="true" />
|
||||
<p class="font-bold my-1 mx-auto text-md">منتظر بمانید</p>
|
||||
</div>
|
||||
</MudListItem>
|
||||
</MudList>
|
||||
</ProgressIndicatorInPopoverTemplate>
|
||||
<ItemTemplate Context="e">
|
||||
<p>@e.Name</p>
|
||||
</ItemTemplate>
|
||||
</MudAutocomplete>
|
||||
</MudItem>
|
||||
<MudItem sm="12" md="12" lg="12">
|
||||
<MudStack class="mt-2 mb-4" Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">تصاویر برند</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید برای برند چند تصویر اپلود کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton HtmlTag="label"
|
||||
Color="Color.Info"
|
||||
Variant="Variant.Outlined"
|
||||
class="w-28 h-28"
|
||||
Size="Size.Large"
|
||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||
OnClick="async () => await ViewModel.SelectFileAsync()">
|
||||
</MudIconButton>
|
||||
@foreach (var item in ViewModel.Files)
|
||||
{
|
||||
<div class="w-28 h-28">
|
||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||
|
||||
<MudIconButton DisableElevation="true"
|
||||
class="absolute m-1.5"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Filled"
|
||||
OnClick="() => ViewModel.RemoveFile(item)"
|
||||
Color="@Color.Error"
|
||||
Icon="@Icons.Material.Outlined.Delete" />
|
||||
@if (item.IsHeader)
|
||||
{
|
||||
<p class="bg-pink-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">هدر</p>
|
||||
}
|
||||
@if (item.IsPrimary)
|
||||
{
|
||||
<p class="bg-blue-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">اصلی</p>
|
||||
}
|
||||
</div>
|
||||
</MudListItem>
|
||||
</MudList>
|
||||
</ProgressIndicatorInPopoverTemplate>
|
||||
<ItemTemplate Context="e">
|
||||
<p>@e.Name</p>
|
||||
</ItemTemplate>
|
||||
</MudAutocomplete>
|
||||
</MudItem>
|
||||
<MudItem sm="12" md="12" lg="12">
|
||||
<MudStack class="mt-2 mb-4" Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">تصاویر برند</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید برای برند چند تصویر اپلود کنید</MudText>
|
||||
</MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton HtmlTag="label"
|
||||
Color="Color.Info"
|
||||
Variant="Variant.Outlined"
|
||||
class="w-28 h-28"
|
||||
Size="Size.Large"
|
||||
Icon="@Icons.Material.Outlined.Wallpaper"
|
||||
OnClick="async () => await ViewModel.SelectFileAsync()">
|
||||
</MudIconButton>
|
||||
@foreach (var item in ViewModel.Files)
|
||||
{
|
||||
<div class="w-28 h-28">
|
||||
<MudImage Src="@item.GetLink()" Elevation="25" Class="rounded-lg w-28 h-28 absolute" />
|
||||
|
||||
<MudIconButton DisableElevation="true"
|
||||
class="absolute m-1.5"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Filled"
|
||||
OnClick="() => ViewModel.RemoveFile(item)"
|
||||
Color="@Color.Error"
|
||||
Icon="@Icons.Material.Outlined.Delete" />
|
||||
@if (item.IsHeader)
|
||||
{
|
||||
<p class="bg-pink-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">هدر</p>
|
||||
}
|
||||
@if (item.IsPrimary)
|
||||
{
|
||||
<p class="bg-blue-500 px-1.5 py-0.5 absolute bottom-0 mr-2 rounded-lg text-white">اصلی</p>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="12" md="12">
|
||||
<MudContainer class="overflow-y-hidden overflow-x-hidden">
|
||||
<MudStack class="mt-4 mb-2" Spacing="0">
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
<MudItem sm="12" lg="12" md="12">
|
||||
<MudContainer class="overflow-y-hidden overflow-x-hidden">
|
||||
<MudStack class="mt-4 mb-2" Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<div class="!text-black">
|
||||
<RichTextEditorUi @bind-Text="@ViewModel.Description" />
|
||||
</div>
|
||||
</MudContainer>
|
||||
</MudItem>
|
||||
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
|
||||
</MudStack>
|
||||
<div class="!text-black">
|
||||
<RichTextEditorUi @bind-Text="@ViewModel.Description" />
|
||||
</div>
|
||||
</MudContainer>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
</MudTabPanel>
|
||||
|
||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||
<MudTabPanel Text="متاتگ و سوالات متداول">
|
||||
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" />
|
||||
}
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="ViewModel.Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
|
||||
<MudText Typo="Typo.h6">سوالات متداول</MudText>
|
||||
<MudText Typo="Typo.caption">می توانید سوالات متداول شهر موردنظر را وارد کنید</MudText>
|
||||
<MudGrid class="mt-1">
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqQuestion" T="string" Label="سوال" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="5" md="6">
|
||||
<MudTextField @bind-Value="@ViewModel.FaqAnswer" T="string" Label="پاسخ" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem lg="2" md="12">
|
||||
<MudButton Variant="Variant.Filled"
|
||||
Size="Size.Large"
|
||||
Color="Color.Info"
|
||||
class="mt-2 w-full py-3"
|
||||
OnClick="ViewModel.AddFaq"
|
||||
StartIcon="@Icons.Material.Outlined.Add">افزودن</MudButton>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="12">
|
||||
<MudExpansionPanels class="mt-1" Elevation="2">
|
||||
@foreach (var item in ViewModel.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="() => ViewModel.Faqs.Remove(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
</MudItem>
|
||||
|
||||
</MudGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudTabPanel>
|
||||
</MudTabs>
|
||||
</MudContainer>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="ثبت ویرایش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
}
|
||||
else
|
||||
{
|
||||
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="تایید" OnClickCallback="ViewModel.SubmitCreateAsync" />
|
||||
}
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="ViewModel.Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
@code
|
||||
{
|
||||
|
|
|
@ -94,7 +94,13 @@ public class ProductCategoryActionDialogBoxViewModel:BaseViewModel
|
|||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new AppException("Token is null");
|
||||
var request = new CreateProductCategoryCommand(Name, Description, IsMain, SelectedCategory?.Id ?? default, Files.ToList());
|
||||
var request = new CreateProductCategoryCommand(Name,
|
||||
Description,
|
||||
IsMain,
|
||||
SelectedCategory?.Id ?? default,
|
||||
Files.ToList(),
|
||||
Faqs,
|
||||
new Dictionary<string, string>());
|
||||
await _restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Create<CreateProductCategoryCommand>(request, token);
|
||||
_mudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
|
@ -127,7 +133,14 @@ public class ProductCategoryActionDialogBoxViewModel:BaseViewModel
|
|||
IsProcessing = true;
|
||||
await Task.Delay(1000);
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
var request = new UpdateProductCategoryCommand(Category.Id, Name, Description, IsMain, SelectedCategory?.Id ?? default, Files.ToList());
|
||||
var request = new UpdateProductCategoryCommand(Category.Id,
|
||||
Name,
|
||||
Description,
|
||||
IsMain,
|
||||
SelectedCategory?.Id ?? default,
|
||||
Files.ToList(),
|
||||
Faqs,
|
||||
new Dictionary<string, string>());
|
||||
await _restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Update<UpdateProductCategoryCommand>(request, token);
|
||||
_mudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
|
@ -177,6 +190,28 @@ public class ProductCategoryActionDialogBoxViewModel:BaseViewModel
|
|||
}
|
||||
|
||||
|
||||
|
||||
public string FaqQuestion { get; set; } = string.Empty;
|
||||
public string FaqAnswer { get; set; } = string.Empty;
|
||||
public Dictionary<string, string> Faqs = new();
|
||||
public void AddFaq()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (FaqAnswer.IsNullOrEmpty())
|
||||
throw new Exception("لطفا پاسخ را وارد کنید");
|
||||
|
||||
if (FaqQuestion.IsNullOrEmpty())
|
||||
throw new Exception("لطفا سوال را وارد کنید");
|
||||
|
||||
Faqs.Add(FaqQuestion, FaqAnswer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SelectFileAsync()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
|
|
|
@ -64,44 +64,11 @@
|
|||
<MudMainContent class="bg-[--mud-palette-background-grey] h-screen overflow-y-auto">
|
||||
@Body
|
||||
</MudMainContent>
|
||||
<div dir="ltr">
|
||||
<PWAUpdater Text="@_updateText" ButtonCaption="اپدیت کنید" />
|
||||
</div>
|
||||
</MudLayout>
|
||||
</MudRTLProvider>
|
||||
|
||||
@* <MudRTLProvider RightToLeft="true">
|
||||
<MudThemeProvider IsDarkMode="@MainTheme.IsDarkMode" Theme="@MainTheme.MyCustomTheme"/>
|
||||
<MudDialogProvider/>
|
||||
<MudSnackbarProvider/>
|
||||
<MudLayout>
|
||||
<MudAppBar class="py-2" Color="Color.Transparent" Fixed="false" Elevation="2">
|
||||
<MudHidden Breakpoint="Breakpoint.MdAndUp">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" OnClick="@ToggleDrawer" Edge="Edge.Start"/>
|
||||
</MudHidden>
|
||||
|
||||
|
||||
<RadzenGravatar class="h-14 w-14" Email="@_user?.Email"/>
|
||||
<MudStack class="mr-2" Spacing="0">
|
||||
<MudText Color="Color.Inherit" Typo="Typo.body1"><b>@_user?.FullName</b></MudText>
|
||||
<MudText Color="Color.Inherit" Typo="Typo.caption">@_user?.PhoneNumber</MudText>
|
||||
</MudStack>
|
||||
<MudSpacer/>
|
||||
<MudToggleIconButton @bind-Toggled="@MainTheme.IsDarkMode"
|
||||
Icon="@Icons.Material.Outlined.DarkMode" Color="@Color.Default" Title="تاریک"
|
||||
ToggledIcon="@Icons.Material.Filled.LightMode" ToggledColor="@Color.Default" ToggledTitle="روشن"/>
|
||||
<MudIconButton Size="Size.Medium" Color="Color.Error" OnClick="LogoutAsync" Icon="@Icons.Material.Outlined.ExitToApp"/>
|
||||
</MudAppBar>
|
||||
|
||||
<MudDrawer @bind-Open="@open" ClipMode="DrawerClipMode.Always" Breakpoint="Breakpoint.MdAndUp" Elevation="1" Variant="@DrawerVariant.Responsive">
|
||||
<SideBarUi/>
|
||||
</MudDrawer>
|
||||
|
||||
<MudMainContent class="h-screen">
|
||||
@Body
|
||||
</MudMainContent>
|
||||
</MudLayout>
|
||||
<div dir="ltr">
|
||||
<PWAUpdater Align="PWAUpdater.Aligns.Buttom" Text="@_updateText" ButtonCaption="اپدیت کنید"/>
|
||||
</div>
|
||||
</MudRTLProvider> *@
|
||||
</Authorized>
|
||||
|
||||
<NotAuthorized>
|
||||
|
|
|
@ -23,4 +23,5 @@ public static class Address
|
|||
public static string DashboardController => $"/dashboard";
|
||||
public static string SettingController => $"/setting";
|
||||
public static string DistrictController => $"/district";
|
||||
public static string FaqController => $"/faq";
|
||||
}
|
|
@ -19,7 +19,7 @@ public class BaseViewModel<TPageDto>
|
|||
public bool IsProcessing { get; set; } = false;
|
||||
public TPageDto PageDto { get; set; }
|
||||
private string[] _permissions = new string[]{};
|
||||
private readonly IUserUtility _userUtility;
|
||||
protected readonly IUserUtility _userUtility;
|
||||
public bool IsPermitted { get; set; } = false;
|
||||
public BaseViewModel(IUserUtility userUtility,params string[] permissions)
|
||||
{
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
|
||||
<AssemblyVersion>1.1.10.15</AssemblyVersion>
|
||||
<FileVersion>1.1.10.15</FileVersion>
|
||||
<AssemblyVersion>1.3.12.16</AssemblyVersion>
|
||||
<FileVersion>1.3.12.16</FileVersion>
|
||||
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
|
@ -34,6 +34,12 @@
|
|||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="wwwroot\assets\vendor\ckeditor5.css.map" />
|
||||
<None Include="wwwroot\assets\vendor\ckeditor5.js" />
|
||||
<None Include="wwwroot\assets\vendor\ckeditor5.js.map" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Append.Blazor.Printing" Version="6.3.0" />
|
||||
<PackageReference Include="Blazored.LocalStorage" Version="4.4.0" />
|
||||
|
@ -55,7 +61,7 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Netina\Netina.Domain\Netina.Domain.csproj" />
|
||||
<ProjectReference Include="..\..\Api\Netina.Domain\Netina.Domain.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -90,6 +96,7 @@
|
|||
<Using Include="Netina.Domain.Entities.ProductCategories" />
|
||||
<Using Include="Netina.Domain.Entities.Products" />
|
||||
<Using Include="Netina.Domain.Enums" />
|
||||
<Using Include="Netina.Domain.Extensions" />
|
||||
<Using Include="Netina.Domain.MartenEntities.Pages" />
|
||||
<Using Include="Netina.Domain.MartenEntities.Settings" />
|
||||
<Using Include="Netina.Domain.Models.Districts" />
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@page "/management/faqs"
|
||||
@page "/setting/faq"
|
||||
|
||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||
|
||||
@inject IDialogService DialogService
|
||||
|
@ -10,45 +11,54 @@
|
|||
<MudStack class="h-full w-full p-8">
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
<MudStack Row="true" class="mb-8">
|
||||
<MudText Typo="Typo.h4">سوالات متداول فروشگاه من</MudText>
|
||||
<MudStack Row="true" class="mb-5">
|
||||
<MudText Typo="Typo.h4">سوالات متداول</MudText>
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Filled" Size="Size.Large" Color="Color.Success" OnClick="@ViewModel.SaveAsync">ذخیره سوالات</MudButton>
|
||||
<MudButton Variant="Variant.Filled"
|
||||
DisableElevation="true"
|
||||
StartIcon="@Icons.Material.Outlined.Add"
|
||||
Color="Color.Secondary"
|
||||
OnClick="@ViewModel.AddClicked"
|
||||
class="my-auto">افزودن سوالات متداول جدید</MudButton>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem sm="4">
|
||||
<MudTextField T="string" Label="سوال" @bind-Value="@ViewModel.Question" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem sm="6">
|
||||
<MudTextField T="string" Label="پاسخ" @bind-Value="@ViewModel.Answer" Variant="Variant.Outlined"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem>
|
||||
<MudButton class="mt-2 py-3" EndIcon="@Icons.Material.Outlined.Add"
|
||||
Variant="Variant.Outlined" Size="Size.Large" Color="Color.Info" OnClick="@ViewModel.AddNewQuestion">افزودن</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
<MudPaper>
|
||||
<MudExpansionPanels class="mt-8">
|
||||
@foreach (var item in ViewModel.PageDto.Faqs)
|
||||
{
|
||||
<MudExpansionPanel>
|
||||
|
||||
<TitleContent>
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
T="BaseFaq" Items="@ViewModel.PageDto" Filterable="false"
|
||||
CurrentPage="@ViewModel.CurrentPage"
|
||||
RowsPerPage="20"
|
||||
Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false">
|
||||
<Columns>
|
||||
<PropertyColumn Title="عنوان" Property="arg => arg.Title" />
|
||||
<PropertyColumn Title="اسلاگ" Property="arg => arg.Slug" />
|
||||
<PropertyColumn T="BaseFaq" TProperty="int" Title="تعداد سوالات" Property="arg => arg.Faqs.Count" />
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Error"
|
||||
OnClick="()=>ViewModel.RemoveQuestion(item.Key)" />
|
||||
<MudText>@item.Key</MudText>
|
||||
</MudStack>
|
||||
</TitleContent>
|
||||
<ChildContent>
|
||||
@item.Value
|
||||
</ChildContent>
|
||||
</MudExpansionPanel>
|
||||
}
|
||||
</MudExpansionPanels>
|
||||
Color="@Color.Info"
|
||||
OnClick="async()=>await ViewModel.EditClicked(context.Item)" />
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="async () => await ViewModel.DeleteAsync(context.Item.Id)"
|
||||
Color="@Color.Error" />
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
<PagerContent>
|
||||
<MudStack Row="true" class="w-full">
|
||||
|
||||
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.PageCount"
|
||||
SelectedChanged="@ViewModel.ChangePageAsync" class="mx-auto my-4" />
|
||||
</MudStack>
|
||||
|
||||
</PagerContent>
|
||||
</MudDataGrid>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
@ -59,8 +69,8 @@
|
|||
public FaqManagementPageViewModel ViewModel { get; set; }
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ViewModel = new FaqManagementPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||
ViewModel = new FaqManagementPageViewModel(DialogService, NavigationManager, RestWrapper, Snackbar, UserUtility);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,72 +1,25 @@
|
|||
namespace Netina.AdminPanel.PWA.Pages;
|
||||
using Netina.Domain.MartenEntities.Faqs;
|
||||
|
||||
public class FaqManagementPageViewModel : BaseViewModel<FAQPage>
|
||||
namespace Netina.AdminPanel.PWA.Pages;
|
||||
|
||||
public class FaqManagementPageViewModel(
|
||||
IDialogService dialogService,
|
||||
NavigationManager navigationManager,
|
||||
IRestWrapper restWrapper,
|
||||
ISnackbar snackbar,
|
||||
IUserUtility userUtility)
|
||||
: BaseViewModel<ObservableCollection<BaseFaq>> (userUtility)
|
||||
{
|
||||
private readonly NavigationManager _navigationManager;
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly IUserUtility _userUtility;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
public int CurrentPage = 0;
|
||||
public int PageCount = 2;
|
||||
|
||||
public FaqManagementPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService) : base(userUtility)
|
||||
{
|
||||
_navigationManager = navigationManager;
|
||||
_snackbar = snackbar;
|
||||
_userUtility = userUtility;
|
||||
_restWrapper = restWrapper;
|
||||
_dialogService = dialogService;
|
||||
}
|
||||
|
||||
|
||||
public string Question { get; set; } = string.Empty;
|
||||
public string Answer { get; set; } = string.Empty;
|
||||
private PageActionRequestDto? _request;
|
||||
public override async Task InitializeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
IsProcessing = true;
|
||||
PageDto.Faqs.Clear();
|
||||
var typeName = typeof(FAQPage).FullName;
|
||||
var dto = await _restWrapper.PageRestApi.ReadByType(typeName, token);
|
||||
if (!dto.Data.IsNullOrEmpty())
|
||||
{
|
||||
|
||||
PageDto = dto.GetData<FAQPage>();
|
||||
_request = new PageActionRequestDto
|
||||
{
|
||||
Title = dto.Title,
|
||||
Content = dto.Content,
|
||||
Description = dto.Description,
|
||||
Id = dto.Id,
|
||||
IsCustomPage = dto.IsCustomPage,
|
||||
IsHtmlBasePage = dto.IsHtmlBasePage,
|
||||
Slug = dto.Slug,
|
||||
Type = typeof(FAQPage).FullName
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
await GetEntitiesAsync();
|
||||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
public async Task SaveAsync()
|
||||
public async Task GetEntitiesAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -74,64 +27,97 @@ public class FaqManagementPageViewModel : BaseViewModel<FAQPage>
|
|||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
IsProcessing = true;
|
||||
var request = new PageActionRequestDto
|
||||
{
|
||||
Title = "سوالات متداول",
|
||||
Content = string.Empty,
|
||||
Description = string.Empty,
|
||||
Data = PageDto,
|
||||
IsCustomPage = true,
|
||||
IsHtmlBasePage = false,
|
||||
Slug = "faq",
|
||||
Type = typeof(FAQPage).FullName
|
||||
};
|
||||
if (_request != null)
|
||||
{
|
||||
request = _request;
|
||||
}
|
||||
request.Data = PageDto;
|
||||
await _restWrapper.PageRestApi.CreatePage(request, token);
|
||||
var faqs = await restWrapper.FaqApiRest.GetFaqs(CurrentPage, token);
|
||||
PageDto.Clear();
|
||||
faqs.ForEach(f => PageDto.Add(f));
|
||||
if (PageDto.Count % 20 == 0)
|
||||
PageCount = CurrentPage + 2;
|
||||
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
if (ex.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
await userUtility.LogoutAsync();
|
||||
navigationManager.NavigateTo("login", true, true);
|
||||
}
|
||||
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
public void AddNewQuestion()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Question.IsNullOrEmpty())
|
||||
throw new Exception("سوال را وارد کنید");
|
||||
if (Answer.IsNullOrEmpty())
|
||||
throw new Exception("پاسخ را وارد کنید");
|
||||
|
||||
PageDto.Faqs.Add(Question,Answer);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
public void RemoveQuestion(string question)
|
||||
|
||||
public async Task ChangePageAsync(int page)
|
||||
{
|
||||
try
|
||||
CurrentPage = page - 1;
|
||||
await GetEntitiesAsync();
|
||||
}
|
||||
|
||||
public async Task AddClicked()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions()
|
||||
{ MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
var reference = await dialogService.ShowAsync<FaqActionDialogBox>("افزودن اژانس هواپیمایی جدید", maxWidth);
|
||||
var result = await reference.Result;
|
||||
if (result.Data is bool and true)
|
||||
await InitializeAsync();
|
||||
}
|
||||
|
||||
public async Task EditClicked(BaseFaq item)
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions()
|
||||
{ MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
var parameters = new DialogParameters<FaqActionDialogBox>();
|
||||
parameters.Add(x => x.Faq, item);
|
||||
var reference = await dialogService.ShowAsync<FaqActionDialogBox>($"ویرایش سوالات متداول {item.Title}", parameters, maxWidth);
|
||||
var result = await reference.Result;
|
||||
if (result.Data is bool and true)
|
||||
await InitializeAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteAsync(Guid selectedId)
|
||||
{
|
||||
var reference = await dialogService.ShowQuestionDialog($"آیا از حذف سوالات متداول مورد نظر اطمینان دارید ?");
|
||||
var result = await reference.Result;
|
||||
if (!result.Canceled)
|
||||
{
|
||||
PageDto.Faqs.Remove(question);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
await restWrapper.FaqApiRest.Delete(selectedId, token);
|
||||
await InitializeAsync();
|
||||
snackbar.Add("حذف سوالات متداول با موفقیت انجام شد", Severity.Success);
|
||||
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
@page "/setting/pages"
|
||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||
|
||||
@inject IDialogService DialogService
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IRestWrapper RestWrapper
|
||||
|
||||
<MudStack class="h-full w-full p-8">
|
||||
<MudStack class="mx-2 mb-5">
|
||||
<MudText Typo="Typo.h4">تنظیمات برگه ها</MudText>
|
||||
<MudText Typo="Typo.caption">برگه های وب سایت خود را ویرایش نمایید</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudPaper class="px-5 py-5">
|
||||
<MudStack>
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
<MudText class="mb-5 mt-4" Typo="Typo.h6">افزودن لینک حذف شده</MudText>
|
||||
|
||||
<MudGrid>
|
||||
<MudItem xs="10">
|
||||
<MudTextField @bind-Value="@ViewModel.NewDeletedPage.Url" T="string" Label="لینک" Variant="Variant.Outlined" />
|
||||
</MudItem>
|
||||
<MudItem xs="2">
|
||||
<MudButton class="mt-1 w-full py-3" Variant="Variant.Outlined" Color="Color.Secondary" OnClick="ViewModel.AddDeletedPage">افزودن +</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
</MudItem>
|
||||
<MudItem xs="12">
|
||||
|
||||
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
T="DeletedPageItem" Items="@ViewModel.DeletedPages" CurrentPage="@ViewModel.DeletedPagesCurrentPage"
|
||||
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false">
|
||||
<Columns>
|
||||
<PropertyColumn Title="لینک حذف شده" Property="arg => arg.Url" />
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="async () => await ViewModel.RemoveDeletedPageAsync(context.Item)"
|
||||
Color="@Color.Error" />
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
<PagerContent>
|
||||
<MudStack Row="true" class="w-full">
|
||||
|
||||
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.DeletedPagesCount"
|
||||
SelectedChanged="@ViewModel.DeletedPagesChangePageAsync" class="mx-auto my-4" />
|
||||
</MudStack>
|
||||
|
||||
</PagerContent>
|
||||
</MudDataGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
<MudPaper class="px-5 py-5">
|
||||
<MudStack>
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
<MudText class="mb-5 mt-4" Typo="Typo.h6">افزودن ریدایرکت جدید</MudText>
|
||||
|
||||
<MudGrid>
|
||||
<MudItem xs="5">
|
||||
<MudTextField @bind-Value="@ViewModel.NewRedirectItem.OldUrl" T="string" Label="لینک قدیمی" Variant="Variant.Outlined" />
|
||||
</MudItem>
|
||||
<MudItem xs="5">
|
||||
<MudTextField @bind-Value="@ViewModel.NewRedirectItem.NewUrl" T="string" Label="لینک جدید" Variant="Variant.Outlined" />
|
||||
</MudItem>
|
||||
<MudItem xs="2">
|
||||
<MudButton class="mt-1 w-full py-3" Variant="Variant.Outlined" Color="Color.Secondary" OnClick="ViewModel.AddPageAsync">افزودن +</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
</MudItem>
|
||||
<MudItem xs="12">
|
||||
|
||||
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
T="RedirectItem" Items="@ViewModel.RedirectItems" CurrentPage="@ViewModel.RedirectItemsCurrentPage"
|
||||
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false">
|
||||
<Columns>
|
||||
<PropertyColumn Title="لینک قدیمی" Property="arg => arg.OldUrl" />
|
||||
<PropertyColumn Title="لینک جدید" Property="arg => arg.NewUrl" />
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="async () => await ViewModel.RemovePageAsync(context.Item)"
|
||||
Color="@Color.Error" />
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
<PagerContent>
|
||||
<MudStack Row="true" class="w-full">
|
||||
|
||||
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.RedirectItemPageCount"
|
||||
SelectedChanged="@ViewModel.RedirectItemChangePageAsync" class="mx-auto my-4" />
|
||||
</MudStack>
|
||||
|
||||
</PagerContent>
|
||||
</MudDataGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
</MudStack>
|
||||
|
||||
@code
|
||||
{
|
||||
public PagesSettingPageViewModel ViewModel { get; set; }
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ViewModel = new PagesSettingPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,244 @@
|
|||
namespace Netina.AdminPanel.PWA.Pages;
|
||||
|
||||
public class PagesSettingPageViewModel(NavigationManager navigationManager,
|
||||
ISnackbar snackbar,
|
||||
IUserUtility userUtility,
|
||||
IRestWrapper restWrapper,
|
||||
IDialogService dialogService) : BaseViewModel<PageSetting> (userUtility)
|
||||
{
|
||||
public ObservableCollection<RedirectItem> RedirectItems { get; set; } = new ObservableCollection<RedirectItem> ();
|
||||
public ObservableCollection<DeletedPageItem> DeletedPages { get; set; } = new ObservableCollection<DeletedPageItem> ();
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
var pages = await restWrapper.SettingRestApi.GetSettingAsync<PageSetting>(nameof(PageSetting), token);
|
||||
PageDto = pages;
|
||||
RedirectItems.Clear();
|
||||
if (PageDto.RedirectItems.Count > 20)
|
||||
RedirectItemPageCount = RedirectItemsCurrentPage + 2;
|
||||
PageDto.RedirectItems.Skip(RedirectItemsCurrentPage * 20).Take(20).ToList().ForEach(a=>RedirectItems.Add(a));
|
||||
|
||||
DeletedPages.Clear();
|
||||
if (PageDto.DeletedPages.Count > 20)
|
||||
DeletedPagesCount = DeletedPagesCurrentPage + 2;
|
||||
PageDto.DeletedPages.Skip(DeletedPagesCurrentPage * 20).Take(20).ToList().ForEach(a => DeletedPages.Add(a));
|
||||
}
|
||||
catch (ApiException e)
|
||||
{
|
||||
var exe = await e.GetContentAsAsync<ApiResult>();
|
||||
if (e.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
await _userUtility.LogoutAsync();
|
||||
navigationManager.NavigateTo("login", true, true);
|
||||
}
|
||||
snackbar.Add(exe != null ? exe.Message : e.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
snackbar.Add(ex.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
}
|
||||
|
||||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
public int RedirectItemsCurrentPage { get; set; } = 0;
|
||||
public int RedirectItemPageCount { get; set; } = 0;
|
||||
public void RedirectItemChangePageAsync(int page)
|
||||
{
|
||||
RedirectItemsCurrentPage = page - 1;
|
||||
|
||||
if (PageDto.RedirectItems.Count > (RedirectItemsCurrentPage * 20))
|
||||
RedirectItemPageCount = RedirectItemsCurrentPage + 2;
|
||||
|
||||
PageDto.RedirectItems.Skip(RedirectItemsCurrentPage * 20).Take(20).ToList().ForEach(a => RedirectItems.Add(a));
|
||||
}
|
||||
|
||||
public RedirectItem NewRedirectItem { get; set; } = new();
|
||||
public async Task AddPageAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
|
||||
if (NewRedirectItem.OldUrl.IsNullOrEmpty())
|
||||
throw new AppException("لینک قدیمی را وارد کنید");
|
||||
if (NewRedirectItem.NewUrl.IsNullOrEmpty())
|
||||
throw new AppException("لینک جدید را وارد کنید");
|
||||
var newUrl = StringExtensions.GetSlug(NewRedirectItem.NewUrl);
|
||||
var oldUrl = StringExtensions.GetSlug(NewRedirectItem.OldUrl);
|
||||
var item = new RedirectItem
|
||||
{
|
||||
NewUrl = newUrl,
|
||||
OldUrl = oldUrl
|
||||
};
|
||||
if (PageDto.RedirectItems.Any(c => c.OldUrl == item.OldUrl))
|
||||
throw new AppException("لینک مورد نظر قبلا اضافه شده است");
|
||||
PageDto.RedirectItems.Add(item);
|
||||
await restWrapper.SettingRestApi.PostSettingAsync(nameof(PageSetting), PageDto, token);
|
||||
NewRedirectItem = new RedirectItem();
|
||||
snackbar.Add("لینک ریدایرکت با موفقیت افزوده شد", Severity.Success);
|
||||
await InitializeAsync();
|
||||
|
||||
}
|
||||
catch (ApiException e)
|
||||
{
|
||||
var exe = await e.GetContentAsAsync<ApiResult>();
|
||||
if (e.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
await _userUtility.LogoutAsync();
|
||||
navigationManager.NavigateTo("login", true, true);
|
||||
}
|
||||
snackbar.Add(exe != null ? exe.Message : e.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
snackbar.Add(ex.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
public async Task RemovePageAsync(RedirectItem item)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
PageDto.RedirectItems.Remove(item);
|
||||
await restWrapper.SettingRestApi.PostSettingAsync(nameof(PageSetting), PageDto, token);
|
||||
snackbar.Add("لینک ریدایرکت مورد نظر با موفقیت حذف شد", Severity.Success);
|
||||
await InitializeAsync();
|
||||
|
||||
|
||||
}
|
||||
catch (ApiException e)
|
||||
{
|
||||
var exe = await e.GetContentAsAsync<ApiResult>();
|
||||
if (e.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
await _userUtility.LogoutAsync();
|
||||
navigationManager.NavigateTo("login", true, true);
|
||||
}
|
||||
snackbar.Add(exe != null ? exe.Message : e.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
snackbar.Add(ex.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public DeletedPageItem NewDeletedPage { get; set; } = new();
|
||||
public async Task AddDeletedPage()
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
|
||||
if (NewDeletedPage.Url.IsNullOrEmpty())
|
||||
throw new AppException("لینک حذف شده را وارد کنید");
|
||||
var item = new DeletedPageItem()
|
||||
{
|
||||
Url = NewDeletedPage.Url
|
||||
};
|
||||
if (PageDto.DeletedPages.Any(c => c.Url == item.Url))
|
||||
throw new AppException("لینک مورد نظر قبلا اضافه شده است");
|
||||
|
||||
PageDto.DeletedPages.Add(NewDeletedPage);
|
||||
DeletedPages.Add(NewDeletedPage);
|
||||
await restWrapper.SettingRestApi.PostSettingAsync(nameof(PageSetting), PageDto, token);
|
||||
NewRedirectItem = new RedirectItem();
|
||||
snackbar.Add("لینک حذف با موفقیت افزوده شد", Severity.Success);
|
||||
await InitializeAsync();
|
||||
|
||||
}
|
||||
catch (ApiException e)
|
||||
{
|
||||
var exe = await e.GetContentAsAsync<ApiResult>();
|
||||
if (e.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
await _userUtility.LogoutAsync();
|
||||
navigationManager.NavigateTo("login", true, true);
|
||||
}
|
||||
snackbar.Add(exe != null ? exe.Message : e.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
snackbar.Add(ex.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task RemoveDeletedPageAsync(DeletedPageItem item)
|
||||
{
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
PageDto.DeletedPages.Remove(item);
|
||||
await restWrapper.SettingRestApi.PostSettingAsync(nameof(PageSetting), PageDto, token);
|
||||
snackbar.Add("لینک مورد نظر با موفقیت حذف شد", Severity.Success);
|
||||
await InitializeAsync();
|
||||
|
||||
|
||||
}
|
||||
catch (ApiException e)
|
||||
{
|
||||
var exe = await e.GetContentAsAsync<ApiResult>();
|
||||
if (e.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
await _userUtility.LogoutAsync();
|
||||
navigationManager.NavigateTo("login", true, true);
|
||||
}
|
||||
snackbar.Add(exe != null ? exe.Message : e.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
snackbar.Add(ex.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
|
||||
public int DeletedPagesCurrentPage { get; set; } = 0;
|
||||
public int DeletedPagesCount { get; set; } = 0;
|
||||
public void DeletedPagesChangePageAsync(int page)
|
||||
{
|
||||
DeletedPagesCurrentPage = page - 1;
|
||||
|
||||
if (PageDto.RedirectItems.Count > (DeletedPagesCurrentPage * 20))
|
||||
DeletedPagesCount = DeletedPagesCurrentPage + 2;
|
||||
|
||||
PageDto.DeletedPages.Skip(DeletedPagesCurrentPage * 20).Take(20).ToList().ForEach(a => DeletedPages.Add(a));
|
||||
}
|
||||
}
|
|
@ -133,7 +133,7 @@ public class ManageNavMenuPageViewModel : BaseViewModel<NavMenuSetting>
|
|||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
var response = await _restWrapper.ProductRestApi.ReadAll(0,product,null,null);
|
||||
var response = await _restWrapper.ProductRestApi.ReadAll(0,product,null,null,token);
|
||||
var categories = response.Products;
|
||||
if (product.IsNullOrEmpty())
|
||||
return categories;
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
@page "/personaliztion/main"
|
||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||
|
||||
@inject IDialogService DialogService
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IRestWrapper RestWrapper
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject IConfiguration Configuration
|
||||
@inject IJSRuntime JsRuntime
|
||||
|
||||
|
||||
<MudStack class="h-full w-full p-8">
|
||||
<MudPaper class="px-5 py-5">
|
||||
<MudStack Row="true">
|
||||
<MudStack class="mx-2 mb-5">
|
||||
<MudText Typo="Typo.h4">اطلاعات بنر ها وکاتالوگ</MudText>
|
||||
<MudText Typo="Typo.caption">بنر ها و کاتالوگ در صفحه اصلی و دیگر صفحه ها نمایش داده خواهند شد</MudText>
|
||||
</MudStack>
|
||||
<MudSpacer />
|
||||
<BaseButtonUi Size="Size.Large"
|
||||
OnClickCallback="ViewModel.SubmitSettingAsync"
|
||||
class="mb-8 mt-2 w-64 rounded-md"
|
||||
IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Content="ثبتـــ اطلاعات" Variant="Variant.Filled" Color="Color.Success" />
|
||||
</MudStack>
|
||||
<MudDivider />
|
||||
|
||||
<MudStack class="mt-3">
|
||||
<MudText Typo="Typo.h6">بنر های سایت شما</MudText>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem xs="12" md="4">
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.NewBanner.Title" class="my-2" Variant="Variant.Outlined" Label="عنوان بنر"></MudTextField>
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.NewBanner.Link" class="my-2" Variant="Variant.Outlined" Label="لینک بنر"></MudTextField>
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.NewBanner.Description" class="my-2" Variant="Variant.Outlined" Label="توضیحات بنر"></MudTextField>
|
||||
<MudSelect Variant="Variant.Outlined" class="my-2" T="BannerSection" ToStringFunc="type => type.ToDisplay()" Label="محل قرارگیری بنر" @bind-Value="ViewModel.NewBanner.Section">
|
||||
@foreach (var state in Enum.GetValues(typeof(BannerSection)).Cast<BannerSection>())
|
||||
{
|
||||
<MudSelectItem T="BannerSection" Value="@state"></MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (ViewModel.NewBanner.ImageLocation.IsNullOrEmpty())
|
||||
{
|
||||
<MudButton class="mt-3"
|
||||
Variant="Variant.Outlined"
|
||||
FullWidth="true"
|
||||
Color="Color.Info"
|
||||
OnClick="@ViewModel.SelectFileAsync">انتخاب تصویر بنر</MudButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudButton class="mt-3"
|
||||
Variant="Variant.Filled"
|
||||
FullWidth="true"
|
||||
Color="Color.Info"
|
||||
OnClick="@ViewModel.SelectFileAsync">انتخاب تصویر دیگر</MudButton>
|
||||
}
|
||||
<MudButton class="mt-3"
|
||||
Variant="Variant.Outlined"
|
||||
FullWidth="true"
|
||||
Color="Color.Info"
|
||||
OnClick="@ViewModel.AddBanner">افزودن بنر</MudButton>
|
||||
</MudItem>
|
||||
<MudItem xs="12" md="8">
|
||||
|
||||
<MudDataGrid Items="@ViewModel.PageDto.Banners"
|
||||
T="BannerItemModel"
|
||||
Elevation="0"
|
||||
Outlined="true"
|
||||
Bordered="true"
|
||||
Striped="false"
|
||||
Dense="true"
|
||||
Filterable="false"
|
||||
SortMode="@SortMode.None"
|
||||
Groupable="false">
|
||||
<Columns>
|
||||
<PropertyColumn T="BannerItemModel" TProperty="string" Property="x => x.Title" Title="نام فارسی" />
|
||||
<TemplateColumn T="BannerItemModel" Title="جایگاه بنر" CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudText Align="Align.Center">@context.Item.Section.ToDisplay()</MudText>
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<PropertyColumn T="BannerItemModel" TProperty="string" Property="x => x.Description" Title="نام انگلیسی" />
|
||||
|
||||
<TemplateColumn T="BannerItemModel" CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
|
||||
<MudButton DisableElevation="true"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="async()=>await ShowBannerPhoto(context.Item.ImageLocation)"
|
||||
Color="@Color.Info"
|
||||
StartIcon="@Icons.Material.Filled.RemoveRedEye">مشاهده تصویر</MudButton>
|
||||
|
||||
<MudButton DisableElevation="true"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="async()=>await ShowBannerLink(context.Item.Link)"
|
||||
Color="@Color.Info"
|
||||
StartIcon="@Icons.Material.Outlined.AttachFile">مشاهده لینک</MudButton>
|
||||
|
||||
<MudButton DisableElevation="true"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="() => ViewModel.PageDto.Banners.Remove(context.Item)"
|
||||
Color="@Color.Error"
|
||||
StartIcon="@Icons.Material.Outlined.Delete">حذف</MudButton>
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
</MudDataGrid>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
<MudDivider class="mt-5" />
|
||||
|
||||
<MudStack class="mb-1 mt-3" Spacing="0">
|
||||
<MudText Typo="Typo.h6">کاتالوگ سایت شما</MudText>
|
||||
<MudText Typo="Typo.caption">کاتالوگ به لیست فهرست مانند صفحه اصلی گفته میشود که تورهای مختلف را نمایش میدهد</MudText>
|
||||
</MudStack>
|
||||
<MudGrid>
|
||||
<MudItem xs="12" sm="6" lg="1">
|
||||
<MudTextField T="int" @bind-Value="@ViewModel.NewCatalogItem.Row" Variant="Variant.Outlined" Label="ردیف"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="6" lg="4">
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.NewCatalogItem.PersianName" Variant="Variant.Outlined" Label="نام فارسی کاتالوگ"></MudTextField>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="6" lg="4">
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.NewCatalogItem.EnglishName" Variant="Variant.Outlined" Label="نام انگلیسی"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" sm="6" lg="3">
|
||||
<MudAutocomplete ToStringFunc="dto => dto.PersianName"
|
||||
T="CatalogItemModel"
|
||||
@bind-Value="ViewModel.SelectedCatalog"
|
||||
MaxItems="306"
|
||||
SearchFunc="ViewModel.SearchCatalog"
|
||||
Label="کاتالوگ پدر"
|
||||
Variant="Variant.Outlined">
|
||||
<ItemTemplate Context="e">
|
||||
|
||||
<p>@e.PersianName</p>
|
||||
</ItemTemplate>
|
||||
</MudAutocomplete>
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="6" lg="6">
|
||||
<MudTextField T="string" @bind-Value="@ViewModel.NewCatalogItem.Query" Variant="Variant.Outlined" Label="کوئری"></MudTextField>
|
||||
</MudItem>
|
||||
|
||||
|
||||
<MudItem xs="12" sm="6" lg="3">
|
||||
@if (ViewModel.CatalogImage.IsNullOrEmpty())
|
||||
{
|
||||
<MudButton class="mt-3 py-3"
|
||||
Variant="Variant.Outlined"
|
||||
FullWidth="true"
|
||||
Color="Color.Info"
|
||||
OnClick="@ViewModel.SelectCatalogFileAsync">انتخاب تصویر کاتالوگ</MudButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudButton class="mt-3 py-3"
|
||||
Variant="Variant.Filled"
|
||||
FullWidth="true"
|
||||
Color="Color.Info"
|
||||
OnClick="@ViewModel.SelectCatalogFileAsync">انتخاب تصویر دیگر</MudButton>
|
||||
}
|
||||
</MudItem>
|
||||
<MudItem xs="12" sm="6" lg="2">
|
||||
|
||||
<MudButton Variant="Variant.Outlined"
|
||||
FullWidth="true"
|
||||
class="mt-2 py-3"
|
||||
Color="Color.Info"
|
||||
OnClick="@ViewModel.AddCatalogItem">+</MudButton>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
|
||||
<MudDataGrid Items="@ViewModel.PageDto.Catalog"
|
||||
T="CatalogItemModel"
|
||||
class="mt-2"
|
||||
Elevation="0"
|
||||
Outlined="true"
|
||||
Bordered="false"
|
||||
Dense="true"
|
||||
Striped="false"
|
||||
Filterable="false"
|
||||
SortMode="@SortMode.None"
|
||||
Groupable="false">
|
||||
<Columns>
|
||||
<PropertyColumn T="CatalogItemModel" TProperty="int" Property="x => x.Row" Title=" " />
|
||||
<PropertyColumn T="CatalogItemModel" TProperty="string" Property="x => x.PersianName" Title="نام فارسی" />
|
||||
<PropertyColumn T="CatalogItemModel" TProperty="string" Property="x => x.ParentName" Title="دسته پدر" />
|
||||
<PropertyColumn T="CatalogItemModel" TProperty="string" Property="x => x.EnglishName" Title="نام انگلیسی" />
|
||||
<PropertyColumn T="CatalogItemModel" TProperty="string" Property="x => x.Query" Title="کوئری" />
|
||||
<TemplateColumn T="CatalogItemModel" CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row>
|
||||
<MudButton DisableElevation="true"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="() => ViewModel.PageDto.Catalog.Remove(context.Item)"
|
||||
Color="@Color.Error"
|
||||
StartIcon="@Icons.Material.Outlined.Delete">حذف</MudButton>
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
</MudDataGrid>
|
||||
</MudPaper>
|
||||
</MudStack>
|
||||
|
||||
|
||||
@code
|
||||
{
|
||||
public PersonalizationPageViewModel ViewModel { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ViewModel = new PersonalizationPageViewModel(DialogService, RestWrapper, Snackbar, NavigationManager, UserUtility);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private async Task ShowBannerPhoto(string photoUrl)
|
||||
{
|
||||
var webUrl = Configuration.GetValue<string>("StorageBaseUrl") ?? string.Empty;
|
||||
var url = $"{webUrl}/{photoUrl}";
|
||||
await JsRuntime.InvokeVoidAsyncIgnoreErrors("open", url, "_blank");
|
||||
}
|
||||
private async Task ShowBannerLink(string url)
|
||||
{
|
||||
await JsRuntime.InvokeVoidAsyncIgnoreErrors("open", url, "_blank");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
using System.Net.Http.Json;
|
||||
|
||||
namespace Netina.AdminPanel.PWA.Pages.Personalization;
|
||||
|
||||
public class PersonalizationPageViewModel(IDialogService dialogService, IRestWrapper restWrapper,
|
||||
ISnackbar snackbar, NavigationManager navigationManager, IUserUtility userUtility)
|
||||
: BaseViewModel<PersonalizationSetting>(userUtility: userUtility)
|
||||
{
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
var personalizationSetting = await restWrapper.SettingRestApi.GetSettingAsync<PersonalizationSetting>(nameof(PersonalizationSetting), token);
|
||||
personalizationSetting.Catalog = personalizationSetting.Catalog.OrderBy(c => c.Row).ToList();
|
||||
PageDto = personalizationSetting;
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
if (ex.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
await userUtility.LogoutAsync();
|
||||
navigationManager.NavigateTo("login", true, true);
|
||||
}
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
|
||||
|
||||
await base.InitializeAsync();
|
||||
}
|
||||
|
||||
public async Task SubmitSettingAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
await restWrapper.SettingRestApi.PostSettingAsync(nameof(PersonalizationSetting), PageDto, token);
|
||||
snackbar.Add("تنظیمات شخصی سازی با موفقیت تغییر یافت", Severity.Success);
|
||||
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
if (ex.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
await userUtility.LogoutAsync();
|
||||
navigationManager.NavigateTo("login", true, true);
|
||||
}
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
public BannerItemModel NewBanner { get; set; } = new();
|
||||
public CatalogItemModel NewCatalogItem { get; set; } = new();
|
||||
|
||||
public void AddBanner()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (NewBanner.ImageLocation.IsNullOrEmpty())
|
||||
throw new Exception("تصویر بنر انتخاب نشده است");
|
||||
if (NewBanner.Title.IsNullOrEmpty())
|
||||
throw new Exception("عنوان بنر انتخاب نشده است");
|
||||
|
||||
PageDto.Banners.Add(NewBanner);
|
||||
NewBanner = new BannerItemModel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
public async Task SelectFileAsync()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, FullWidth = true, DisableBackdropClick = true };
|
||||
var dialog = await dialogService.ShowAsync<StorageDialogBox>("انتخاب عکس", maxWidth);
|
||||
var result = await dialog.Result;
|
||||
var file = result.Data;
|
||||
if (file is StorageFileSDto storageFile)
|
||||
{
|
||||
NewBanner.ImageLocation = storageFile.FileLocation;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public CatalogItemModel? SelectedCatalog { get; set; }
|
||||
public async Task<IEnumerable<CatalogItemModel>> SearchCatalog(string catelogName)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (catelogName.IsNullOrEmpty())
|
||||
return PageDto.Catalog;
|
||||
return PageDto.Catalog.Where(f => f.PersianName.Contains(catelogName));
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
return new List<CatalogItemModel>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
return new List<CatalogItemModel>();
|
||||
}
|
||||
}
|
||||
|
||||
public string CatalogImage { get; set; } = string.Empty;
|
||||
public async Task SelectCatalogFileAsync()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, FullWidth = true, DisableBackdropClick = true };
|
||||
var dialog = await dialogService.ShowAsync<StorageDialogBox>("انتخاب عکس", maxWidth);
|
||||
var result = await dialog.Result;
|
||||
var file = result.Data;
|
||||
if (file is StorageFileSDto storageFile)
|
||||
{
|
||||
CatalogImage = storageFile.FileLocation;
|
||||
}
|
||||
}
|
||||
public void AddCatalogItem()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (NewCatalogItem.EnglishName.IsNullOrEmpty())
|
||||
throw new Exception("نام انگلیسی را وارد کنید");
|
||||
if (NewCatalogItem.PersianName.IsNullOrEmpty())
|
||||
throw new Exception("نام فارسی ایتم کاتالوگ را وارد کنید");
|
||||
if (NewCatalogItem.Query.IsNullOrEmpty())
|
||||
throw new Exception("کوئری ایتم کاتالوگ را وارد کنید");
|
||||
if (SelectedCatalog != null)
|
||||
{
|
||||
NewCatalogItem.ParentId = SelectedCatalog.Id;
|
||||
NewCatalogItem.ParentName = SelectedCatalog.PersianName;
|
||||
}
|
||||
else
|
||||
NewCatalogItem.IsMain = true;
|
||||
|
||||
if (!CatalogImage.IsNullOrEmpty())
|
||||
NewCatalogItem.ImageLocation = CatalogImage;
|
||||
CatalogImage = string.Empty;
|
||||
NewCatalogItem.Id = Guid.NewGuid();
|
||||
PageDto.Catalog.Add(NewCatalogItem);
|
||||
PageDto.Catalog = PageDto.Catalog.OrderBy(c => c.Row).ToList();
|
||||
NewCatalogItem = new CatalogItemModel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,9 +45,10 @@
|
|||
<MudGrid class="mb-3" Row="true">
|
||||
|
||||
<MudItem xs="12" sm="6">
|
||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start"
|
||||
Immediate="true"
|
||||
Clearable="true"
|
||||
ValueChanged="@ViewModel.SearchChanged"
|
||||
@bind-Value="@ViewModel.Search"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||
OnAdornmentClick="@ViewModel.GetEntitiesAsync"></MudTextField>
|
||||
</MudItem>
|
||||
|
@ -87,9 +88,10 @@
|
|||
<MudGrid class="collapse md:visible">
|
||||
|
||||
<MudItem xs="12" sm="4">
|
||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start"
|
||||
Immediate="true"
|
||||
Clearable="true"
|
||||
ValueChanged="@ViewModel.SearchChanged"
|
||||
@bind-Value="@ViewModel.Search"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||
OnAdornmentClick="@ViewModel.GetEntitiesAsync"></MudTextField>
|
||||
</MudItem>
|
||||
|
@ -134,7 +136,6 @@
|
|||
</TemplateColumn>
|
||||
<PropertyColumn Title="نام محصول" Property="arg => arg.PersianName" />
|
||||
<PropertyColumn Title="دسته بندی" Property="arg => arg.CategoryName" />
|
||||
<PropertyColumn Title="برند" Property="arg => arg.BrandName" />
|
||||
<TemplateColumn T="ProductSDto" Title="پیشنهاد ویژه است">
|
||||
<CellTemplate>
|
||||
@if (@context.Item.IsSpecial)
|
||||
|
@ -165,7 +166,15 @@
|
|||
|
||||
<TemplateColumn T="ProductSDto" Title="قیمتــ">
|
||||
<CellTemplate>
|
||||
<p>@context.Item.Cost.ToString("N0") ریالــ</p>
|
||||
<MudTextField class="-mt-2"
|
||||
Format="N0"
|
||||
T="double"
|
||||
ValueChanged="async(cost) => await ViewModel.ChangeProductCostAsync(context.Item,cost)"
|
||||
AdornmentText="ریالــ"
|
||||
Immediate="false"
|
||||
AdornmentIcon="@Icons.Material.Filled.Check"
|
||||
Adornment="Adornment.End"
|
||||
Value="context.Item.Cost"></MudTextField>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
using MudBlazor.Services;
|
||||
using Netina.Domain.Entities.Products;
|
||||
|
||||
namespace Netina.AdminPanel.PWA.Pages;
|
||||
|
||||
public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductSDto>>
|
||||
public class ProductsPageViewModel(
|
||||
NavigationManager navigationManager,
|
||||
ISnackbar snackbar,
|
||||
IUserUtility userUtility,
|
||||
IRestWrapper restWrapper,
|
||||
IDialogService dialogService,
|
||||
IBrowserViewportService browserViewportService)
|
||||
: BaseViewModel<ObservableCollection<ProductSDto>>(userUtility)
|
||||
{
|
||||
private readonly NavigationManager _navigationManager;
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly IUserUtility _userUtility;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IBrowserViewportService _browserViewportService;
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
private readonly NavigationManager _navigationManager = navigationManager;
|
||||
private readonly IUserUtility _userUtility = userUtility;
|
||||
|
||||
public string? Search = string.Empty;
|
||||
public int CurrentPage = 0;
|
||||
|
@ -18,22 +22,6 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
public bool IsXs = false;
|
||||
public bool IsEnable { get; set; } = true;
|
||||
|
||||
public ProductsPageViewModel(NavigationManager navigationManager,
|
||||
ISnackbar snackbar,
|
||||
IUserUtility userUtility,
|
||||
IRestWrapper restWrapper,
|
||||
IDialogService dialogService,
|
||||
IBrowserViewportService browserViewportService) : base(userUtility)
|
||||
{
|
||||
_navigationManager = navigationManager;
|
||||
_snackbar = snackbar;
|
||||
_userUtility = userUtility;
|
||||
_restWrapper = restWrapper;
|
||||
_dialogService = dialogService;
|
||||
_browserViewportService = browserViewportService;
|
||||
|
||||
}
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
{
|
||||
await GetEntitiesAsync();
|
||||
|
@ -50,21 +38,21 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
IsProcessing = true;
|
||||
PageDto.Clear();
|
||||
var search = Search.IsNullOrEmpty() ? null : Search;
|
||||
var dto = await _restWrapper.ProductRestApi.ReadAll(CurrentPage, search, SelectedCategory?.Id, IsEnable);
|
||||
var dto = await restWrapper.ProductRestApi.ReadAll(CurrentPage, search, SelectedCategory?.Id, IsEnable,token);
|
||||
dto.Products.ForEach(d => PageDto.Add(d));
|
||||
if (PageDto.Count % 20 == 0)
|
||||
PageCount = CurrentPage + 2;
|
||||
TotalItems = dto.Pager.TotalItems;
|
||||
IsXs = (await _browserViewportService.GetCurrentBreakpointAsync()) == Breakpoint.Xs;
|
||||
IsXs = (await browserViewportService.GetCurrentBreakpointAsync()) == Breakpoint.Xs;
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -82,10 +70,10 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
public async Task AddProductClicked()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, FullWidth = true, DisableBackdropClick = true };
|
||||
var breakPoint = await _browserViewportService.GetCurrentBreakpointAsync();
|
||||
var breakPoint = await browserViewportService.GetCurrentBreakpointAsync();
|
||||
if (breakPoint == Breakpoint.Xs)
|
||||
maxWidth = new DialogOptions { FullScreen = true, CloseButton = true };
|
||||
var dialogResult = await _dialogService.ShowAsync<ProductActionDialogBox>("افزودن محصول جدید", maxWidth);
|
||||
var dialogResult = await dialogService.ShowAsync<ProductActionDialogBox>("افزودن محصول جدید", maxWidth);
|
||||
var result = await dialogResult.Result;
|
||||
if (!result.Canceled && result.Data is bool and true)
|
||||
{
|
||||
|
@ -97,10 +85,10 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
public async Task AddFastProductClicked()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, FullWidth = true, NoHeader = true, DisableBackdropClick = true, CloseButton = true };
|
||||
var breakPoint = await _browserViewportService.GetCurrentBreakpointAsync();
|
||||
var breakPoint = await browserViewportService.GetCurrentBreakpointAsync();
|
||||
if (breakPoint == Breakpoint.Xs)
|
||||
maxWidth = new DialogOptions { FullScreen = true, NoHeader = true, CloseButton = true };
|
||||
var dialogResult = await _dialogService.ShowAsync<FastProductCreateDialogBox>("افزودن محصول جدید", maxWidth);
|
||||
var dialogResult = await dialogService.ShowAsync<FastProductCreateDialogBox>("افزودن محصول جدید", maxWidth);
|
||||
var result = await dialogResult.Result;
|
||||
if (!result.Canceled && result.Data is bool and true)
|
||||
{
|
||||
|
@ -111,7 +99,7 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
{
|
||||
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
var dialogResult = await _dialogService.ShowAsync<DigikalaProductActionDialogBox>("افزودن محصول جدید", maxWidth);
|
||||
var dialogResult = await dialogService.ShowAsync<DigikalaProductActionDialogBox>("افزودن محصول جدید", maxWidth);
|
||||
var result = await dialogResult.Result;
|
||||
if (!result.Canceled && result.Data is bool and true)
|
||||
{
|
||||
|
@ -122,12 +110,12 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
public async Task EditProductClicked(ProductSDto product)
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, FullWidth = true, DisableBackdropClick = true };
|
||||
var breakPoint = await _browserViewportService.GetCurrentBreakpointAsync();
|
||||
var breakPoint = await browserViewportService.GetCurrentBreakpointAsync();
|
||||
if (breakPoint == Breakpoint.Xs)
|
||||
maxWidth = new DialogOptions { FullScreen = true, CloseButton = true };
|
||||
var parameters = new DialogParameters<ProductActionDialogBox>();
|
||||
parameters.Add(x => x.Product, product);
|
||||
var dialogResult = await _dialogService.ShowAsync<ProductActionDialogBox>($"ویرایش محصول {product.PersianName}", parameters, maxWidth);
|
||||
var dialogResult = await dialogService.ShowAsync<ProductActionDialogBox>($"ویرایش محصول {product.PersianName}", parameters, maxWidth);
|
||||
var result = await dialogResult.Result;
|
||||
if (!result.Canceled && result.Data is bool and true)
|
||||
{
|
||||
|
@ -137,7 +125,7 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
|
||||
public async Task DeleteProductAsync(Guid selectedCategoryId)
|
||||
{
|
||||
var reference = await _dialogService.ShowQuestionDialog($"آیا از حذف محصول اطمینان دارید ?");
|
||||
var reference = await dialogService.ShowQuestionDialog($"آیا از حذف محصول اطمینان دارید ?");
|
||||
var result = await reference.Result;
|
||||
if (!result.Canceled)
|
||||
{
|
||||
|
@ -147,20 +135,20 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
await _restWrapper.CrudDtoApiRest<Product, ProductSDto, Guid>(Address.ProductController)
|
||||
await restWrapper.CrudDtoApiRest<Product, ProductSDto, Guid>(Address.ProductController)
|
||||
.Delete(selectedCategoryId, token);
|
||||
_snackbar.Add("حذف محصول با موفقیت انجام شد", Severity.Success);
|
||||
snackbar.Add("حذف محصول با موفقیت انجام شد", Severity.Success);
|
||||
await InitializeAsync();
|
||||
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -170,11 +158,10 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
}
|
||||
}
|
||||
|
||||
public async Task SearchChanged(string search)
|
||||
public async Task SearchChanged()
|
||||
{
|
||||
if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
|
||||
if (Search!=null && !Search.IsNullOrEmpty())
|
||||
await InitializeAsync();
|
||||
Search = search;
|
||||
}
|
||||
|
||||
|
||||
|
@ -185,22 +172,22 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
try
|
||||
{
|
||||
if (category.IsNullOrEmpty())
|
||||
_productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(0);
|
||||
_productCategories = await restWrapper.ProductCategoryRestApi.ReadAll(0);
|
||||
else
|
||||
_productCategories = await _restWrapper.ProductCategoryRestApi.ReadAll(category);
|
||||
_productCategories = await restWrapper.ProductCategoryRestApi.ReadAll(category);
|
||||
return _productCategories;
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
if (exe != null)
|
||||
_snackbar.Add(exe.Message, Severity.Error);
|
||||
_snackbar.Add(ex.Content, Severity.Error);
|
||||
snackbar.Add(exe.Message, Severity.Error);
|
||||
snackbar.Add(ex.Content, Severity.Error);
|
||||
return _productCategories;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
return _productCategories;
|
||||
}
|
||||
}
|
||||
|
@ -224,16 +211,16 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
await _restWrapper.ProductRestApi.ChangeDisplayedAsync(product.Id, product.BeDisplayed, token);
|
||||
await restWrapper.ProductRestApi.ChangeDisplayedAsync(product.Id, product.BeDisplayed, token);
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,4 +232,28 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
CurrentPage = 0;
|
||||
await GetEntitiesAsync();
|
||||
}
|
||||
|
||||
public async Task ChangeProductCostAsync(ProductSDto product,double cost)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
await restWrapper.ProductRestApi.ChangeCostAsync(product.Id, cost, token);
|
||||
product.Cost = cost;
|
||||
|
||||
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using Netina.Domain.MartenEntities.Faqs;
|
||||
|
||||
namespace Netina.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
public interface IFaqApiRest
|
||||
{
|
||||
[Delete("/{id}")]
|
||||
Task Delete(Guid id, [Header("Authorization")] string token);
|
||||
|
||||
[Post("")]
|
||||
Task Create([Body] BaseFaq faq, [Header("Authorization")] string token);
|
||||
|
||||
[Put("")]
|
||||
Task Update([Body] BaseFaq faq, [Header("Authorization")] string token);
|
||||
|
||||
[Get("")]
|
||||
Task<List<BaseFaq>> GetFaqs([Query]int page,[Header("Authorization")] string token);
|
||||
|
||||
[Get("/slug")]
|
||||
Task<BaseFaq> ReadOne([Query]string slug);
|
||||
}
|
|
@ -16,6 +16,9 @@ public interface IOrderRestApi
|
|||
|
||||
[Post("/{id}/confirm")]
|
||||
Task<bool> ConfirmOrderStepAsync(Guid id,[Query] OrderStatus nextOrderStatus, [Header("Authorization")] string authorization);
|
||||
|
||||
[Post("/{id}/cancel")]
|
||||
Task<bool> CancelOrderStepAsync(Guid id ,[Header("Authorization")] string authorization);
|
||||
[Post("/{id}/confirm")]
|
||||
Task<bool> ConfirmOrderStepAsync(Guid id, [Query] OrderStatus nextOrderStatus, [Query]string trackingCode, [Header("Authorization")] string authorization);
|
||||
}
|
|
@ -2,17 +2,21 @@
|
|||
|
||||
public interface IProductRestApi
|
||||
{
|
||||
[Put("/{productId}")]
|
||||
[Put("/{productId}/displayed")]
|
||||
Task<bool> ChangeDisplayedAsync(Guid productId, [Query]bool beDisplayed, [Header("Authorization")]string authorization);
|
||||
|
||||
[Put("/{productId}/cost")]
|
||||
Task<bool> ChangeCostAsync(Guid productId, [Query] double cost, [Header("Authorization")] string authorization);
|
||||
|
||||
|
||||
[Get("/{productId}")]
|
||||
Task<GetProductResponseDto> ReadOne(Guid productId);
|
||||
|
||||
[Get("")]
|
||||
Task<GetProductsResponseDto> ReadAll([Query] string productName);
|
||||
Task<GetProductsResponseDto> ReadAll([Query] string productName, [Header("Authorization")] string authorization);
|
||||
|
||||
[Get("")]
|
||||
Task<GetProductsResponseDto> ReadAll([Query] int page, [Query] string? productName, [Query] Guid? categoryId, [Query] bool? isActive);
|
||||
Task<GetProductsResponseDto> ReadAll([Query] int page, [Query] string? productName, [Query] Guid? categoryId, [Query] bool? isActive, [Header("Authorization")] string authorization);
|
||||
|
||||
[Get("")]
|
||||
Task<GetProductsResponseDto> ReadAll([Query] string productName, [Query] Guid categoryId, [Header("Authorization")] string authorization);
|
||||
|
|
|
@ -23,4 +23,5 @@ public interface IRestWrapper
|
|||
public IDashboardApiRest DashboardApiRest { get; }
|
||||
public ISettingRestApi SettingRestApi { get; }
|
||||
public IDistrictApiRest DistrictApiRest { get; }
|
||||
public IFaqApiRest FaqApiRest { get; }
|
||||
}
|
|
@ -1,12 +1,9 @@
|
|||
namespace Netina.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
public class RestWrapper : IRestWrapper
|
||||
public class RestWrapper(IConfiguration configuration) : IRestWrapper
|
||||
{
|
||||
private string baseApiAddress;
|
||||
public RestWrapper(IConfiguration configuration)
|
||||
{
|
||||
baseApiAddress = configuration.GetValue<string>("ApiUrl") ?? string.Empty;
|
||||
}
|
||||
private string baseApiAddress = configuration.GetValue<string>("ApiUrl") ?? string.Empty;
|
||||
|
||||
private static RefitSettings setting = new RefitSettings(new NewtonsoftJsonContentSerializer(new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Newtonsoft.Json.Formatting.Indented,
|
||||
|
@ -39,4 +36,5 @@ public class RestWrapper : IRestWrapper
|
|||
public ISettingRestApi SettingRestApi => RestService.For<ISettingRestApi>($"{baseApiAddress}{Address.SettingController}", setting);
|
||||
public IDashboardApiRest DashboardApiRest => RestService.For<IDashboardApiRest>($"{baseApiAddress}{Address.DashboardController}", setting);
|
||||
public IDistrictApiRest DistrictApiRest => RestService.For<IDistrictApiRest>($"{baseApiAddress}{Address.DistrictController}", setting);
|
||||
public IFaqApiRest FaqApiRest => RestService.For<IFaqApiRest>($"{baseApiAddress}{Address.FaqController}", setting);
|
||||
}
|
|
@ -19,4 +19,5 @@
|
|||
@using Netina.Domain.Entities.Users
|
||||
@using Netina.AdminPanel.PWA.Components.Originals
|
||||
@using Netina.Domain.Models.Claims
|
||||
@using MudBlazor.Services
|
||||
@using MudBlazor.Services
|
||||
@using Netina.Domain.MartenEntities.Faqs
|
|
@ -1,27 +1,5 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"@ckeditor/ckeditor5-alignment": "41.0.0",
|
||||
"@ckeditor/ckeditor5-autoformat": "41.0.0",
|
||||
"@ckeditor/ckeditor5-basic-styles": "41.0.0",
|
||||
"@ckeditor/ckeditor5-block-quote": "41.0.0",
|
||||
"@ckeditor/ckeditor5-editor-classic": "41.0.0",
|
||||
"@ckeditor/ckeditor5-essentials": "41.0.0",
|
||||
"@ckeditor/ckeditor5-font": "41.0.0",
|
||||
"@ckeditor/ckeditor5-heading": "41.0.0",
|
||||
"@ckeditor/ckeditor5-horizontal-line": "41.0.0",
|
||||
"@ckeditor/ckeditor5-html-support": "^41.0.0",
|
||||
"@ckeditor/ckeditor5-image": "41.0.0",
|
||||
"@ckeditor/ckeditor5-indent": "41.0.0",
|
||||
"@ckeditor/ckeditor5-link": "41.0.0",
|
||||
"@ckeditor/ckeditor5-list": "41.0.0",
|
||||
"@ckeditor/ckeditor5-media-embed": "41.0.0",
|
||||
"@ckeditor/ckeditor5-paragraph": "41.0.0",
|
||||
"@ckeditor/ckeditor5-paste-from-office": "41.0.0",
|
||||
"@ckeditor/ckeditor5-table": "41.0.0",
|
||||
"@ckeditor/ckeditor5-typing": "41.0.0",
|
||||
"@ckeditor/ckeditor5-undo": "41.0.0",
|
||||
"@ckeditor/ckeditor5-upload": "41.0.0",
|
||||
"@ckeditor/ckeditor5-word-count": "41.0.0",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"flowbite": "^2.2.1",
|
||||
"postcss": "^8.4.33",
|
||||
|
|
|
@ -29,7 +29,6 @@ module.exports = {
|
|||
}
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/typography'),
|
||||
require('flowbite/plugin')
|
||||
],
|
||||
}
|
||||
|
|
|
@ -8,10 +8,15 @@
|
|||
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||
}
|
||||
},
|
||||
"WebSiteUrl": "https://bonsaigallery.shop",
|
||||
"AdminPanelBaseUrl": "https://admin.bonsaigallery.shop",
|
||||
"StorageBaseUrl": "https://storage.bonsaigallery.shop",
|
||||
"WebSiteUrl": "https://vesmeh.com",
|
||||
"AdminPanelBaseUrl": "https://admin.vesmeh.com",
|
||||
"StorageBaseUrl": "https://storage.vesmeh.com",
|
||||
//"ApiUrl": "https://api.vesmeh.com/api",
|
||||
"ApiUrl": "http://localhost:32770/api",
|
||||
|
||||
//"WebSiteUrl": "https://bonsaigallery.shop",
|
||||
//"AdminPanelBaseUrl": "https://admin.bonsaigallery.shop",
|
||||
//"StorageBaseUrl": "https://storage.bonsaigallery.shop",
|
||||
//"ApiUrl": "https://api.bonsaigallery.shop/api",
|
||||
"IsShop": true
|
||||
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,322 @@
|
|||
import {
|
||||
ClassicEditor,
|
||||
AccessibilityHelp,
|
||||
Alignment,
|
||||
Autoformat,
|
||||
AutoImage,
|
||||
AutoLink,
|
||||
Autosave,
|
||||
BalloonToolbar,
|
||||
BlockQuote,
|
||||
Bold,
|
||||
CodeBlock,
|
||||
Essentials,
|
||||
FindAndReplace,
|
||||
FontBackgroundColor,
|
||||
FontColor,
|
||||
FontFamily,
|
||||
FontSize,
|
||||
Heading,
|
||||
Highlight,
|
||||
HorizontalLine,
|
||||
HtmlEmbed,
|
||||
ImageBlock,
|
||||
ImageCaption,
|
||||
ImageInline,
|
||||
ImageInsert,
|
||||
ImageInsertViaUrl,
|
||||
ImageResize,
|
||||
ImageStyle,
|
||||
ImageTextAlternative,
|
||||
ImageToolbar,
|
||||
ImageUpload,
|
||||
Indent,
|
||||
IndentBlock,
|
||||
Italic,
|
||||
Link,
|
||||
LinkImage,
|
||||
List,
|
||||
ListProperties,
|
||||
MediaEmbed,
|
||||
Paragraph,
|
||||
PasteFromOffice,
|
||||
SelectAll,
|
||||
ShowBlocks,
|
||||
SimpleUploadAdapter,
|
||||
SourceEditing,
|
||||
SpecialCharacters,
|
||||
SpecialCharactersArrows,
|
||||
SpecialCharactersCurrency,
|
||||
SpecialCharactersEssentials,
|
||||
SpecialCharactersLatin,
|
||||
SpecialCharactersMathematical,
|
||||
SpecialCharactersText,
|
||||
Strikethrough,
|
||||
Table,
|
||||
TableCaption,
|
||||
TableCellProperties,
|
||||
TableColumnResize,
|
||||
TableProperties,
|
||||
TableToolbar,
|
||||
TextTransformation,
|
||||
TodoList,
|
||||
Underline,
|
||||
Undo
|
||||
} from '/assets/vendor/ckeditor5.js';
|
||||
const editorConfig = {
|
||||
toolbar: {
|
||||
items: [
|
||||
'undo',
|
||||
'redo',
|
||||
'|',
|
||||
'sourceEditing',
|
||||
'showBlocks',
|
||||
'findAndReplace',
|
||||
'selectAll',
|
||||
'|',
|
||||
'heading',
|
||||
'|',
|
||||
'fontSize',
|
||||
'fontFamily',
|
||||
'fontColor',
|
||||
'fontBackgroundColor',
|
||||
'|',
|
||||
'bold',
|
||||
'italic',
|
||||
'underline',
|
||||
'strikethrough',
|
||||
'|',
|
||||
'specialCharacters',
|
||||
'horizontalLine',
|
||||
'link',
|
||||
'insertImage',
|
||||
'mediaEmbed',
|
||||
'insertTable',
|
||||
'highlight',
|
||||
'blockQuote',
|
||||
'codeBlock',
|
||||
'htmlEmbed',
|
||||
'|',
|
||||
'alignment',
|
||||
'|',
|
||||
'bulletedList',
|
||||
'numberedList',
|
||||
'todoList',
|
||||
'outdent',
|
||||
'indent',
|
||||
'|',
|
||||
'accessibilityHelp'
|
||||
],
|
||||
shouldNotGroupWhenFull: true
|
||||
},
|
||||
plugins: [
|
||||
AccessibilityHelp,
|
||||
Alignment,
|
||||
Autoformat,
|
||||
AutoImage,
|
||||
AutoLink,
|
||||
Autosave,
|
||||
BalloonToolbar,
|
||||
BlockQuote,
|
||||
Bold,
|
||||
CodeBlock,
|
||||
Essentials,
|
||||
FindAndReplace,
|
||||
FontBackgroundColor,
|
||||
FontColor,
|
||||
FontFamily,
|
||||
FontSize,
|
||||
Heading,
|
||||
Highlight,
|
||||
HorizontalLine,
|
||||
HtmlEmbed,
|
||||
ImageBlock,
|
||||
ImageCaption,
|
||||
ImageInline,
|
||||
ImageInsert,
|
||||
ImageInsertViaUrl,
|
||||
ImageResize,
|
||||
ImageStyle,
|
||||
ImageTextAlternative,
|
||||
ImageToolbar,
|
||||
ImageUpload,
|
||||
Indent,
|
||||
IndentBlock,
|
||||
Italic,
|
||||
Link,
|
||||
LinkImage,
|
||||
List,
|
||||
ListProperties,
|
||||
MediaEmbed,
|
||||
Paragraph,
|
||||
PasteFromOffice,
|
||||
SelectAll,
|
||||
ShowBlocks,
|
||||
SimpleUploadAdapter,
|
||||
SourceEditing,
|
||||
SpecialCharacters,
|
||||
SpecialCharactersArrows,
|
||||
SpecialCharactersCurrency,
|
||||
SpecialCharactersEssentials,
|
||||
SpecialCharactersLatin,
|
||||
SpecialCharactersMathematical,
|
||||
SpecialCharactersText,
|
||||
Strikethrough,
|
||||
Table,
|
||||
TableCaption,
|
||||
TableCellProperties,
|
||||
TableColumnResize,
|
||||
TableProperties,
|
||||
TableToolbar,
|
||||
TextTransformation,
|
||||
TodoList,
|
||||
Underline,
|
||||
Undo
|
||||
],
|
||||
simpleUpload: {
|
||||
uploadUrl: 'https://api.vesmeh.com/api/file/ckeditor',
|
||||
withCredentials: true,
|
||||
headers: {
|
||||
Authorization: 'xuwp4KzU1/YBoevpzgH0cz8+zLKQ+EOaYXeo4JtRxmVIuN7Hqxz97oQ398tNX68+'
|
||||
}
|
||||
},
|
||||
balloonToolbar: ['bold', 'italic', '|', 'link', 'insertImage', '|', 'bulletedList', 'numberedList'],
|
||||
fontFamily: {
|
||||
supportAllValues: true
|
||||
},
|
||||
fontSize: {
|
||||
options: [10, 12, 14, 'default', 18, 20, 22],
|
||||
supportAllValues: true
|
||||
},
|
||||
heading: {
|
||||
options: [
|
||||
{
|
||||
model: 'paragraph',
|
||||
title: 'Paragraph',
|
||||
class: 'ck-heading_paragraph'
|
||||
},
|
||||
{
|
||||
model: 'heading1',
|
||||
view: 'h1',
|
||||
title: 'Heading 1',
|
||||
class: 'ck-heading_heading1'
|
||||
},
|
||||
{
|
||||
model: 'heading2',
|
||||
view: 'h2',
|
||||
title: 'Heading 2',
|
||||
class: 'ck-heading_heading2'
|
||||
},
|
||||
{
|
||||
model: 'heading3',
|
||||
view: 'h3',
|
||||
title: 'Heading 3',
|
||||
class: 'ck-heading_heading3'
|
||||
},
|
||||
{
|
||||
model: 'heading4',
|
||||
view: 'h4',
|
||||
title: 'Heading 4',
|
||||
class: 'ck-heading_heading4'
|
||||
},
|
||||
{
|
||||
model: 'heading5',
|
||||
view: 'h5',
|
||||
title: 'Heading 5',
|
||||
class: 'ck-heading_heading5'
|
||||
},
|
||||
{
|
||||
model: 'heading6',
|
||||
view: 'h6',
|
||||
title: 'Heading 6',
|
||||
class: 'ck-heading_heading6'
|
||||
}
|
||||
]
|
||||
},
|
||||
image: {
|
||||
toolbar: [
|
||||
'toggleImageCaption',
|
||||
'imageTextAlternative',
|
||||
'|',
|
||||
'imageStyle:inline',
|
||||
'imageStyle:wrapText',
|
||||
'imageStyle:breakText',
|
||||
'|',
|
||||
'resizeImage'
|
||||
]
|
||||
},
|
||||
link: {
|
||||
addTargetToExternalLinks: true,
|
||||
defaultProtocol: 'https://',
|
||||
decorators: {
|
||||
toggleDownloadable: {
|
||||
mode: 'manual',
|
||||
label: 'Downloadable',
|
||||
attributes: {
|
||||
download: 'file'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
list: {
|
||||
properties: {
|
||||
styles: true,
|
||||
startIndex: true,
|
||||
reversed: true
|
||||
}
|
||||
},
|
||||
placeholder: 'متن خود را بنویسید یا کپی کنید',
|
||||
table: {
|
||||
contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties']
|
||||
},
|
||||
language: {
|
||||
ui: 'en',
|
||||
content: 'ar'
|
||||
}
|
||||
};
|
||||
export function initializeCKEditor(data) {
|
||||
if (!document.querySelector('.editor')) return;
|
||||
if (window.editor) return;
|
||||
|
||||
ClassicEditor.create(document.querySelector('.editor'), editorConfig)
|
||||
.then(editor => {
|
||||
window.editor = editor;
|
||||
window.editor.setData(data);
|
||||
editor.editing.view.document.on('blur', () => {
|
||||
if (GLOBAL.DotNetReference) {
|
||||
GLOBAL.DotNetReference.invokeMethodAsync('MyMethod', window.editor.getData());
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(handleSampleError);
|
||||
}
|
||||
|
||||
export function destroyEditor() {
|
||||
if (window.editor) {
|
||||
window.editor.destroy();
|
||||
window.editor = null;
|
||||
}
|
||||
}
|
||||
|
||||
export function setData(data) {
|
||||
if (window.editor) {
|
||||
window.editor.setData(data);
|
||||
}
|
||||
}
|
||||
|
||||
function handleSampleError(error) {
|
||||
const issueUrl = 'https://github.com/ckeditor/ckeditor5/issues';
|
||||
const message = [
|
||||
'Oops, something went wrong!',
|
||||
`Please, report the following error on ${issueUrl} with the build id "pws0dnpd0jqj-zi42lsl7aqxa" and the error stack trace:`
|
||||
].join('\n');
|
||||
console.error(message);
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
export var GLOBAL = {
|
||||
DotNetReference: null,
|
||||
SetDotnetReference: function (pDotNetReference) {
|
||||
this.DotNetReference = pDotNetReference;
|
||||
}
|
||||
};
|
|
@ -1096,10 +1096,6 @@ input:checked + .toggle-bg {
|
|||
margin-left: 1rem;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
.mx-5 {
|
||||
margin-left: 1.25rem;
|
||||
margin-right: 1.25rem;
|
||||
}
|
||||
.mx-auto {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
@ -1209,6 +1205,9 @@ input:checked + .toggle-bg {
|
|||
.mt-4 {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
.mt-5 {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
.mt-6 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<script src="https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs" type="module"></script>
|
||||
<link rel="icon" type="image/png" href="favicon.png" />
|
||||
<link rel="stylesheet" href="css/CKEditor.css" />
|
||||
<link rel="stylesheet" href="assets/vendor/ckeditor5.css">
|
||||
<link href="manifest.webmanifest" rel="manifest" />
|
||||
<link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" />
|
||||
<link rel="apple-touch-icon" sizes="192x192" href="icon-192.png" />
|
||||
|
@ -43,11 +44,20 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div dir="rtl" id="blazor-error-ui" class="!text-black !z-[9999]">
|
||||
<div id="blazor-error-ui" class="!text-black !z-[9999]">
|
||||
<b>مشکلی رخ داده است</b>
|
||||
<a href="" class="reload">بارگزاری مجدد</a>
|
||||
<a class="dismiss">بستن</a>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import { initializeCKEditor, destroyEditor, setData, GLOBAL } from './ckeditor5New.js';
|
||||
window.initializeCKEditor = initializeCKEditor;
|
||||
window.destroyEditor = destroyEditor;
|
||||
window.setData = setData;
|
||||
window.GLOBAL = GLOBAL;
|
||||
</script>
|
||||
|
||||
<script src="_framework/blazor.webassembly.js"></script>
|
||||
|
||||
<script src="aes-js-3.1.2.js"></script>
|
||||
|
@ -104,7 +114,6 @@
|
|||
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
|
||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||
<script src="_content/Toolbelt.Blazor.PWA.Updater.Service/script.min.js"></script>
|
||||
<script src="ckeditor.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@ VisualStudioVersion = 17.8.34316.72
|
|||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netina.AdminPanel.PWA", "Netina.AdminPanel.PWA\Netina.AdminPanel.PWA.csproj", "{EB154E26-A392-4521-B26D-1B82C8597201}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netina.Domain", "..\Netina\Netina.Domain\Netina.Domain.csproj", "{FD9AD662-66FB-431A-A2C1-8D6262402FCE}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netina.Domain", "..\Api\Netina.Domain\Netina.Domain.csproj", "{FD9AD662-66FB-431A-A2C1-8D6262402FCE}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netina.Common", "..\Netina\Netina.Common\Netina.Common.csproj", "{CE60F736-C3F2-4D81-862E-48135E5FFC9C}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Netina.Common", "..\Api\Netina.Common\Netina.Common.csproj", "{CE60F736-C3F2-4D81-862E-48135E5FFC9C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
Loading…
Reference in New Issue