feat : products , ordering system , discount

add discount page and CRUD , complete products CRUD , improve ordering system
release
Amir Hossein Khademi 2024-02-09 19:43:20 +03:30
parent c3d4c265ce
commit e081a39682
36 changed files with 2598 additions and 346 deletions

View File

@ -0,0 +1,58 @@
@inject IJSRuntime JsRuntime
<div class="editor"></div>
<script type="text/javascript">
function destroyEditor(){
window.editor?.destroy()
}
function lunchEditor(data) {
ClassicEditor.create(document.querySelector('.editor'), {
// Editor configuration.
})
.then(editor => {
window.editor = editor;
window.editor.setData(data);
editor.on('change', function () {
console.log(editor.getData());
});
})
.catch(handleSampleError);
}
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>
@code {
[Parameter]
public string Text { get; set; } = string.Empty;
[Parameter]
public EventCallback<string> TextChanged { get; set; }
protected override Task OnParametersSetAsync()
{
return base.OnParametersSetAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
await JsRuntime.InvokeVoidAsync("window.lunchEditor", Text);
await base.OnAfterRenderAsync(firstRender);
}
}

View File

@ -37,8 +37,8 @@
<MudNavLink Href="discounts"
Icon="@Icons.Material.Outlined.LocalOffer">تخفیفـــ ها</MudNavLink>
<MudNavLink Href="accounting"
Icon="@Icons.Material.Outlined.AccountBalance">گزارشاتـــ</MudNavLink>
<MudNavLink Href="payments"
Icon="@Icons.Material.Outlined.AccountBalance">پرداختـــ ها</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="باشگاه مشتریانـــ" Expanded="false"
@ -58,6 +58,14 @@
<MudNavLink Href="blog/categories"
Icon="@Icons.Material.Outlined.WebAsset">دسته بندی های بلاگـــ</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="تنظیماتـــ" Expanded="false"
Icon="@Icons.Material.Outlined.Settings">
<MudNavLink Href="users" Icon="@Icons.Material.Filled.ManageAccounts">نقش ها و کاربران</MudNavLink>
</MudNavGroup>
</MudNavMenu>
</MudStack>

View File

@ -12,7 +12,11 @@ public class BlogActionDialogBoxViewModel : BaseViewModel
private readonly IDialogService _dialogService;
private readonly MudDialogInstance _mudDialog;
public BlogActionDialogBoxViewModel(ISnackbar snackbar, IRestWrapper restWrapper, IUserUtility userUtility, IDialogService dialogService, MudDialogInstance mudDialog)
public BlogActionDialogBoxViewModel(ISnackbar snackbar,
IRestWrapper restWrapper,
IUserUtility userUtility,
IDialogService dialogService,
MudDialogInstance mudDialog)
{
_snackbar = snackbar;
_restWrapper = restWrapper;
@ -20,6 +24,7 @@ public class BlogActionDialogBoxViewModel : BaseViewModel
_dialogService = dialogService;
_mudDialog = mudDialog;
}
public BlogActionDialogBoxViewModel(ISnackbar snackbar,
IRestWrapper restWrapper,
IUserUtility userUtility,

View File

@ -79,6 +79,9 @@
<MudItem lg="4" md="6">
<MudTextField @bind-Value="@ViewModel.PageDto.PackingCost" T="double" Label="مبلغ بسته بندی" Adornment="Adornment.End" AdornmentText="ریالــ" Variant="Variant.Outlined" />
</MudItem>
<MudItem lg="4" md="6">
<MudTextField @bind-Value="@ViewModel.PageDto.Stock" T="int" Label="موجودی انبار" Variant="Variant.Outlined" />
</MudItem>
<MudItem lg="4" md="6">
<MudTextField @bind-Value="@ViewModel.PageDto.MaxOrderCount" T="int" Label="بیشترین خرید" Variant="Variant.Outlined" />
</MudItem>
@ -168,33 +171,48 @@
</MudStack>
<MudGrid>
<MudItem sm="12">
<RadzenHtmlEditor @bind-Value="@ViewModel.PageDto.ExpertCheck" class="min-h-[28rem]">
<RadzenHtmlEditorUndo />
<RadzenHtmlEditorRedo />
<RadzenHtmlEditorSeparator />
<RadzenHtmlEditorFormatBlock />
<RadzenHtmlEditorSeparator />
<RadzenHtmlEditorAlignLeft />
<RadzenHtmlEditorAlignCenter />
<RadzenHtmlEditorAlignRight />
<RadzenHtmlEditorJustify />
<RadzenHtmlEditorSeparator />
<RadzenHtmlEditorSource />
<RadzenHtmlEditorBold />
<RadzenHtmlEditorItalic />
<RadzenHtmlEditorUnderline />
<RadzenHtmlEditorStrikeThrough />
<RadzenHtmlEditorRemoveFormat />
<RadzenHtmlEditorSeparator />
</RadzenHtmlEditor>
<RichTextEditorUi @bind-Text="@ViewModel.PageDto.ExpertCheck" />
</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">
@ -310,6 +328,7 @@
</MudStack>
</DialogActions>
</MudDialog>
@code {
[CascadingParameter]
MudDialogInstance MudDialog { get; set; }

View File

@ -91,6 +91,7 @@ public class ProductActionDialogBoxViewModel : BaseViewModel<ProductLDto>
PageDto.PackingCost = productLDto.PackingCost;
PageDto.MaxOrderCount = productLDto.MaxOrderCount;
PageDto.Warranty = productLDto.Warranty;
PageDto.Stock = productLDto.Stock;
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

@ -54,29 +54,7 @@
<MudText Typo="Typo.h6">توضیحات تکمیلی</MudText>
<MudText Typo="Typo.caption">می توانید توضیحاتــ تکمیلی محصول را کامل وارد کنید</MudText>
</MudStack>
<RadzenHtmlEditor @bind-Value="@ViewModel.Description" class="min-h-[10rem]">
<RadzenHtmlEditorUndo/>
<RadzenHtmlEditorRedo/>
<RadzenHtmlEditorSeparator />
<RadzenHtmlEditorFormatBlock/>
<RadzenHtmlEditorSeparator />
<RadzenHtmlEditorAlignLeft/>
<RadzenHtmlEditorAlignCenter/>
<RadzenHtmlEditorAlignRight/>
<RadzenHtmlEditorJustify/>
<RadzenHtmlEditorSeparator/>
<RadzenHtmlEditorSource />
<RadzenHtmlEditorBold/>
<RadzenHtmlEditorItalic/>
<RadzenHtmlEditorUnderline/>
<RadzenHtmlEditorStrikeThrough />
<RadzenHtmlEditorRemoveFormat />
<RadzenHtmlEditorSeparator/>
</RadzenHtmlEditor>
<RichTextEditorUi @bind-Text="@ViewModel.Description" />
</MudItem>
</MudGrid>

View File

@ -57,7 +57,7 @@ public class ProductCategoryActionDialogBoxViewModel:BaseViewModel
var token = await _userUtility.GetBearerTokenAsync();
var request = new CreateProductCategoryCommand(Name, Description, IsMain, SelectedCategory?.Id ?? default, new List<StorageFileSDto>());
await _restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Create<CreateProductCategoryCommand>(request, token);
_mudDialog.Close();
_mudDialog.Close(DialogResult.Ok(true));
}
catch (ApiException ex)
{
@ -92,7 +92,7 @@ public class ProductCategoryActionDialogBoxViewModel:BaseViewModel
var token = await _userUtility.GetBearerTokenAsync();
var request = new UpdateProductCategoryCommand(Category.Id, Name, Description, IsMain, SelectedCategory?.Id ?? default, new List<StorageFileSDto>());
await _restWrapper.CrudApiRest<ProductCategory, Guid>(Address.ProductCategoryController).Update<UpdateProductCategoryCommand>(request, token);
_mudDialog.Close();
_mudDialog.Close(DialogResult.Ok(true));
}
catch (ApiException ex)
{

View File

@ -0,0 +1,93 @@
@using NetinaShop.Domain.Entities.Users
@inject ISnackbar Snackbar
@inject IRestWrapper RestWrapper
@inject IUserUtility UserUtility
@inject IDialogService DialogService
<MudDialog DisableSidePadding="true" class="mx-auto">
<DialogContent>
<MudContainer class="max-h-[30rem]" Style="overflow-y: scroll">
<MudStack>
<MudDivider class="-mt-3" />
<MudStack Spacing="0">
<MudText Typo="Typo.h6"><b>اطلاعات کلی</b></MudText>
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی را به دقت وارد کنید</MudText>
</MudStack>
<MudGrid>
<MudItem sm="12" md="6">
<MudTextField T="string" Label="نام فارسی نفش" @bind-Value="@ViewModel.PageDto.PersianName" Variant="Variant.Outlined"></MudTextField>
</MudItem>
<MudItem sm="12" md="6">
<MudTextField T="string" Label="نام انگلیسی نقش" @bind-Value="@ViewModel.PageDto.EnglishName" Variant="Variant.Outlined"></MudTextField>
</MudItem>
<MudItem sm="12">
<MudTextField T="string" Label="توضیحاتــــ" @bind-Value="@ViewModel.PageDto.Description" Variant="Variant.Outlined"></MudTextField>
</MudItem>
<MudItem sm="12">
<MudStack Spacing="0">
<MudText Typo="Typo.h6"><b>سطح دسترسی ها</b></MudText>
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی را به دقت وارد کنید</MudText>
</MudStack>
</MudItem>
@foreach (var item in ViewModel.RoleClaims)
{
<MudItem sm="6" md="4">
<MudStack Spacing="0">
<MudSwitch @bind-Value="@item.IsSelected" Label="@item.Title" Color="Color.Info" />
</MudStack>
</MudItem>
}
</MudGrid>
</MudStack>
</MudContainer>
</DialogContent>
<DialogActions>
<MudStack Row="true" class="w-full mx-4 mb-2">
@if (ViewModel.IsEditing)
{
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
Icon="@Icons.Material.Outlined.Check"
Variant="Variant.Filled" Color="Color.Success"
Content="ثبت ویرایش" OnClickCallback="@ViewModel.SubmitEditAsync" />
}
else
{
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
Icon="@Icons.Material.Outlined.Check"
Variant="Variant.Filled" Color="Color.Success"
Content="تایید" OnClickCallback="@ViewModel.SubmitCreateAsync" />
}
<MudSpacer />
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="@ViewModel.Cancel">بستن</MudButton>
</MudStack>
</DialogActions>
</MudDialog>
@code {
[CascadingParameter]
MudDialogInstance MudDialog { get; set; }
[Parameter]
public ApplicationRole? Role { get; set; }
public RoleActionDialogBoxViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
if (Role == null)
ViewModel = new RoleActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
else
ViewModel = new RoleActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, Role);
await ViewModel.InitializeAsync();
await base.OnInitializedAsync();
}
}

