feat : add version 0.6.12.22 , fix updating issue
complete discount and product page changingrelease
parent
f883451697
commit
e6dd4c875e
|
@ -2,6 +2,7 @@
|
|||
Color="@Color"
|
||||
@onclick="OnClickCallback"
|
||||
@attributes="CapturedAttributes"
|
||||
Size="Size"
|
||||
Disabled="IsProcessing"
|
||||
DisableElevation="true"
|
||||
>
|
||||
|
@ -47,6 +48,9 @@
|
|||
[Parameter]
|
||||
public bool IsProcessing { get; set; } = false;
|
||||
|
||||
[Parameter]
|
||||
public Size Size { get; set; } = Size.Medium;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback OnClickCallback { get; set; }
|
||||
|
||||
|
|
|
@ -1,25 +1,36 @@
|
|||
@inject IJSRuntime JsRuntime
|
||||
@implements IAsyncDisposable
|
||||
|
||||
<div class="editor"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
function destroyEditor() {
|
||||
window.editor?.destroy()
|
||||
// document.querySelector('.editor').ckeditorInstance.destroy();
|
||||
window.editor = null;
|
||||
console.log('Editor Destroyed');
|
||||
}
|
||||
function lunchEditor(data) {
|
||||
|
||||
if (!document.querySelector('.editor')) return
|
||||
if (window.editor) return
|
||||
ClassicEditor.create(document.querySelector('.editor'), {
|
||||
// Editor configuration.
|
||||
})
|
||||
.then(editor => {
|
||||
window.editor = editor;
|
||||
window.editor.setData(data);
|
||||
editor.on('change', function () {
|
||||
console.log(editor.getData());
|
||||
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';
|
||||
|
||||
|
@ -44,6 +55,15 @@
|
|||
[Parameter]
|
||||
public EventCallback<string> TextChanged { get; set; }
|
||||
|
||||
[JSInvokable("MyMethod")]
|
||||
public void HandleEditorBlur(string data)
|
||||
{
|
||||
Text = data;
|
||||
TextChanged.InvokeAsync(data);
|
||||
StateHasChanged(); // Ensure UI updates
|
||||
}
|
||||
|
||||
|
||||
protected override Task OnParametersSetAsync()
|
||||
{
|
||||
return base.OnParametersSetAsync();
|
||||
|
@ -51,8 +71,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);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
JsRuntime.InvokeVoidAsync("window.destroyEditor", Text);
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
|
||||
await JsRuntime.InvokeVoidAsync("window.destroyEditor", Text);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,6 +71,11 @@
|
|||
</MudNavGroup>
|
||||
|
||||
|
||||
<MudNavGroup Title="فروشگاه من" Expanded="false"
|
||||
Icon="@Icons.Material.Outlined.Settings">
|
||||
|
||||
<MudNavLink Href="faqs" Icon="@Icons.Material.Filled.ManageAccounts">سوالات متداول</MudNavLink>
|
||||
</MudNavGroup>
|
||||
|
||||
<MudNavGroup Title="تنظیماتـــ" Expanded="false"
|
||||
Icon="@Icons.Material.Outlined.Settings">
|
||||
|
@ -78,12 +83,13 @@
|
|||
<MudNavLink Href="users" Icon="@Icons.Material.Filled.ManageAccounts">نقش ها و کاربران</MudNavLink>
|
||||
</MudNavGroup>
|
||||
</MudNavMenu>
|
||||
|
||||
<p class="bottom-0 align-bottom mx-auto">Version : @version</p>
|
||||
</MudStack>
|
||||
|
||||
@code
|
||||
{
|
||||
|
||||
string? version = typeof(Program)?.Assembly.GetName()?.Version?.ToString();
|
||||
private void SelectNav()
|
||||
{
|
||||
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
@using NetinaShop.Domain.Entities.Users
|
||||
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IRestWrapper RestWrapper
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IDialogService DialogService
|
||||
|
||||
<MudDialog DisableSidePadding="true" class="mx-auto">
|
||||
<DialogContent>
|
||||
<MudStack class="px-4">
|
||||
<MudDivider class="-mt-3" />
|
||||
<MudStack Spacing="0">
|
||||
|
||||
<MudText Typo="Typo.h6"><b>جست جو از دیجیکالا</b></MudText>
|
||||
<MudText Typo="Typo.caption">میتوانید نام کالا را از دیجیکالا جست جو کرده و به فروشگاه اضافه کنید</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudTextField T="string" Placeholder="جست جو بر اساس نام" Adornment="Adornment.Start" Immediate="true"
|
||||
Clearable="true"
|
||||
Variant="Variant.Outlined"
|
||||
ValueChanged="@ViewModel.SearchChanged"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||
|
||||
<MudContainer class="h-[35rem]" Style="overflow-y: scroll">
|
||||
@if (ViewModel.IsProcessing)
|
||||
{
|
||||
<MudProgressCircular class="my-auto" Size="Size.Large" Color="Color.Info" Indeterminate="true" />
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var item in ViewModel.PageDto)
|
||||
{
|
||||
<MudCard Outlined="true" class="my-2">
|
||||
<MudCardContent>
|
||||
<MudStack Row="true">
|
||||
<MudImage Width="100" Height="100" Class="rounded-lg" Src="@item.MainImage" />
|
||||
<MudStack>
|
||||
<MudText Typo="Typo.body1">@item.PersianName</MudText>
|
||||
<MudText Typo="Typo.body1">@item.EnglishName</MudText>
|
||||
<MudText Typo="Typo.body2">@item.Summery</MudText>
|
||||
<MudText Typo="Typo.body2">قیمت : @item.Cost.ToString("N0")</MudText>
|
||||
</MudStack>
|
||||
</MudStack>
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudButton OnClick="async()=> await ViewModel.AddProductToShopAsync(item.ScraperId)"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Success">افزودن به فروشگاه</MudButton>
|
||||
<a href="@item.ScraperUrl" target="_blank">
|
||||
<MudButton class="mx-3"
|
||||
Variant="Variant.Outlined"
|
||||
Color="Color.Warning">مشاهده کالا</MudButton>
|
||||
</a>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</MudContainer>
|
||||
</MudStack>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="w-full mx-4 mb-2">
|
||||
|
||||
@* <BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Check"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="ثبت ویرایش" OnClickCallback="@ViewModel.SubmitEditAsync" /> *@
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="@ViewModel.Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
@code {
|
||||
|
||||
[CascadingParameter]
|
||||
MudDialogInstance MudDialog { get; set; }
|
||||
|
||||
public DigikalaProductActionDialogBoxViewModel ViewModel { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ViewModel = new DigikalaProductActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
using NetinaShop.Domain.Dtos.ScraperDtos.Response;
|
||||
|
||||
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
||||
|
||||
public class DigikalaProductActionDialogBoxViewModel : BaseViewModel<ObservableCollection<ScraperProductDto>>
|
||||
{
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
private readonly IUserUtility _userUtility;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly MudDialogInstance _mudDialog;
|
||||
|
||||
|
||||
public string Search = string.Empty;
|
||||
|
||||
public DigikalaProductActionDialogBoxViewModel(ISnackbar snackbar,
|
||||
IRestWrapper restWrapper,
|
||||
IUserUtility userUtility,
|
||||
IDialogService dialogService,
|
||||
MudDialogInstance mudDialog)
|
||||
{
|
||||
_snackbar = snackbar;
|
||||
_restWrapper = restWrapper;
|
||||
_userUtility = userUtility;
|
||||
_dialogService = dialogService;
|
||||
_mudDialog = mudDialog;
|
||||
}
|
||||
public void Cancel() => _mudDialog.Cancel();
|
||||
|
||||
public async Task AddProductToShopAsync(string productId)
|
||||
{
|
||||
var options = new DialogOptions { CloseOnEscapeKey = true };
|
||||
var parameters = new DialogParameters<QuestionDialog>();
|
||||
parameters.Add(x => x.ContentText, "آیا از افزودن محصول اطمینان دارید ?");
|
||||
var dialogReference = await _dialogService.ShowAsync<QuestionDialog>("افزودن محصول از دیجیکالا", parameters, options);
|
||||
var result = await dialogReference.Result;
|
||||
if (!result.Canceled)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
IsProcessing = true;
|
||||
await _restWrapper.ScraperRestApi.AddDigiProductToShopAsync(productId,Search, token);
|
||||
_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SearchChanged(string search)
|
||||
{
|
||||
if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
|
||||
await InitializeAsync();
|
||||
Search = search;
|
||||
}
|
||||
public async Task SearchAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
if (Search.IsNullOrEmpty())
|
||||
throw new AppException("اسم کالا برای جست جو وارد نشده است");
|
||||
IsProcessing = true;
|
||||
var dto = await _restWrapper.ScraperRestApi.SearchDigiProductsAsync(Search, token);
|
||||
PageDto.Clear();
|
||||
dto.ForEach(d => PageDto.Add(d));
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Mapster;
|
||||
using NetinaShop.Domain.Dtos.ResponseDtos;
|
||||
using NetinaShop.Domain.Entities.Blogs;
|
||||
using NetinaShop.Domain.Entities.Discounts;
|
||||
using NetinaShop.Domain.Mappers;
|
||||
|
@ -230,15 +231,33 @@ public class DiscountActionDialogBoxViewModel : BaseViewModel<DiscountLDto>
|
|||
{
|
||||
IsProcessing = true;
|
||||
if (_discountId == default)
|
||||
throw new Exception("بلاگ اشتباه است");
|
||||
throw new Exception("Id is null");
|
||||
|
||||
if (IsAllEnable)
|
||||
{
|
||||
PageDto.Type = DiscountType.All;
|
||||
}
|
||||
else if (IsCategoryEnable)
|
||||
{
|
||||
PageDto.Type = DiscountType.Category;
|
||||
if (SelectedCategory == null)
|
||||
throw new Exception("لطفا یک دسته بندی انتخاب کنید");
|
||||
throw new Exception("دسته بندی را برای تخفیف انتخاب نمایید");
|
||||
PageDto.CategoryId = SelectedCategory.Id;
|
||||
}
|
||||
else if (IsProductEnable)
|
||||
{
|
||||
PageDto.Type = DiscountType.Product;
|
||||
if (SelectedProduct == null)
|
||||
throw new Exception("کالا مورد نظر را برای تخفیف انتخاب نمایید");
|
||||
PageDto.ProductId = SelectedProduct.Id;
|
||||
}
|
||||
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
PageDto.Id = _discountId;
|
||||
var request = PageDto.Adapt<UpdateDiscountCommand>();
|
||||
await _restWrapper.CrudApiRest<Discount, Guid>(Address.DiscountController).Create<UpdateDiscountCommand>(request, token);
|
||||
await _restWrapper.CrudApiRest<Discount, Guid>(Address.DiscountController).Update<UpdateDiscountCommand>(request, token);
|
||||
_snackbar.Add($"ویرایش تخفیف با موفقیت انجام شد", Severity.Success);
|
||||
_mudDialog.Close();
|
||||
}
|
||||
|
@ -298,10 +317,12 @@ public class DiscountActionDialogBoxViewModel : BaseViewModel<DiscountLDto>
|
|||
{
|
||||
try
|
||||
{
|
||||
GetProductsResponseDto response = new GetProductsResponseDto();
|
||||
if (product.IsNullOrEmpty())
|
||||
_products = await _restWrapper.ProductRestApi.ReadAll(0);
|
||||
response = await _restWrapper.ProductRestApi.ReadAll(0);
|
||||
else
|
||||
_products = await _restWrapper.ProductRestApi.ReadAll(product);
|
||||
response = await _restWrapper.ProductRestApi.ReadAll(product);
|
||||
_products = response.Products;
|
||||
return _products;
|
||||
}
|
||||
catch (ApiException ex)
|
||||
|
|
|
@ -0,0 +1,219 @@
|
|||
@inject ISnackbar Snackbar
|
||||
@inject IRestWrapper RestWrapper
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IDialogService DialogService
|
||||
|
||||
<MudDialog class="mx-auto" DisableSidePadding="true">
|
||||
<DialogContent>
|
||||
<MudContainer class="max-h-[40rem] mt-4" Style="overflow-y: scroll">
|
||||
<MudGrid>
|
||||
<MudItem md="9">
|
||||
<MudStack>
|
||||
|
||||
<MudStack Row="true">
|
||||
|
||||
<MudText Typo="Typo.h6" class="my-auto"><b>اطلاعات سفارش</b></MudText>
|
||||
<MudSpacer/>
|
||||
<MudPaper Elevation="0" class="bg-blue-500 px-4 py-2 my-auto">
|
||||
<MudText Typo="Typo.body2" class="text-white">@ViewModel.PageDto.OrderStatus.ToDisplay()</MudText>
|
||||
</MudPaper>
|
||||
</MudStack>
|
||||
|
||||
<MudGrid>
|
||||
<MudItem sm="4">
|
||||
<MudField Variant="Variant.Outlined" Label="نام و نام خانوادگی">@ViewModel.PageDto.UserFullName</MudField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="4">
|
||||
<MudField Variant="Variant.Outlined" Label="شماره تماس">@ViewModel.PageDto.UserPhoneNumber</MudField>
|
||||
</MudItem>
|
||||
|
||||
<MudItem sm="4">
|
||||
<MudField Variant="Variant.Outlined" Label="کد تخفیف">@ViewModel.PageDto.DiscountCode</MudField>
|
||||
</MudItem>
|
||||
|
||||
|
||||
<MudItem sm="9">
|
||||
<MudField Variant="Variant.Outlined" Label="آدرس">@ViewModel.PageDto.OrderDelivery.Address</MudField>
|
||||
</MudItem>
|
||||
<MudItem sm="3">
|
||||
<MudField Variant="Variant.Outlined" Label="روش ارسال">@ViewModel.PageDto.OrderDelivery.ShippingMethod</MudField>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
<MudStack class="mt-3" Row="true">
|
||||
|
||||
<MudText Typo="Typo.h6"><b>کالاهای این سفارش</b></MudText>
|
||||
<MudSpacer/>
|
||||
<MudPaper Elevation="0" class="border-dashed border-violet-400 border-2 px-3 py-1 my-auto">
|
||||
<MudText Typo="Typo.caption" class="text-violet-500"><b>@ViewModel.PageDto.OrderProducts.Sum(op => op.Count) قلم کالا</b></MudText>
|
||||
</MudPaper>
|
||||
</MudStack>
|
||||
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
Elevation="0"
|
||||
Bordered="true"
|
||||
T="OrderProductSDto" Items="@ViewModel.PageDto.OrderProducts"
|
||||
Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false"
|
||||
class="border-solid border-2 border-gray-200">
|
||||
<Columns>
|
||||
|
||||
<TemplateColumn T="OrderProductSDto" Title="نام کالا">
|
||||
|
||||
<CellTemplate>
|
||||
<b>@context.Item.ProductName</b>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn T="OrderProductSDto" Title="قیمت کالا">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.ProductFeeWithDiscount.ToString("N0") ریالــ</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<PropertyColumn Title="تعداد" Property="arg => arg.Count" />
|
||||
|
||||
<TemplateColumn T="OrderProductSDto" Title="قیمت کل">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.ProductCost.ToString("N0") ریالــ</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
</MudDataGrid>
|
||||
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
|
||||
<MudItem md="3">
|
||||
|
||||
<MudText Typo="Typo.h6" class="mb-2"><b>مبــــالغ</b></MudText>
|
||||
<MudPaper class="bg-[--mud-palette-background-grey] rounded-md">
|
||||
<MudStack class="p-3">
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudText class="my-auto" Typo="Typo.body2">جمع کالاها : </MudText>
|
||||
<MudSpacer/>
|
||||
<MudText Typo="Typo.body1"><b>@ViewModel.PageDto.TotalProductsPrice.ToString("N0")</b> ریالــ</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudDivider/>
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudText class="my-auto" Typo="Typo.body2">مالیات : </MudText>
|
||||
<MudSpacer/>
|
||||
<MudText Typo="Typo.body1"><b>@ViewModel.PageDto.TaxesPrice.ToString("N0")</b> ریالــ</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudDivider/>
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudText class="my-auto" Typo="Typo.body2">بسته بندی : </MudText>
|
||||
<MudSpacer/>
|
||||
<MudText Typo="Typo.body1"><b>@ViewModel.PageDto.PackingPrice.ToString("N0")</b> ریالــ</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudDivider/>
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudText class="my-auto" Typo="Typo.body2">هزینه ارسال : </MudText>
|
||||
<MudSpacer/>
|
||||
<MudText Typo="Typo.body1"><b>@ViewModel.PageDto.DeliveryPrice.ToString("N0")</b> ریالــ</MudText>
|
||||
</MudStack>
|
||||
|
||||
</MudStack>
|
||||
|
||||
<MudPaper class="mud-theme-dark rounded-md">
|
||||
|
||||
<MudStack class="p-3">
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudText class="my-auto" Typo="Typo.body2">جمع کل : </MudText>
|
||||
<MudSpacer/>
|
||||
<MudText Typo="Typo.body1"><b>@ViewModel.PageDto.TotalPriceWithoutDiscount.ToString("N0")</b> ریالــ</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudDivider/>
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudText class="my-auto" Typo="Typo.body2">مقدار تخفیف : </MudText>
|
||||
<MudSpacer/>
|
||||
<MudText Typo="Typo.body1"><b>@ViewModel.PageDto.DiscountPrice.ToString("N0")</b> ریالــ</MudText>
|
||||
</MudStack>
|
||||
|
||||
<MudDivider/>
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudText class="my-auto" Typo="Typo.body2">مبلغ قابل پرداخت : </MudText>
|
||||
<MudSpacer/>
|
||||
<MudText Typo="Typo.body1"><b>@ViewModel.PageDto.TotalPrice.ToString("N0")</b> ریالــ</MudText>
|
||||
</MudStack>
|
||||
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
</MudPaper>
|
||||
|
||||
<MudText Typo="Typo.h6" class="mt-3"><b>پرداختــ ها</b></MudText>
|
||||
|
||||
<MudPaper Elevation="0" class="bg-[--mud-palette-background-grey] rounded-md">
|
||||
<MudStack class="p-3">
|
||||
|
||||
@foreach (var item in ViewModel.PageDto.Payments)
|
||||
{
|
||||
<MudStack Row="true">
|
||||
<MudText class="my-auto" Typo="Typo.body2">@item.Type.ToDisplay()</MudText>
|
||||
<MudSpacer/>
|
||||
<MudText Typo="Typo.body1"><b>@item.Amount.ToString("N0")</b> ریالــ</MudText>
|
||||
</MudStack>
|
||||
}
|
||||
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudContainer>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="w-full h-fit mx-4 mb-3 bottom-0">
|
||||
|
||||
<BaseButtonUi class="w-64 h-12 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.AirportShuttle"
|
||||
Variant="Variant.Filled" Color="Color.Success"
|
||||
Content="ثبت ارسال سفارش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
<BaseButtonUi class="w-52 h-12 rounded-md" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.RemoveCircle"
|
||||
Variant="Variant.Outlined" Color="Color.Error"
|
||||
Content="لغو سفارش" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
<MudSpacer />
|
||||
|
||||
<BaseButtonUi class="w-52 h-12 rounded-md my-auto" IsProcessing="@ViewModel.IsProcessing"
|
||||
Icon="@Icons.Material.Outlined.Print"
|
||||
Size="Size.Small"
|
||||
Variant="Variant.Outlined" Color="Color.Info"
|
||||
Content="چاپــ فاکتور" OnClickCallback="ViewModel.SubmitEditAsync" />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Medium" Color="Color.Error" OnClick="ViewModel.Cancel">بستن</MudButton>
|
||||
</MudStack>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code {
|
||||
|
||||
[CascadingParameter]
|
||||
MudDialogInstance MudDialog { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public OrderSDto? Order { get; set; }
|
||||
|
||||
public OrderActionDialogBoxViewModel ViewModel { get; set; }
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (Order == null)
|
||||
ViewModel = new OrderActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
|
||||
else
|
||||
ViewModel = new OrderActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Order);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Dialogs;
|
||||
|
||||
public class OrderActionDialogBoxViewModel : BaseViewModel<OrderLDto>
|
||||
{
|
||||
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
private readonly IUserUtility _userUtility;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly MudDialogInstance _mudDialog;
|
||||
|
||||
public OrderActionDialogBoxViewModel(ISnackbar snackbar, IRestWrapper restWrapper, IUserUtility userUtility, IDialogService dialogService, MudDialogInstance mudDialog)
|
||||
{
|
||||
_snackbar = snackbar;
|
||||
_restWrapper = restWrapper;
|
||||
_userUtility = userUtility;
|
||||
_dialogService = dialogService;
|
||||
_mudDialog = mudDialog;
|
||||
}
|
||||
public OrderActionDialogBoxViewModel(ISnackbar snackbar,
|
||||
IRestWrapper restWrapper,
|
||||
IUserUtility userUtility,
|
||||
IDialogService dialogService,
|
||||
MudDialogInstance mudDialog,
|
||||
OrderSDto order)
|
||||
{
|
||||
_snackbar = snackbar;
|
||||
_restWrapper = restWrapper;
|
||||
_userUtility = userUtility;
|
||||
_dialogService = dialogService;
|
||||
_mudDialog = mudDialog;
|
||||
PageDto.Id = order.Id;
|
||||
IsEditing = true;
|
||||
}
|
||||
|
||||
|
||||
public void Cancel() => _mudDialog.Cancel();
|
||||
|
||||
public bool IsEditing = false;
|
||||
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
{
|
||||
if (IsEditing && PageDto.Id != default)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
|
||||
IsProcessing = true;
|
||||
|
||||
var order = await _restWrapper.OrderRestApi.ReadOne(PageDto.Id, token);
|
||||
PageDto = order;
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
if (exe != null)
|
||||
_snackbar.Add(exe.Message, Severity.Error);
|
||||
_snackbar.Add(ex.Content, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public async Task SubmitEditAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
_snackbar.Add($"ویرایش سفارش {PageDto.FactorCode} با موفقیت انجام شد", Severity.Success);
|
||||
_mudDialog.Close();
|
||||
}
|
||||
catch (ApiException ex)
|
||||
{
|
||||
var exe = await ex.GetContentAsAsync<ApiResult>();
|
||||
if (exe != null)
|
||||
_snackbar.Add(exe.Message, Severity.Error);
|
||||
_snackbar.Add(ex.Content, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
_mudDialog.Cancel();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
IsProcessing = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,10 @@
|
|||
@using Radzen.Blazor
|
||||
@using NetinaShop.AdminPanel.PWA.Extensions
|
||||
@using NetinaShop.AdminPanel.PWA.Extensions
|
||||
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IRestWrapper RestWrapper
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IDialogService DialogService
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
|
||||
</head>
|
||||
|
||||
<MudDialog class="mx-auto">
|
||||
<DialogContent>
|
||||
|
@ -177,42 +173,6 @@
|
|||
</MudItem>
|
||||
</MudGrid>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
|
||||
var myInterval = setInterval(()=>{
|
||||
lunchEditor()
|
||||
console.log("retry to load editor")
|
||||
},50)
|
||||
|
||||
function lunchEditor() {
|
||||
if (document.querySelector('.editor')) {
|
||||
ClassicEditor
|
||||
.create(document.querySelector('.editor'), {
|
||||
// Editor configuration.
|
||||
})
|
||||
.then(editor => {
|
||||
window.editor = editor;
|
||||
clearInterval(myInterval)
|
||||
console.info("Editor Lunched , Interval Cleared !")
|
||||
})
|
||||
.catch(handleSampleError);
|
||||
}else return
|
||||
}
|
||||
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);
|
||||
}
|
||||
</script>
|
||||
</MudTabPanel>
|
||||
<MudTabPanel Text="تـــــصاویر" Icon="@Icons.Material.Outlined.ImageSearch">
|
||||
|
||||
|
@ -307,7 +267,7 @@
|
|||
</MudContainer>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudStack Row="true" class="w-full h-fit mx-4 bottom-0">
|
||||
<MudStack Row="true" class="w-full h-fit mx-4 mb-3 bottom-0">
|
||||
|
||||
@if (ViewModel.IsEditing)
|
||||
{
|
||||
|
|
|
@ -80,7 +80,8 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
|
|||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var productLDto = await _restWrapper.CrudDtoApiRest<Product, ProductLDto, Guid>(Address.ProductController).ReadOne(_product.Id);
|
||||
var response = await _restWrapper.ProductRestApi.ReadOne(_product.Id);
|
||||
var productLDto = response.Product;
|
||||
PageDto.ExpertCheck = productLDto.ExpertCheck;
|
||||
PageDto.Summery = productLDto.Summery;
|
||||
PageDto.BeDisplayed = productLDto.BeDisplayed;
|
||||
|
|
|
@ -40,8 +40,8 @@
|
|||
|
||||
<MudLayout>
|
||||
<MudAppBar class="py-2" Color="Color.Transparent" Fixed="false" Elevation="2">
|
||||
<MudHidden Breakpoint="Breakpoint.SmAndUp">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" />
|
||||
<MudHidden Breakpoint="Breakpoint.MdAndUp">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" OnClick="@ToggleDrawer" Edge="Edge.Start" />
|
||||
</MudHidden>
|
||||
@* <MudAvatar Size="Size.Large" Variant="Variant.Outlined">
|
||||
<MudImage Src="https://img.freepik.com/free-photo/portrait-white-man-isolated_53876-40306.jpg?size=626&ext=jpg&ga=GA1.1.632798143.1705708800&semt=ais"></MudImage>
|
||||
|
@ -53,14 +53,18 @@
|
|||
<MudText Color="Color.Inherit" Typo="Typo.caption">@_user?.PhoneNumber</MudText>
|
||||
</MudStack>
|
||||
<MudSpacer />
|
||||
<MudIconButton Size="Size.Medium" Color="Color.Inherit" Icon="@Icons.Material.Outlined.Settings"/>
|
||||
@* <MudIconButton Size="Size.Medium" Color="Color.Inherit" Icon="@Icons.Material.Outlined.Settings"/> *@
|
||||
<MudIconButton Size="Size.Medium" Color="Color.Error" OnClick="LogoutAsync" Icon="@Icons.Material.Outlined.ExitToApp" />
|
||||
</MudAppBar>
|
||||
|
||||
<MudDrawer @bind-Open="@open" Breakpoint="Breakpoint.MdAndUp" Elevation="1" Variant="@DrawerVariant.Responsive">
|
||||
<SideBarUi/>
|
||||
</MudDrawer>
|
||||
|
||||
<MudGrid Spacing="0">
|
||||
|
||||
<MudItem sm="0" md="3" lg="2">
|
||||
<MudHidden Breakpoint="Breakpoint.SmAndDown">
|
||||
<MudHidden Breakpoint="Breakpoint.MdAndDown">
|
||||
<SideBarUi/>
|
||||
</MudHidden>
|
||||
</MudItem>
|
||||
|
@ -73,7 +77,7 @@
|
|||
</MudGrid>
|
||||
</MudLayout>
|
||||
<div dir="ltr">
|
||||
<PWAUpdater StateChanged="Callback" Text="@_updateText" ButtonCaption="اپدیت کنید"/>
|
||||
<PWAUpdater Align="PWAUpdater.Aligns.Buttom" Text="@_updateText" ButtonCaption="اپدیت کنید"/>
|
||||
</div>
|
||||
</MudRTLProvider>
|
||||
|
||||
|
@ -101,6 +105,8 @@
|
|||
|
||||
private string _updateText = "! نسخه جدید پنل ادمین رسید";
|
||||
private ApplicationUserSDto? _user;
|
||||
bool open = false;
|
||||
void ToggleDrawer() => open = !open;
|
||||
private async Task LogoutAsync()
|
||||
{
|
||||
await UserUtility.LogoutAsync();
|
||||
|
@ -118,11 +124,6 @@
|
|||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_user = await UserUtility.GetUserAsync();
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
private void Callback(PWAUpdater.States obj)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,4 +19,8 @@ public static class Address
|
|||
public static string DiscountController => $"{BaseAddress}/discount";
|
||||
public static string RoleController => $"{BaseAddress}/user/role";
|
||||
public static string ShippingController => $"{BaseAddress}/warehouse/shipping";
|
||||
public static string OrderController => $"{BaseAddress}/order";
|
||||
public static string PaymentController => $"{BaseAddress}/accounting/pay";
|
||||
public static string PageController => $"{BaseAddress}/page";
|
||||
public static string ScraperController => $"{BaseAddress}/scraper";
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Models;
|
||||
|
||||
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
|
||||
public class OrderProduct
|
||||
{
|
||||
public int Count { get; set; }
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
public class OrderTest
|
||||
{
|
||||
public string FactorCode { get; set; }
|
||||
public int TotalPrice { get; set; }
|
||||
public int DeliveryPrice { get; set; }
|
||||
public int TaxesPrice { get; set; }
|
||||
public int ServicePrice { get; set; }
|
||||
public int PackingPrice { get; set; }
|
||||
public int TotalProductsPrice { get; set; }
|
||||
public int DiscountPrice { get; set; }
|
||||
public bool IsPayed { get; set; }
|
||||
public int OrderStatus { get; set; }
|
||||
public DateTime DoneAt { get; set; }
|
||||
public DateTime OrderAt { get; set; }
|
||||
public int PreparingMinute { get; set; }
|
||||
public string DiscountCode { get; set; }
|
||||
public List<OrderProduct> OrderProducts { get; set; }
|
||||
public List<object> OrderDeliveries { get; set; }
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
|
@ -5,8 +5,9 @@
|
|||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
|
||||
<AssemblyVersion>0.4.3.12</AssemblyVersion>
|
||||
<FileVersion>0.4.3.12</FileVersion>
|
||||
<AssemblyVersion>0.6.12.22</AssemblyVersion>
|
||||
<FileVersion>0.6.12.22</FileVersion>
|
||||
<AssemblyName>$(MSBuildProjectName)</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
|
||||
|
@ -38,10 +39,6 @@
|
|||
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Utilities\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Blazored.LocalStorage" />
|
||||
<Using Include="Microsoft.AspNetCore.Components" />
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
@page "/faqs"
|
||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||
|
||||
@inject IDialogService DialogService
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IRestWrapper RestWrapper
|
||||
|
||||
<MudStack class="w-full p-8 h-screen bg-[--mud-palette-background-grey]">
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
<MudStack Row="true" class="mb-8">
|
||||
<MudText Typo="Typo.h4">سوالات متداول فروشگاه من</MudText>
|
||||
<MudSpacer />
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Success" OnClick="@ViewModel.SaveAsync">ذخیره سوالات</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 sm="1">
|
||||
<MudButton class="my-auto" 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>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Outlined.Delete"
|
||||
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>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
|
||||
@code
|
||||
{
|
||||
public FaqManagementPageViewModel ViewModel { get; set; }
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ViewModel = new FaqManagementPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
using NetinaShop.Domain.Entities.Pages;
|
||||
|
||||
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||
|
||||
public class FaqManagementPageViewModel : BaseViewModel<FAQPage>
|
||||
{
|
||||
private readonly NavigationManager _navigationManager;
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly IUserUtility _userUtility;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
|
||||
public FaqManagementPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||
{
|
||||
_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
|
||||
{
|
||||
Name = dto.Name,
|
||||
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 base.InitializeAsync();
|
||||
}
|
||||
|
||||
public async Task SaveAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
IsProcessing = true;
|
||||
var request = new PageActionRequestDto
|
||||
{
|
||||
Name = "سوالات متداول",
|
||||
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);
|
||||
}
|
||||
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 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)
|
||||
{
|
||||
try
|
||||
{
|
||||
PageDto.Faqs.Remove(question);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_snackbar.Add(e.Message, Severity.Error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,34 +44,53 @@
|
|||
|
||||
<MudPaper>
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
T="BlogSDto" Items="@ViewModel.PageDto" CurrentPage="@ViewModel.CurrentPage"
|
||||
T="OrderSDto" Items="@ViewModel.MainOrders" CurrentPage="@ViewModel.MainGridCurrentPage"
|
||||
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false">
|
||||
|
||||
<ToolBarContent>
|
||||
<MudTextField T="string" Placeholder="جست جو بر اساس کد پیگیری" Adornment="Adornment.Start" Immediate="true"
|
||||
@* <MudTextField T="string" Placeholder="جست جو بر اساس کد پیگیری" Adornment="Adornment.Start" Immediate="true"
|
||||
Clearable="true"
|
||||
ValueChanged="@ViewModel.SearchChanged"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField> *@
|
||||
</ToolBarContent>
|
||||
<Columns>
|
||||
<PropertyColumn Title="کد پیگیری" Property="arg => arg.Title"/>
|
||||
<PropertyColumn Title="مبلغ" Property="arg => arg.CategoryName"/>
|
||||
<PropertyColumn Title="تاریخ پرداخت" Property="arg => arg.ReadingTime"/>
|
||||
<PropertyColumn Title="کد سفارش" Property="arg => arg.FactorCode" />
|
||||
<PropertyColumn Title="نام خریدار" Property="arg => arg.UserFullName" />
|
||||
<TemplateColumn T="OrderSDto" Title="تاریخ سفارش">
|
||||
<CellTemplate>
|
||||
<p>@context.Item.OrderAt.ToPersianDateTime().ToLongDateString()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn T="OrderSDto" Title="تاریخ پرداخت">
|
||||
<CellTemplate>
|
||||
<p>@context.Item.PayedAt.ToPersianDateTime().ToLongDateString()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn T="OrderSDto" Title="مبلغ سفارش ">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.TotalPrice.ToString("N0") ریالــ</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn T="OrderSDto" Title="وضعیت سفارش">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.OrderStatus.ToDisplay()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
<MudIconButton Icon="@Icons.Material.Filled.RemoveRedEye"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Info"
|
||||
OnClick="async () => await ViewModel.EditBlogClicked(context.Item)"/>
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="async () => await ViewModel.DeleteBlogAsync(context.Item.Id)"
|
||||
Color="@Color.Error"/>
|
||||
OnClick="async () => await ViewModel.ShowClicked(context.Item)"/>
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
@ -79,7 +98,7 @@
|
|||
<PagerContent>
|
||||
<MudStack Row="true" class="w-full">
|
||||
|
||||
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.PageCount"
|
||||
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.MainGridPageCount"
|
||||
SelectedChanged="@ViewModel.ChangePageAsync" class="my-4 mx-auto"/>
|
||||
</MudStack>
|
||||
|
||||
|
@ -92,10 +111,10 @@
|
|||
|
||||
@code
|
||||
{
|
||||
public BlogsPageViewModel ViewModel { get; set; }
|
||||
public OrdersPageViewModel ViewModel { get; set; }
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ViewModel = new BlogsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||
ViewModel = new OrdersPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,109 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||
|
||||
public class OrdersPageViewModel
|
||||
public class OrdersPageViewModel : BaseViewModel
|
||||
{
|
||||
private readonly NavigationManager _navigationManager;
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly IUserUtility _userUtility;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
|
||||
public string Search = string.Empty;
|
||||
public int MainGridCurrentPage = 0;
|
||||
public int MainGridPageCount = 1;
|
||||
|
||||
public ObservableCollection<OrderSDto> MainOrders { get; } = new ObservableCollection<OrderSDto>();
|
||||
|
||||
public OrdersPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||
{
|
||||
_navigationManager = navigationManager;
|
||||
_snackbar = snackbar;
|
||||
_userUtility = userUtility;
|
||||
_restWrapper = restWrapper;
|
||||
_dialogService = dialogService;
|
||||
}
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
IsProcessing = true;
|
||||
MainOrders.Clear();
|
||||
var dto = await _restWrapper.OrderRestApi.ReadAll(MainGridCurrentPage, null, null, null,token);
|
||||
dto.ForEach(d => MainOrders.Add(d));
|
||||
if (MainOrders.Count == 15)
|
||||
MainGridPageCount = 2;
|
||||
}
|
||||
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 base.InitializeAsync();
|
||||
}
|
||||
|
||||
public async Task ChangePageAsync(int page)
|
||||
{
|
||||
MainGridCurrentPage = page - 1;
|
||||
if (MainGridCurrentPage > MainGridPageCount - 2)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
|
||||
|
||||
var dto = await _restWrapper.OrderRestApi.ReadAll(MainGridCurrentPage, null, null, null, token);
|
||||
dto.ForEach(d => MainOrders.Add(d));
|
||||
if (MainOrders.Count == 15)
|
||||
MainGridPageCount = MainGridCurrentPage + 2;
|
||||
|
||||
}
|
||||
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 ShowClicked(OrderSDto order)
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, NoHeader = true, FullWidth = true, DisableBackdropClick = true };
|
||||
var parameters = new DialogParameters<OrderActionDialogBox>();
|
||||
parameters.Add(x => x.Order, order);
|
||||
var dialogResult = await _dialogService.ShowAsync<OrderActionDialogBox>($" سفارش {order.FactorCode}", parameters, maxWidth);
|
||||
var result = await dialogResult.Result;
|
||||
if (!result.Canceled && result.Data is bool and true)
|
||||
{
|
||||
await InitializeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
@page "/pages"
|
||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
|
||||
|
||||
@inject IDialogService DialogService
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IUserUtility UserUtility
|
||||
@inject IRestWrapper RestWrapper
|
||||
|
||||
<MudStack class="w-full p-8 h-screen bg-[--mud-palette-background-grey]">
|
||||
<MudGrid>
|
||||
<MudItem xs="12">
|
||||
<MudStack Row="true" class="mb-5">
|
||||
<MudText Typo="Typo.h4">پرداختـــ ها</MudText>
|
||||
<MudSpacer />
|
||||
</MudStack>
|
||||
<MudPaper>
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
T="PaymentSDto" Items="@ViewModel.PageDto" CurrentPage="@ViewModel.CurrentPage"
|
||||
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false">
|
||||
|
||||
@* <ToolBarContent>
|
||||
<MudTextField T="string" Placeholder="جست جو بر اساس کد پیگیری" Adornment="Adornment.Start" Immediate="true"
|
||||
Clearable="true"
|
||||
ValueChanged="@ViewModel.SearchChanged"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||
</ToolBarContent> *@
|
||||
<Columns>
|
||||
<PropertyColumn Title="شماره فاکتور" Property="arg => arg.FactorNumber" />
|
||||
<PropertyColumn Title="پرداخت کننده" Property="arg => arg.UserFullName" />
|
||||
<PropertyColumn Title="شماره تماس" Property="arg => arg.UserPhoneNumber" />
|
||||
<TemplateColumn T="PaymentSDto" Title="نوع پرداخت">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.Type.ToDisplay()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn T="PaymentSDto" Title="وظعیت پرداخت">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.Status.ToDisplay()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn T="PaymentSDto" Title="مبلغ سفارش ">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.Amount.ToString("N0") ریالــ</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn T="PaymentSDto" Title="تاریخ پرداخت">
|
||||
<CellTemplate>
|
||||
<p>@context.Item.CreatedAt.ToPersianDateTime().ToLongDateString()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.PanoramaFishEye"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Info"
|
||||
OnClick="async()=>await ViewModel.ShowClicked(context.Item)" />
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
</Columns>
|
||||
<PagerContent>
|
||||
<MudStack Row="true" class="w-full">
|
||||
|
||||
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.PageCount"
|
||||
SelectedChanged="@ViewModel.ChangePageAsync" class="my-4 mx-auto" />
|
||||
</MudStack>
|
||||
|
||||
</PagerContent>
|
||||
</MudDataGrid>
|
||||
</MudPaper>
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudStack>
|
||||
|
||||
@code
|
||||
{
|
||||
public PaymentsPageViewModel ViewModel { get; set; }
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ViewModel = new PaymentsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||
|
||||
public class PagesManagementPageViewModel
|
||||
{
|
||||
|
||||
}
|
|
@ -16,34 +16,55 @@
|
|||
</MudStack>
|
||||
<MudPaper>
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
T="BlogSDto" Items="@ViewModel.PageDto" CurrentPage="@ViewModel.CurrentPage"
|
||||
T="PaymentSDto" Items="@ViewModel.PageDto" CurrentPage="@ViewModel.CurrentPage"
|
||||
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
|
||||
SortMode="@SortMode.None" Groupable="false">
|
||||
|
||||
<ToolBarContent>
|
||||
@* <ToolBarContent>
|
||||
<MudTextField T="string" Placeholder="جست جو بر اساس کد پیگیری" Adornment="Adornment.Start" Immediate="true"
|
||||
Clearable="true"
|
||||
ValueChanged="@ViewModel.SearchChanged"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
|
||||
OnAdornmentClick="@ViewModel.SearchAsync"></MudTextField>
|
||||
</ToolBarContent>
|
||||
</ToolBarContent> *@
|
||||
<Columns>
|
||||
<PropertyColumn Title="کد پیگیری" Property="arg => arg.Title" />
|
||||
<PropertyColumn Title="مبلغ" Property="arg => arg.CategoryName" />
|
||||
<PropertyColumn Title="تاریخ پرداخت" Property="arg => arg.ReadingTime" />
|
||||
<PropertyColumn Title="شماره فاکتور" Property="arg => arg.FactorNumber" />
|
||||
<PropertyColumn Title="پرداخت کننده" Property="arg => arg.UserFullName" />
|
||||
<PropertyColumn Title="شماره تماس" Property="arg => arg.UserPhoneNumber" />
|
||||
<TemplateColumn T="PaymentSDto" Title="نوع پرداخت">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.Type.ToDisplay()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
<TemplateColumn T="PaymentSDto" Title="وظعیت پرداخت">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.Status.ToDisplay()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn T="PaymentSDto" Title="مبلغ سفارش ">
|
||||
|
||||
<CellTemplate>
|
||||
<p>@context.Item.Amount.ToString("N0") ریالــ</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn T="PaymentSDto" Title="تاریخ پرداخت">
|
||||
<CellTemplate>
|
||||
<p>@context.Item.CreatedAt.ToPersianDateTime().ToLongDateString()</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn CellClass="d-flex justify-end">
|
||||
<CellTemplate>
|
||||
<MudStack Row="true">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Edit"
|
||||
<MudIconButton Icon="@Icons.Material.Filled.PanoramaFishEye"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
Color="@Color.Info"
|
||||
OnClick="async()=>await ViewModel.EditBlogClicked(context.Item)" />
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Delete"
|
||||
Size="@Size.Small"
|
||||
Variant="@Variant.Outlined"
|
||||
OnClick="async () => await ViewModel.DeleteBlogAsync(context.Item.Id)"
|
||||
Color="@Color.Error" />
|
||||
OnClick="async()=>await ViewModel.ShowClicked(context.Item)" />
|
||||
</MudStack>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
@ -64,10 +85,10 @@
|
|||
|
||||
@code
|
||||
{
|
||||
public BlogsPageViewModel ViewModel { get; set; }
|
||||
public PaymentsPageViewModel ViewModel { get; set; }
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
ViewModel = new BlogsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||
ViewModel = new PaymentsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
|
||||
await ViewModel.InitializeAsync();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
|
|
@ -1,6 +1,105 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||
|
||||
public class PaymentsPageViewModel
|
||||
public class PaymentsPageViewModel : BaseViewModel<ObservableCollection<PaymentSDto>>
|
||||
{
|
||||
private readonly NavigationManager _navigationManager;
|
||||
private readonly ISnackbar _snackbar;
|
||||
private readonly IUserUtility _userUtility;
|
||||
private readonly IDialogService _dialogService;
|
||||
private readonly IRestWrapper _restWrapper;
|
||||
|
||||
public string Search = string.Empty;
|
||||
public int CurrentPage = 0;
|
||||
public int PageCount = 1;
|
||||
|
||||
public PaymentsPageViewModel(NavigationManager navigationManager, ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
|
||||
{
|
||||
_navigationManager = navigationManager;
|
||||
_snackbar = snackbar;
|
||||
_userUtility = userUtility;
|
||||
_restWrapper = restWrapper;
|
||||
_dialogService = dialogService;
|
||||
}
|
||||
|
||||
public override async Task InitializeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
IsProcessing = true;
|
||||
PageDto.Clear();
|
||||
var dto = await _restWrapper.PaymentRestApi.ReadAll(CurrentPage, token);
|
||||
dto.ForEach(d => PageDto.Add(d));
|
||||
if (PageDto.Count == 20)
|
||||
PageCount = 2;
|
||||
}
|
||||
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 base.InitializeAsync();
|
||||
}
|
||||
|
||||
public async Task ChangePageAsync(int page)
|
||||
{
|
||||
CurrentPage = page - 1;
|
||||
if (CurrentPage > PageCount - 2)
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
IsProcessing = true;
|
||||
var token = await _userUtility.GetBearerTokenAsync();
|
||||
if (token == null)
|
||||
throw new Exception("Token is null");
|
||||
|
||||
|
||||
var dto = await _restWrapper.PaymentRestApi.ReadAll(CurrentPage, token);
|
||||
dto.ForEach(d => PageDto.Add(d));
|
||||
if (PageDto.Count == 20)
|
||||
PageCount = CurrentPage + 2;
|
||||
|
||||
}
|
||||
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 ShowClicked(PaymentSDto order)
|
||||
{
|
||||
//DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, NoHeader = true, FullWidth = true, DisableBackdropClick = true };
|
||||
//var parameters = new DialogParameters<OrderActionDialogBox>();
|
||||
//parameters.Add(x => x.Order, order);
|
||||
//var dialogResult = await _dialogService.ShowAsync<OrderActionDialogBox>($" سفارش {order.FactorCode}", parameters, maxWidth);
|
||||
//var result = await dialogResult.Result;
|
||||
//if (!result.Canceled && result.Data is bool and true)
|
||||
//{
|
||||
// await InitializeAsync();
|
||||
//}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,12 @@
|
|||
Color="Color.Secondary"
|
||||
OnClick="@ViewModel.AddProductClicked"
|
||||
class="my-auto">افزودن محصول</MudButton>
|
||||
@* <MudButton Variant="Variant.Filled"
|
||||
DisableElevation="true"
|
||||
StartIcon="@Icons.Material.Outlined.Add"
|
||||
Color="Color.Error"
|
||||
OnClick="@ViewModel.AddDigikalaProductClicked"
|
||||
class="my-auto">افزودن محصول از دیجیکالا</MudButton> *@
|
||||
</MudStack>
|
||||
<MudPaper>
|
||||
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MudBlazor;
|
||||
using NetinaShop.Domain.Dtos.ResponseDtos;
|
||||
|
||||
namespace NetinaShop.AdminPanel.PWA.Pages;
|
||||
|
||||
|
@ -30,7 +31,7 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
IsProcessing = true;
|
||||
PageDto.Clear();
|
||||
var dto = await _restWrapper.ProductRestApi.ReadAll(CurrentPage);
|
||||
dto.ForEach(d => PageDto.Add(d));
|
||||
dto.Products.ForEach(d => PageDto.Add(d));
|
||||
if (PageDto.Count == 20)
|
||||
PageCount = 2;
|
||||
}
|
||||
|
@ -61,18 +62,17 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
{
|
||||
IsProcessing = true;
|
||||
|
||||
List<ProductSDto> dto = new List<ProductSDto>();
|
||||
GetProductsResponseDto dto = new GetProductsResponseDto();
|
||||
if (Search.IsNullOrEmpty())
|
||||
{
|
||||
dto = await _restWrapper.CrudDtoApiRest<Product, ProductSDto, Guid>(Address.ProductController)
|
||||
.ReadAll(CurrentPage);
|
||||
dto = await _restWrapper.ProductRestApi.ReadAll(CurrentPage);
|
||||
}
|
||||
else
|
||||
{
|
||||
dto = await _restWrapper.ProductRestApi.ReadAll(CurrentPage, Search);
|
||||
}
|
||||
|
||||
dto.ForEach(d => PageDto.Add(d));
|
||||
dto.Products.ForEach(d => PageDto.Add(d));
|
||||
if (PageDto.Count % 20 == 0)
|
||||
PageCount = CurrentPage + 2;
|
||||
|
||||
|
@ -96,7 +96,7 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
|
||||
public async Task AddProductClicked()
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, FullWidth = true, DisableBackdropClick = true };
|
||||
var dialogResult = await _dialogService.ShowAsync<ProductActionDialogBox>("افزودن محصول جدید", maxWidth);
|
||||
var result = await dialogResult.Result;
|
||||
if (!result.Canceled && result.Data is bool and true)
|
||||
|
@ -105,9 +105,21 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
}
|
||||
}
|
||||
|
||||
public async Task AddDigikalaProductClicked()
|
||||
{
|
||||
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
var dialogResult = await _dialogService.ShowAsync<DigikalaProductActionDialogBox>("افزودن محصول جدید", maxWidth);
|
||||
var result = await dialogResult.Result;
|
||||
if (!result.Canceled && result.Data is bool and true)
|
||||
{
|
||||
await InitializeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task EditProductClicked(ProductSDto product)
|
||||
{
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
|
||||
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Large, FullWidth = true, DisableBackdropClick = true };
|
||||
var parameters = new DialogParameters<ProductActionDialogBox>();
|
||||
parameters.Add(x => x.Product, product);
|
||||
var dialogResult = await _dialogService.ShowAsync<ProductActionDialogBox>($"ویرایش محصول {product.PersianName}", parameters, maxWidth);
|
||||
|
@ -173,7 +185,7 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
|
|||
PageCount = 1;
|
||||
PageDto.Clear();
|
||||
var dto = await _restWrapper.ProductRestApi.ReadAll(CurrentPage, Search);
|
||||
dto.ForEach(d => PageDto.Add(d));
|
||||
dto.Products.ForEach(d => PageDto.Add(d));
|
||||
if (PageDto.Count == 20)
|
||||
PageCount = 2;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,13 @@
|
|||
<Columns>
|
||||
<PropertyColumn Title="نام" Property="arg => arg.Name" />
|
||||
<PropertyColumn Title="نام انبار ارسال" Property="arg => arg.WarehouseName" />
|
||||
<PropertyColumn Title="هرینه ارسال" Property="arg => arg.DeliveryCost" />
|
||||
|
||||
<TemplateColumn T="ShippingSDto" Title="هزینه ارسال">
|
||||
<CellTemplate>
|
||||
<p>@context.Item.DeliveryCost.ToString("N0") ریالــ</p>
|
||||
</CellTemplate>
|
||||
</TemplateColumn>
|
||||
|
||||
<TemplateColumn T="ShippingSDto" Title="ارسال فوری می باشد">
|
||||
<CellTemplate>
|
||||
@if (@context.Item.IsExpressShipping)
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
public interface IOrderRestApi
|
||||
{
|
||||
[Get("")]
|
||||
Task<List<OrderSDto>> ReadAll([Query]int page, [Query] long? selectedDate, [Query] OrderStatus? orderStatus, [Query] OrderQueryDateFilter? dateFilter, [Header("Authorization")] string authorization);
|
||||
|
||||
[Get("/{id}")]
|
||||
Task<OrderLDto> ReadOne(Guid id, [Header("Authorization")] string authorization);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
public interface IPageRestApi
|
||||
{
|
||||
|
||||
[Get("/type/{type}")]
|
||||
Task<BasePageEntitySDto> ReadByType([Query] string type, [Header("Authorization")] string authorization);
|
||||
|
||||
[Get("/{id}")]
|
||||
Task<BasePageEntitySDto> ReadById(Guid id, [Header("Authorization")] string authorization);
|
||||
|
||||
[Post("")]
|
||||
Task CreatePage([Body] PageActionRequestDto request, [Header("Authorization")] string authorization);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
public interface IPaymentRestApi
|
||||
{
|
||||
[Get("")]
|
||||
Task<List<PaymentSDto>> ReadAll([Query] int page, [Header("Authorization")] string authorization);
|
||||
|
||||
}
|
|
@ -1,14 +1,18 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||
using NetinaShop.Domain.Dtos.ResponseDtos;
|
||||
|
||||
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
public interface IProductRestApi
|
||||
{
|
||||
|
||||
[Get("")]
|
||||
Task<List<ProductSDto>> ReadAll();
|
||||
Task<GetProductsResponseDto> ReadAll();
|
||||
[Get("/{productId}")]
|
||||
Task<GetProductResponseDto> ReadOne(Guid productId);
|
||||
[Get("")]
|
||||
Task<List<ProductSDto>> ReadAll([Query] int page);
|
||||
Task<GetProductsResponseDto> ReadAll([Query] int page);
|
||||
[Get("")]
|
||||
Task<List<ProductSDto>> ReadAll([Query] int page, [Query] string productName);
|
||||
Task<GetProductsResponseDto> ReadAll([Query] int page, [Query] string productName);
|
||||
[Get("")]
|
||||
Task<List<ProductSDto>> ReadAll([Query] string productName);
|
||||
Task<GetProductsResponseDto> ReadAll([Query] string productName);
|
||||
}
|
|
@ -16,4 +16,8 @@ public interface IRestWrapper
|
|||
public IDiscountRestApi DiscountRest { get; }
|
||||
public IBlogCategoryRestApi BlogCategoryRestApi { get; }
|
||||
public IRoleRestApi RoleRestApi { get; }
|
||||
public IOrderRestApi OrderRestApi { get; }
|
||||
public IPaymentRestApi PaymentRestApi { get; }
|
||||
public IPageRestApi PageRestApi { get; }
|
||||
public IScraperRestApi ScraperRestApi { get; }
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using NetinaShop.Domain.Dtos.ScraperDtos.Response;
|
||||
|
||||
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
|
||||
|
||||
public interface IScraperRestApi
|
||||
{
|
||||
[Get("/digi")]
|
||||
Task<List<ScraperProductDto>> SearchDigiProductsAsync([Query] string productName, [Header("Authorization")]string authorization);
|
||||
[Post("/digi/{productId}")]
|
||||
Task<bool> AddDigiProductToShopAsync(string productId, [Query] string productName, [Header("Authorization")] string authorization);
|
||||
}
|
|
@ -27,5 +27,9 @@ public class RestWrapper : IRestWrapper
|
|||
public IBlogRestApi BlogRestApi => RestService.For<IBlogRestApi>(Address.BlogController, setting);
|
||||
public IDiscountRestApi DiscountRest => RestService.For<IDiscountRestApi>(Address.DiscountController, setting);
|
||||
public IBlogCategoryRestApi BlogCategoryRestApi => RestService.For<IBlogCategoryRestApi>(Address.BlogCategoryController, setting);
|
||||
public IRoleRestApi RoleRestApi => RestService.For<IRoleRestApi>(Address.RoleController);
|
||||
public IRoleRestApi RoleRestApi => RestService.For<IRoleRestApi>(Address.RoleController, setting);
|
||||
public IOrderRestApi OrderRestApi => RestService.For<IOrderRestApi>(Address.OrderController, setting);
|
||||
public IPaymentRestApi PaymentRestApi => RestService.For<IPaymentRestApi>(Address.PaymentController, setting);
|
||||
public IPageRestApi PageRestApi => RestService.For<IPageRestApi>(Address.PageController, setting);
|
||||
public IScraperRestApi ScraperRestApi => RestService.For<IScraperRestApi>(Address.ScraperController, setting);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
namespace NetinaShop.AdminPanel.PWA.Utilities.Models;
|
||||
public class CustomEventHelper
|
||||
{
|
||||
private readonly Func<EventArgs, Task> _callback;
|
||||
|
||||
public CustomEventHelper(Func<EventArgs, Task> callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public Task OnCustomEvent(EventArgs args) => _callback(args);
|
||||
}
|
||||
|
||||
public class CustomEventInterop : IDisposable
|
||||
{
|
||||
private readonly IJSRuntime _jsRuntime;
|
||||
private DotNetObjectReference<CustomEventHelper> Reference;
|
||||
|
||||
public CustomEventInterop(IJSRuntime jsRuntime)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
public ValueTask<string> SetupCustomEventCallback(Func<EventArgs, Task> callback)
|
||||
{
|
||||
Reference = DotNetObjectReference.Create(new CustomEventHelper(callback));
|
||||
// addCustomEventListener will be a js function we create later
|
||||
return _jsRuntime.InvokeAsync<string>("addCustomEventListener", Reference);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Reference?.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
@ -1084,6 +1084,10 @@ input:checked + .toggle-bg {
|
|||
margin-top: 2.5rem;
|
||||
margin-bottom: 2.5rem;
|
||||
}
|
||||
.my-2 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.my-4 {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -1128,6 +1132,9 @@ input:checked + .toggle-bg {
|
|||
.mb-5 {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.mb-8 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.mr-1 {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
@ -1158,6 +1165,9 @@ input:checked + .toggle-bg {
|
|||
.mt-6 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.mt-8 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.line-clamp-1 {
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
|
@ -1224,6 +1234,9 @@ input:checked + .toggle-bg {
|
|||
.h-96 {
|
||||
height: 24rem;
|
||||
}
|
||||
.h-\[35rem\] {
|
||||
height: 35rem;
|
||||
}
|
||||
.h-fit {
|
||||
height: -moz-fit-content;
|
||||
height: fit-content;
|
||||
|
@ -1237,6 +1250,9 @@ input:checked + .toggle-bg {
|
|||
.max-h-\[30rem\] {
|
||||
max-height: 30rem;
|
||||
}
|
||||
.max-h-\[40rem\] {
|
||||
max-height: 40rem;
|
||||
}
|
||||
.min-h-\[28rem\] {
|
||||
min-height: 28rem;
|
||||
}
|
||||
|
@ -1429,6 +1445,9 @@ input:checked + .toggle-bg {
|
|||
.border-0 {
|
||||
border-width: 0px;
|
||||
}
|
||||
.border-2 {
|
||||
border-width: 2px;
|
||||
}
|
||||
.border-4 {
|
||||
border-width: 4px;
|
||||
}
|
||||
|
@ -1441,6 +1460,9 @@ input:checked + .toggle-bg {
|
|||
.border-solid {
|
||||
border-style: solid;
|
||||
}
|
||||
.border-dashed {
|
||||
border-style: dashed;
|
||||
}
|
||||
.border-blue-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(63 131 248 / var(--tw-border-opacity));
|
||||
|
@ -1469,6 +1491,10 @@ input:checked + .toggle-bg {
|
|||
--tw-border-opacity: 1;
|
||||
border-color: rgb(104 117 245 / var(--tw-border-opacity));
|
||||
}
|
||||
.border-violet-400 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(167 139 250 / var(--tw-border-opacity));
|
||||
}
|
||||
.bg-\[\#000000\] {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
||||
|
@ -1556,6 +1582,10 @@ input:checked + .toggle-bg {
|
|||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
.px-3 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
.px-4 {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
|
@ -1572,6 +1602,10 @@ input:checked + .toggle-bg {
|
|||
padding-top: 0.125rem;
|
||||
padding-bottom: 0.125rem;
|
||||
}
|
||||
.py-1 {
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
|
@ -1600,6 +1634,9 @@ input:checked + .toggle-bg {
|
|||
.text-justify {
|
||||
text-align: justify;
|
||||
}
|
||||
.align-bottom {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.text-5xl {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
@ -1673,6 +1710,10 @@ input:checked + .toggle-bg {
|
|||
--tw-text-opacity: 1;
|
||||
color: rgb(225 29 72 / var(--tw-text-opacity));
|
||||
}
|
||||
.text-violet-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(139 92 246 / var(--tw-text-opacity));
|
||||
}
|
||||
.text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
|
|
|
@ -1165,6 +1165,11 @@ input:checked + .toggle-bg {
|
|||
margin-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.my-2 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.my-4 {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -1223,6 +1228,10 @@ input:checked + .toggle-bg {
|
|||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.mb-8 {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.mr-1 {
|
||||
margin-right: 0.25rem;
|
||||
}
|
||||
|
@ -1263,6 +1272,10 @@ input:checked + .toggle-bg {
|
|||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
.mt-8 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.line-clamp-1 {
|
||||
overflow: hidden;
|
||||
display: -webkit-box;
|
||||
|
@ -1350,6 +1363,10 @@ input:checked + .toggle-bg {
|
|||
height: 24rem;
|
||||
}
|
||||
|
||||
.h-\[35rem\] {
|
||||
height: 35rem;
|
||||
}
|
||||
|
||||
.h-fit {
|
||||
height: -moz-fit-content;
|
||||
height: fit-content;
|
||||
|
@ -1367,6 +1384,10 @@ input:checked + .toggle-bg {
|
|||
max-height: 30rem;
|
||||
}
|
||||
|
||||
.max-h-\[40rem\] {
|
||||
max-height: 40rem;
|
||||
}
|
||||
|
||||
.min-h-\[28rem\] {
|
||||
min-height: 28rem;
|
||||
}
|
||||
|
@ -1617,6 +1638,10 @@ input:checked + .toggle-bg {
|
|||
border-width: 0px;
|
||||
}
|
||||
|
||||
.border-2 {
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
.border-4 {
|
||||
border-width: 4px;
|
||||
}
|
||||
|
@ -1633,6 +1658,10 @@ input:checked + .toggle-bg {
|
|||
border-style: solid;
|
||||
}
|
||||
|
||||
.border-dashed {
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
.border-blue-500 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(63 131 248 / var(--tw-border-opacity));
|
||||
|
@ -1668,6 +1697,11 @@ input:checked + .toggle-bg {
|
|||
border-color: rgb(104 117 245 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.border-violet-400 {
|
||||
--tw-border-opacity: 1;
|
||||
border-color: rgb(167 139 250 / var(--tw-border-opacity));
|
||||
}
|
||||
|
||||
.bg-\[\#000000\] {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(0 0 0 / var(--tw-bg-opacity));
|
||||
|
@ -1780,6 +1814,11 @@ input:checked + .toggle-bg {
|
|||
padding-right: 0.5rem;
|
||||
}
|
||||
|
||||
.px-3 {
|
||||
padding-left: 0.75rem;
|
||||
padding-right: 0.75rem;
|
||||
}
|
||||
|
||||
.px-4 {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
|
@ -1800,6 +1839,11 @@ input:checked + .toggle-bg {
|
|||
padding-bottom: 0.125rem;
|
||||
}
|
||||
|
||||
.py-1 {
|
||||
padding-top: 0.25rem;
|
||||
padding-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.py-2 {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
|
@ -1836,6 +1880,10 @@ input:checked + .toggle-bg {
|
|||
text-align: justify;
|
||||
}
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.text-5xl {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
@ -1930,6 +1978,11 @@ input:checked + .toggle-bg {
|
|||
color: rgb(225 29 72 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-violet-500 {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(139 92 246 / var(--tw-text-opacity));
|
||||
}
|
||||
|
||||
.text-white {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(255 255 255 / var(--tw-text-opacity));
|
||||
|
|
|
@ -5,7 +5,9 @@ self.importScripts('./service-worker-assets.js');
|
|||
self.addEventListener('install', event => event.waitUntil(onInstall(event)));
|
||||
self.addEventListener('activate', event => event.waitUntil(onActivate(event)));
|
||||
self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
|
||||
|
||||
self.addEventListener('message', event => {
|
||||
if (event.data?.type === 'SKIP_WAITING') self.skipWaiting();
|
||||
});
|
||||
const cacheNamePrefix = 'offline-cache-';
|
||||
const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
|
||||
const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ];
|
||||
|
|
Loading…
Reference in New Issue