feat : refactor , version 0.27.31.52 , fix issues

add torob search , add webite controller , refacor unused namespaces , fix job scheduler , fix nav menu management page
release
Amir Hossein Khademi 2024-05-07 11:01:57 +03:30
parent 31b9d0638c
commit 684b7783f8
63 changed files with 798 additions and 822 deletions

View File

@ -16,25 +16,21 @@
function destroyEditor() {
// document.querySelector('.editor').ckeditorInstance.destroy();
window.editor = null;
console.log('Editor Destroyed');
}
function setData(data) {
if (window.editor.data != data) {
window.editor.setData(data);
console.log("data passed ", data);
}
}
function lunchEditor(data) {
if (!document.querySelector('.editor')) return
if (window.editor) return
console.log("editor start");
ClassicEditor.create(document.querySelector('.editor'), {
// Editor configuration.
})
.then(editor => {
window.editor = editor;
window.editor.setData(data);
console.log("data passed ", data);
editor.editing.view.document.on('blur', () => {
GLOBAL.DotNetReference.invokeMethodAsync('MyMethod', window.editor.getData());
});

View File

@ -1,57 +1,30 @@
@inject NavigationManager NavigationManager
@inject IRestWrapper RestWrapper
@inject IUserUtility UserUtility
<MudStack class="w-full pt-4 h-screen bg-[--mud-palette-background]">
<MudImage class="mx-15 mt-5" Src="https://vesmeh.com/wp-content/uploads/2023/02/logo-web.png.webp"></MudImage>
<MudNavMenu Rounded="true" Margin="Margin.Dense" Color="Color.Warning" Class="pa-2" Bordered="true">
<MudNavLink Href="home" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Dashboard">داشبورد</MudNavLink>
@if (isShop)
{
<MudNavLink Href="orders"
Icon="@Icons.Material.Outlined.ShoppingBag">فروش</MudNavLink>
}
@if (isShop)
{
<MudNavGroup Title="محصولاتــ" Expanded="false"
Icon="@Icons.Material.Outlined.CenterFocusStrong">
<MudNavLink Href="orders"
Icon="@Icons.Material.Outlined.ShoppingBag">فروش</MudNavLink>
<MudNavGroup Title="محصولاتــ" Expanded="false"
Icon="@Icons.Material.Outlined.CenterFocusStrong">
<MudNavLink Href="products"
Icon="@Icons.Material.Outlined.CenterFocusStrong">محصولاتــ فروشگاه</MudNavLink>
<MudNavLink Href="product/categories"
Icon="@Icons.Material.Outlined.AllInbox">دسته بندی محصولاتـــ</MudNavLink>
<MudNavLink Href="product/brands"
Icon="@Icons.Custom.Brands.Facebook">برند محصولاتــــ</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="حسابداری" Expanded="false"
Icon="@Icons.Material.Outlined.BusinessCenter">
<MudNavLink Href="discounts"
Icon="@Icons.Material.Outlined.LocalOffer">تخفیفـــ ها</MudNavLink>
<MudNavLink Href="payments"
Icon="@Icons.Material.Outlined.AccountBalance">پرداختـــ ها</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="انبارداری" Expanded="false"
Icon="@Icons.Material.Outlined.Inventory">
<MudNavLink Href="inveroty"
Icon="@Icons.Material.Outlined.Inventory2">انبار</MudNavLink>
<MudNavLink Href="inventory/shipping"
Icon="@Icons.Material.Outlined.AirportShuttle">روش های ارسال</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="باشگاه مشتریانـــ" Expanded="false"
Icon="@Icons.Material.Outlined.AccountBalance">
<MudNavLink Href="customers"
Icon="@Icons.Material.Outlined.PeopleAlt">مشترکین</MudNavLink>
<MudNavLink Href="smspanel"
Icon="@Icons.Material.Outlined.Sms">پنل پیامکی</MudNavLink>
<MudNavLink Href="newsletler"
Icon="@Icons.Material.Outlined.Newspaper">خبرنامه</MudNavLink>
</MudNavGroup>
<MudNavLink Href="products"
Icon="@Icons.Material.Outlined.CenterFocusStrong">محصولاتــ فروشگاه</MudNavLink>
<MudNavLink Href="product/categories"
Icon="@Icons.Material.Outlined.AllInbox">دسته بندی محصولاتـــ</MudNavLink>
<MudNavLink Href="product/brands"
Icon="@Icons.Custom.Brands.Facebook">برند محصولاتــــ</MudNavLink>
</MudNavGroup>
}
<MudNavGroup Title="وبلاگــــ" Expanded="false"
Icon="@Icons.Material.Outlined.Web">
@ -62,12 +35,64 @@
Icon="@Icons.Material.Outlined.WebAsset">دسته بندی های بلاگـــ</MudNavLink>
</MudNavGroup>
@if (isShop)
{
<MudNavGroup Title="حسابداری" Expanded="false"
Icon="@Icons.Material.Outlined.BusinessCenter">
<MudNavGroup Title="فروشگاه من" Expanded="false" Icon="@Icons.Material.Outlined.Settings">
<MudNavLink Href="management/shop" Icon="@Icons.Material.Filled.Shop2">فروشگاه</MudNavLink>
<MudNavLink Href="management/marketer" Icon="@Icons.Material.Filled.Person4">بازاریاب ها</MudNavLink>
<MudNavLink Href="management/faqs" Icon="@Icons.Material.Filled.ManageAccounts">سوالات متداول</MudNavLink>
</MudNavGroup>
<MudNavLink Href="discounts"
Icon="@Icons.Material.Outlined.LocalOffer">تخفیفـــ ها</MudNavLink>
<MudNavLink Href="payments"
Icon="@Icons.Material.Outlined.AccountBalance">پرداختـــ ها</MudNavLink>
</MudNavGroup>
}
@if (isShop)
{
<MudNavGroup Title="انبارداری" Expanded="false"
Icon="@Icons.Material.Outlined.Inventory">
<MudNavLink Href="inveroty"
Icon="@Icons.Material.Outlined.Inventory2">انبار</MudNavLink>
<MudNavLink Href="inventory/shipping"
Icon="@Icons.Material.Outlined.AirportShuttle">روش های ارسال</MudNavLink>
</MudNavGroup>
}
@if (isShop)
{
<MudNavGroup Title="باشگاه مشتریانـــ" Expanded="false"
Icon="@Icons.Material.Outlined.AccountBalance">
<MudNavLink Href="customers"
Icon="@Icons.Material.Outlined.PeopleAlt">مشترکین</MudNavLink>
<MudNavLink Href="smspanel"
Icon="@Icons.Material.Outlined.Sms">پنل پیامکی</MudNavLink>
<MudNavLink Href="newsletler"
Icon="@Icons.Material.Outlined.Newspaper">خبرنامه</MudNavLink>
</MudNavGroup>
}
@if (isShop)
{
<MudNavGroup Title="شخصی سازی" Expanded="false" Icon="@Icons.Material.Outlined.PersonalInjury">
<MudNavLink Href="personalization/nav" Icon="@Icons.Material.Filled.Navigation">فهرست ها</MudNavLink>
</MudNavGroup>
}
@if (isShop)
{
<MudNavGroup Title="فروشگاه من" Expanded="false" Icon="@Icons.Material.Outlined.Settings">
<MudNavLink Href="management/shop" Icon="@Icons.Material.Filled.Shop2">فروشگاه</MudNavLink>
<MudNavLink Href="management/marketer" Icon="@Icons.Material.Filled.Person4">بازاریاب ها</MudNavLink>
<MudNavLink Href="management/faqs" Icon="@Icons.Material.Filled.ManageAccounts">سوالات متداول</MudNavLink>
</MudNavGroup>
}
else
{
<MudNavGroup Title="وب سایتــ من" Expanded="false" Icon="@Icons.Material.Outlined.Settings">
<MudNavLink Href="management/shop" Icon="@Icons.Material.Filled.Shop2">وب سایتــ</MudNavLink>
</MudNavGroup>
}
<MudNavGroup Title="تنظیماتـــ" Expanded="false" Icon="@Icons.Material.Outlined.Settings">
<MudNavLink Href="setting/users" Icon="@Icons.Material.Filled.ManageAccounts">نقش ها و کاربران</MudNavLink>
@ -78,61 +103,37 @@
@code
{
string? version = typeof(Program)?.Assembly.GetName()?.Version?.ToString();
private void SelectNav()
private bool isShop = true;
protected override async Task OnInitializedAsync()
{
}
private void SelectedChange(TreeItemData? data)
{
if (data != null)
NavigationManager.NavigateTo(data.Page);
}
private HashSet<TreeItemData> TreeItems { get; set; } = new HashSet<TreeItemData>();
public class TreeItemData
{
public string Text { get; set; }
public string Icon { get; set; }
public string Page { get; set; }
private bool _isActive;
public bool IsActive
try
{
get { return _isActive; }
set
var token = await UserUtility.GetBearerTokenAsync();
if (token == null)
{
await UserUtility.LogoutAsync();
NavigationManager.NavigateTo("login", true, true);
return;
}
_isActive = value;
var rest = await RestWrapper.SettingRestApi.GetSettingAsync<NetinaSetting>(nameof(NetinaSetting), token);
if (rest.WebSiteType == 0)
isShop = true;
else
isShop = false;
await base.OnInitializedAsync();
}
catch (ApiException e)
{
var exe = await e.GetContentAsAsync<ApiResult>();
if (e.StatusCode == HttpStatusCode.Unauthorized)
{
await UserUtility.LogoutAsync();
NavigationManager.NavigateTo("login", true, true);
}
}
public HashSet<TreeItemData> TreeItems { get; set; } = new HashSet<TreeItemData>();
public TreeItemData(string text, string icon, string page)
{
Page = page;
Text = text;
Icon = icon;
}
}
protected override void OnInitialized()
{
TreeItems.Add(new TreeItemData("داشبورد", Icons.Material.Outlined.Dashboard, ""));
TreeItems.Add(new TreeItemData("فروش", Icons.Material.Outlined.ShoppingCart, "products"));
TreeItems.Add(new TreeItemData("محصولات", Icons.Material.Outlined.CenterFocusStrong, "products"));
TreeItems.Add(new TreeItemData("دسته بندی محصولات", Icons.Material.Outlined.AllInbox, "categories"));
TreeItems.Add(new TreeItemData("برند محصولات", Icons.Custom.Brands.Facebook, "brands"));
TreeItems.Add(new TreeItemData("بلاگ ها", Icons.Material.Outlined.Web, "blogs"));
TreeItems.Add(new TreeItemData("دسته بندی بلاگ ها", Icons.Material.Outlined.Web, "blog/categories"));
TreeItems.Add(new TreeItemData("مشترکین", Icons.Material.Outlined.People, "products"));
TreeItems.Add(new TreeItemData("تنظیمات", Icons.Material.Outlined.Settings, "products"));
}
string? version = typeof(Program)?.Assembly.GetName()?.Version?.ToString();
}

View File

@ -1,8 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.Domain.Entities.Blogs;
using Netina.Domain.Entities.Blogs;
namespace Netina.AdminPanel.PWA.Dialogs;

View File

@ -1,6 +1,4 @@
@using Netina.AdminPanel.PWA.Models.Api
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Models
@using Netina.Domain.Entities.Blogs

View File

@ -1,8 +1,5 @@
@using Netina.AdminPanel.PWA.Models.Api
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Models
@using Netina.Common.Extensions
@using Netina.Domain.Entities.Brands
@inject ISnackbar Snackbar

View File

@ -1,7 +1,4 @@
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@inject ISnackbar Snackbar
@inject ISnackbar Snackbar
@inject IRestWrapper RestWrapper
@inject IUserUtility UserUtility
@inject IDialogService DialogService

View File

@ -1,5 +1,4 @@
using System.Net;
using Netina.Domain.Dtos.ScraperDtos.Response;
using Netina.Domain.Dtos.ScraperDtos.Response;
namespace Netina.AdminPanel.PWA.Dialogs;

View File

@ -1,6 +1,4 @@
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Extensions
@using Netina.AdminPanel.PWA.Extensions
@inject ISnackbar Snackbar
@inject IRestWrapper RestWrapper
@inject IUserUtility UserUtility

View File

@ -1,7 +1,5 @@
@using Color = MudBlazor.Color
@using Size = MudBlazor.Size
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@inject ISnackbar Snackbar
@inject IRestWrapper RestWrapper

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Dialogs;
namespace Netina.AdminPanel.PWA.Dialogs;
public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
{
@ -85,17 +80,7 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
IsProcessing = true;
var response = await _restWrapper.ProductRestApi.ReadOne(_product.Id);
var productLDto = response.Product;
PageDto.ExpertCheck = productLDto.ExpertCheck;
PageDto.Summery = productLDto.Summery;
PageDto.BeDisplayed = productLDto.BeDisplayed;
PageDto.HasExpressDelivery = productLDto.HasExpressDelivery;
PageDto.PersianName = productLDto.PersianName;
PageDto.EnglishName = productLDto.EnglishName;
PageDto.Cost = productLDto.Cost;
PageDto.PackingCost = productLDto.PackingCost;
PageDto.MaxOrderCount = productLDto.MaxOrderCount;
PageDto.Warranty = productLDto.Warranty;
PageDto.Stock = productLDto.Stock;
PageDto = productLDto;
productLDto.Specifications.ForEach(s => Specifications.Add(s));
productLDto.Files.ForEach(f => Files.Add(f));
SelectedCategory = new ProductCategorySDto { Id = productLDto.CategoryId, Name = productLDto.CategoryName };

View File

@ -1,6 +1,4 @@
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@inject ISnackbar Snackbar
@inject ISnackbar Snackbar
@inject IRestWrapper RestWrapper
@inject IUserUtility UserUtility
@inject IDialogService DialogService

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Dialogs;
namespace Netina.AdminPanel.PWA.Dialogs;
public class ProductCategoryActionDialogBoxViewModel:BaseViewModel
{

View File

@ -1,8 +1,4 @@
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@using Netina.Domain.Entities.Users
@inject ISnackbar Snackbar
@inject ISnackbar Snackbar
@inject IRestWrapper RestWrapper
@inject IUserUtility UserUtility
@inject IDialogService DialogService

View File

@ -1,8 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.Domain.Entities.Warehouses;
using Netina.Domain.Entities.Warehouses;
namespace Netina.AdminPanel.PWA.Dialogs;

View File

@ -1,6 +1,4 @@
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@inject IRestWrapper RestWrapper
@inject IRestWrapper RestWrapper
@inject IUserUtility UserUtility
@inject ISnackbar Snackbar
@ -72,11 +70,14 @@
[CascadingParameter]
MudDialogInstance MudDialog { get; set; }
[Parameter]
public FileUploadType FileUploadType { get; set; } = FileUploadType.Image;
public StorageDialogBoxViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
ViewModel = new StorageDialogBoxViewModel(RestWrapper,UserUtility,Snackbar,MudDialog);
ViewModel = new StorageDialogBoxViewModel(RestWrapper, UserUtility, Snackbar, MudDialog, FileUploadType);
await ViewModel.InitializeAsync();
await base.OnInitializedAsync();
}

View File

@ -1,8 +1,4 @@
using Microsoft.AspNetCore.Components.Forms;
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Dialogs;
@ -13,6 +9,7 @@ public class StorageDialogBoxViewModel : BaseViewModel
private readonly ISnackbar _snackbar;
private readonly MudDialogInstance _mudDialog;
private readonly FileUploadType _fileUploadType;
public readonly ObservableCollection<StorageFileSDto> Files = new ObservableCollection<StorageFileSDto>();
public List<StorageFileSDto> OriginalFiles = new List<StorageFileSDto>();
@ -20,12 +17,13 @@ public class StorageDialogBoxViewModel : BaseViewModel
public bool IsPrimary { get; set; }
public bool IsHeader { get; set; }
public StorageDialogBoxViewModel(IRestWrapper restWrapper, IUserUtility userUtility, ISnackbar snackbar, MudDialogInstance mudDialog)
public StorageDialogBoxViewModel(IRestWrapper restWrapper, IUserUtility userUtility, ISnackbar snackbar, MudDialogInstance mudDialog,FileUploadType fileUploadType)
{
_restWrapper = restWrapper;
_userUtility = userUtility;
_snackbar = snackbar;
_mudDialog = mudDialog;
_fileUploadType = fileUploadType;
}
@ -124,7 +122,7 @@ public class StorageDialogBoxViewModel : BaseViewModel
{
ContentType = file.ContentType,
FileName = file.Name,
FileUploadType = FileUploadType.Image,
FileUploadType = _fileUploadType,
StringBaseFile = Convert.ToBase64String(memoryStream.ToArray())
};
var token = await _userUtility.GetBearerTokenAsync();

View File

@ -1,9 +1,4 @@
using Mapster;
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.Domain.Entities.Users;
using Netina.Domain.Entities.Users;
namespace Netina.AdminPanel.PWA.Dialogs;

View File

@ -2,6 +2,9 @@
public static class Address
{
public static string WebSiteAddress = string.Empty;
public static string StorageAddress = string.Empty;
#if DEBUG
public static string BaseAddress = "http://localhost:32770/api";
//public static string BaseAddress = "https://api.vesmeh.com/api";

View File

@ -90,16 +90,27 @@
<Using Include="Netina.Domain.Entities.Products" />
<Using Include="Netina.Domain.Enums" />
<Using Include="Netina.Domain.MartenEntities.Pages" />
<Using Include="Netina.Domain.MartenEntities.Settings" />
<Using Include="Netina.Domain.Models.Districts" />
<Using Include="Newtonsoft.Json" />
<Using Include="Refit" />
<Using Include="System.Collections.ObjectModel" />
<Using Include="System.Net" />
</ItemGroup>
<ItemGroup>
<Content Update="version.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\appsettings.Development.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Update="wwwroot\appsettings.Production.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@ -1,6 +1,4 @@
@page "/blog/categories"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.AdminPanel.PWA.Utilities.Models;
using Netina.Domain.Entities.Blogs;
using Netina.Domain.Entities.Blogs;
namespace Netina.AdminPanel.PWA.Pages;

View File

@ -1,6 +1,4 @@
@page "/blogs"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,6 +1,4 @@
@page "/product/brands"
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@inject IDialogService DialogService
@inject NavigationManager NavigationManager

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.AdminPanel.PWA.Utilities.Models;
using Netina.Domain.Entities.Brands;
using Netina.Domain.Entities.Brands;
namespace Netina.AdminPanel.PWA.Pages;

View File

@ -1,7 +1,4 @@
@using Radzen.Blazor
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.AdminPanel.PWA.Utilities
@page "/product/categories"
@page "/product/categories"
@inject IDialogService DialogService
@inject NavigationManager NavigationManager
@inject IRestWrapper RestWrapper

View File

@ -1,10 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.AdminPanel.PWA.Utilities.Models;
namespace Netina.AdminPanel.PWA.Pages;
namespace Netina.AdminPanel.PWA.Pages;
public class CategoriesPageViewModel : BaseViewModel<ObservableCollection<ProductCategorySDto>>
{

View File

@ -1,6 +1,4 @@
@page "/discounts"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.AdminPanel.PWA.Utilities.Models;
using Netina.Domain.Entities.Discounts;
using Netina.Domain.Entities.Discounts;
namespace Netina.AdminPanel.PWA.Pages;

View File

@ -1,6 +1,4 @@
@page "/management/faqs"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Pages;
namespace Netina.AdminPanel.PWA.Pages;
public class FaqManagementPageViewModel : BaseViewModel<FAQPage>
{

View File

@ -168,7 +168,7 @@
public HomeViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
ViewModel = new HomeViewModel(Snackbar, UserUtility, RestWrapper, DialogService);
ViewModel = new HomeViewModel(Snackbar, UserUtility, RestWrapper, DialogService,NavigationManager);
await ViewModel.InitializeAsync();
await base.OnInitializedAsync();
}

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Pages;
namespace Netina.AdminPanel.PWA.Pages;
public class HomeViewModel : BaseViewModel<HomeDashboardDto>
{
@ -12,13 +7,15 @@ public class HomeViewModel : BaseViewModel<HomeDashboardDto>
private readonly IUserUtility _userUtility;
private readonly IRestWrapper _restWrapper;
private readonly IDialogService _dialogService;
private readonly NavigationManager _navigationManager;
public HomeViewModel(ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService)
public HomeViewModel(ISnackbar snackbar, IUserUtility userUtility, IRestWrapper restWrapper, IDialogService dialogService,NavigationManager navigationManager)
{
_snackbar = snackbar;
_userUtility = userUtility;
_restWrapper = restWrapper;
_dialogService = dialogService;
_navigationManager = navigationManager;
}
public override async Task InitializeAsync()
@ -45,6 +42,11 @@ public class HomeViewModel : BaseViewModel<HomeDashboardDto>
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)

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Pages;
namespace Netina.AdminPanel.PWA.Pages;
public class LoginPageViewModel : BaseViewModel
{

View File

@ -1,6 +1,4 @@
using Netina.Domain.MartenEntities.Settings;
namespace Netina.AdminPanel.PWA.Pages;
namespace Netina.AdminPanel.PWA.Pages;
public class MarketerManagementPageViewModel : BaseViewModel<MarketerSetting>
{

View File

@ -1,6 +1,4 @@
@page "/newsletler"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,8 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.Domain.Entities.Users;
using Netina.Domain.Entities.Users;
namespace Netina.AdminPanel.PWA.Pages;

View File

@ -1,7 +1,4 @@
@page "/orders"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@using Netina.Common.Extensions
@using Netina.Domain.Models.Claims
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@attribute [PermissionAuthorize(ApplicationPermission.ManageDashboard)]

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Pages;
namespace Netina.AdminPanel.PWA.Pages;
public class OrdersPageViewModel : BaseViewModel
{

View File

@ -1,6 +1,4 @@
@page "/pages"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,6 +1,4 @@
@page "/payments"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Pages;
namespace Netina.AdminPanel.PWA.Pages;
public class PaymentsPageViewModel : BaseViewModel<ObservableCollection<PaymentSDto>>
{

View File

@ -0,0 +1,197 @@
@page "/personalization/nav"
@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]">
<MudPaper class="px-5 py-5">
<MudStack>
<MudStack Row="true">
<MudStack class="mb-5 mx-2">
<MudText Typo="Typo.h4">تنظیمات فهرست ها</MudText>
<MudText Typo="Typo.caption">فهرست های بالای سایت خود را ویرایش نمایید</MudText>
</MudStack>
<MudSpacer />
<BaseButtonUi Size="Size.Large"
OnClickCallback="ViewModel.SubmitNavMenuSettingAsync"
class="mt-2 mb-8 w-64 rounded-md"
IsProcessing="@ViewModel.IsProcessing"
Icon="@Icons.Material.Outlined.Check"
Content="ثبتـــ اطلاعات" Variant="Variant.Filled" Color="Color.Success" />
</MudStack>
<MudStack Row="true">
<MudSwitch @bind-Value="@ViewModel.PageDto.ShowProductCategories" class="mt-2" Size="Size.Large" T="bool" Label="تنها دسته بندی محصولات را نمایش بدهد ؟" Color="Color.Info" />
<MudSpacer />
<MudSwitch @bind-Value="@ViewModel.PageDto.ShowBlogCategories" class="mt-2" Size="Size.Large" T="bool" Label="تنها دسته بندی بلاگ ها را نمایش بدهد ؟" Color="Color.Info" />
</MudStack>
<MudGrid class="!max-h-[80vh] overflow-auto">
<MudItem xs="6">
<MudDivider />
<MudText Typo="Typo.h6">افزودن فهرست جدید</MudText>
<MudTextField @bind-Value="@ViewModel.NewNavItem.Title" T="string" Label="عنوان" Variant="Variant.Outlined" />
<MudTextField class="my-3" @bind-Value="@ViewModel.NewNavItem.Url" T="string" Label="لینک" Variant="Variant.Outlined" />
<MudButton class="w-full mt-1" Variant="Variant.Outlined" Color="Color.Secondary" OnClick="()=>{ViewModel.SubmitAddNewNavItem();}">افزودن +</MudButton>
<MudDivider class="my-3" />
<MudText class="mb-4" Typo="Typo.h6">افزودن از اطلاعات موجود</MudText>
<MudAutocomplete @bind-value="ViewModel.SelectedBlogCategory"
OnAdornmentClick="@ViewModel.AddFromBlogCategory"
AdornmentIcon="@Icons.Material.Filled.Check"
class="my-2" Required="true" ToStringFunc="dto => dto.Name"
SearchFunc="@ViewModel.SearchBlogCategoryAsync"
T="BlogCategorySDto"
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>
<MudAutocomplete class="my-2" Required="true" ToStringFunc="dto => dto.Name"
@bind-value="ViewModel.SelectedProductCategory"
OnAdornmentClick="@ViewModel.AddFromProductCategory"
AdornmentIcon="@Icons.Material.Filled.Check"
SearchFunc="@ViewModel.SearchProductCategoryAsync"
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>
<MudAutocomplete class="my-2" Required="true" ToStringFunc="dto => dto.Title"
@bind-value="ViewModel.SelectedBlog"
OnAdornmentClick="@ViewModel.AddFromBlog"
AdornmentIcon="@Icons.Material.Filled.Check"
SearchFunc="@ViewModel.SearchBlogAsync"
T="BlogSDto"
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.Title</p>
</ItemTemplate>
</MudAutocomplete>
<MudAutocomplete class="my-2" Required="true" ToStringFunc="dto => dto.PersianName"
@bind-value="ViewModel.SelectedProduct"
OnAdornmentClick="@ViewModel.AddFromProduct"
AdornmentIcon="@Icons.Material.Filled.Check"
SearchFunc="@ViewModel.SearchProductAsync"
T="ProductSDto"
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.PersianName</p>
</ItemTemplate>
</MudAutocomplete>
</MudItem>
<MudItem xs="6">
<MudExpansionPanels>
@foreach (var navMenuItem in ViewModel.NavMenuItems)
{
<MudExpansionPanel>
<TitleContent>
<MudStack Row="true">
<MudText class="my-auto">@navMenuItem.Title</MudText>
<MudSpacer />
<MudIconButton Icon="@Icons.Material.Filled.Delete" OnClick="()=>{ViewModel.RemoveNavItem(navMenuItem.Id);}" Color="Color.Error"></MudIconButton>
</MudStack>
</TitleContent>
<ChildContent>
<MudAutocomplete class="my-2" Required="true" ToStringFunc="dto => dto.Title"
SearchFunc="@ViewModel.SearchNavMenuItem"
@bind-value="navMenuItem.Parent"
OnAdornmentClick="() => { ViewModel.AddNavMenuItemParent(navMenuItem.Id); }"
AdornmentIcon="@Icons.Material.Filled.Check"
T="NavMenuItem"
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.Title</p>
</ItemTemplate>
</MudAutocomplete>
<MudTextField class="my-3" @bind-Value="@navMenuItem.Title" T="string" Label="عنوان" Variant="Variant.Outlined" />
<MudTextField class="my-3" @bind-Value="@navMenuItem.Url" T="string" Label="لینک" Variant="Variant.Outlined" />
</ChildContent>
</MudExpansionPanel>
}
</MudExpansionPanels>
</MudItem>
</MudGrid>
</MudStack>
</MudPaper>
</MudStack>
@code {
public ManageNavMenuPageViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
ViewModel = new ManageNavMenuPageViewModel( NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
await ViewModel.InitializeAsync();
await base.OnInitializedAsync();
}
}

View File

@ -0,0 +1,325 @@
using Force.DeepCloner;
namespace Netina.AdminPanel.PWA.Pages.Personalization;
public class ManageNavMenuPageViewModel : BaseViewModel<NavMenuSetting>
{
private readonly NavigationManager _navigationManager;
private readonly ISnackbar _snackbar;
private readonly IUserUtility _userUtility;
private readonly IDialogService _dialogService;
private readonly IRestWrapper _restWrapper;
public ObservableCollection<NavMenuItem> NavMenuItems { get; set; } = new();
public NavMenuItem NewNavItem { get; set; } = new NavMenuItem();
public ManageNavMenuPageViewModel(
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
{
IsProcessing = true;
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
PageDto = await _restWrapper.SettingRestApi.GetSettingAsync<NavMenuSetting>(nameof(NavMenuSetting), token);
PageDto.NavMenuItems.ForEach(ni =>
{
if (ni.ParentId!=default)
ni.Parent = PageDto.NavMenuItems.FirstOrDefault(np => np.Id == ni.ParentId);
NavMenuItems.Add(ni);
});
}
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 void SubmitAddNewNavItem()
{
try
{
if (NewNavItem.Title.IsNullOrEmpty())
throw new Exception("عنوان فهرست را وارد کنید");
if (NewNavItem.Url.IsNullOrEmpty())
throw new Exception("لینک صفحه فهرست را وارد کنید");
var item = NewNavItem.DeepClone();
NavMenuItems.Add(item);
NewNavItem = new NavMenuItem();
}
catch (Exception ex)
{
_snackbar.Add(ex.Message, Severity.Error);
}
}
public async Task SubmitNavMenuSettingAsync()
{
try
{
var token = await _userUtility.GetBearerTokenAsync();
if (token == null) throw new Exception("Token is null");
PageDto.NavMenuItems.Clear();
foreach (var navMenuItem in NavMenuItems)
{
navMenuItem.Parent = null;
navMenuItem.Children = new List<NavMenuItem>();
PageDto.NavMenuItems.Add(navMenuItem);
}
await _restWrapper.SettingRestApi.PostSettingAsync(nameof(NavMenuSetting), 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);
}
finally
{
IsProcessing = false;
}
}
public ProductSDto? SelectedProduct = null;
public async Task<IEnumerable<ProductSDto>> SearchProductAsync(string product)
{
try
{
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
var response = await _restWrapper.ProductRestApi.ReadAll(0,product,null, token);
var categories = response.Products;
if (product.IsNullOrEmpty())
return categories;
return categories.Where(c => c.PersianName.Contains(product));
}
catch (ApiException ex)
{
var exe = await ex.GetContentAsAsync<ApiResult>();
if (exe != null)
_snackbar.Add(exe.Message, Severity.Error);
_snackbar.Add(ex.Content, Severity.Error);
return new List<ProductSDto>();
}
catch (Exception e)
{
_snackbar.Add(e.Message, Severity.Error);
return new List<ProductSDto>();
}
}
public void AddFromProduct()
{
if (SelectedProduct == null)
return;
NavMenuItems.Add(new NavMenuItem
{
Title = SelectedProduct.PersianName,
Id = Guid.NewGuid(),
Url = $"/products/{SelectedProduct.Id}/{SelectedProduct.Slug}"
});
SelectedProduct = null;
}
public BlogSDto? SelectedBlog = null;
public async Task<IEnumerable<BlogSDto>> SearchBlogAsync(string blog)
{
try
{
var response = await _restWrapper.BlogRestApi.ReadAll(0, blog);
var categories = response.Blogs;
if (blog.IsNullOrEmpty())
return categories;
return categories.Where(c => c.Title.Contains(blog));
}
catch (ApiException ex)
{
var exe = await ex.GetContentAsAsync<ApiResult>();
if (exe != null)
_snackbar.Add(exe.Message, Severity.Error);
_snackbar.Add(ex.Content, Severity.Error);
return new List<BlogSDto>();
}
catch (Exception e)
{
_snackbar.Add(e.Message, Severity.Error);
return new List<BlogSDto>();
}
}
public void AddFromBlog()
{
if (SelectedBlog == null)
return;
NavMenuItems.Add(new NavMenuItem
{
Title = SelectedBlog.Title,
Id = Guid.NewGuid(),
Url = $"/blogs/{SelectedBlog.Id}/{SelectedBlog.Slug}"
});
SelectedBlog = null;
}
public BlogCategorySDto? SelectedBlogCategory = null;
public async Task<IEnumerable<BlogCategorySDto>> SearchBlogCategoryAsync(string blogCategory)
{
try
{
var categories = await _restWrapper.BlogCategoryRestApi.ReadAll(blogCategory);
if (blogCategory.IsNullOrEmpty())
return categories;
return categories.Where(c => c.Name.Contains(blogCategory));
}
catch (ApiException ex)
{
var exe = await ex.GetContentAsAsync<ApiResult>();
if (exe != null)
_snackbar.Add(exe.Message, Severity.Error);
_snackbar.Add(ex.Content, Severity.Error);
return new List<BlogCategorySDto>();
}
catch (Exception e)
{
_snackbar.Add(e.Message, Severity.Error);
return new List<BlogCategorySDto>();
}
}
public void AddFromBlogCategory()
{
if(SelectedBlogCategory==null)
return;
NavMenuItems.Add(new NavMenuItem
{
Title = SelectedBlogCategory.Name,
Id = Guid.NewGuid(),
Url = $"/categories/{SelectedBlogCategory.Id}/{SelectedBlogCategory.Slug}"
});
SelectedBlogCategory = null;
}
public ProductCategorySDto? SelectedProductCategory = null;
public async Task<IEnumerable<ProductCategorySDto>> SearchProductCategoryAsync(string productCategory)
{
try
{
var categories = await _restWrapper.ProductCategoryRestApi.ReadAll(productCategory);
if (productCategory.IsNullOrEmpty())
return categories;
return categories.Where(c => c.Name.Contains(productCategory));
}
catch (ApiException ex)
{
var exe = await ex.GetContentAsAsync<ApiResult>();
if (exe != null)
_snackbar.Add(exe.Message, Severity.Error);
_snackbar.Add(ex.Content, Severity.Error);
return new List<ProductCategorySDto>();
}
catch (Exception e)
{
_snackbar.Add(e.Message, Severity.Error);
return new List<ProductCategorySDto>();
}
}
public void AddFromProductCategory()
{
if (SelectedProductCategory == null)
return;
NavMenuItems.Add(new NavMenuItem
{
Title = SelectedProductCategory.Name,
Id = Guid.NewGuid(),
Url = $"/products/{SelectedProductCategory.Id}/{SelectedProductCategory.Slug}"
});
SelectedBlogCategory = null;
}
public async Task<IEnumerable<NavMenuItem>> SearchNavMenuItem(string navTitle)
{
if (navTitle.IsNullOrEmpty())
return NavMenuItems;
return NavMenuItems.Where(c => c.Title.Trim().ToUpper().Contains(navTitle.Trim().ToUpper()));
}
public NavMenuItem? SelectedParent = null;
public void AddNavMenuItemParent(Guid childId)
{
var child = NavMenuItems.FirstOrDefault(c => c.Id == childId);
if(child == null)
return;
if (child.ParentId != default)
{
var oldParent = NavMenuItems.FirstOrDefault(c => c.Id == child.ParentId);
if (oldParent != null)
oldParent.Children.Remove(child);
}
if (child.Parent == null)
return;
var parentId = child.Parent.Id;
var parent = NavMenuItems.FirstOrDefault(c => c.Id == parentId);
if(parent == null)
return;
child.ParentId = parentId;
parent.Children.Add(child);
SelectedParent = null;
return;
}
public void RemoveNavItem(Guid navItemId)
{
var navItem = NavMenuItems.FirstOrDefault(ni => ni.Id == navItemId);
if (navItem != null)
NavMenuItems.Remove(navItem);
}
}

View File

@ -1,6 +1,4 @@
@page "/products"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,10 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.AdminPanel.PWA.Utilities.Models;
namespace Netina.AdminPanel.PWA.Pages;
namespace Netina.AdminPanel.PWA.Pages;
public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductSDto>>
{

View File

@ -1,6 +1,4 @@
@page "/inventory/shipping"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.AdminPanel.PWA.Utilities.Models;
using Netina.Domain.Entities.Warehouses;
using Netina.Domain.Entities.Warehouses;
namespace Netina.AdminPanel.PWA.Pages;

View File

@ -33,6 +33,7 @@
<MudTextField T="string" @bind-Value="@ViewModel.ShopSetting.Slogan" Variant="Variant.Outlined" Label="شعار فروشگاه"></MudTextField>
</MudItem>
<MudItem xs="12" sm="4">
<MudTextField T="string" @bind-Value="@ViewModel.ShopSetting.Description" Variant="Variant.Outlined" Label="توضیحات"></MudTextField>
</MudItem>
@ -103,7 +104,16 @@
<MudItem xs="12" sm="6">
<MudTextField T="string" @bind-Value="@ViewModel.ShopSetting.ENamad" Variant="Variant.Outlined" Label="آدرس نماد اعتماد"></MudTextField>
</MudItem>
<MudItem xs="12" sm="12">
<MudStack Row="true">
<MudStack>
<MudText Typo="Typo.h4">لوگو وب سایت</MudText>
<MudText Typo="Typo.body1">سایز لوگو شما باید 512 * 512 باشد و به شکل مربع ، تا جایگیری مناسبی داشته باشد</MudText>
<BaseButtonUi Variant="Variant.Outlined" Content="اپلود و تغییر لوگو" OnClickCallback="async () => await ViewModel.SelectFileAsync()" />
</MudStack>
<MudImage Src="@ViewModel.ShopSetting.LogoUrl" Width="150" Height="150" Elevation="25" Class="rounded-lg ma-4" />
</MudStack>
</MudItem>
</MudGrid>
</MudPaper>

View File

@ -1,4 +1,4 @@
using Netina.Domain.MartenEntities.Settings;
using Netina.Domain.Entities.Products;
namespace Netina.AdminPanel.PWA.Pages;
@ -178,4 +178,15 @@ public class ShopManagementPageViewModel : BaseViewModel
}
}
public async Task SelectFileAsync()
{
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
var parameters = new DialogParameters<StorageDialogBox>();
parameters.Add(x => x.FileUploadType , FileUploadType.Logo);
var dialog = await _dialogService.ShowAsync<StorageDialogBox>("انتخاب عکس", parameters, maxWidth);
var result = await dialog.Result;
ShopSetting.LogoUrl = $"{Address.StorageAddress}/Logo/Med/Main.png";
}
}

View File

@ -1,6 +1,4 @@
@page "/setting/users"
@using Netina.AdminPanel.PWA.Utilities
@using Netina.AdminPanel.PWA.Services.RestServices
@attribute [Microsoft.AspNetCore.Authorization.Authorize]
@inject IDialogService DialogService

View File

@ -1,9 +1,4 @@
using Netina.AdminPanel.PWA.Models;
using Netina.AdminPanel.PWA.Models.Api;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Netina.AdminPanel.PWA.Utilities.Models;
using Netina.Domain.Entities.Users;
using Netina.Domain.Entities.Users;
namespace Netina.AdminPanel.PWA.Pages;

View File

@ -4,13 +4,16 @@ using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MudBlazor.Services;
using Netina.AdminPanel.PWA;
using Netina.AdminPanel.PWA.Extensions;
using Netina.AdminPanel.PWA.Services;
using Netina.AdminPanel.PWA.Services.RestServices;
using Netina.AdminPanel.PWA.Utilities;
using Toolbelt.Blazor.Extensions.DependencyInjection;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
Address.WebSiteAddress = builder.Configuration.GetValue<string>($"WebSiteUrl") ?? string.Empty;
Address.StorageAddress = builder.Configuration.GetValue<string>("StorageBaseUrl") ?? string.Empty;
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddCascadingAuthenticationState();

View File

@ -1,6 +1,5 @@
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Services;

View File

@ -7,7 +7,7 @@ public interface IBlogCategoryRestApi
[Get("")]
Task<List<BlogCategorySDto>> ReadAll([Query] int page);
[Get("")]
Task<List<BlogCategorySDto>> ReadAll([Query] int page, [Query] string productName);
Task<List<BlogCategorySDto>> ReadAll([Query] int page, [Query] string categoryName);
[Get("")]
Task<List<BlogCategorySDto>> ReadAll([Query] string blogCategoryName);
Task<List<BlogCategorySDto>> ReadAll([Query] string categoryName);
}

View File

@ -1,6 +1,4 @@
using Netina.Domain.Dtos.ResponseDtos;
namespace Netina.AdminPanel.PWA.Services.RestServices;
namespace Netina.AdminPanel.PWA.Services.RestServices;
public interface IProductRestApi
{

View File

@ -1,6 +1,4 @@
using Netina.AdminPanel.PWA.Models;
namespace Netina.AdminPanel.PWA.Services.RestServices;
namespace Netina.AdminPanel.PWA.Services.RestServices;
public class RestWrapper : IRestWrapper
{

View File

@ -1,7 +1,4 @@
using Netina.AdminPanel.PWA.Extensions;
using Netina.AdminPanel.PWA.Models;
namespace Netina.AdminPanel.PWA.Utilities;
namespace Netina.AdminPanel.PWA.Utilities;
public class UserUtility : IUserUtility
{

View File

@ -1,6 +1,6 @@
{
"version": "0.21.24.41",
"versionNumber": 0.212441,
"version": "0.25.28.49",
"versionNumber": 0.252849,
"versionName": "چرتکه",
"description": "",
"features": [
@ -12,13 +12,17 @@
"افزودن بخش تنظیمات فروشگاه",
"قابلیت افزودن تصویر به برند ها",
"قابلیت افزودن تصویر به دسته بندی محصولات",
"عدم نمایش محصولات غیرقابل نمایش برای مشتری"
"عدم نمایش محصولات غیرقابل نمایش برای مشتری",
"افزودن فاکتور برای فروش ها"
],
"bugFixes": [
"حل مشکلات امنیتی",
"رفع مشکلات رسپانسیو",
"رفع مشکل دریافت تصاویر",
"رفع مشکل عدم اتصال به درگاه",
"رفع مشکل عدم نمایش لیست بلاگ ها",
"رفع مشکل عدم ویرایش تگ ها در محصولات",
"رفع مشکل ادیتور متن در بلاگ و محصولات",
"رفع مشکلات ساختاری در ریسپانس"
]
}

View File

@ -0,0 +1,14 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "None",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.AspNetCore.SignalR": "Debug",
"Microsoft.AspNetCore.Http.Connections": "Debug"
}
},
"WebSiteUrl": "https://vesmeh.com",
"AdminPanelBaseUrl": "https://admin.vesmeh.com",
"StorageBaseUrl": "https://storage.vesmeh.com"
}

View File

@ -0,0 +1,14 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "None",
"Microsoft.Hosting.Lifetime": "Information",
"Microsoft.AspNetCore.SignalR": "Debug",
"Microsoft.AspNetCore.Http.Connections": "Debug"
}
},
"WebSiteUrl": "https://hamyanedalat.com",
"AdminPanelBaseUrl": "https://admin.hamyanedalat.com",
"StorageBaseUrl": "https://storage.hamyanedalat.com"
}

View File

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}

View File

@ -1114,6 +1114,10 @@ input:checked + .toggle-bg {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.my-3 {
margin-top: 0.75rem;
margin-bottom: 0.75rem;
}
.my-4 {
margin-top: 1rem;
margin-bottom: 1rem;

View File

@ -1061,508 +1061,6 @@ input:checked + .toggle-bg {
}
}
.prose {
color: var(--tw-prose-body);
max-width: 65ch;
}
.prose :where(p):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 1.25em;
margin-bottom: 1.25em;
}
.prose :where([class~="lead"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-lead);
font-size: 1.25em;
line-height: 1.6;
margin-top: 1.2em;
margin-bottom: 1.2em;
}
.prose :where(a):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-links);
text-decoration: underline;
font-weight: 500;
}
.prose :where(strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-bold);
font-weight: 600;
}
.prose :where(a strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
}
.prose :where(blockquote strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
}
.prose :where(thead th strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
}
.prose :where(ol):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: decimal;
margin-top: 1.25em;
margin-bottom: 1.25em;
padding-inline-start: 1.625em;
}
.prose :where(ol[type="A"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: upper-alpha;
}
.prose :where(ol[type="a"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: lower-alpha;
}
.prose :where(ol[type="A" s]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: upper-alpha;
}
.prose :where(ol[type="a" s]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: lower-alpha;
}
.prose :where(ol[type="I"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: upper-roman;
}
.prose :where(ol[type="i"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: lower-roman;
}
.prose :where(ol[type="I" s]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: upper-roman;
}
.prose :where(ol[type="i" s]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: lower-roman;
}
.prose :where(ol[type="1"]):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: decimal;
}
.prose :where(ul):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
list-style-type: disc;
margin-top: 1.25em;
margin-bottom: 1.25em;
padding-inline-start: 1.625em;
}
.prose :where(ol > li):not(:where([class~="not-prose"],[class~="not-prose"] *))::marker {
font-weight: 400;
color: var(--tw-prose-counters);
}
.prose :where(ul > li):not(:where([class~="not-prose"],[class~="not-prose"] *))::marker {
color: var(--tw-prose-bullets);
}
.prose :where(dt):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-headings);
font-weight: 600;
margin-top: 1.25em;
}
.prose :where(hr):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
border-color: var(--tw-prose-hr);
border-top-width: 1px;
margin-top: 3em;
margin-bottom: 3em;
}
.prose :where(blockquote):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
font-weight: 500;
font-style: italic;
color: var(--tw-prose-quotes);
border-inline-start-width: 0.25rem;
border-inline-start-color: var(--tw-prose-quote-borders);
quotes: "\201C""\201D""\2018""\2019";
margin-top: 1.6em;
margin-bottom: 1.6em;
padding-inline-start: 1em;
}
.prose :where(blockquote p:first-of-type):not(:where([class~="not-prose"],[class~="not-prose"] *))::before {
content: open-quote;
}
.prose :where(blockquote p:last-of-type):not(:where([class~="not-prose"],[class~="not-prose"] *))::after {
content: close-quote;
}
.prose :where(h1):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-headings);
font-weight: 800;
font-size: 2.25em;
margin-top: 0;
margin-bottom: 0.8888889em;
line-height: 1.1111111;
}
.prose :where(h1 strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
font-weight: 900;
color: inherit;
}
.prose :where(h2):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-headings);
font-weight: 700;
font-size: 1.5em;
margin-top: 2em;
margin-bottom: 1em;
line-height: 1.3333333;
}
.prose :where(h2 strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
font-weight: 800;
color: inherit;
}
.prose :where(h3):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-headings);
font-weight: 600;
font-size: 1.25em;
margin-top: 1.6em;
margin-bottom: 0.6em;
line-height: 1.6;
}
.prose :where(h3 strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
font-weight: 700;
color: inherit;
}
.prose :where(h4):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-headings);
font-weight: 600;
margin-top: 1.5em;
margin-bottom: 0.5em;
line-height: 1.5;
}
.prose :where(h4 strong):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
font-weight: 700;
color: inherit;
}
.prose :where(img):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 2em;
margin-bottom: 2em;
}
.prose :where(picture):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
display: block;
margin-top: 2em;
margin-bottom: 2em;
}
.prose :where(video):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 2em;
margin-bottom: 2em;
}
.prose :where(kbd):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
font-weight: 500;
font-family: inherit;
color: var(--tw-prose-kbd);
box-shadow: 0 0 0 1px rgb(var(--tw-prose-kbd-shadows) / 10%), 0 3px 0 rgb(var(--tw-prose-kbd-shadows) / 10%);
font-size: 0.875em;
border-radius: 0.3125rem;
padding-top: 0.1875em;
padding-inline-end: 0.375em;
padding-bottom: 0.1875em;
padding-inline-start: 0.375em;
}
.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-code);
font-weight: 600;
font-size: 0.875em;
}
.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::before {
content: "`";
}
.prose :where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::after {
content: "`";
}
.prose :where(a code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
}
.prose :where(h1 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
}
.prose :where(h2 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
font-size: 0.875em;
}
.prose :where(h3 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
font-size: 0.9em;
}
.prose :where(h4 code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
}
.prose :where(blockquote code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
}
.prose :where(thead th code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: inherit;
}
.prose :where(pre):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-pre-code);
background-color: var(--tw-prose-pre-bg);
overflow-x: auto;
font-weight: 400;
font-size: 0.875em;
line-height: 1.7142857;
margin-top: 1.7142857em;
margin-bottom: 1.7142857em;
border-radius: 0.375rem;
padding-top: 0.8571429em;
padding-inline-end: 1.1428571em;
padding-bottom: 0.8571429em;
padding-inline-start: 1.1428571em;
}
.prose :where(pre code):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
background-color: transparent;
border-width: 0;
border-radius: 0;
padding: 0;
font-weight: inherit;
color: inherit;
font-size: inherit;
font-family: inherit;
line-height: inherit;
}
.prose :where(pre code):not(:where([class~="not-prose"],[class~="not-prose"] *))::before {
content: none;
}
.prose :where(pre code):not(:where([class~="not-prose"],[class~="not-prose"] *))::after {
content: none;
}
.prose :where(table):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
width: 100%;
table-layout: auto;
text-align: start;
margin-top: 2em;
margin-bottom: 2em;
font-size: 0.875em;
line-height: 1.7142857;
}
.prose :where(thead):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
border-bottom-width: 1px;
border-bottom-color: var(--tw-prose-th-borders);
}
.prose :where(thead th):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-headings);
font-weight: 600;
vertical-align: bottom;
padding-inline-end: 0.5714286em;
padding-bottom: 0.5714286em;
padding-inline-start: 0.5714286em;
}
.prose :where(tbody tr):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
border-bottom-width: 1px;
border-bottom-color: var(--tw-prose-td-borders);
}
.prose :where(tbody tr:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
border-bottom-width: 0;
}
.prose :where(tbody td):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
vertical-align: baseline;
}
.prose :where(tfoot):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
border-top-width: 1px;
border-top-color: var(--tw-prose-th-borders);
}
.prose :where(tfoot td):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
vertical-align: top;
}
.prose :where(figure > *):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0;
margin-bottom: 0;
}
.prose :where(figcaption):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
color: var(--tw-prose-captions);
font-size: 0.875em;
line-height: 1.4285714;
margin-top: 0.8571429em;
}
.prose {
--tw-prose-body: #374151;
--tw-prose-headings: #111827;
--tw-prose-lead: #4b5563;
--tw-prose-links: #111827;
--tw-prose-bold: #111827;
--tw-prose-counters: #6b7280;
--tw-prose-bullets: #d1d5db;
--tw-prose-hr: #e5e7eb;
--tw-prose-quotes: #111827;
--tw-prose-quote-borders: #e5e7eb;
--tw-prose-captions: #6b7280;
--tw-prose-kbd: #111827;
--tw-prose-kbd-shadows: 17 24 39;
--tw-prose-code: #111827;
--tw-prose-pre-code: #e5e7eb;
--tw-prose-pre-bg: #1f2937;
--tw-prose-th-borders: #d1d5db;
--tw-prose-td-borders: #e5e7eb;
--tw-prose-invert-body: #d1d5db;
--tw-prose-invert-headings: #fff;
--tw-prose-invert-lead: #9ca3af;
--tw-prose-invert-links: #fff;
--tw-prose-invert-bold: #fff;
--tw-prose-invert-counters: #9ca3af;
--tw-prose-invert-bullets: #4b5563;
--tw-prose-invert-hr: #374151;
--tw-prose-invert-quotes: #f3f4f6;
--tw-prose-invert-quote-borders: #374151;
--tw-prose-invert-captions: #9ca3af;
--tw-prose-invert-kbd: #fff;
--tw-prose-invert-kbd-shadows: 255 255 255;
--tw-prose-invert-code: #fff;
--tw-prose-invert-pre-code: #d1d5db;
--tw-prose-invert-pre-bg: rgb(0 0 0 / 50%);
--tw-prose-invert-th-borders: #4b5563;
--tw-prose-invert-td-borders: #374151;
font-size: 1rem;
line-height: 1.75;
}
.prose :where(picture > img):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0;
margin-bottom: 0;
}
.prose :where(li):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.prose :where(ol > li):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
padding-inline-start: 0.375em;
}
.prose :where(ul > li):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
padding-inline-start: 0.375em;
}
.prose :where(.prose > ul > li p):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0.75em;
margin-bottom: 0.75em;
}
.prose :where(.prose > ul > li > *:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 1.25em;
}
.prose :where(.prose > ul > li > *:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-bottom: 1.25em;
}
.prose :where(.prose > ol > li > *:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 1.25em;
}
.prose :where(.prose > ol > li > *:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-bottom: 1.25em;
}
.prose :where(ul ul, ul ol, ol ul, ol ol):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0.75em;
margin-bottom: 0.75em;
}
.prose :where(dl):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 1.25em;
margin-bottom: 1.25em;
}
.prose :where(dd):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0.5em;
padding-inline-start: 1.625em;
}
.prose :where(hr + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0;
}
.prose :where(h2 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0;
}
.prose :where(h3 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0;
}
.prose :where(h4 + *):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0;
}
.prose :where(thead th:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
padding-inline-start: 0;
}
.prose :where(thead th:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
padding-inline-end: 0;
}
.prose :where(tbody td, tfoot td):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
padding-top: 0.5714286em;
padding-inline-end: 0.5714286em;
padding-bottom: 0.5714286em;
padding-inline-start: 0.5714286em;
}
.prose :where(tbody td:first-child, tfoot td:first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
padding-inline-start: 0;
}
.prose :where(tbody td:last-child, tfoot td:last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
padding-inline-end: 0;
}
.prose :where(figure):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 2em;
margin-bottom: 2em;
}
.prose :where(.prose > :first-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-top: 0;
}
.prose :where(.prose > :last-child):not(:where([class~="not-prose"],[class~="not-prose"] *)) {
margin-bottom: 0;
}
.visible {
visibility: visible;
}
@ -1702,6 +1200,11 @@ input:checked + .toggle-bg {
margin-bottom: 0.5rem;
}
.my-3 {
margin-top: 0.75rem;
margin-bottom: 0.75rem;
}
.my-4 {
margin-top: 1rem;
margin-bottom: 1rem;
@ -1871,6 +1374,10 @@ input:checked + .toggle-bg {
height: 3rem;
}
.h-14 {
height: 3.5rem;
}
.h-24 {
height: 6rem;
}
@ -1932,10 +1439,6 @@ input:checked + .toggle-bg {
height: 100vh;
}
.h-14 {
height: 3.5rem;
}
.\!max-h-\[80vh\] {
max-height: 80vh !important;
}
@ -1952,6 +1455,27 @@ input:checked + .toggle-bg {
max-height: 50rem;
}
.\!max-h-\[75vh\] {
max-height: 75vh !important;
}
.\!max-h-\[70vh\] {
max-height: 70vh !important;
}
.\!max-h-full {
max-height: 100% !important;
}
.\!max-h-\[70\%\] {
max-height: 70% !important;
}
.\!max-h-max {
max-height: -moz-max-content !important;
max-height: max-content !important;
}
.min-h-\[33rem\] {
min-height: 33rem;
}
@ -1972,6 +1496,10 @@ input:checked + .toggle-bg {
width: 3rem;
}
.w-14 {
width: 3.5rem;
}
.w-24 {
width: 6rem;
}
@ -2021,10 +1549,6 @@ input:checked + .toggle-bg {
width: 100vw;
}
.w-14 {
width: 3.5rem;
}
.flex-1 {
flex: 1 1 0%;
}