View File

@ -0,0 +1,188 @@
using NetinaShop.Domain.Entities.Blogs;
using NetinaShop.Domain.Entities.Users;
using System.Reflection.Metadata;
using NetinaShop.Domain.Models.Claims;
namespace NetinaShop.AdminPanel.PWA.Dialogs;
public class RoleActionDialogBoxViewModel : BaseViewModel<RoleActionRequestDto>
{
private readonly ISnackbar _snackbar;
private readonly IRestWrapper _restWrapper;
private readonly IUserUtility _userUtility;
private readonly IDialogService _dialogService;
private readonly MudDialogInstance _mudDialog;
public RoleActionDialogBoxViewModel(ISnackbar snackbar,
IRestWrapper restWrapper,
IUserUtility userUtility,
IDialogService dialogService,
MudDialogInstance mudDialog)
{
_snackbar = snackbar;
_restWrapper = restWrapper;
_userUtility = userUtility;
_dialogService = dialogService;
_mudDialog = mudDialog;
ApplicationClaims.AllClaimDtos.ForEach(c => RoleClaims.Add(c));
}
public RoleActionDialogBoxViewModel(ISnackbar snackbar,
IRestWrapper restWrapper,
IUserUtility userUtility,
IDialogService dialogService,
MudDialogInstance mudDialog,
ApplicationRole role)
{
_snackbar = snackbar;
_restWrapper = restWrapper;
_userUtility = userUtility;
_dialogService = dialogService;
_mudDialog = mudDialog;
PageDto.RoleId = role.Id;
IsEditing = true;
ApplicationClaims.AllClaimDtos.ForEach(c=>RoleClaims.Add(c));
foreach (var roleClaim in RoleClaims)
{
roleClaim.IsSelected = false;
}
}
public bool IsEditing = false;
public ObservableCollection<ClaimDto> RoleClaims { get; } = new ObservableCollection<ClaimDto>();
public override async Task InitializeAsync()
{
if (IsEditing && PageDto.RoleId != default)
{
try
{
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
IsProcessing = true;
var role = await _restWrapper.RoleRestApi.ReadOne(PageDto.RoleId, token);
PageDto = role;
foreach (var permission in PageDto.Permissions)
{
var selected = RoleClaims.FirstOrDefault(f => f.Value == permission);
if (selected != null)
selected.IsSelected = true;
}
}
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 void Cancel() => _mudDialog.Cancel();
public async Task SubmitEditAsync()
{
try
{
IsProcessing = true;
if (PageDto.RoleId == default)
throw new Exception("نقش اشتباه است");
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
if (PageDto.PersianName.IsNullOrEmpty())
throw new Exception("نام فارسی نقش را وارد کنید");
if (PageDto.EnglishName.IsNullOrEmpty())
throw new Exception("نام انگلیسی نقش را وارد کنید");
PageDto.Permissions.Clear();
foreach (var claimDto in RoleClaims.Where(r => r.IsSelected))
PageDto.Permissions.Add(claimDto.Value);
await _restWrapper.RoleRestApi.UpdateRoleAsync(PageDto, token);
_snackbar.Add($"ویرایش بلاگ {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
_mudDialog.Close(DialogResult.Ok(true));
}
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 SubmitCreateAsync()
{
try
{
IsProcessing = true;
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
if (PageDto.PersianName.IsNullOrEmpty())
throw new Exception("نام فارسی نقش را وارد کنید");
if (PageDto.EnglishName.IsNullOrEmpty())
throw new Exception("نام انگلیسی نقش را وارد کنید");
PageDto.Permissions.Clear();
foreach (var claimDto in RoleClaims.Where(r=>r.IsSelected))
PageDto.Permissions.Add(claimDto.Value);
await _restWrapper.RoleRestApi.CreateRoleAsync(PageDto, token);
_snackbar.Add($"ساخت بلاگ {PageDto.PersianName} با موفقیت انجام شد", Severity.Success);
_mudDialog.Close(DialogResult.Ok(true));
}
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;
}
}
}

View File

@ -0,0 +1,108 @@
@using NetinaShop.Domain.Entities.Users
@inject ISnackbar Snackbar
@inject IRestWrapper RestWrapper
@inject IUserUtility UserUtility
@inject IDialogService DialogService
<MudDialog DisableSidePadding="true" class="mx-auto">
<DialogContent>
<MudContainer class="max-h-[30rem]" Style="overflow-y: scroll">
<MudStack>
<MudDivider class="-mt-3" />
<MudStack Spacing="0">
<MudText Typo="Typo.h6"><b>اطلاعات کلی</b></MudText>
<MudText Typo="Typo.caption">اطلاعات کلی دسته بندی را به دقت وارد کنید</MudText>
</MudStack>
<MudGrid>
<MudItem sm="12" md="6">
<MudTextField T="string" Label="نام" @bind-Value="@ViewModel.PageDto.FirstName" Variant="Variant.Outlined"></MudTextField>
</MudItem>
<MudItem sm="12" md="6">
<MudTextField T="string" Label="نام خانوادگی" @bind-Value="@ViewModel.PageDto.LastName" Variant="Variant.Outlined"></MudTextField>
</MudItem>
<MudItem sm="12" md="6">
<MudTextField T="string" Label="شماره تلفن" @bind-Value="@ViewModel.PageDto.PhoneNumber" Variant="Variant.Outlined"></MudTextField>
</MudItem>
<MudItem sm="12" md="6">
<MudAutocomplete Required="true" ToStringFunc="dto => dto.PersianName" @bind-Value="@ViewModel.SelectedRole"
SearchFunc="ViewModel.SearchRole"
T="ApplicationRole"
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 sm="12" md="6">
<MudTextField T="string" Label="کد ملی" @bind-Value="@ViewModel.PageDto.NationalId" Variant="Variant.Outlined"></MudTextField>
</MudItem>
<MudItem sm="12" md="6">
<MudSelect T="Gender" @bind-Value="@ViewModel.PageDto.Gender" Label="جنستــــ" ToStringFunc="b=>b.ToDisplay()" Variant="Variant.Outlined" AnchorOrigin="Origin.BottomCenter">
<MudSelectItem T="Gender" Value="Gender.Male" />
<MudSelectItem T="Gender" Value="Gender.Female" />
</MudSelect>
</MudItem>
</MudGrid>
</MudStack>
</MudContainer>
</DialogContent>
<DialogActions>
<MudStack Row="true" class="w-full mx-4 mb-2">
@if (ViewModel.IsEditing)
{
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
Icon="@Icons.Material.Outlined.Check"
Variant="Variant.Filled" Color="Color.Success"
Content="ثبت ویرایش" OnClickCallback="@ViewModel.SubmitEditAsync" />
}
else
{
<BaseButtonUi class="w-64 rounded-md" IsProcessing="@ViewModel.IsProcessing"
Icon="@Icons.Material.Outlined.Check"
Variant="Variant.Filled" Color="Color.Success"
Content="تایید" OnClickCallback="@ViewModel.SubmitCreateAsync" />
}
<MudSpacer />
<MudButton Variant="Variant.Outlined" Size="Size.Large" Color="Color.Error" OnClick="@ViewModel.Cancel">بستن</MudButton>
</MudStack>
</DialogActions>
</MudDialog>
@code {
[CascadingParameter]
MudDialogInstance MudDialog { get; set; }
[Parameter]
public ApplicationUserSDto? User { get; set; }
public UserActionDialogBoxViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
if (User == null)
ViewModel = new UserActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog);
else
ViewModel = new UserActionDialogBoxViewModel(Snackbar, RestWrapper, UserUtility, DialogService, MudDialog, User);
await ViewModel.InitializeAsync();
await base.OnInitializedAsync();
}
}

View File

@ -0,0 +1,229 @@
using Mapster;
using NetinaShop.Domain.Entities.Users;
using NetinaShop.Domain.Models.Claims;
namespace NetinaShop.AdminPanel.PWA.Dialogs;
public class UserActionDialogBoxViewModel : BaseViewModel<UserActionRequestDto>
{
private readonly ISnackbar _snackbar;
private readonly IRestWrapper _restWrapper;
private readonly IUserUtility _userUtility;
private readonly IDialogService _dialogService;
private readonly MudDialogInstance _mudDialog;
public UserActionDialogBoxViewModel(ISnackbar snackbar,
IRestWrapper restWrapper,
IUserUtility userUtility,
IDialogService dialogService,
MudDialogInstance mudDialog)
{
_snackbar = snackbar;
_restWrapper = restWrapper;
_userUtility = userUtility;
_dialogService = dialogService;
_mudDialog = mudDialog;
}
public UserActionDialogBoxViewModel(ISnackbar snackbar,
IRestWrapper restWrapper,
IUserUtility userUtility,
IDialogService dialogService,
MudDialogInstance mudDialog,
ApplicationUserSDto user)
{
_snackbar = snackbar;
_restWrapper = restWrapper;
_userUtility = userUtility;
_dialogService = dialogService;
_mudDialog = mudDialog;
PageDto.UserId = user.Id;
IsEditing = true;
}
public bool IsEditing = false;
public override async Task InitializeAsync()
{
if (IsEditing && PageDto.UserId != default)
{
try
{
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
IsProcessing = true;
var user = await _restWrapper.UserRestApi.ReadOne(PageDto.UserId, token);
PageDto = user.Adapt<UserActionRequestDto>();
PageDto.UserId = user.Id;
if (PageDto.RoleIds.Count > 0)
{
var role = await _restWrapper.RoleRestApi.ReadOne(PageDto.RoleIds.FirstOrDefault(), token);
if (role != null)
SelectedRole = new ApplicationRole
{
Id = role.RoleId,
Name = role.EnglishName,
PersianName = role.PersianName
};
}
}
catch (ApiException ex)
{
var exe = await ex.GetContentAsAsync<ApiResult>();
if (exe != null)
_snackbar.Add(exe.Message, Severity.Error);
_snackbar.Add(ex.Content, Severity.Error);
}
catch (Exception e)
{
_snackbar.Add(e.Message, Severity.Error);
}
finally
{
IsProcessing = false;
}
};
}
private List<ApplicationRole> _roles = new List<ApplicationRole>();
public ApplicationRole? SelectedRole;
public async Task<IEnumerable<ApplicationRole>> SearchRole(string roleName)
{
try
{
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
if (roleName.IsNullOrEmpty())
_roles = await _restWrapper.RoleRestApi.ReadAll(0, token);
else
_roles = await _restWrapper.RoleRestApi.ReadAll(roleName, token);
return _roles;
}
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 _roles;
}
catch (Exception e)
{
_snackbar.Add(e.Message, Severity.Error);
return _roles;
}
}
public void Cancel() => _mudDialog.Cancel();
public async Task SubmitEditAsync()
{
try
{
IsProcessing = true;
if (PageDto.UserId == default)
throw new Exception("Id is null !");
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
if (PageDto.FirstName.IsNullOrEmpty())
throw new Exception("نام را وارد کنید");
if (PageDto.LastName.IsNullOrEmpty())
throw new Exception("نام خانوادگی را وارد کنید");
if (PageDto.PhoneNumber.IsNullOrEmpty())
throw new Exception("شماره تلفن را وارد کنید");
if (SelectedRole == null)
throw new Exception("نقش را انتخاب کنید");
PageDto.RoleIds.Clear();
PageDto.RoleIds.Add(SelectedRole.Id);
await _restWrapper.UserRestApi.UpdateUserAsync(PageDto, token);
_snackbar.Add($"ویرایش {PageDto.FirstName + " " + PageDto.LastName} با موفقیت انجام شد", Severity.Success);
_mudDialog.Close(DialogResult.Ok(true));
}
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 SubmitCreateAsync()
{
try
{
IsProcessing = true;
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
if (PageDto.FirstName.IsNullOrEmpty())
throw new Exception("نام را وارد کنید");
if (PageDto.LastName.IsNullOrEmpty())
throw new Exception("نام خانوادگی را وارد کنید");
if (PageDto.PhoneNumber.IsNullOrEmpty())
throw new Exception("شماره تلفن را وارد کنید");
if (SelectedRole == null)
throw new Exception("نقش را انتخاب کنید");
PageDto.RoleIds.Clear();
PageDto.RoleIds.Add(SelectedRole.Id);
await _restWrapper.UserRestApi.CreateUserAsync(PageDto, token);
_snackbar.Add($"ساخت کاربر {PageDto.FirstName + " "+ PageDto.LastName} با موفقیت انجام شد", Severity.Success);
_mudDialog.Close(DialogResult.Ok(true));
}
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;
}
}
}

View File

@ -68,13 +68,13 @@
<div>
@Body
<div dir="ltr">
<PWAUpdater Text="@_updateText" ButtonCaption="اپدیت کنید"/>
</div>
</div>
</MudItem>
</MudGrid>
</MudLayout>
<div dir="ltr">
<PWAUpdater StateChanged="Callback" Text="@_updateText" ButtonCaption="اپدیت کنید"/>
</div>
</MudRTLProvider>
</Authorized>
@ -121,4 +121,8 @@
await base.OnInitializedAsync();
}
private void Callback(PWAUpdater.States obj)
{
}
}

View File

@ -17,4 +17,5 @@ public static class Address
public static string BlogController => $"{BaseAddress}/blog";
public static string BlogCategoryController => $"{BaseAddress}/blog/category";
public static string DiscountController => $"{BaseAddress}/discount";
public static string RoleController => $"{BaseAddress}/user/role";
}

View File

@ -5,8 +5,8 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
<AssemblyVersion>0.2.2.11</AssemblyVersion>
<FileVersion>0.2.2.11</FileVersion>
<AssemblyVersion>0.2.5.11</AssemblyVersion>
<FileVersion>0.2.5.11</FileVersion>
</PropertyGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">

View File

@ -1,4 +1,5 @@
using System.Collections.ObjectModel;
using MudBlazor;
using NetinaShop.Common.Models.Exception;
namespace NetinaShop.AdminPanel.PWA.Pages;
@ -29,6 +30,7 @@ public class CategoriesPageViewModel : BaseViewModel<ObservableCollection<Produc
try
{
IsProcessing = true;
CurrentPage = 0;
PageDto.Clear();
var dto = await _restWrapper.CrudDtoApiRest<ProductCategory, ProductCategorySDto, Guid>(Address.ProductCategoryController)
.ReadAll(CurrentPage);
@ -89,7 +91,12 @@ public class CategoriesPageViewModel : BaseViewModel<ObservableCollection<Produc
public async Task AddProductCategoryClicked()
{
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
await _dialogService.ShowAsync<ProductCategoryActionDialogBox>("افزودن دسته جدید", maxWidth);
var dialogResult = await _dialogService.ShowAsync<ProductCategoryActionDialogBox>("افزودن دسته جدید", maxWidth);
var result = await dialogResult.Result;
if (!result.Canceled && result.Data is bool and true)
{
await InitializeAsync();
}
}
public async Task EditProductCategoryClicked(ProductCategorySDto category)
@ -97,7 +104,12 @@ public class CategoriesPageViewModel : BaseViewModel<ObservableCollection<Produc
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
var parameters = new DialogParameters<ProductCategoryActionDialogBox>();
parameters.Add(x=>x.Category,category);
await _dialogService.ShowAsync<ProductCategoryActionDialogBox>($"ویرایش دسته {category.Name}", parameters, maxWidth);
var dialogResult = await _dialogService.ShowAsync<ProductCategoryActionDialogBox>($"ویرایش دسته {category.Name}", parameters, maxWidth);
var result = await dialogResult.Result;
if (!result.Canceled && result.Data is bool and true)
{
await InitializeAsync();
}
}
public async Task DeleteProductCategoryAsync(Guid selectedCategoryId)
@ -118,6 +130,7 @@ public class CategoriesPageViewModel : BaseViewModel<ObservableCollection<Produc
await _restWrapper.CrudDtoApiRest<ProductCategory, ProductCategorySDto, Guid>(Address.ProductCategoryController)
.Delete(selectedCategoryId, token);
_snackbar.Add("حذف دسته بندی با موفقیت انجام شد", Severity.Success);
await InitializeAsync();
}
catch (ApiException ex)

View File

@ -90,7 +90,7 @@
<Columns>
<PropertyColumn Title="نام محصول" Property="arg => arg.PersianName" />
<PropertyColumn Title="دسته بندی" Property="arg => arg.CategoryName" />
<PropertyColumn Title="برند" Property="arg => arg.BrandNames" />
<PropertyColumn Title="برند" Property="arg => arg.BrandName" />
<PropertyColumn Title="قیمتــ" Property="arg => arg.Cost" />
<TemplateColumn CellClass="d-flex justify-end">
<CellTemplate>

View File

@ -0,0 +1,102 @@
@page "/orders"
@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 sm="6" lg="3">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">سفارشات امروز</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-amber-600"><b>1124</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
<MudItem sm="6" lg="3">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">سفارشات در انتظار تایید</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-blue-600"><b>845</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
<MudItem sm="6" lg="3">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">تغییر نسبت هفته پیش</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-lime-600"><b>125</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
<MudItem sm="6" lg="3">
<MudPaper class="p-3 m-2 rounded-md" Elevation="2">
<MudText Typo="Typo.body1" class="mb-4">تغییر نسبت به ماه پیش</MudText>
<MudText Typo="Typo.h3" Align="Align.Center" class="text-rose-600"><b>10</b></MudText>
<MudText Typo="Typo.h6" Align="Align.Center" class="mb-4 -mt-1"><b>عدد</b></MudText>
</MudPaper>
</MudItem>
</MudGrid>
<MudGrid>
<MudItem xs="12">
<MudPaper>
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
T="BlogSDto" 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.Title"/>
<PropertyColumn Title="مبلغ" Property="arg => arg.CategoryName"/>
<PropertyColumn Title="تاریخ پرداخت" Property="arg => arg.ReadingTime"/>
<TemplateColumn CellClass="d-flex justify-end">
<CellTemplate>
<MudStack Row="true">
<MudIconButton Icon="@Icons.Material.Filled.Edit"
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"/>
</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 BlogsPageViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
ViewModel = new BlogsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
await ViewModel.InitializeAsync();
await base.OnInitializedAsync();
}
}

View File

@ -0,0 +1,6 @@
namespace NetinaShop.AdminPanel.PWA.Pages;
public class OrdersPageViewModel
{
}

View File

@ -0,0 +1,74 @@
@page "/payments"
@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="BlogSDto" 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.Title" />
<PropertyColumn Title="مبلغ" Property="arg => arg.CategoryName" />
<PropertyColumn Title="تاریخ پرداخت" Property="arg => arg.ReadingTime" />
<TemplateColumn CellClass="d-flex justify-end">
<CellTemplate>
<MudStack Row="true">
<MudIconButton Icon="@Icons.Material.Filled.Edit"
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" />
</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 BlogsPageViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
ViewModel = new BlogsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
await ViewModel.InitializeAsync();
await base.OnInitializedAsync();
}
}

View File

@ -0,0 +1,6 @@
namespace NetinaShop.AdminPanel.PWA.Pages;
public class PaymentsPageViewModel
{
}

View File

@ -64,7 +64,7 @@
<Columns>
<PropertyColumn Title="نام محصول" Property="arg => arg.PersianName"/>
<PropertyColumn Title="دسته بندی" Property="arg => arg.CategoryName"/>
<PropertyColumn Title="برند" Property="arg => arg.BrandNames" />
<PropertyColumn Title="برند" Property="arg => arg.BrandName" />
<TemplateColumn T="ProductSDto" Title="پیشنهاد ویژه است">
<CellTemplate>
@if (@context.Item.IsSpecial)

View File

@ -27,8 +27,7 @@ public class ProductsPageViewModel : BaseViewModel<ObservableCollection<ProductS
{
IsProcessing = true;
PageDto.Clear();
var dto = await _restWrapper.CrudDtoApiRest<Product, ProductSDto, Guid>(Address.ProductController)
.ReadAll(CurrentPage);
var dto = await _restWrapper.ProductRestApi.ReadAll(CurrentPage);
dto.ForEach(d => PageDto.Add(d));
if (PageDto.Count == 20)
PageCount = 2;

View File

@ -0,0 +1,134 @@
@page "/users"
@using NetinaShop.Domain.Entities.Users
@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" md="6">
<MudStack Row="true" class="mb-5">
<MudText Typo="Typo.h4">کاربـــــران</MudText>
<MudChip Color="Color.Info" Variant="Variant.Outlined">124 عدد</MudChip>
<MudSpacer />
<MudButton Variant="Variant.Filled"
DisableElevation="true"
StartIcon="@Icons.Material.Outlined.Add"
Color="Color.Secondary"
OnClick="@ViewModel.AddUserClicked"
class="my-auto">افزودن کاربر</MudButton>
</MudStack>
<MudPaper>
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
T="ApplicationUserSDto" Items="@ViewModel.Users" CurrentPage="@ViewModel.UsersCurrentPage"
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.SearchUserChanged"
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" class="my-auto"
OnAdornmentClick="@ViewModel.SearchUserAsync"></MudTextField>
</ToolBarContent>
<Columns>
<PropertyColumn Title="نام و نام خانوادگی" Property="arg => arg.FullName" />
<PropertyColumn Title="شماره تماس" Property="arg => arg.PhoneNumber" />
<PropertyColumn Title="نقش" Property="arg => arg.RoleName" />
<TemplateColumn CellClass="d-flex justify-end">
<CellTemplate>
<MudStack Row="true">
<MudIconButton Icon="@Icons.Material.Filled.Edit"
Size="@Size.Small"
Variant="@Variant.Outlined"
Color="@Color.Info"
OnClick="async()=>await ViewModel.EditUserClicked(context.Item)" />
<MudIconButton Icon="@Icons.Material.Filled.Delete"
Size="@Size.Small"
Variant="@Variant.Outlined"
OnClick="async () => await ViewModel.DeleteUserAsync(context.Item.Id)"
Color="@Color.Error" />
</MudStack>
</CellTemplate>
</TemplateColumn>
</Columns>
<PagerContent>
<MudStack Row="true" class="w-full">
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.UsersPageCount"
SelectedChanged="@ViewModel.ChangeUserPageAsync" class="my-4 mx-auto" />
</MudStack>
</PagerContent>
</MudDataGrid>
</MudPaper>
</MudItem>
<MudItem xs="12" md="6">
<MudStack Row="true" class="mb-5">
<MudText Typo="Typo.h4">نــــــقش ها</MudText>
<MudChip Color="Color.Info" Variant="Variant.Outlined">124 عدد</MudChip>
<MudSpacer/>
<MudButton Variant="Variant.Filled"
DisableElevation="true"
StartIcon="@Icons.Material.Outlined.Add"
Color="Color.Secondary"
OnClick="@ViewModel.AddRoleClicked"
class="my-auto">افزودن نقش</MudButton>
</MudStack>
<MudPaper>
<MudDataGrid FixedFooter="true" FixedHeader="true" Striped="true"
T="ApplicationRole" Items="@ViewModel.Roles" CurrentPage="@ViewModel.RolesCurrentPage"
RowsPerPage="20" Filterable="false" Loading="@ViewModel.IsProcessing"
SortMode="@SortMode.None" Groupable="false">
<Columns>
<PropertyColumn Title="نام" Property="arg => arg.PersianName" />
<PropertyColumn Title="توضیحاتـــ" Property="arg => arg.Description"/>
<TemplateColumn CellClass="d-flex justify-end">
<CellTemplate>
<MudStack Row="true">
<MudIconButton Icon="@Icons.Material.Filled.Edit"
Size="@Size.Small"
Variant="@Variant.Outlined"
OnClick="async()=>await ViewModel.EditRoleClicked(context.Item)"
Color="@Color.Info"/>
<MudIconButton Icon="@Icons.Material.Filled.Delete"
Size="@Size.Small"
OnClick="async () => await ViewModel.DeleteRoleAsync(context.Item.Id)"
Variant="@Variant.Outlined"
Color="@Color.Error"/>
</MudStack>
</CellTemplate>
</TemplateColumn>
</Columns>
<PagerContent>
<MudStack Row="true" class="w-full">
<MudPagination Rectangular="true" Variant="Variant.Filled" Count="@ViewModel.RolesPageCount"
SelectedChanged="@ViewModel.ChangeRolePageAsync" class="my-4 mx-auto"/>
</MudStack>
</PagerContent>
</MudDataGrid>
</MudPaper>
</MudItem>
</MudGrid>
</MudStack>
@code
{
public UserSettingsPageViewModel ViewModel { get; set; }
protected override async Task OnInitializedAsync()
{
ViewModel = new UserSettingsPageViewModel(NavigationManager, Snackbar, UserUtility, RestWrapper, DialogService);
await ViewModel.InitializeAsync();
await base.OnInitializedAsync();
}
}

View File

@ -0,0 +1,321 @@
using MudBlazor;
using NetinaShop.Common.Models.Mapper;
using NetinaShop.Domain.Entities.Blogs;
using NetinaShop.Domain.Entities.Users;
namespace NetinaShop.AdminPanel.PWA.Pages;
public class UserSettingsPageViewModel : 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 UsersCurrentPage = 0;
public int UsersPageCount = 1;
public int RolesCurrentPage = 0;
public int RolesPageCount = 1;
public ObservableCollection<ApplicationUserSDto> Users { get; set; } = new ObservableCollection<ApplicationUserSDto>();
public ObservableCollection<ApplicationRole> Roles { get; set; } = new ObservableCollection<ApplicationRole>();
public UserSettingsPageViewModel(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;
Users.Clear();
var dto = await _restWrapper.UserRestApi.ReadAll(UsersCurrentPage, token);
dto.ForEach(d => Users.Add(d));
if (Users.Count == 15)
UsersPageCount = 2;
Roles.Clear();
var roleDtos = await _restWrapper.RoleRestApi.ReadAll(RolesCurrentPage, token);
roleDtos.ForEach(d => Roles.Add(d));
if (Users.Count == 15)
UsersPageCount = 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 ChangeUserPageAsync(int page)
{
UsersCurrentPage = page - 1;
if (UsersCurrentPage > UsersPageCount - 2)
{
try
{
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
IsProcessing = true;
List<ApplicationUserSDto> dto = new List<ApplicationUserSDto>();
if (Search.IsNullOrEmpty())
{
dto = await _restWrapper.UserRestApi.ReadAll(UsersCurrentPage,token);
}
else
{
dto = await _restWrapper.UserRestApi.ReadAll(UsersCurrentPage, Search);
}
dto.ForEach(d => Users.Add(d));
if (Users.Count % 20 == 0)
UsersPageCount = UsersCurrentPage + 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 ChangeRolePageAsync(int page)
{
RolesCurrentPage = page - 1;
if (RolesCurrentPage > RolesPageCount - 2)
{
try
{
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
IsProcessing = true;
var roleDtos = await _restWrapper.RoleRestApi.ReadAll(RolesCurrentPage, token);
roleDtos.ForEach(d => Roles.Add(d));
if (Users.Count == 15)
RolesPageCount = RolesCurrentPage + 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 AddRoleClicked()
{
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
var dialogResult =await _dialogService.ShowAsync<RoleActionDialogBox>("افزودن نقش جدید", maxWidth);
var result = await dialogResult.Result;
if (!result.Canceled && result.Data is bool and true)
{
await InitializeAsync();
}
}
public async Task EditRoleClicked(ApplicationRole role)
{
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
var parameters = new DialogParameters<RoleActionDialogBox>();
parameters.Add(x => x.Role, role);
var dialogResult = await _dialogService.ShowAsync<RoleActionDialogBox>($"ویرایش نقش {role.PersianName}", parameters, maxWidth);
var result = await dialogResult.Result;
if (!result.Canceled && result.Data is bool and true)
{
await InitializeAsync();
}
}
public async Task DeleteRoleAsync(Guid selectedRoleId)
{
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
{
IsProcessing = true;
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
await _restWrapper.CrudApiRest<ApplicationRole, Guid>(Address.RoleController).Delete(selectedRoleId, token);
_snackbar.Add("حذف نقش با موفقیت انجام شد", Severity.Success);
await InitializeAsync();
}
catch (ApiException ex)
{
var exe = await ex.GetContentAsAsync<ApiResult>();
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
}
catch (Exception e)
{
_snackbar.Add(e.Message, Severity.Error);
}
finally
{
IsProcessing = false;
}
}
}
public async Task AddUserClicked()
{
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
var dialogResult = await _dialogService.ShowAsync<UserActionDialogBox>("افزودن کاربر جدید", maxWidth);
var result = await dialogResult.Result;
if (!result.Canceled && result.Data is bool and true)
{
await InitializeAsync();
}
}
public async Task EditUserClicked(ApplicationUserSDto user)
{
DialogOptions maxWidth = new DialogOptions() { MaxWidth = MaxWidth.Medium, FullWidth = true, DisableBackdropClick = true };
var parameters = new DialogParameters<UserActionDialogBox>();
parameters.Add(x => x.User, user);
var dialogResult = await _dialogService.ShowAsync<UserActionDialogBox>($"ویرایش {user.FirstName + " " + user.LastName}", parameters, maxWidth);
var result = await dialogResult.Result;
if (!result.Canceled && result.Data is bool and true)
{
await InitializeAsync();
}
}
public async Task DeleteUserAsync(Guid selectedUserId)
{
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
{
IsProcessing = true;
var token = await _userUtility.GetBearerTokenAsync();
if (token == null)
throw new Exception("Token is null");
await _restWrapper.CrudApiRest<ApplicationUser, Guid>(Address.UserController).Delete(selectedUserId, token);
_snackbar.Add("حذف کاربر با موفقیت انجام شد", Severity.Success);
await InitializeAsync();
}
catch (ApiException ex)
{
var exe = await ex.GetContentAsAsync<ApiResult>();
_snackbar.Add(exe != null ? exe.Message : ex.Content, Severity.Error);
}
catch (Exception e)
{
_snackbar.Add(e.Message, Severity.Error);
}
finally
{
IsProcessing = false;
}
}
}
public async Task SearchUserChanged(string search)
{
if (search.IsNullOrEmpty() && !Search.IsNullOrEmpty())
await InitializeAsync();
Search = search;
}
public async Task SearchUserAsync()
{
try
{
if (Search.IsNullOrEmpty())
throw new AppException("نام بلاگ برای جست جو وارد نشده است");
IsProcessing = true;
UsersCurrentPage = 0;
UsersPageCount = 1;
Users.Clear();
var dto = await _restWrapper.UserRestApi.ReadAll(UsersCurrentPage, Search);
dto.ForEach(d => Users.Add(d));
if (Users.Count == 20)
UsersPageCount = 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;
}
}
}

View File

@ -30,6 +30,7 @@ public interface ICrudDtoApiRest<T, TDto, in TKey> where T : class where TDto :
[Get("")]
Task<List<TDto>> ReadAll([Query]int page);
[Get("")]
Task<List<TDto>> ReadAll();

View File

@ -15,4 +15,5 @@ public interface IRestWrapper
public IBlogRestApi BlogRestApi { get; }
public IDiscountRestApi DiscountRest { get; }
public IBlogCategoryRestApi BlogCategoryRestApi { get; }
public IRoleRestApi RoleRestApi { get; }
}

View File

@ -0,0 +1,19 @@
using NetinaShop.Domain.Entities.Users;
namespace NetinaShop.AdminPanel.PWA.Services.RestServices;
public interface IRoleRestApi
{
[Put("")]
Task UpdateRoleAsync([Body] RoleActionRequestDto request, [Header("Authorization")] string authorization);
[Post("")]
Task CreateRoleAsync([Body] RoleActionRequestDto request, [Header("Authorization")] string authorization);
[Get("/{id}")]
Task<RoleActionRequestDto> ReadOne(Guid id, [Header("Authorization")] string authorization);
[Get("")]
Task<List<ApplicationRole>> ReadAll([Query] int page, [Header("Authorization")] string authorization);
[Get("")]
Task<List<ApplicationRole>> ReadAll([Query] string roleName, [Header("Authorization")] string authorization);
}

View File

@ -2,8 +2,15 @@
public interface IUserRestApi
{
[Put("")]
Task UpdateUserAsync([Body]UserActionRequestDto request, [Header("Authorization")] string authorization);
[Post("")]
Task CreateUserAsync([Body] UserActionRequestDto request, [Header("Authorization")] string authorization);
[Get("/{id}")]
Task<ApplicationUserSDto> ReadOne(Guid id, [Header("Authorization")] string authorization);
[Get("")]
Task<List<ApplicationUserSDto>> ReadAll([Query] int page, [Header("Authorization")] string authorization);
[Get("")]
Task<List<ApplicationUserSDto>> ReadAll([Query] int page, [Query] string userPhone, [Header("Authorization")] string authorization);
}

View File

@ -27,4 +27,5 @@ 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);
}

View File

@ -9,6 +9,27 @@
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@ckeditor/ckeditor5-alignment": "41.0.0",
"@ckeditor/ckeditor5-autoformat": "41.0.0",
"@ckeditor/ckeditor5-basic-styles": "41.0.0",
"@ckeditor/ckeditor5-block-quote": "41.0.0",
"@ckeditor/ckeditor5-editor-classic": "41.0.0",
"@ckeditor/ckeditor5-essentials": "41.0.0",
"@ckeditor/ckeditor5-font": "41.0.0",
"@ckeditor/ckeditor5-heading": "41.0.0",
"@ckeditor/ckeditor5-horizontal-line": "41.0.0",
"@ckeditor/ckeditor5-image": "41.0.0",
"@ckeditor/ckeditor5-indent": "41.0.0",
"@ckeditor/ckeditor5-link": "41.0.0",
"@ckeditor/ckeditor5-list": "41.0.0",
"@ckeditor/ckeditor5-media-embed": "41.0.0",
"@ckeditor/ckeditor5-paragraph": "41.0.0",
"@ckeditor/ckeditor5-paste-from-office": "41.0.0",
"@ckeditor/ckeditor5-table": "41.0.0",
"@ckeditor/ckeditor5-typing": "41.0.0",
"@ckeditor/ckeditor5-undo": "41.0.0",
"@ckeditor/ckeditor5-upload": "41.0.0",
"@ckeditor/ckeditor5-word-count": "41.0.0",
"autoprefixer": "^10.4.17",
"flowbite": "^2.2.1",
"postcss": "^8.4.33",
@ -27,6 +48,286 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@ckeditor/ckeditor5-alignment": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-41.0.0.tgz",
"integrity": "sha512-+4FnN2xwHCRjRtXUqYV5Ura1tFZx3Uyt5312L30DlWcmYaAoc3zz6AcGvu/Ft7wuEoweGuY+JPQbK1v3tQSZlQ==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-autoformat": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-41.0.0.tgz",
"integrity": "sha512-GxAzOlSarvObBkd+qvy0/fwkNt9x0Pugy8Sh0/7bXDJIkvSXqB4Vecq2l3RA8ATIietW2mD/NYQtu53U1Y8GvQ==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-basic-styles": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-41.0.0.tgz",
"integrity": "sha512-5BZnkL0TRbpdyY4Uwj230Aj+iQufO6He/KPlnA5fFglXKG+AyuPubXOY5P5dAX1SOMKpEZ720zSugFTVvM0ErA==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-block-quote": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-41.0.0.tgz",
"integrity": "sha512-N3AbHpWllqYVY9/ME2NhQJhJLoZoks8r+7HdhZ7mrSPtOJVdeSN7L9X2LXLIozddQ/zqJXv1oJq5m/qMH9ruTw==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-clipboard": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-41.0.0.tgz",
"integrity": "sha512-OS0jL9s5P4uFadQYrPkRtx6+KlDkJwMLbQoeEhTpyG4BwF3zf2Q3UE+KdyvULS2er8FtxVu5bx3zeA7DtxYa9w==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-engine": "41.0.0",
"@ckeditor/ckeditor5-ui": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0",
"@ckeditor/ckeditor5-widget": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-core": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-41.0.0.tgz",
"integrity": "sha512-/t4Cl8fxdrjxn4WRobJdRui4WwGUq/qsD3q5W5IzdCQyON1fr+qaDJ4popGfg+MFSNIFFF9/ip5wkgqOexYMOg==",
"dependencies": {
"@ckeditor/ckeditor5-engine": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-editor-classic": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-41.0.0.tgz",
"integrity": "sha512-64E/zrOs6BRSHJ34wIEtRMEOQwceK9TOWZCmXcIqjS+gH7D1O9mCgM3u8wN+Vk/LfHNXNZq/xl27nYG0tHxwww==",
"dependencies": {
"ckeditor5": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-engine": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-41.0.0.tgz",
"integrity": "sha512-SrzyRU4LXkgIFl614Vshciiwq76zbMt3gKR4Gi1xth2Q5jStT2V42KfUJ+aeigD0RevRcOL8X/g/oSXgKudbow==",
"dependencies": {
"@ckeditor/ckeditor5-utils": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-enter": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-41.0.0.tgz",
"integrity": "sha512-6APFUXOsYcoDVyip2E79gWzE/bmEN1+5eY0ShxJmL4seSD7ipn8TflpGsPjqxe4+bcMBzpfYOcm2wlMxo/Nf6A==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-engine": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-essentials": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-41.0.0.tgz",
"integrity": "sha512-R80qtyBgPGFDaDsJAF3gqqAAnq8+kLijR1bDsAvHwRY4FN0zhdxfwQOdeIB+OCGBevyYNrJ6MFfX/LSOZj66CA==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-font": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-41.0.0.tgz",
"integrity": "sha512-1AbJvWOs0c56O2ARyMGWybsy5fW/9EB7pOcTKeiXaDYZsligb+iOYsUL0XqOdi0v8tibl4l1y49QIJ25TO2N7w==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-heading": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-41.0.0.tgz",
"integrity": "sha512-00axXKOHXVDquO6yvQLAmLe4fk3v/x4JK5FHaclIeFILlJvDU5X4r5J2lEK8ClaJ/2EeaLyt+Dnwk/FRpp+0IQ==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-horizontal-line": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-41.0.0.tgz",
"integrity": "sha512-U0QPHMd3hGEzmsyljoIqd+cltdDBycSUJ8uVI/ELQWIA8YFQRqC3NmdTf4IaHM6kCoihp48bKLdERFj0Gl0Trg==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-image": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-41.0.0.tgz",
"integrity": "sha512-p7tFXov36cQP3Y3Kyr6Q9a/5BA0Pj5Wq8q0qPb08jpdRb6TCR60WkmiIK9yzSNR3FN4sfq1PG4l4mM4M2MJqaA==",
"dependencies": {
"@ckeditor/ckeditor5-ui": "41.0.0",
"ckeditor5": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-indent": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-41.0.0.tgz",
"integrity": "sha512-OpwL9eyKOnQJ3Rv50/ur+fYKd6dpRuEhNUpsf39h0UNbF9i1KU+nUiIU/WLpj3uPPeFKE5DeyM4RQFJuK6oMdw==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-link": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-41.0.0.tgz",
"integrity": "sha512-eMnQNUbTaQSCEeZs4PT/WYpeTLeJj39wASygW+m4Cv28zs91RVhS3amXEuOfoTEp2yxaCw+wAlbAlAoOWhPQCg==",
"dependencies": {
"@ckeditor/ckeditor5-ui": "41.0.0",
"ckeditor5": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-list": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-41.0.0.tgz",
"integrity": "sha512-KBbGWY7ihhc2IpCNpYoT+mzTThpsS3X7Pz6nQHAkGC3rzrdnfPhSbTnrXqckmMfM6VQzGrXUMWnIwLMDdGfGcw==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-media-embed": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-41.0.0.tgz",
"integrity": "sha512-x+umwDKQSB/oCB07r3cYzqWimr4XCOES+iBwFm4gIRp1Prh4DowqaEFipp6WV3goZLParFjkq9aiHaAHXcqO2g==",
"dependencies": {
"@ckeditor/ckeditor5-ui": "41.0.0",
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-paragraph": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-41.0.0.tgz",
"integrity": "sha512-w344YUyhk+ME1fbD0/Dm/xe92OLCMTg5IYEWBpyn20VjnWhu1DPTMJ6NWM6/aGTCZ3bxEIh0UWj4QFr+QstiVA==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-ui": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-paste-from-office": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-41.0.0.tgz",
"integrity": "sha512-QCgLLY9k3LC4iqG9T7m1PyWPZ8c5ZzCcu/Jed3eA9ixjFVFcdL2wkAaiGug50Uw8gfclrsygBAmGrdtH2qSZ7w==",
"dependencies": {
"ckeditor5": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-select-all": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-41.0.0.tgz",
"integrity": "sha512-5dn8TlkygVjs3WILIBIyQrZBwZ7Ip+VS0aC7LJiNLCc1XIEZOpuP7dHph014IbW+8m7P61DK24AuuNn1J0KCRA==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-ui": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-table": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-41.0.0.tgz",
"integrity": "sha512-4JTIc42eN+tfW0Sucw867PDdLD2IOajLXPJ8W1MaDjOfM+7RZZ4muCHMOf1LXk69Gfrt3cd2YrRELv3N2fjv5Q==",
"dependencies": {
"ckeditor5": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-typing": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-41.0.0.tgz",
"integrity": "sha512-uaIU/5X1Ffk2XZZ/3q1NyrINhxPDre8Bnb7+AvzPWtLsdimoCotpzA84h00WVYWS4B5xotrM/eV/MikQvcpRkQ==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-engine": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-ui": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-41.0.0.tgz",
"integrity": "sha512-0oLE7WQyCcNxwvSJw2gwFgrktK19aqbqzIQJpr8xrn5KfDJw7WWk53/yWye05pAphtGo1VZTOk8YG7OJMvQn2Q==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0",
"color-convert": "2.0.1",
"color-parse": "1.4.2",
"lodash-es": "4.17.21",
"vanilla-colorful": "0.7.2"
}
},
"node_modules/@ckeditor/ckeditor5-undo": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-41.0.0.tgz",
"integrity": "sha512-2rF8YqEDZgPa3sD1BVZxlEKxZ7bwqPVCG9f4ebLr9AYSI3DnneitAtiTlkbb2CjcPc4FAcOPFpvQyzavIpkNDg==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-engine": "41.0.0",
"@ckeditor/ckeditor5-ui": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-upload": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-41.0.0.tgz",
"integrity": "sha512-EGb88xYTyL6Xdi7pFkmhv3Zv2JrKUWvyTXGdUEmLsMqRzxV+VHkVt2HTxHERaZlOa/iY6GzkC4yHGFL+jC28/Q==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-ui": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0"
}
},
"node_modules/@ckeditor/ckeditor5-utils": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-41.0.0.tgz",
"integrity": "sha512-7ITAPlFxjPtFa4HnB+zrjgEs0nfPs+QHmf1pOltfIUhpFvg5V6ImIrBvzIaf+AeU5Uf6pNVHjXnqorn9oeqRTA==",
"dependencies": {
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-watchdog": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-41.0.0.tgz",
"integrity": "sha512-S2mP2A+Zil7j7LMZqJhBTXc007gbYJD12xBpa5MQFLcUNLwYR9nj69IM5QmJV50ai0U7znkWQxJai/4BAJvL8Q==",
"dependencies": {
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-widget": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-41.0.0.tgz",
"integrity": "sha512-pQomiS4wSlDs17muViabmGzcGAWR/cqtUIJswXAqlaQICdbOIX+tfA9XsZDdekrTZZxZxk+1Zh1UJ4WWK4kmSg==",
"dependencies": {
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-engine": "41.0.0",
"@ckeditor/ckeditor5-enter": "41.0.0",
"@ckeditor/ckeditor5-typing": "41.0.0",
"@ckeditor/ckeditor5-ui": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@ckeditor/ckeditor5-word-count": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-41.0.0.tgz",
"integrity": "sha512-0+z73n94Sgyp9wN13ZGEdxF4u9rTFBGZ0LreRX7O4wTHBPMVQY6KFWXXo+BVAEI/L6moR57VBlp8aTMIhvdzQA==",
"dependencies": {
"ckeditor5": "41.0.0",
"lodash-es": "4.17.21"
}
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@ -343,6 +644,26 @@
"fsevents": "~2.3.2"
}
},
"node_modules/ckeditor5": {
"version": "41.0.0",
"resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-41.0.0.tgz",
"integrity": "sha512-b1mS43gOmoUtf/fWDYrNxSWhHQFc7Qv9JB5nnePmv1XGIYBa/Bcgp4SSXRSSVl8XfmT9Z7BbYKux0V+ZE45RIQ==",
"dependencies": {
"@ckeditor/ckeditor5-clipboard": "41.0.0",
"@ckeditor/ckeditor5-core": "41.0.0",
"@ckeditor/ckeditor5-engine": "41.0.0",
"@ckeditor/ckeditor5-enter": "41.0.0",
"@ckeditor/ckeditor5-paragraph": "41.0.0",
"@ckeditor/ckeditor5-select-all": "41.0.0",
"@ckeditor/ckeditor5-typing": "41.0.0",
"@ckeditor/ckeditor5-ui": "41.0.0",
"@ckeditor/ckeditor5-undo": "41.0.0",
"@ckeditor/ckeditor5-upload": "41.0.0",
"@ckeditor/ckeditor5-utils": "41.0.0",
"@ckeditor/ckeditor5-watchdog": "41.0.0",
"@ckeditor/ckeditor5-widget": "41.0.0"
}
},
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
@ -439,6 +760,14 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/color-parse": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz",
"integrity": "sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==",
"dependencies": {
"color-name": "^1.0.0"
}
},
"node_modules/commander": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
@ -821,6 +1150,11 @@
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lru-cache": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz",
@ -1657,6 +1991,11 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/vanilla-colorful": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz",
"integrity": "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg=="
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",

View File

@ -4,7 +4,28 @@
"flowbite": "^2.2.1",
"postcss": "^8.4.33",
"postcss-cli": "^11.0.0",
"tailwindcss": "^3.4.1"
"tailwindcss": "^3.4.1",
"@ckeditor/ckeditor5-alignment": "41.0.0",
"@ckeditor/ckeditor5-autoformat": "41.0.0",
"@ckeditor/ckeditor5-basic-styles": "41.0.0",
"@ckeditor/ckeditor5-block-quote": "41.0.0",
"@ckeditor/ckeditor5-editor-classic": "41.0.0",
"@ckeditor/ckeditor5-essentials": "41.0.0",
"@ckeditor/ckeditor5-font": "41.0.0",
"@ckeditor/ckeditor5-heading": "41.0.0",
"@ckeditor/ckeditor5-horizontal-line": "41.0.0",
"@ckeditor/ckeditor5-image": "41.0.0",
"@ckeditor/ckeditor5-indent": "41.0.0",
"@ckeditor/ckeditor5-link": "41.0.0",
"@ckeditor/ckeditor5-list": "41.0.0",
"@ckeditor/ckeditor5-media-embed": "41.0.0",
"@ckeditor/ckeditor5-paragraph": "41.0.0",
"@ckeditor/ckeditor5-paste-from-office": "41.0.0",
"@ckeditor/ckeditor5-table": "41.0.0",
"@ckeditor/ckeditor5-typing": "41.0.0",
"@ckeditor/ckeditor5-undo": "41.0.0",
"@ckeditor/ckeditor5-upload": "41.0.0",
"@ckeditor/ckeditor5-word-count": "41.0.0"
},
"name": "netina.admin.pwa",
"version": "1.0.0",

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,511 @@
/**
* @license Copyright (c) 2014-2024, CKSource Holding sp. z o.o. All rights reserved.
* This file is licensed under the terms of the MIT License (see LICENSE.md).
*/
:root {
--ck-sample-base-spacing: 2em;
--ck-sample-color-white: #fff;
--ck-sample-color-green: #279863;
--ck-sample-color-blue: #1a9aef;
--ck-sample-container-width: 1285px;
--ck-sample-sidebar-width: 350px;
--ck-sample-editor-min-height: 400px;
--ck-sample-editor-z-index: 10;
}
/* --------- EDITOR STYLES ---------------------------------------------------------------------------------------- */
.editor__editable,
/* Classic build. */
main .ck-editor[role='application'] .ck.ck-content,
/* Decoupled document build. */
.ck.editor__editable[role='textbox'],
.ck.ck-editor__editable[role='textbox'],
/* Inline & Balloon build. */
.ck.editor[role='textbox'] {
width: 100%;
background: #fff;
font-size: 1em;
line-height: 1.6em;
min-height: var(--ck-sample-editor-min-height);
padding: 1.5em 2em;
}
.ck.ck-editor__editable {
background: #fff;
border: 1px solid hsl(0, 0%, 70%);
width: 100%;
}
/* Because of sidebar `position: relative`, Edge is overriding the outline of a focused editor. */
.ck.ck-editor__editable {
position: relative;
z-index: var(--ck-sample-editor-z-index);
}
.editor-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
position: relative;
width: 100%;
justify-content: center;
}
.editor-container--with-sidebar > .ck.ck-editor {
width: calc( 100% - var(--ck-sample-sidebar-width) );
}
/* --------- DECOUPLED (DOCUMENT) BUILD. ---------------------------------------------*/
body[data-editor='DecoupledEditor'] .document-editor__toolbar {
width: 100%;
}
body[data-editor='DecoupledEditor'] .collaboration-demo__editable,
body[data-editor='DecoupledEditor'] .row-editor .editor {
/* A pixel is added for each of the border. */
width: calc(21cm + 2px);
min-height: calc(29.7cm + 2px);
/* To avoid having extra scrolls inside the editor container. */
height: fit-content;
padding: 2cm 1.2cm;
margin: 2.5rem;
border: 1px hsl( 0, 0%, 82.7% ) solid;
background-color: var(--ck-sample-color-white);
box-shadow: 0 0 5px hsla( 0, 0%, 0%, .1 );
box-sizing: border-box;
}
body[data-editor='DecoupledEditor'] .row-editor {
display: flex;
position: relative;
justify-content: center;
overflow-y: auto;
background-color: #f2f2f2;
border: 1px solid hsl(0, 0%, 77%);
/* Limit the max-height of the editor to avoid scrolling from bottom to top to see the toolbar. */
max-height: 700px;
}
body[data-editor='DecoupledEditor'] .sidebar {
background: transparent;
border: 0;
box-shadow: none;
}
/* --------- COMMENTS & TRACK CHANGES FEATURE ---------------------------------------------------------------------- */
.sidebar {
padding: 0 15px;
position: relative;
min-width: var(--ck-sample-sidebar-width);
max-width: var(--ck-sample-sidebar-width);
font-size: 20px;
border: 1px solid hsl(0, 0%, 77%);
background: hsl(0, 0%, 98%);
border-left: 0;
overflow: hidden;
min-height: 100%;
flex-grow: 1;
}
/* Do not inherit styles related to the editable editor content. See line 25.*/
.sidebar .ck-content[role='textbox'],
.ck.ck-annotation-wrapper .ck-content[role='textbox'] {
min-height: unset;
width: unset;
padding: 0;
background: transparent;
}
.sidebar.narrow {
min-width: 60px;
flex-grow: 0;
}
.sidebar.hidden {
display: none !important;
}
#sidebar-display-toggle {
position: absolute;
z-index: 1;
width: 30px;
height: 30px;
text-align: center;
left: 15px;
top: 30px;
border: 0;
padding: 0;
color: hsl( 0, 0%, 50% );
transition: 250ms ease color;
background-color: transparent;
}
#sidebar-display-toggle:hover {
color: hsl( 0, 0%, 30% );
cursor: pointer;
}
#sidebar-display-toggle:focus,
#sidebar-display-toggle:active {
outline: none;
border: 1px solid #a9d29d;
}
#sidebar-display-toggle svg {
fill: currentColor;
}
/* --------- COLLABORATION FEATURES (USERS) ------------------------------------------------------------------------ */
.row-presence {
width: 100%;
border: 1px solid hsl(0, 0%, 77%);
border-bottom: 0;
background: hsl(0, 0%, 98%);
padding: var(--ck-spacing-small);
/* Make `border-bottom` as `box-shadow` to not overlap with the editor border. */
box-shadow: 0 1px 0 0 hsl(0, 0%, 77%);
/* Make `z-index` bigger than `.editor` to properly display tooltips. */
z-index: 20;
}
.ck.ck-presence-list {
flex: 1;
padding: 1.25rem .75rem;
}
.presence .ck.ck-presence-list__counter {
order: 2;
margin-left: var(--ck-spacing-large)
}
/* --------- REAL TIME COLLABORATION FEATURES (SHARE TOPBAR CONTAINER) --------------------------------------------- */
.collaboration-demo__row {
display: flex;
position: relative;
justify-content: center;
overflow-y: auto;
background-color: #f2f2f2;
border: 1px solid hsl(0, 0%, 77%);
}
body[data-editor='InlineEditor'] .collaboration-demo__row {
border: 0;
}
.collaboration-demo__container {
max-width: var(--ck-sample-container-width);
margin: 0 auto;
padding: 1.25rem;
}
.presence, .collaboration-demo__row {
transition: .2s opacity;
}
.collaboration-demo__topbar {
background: #fff;
border: 1px solid var(--ck-color-toolbar-border);
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 0;
border-radius: 4px 4px 0 0;
}
.collaboration-demo__topbar .btn {
margin-right: 1em;
outline-offset: 2px;
outline-width: 2px;
background-color: var( --ck-sample-color-blue );
}
.collaboration-demo__topbar .btn:focus,
.collaboration-demo__topbar .btn:hover {
border-color: var( --ck-sample-color-blue );
}
.collaboration-demo__share {
display: flex;
align-items: center;
padding: 1.25rem .75rem
}
.collaboration-demo__share-description p {
margin: 0;
font-weight: bold;
font-size: 0.9em;
}
.collaboration-demo__share input {
height: auto;
font-size: 0.9em;
min-width: 220px;
margin: 0 10px;
border-radius: 4px;
border: 1px solid var(--ck-color-toolbar-border)
}
.collaboration-demo__share button,
.collaboration-demo__share input {
height: 40px;
padding: 5px 10px;
}
.collaboration-demo__share button {
position: relative;
}
.collaboration-demo__share button:focus {
outline: none;
}
.collaboration-demo__share button[data-tooltip]::before,
.collaboration-demo__share button[data-tooltip]::after {
position: absolute;
visibility: hidden;
opacity: 0;
pointer-events: none;
transition: all .15s cubic-bezier(.5,1,.25,1);
z-index: 1;
}
.collaboration-demo__share button[data-tooltip]::before {
content: attr(data-tooltip);
padding: 5px 15px;
border-radius: 3px;
background: #111;
color: #fff;
text-align: center;
font-size: 11px;
top: 100%;
left: 50%;
margin-top: 5px;
transform: translateX(-50%);
}
.collaboration-demo__share button[data-tooltip]::after {
content: '';
border: 5px solid transparent;
width: 0;
font-size: 0;
line-height: 0;
top: 100%;
left: 50%;
transform: translateX(-50%);
border-bottom: 5px solid #111;
border-top: none;
}
.collaboration-demo__share button[data-tooltip]:hover:before,
.collaboration-demo__share button[data-tooltip]:hover:after {
visibility: visible;
opacity: 1;
}
.collaboration-demo--ready {
overflow: visible;
height: auto;
}
.collaboration-demo--ready .presence,
.collaboration-demo--ready .collaboration-demo__row {
opacity: 1;
}
/* --------- PAGINATION FEATURE ------------------------------------------------------------------------------------ */
/* Pagination view line must be stacked at least at the same level as the editor,
otherwise it will be hidden underneath. */
.ck.ck-pagination-view-line {
z-index: var(--ck-sample-editor-z-index);
}
/* --------- REVISION HISTORY FEATURE ------------------------------------------------------------------------------ */
.revision-viewer-container {
display: none;
max-width: 100%;
word-wrap: break-word;
}
.revision-viewer-sidebar {
position: relative;
min-width: 310px;
overflow: hidden;
background: var(--ck-color-toolbar-background);
border: 1px solid var(--ck-color-toolbar-border);
margin-left: -1px;
}
/* A case when Pagination and Revision History features are enabled in the editor. */
/* Move the square with page number from the Pagination plugin to the left side, so that it does not cover the RH sidebar. */
body[data-revision-history='true'] .ck.ck-pagination-view-line::after {
transform: translateX(-100%) !important;
left: -1px !important;
right: unset !important;
}
/* --------- DOCUMENT OUTLINE FEATURE ------------------------------------------------------------------------------ */
.document-outline-container {
max-height: 80vh;
overflow-y: auto;
margin-bottom: 1em;
}
.document-outline-container .ck.ck-document-outline {
min-height: 100%;
border: 1px solid var(--ck-color-base-border);
background-color: hsl(0, 0%, 96%);
}
/* --------- SAMPLE GENERIC STYLES (not related to CKEditor) ------------------------------------------------------- */
body, html {
padding: 0;
margin: 0;
font-family: sans-serif, Arial, Verdana, "Trebuchet MS", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
font-size: 16px;
line-height: 1.5;
}
body {
height: 100%;
color: #2D3A4A;
}
body * {
box-sizing: border-box;
}
a {
color: #38A5EE;
}
header .centered {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
min-height: 8em;
}
header h1 a {
font-size: 20px;
display: flex;
align-items: center;
color: #2D3A4A;
text-decoration: none;
}
header h1 img {
display: block;
height: 64px;
}
header nav ul {
margin: 0;
padding: 0;
list-style-type: none;
}
header nav ul li {
display: inline-block;
}
header nav ul li + li {
margin-left: 1em;
}
header nav ul li a {
font-weight: bold;
text-decoration: none;
color: #2D3A4A;
}
header nav ul li a:hover {
text-decoration: underline;
}
main .message {
padding: 0 0 var(--ck-sample-base-spacing);
background: var(--ck-sample-color-green);
color: var(--ck-sample-color-white);
}
main .message::after {
content: "";
z-index: -1;
display: block;
height: 10em;
width: 100%;
background: var(--ck-sample-color-green);
position: absolute;
left: 0;
}
main .message h2 {
position: relative;
padding-top: 1em;
font-size: 2em;
}
.centered {
max-width: var(--ck-sample-container-width);
margin: 0 auto;
padding: 0 var(--ck-sample-base-spacing);
}
.row {
display: flex;
position: relative;
}
.btn {
cursor: pointer;
padding: 8px 16px;
font-size: 1rem;
user-select: none;
border-radius: 4px;
transition: color .2s ease-in-out,background-color .2s ease-in-out,border-color .2s ease-in-out,opacity .2s ease-in-out;
background-color: var(--ck-sample-color-button-blue);
border-color: var(--ck-sample-color-button-blue);
color: var(--ck-sample-color-white);
display: inline-block;
}
.btn--tiny {
padding: 6px 12px;
font-size: .8rem;
}
footer {
margin: calc(2*var(--ck-sample-base-spacing)) var(--ck-sample-base-spacing);
font-size: .8em;
text-align: center;
color: rgba(0,0,0,.4);
}
/* --------- RWD --------------------------------------------------------------------------------------------------- */
@media screen and ( max-width: 800px ) {
:root {
--ck-sample-base-spacing: 1em;
}
header h1 {
width: 100%;
}
header h1 img {
height: 40px;
}
header nav ul {
text-align: right;
}
main .message h2 {
font-size: 1.5em;
}
}

View File

@ -1237,9 +1237,6 @@ input:checked + .toggle-bg {
.max-h-\[30rem\] {
max-height: 30rem;
}
.min-h-\[10rem\] {
min-height: 10rem;
}
.min-h-\[28rem\] {
min-height: 28rem;
}

View File

@ -1367,10 +1367,6 @@ input:checked + .toggle-bg {
max-height: 30rem;
}
.min-h-\[10rem\] {
min-height: 10rem;
}
.min-h-\[28rem\] {
min-height: 28rem;
}

View File

@ -9,6 +9,7 @@
<link href="https://use.fontawesome.com/releases/v5.14.0/css/all.css" rel="stylesheet">
<link rel="stylesheet" href="css/app.min.css" />
<link rel="stylesheet" href="css/CKEditor.css" />
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/@dotlottie/player-component@latest/dist/dotlottie-player.mjs" type="module"></script>
@ -57,6 +58,7 @@
<a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
<script src="aes-js-3.1.2.js"></script>
<script type="text/javascript">
function encryptText(inputSrt, keyArray) {
@ -72,7 +74,11 @@
var decryptedBytes = aesCtr.decrypt(encryptedBytes);
return aesjs.utils.utf8.fromBytes(decryptedBytes);
}
</script>
<script src="ckeditor.js"></script>
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
<!--<script>navigator.serviceWorker.register('service-worker.js');</script>-->
<script src="_content/MudBlazor/MudBlazor.min.js"></script>