This commit is contained in:
mmrbnjd
2025-07-11 20:37:28 +03:30
parent 1924c88e7a
commit ff342a53c0
156 changed files with 13746 additions and 35 deletions

View File

@@ -0,0 +1,12 @@
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>

View File

@@ -0,0 +1,82 @@
@using Common.Dtos.User
@using Hushian.Application.Dtos
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject UserService userService;
<div class="row" style="height: fit-content; padding: 1rem;">
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.FullName" type="text" class="form-control" placeholder="نام و نام خانوادگی" />
</div>
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.PhoneNumber" type="text" class="form-control" placeholder="موبایل" />
</div>
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.Email" type="text" class="form-control" placeholder="پست الکترونیک" />
</div>
<div class="col-md-12" style="display: flex;flex-wrap: nowrap;align-items: baseline;">
<InputFile type="file" OnChange="OnFileChange" accept=".png" style="margin-bottom:10px" />
@if (model.img != null && model.img.Length > 0)
{
<Image src="@GetImageSource()" Class="rounded mx-auto d-block" height="25" width="25" alt="Uploaded Image" />
}
</div>
<Button Loading=loading LoadingText="در حال ذخیره اطلاعات..." Color="ButtonColor.Warning" @onclick="NewItem"> جدید </Button>
</div>
@code {
public AddUserDto model { get; set; } = new();
[Parameter] public EventCallback OnMultipleOfThree { get; set; }
public bool loading { get; set; } = false;
}
@functions{
async Task NewItem()
{
if (!string.IsNullOrEmpty(model.FullName) && !string.IsNullOrEmpty(model.PhoneNumber))
{
model.PassWord =model.UserName= model.PhoneNumber;
if (string.IsNullOrEmpty(model.Email)) model.Email = $"{model.UserName}@hushian.ir";
loading = true;
if (await userService.AddExper(model))
{
loading = false;
await OnMultipleOfThree.InvokeAsync();
}
loading = false;
}
}
protected override async Task OnParametersSetAsync()
{
model = new();
await base.OnParametersSetAsync();
}
private async Task OnFileChange(InputFileChangeEventArgs e)
{
var file = e.File;
using (var memoryStream = new MemoryStream())
{
await file.OpenReadStream().CopyToAsync(memoryStream);
model.img = memoryStream.ToArray();
}
}
private string GetImageSource()
{
if (model.img != null)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(model.img)}";
}
return string.Empty;
}
}

View File

@@ -0,0 +1,66 @@
@using Hushian.Application.Dtos
@using HushianWebApp.Service
@inject GroupService groupService;
<div class="row" style="height: fit-content; padding: 1rem;">
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.Name" type="text" class="form-control" placeholder="نام گروه" />
</div>
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.Info" type="text" class="form-control" placeholder="توضیحات" />
</div>
<div class="col-md-12" style="display: flex;flex-wrap: nowrap;align-items: baseline;">
<InputFile type="file" OnChange="OnFileChange" accept=".png" style="margin-bottom:10px" />
@if (model.img != null && model.img.Length >0)
{
<Image src="@GetImageSource()" Class="rounded mx-auto d-block" height="25" width="25" alt="Uploaded Image" />
}
</div>
<Button Loading=loading LoadingText="در حال ذخیره اطلاعات..." Color="ButtonColor.Warning" @onclick="NewItem"> جدید </Button>
</div>
@code {
[Parameter] public ADDGroupDto model { get; set; } = new();
[Parameter] public EventCallback OnMultipleOfThree { get; set; }
public bool loading { get; set; } = false;
}
@functions {
async Task NewItem()
{
if (!string.IsNullOrEmpty(model.Name))
{
loading = true;
if (await groupService.AddGroup(model))
{
loading = false;
await OnMultipleOfThree.InvokeAsync();
}
loading = false;
}
}
private async Task OnFileChange(InputFileChangeEventArgs e)
{
var file = e.File;
using (var memoryStream = new MemoryStream())
{
await file.OpenReadStream().CopyToAsync(memoryStream);
model.img = memoryStream.ToArray();
}
}
private string GetImageSource()
{
if (model.img != null)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(model.img)}";
}
return string.Empty;
}
}

View File

@@ -0,0 +1,101 @@
@using Hushian.Application.Dtos
@inject IJSRuntime JSRuntime
<div class="chat-container p-3">
@foreach (var msg in Messages)
{
@if (!target && ((!msg.IsRead && msg.Type == Hushian.Enums.ConversationType.UE) || Messages.Last() == msg))
{
target = true;
<div id="target" style="text-align: center;">
@if (!msg.IsRead && msg.Type == Hushian.Enums.ConversationType.UE)
{
<p>ـــــــــــــــــــــــــ</p>
}
</div>
}
<div class="d-flex mb-2 @(msg.Type==Hushian.Enums.ConversationType.UE ? "justify-content-end" : "justify-content-start")" >
<div class="chat-bubble @(msg.Type==Hushian.Enums.ConversationType.UE ? "chat-mine"
: msg.Type==Hushian.Enums.ConversationType.UE && msg.ExperID=="bot" ? "chat-ai" : "chat-other")" data-id="@msg.ID">
@msg.text
</div>
@if (msg.Type == Hushian.Enums.ConversationType.EU)
{
if (msg.IsRead)
{
<Icon Style="align-self: self-end;" Name="IconName.CheckAll" Size="IconSize.x5" Color="IconColor.Success" />
}
else
{
<Icon Style="align-self: self-end;" Name="IconName.CheckLg" Size="IconSize.x5" />
}
}
</div>
}
</div>
<style>
.chat-bubble {
padding: 0.5rem 0.75rem;
border-radius: 1rem;
max-width: 75%;
word-wrap: break-word;
white-space: pre-wrap;
}
.chat-mine {
background: linear-gradient(to right, #005eff, #267fff);
color: white;
border-top-left-radius: 0;
}
.chat-other {
background-color: #f1f1f1;
color: #333;
border-top-right-radius: 0;
}
.chat-ai {
background-color: #f1f1f1;
color: #353;
border-top-right-radius: 0;
}
</style>
@code {
bool target = false;
[Parameter]
public List<ConversationItemDto> Messages { get; set; } = new();
[Parameter] public EventCallback<int> EventCallIsRead { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await JSRuntime.InvokeVoidAsync("observeVisibility", DotNetObjectReference.Create(this));
await JSRuntime.InvokeVoidAsync("scrollToTarget");
}
}
[JSInvokable]
public async Task MarkAsRead(int id)
{
var msg = Messages.FirstOrDefault(m => m.ID == id);
if (msg != null && !msg.IsRead && msg.Type==Hushian.Enums.ConversationType.UE)
{
msg.IsRead = true;
await EventCallIsRead.InvokeAsync(id);
}
await Task.CompletedTask;
}
}

View File

@@ -0,0 +1,66 @@
@using Common.Dtos.User
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject UserService userService;
@inject NavigationManager NavigationManager
@inject AuthService authService;
@inject ILocalStorageService localStorageService;
<form style="background-color: #ffffff; padding: 20px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); display: flex; flex-direction: column;">
<label style="margin-bottom: 8px; font-size: 14px; color: #333;" for="oldpass">رمز عبور قبلی:</label>
<input dir="ltr" style="text-align:center" @bind="@dto.OldPassword" type="password" class="form-control" placeholder="رمز عبور قبلی" />
<label style="margin-bottom: 8px; font-size: 14px; color: #333; margin-top:15px" for="newpass">رمز عبور جدید:</label>
<input dir="ltr" style="text-align:center" @bind="@dto.NewPassword" type="password" class="form-control" placeholder="رمز عبور جدید" />
<label style="margin-bottom: 8px; font-size: 14px; color: #333; margin-top:15px" for="newpass2">تکرار رمز عبور جدید:</label>
<input dir="ltr" style="text-align:center" @bind="RePassword" type="password" class="form-control" placeholder="تکرار رمز عبور جدید" />
<ul style="padding-right:10px; padding-top:10px">
<li style="color:red">رمز عبور باید حداقل دارای یک کاراکتر باشد</li>
<li style="color:red">رمز عبور باید حداقل دارای یک کاراکتر انگلیسی بزرگ باشد</li>
<li style="color:red">رمز عبور باید حداقل دارای یک کاراکتر انگلیسی کوچک باشد</li>
<li style="color:red">رمز عبور باید حداقل دارای یک عدد باشد</li>
</ul>
<div class="d-grid gap-2">
<Button style="margin-top:15px" Loading="SpinnerVisible" onclick="@Click" Color="ButtonColor.Primary"> تغییر کلمه عبور </Button>
</div>
</form>
@code {
[Inject] protected ToastService ToastService { get; set; } = default!;
public bool SpinnerVisible { get; set; }
public ChangePasswordFromUserDto dto { get; set; } = new();
public string RePassword { get; set; } = "";
public string Username { get; set; } = "";
protected override async Task OnParametersSetAsync()
{
Username = await localStorageService.GetItem<string>("Username");
dto = new() { UserName = Username };
await base.OnParametersSetAsync();
}
async Task Click()
{
if (string.IsNullOrEmpty(dto.OldPassword) || string.IsNullOrEmpty(dto.NewPassword))
return;
if (dto.NewPassword != RePassword)
{
ToastService.Notify(new ToastMessage(ToastType.Danger, "کلمه عبور با تکرار متفاوت است"));
return;
}
SpinnerVisible = true;
var result = await userService.ChangePasswordYourself(dto);
if (result)
{
ToastService.Notify(new ToastMessage(ToastType.Success, "تغییر کلمه عبور با موفقیت انجام شد"));
await authService.Logout();
NavigationManager.NavigateTo("/login");
}
else ToastService.Notify(new ToastMessage(ToastType.Danger, "خطا در تغییر کلمه عبور"));
SpinnerVisible = false;
}
}

View File

@@ -0,0 +1,106 @@
@using Common.Dtos.User
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject UserService userService;
@inject ILocalStorageService localStorageService;
<div class="row" style="height: fit-content; padding: 1rem;">
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.FullName" type="text" class="form-control" placeholder="نام کامل" />
</div>
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.Email" type="text" class="form-control" placeholder="پست الکترونیک" />
</div>
<div class="col-md-12" style="display: flex;flex-wrap: nowrap;align-items: baseline;">
<InputFile type="file" OnChange="OnFileChange" accept=".png" style="margin-bottom:10px" />
@if (model.img != null && model.img.Length > 0)
{
<Image src="@GetImageSource()" Class="rounded mx-auto d-block" height="25" width="25" alt="Uploaded Image" />
}
</div>
<Button Loading=loading LoadingText="در حال ذخیره اطلاعات..." Color="ButtonColor.Warning" @onclick="NewItem"> ویرایش </Button>
@if (isAuthorizedCompanyUser)
{
<Button Loading=loading LoadingText="در حال آزادسازی..." Color="ButtonColor.Danger" @onclick="FreeExper"> آزادسازی کارشناس </Button>
}
</div>
@code {
bool isAuthorizedCompanyUser = false;
[Parameter] public EventCallback<EditUserFromUserDto> OnMultipleOfThree { get; set; }
public List<string> Roles { get; set; } = new();
public bool loading { get; set; } = false;
[Inject] protected ToastService ToastService { get; set; } = default!;
public EditUserFromUserDto model { get; set; } = new();
protected override async Task OnInitializedAsync()
{
var user=await userService.GetCurrentUser();
if (user!=null)
{
model.UserName=user.UserName;
model.img = user.img;
model.FullName = user.FullName;
model.Email = user.Email;
Roles = await localStorageService.GetItem<List<string>>("Role");
isAuthorizedCompanyUser = Roles.Contains("HushianExperCompany") && await userService.CheckAvailableExperInCompany();
}
else
{
ToastService.Notify(new ToastMessage(ToastType.Danger,"خطا در فراخوانی اطلاعات کاربر"));
}
await base.OnInitializedAsync();
}
private async Task OnFileChange(InputFileChangeEventArgs e)
{
var file = e.File;
using (var memoryStream = new MemoryStream())
{
await file.OpenReadStream().CopyToAsync(memoryStream);
model.img = memoryStream.ToArray();
}
}
private string GetImageSource()
{
if (model.img != null)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(model.img)}";
}
return string.Empty;
}
async Task NewItem()
{
if (!string.IsNullOrEmpty(model.FullName))
{
if (string.IsNullOrEmpty(model.Email)) model.Email = $"{model.UserName}@hushian.ir";
loading = true;
if (await userService.EditUserYourself(model))
{
loading = false;
await OnMultipleOfThree.InvokeAsync(model);
}
loading = false;
}
}
async Task FreeExper()
{
loading = true;
if (await userService.FreeExper())
{
loading = false;
await OnMultipleOfThree.InvokeAsync(model);
}
loading = false;
}
}

View File

@@ -0,0 +1,75 @@
@using Hushian.Application.Dtos
@using HushianWebApp.Service
@inject GroupService groupService;
@inject UserService userService;
@if (!Spinnervisible)
{
<div class="row">
<div class="col-md-12 col-sm-12" style="margin-bottom:15px">
<AutoComplete @bind-Value="ExperName"
TItem="HushianUserDto"
DataProvider="DataProvider"
PropertyName="FullName"
Placeholder="جستجو در کاربران..."
OnChanged="(HushianUserDto exper) => OnAutoCompleteChanged(exper)" />
</div>
</div>
<SortableList TItem="HushianUserDto"
Data="Expers"
Context="item"
AllowSorting="false">
<ItemTemplate>
@item.FullName
<Tooltip Title="گرفتن دسترسی" role="button">
<Icon Name="IconName.Trash3" @onclick="async()=>{await UnJoin(item);}"></Icon>
</Tooltip>
</ItemTemplate>
</SortableList>
}
<div class="d-flex justify-content-center">
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Success" Visible="@Spinnervisible" />
</div>
@code {
private string? ExperName;
private bool Spinnervisible = false;
[Parameter] public int GroupID { get; set; }
public List<HushianUserDto> Expers { get; set; }
= new();
public List<HushianUserDto> CoExpers { get; set; }
= new();
protected override async Task OnParametersSetAsync()
{
Spinnervisible = true;
Expers = await groupService.GetExpersFromGroupID(GroupID);
Spinnervisible = false;
await base.OnParametersSetAsync();
}
}
@functions {
private async Task<AutoCompleteDataProviderResult<HushianUserDto>> DataProvider(AutoCompleteDataProviderRequest<HushianUserDto> request)
{
CoExpers = (await userService.GetExpersCompany(0, 0, 0)).list;
return await Task.FromResult(new AutoCompleteDataProviderResult<HushianUserDto> { Data = CoExpers.Where(w => w.FullName.Contains(request.Filter.Value)), TotalCount = CoExpers.Count() });
}
private async Task OnAutoCompleteChanged(HushianUserDto exper)
{
Spinnervisible = true;
if (exper != null
&& !Expers.Any(a => a.UserID == exper.UserID)
&& await groupService.JoinExperToGroup(GroupID, exper.UserID) )
Expers.Add(exper);
Spinnervisible = false;
}
async Task UnJoin(HushianUserDto exper)
{
Spinnervisible = true;
if (exper != null && await groupService.UnJoinExperToGroup(GroupID, exper.UserID))
Expers.Remove(exper);
Spinnervisible = false;
}
}

View File

@@ -0,0 +1,73 @@
@using Common.Dtos.User
@using Hushian.Application.Dtos
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject UserService userService;
<div class="row" style="height: fit-content; padding: 1rem;">
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.FullName" type="text" class="form-control" placeholder="نام و نام خانوادگی" />
</div>
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.Email" type="text" class="form-control" placeholder="پست الکترونیک" />
</div>
<div class="col-md-12" style="display: flex;flex-wrap: nowrap;align-items: baseline;">
<InputFile type="file" OnChange="OnFileChange" accept=".png" style="margin-bottom:10px" />
@if (model.img != null && model.img.Length > 0)
{
<Image src="@GetImageSource()" Class="rounded mx-auto d-block" height="25" width="25" alt="Uploaded Image" />
}
</div>
<Button Loading=loading LoadingText="در حال ویرایش اطلاعات..." Color="ButtonColor.Warning" @onclick="NewItem"> ویرایش </Button>
</div>
@code {
[Parameter] public EditUserFromUserDto model { get; set; }
[Parameter] public EventCallback OnMultipleOfThree { get; set; }
public bool loading { get; set; } = false;
}
@functions{
async Task NewItem()
{
if (!string.IsNullOrEmpty(model.FullName))
{
if (string.IsNullOrEmpty(model.Email)) model.Email = $"{model.UserName}@hushian.ir";
loading = true;
if (await userService.ExperEditingFromManager(model))
{
loading = false;
await OnMultipleOfThree.InvokeAsync();
}
loading = false;
}
}
private async Task OnFileChange(InputFileChangeEventArgs e)
{
var file = e.File;
using (var memoryStream = new MemoryStream())
{
await file.OpenReadStream().CopyToAsync(memoryStream);
model.img = memoryStream.ToArray();
}
}
private string GetImageSource()
{
if (model.img != null)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(model.img)}";
}
return string.Empty;
}
}

View File

@@ -0,0 +1,66 @@
@using Hushian.Application.Dtos
@using HushianWebApp.Service
@inject GroupService groupService;
<div class="row" style="height: fit-content; padding: 1rem;">
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.Name" type="text" class="form-control" placeholder="نام گروه" />
</div>
<div class="col-md-12">
<input dir="ltr" style="text-align:center;margin-bottom:10px" @bind-value="@model.Info" type="text" class="form-control" placeholder="توضیحات" />
</div>
<div class="col-md-12" style="display: flex;flex-wrap: nowrap;align-items: baseline;">
<InputFile type="file" OnChange="OnFileChange" accept=".png" style="margin-bottom:10px" />
@if (model.img != null && model.img.Length > 0)
{
<Image src="@GetImageSource()" Class="rounded mx-auto d-block" height="25" width="25" alt="Uploaded Image" />
}
</div>
<Button Loading=loading LoadingText="در حال ذخیره اطلاعات..." Color="ButtonColor.Warning" @onclick="NewItem"> ویرایش </Button>
</div>
@code {
[Parameter] public GroupDto model { get; set; }
[Parameter] public EventCallback OnMultipleOfThree { get; set; }
public bool loading { get; set; } = false;
}
@functions {
async Task NewItem()
{
if (!string.IsNullOrEmpty(model.Name))
{
loading = true;
if (await groupService.UpdateGroup(model))
{
loading = false;
await OnMultipleOfThree.InvokeAsync();
}
loading = false;
}
}
private async Task OnFileChange(InputFileChangeEventArgs e)
{
var file = e.File;
using (var memoryStream = new MemoryStream())
{
await file.OpenReadStream().CopyToAsync(memoryStream);
model.img = memoryStream.ToArray();
}
}
private string GetImageSource()
{
if (model.img != null)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(model.img)}";
}
return string.Empty;
}
}

View File

@@ -0,0 +1,74 @@
@using Hushian.Application.Dtos
@using HushianWebApp.Service
@inject GroupService groupService;
@if (!Spinnervisible)
{
<div class="row">
<div class="col-md-12 col-sm-12" style="margin-bottom:15px">
<AutoComplete @bind-Value="GroupName"
TItem="GroupDto"
DataProvider="DataProvider"
PropertyName="Name"
Placeholder="جستجو در گروه ها..."
OnChanged="(GroupDto group) => OnAutoCompleteChanged(group)" />
</div>
</div>
<SortableList TItem="GroupDto"
Data="Groups"
Context="item"
AllowSorting="false">
<ItemTemplate>
@item.Name
<Tooltip Title="گرفتن دسترسی" role="button">
<Icon Name="IconName.Trash3" @onclick="async()=>{await UnJoin(item);}"></Icon>
</Tooltip>
</ItemTemplate>
</SortableList>
}
<div class="d-flex justify-content-center">
<Spinner Type="SpinnerType.Dots" Class="me-3" Color="SpinnerColor.Success" Visible="@Spinnervisible" />
</div>
@code {
private string? GroupName;
private bool Spinnervisible = false;
[Parameter] public string ExperID { get; set; }
public List<GroupDto> Groups { get; set; }
= new();
public List<GroupDto> CoGroups { get; set; }
= new();
protected override async Task OnParametersSetAsync()
{
Spinnervisible = true;
Groups = await groupService.GetGroupsFromExperID(ExperID);
Spinnervisible = false;
await base.OnParametersSetAsync();
}
}
@functions {
private async Task<AutoCompleteDataProviderResult<GroupDto>> DataProvider(AutoCompleteDataProviderRequest<GroupDto> request)
{
CoGroups = await groupService.GetGroupsCompany();
return await Task.FromResult(new AutoCompleteDataProviderResult<GroupDto> { Data = CoGroups.Where(w=>w.Name.Contains(request.Filter.Value)), TotalCount = CoGroups.Count() });
}
private async Task OnAutoCompleteChanged(GroupDto group)
{
Spinnervisible = true;
if (group != null
&& !Groups.Any(a => a.ID == group.ID)
&& await groupService.JoinExperToGroup(group.ID, ExperID))
Groups.Add(group);
Spinnervisible = false;
}
async Task UnJoin(GroupDto group)
{
Spinnervisible = true;
if (group != null && await groupService.UnJoinExperToGroup(group.ID, ExperID))
Groups.Remove(group);
Spinnervisible = false;
}
}

View File

@@ -0,0 +1,41 @@
@using Hushian.Application.Dtos
<small>پیام های اخیر شما ...</small>
<div class="row">
@foreach (var item in Conversations)
{
<div class="col-sm-3">
<Card>
<CardBody>
<CardText>@GetTitleCon(item.Title)</CardText>
<Button Color="ButtonColor.Primary" @onclick="async()=>await OnMultipleOfThree.InvokeAsync(item.ID)" Type="ButtonType.Link">Go somewhere</Button>
</CardBody>
<ul class="list-group list-group-flush">
<li class="list-group-item">@item.ExperFullName (@item.Cdate item.Ctime)</li>
</ul>
@if (item.status == Hushian.Enums.ConversationStatus.InProgress && item.NoReadCount > 0)
{
<Badge Color="BadgeColor.Danger"
Position="Position.Absolute"
Placement="BadgePlacement.TopLeft"
IndicatorType="BadgeIndicatorType.RoundedPill"
VisuallyHiddenText="unread messages">@item.NoReadCount </Badge>
}
}
</Card>
</div>
}
</div>
@code {
[Parameter] public EventCallback<int> OnMultipleOfThree { get; set; }
[Parameter] public List<ConversationDto> Conversations { get; set; }
string GetTitleCon(string str)
{
if (str.Length > 15) return str.Substring(0, 15) + "...";
return str;
}
}

View File

@@ -0,0 +1,128 @@
@using Common.Dtos.User
@using Common.Enums
@using HushianWebApp.Service
@inject VerificationService verificationService;
@inject NavigationManager navigation;
<div class="header-form">
<img src="/before/assets/images/Hushian-logo.svg" width="133" alt="Hushian" class="lg:hidden mb-3">
<span>@Title</span>
</div>
<p></p>
@if (type == VerificationCodeType.ForgetPassword)
{
<div style="display: flex; justify-content: space-between">
<TextInput @bind-value=code type="text" name="code" style="text-align:center;margin-left: 10px;" placeholder="کد ارسال شده" required="required" />
</div>
<div style="display: flex; justify-content: space-between">
<TextInput @bind-value=Value type="password" name="Value" style="text-align:center;margin-top: 10px;;margin-left: 10px" placeholder="کلمه عبور جدید" required="required" />
<TextInput @bind-value=ReValue type="password" name="ReValue" style="text-align:center;margin-top: 10px;;margin-left: 10px" placeholder="تکرار کلمه عبور جدید" required="required" />
<Button Loading=loading LoadingText="ارسال درخواست" @onclick=onClick Color="ButtonColor.Success" style="margin-top: 10px;;margin-left: 10px"> احراز </Button>
</div>
}
else
{
<div style="display: flex; justify-content: space-between">
<TextInput @bind-value=code type="text" name="code" style="text-align:center;margin-left: 10px;" placeholder="کد ارسال شده" required="required" />
<Button Loading=loading LoadingText="ارسال درخواست" @onclick=onClick Color="ButtonColor.Success"> احراز </Button>
</div>
}
<div style="display: flex; justify-content: space-between">
<Button Disabled=Disabledresendmsg @onclick=onClickresend Color="ButtonColor.Link" style="font-size: small;font-weight: normal;text-decoration: none;"> @resendmsg </Button>
</div>
@code {
[Parameter]
// PhoneNumberConfirmed
public VerificationCodeType type { get; set; }
[Parameter]
public string sendValue { get; set; }
[Parameter]
public int? ID { get; set; }
public string? code { get; set; }
[Parameter] public string? Title { get; set; }
[Inject] protected ToastService ToastService { get; set; } = default!;
[Parameter] public EventCallback<VerificationCodeType> OnMultipleOfThree { get; set; }
public string? Value { get; set; }
public string? ReValue { get; set; }
bool loading = false;
string resendmsg = "ارسال مجدد";
bool Disabledresendmsg = false;
}
@functions {
protected override async Task OnParametersSetAsync()
{
resendmsg = "در حال ارسال کد احراز ...";
Disabledresendmsg = true;
if (ID == 0)
ID = await verificationService.FromUserName(sendValue, type);
ToastService.Notify(new(ToastType.Info, $"کد احراز به کاربری '{sendValue}' ارسال شد"));
resendmsg = "ارسال مجدد";
Disabledresendmsg = false;
await base.OnParametersSetAsync();
}
async Task onClickresend()
{
resendmsg = "در حال ارسال مجدد کد احراز ...";
Disabledresendmsg = true;
if (ID == 0)
ID = await verificationService.FromUserName(sendValue, type);
else
{
await verificationService.ReSendCode(ID.Value);
}
ToastService.Notify(new(ToastType.Info, $"کد احراز به کاربری '{sendValue}' ارسال شد"));
resendmsg = "ارسال مجدد";
Disabledresendmsg = false;
}
async Task onClick()
{
if (string.IsNullOrEmpty(code))
{
ToastService.Notify(new(ToastType.Warning, $"کد ارسالی را وارد کنید"));
return;
}
if (type == VerificationCodeType.ForgetPassword)
{
if (string.IsNullOrEmpty(Value) || string.IsNullOrEmpty(ReValue))
{
ToastService.Notify(new(ToastType.Warning, $"کلمه عبور جدید را مشخص کنید"));
return;
}
else
{
if (Value != ReValue)
{ ToastService.Notify(new(ToastType.Warning, $"کلمه عبور جدید و تکرار متفاوت هستند"));
return;}
}
}
loading = true;
if (await verificationService.ConfirmedCode(new ConfirmedCodeDto()
{ code = code, codeType = type, Id = ID.Value, value = Value }))
{
ToastService.Notify(new(ToastType.Success, $"احراز با موفقیت انجام شد برای ادامه ورود کنید"));
await OnMultipleOfThree.InvokeAsync(type);
}
loading = false;
}
}

View File

@@ -0,0 +1,17 @@
using Hushian.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos
{
public class ADDConversationDto
{
public string Question { get; set; }
public int? GroupID { get; set; }
public int? CompanyID { get; set; }
public string? ExperID { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using Hushian.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos
{
public class ADDConversationItemDto
{
public int ConversationID { get; set; }
//public string? ExperID { get; set; }
// public ConversationType Type { get; set; }
public string text { get; set; }
public string? FileName { get; set; }
public string? FileType { get; set; }
public byte[]? FileContent { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos
{
public class ADDGroupDto
{
public string Name { get; set; }
public byte[]? img { get; set; }
public string? Info { get; set; }
public bool Available { get; set; } = true;
}
}

View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Common.Dtos
{
public class BaseDto
{
public int Id { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos.Company
{
public class AddCompanyDto
{
public string Fullname { get; set; }
public string Info { get; set; }
// public string? UserIDManager { get; set; }
public string? Phone { get; set; }
public string? WebSite { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos.Company
{
public class CompanyDto
{
public int ID { get; set; }
public string Fullname { get; set; }
public string Info { get; set; }
public byte[]? img { get; set; }
public string? Phone { get; set; }
public string? WebSite { get; set; }
public string? Email { get; set; }
public bool Available { get; set; }
public bool allowBot { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos.Company
{
public class ContentInfoDto
{
public int ID { get; set; }
public string Content { get; set; }
}
}

View File

@@ -0,0 +1,28 @@
using Hushian.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos
{
public class ConversationDto
{
public int ID { get; set; }
public string Title { get; set; }
public ConversationStatus status { get; set; }
public int? GroupID { get; set; }
//
public string? GroupName { get; set; }
public string UserID { get; set; }
//
public string? UserFullName { get; set; }
public string? ExperID { get; set; }
//
public string? ExperFullName { get; set; }
public string Cdate { get; set; }
public string Ctime { get; set; }
public int NoReadCount { get; set; } = 0;
}
}

View File

@@ -0,0 +1,23 @@
using Hushian.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos
{
public class ConversationItemDto
{
public int ID { get; set; }
public int ConversationID { get; set; }
public string? ExperID { get; set; }
public bool IsRead { get; set; } = false;
public string ExperName { get; set; }
public ConversationType Type { get; set; }
public string text { get; set; }
public string FileName { get; set; }
public string FileType { get; set; }
public byte[] FileContent { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos
{
public class GroupDto
{
public int ID { get; set; }
public string Name { get; set; }
public byte[]? img { get; set; }
public string? Info { get; set; }
public bool Available { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos
{
public class IdName<T>
{
public T ID { get; set; }
public string Title { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.Identity
{
public class RoleDto
{
public RoleDto(string id, string name, string normalizedName)
{
Id = id;
Name = name;
NormalizedName = normalizedName;
}
public string Id { get; set; }
public string Name { get; set; }
public string NormalizedName { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using Common.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.Identity
{
public class VerificationDto
{
public string UserId { get; set; }
public VerificationCodeType Type { get; set; }
public string Code { get; set; }
public string ToMobile { get; set; }
public string? Token { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos
{
public class PagingDto<T>
{
public PagingDto(int RowCount, int pageCount, List<T> list)
{
this.RowCount = RowCount;
this.list = list;
PageCount = pageCount;
}
public int RowCount { get; set; }
public int PageCount { get; set; }
public List<T> list { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using Hushian.Application.Dtos.Company;
using Common.Dtos.User;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Application.Dtos
{
public class RegistrationDto
{
public AddUserDto User { get; set; }
public AddCompanyDto Company { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using Common.Enums.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class AddUserDto
{
public string Id { get; set; } = Guid.NewGuid().ToString();
public string UserName { get; set; }
public string? DefultRoleID { get; set; }
public string PassWord { get; set; }
public string FullName { get; set; }
public string? Email { get; set; }
public string PhoneNumber { get; set; }
public byte[]? img { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class ChangeIsActieUserDto
{
public string UserName { get; set; }
public bool IsActive { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class ChangePasswordDto
{
public string UserName { get; set; }
public string NewPassword { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class ChangePasswordFromUserDto
{
public string UserName { get; set; }
public string OldPassword { get; set; }
public string NewPassword { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class ChangeRoleUserDto
{
public string UserName { get; set; }
public string RoleID { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using Common.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class ConfirmedCodeDto
{
public int Id { get; set; }
public string code { get; set; }
public VerificationCodeType codeType { get; set; }
public string? value { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class EditUserDto
{
public string UserName { get; set; }
public string FullName { get; set; }
public string? Email { get; set; }
public string? PhoneNumber { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class EditUserFromUserDto
{
//key
public string UserName { get; set; }
public string? FullName { get; set; }
public string? Email { get; set; }
public byte[]? img { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos.User
{
public class ReadUserDto
{
public string UserName { get; set; }
public string Role { get; set; } = "";
public string FullName { get; set; }
public string? Email { get; set; }
public string? PhoneNumber { get; set; }
public bool IsActive { get; set; }
}
}

View File

@@ -0,0 +1,14 @@

namespace Hushian.Application.Dtos
{
public class HushianUserDto
{
public string UserID { get; set; }
public string UserName { get; set; }
public string FullName { get; set; }
public byte[]? img { get; set; }
public bool Available { get; set; } = true;
public string? Email { get; set; }
public string PhoneNumber { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Dtos
{
public class condination
{
public string PropName { get; set; }
public string Operation { get; set; }
public object? Value { get; set; }
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Enums
{
public enum ConversationStatus
{
InProgress, Finished
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Hushian.Enums
{
public enum ConversationType
{
EU=1, UE=2
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Enums.Identity
{
public enum Cors
{
MMRBNJD, Moadiran, Hushian
}
}

View File

@@ -0,0 +1,10 @@
namespace Common.Enums
{
public enum VerificationCodeType
{
PhoneNumberConfirmed,
ForgetPassword,
ChangeMobile,
Login
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Common.Models.Identity
{
public class AuthRequest
{
public AuthRequest(string username, string password)
{
Username = username;
Password = password;
}
public string Username { get; set; }
public string Password { get; set; }
}
public class AuthRequestFromMobile
{
public string Mobile { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Common.Models.Identity
{
public class AuthResponse
{
public string Id { get; set; }
public string UserName { get; set; }
public string Fullname { get; set; }
public List <string>? Roles { get; set; }
public string Token { get; set; }
public byte[]? img { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Common.Models
{
public class ResponseBase<T>
{
public T? Value { get; set; }
public bool Success { get; set; }=false;
public List<string> Errors { get; set; }=new List<string>();
}
}

View File

@@ -0,0 +1,8 @@
namespace HushianWebApp.Data.Models
{
public class WindowSize
{
public int Width { get; set; }
public int Height { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Common.Models.ai.openAi
{
public class RequestModel
{
public string model { get; set; }
public string question { get; set; }
public string Context { get; set; }
}
}

View File

@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Data\**" />
<Content Remove="Data\**" />
<EmbeddedResource Remove="Data\**" />
<None Remove="Data\**" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Blazor.Bootstrap" Version="3.3.1" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="9.0.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="9.0.2" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Common\Common.csproj" />
</ItemGroup>
<ItemGroup>
<ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,29 @@
@inherits LayoutComponentBase
<main class="main w-full lg:h-screen min-[500px]:py-6 bg-main-500 overflow-auto">
<Toasts class="p-3" AutoHide="true" Delay="4000" Placement="ToastsPlacement.TopRight" />
<div class="container">
<div class="right-side">
@Body
</div>
<div class="left-side" style="align-self: center;">
<div>
<img src="/before/assets/images/Hushian-logo.svg" alt="Hushian" class="hidden lg:block">
</div>
<div class="text-right py-5">
<p class="font-bold text-slate-700 mb-2">نکات امنیتی</p>
<ul class=" text-slate-500 text-xs space-y-3 list-disc">
<li class="mr-4">
هرگز اطلاعات حساب کاربری (نام کاربری و کلمه عبور) خود را در اختیار دیگران قرار ندهید.
</li>
<li class="mr-4">
پس از اتمام کار با سامانه، حتما بر روی دکمه خروج از سامانه کلیک نمایید.
</li>
</ul>
</div>
</div>
</div>
</main>

View File

@@ -0,0 +1,11 @@
@inherits LayoutComponentBase
<main class="main w-full lg:h-screen min-[500px]:py-6 bg-main-500 overflow-auto">
<div class="container">
@Body
</div>
</main>

View File

@@ -0,0 +1,243 @@
@inherits LayoutComponentBase
@using Common.Dtos.User
@using HushianWebApp.Components
@using HushianWebApp.Pages
@using HushianWebApp.Pages.Manage
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject NavigationManager NavigationManager
@inject ILocalStorageService localStorageService;
@inject AuthService authService;
@inject BaseController baseController;
@inject UserService userService;
<Modal @ref="modal" />
<Toasts class="p-3" AutoHide="true" Delay="4000" Placement="ToastsPlacement.TopRight" />
<div class="bb-page">
<Sidebar @ref="sidebar"
Href="/"
IconName="IconName.BootstrapFill"
Title="هوشــیان"
BadgeText="v1.3.1"
ImageSrc="/before/assets/images/hushian-logo.svg"
DataProvider="SidebarDataProvider"
Width="230"
WidthUnit="Unit.Px" />
<main>
<div class="d-flex align-items-center justify-content-end">
<div class="text-white text-end d-flex flex-column justify-content-center align-items-end mx-2">
<div style="color: black;" class="fw-bold">@Fullname</div>
<h6 style="color: black;">@TitleRole</h6>
</div>
@if (img != null && img.Length > 0)
{
<Image Src=@GetImageSource() Class="rounded" Alt="placeholder" @onclick="EditCurrentUser"
Style="height: 30px;cursor:pointer;margin-left:10px" />
}
else
{
<Icon Name="IconName.People" Size="IconSize.x3" Style="height: 30px;cursor:pointer;margin-left:10px" @onclick="EditCurrentUser" />
}
<Button Color="ButtonColor.Danger" Size="ButtonSize.Small"
@onclick=OnCliclLogout Style="margin-left:10px">
<Icon Name="IconName.DoorOpen" /> خروج
</Button>
</div>
<article class="content px-4">
<div class="py-2">
@if (isonline)
{
@if (isAuthorizedCompanyUser)
{
@Body
}
else
{
<p>دسترسی به شرکت برای شما یافت نشد</p>
}
}
</div>
</article>
</main>
</div>
@code {
private Modal modal = default!;
public string Info { get; set; } = "";
private string SelectedMenu = "page2";
public string Username { get; set; }
public string Fullname { get; set; }
public byte[]? img { get; set; }
public List<string> Roles { get; set; } = new();
bool isonline = false;
bool isAuthorizedCompanyUser = false;
public string TitleRole { get; set; } = "";
protected override async Task OnInitializedAsync()
{
await CheckOnline();
if (isonline)
{
//Roles = await localStorageService.GetItem<List<string>>("Role");
Username = await localStorageService.GetItem<string>("Username");
Fullname = await localStorageService.GetItem<string>("Fullname");
string UserID = await localStorageService.GetItem<string>("UserID");
img = await localStorageService.GetItem<byte[]?>("img");
}
TitleRole = Roles.Any(a => a == "HushianManagerCompany") ? "مدیر" : "کارشناس";
isAuthorizedCompanyUser = Roles.Contains("HushianManagerCompany") || (Roles.Contains("HushianExperCompany") && await userService.CheckAvailableExperInCompany());
string route = NavigationManager.Uri.Replace(NavigationManager.BaseUri, "").ToLower();
if (route.Length > 0)
{
SelectedMenu = route switch
{
"conversation" => "page2",
"usermanagement" => "page3",
"groupmanagement" => "page4",
"settings" => "page5",
_ => "page1"
};
}
else SelectedMenu = "page1";
await base.OnInitializedAsync();
}
async Task OnCliclLogout()
{
await authService.Logout();
NavigationManager.NavigateTo("/login");
}
private async Task ChangePasword()
{
var parameters = new Dictionary<string, object>();
parameters.Add("Username", Username);
await modal.ShowAsync<ChangePassWordComponent>(title: "تغییر رمز عبور", parameters: parameters);
}
private async Task Settings()
{
var parameters = new Dictionary<string, object>();
await modal.ShowAsync<Settings>(title: "تنظیمات شرکت", parameters: parameters);
}
private async Task EditCurrentUser()
{
var parameters = new Dictionary<string, object>();
parameters.Add("OnMultipleOfThree", EventCallback.Factory.Create<EditUserFromUserDto>(this, CallBack));
await modal.ShowAsync<EditUserYourselfComponent>(title: $"ویرایش کاربر {Username}", parameters: parameters);
}
async Task CallBack(EditUserFromUserDto edit)
{
await modal.HideAsync();
img = edit.img;
await localStorageService.RemoveItem("img");
await localStorageService.SetItem("img", img);
Fullname = edit.FullName;
await localStorageService.RemoveItem("Fullname");
await localStorageService.SetItem("Fullname", Fullname);
}
private void SetActiveMenu(string menu)
{
SelectedMenu = menu;
if (menu == "page1") NavigationManager.NavigateTo("/");
else if (menu == "page2") NavigationManager.NavigateTo("/Conversation");
else if (menu == "page3") NavigationManager.NavigateTo("/UserManagement");
else if (menu == "page4") NavigationManager.NavigateTo("/GroupManagement");
else if (menu == "page5") NavigationManager.NavigateTo("/Settings");
}
async Task CheckOnline()
{
var token = await localStorageService.GetItem<string>("key");
if (string.IsNullOrEmpty(token))
{
isonline = false;
NavigationManager.NavigateTo("/login");
}
else
{
await baseController.RemoveToken();
await baseController.SetToken(token);
if (!await authService.IsOnline())
{
await baseController.RemoveToken();
isonline = false;
NavigationManager.NavigateTo("/login");
}
else
{
Roles = await localStorageService.GetItem<List<string>>("Role");
if (Roles.Count == 1 && Roles.Contains("HushianUserCompany"))
{
isonline = false;
NavigationManager.NavigateTo("/NotFound");
}
else
isonline = true;
}
}
}
private string GetImageSource()
{
if (img != null && img.Length > 0)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(img)}";
}
return "/defprofile.jpg";
}
}
@code {
Sidebar sidebar = default!;
IEnumerable<NavItem>? navItems;
private async Task<SidebarDataProviderResult> SidebarDataProvider(SidebarDataProviderRequest request)
{
if (navItems is null)
navItems = GetNavItems();
return await Task.FromResult(request.ApplyTo(navItems));
}
private IEnumerable<NavItem> GetNavItems()
{
navItems = new List<NavItem>
{
// new NavItem { Href = "/", IconName = IconName.HouseDoorFill, Text = "خانه"},
// new NavItem { Href = "/Conversation", IconName = IconName.ChatText, Text = " گفتگو ها"},
new NavItem { Href = "/", IconName = IconName.ChatText, Text = " گفتگو ها"},
new NavItem { Href = "/UserManagement", IconName = IconName.PersonBoundingBox, Text = " مدیریت کاربران"},
new NavItem { Href = "/GroupManagement", IconName = IconName.Grid1X2, Text = " مدیریت گروه ها"},
new NavItem { Href = "/Settings", IconName = IconName.Hammer, Text = " تنظیمات"},
};
return navItems;
}
private void ToggleSidebar() => sidebar.ToggleSidebar();
}

View File

@@ -0,0 +1,77 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}
.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}
.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}
.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}
@media (min-width: 641px) {
.page {
flex-direction: row;
}
.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}
.top-row {
position: sticky;
top: 0;
z-index: 1;
}
.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}
.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}

View File

@@ -0,0 +1,55 @@
<div class="bb-page">
<main>
<div class="bb-top-row px-4 d-flex justify-content-between">
<Icon Name="IconName.List" role="button" @onclick="ToggleSidebar" />
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
<div class="py-2">Page content goes here</div>
</article>
</main>
</div>
@code {
Sidebar sidebar = default!;
IEnumerable<NavItem>? navItems;
private async Task<SidebarDataProviderResult> SidebarDataProvider(SidebarDataProviderRequest request)
{
if (navItems is null)
navItems = GetNavItems();
return await Task.FromResult(request.ApplyTo(navItems));
}
private IEnumerable<NavItem> GetNavItems()
{
navItems = new List<NavItem>
{
new NavItem { Id = "1", Href = "/getting-started", IconName = IconName.HouseDoorFill, Text = "Getting Started"},
new NavItem { Id = "2", IconName = IconName.LayoutSidebarInset, Text = "Content", IconColor = IconColor.Primary },
new NavItem { Id = "3", Href = "/icons", IconName = IconName.PersonSquare, Text = "Icons", ParentId="2"},
new NavItem { Id = "4", IconName = IconName.ExclamationTriangleFill, Text = "Components", IconColor = IconColor.Success },
new NavItem { Id = "5", Href = "/alerts", IconName = IconName.CheckCircleFill, Text = "Alerts", ParentId="4"},
new NavItem { Id = "6", Href = "/breadcrumb", IconName = IconName.SegmentedNav, Text = "Breadcrumb", ParentId="4"},
new NavItem { Id = "7", Href = "/sidebar", IconName = IconName.LayoutSidebarInset, Text = "Sidebar", ParentId="4"},
new NavItem { Id = "8", IconName = IconName.WindowPlus, Text = "Forms", IconColor = IconColor.Danger },
new NavItem { Id = "9", Href = "/autocomplete", IconName = IconName.InputCursorText, Text = "Auto Complete", ParentId="8"},
new NavItem { Id = "10", Href = "/currency-input", IconName = IconName.CurrencyDollar, Text = "Currency Input", ParentId="8"},
new NavItem { Id = "11", Href = "/number-input", IconName = IconName.InputCursor, Text = "Number Input", ParentId="8"},
new NavItem { Id = "12", Href = "/switch", IconName = IconName.ToggleOn, Text = "Switch", ParentId="8"},
};
return navItems;
}
private void ToggleSidebar() => sidebar.ToggleSidebar();
}

View File

@@ -0,0 +1,4 @@
@inherits LayoutComponentBase
<Toasts class="p-3" AutoHide="true" Delay="4000" Placement="ToastsPlacement.TopRight" />
@Body

View File

@@ -0,0 +1,101 @@
@page "/ForgetPassword"
@layout BeforeLayout
@using Common.Enums
@using HushianWebApp.Components
@inject NavigationManager navigationManager;
<Modal @ref="modal" />
<PageTitle>هوشیان / بازیابی کلمه عبور</PageTitle>
<div class="right-side">
<div class="header-form">
<img src="/Before/assets/images/Hushian-logo.svg" width="133" alt="Hushian" class="lg:hidden mb-3">
<span>
بازیابی کلمه عبور
</span>
</div>
<div id="alert" class="gap-5 text-xs bg-red-400 bg-opacity-20 px-3 py-2 rounded-md text-start justify-start items-center text-red-600" style="display:none;">
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0.87793C12.3069 0.87793 12.6962 0.911609 13.0241 1.0307C13.7791 1.30489 14.1225 1.7131 14.5027 2.16498L14.5326 2.20051C15.6287 3.50221 17.1301 5.52401 18.8638 8.49604C21.001 12.1599 22.0535 15.2888 22.5574 17.2397L22.5658 17.2722C22.6183 17.4752 22.6807 17.7162 22.705 17.9698C22.7334 18.2669 22.7093 18.5485 22.6388 18.8651C22.571 19.1697 22.4068 19.4939 22.2702 19.7251C22.1337 19.9564 21.9291 20.2568 21.6951 20.4632C21.4621 20.6687 21.2385 20.8247 20.978 20.942C20.7521 21.0437 20.5262 21.1015 20.3486 21.1469L20.3486 21.1469L20.3188 21.1546C18.6852 21.5737 16.033 21.9999 12 21.9999C7.96696 21.9999 5.31484 21.5737 3.68119 21.1546L3.65143 21.1469C3.47377 21.1015 3.24787 21.0437 3.02198 20.942C2.76146 20.8247 2.53785 20.6687 2.3049 20.4632C2.07091 20.2568 1.86634 19.9564 1.72976 19.7251C1.59318 19.4939 1.42895 19.1697 1.36117 18.8651C1.29072 18.5485 1.26655 18.2669 1.29498 17.9698C1.31926 17.7162 1.38164 17.4752 1.43421 17.2722L1.44261 17.2397C1.94651 15.2888 2.99896 12.1599 5.13622 8.49604C6.86989 5.52401 8.37131 3.50221 9.46744 2.20051L9.49733 2.16498C9.8775 1.7131 10.2209 1.30489 10.9759 1.0307C11.3038 0.911609 11.6931 0.87793 12 0.87793ZM11.6591 2.91054C11.6576 2.91096 11.6574 2.911 11.6586 2.91056C11.5094 2.96477 11.4439 3.00963 11.3855 3.06007C11.2981 3.13551 11.2065 3.24026 10.9973 3.48875C9.97906 4.69794 8.54299 6.62512 6.86377 9.50378C4.83238 12.9862 3.84405 15.9396 3.37906 17.7399C3.31457 17.9895 3.2935 18.0808 3.28588 18.1604C3.28117 18.2096 3.27951 18.2762 3.31197 18.4241L3.31284 18.4265L3.31285 18.4265C3.3154 18.4339 3.32386 18.4583 3.34309 18.501C3.37013 18.561 3.40763 18.6332 3.45189 18.7081C3.49616 18.7831 3.5413 18.8508 3.58079 18.9035C3.6089 18.9409 3.62617 18.9601 3.63137 18.9659L3.63304 18.9678C3.75701 19.0766 3.813 19.1048 3.84312 19.1184C3.89547 19.1419 3.95816 19.1608 4.17826 19.2173C5.62402 19.5883 8.10611 19.9999 12 19.9999C15.8939 19.9999 18.376 19.5883 19.8217 19.2173C20.0418 19.1608 20.1045 19.1419 20.1569 19.1184C20.187 19.1048 20.243 19.0766 20.367 18.9678C20.3669 18.9678 20.3675 18.9672 20.3686 18.9659C20.3738 18.9601 20.3911 18.9409 20.4192 18.9035C20.4587 18.8508 20.5038 18.7831 20.5481 18.7081C20.5924 18.6332 20.6299 18.561 20.6569 18.501C20.6761 18.4582 20.6846 18.4338 20.6871 18.4265L20.688 18.4241C20.7205 18.2762 20.7188 18.2096 20.7141 18.1604C20.7065 18.0808 20.6854 17.9895 20.6209 17.7399C20.1559 15.9396 19.1676 12.9862 17.1362 9.50378C15.457 6.62512 14.0209 4.69794 13.0027 3.48875C12.7935 3.24026 12.7019 3.13551 12.6145 3.06007C12.5561 3.00963 12.4906 2.96477 12.3414 2.91056C12.3419 2.91076 12.3422 2.91086 12.3422 2.91087C12.3421 2.91088 12.3417 2.91077 12.3409 2.91054C12.3344 2.90881 12.3035 2.90049 12.2432 2.89255C12.1741 2.88346 12.0899 2.87793 12 2.87793C11.9101 2.87793 11.8259 2.88346 11.7568 2.89255C11.6965 2.90049 11.6656 2.90881 11.6591 2.91054ZM10.5 15.9999C10.5 15.4476 10.9477 14.9999 11.5 14.9999H12.5C13.0523 14.9999 13.5 15.4476 13.5 15.9999V16.9999C13.5 17.5522 13.0523 17.9999 12.5 17.9999H11.5C10.9477 17.9999 10.5 17.5522 10.5 16.9999V15.9999ZM13 6.99991C13 6.44762 12.5523 5.99991 12 5.99991C11.4477 5.99991 11 6.44762 11 6.99991V12.4999C11 13.0522 11.4477 13.4999 12 13.4999C12.5523 13.4999 13 13.0522 13 12.4999V6.99991Z" fill="currentColor"></path>
</svg>
</div>
<span id="alert-item"></span>
</div>
<div class="form">
<div class="relative group">
<label class="block mb-2 text-slate-600 font-bold" for="PhoneNumber">
شماره همراه
</label>
<div class="relative flex justify-center items-center gap-1 pl-1 group-[.form-invalid]:border-red-500 bg-slate-50 border border-slate-300 hover:border-gray-800 text-slate-900 rounded-md focus:border-gray-800 w-full dark:placeholder-slate-400 dark:text-white ">
<input style="text-align:center" @bind-value="Username" type="number" pattern="[0-9]*" inputmode="numeric" id="number" maxlength="11" placeholder="مثلا 09123456789" title="شماره همراه را وارد کنید." class="input-form hide-arrow input_vk_2" required="" data-val="true" data-val-regex="شماره همراه را به درستی وارد کنید." data-val-regex-pattern="^09\d{9}$" data-val-required="شماره همراه را وارد کنید." name="PhoneNumber">
</div>
</div>
@* <div class=" group">
<label for="dntCaptcha" class="block mb-2 text-slate-600 font-bold">
کد‌‌‌‌‌‌‌ امنیتی
</label>
<div class="dntCaptcha" id="dntCaptcha5ccc40c53c4ef8a66d86a6eed86f9b4f9eef68f37d32223cf93ed20977435372404243268"><img alt="captcha" id="dntCaptchaImg" name="dntCaptchaImg" src="DNTCaptchaImage/Show/Showc0e8.png?data=cCLkZTEwt_8WXVmTAO4YWjJh2L9TWcSpNhCtGX5pS3rJ2-w7-GF7R1E2LzPjnCwew6bizLJfDczIssUAc6tL9IgjW9K1yMH-" style="margin-bottom: 4px;"><a class="btn-refresh" data-ajax="true" data-ajax-begin="onRefreshButtonDataAjaxBegin" data-ajax-failure="onRefreshButtonDataAjaxFailure" data-ajax-method="POST" data-ajax-mode="replace-with" data-ajax-update="#dntCaptcha5ccc40c53c4ef8a66d86a6eed86f9b4f9eef68f37d32223cf93ed20977435372404243268" data-ajax-url="/DNTCaptchaImage/Refresh/Refresh?data=BxYRIFz4xqmFsaK1Qm30KNPZ-Z6isKi8rTq05ptA0iZau2dnd2tk3osy_OAzBPaUMJEGVd4EO9S-zSBm5Oh6kYj8_XXTqZx_" href="#refresh" id="dntCaptchaRefreshButton" name="dntCaptchaRefreshButton"></a><input id="DNTCaptchaText" name="DNTCaptchaText" type="hidden" value="a3-Pm8lioQSD-9vYrK5FpQ"><div class="captcha-input h-full flex-1"><input autocomplete="off" class="bg-transparent border-0 outline-none px-3 w-full rtl h-full rounded" data-required-msg="کد امنیتی را وارد کنید." data-val="true" data-val-required="کد امنیتی را وارد کنید." dir="ltr" id="DNTCaptchaInputText" name="DNTCaptchaInputText" placeholder="کد امنیتی به رقم" required="required" type="text" value=""></div><span class="field-validation-error absolute" data-valmsg-for="DNTCaptchaInputText" data-valmsg-replace="true"></span><input id="DNTCaptchaToken" name="DNTCaptchaToken" type="hidden" value="jhlOWyyDQC-XSci5nR5IgkcP-Ca0BBXCTyD6223w4ZspWodsJz8du1B7tgqQbEGFD-hiHonjTFwFrgVRkCtfZsXFCyhzXfWEOQAiDtlCBXtXXzhJsefTQboA4QSYT6LK"><script nonce="" type="text/javascript"> function onRefreshButtonDataAjaxBegin(xhr, settings) { settings.data = settings.data + '&__RequestVerificationToken=CfDJ8P2efyfpaLFHon15HCO5GnQYiHZToPLUBHxKHM5v-OWfVVFCrkkH7hvAHt3vxFR7nY2kZiSMJ87mnll7CE4tbuUwiPAqR5UQydS31Psq1H3_I9rNevGgDPB_vMDKsTKCOtg_fwejixdzpLRqngJWPVs'; } function onRefreshButtonDataAjaxFailure(xhr, status, error) { if(xhr.status === 429) alert('تعداد درخواست غیر مجاز است.'); }</script></div>
</div> *@
<div class=" space-y-2 ">
<button @onclick=onClickforgetpass class="btn-primary w-full">
ادامه
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.7071 6.29289C15.0976 6.68342 15.0976 7.31658 14.7071 7.70711L11.4042 11.0101C11.0955 11.3187 10.9071 11.5083 10.7772 11.6612C10.7167 11.7325 10.6836 11.7791 10.6651 11.809C10.6563 11.8232 10.6515 11.8325 10.6491 11.8377C10.6467 11.8427 10.6459 11.8451 10.6458 11.8455C10.6132 11.9459 10.6132 12.0541 10.6458 12.1545C10.6459 12.1549 10.6467 12.1573 10.6491 12.1623C10.6515 12.1675 10.6563 12.1768 10.6651 12.191C10.6836 12.2209 10.7167 12.2675 10.7772 12.3388C10.9071 12.4917 11.0955 12.6813 11.4042 12.9899L14.7071 16.2929C15.0976 16.6834 15.0976 17.3166 14.7071 17.7071C14.3166 18.0976 13.6834 18.0976 13.2929 17.7071L9.98997 14.4042L9.96446 14.3787C9.68931 14.1035 9.44171 13.856 9.25255 13.6331C9.04997 13.3945 8.85638 13.1193 8.7437 12.7725C8.58055 12.2704 8.58055 11.7296 8.7437 11.2275C8.85638 10.8807 9.04997 10.6055 9.25254 10.3669C9.44171 10.144 9.6893 9.89647 9.96445 9.62135C9.97293 9.61287 9.98143 9.60437 9.98997 9.59584L13.2929 6.29289C13.6834 5.90237 14.3166 5.90237 14.7071 6.29289Z" fill="currentColor"></path>
</svg>
</button>
<NavLink class="block btn-outline" href="Login">
برگشت
</NavLink>
</div>
</div>
</div>
@code {
public string Username { get; set; }
private Modal modal = default!;
[Inject] protected ToastService ToastService { get; set; } = default!;
public bool Loading { get; set; }
}
@functions {
async Task onClickforgetpass()
{
if (string.IsNullOrEmpty(Username))
{
ToastService.Notify(new(ToastType.Primary, $"برای فراموشی رمز نیاز نام کاربری /موبایل را وارد کنید"));
return;
}
Loading = true;
await forgetpass();
Loading = false;
}
async Task forgetpass()
{
var parameters = new Dictionary<string, object>();
parameters.Add("type", VerificationCodeType.ForgetPassword);
parameters.Add("sendValue", Username);
parameters.Add("ID", 0);
parameters.Add("OnMultipleOfThree", EventCallback.Factory.Create<VerificationCodeType>(this, CallBackVer));
parameters.Add("Title", "بازیابی کلمه عبور");
await modal.ShowAsync<Verification>(title: "احراز", parameters: parameters);
}
async Task CallBackVer(VerificationCodeType type)
{
await modal.HideAsync();
}
}

View File

@@ -0,0 +1,124 @@
@page "/Login"
@using Common.Enums
@using Common.Models.Identity
@using HushianWebApp.Components
@using HushianWebApp.Service
@layout BeforeLayout
<Modal @ref="modal" />
@inject AuthService auth;
@inject NavigationManager navigationManager;
<PageTitle>هوشیان / ورود بخش شرکت ها</PageTitle>
<ConfirmDialog @ref="dialog" />
<div class="header-form">
<img src="/before/assets/images/Hushian-logo.svg" width="133" alt="Hushian" class="lg:hidden mb-3">
<span>ورود</span>
<span>به هوشیان</span>
</div>
<div id="primary_form" class="form">
<div class=" group w-full">
<label for="user-name" class="block mb-2 text-slate-600 font-bold">
شماره همراه / نام کاربری
</label>
<div class="container-input">
<input style="text-align:center" type="text" @bind-value="username" id="user-name" maxlength="64" title="نام کاربری را وارد کنید." class="input-form input_vk_1" required="" data-val="true" data-val-required="شماره همراه / نام کاربری را وارد کنید." name="Username">
</div>
</div>
<div class="relative group">
<label for="password" class="block mb-2 text-slate-600 font-bold">
کلمه عبور
</label>
<div class="container-input">
<input style="text-align:center" @bind-value=Password type="password" id="password" title="کلمه عبور را وارد کنید." maxlength="36" class="input-form input_vk_2" autocomplete="off" required="" data-val="true" data-val-required="کلمه عبور را وارد کنید." name="Password">
<div class=" flex gap-1 px-1">
<div class="cursor-pointer hover:text-black hover:bg-primary hover:bg-opacity-10 rounded transition-all p-1 bg-slate-50 z-10 text-slate-500" onclick="showPassword(event, 'password')">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1364 8.4628C18.0615 5.45328 15.063 3.88257 12.0001 3.88257C8.93711 3.88257 5.93861 5.45326 3.86353 8.46277L3.8635 8.46275L3.85865 8.46991L1.17195 12.4394C0.862392 12.8968 0.982214 13.5185 1.43959 13.8281C1.89696 14.1377 2.51868 14.0178 2.82825 13.5605L5.51247 9.5946C7.25051 7.07601 9.65752 5.88257 12.0001 5.88257C14.3426 5.88257 16.7495 7.07601 18.4874 9.59458L21.172 13.5605C21.4816 14.0179 22.1033 14.1377 22.5607 13.8281C23.018 13.5185 23.1378 12.8968 22.8282 12.4394L20.1413 8.46988L20.1413 8.46986L20.1364 8.4628ZM8.5001 12.9999C8.5001 11.0669 10.0671 9.49994 12.0001 9.49994C13.9331 9.49994 15.5001 11.0669 15.5001 12.9999C15.5001 14.9329 13.9331 16.4999 12.0001 16.4999C10.0671 16.4999 8.5001 14.9329 8.5001 12.9999ZM12.0001 7.49994C8.96253 7.49994 6.5001 9.96238 6.5001 12.9999C6.5001 16.0375 8.96253 18.4999 12.0001 18.4999C15.0377 18.4999 17.5001 16.0375 17.5001 12.9999C17.5001 9.96238 15.0377 7.49994 12.0001 7.49994Z" fill="currentColor"></path>
</svg>
</div>
</div>
</div>
<NavLink href="ForgetPassword">
<div class=" cursor-pointer font-light left-0 py-2 text-end w-full text-primary hover:text-black hover:underline flex items-center justify-end">
<div>
فراموشی کلمه‌ عبور
</div>
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.7071 6.29289C15.0976 6.68342 15.0976 7.31658 14.7071 7.70711L11.4042 11.0101C11.0955 11.3187 10.9071 11.5083 10.7772 11.6612C10.7167 11.7325 10.6836 11.7791 10.6651 11.809C10.6563 11.8232 10.6515 11.8325 10.6491 11.8377C10.6467 11.8427 10.6459 11.8451 10.6458 11.8455C10.6132 11.9459 10.6132 12.0541 10.6458 12.1545C10.6459 12.1549 10.6467 12.1573 10.6491 12.1623C10.6515 12.1675 10.6563 12.1768 10.6651 12.191C10.6836 12.2209 10.7167 12.2675 10.7772 12.3388C10.9071 12.4917 11.0955 12.6813 11.4042 12.9899L14.7071 16.2929C15.0976 16.6834 15.0976 17.3166 14.7071 17.7071C14.3166 18.0976 13.6834 18.0976 13.2929 17.7071L9.98997 14.4042L9.96446 14.3787C9.68931 14.1035 9.44171 13.856 9.25255 13.6331C9.04997 13.3945 8.85638 13.1193 8.7437 12.7725C8.58055 12.2704 8.58055 11.7296 8.7437 11.2275C8.85638 10.8807 9.04997 10.6055 9.25254 10.3669C9.44171 10.144 9.6893 9.89647 9.96445 9.62135C9.97293 9.61287 9.98143 9.60437 9.98997 9.59584L13.2929 6.29289C13.6834 5.90237 14.3166 5.90237 14.7071 6.29289Z" fill="currentColor"></path>
</svg>
</div>
</NavLink>
</div>
<div class=" space-y-5 flex flex-col items-center">
<Button Loading=Loading LoadingText="در حال ورود ..." Color="ButtonColor.Primary" Type="ButtonType.Submit" @onclick=onClick class="btn-primary w-full mb-4 lg:mb-0">
ورود
</Button>
</div>
<div class=" space-y-5 flex flex-col items-center">
<NavLink class="btn btn-outline w-full mb-4 lg:mb-0" href="Register">
ثبت نام
</NavLink>
</div>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8P2efyfpaLFHon15HCO5GnTcqzVeJClceMnnP99o04SA4Jbau0j_wcgDQBvHrI3oVb7JTofciu8lxPVwkHOn85rf9-vWzZefUXIBfzQb9upg_bF2ZDxTduIs62mLs07I48u7WZpLohGSjdmJTjjcCQY">
</div>
@code {
[Inject] protected ToastService ToastService { get; set; } = default!;
private ConfirmDialog dialog = default!;
private Modal modal = default!;
public string username { get; set; }
public string Password { get; set; }
public bool Loading { get; set; }
}
@functions {
async Task onClick()
{
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(Password)) return;
Loading = true;
var msg = await auth.login(new AuthRequest(username, Password));
if (msg == "PhoneNumberNotConfirmed")
{
var confirmation = await dialog.ShowAsync(
title: "احراز کاربری",
message1: "کاربری/ موبایل شما فعال نشده برای ورود باید احراز کنید",
message2: "انجام بدیم؟");
if (!confirmation)
{
Loading = false;
return;
}
await verification();
}
else if (msg == "ok")
{
navigationManager.NavigateTo("/");
}
Loading = false;
}
async Task verification()
{
var parameters = new Dictionary<string, object>();
parameters.Add("type", VerificationCodeType.PhoneNumberConfirmed);
parameters.Add("sendValue", username);
parameters.Add("ID", 0);
parameters.Add("OnMultipleOfThree", EventCallback.Factory.Create<VerificationCodeType>(this, CallBackVer));
parameters.Add("Title", "کاربری/ موبایل شما فعال نشده برای ورود باید احراز کنید");
await modal.ShowAsync<Verification>(title: "احراز", parameters: parameters);
}
async Task CallBackVer(VerificationCodeType type)
{
await modal.HideAsync();
}
}

View File

@@ -0,0 +1,197 @@
@page "/Register"
@using Common.Enums
@using HushianWebApp.Components
@using HushianWebApp.Service
@layout BeforeLayout
@inject CompanyService companyService;
@inject NavigationManager navigationManager;
<Modal @ref="modal" />
<PageTitle>هوشیان / ثبت نام</PageTitle>
<div class="header-form">
<img src="/Before/assets/images/Hushian-logo.svg" width="133" alt="Hushian" class="lg:hidden mb-3">
<span>حساب کاربری خود را در هوشیان بسازید</span>
</div>
<div class=" flex justify-center text-start gap-2 items-center bg-yellow-300 bg-opacity-30 py-3 px-2 rounded-md text-yellow-800 text-sm">
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 0.87793C12.3069 0.87793 12.6962 0.911609 13.0241 1.0307C13.7791 1.30489 14.1225 1.7131 14.5027 2.16498L14.5326 2.20051C15.6287 3.50221 17.1301 5.52401 18.8638 8.49604C21.001 12.1599 22.0535 15.2888 22.5574 17.2397L22.5658 17.2722C22.6183 17.4752 22.6807 17.7162 22.705 17.9698C22.7334 18.2669 22.7093 18.5485 22.6388 18.8651C22.571 19.1697 22.4068 19.4939 22.2702 19.7251C22.1337 19.9564 21.9291 20.2568 21.6951 20.4632C21.4621 20.6687 21.2385 20.8247 20.978 20.942C20.7521 21.0437 20.5262 21.1015 20.3486 21.1469L20.3486 21.1469L20.3188 21.1546C18.6852 21.5737 16.033 21.9999 12 21.9999C7.96696 21.9999 5.31484 21.5737 3.68119 21.1546L3.65143 21.1469C3.47377 21.1015 3.24787 21.0437 3.02198 20.942C2.76146 20.8247 2.53785 20.6687 2.3049 20.4632C2.07091 20.2568 1.86634 19.9564 1.72976 19.7251C1.59318 19.4939 1.42895 19.1697 1.36117 18.8651C1.29072 18.5485 1.26655 18.2669 1.29498 17.9698C1.31926 17.7162 1.38164 17.4752 1.43421 17.2722L1.44261 17.2397C1.94651 15.2888 2.99896 12.1599 5.13622 8.49604C6.86989 5.52401 8.37131 3.50221 9.46744 2.20051L9.49733 2.16498C9.8775 1.7131 10.2209 1.30489 10.9759 1.0307C11.3038 0.911609 11.6931 0.87793 12 0.87793ZM11.6591 2.91054C11.6576 2.91096 11.6574 2.911 11.6586 2.91056C11.5094 2.96477 11.4439 3.00963 11.3855 3.06007C11.2981 3.13551 11.2065 3.24026 10.9973 3.48875C9.97906 4.69794 8.54299 6.62512 6.86377 9.50378C4.83238 12.9862 3.84405 15.9396 3.37906 17.7399C3.31457 17.9895 3.2935 18.0808 3.28588 18.1604C3.28117 18.2096 3.27951 18.2762 3.31197 18.4241L3.31284 18.4265L3.31285 18.4265C3.3154 18.4339 3.32386 18.4583 3.34309 18.501C3.37013 18.561 3.40763 18.6332 3.45189 18.7081C3.49616 18.7831 3.5413 18.8508 3.58079 18.9035C3.6089 18.9409 3.62617 18.9601 3.63137 18.9659L3.63304 18.9678C3.75701 19.0766 3.813 19.1048 3.84312 19.1184C3.89547 19.1419 3.95816 19.1608 4.17826 19.2173C5.62402 19.5883 8.10611 19.9999 12 19.9999C15.8939 19.9999 18.376 19.5883 19.8217 19.2173C20.0418 19.1608 20.1045 19.1419 20.1569 19.1184C20.187 19.1048 20.243 19.0766 20.367 18.9678C20.3669 18.9678 20.3675 18.9672 20.3686 18.9659C20.3738 18.9601 20.3911 18.9409 20.4192 18.9035C20.4587 18.8508 20.5038 18.7831 20.5481 18.7081C20.5924 18.6332 20.6299 18.561 20.6569 18.501C20.6761 18.4582 20.6846 18.4338 20.6871 18.4265L20.688 18.4241C20.7205 18.2762 20.7188 18.2096 20.7141 18.1604C20.7065 18.0808 20.6854 17.9895 20.6209 17.7399C20.1559 15.9396 19.1676 12.9862 17.1362 9.50378C15.457 6.62512 14.0209 4.69794 13.0027 3.48875C12.7935 3.24026 12.7019 3.13551 12.6145 3.06007C12.5561 3.00963 12.4906 2.96477 12.3414 2.91056C12.3419 2.91076 12.3422 2.91086 12.3422 2.91087C12.3421 2.91088 12.3417 2.91077 12.3409 2.91054C12.3344 2.90881 12.3035 2.90049 12.2432 2.89255C12.1741 2.88346 12.0899 2.87793 12 2.87793C11.9101 2.87793 11.8259 2.88346 11.7568 2.89255C11.6965 2.90049 11.6656 2.90881 11.6591 2.91054ZM10.5 15.9999C10.5 15.4476 10.9477 14.9999 11.5 14.9999H12.5C13.0523 14.9999 13.5 15.4476 13.5 15.9999V16.9999C13.5 17.5522 13.0523 17.9999 12.5 17.9999H11.5C10.9477 17.9999 10.5 17.5522 10.5 16.9999V15.9999ZM13 6.99991C13 6.44762 12.5523 5.99991 12 5.99991C11.4477 5.99991 11 6.44762 11 6.99991V12.4999C11 13.0522 11.4477 13.4999 12 13.4999C12.5523 13.4999 13 13.0522 13 12.4999V6.99991Z" fill="currentColor"></path>
</svg>
</div>
<div>
کاربر گرامی، لطفاً توجه فرمایید که شماره‌همراه واردشده به نام خودتان باشد .
</div>
</div>
<form id="primary_form" class="form" method="post">
<div class=" group w-full">
<label class="block mb-2 text-slate-600 font-bold" for="PhoneNumber">
شماره همراه
</label>
<div class="container-input">
<input style="text-align:center" @bind-value=PhoneNumber type="number" pattern="[0-9]*" inputmode="numeric" maxlength="11" oninput="this.value = this.value.replace(/[^0-9]/g, '')" title=" شماره همراه را وارد کنید." class="input-form input_vk_1" id="PhoneNumber" name="PhoneNumber" />
</div>
</div>
<div class=" group">
<label class="block mb-2 text-slate-600 font-bold" for="FullName">
نام کامل
</label>
<div class="container-input">
<input style="text-align:center" @bind-value=FullName type="text" title=" نام را وارد کنید." class="input-form input_vk_1" id="FullName" name="FullName" />
</div>
</div>
<div class=" group">
<label class="block mb-2 text-slate-600 font-bold" for="password">
کلمه عبور
</label>
<div class="container-input">
<input style="text-align:center" @bind-value=Password type="password" id="password" title="کلمه عبور را وارد کنید." maxlength="36" class="input-form input_vk_2" autocomplete="off" required="" data-val="true" data-val-required="کلمه عبور را وارد کنید." name="Password">
<div class=" flex gap-1 px-1">
<div class="cursor-pointer hover:text-black hover:bg-primary hover:bg-opacity-10 rounded transition-all p-1 bg-slate-50 z-10 text-slate-500" onclick="showPassword(event, 'password')">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1364 8.4628C18.0615 5.45328 15.063 3.88257 12.0001 3.88257C8.93711 3.88257 5.93861 5.45326 3.86353 8.46277L3.8635 8.46275L3.85865 8.46991L1.17195 12.4394C0.862392 12.8968 0.982214 13.5185 1.43959 13.8281C1.89696 14.1377 2.51868 14.0178 2.82825 13.5605L5.51247 9.5946C7.25051 7.07601 9.65752 5.88257 12.0001 5.88257C14.3426 5.88257 16.7495 7.07601 18.4874 9.59458L21.172 13.5605C21.4816 14.0179 22.1033 14.1377 22.5607 13.8281C23.018 13.5185 23.1378 12.8968 22.8282 12.4394L20.1413 8.46988L20.1413 8.46986L20.1364 8.4628ZM8.5001 12.9999C8.5001 11.0669 10.0671 9.49994 12.0001 9.49994C13.9331 9.49994 15.5001 11.0669 15.5001 12.9999C15.5001 14.9329 13.9331 16.4999 12.0001 16.4999C10.0671 16.4999 8.5001 14.9329 8.5001 12.9999ZM12.0001 7.49994C8.96253 7.49994 6.5001 9.96238 6.5001 12.9999C6.5001 16.0375 8.96253 18.4999 12.0001 18.4999C15.0377 18.4999 17.5001 16.0375 17.5001 12.9999C17.5001 9.96238 15.0377 7.49994 12.0001 7.49994Z" fill="currentColor"></path>
</svg>
</div>
</div>
</div>
</div>
<div class=" group">
<label class="block mb-2 text-slate-600 font-bold" for="RePassword">
تکرار کلمه عبور
</label>
<div class="container-input">
<input style="text-align:center" @bind-value=RePassword type="password" id="RePassword" title="کلمه عبور را وارد کنید." maxlength="36" class="input-form input_vk_2" autocomplete="off" required="" data-val="true" data-val-required="کلمه عبور را وارد کنید." name="RePassword">
<div class=" flex gap-1 px-1">
<div class="cursor-pointer hover:text-black hover:bg-primary hover:bg-opacity-10 rounded transition-all p-1 bg-slate-50 z-10 text-slate-500" onclick="showPassword(event, 'RePassword')">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.1364 8.4628C18.0615 5.45328 15.063 3.88257 12.0001 3.88257C8.93711 3.88257 5.93861 5.45326 3.86353 8.46277L3.8635 8.46275L3.85865 8.46991L1.17195 12.4394C0.862392 12.8968 0.982214 13.5185 1.43959 13.8281C1.89696 14.1377 2.51868 14.0178 2.82825 13.5605L5.51247 9.5946C7.25051 7.07601 9.65752 5.88257 12.0001 5.88257C14.3426 5.88257 16.7495 7.07601 18.4874 9.59458L21.172 13.5605C21.4816 14.0179 22.1033 14.1377 22.5607 13.8281C23.018 13.5185 23.1378 12.8968 22.8282 12.4394L20.1413 8.46988L20.1413 8.46986L20.1364 8.4628ZM8.5001 12.9999C8.5001 11.0669 10.0671 9.49994 12.0001 9.49994C13.9331 9.49994 15.5001 11.0669 15.5001 12.9999C15.5001 14.9329 13.9331 16.4999 12.0001 16.4999C10.0671 16.4999 8.5001 14.9329 8.5001 12.9999ZM12.0001 7.49994C8.96253 7.49994 6.5001 9.96238 6.5001 12.9999C6.5001 16.0375 8.96253 18.4999 12.0001 18.4999C15.0377 18.4999 17.5001 16.0375 17.5001 12.9999C17.5001 9.96238 15.0377 7.49994 12.0001 7.49994Z" fill="currentColor"></path>
</svg>
</div>
</div>
</div>
</div>
@* <div class=" group">
<label for="dntCaptcha" class="block mb-2 text-slate-600 font-bold">
کد‌‌‌‌‌‌‌ امنیتی
</label>
<div class="dntCaptcha" id="dntCaptchabe73dcd1e734488ad3956521836de63cfaa59c2c82a26f6b0d22258593c9caeb316264478">
<img alt="captcha" id="dntCaptchaImg" name="dntCaptchaImg"
src="@imgcap"
style="margin-bottom: 4px;">
<input id="DNTCaptchaText" name="DNTCaptchaText" type="number" @bind-value=CapUser>
</div>
</div> *@
<div class=" space-y-5 flex flex-col items-center">
<Button Loading=Loading LoadingText="منتظر بمانید" @onclick=onClick Color="ButtonColor.Success" Type="ButtonType.Submit" Class="btn-primary w-full mb-4 lg:mb-0"> ثبت نام </Button>
</div>
</form>
@code {
[Inject] protected ToastService ToastService { get; set; } = default!;
public string Orgcap { get; set; } = "";
public string imgcap { get; set; } = "";
public string CapUser { get; set; }
private Modal modal = default!;
public bool Loading { get; set; }
public string FullName { get; set; }
public string Password { get; set; }
public string RePassword { get; set; }
//mobile
public string PhoneNumber { get; set; }
public string? Email { get { return $"{PhoneNumber}@hushian.ir"; } }
public string? WebSite { get { return $"{PhoneNumber}.ir"; } }
}
@functions {
protected override async Task OnInitializedAsync()
{
Orgcap = CaptchaService.GetCaptchaWord(4);
imgcap = CaptchaService.GenerateCaptchaBase64(Orgcap);
await base.OnInitializedAsync();
}
async Task onClick()
{
//-----------validate
if (string.IsNullOrEmpty(FullName))
{
ToastService.Notify(new ToastMessage(ToastType.Danger, "نام نمی تواند خالی باشد"));
return;
}
if (FullName.Length < 5)
{
ToastService.Notify(new ToastMessage(ToastType.Danger, "نام را کامل وارد کنید"));
return;
}
if (Password.Length < 5)
{
ToastService.Notify(new ToastMessage(ToastType.Danger, "کلمه عبور باید بیشتر از 4کاراکتر باشد"));
return;
}
if (Password != RePassword)
{
ToastService.Notify(new ToastMessage(ToastType.Danger, "کلمه عبور و تکرار آن یکسان نیست"));
return;
}
if (!PhoneNumber.StartsWith("09") || PhoneNumber.Length!=11)
{
ToastService.Notify(new ToastMessage(ToastType.Danger, "فرمت موبایل صحیح نمی باشد"));
return;
}
if (!string.IsNullOrEmpty(Email) && (!Email.Contains("@") || !Email.Contains(".") || Email.Length < 4))
{
ToastService.Notify(new ToastMessage(ToastType.Danger, "فرمت ایمیل صحیح نمی باشد"));
return;
}
if (!string.IsNullOrEmpty(WebSite) && (!WebSite.Contains(".") || WebSite.Length < 4))
{
ToastService.Notify(new ToastMessage(ToastType.Danger, "فرمت وب سایت صحیح نمی باشد"));
return;
}
//-------------------
Loading = true;
var ID = await companyService.RegisterCompany(new Hushian.Application.Dtos.RegistrationDto()
{
Company = new()
{
Fullname = FullName,
Info = "" ,
WebSite = WebSite
},
User = new()
{
Email = Email,
FullName = FullName,
PhoneNumber = PhoneNumber,
UserName = PhoneNumber,
PassWord = Password
}
});
Loading = false;
if (ID > 0)
{
var parameters = new Dictionary<string, object>();
parameters.Add("type", VerificationCodeType.PhoneNumberConfirmed);
parameters.Add("sendValue", PhoneNumber);
parameters.Add("ID", ID);
parameters.Add("Title", "ثبت نام با موفقیت انجام شد برای استفاده کاربری را احذار کنید");
parameters.Add("OnMultipleOfThree", EventCallback.Factory.Create<VerificationCodeType>(this, CallBackVer));
await modal.ShowAsync<Verification>(title: "احراز", parameters: parameters);
}
}
async Task CallBackVer(VerificationCodeType type)
{
await modal.HideAsync();
navigationManager.NavigateTo("Login");
}
}

View File

@@ -0,0 +1,424 @@
@page "/Conversation"
@page "/"
@inject IJSRuntime JS
@using Hushian.Application.Dtos
@using HushianWebApp.Data.Models
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject ILocalStorageService localStorageService;
@inject NavigationManager navigationManager;
@inject ConversationService conversationService;
<Modal @ref="modal" Title="@SelectedChatUserName" UseStaticBackdrop="true" CloseOnEscape="false">
<BodyTemplate>
@Content
</BodyTemplate>
</Modal>
<div class="container-fluid">
<div class="row" style="height:85vh">
<!-- Sidebar (A) -->
<div class="col-md-3 bg-light d-flex flex-column p-2 rounded-end" id="A">
<!-- A1: Header -->
<div class="border mb-2 p-2" id="A1">
گفتگو های اخیر
</div>
<!-- A2: Buttons -->
<div class="d-flex justify-content-between mb-2" id="A2">
<!-- Inbox1 -->
<Button Outline="@isSelectedInbox1" Type="ButtonType.Link" @onclick="async()=>{await OnclickInbox(1);}" Size=ButtonSize.ExtraSmall Color="ButtonColor.Secondary">
پیام های آمده <Badge Color="BadgeColor.Warning">@countInbox1</Badge>
</Button>
<!-- Inbox2 -->
<Button Outline="@isSelectedInbox2" Type="ButtonType.Link" @onclick="async()=>{await OnclickInbox(2);}" Size=ButtonSize.ExtraSmall Color="ButtonColor.Secondary">
پیام های من <Badge Color="BadgeColor.Warning">@countInbox2</Badge>
</Button>
<!-- Inbox3 -->
<Button Outline="@isSelectedInbox3" Type="ButtonType.Link" @onclick="async()=>{await OnclickInbox(3);}" Size=ButtonSize.ExtraSmall Color="ButtonColor.Secondary">
پیام های بسته
</Button>
</div>
<!-- A3: Chat list -->
<div class="flex-fill border p-2 overflow-auto" id="A3" style="height: 300px; overflow-y: auto;">
<Spinner Class="me-3" Type="SpinnerType.Dots" Color="SpinnerColor.Primary" Visible="@convloading" Size="SpinnerSize.Small" />
@if (isSelectedInbox1)
{
@foreach (var item in Inbox1Items)
{
<div class="d-flex align-items-center p-3 border-bottom message-item hover-bg"
style="cursor: pointer; margin-top: -10px;margin-bottom: -10px;" @onclick="async()=>await onClickSelectedCon(1,item)">
<div class="flex-grow-1">
<div class="d-flex justify-content-between">
<strong>@item.UserFullName</strong>
<small class="text-muted">@item.Cdate</small>
<small class="text-muted">@item.Ctime</small>
</div>
<div class="text-muted small text-truncate">@item.Title</div>
</div>
@if (item.NoReadCount > 0)
{
<Badge Style="margin-top:25px" Color="BadgeColor.Danger">@item.NoReadCount</Badge>
}
</div>
}
}
@if (isSelectedInbox2)
{
@foreach (var item in Inbox2Items)
{
<div class="d-flex align-items-center p-3 border-bottom message-item hover-bg"
style="cursor: pointer; margin-top: -10px;margin-bottom: -10px;" @onclick="async()=>await onClickSelectedCon(2,item)">
<div class="flex-grow-1">
<div class="d-flex justify-content-between">
<strong>@item.UserFullName</strong>
<small class="text-muted">@item.Cdate</small>
<small class="text-muted">@item.Ctime</small>
</div>
<div class="text-muted small text-truncate">@item.Title</div>
</div>
@if (item.NoReadCount>0)
{
<Badge Style="margin-top:25px" Color="BadgeColor.Danger">@item.NoReadCount</Badge>
}
</div>
}
}
@if (isSelectedInbox3)
{
@foreach (var item in Inbox3Items)
{
<div class="d-flex align-items-center p-3 border-bottom message-item hover-bg"
style="cursor: pointer; margin-top: -10px;margin-bottom: -10px;" @onclick="async()=>await onClickSelectedCon(3,item)">
<div class="flex-grow-1">
<div class="d-flex justify-content-between">
<strong>@item.UserFullName</strong>
<small class="text-muted">@item.Cdate</small>
<small class="text-muted">@item.Ctime</small>
</div>
<div class="text-muted small text-truncate">@item.Title</div>
</div>
</div>
}
}
</div>
</div>
<!-- Main Chat Section (B) -->
@if (maximomeallowsize < width)
{
@Content
}
</div>
</div>
@code {
private Modal modal = default!;
int maximomeallowsize = 700;
private int width;
private int height;
public RenderFragment Content { get; set; }
private DotNetObjectReference<Conversation>? objRef;
int colmdB = 9;
bool chatloading = false;
bool convloading = false;
public string MsgInput { get; set; }
bool isSelectedInbox1 = false;
bool isSelectedInbox2 = true;
bool isSelectedInbox3 = false;
public int countInbox1 { get { return Inbox1Items.Count(); } }
public int countInbox2 { get { return Inbox2Items.Count(); } }
public List<ConversationDto> Inbox1Items { get; set; }
= new() ;
public List<ConversationDto> Inbox2Items { get; set; }
= new();
public List<ConversationDto> Inbox3Items { get; set; }
= new();
public ConversationDto? SelectedConversation { get; set; } = null;
public List<ConversationItemDto>? SelectedConversationItems { get; set; }
= null;
public string SelectedChatUserName { get; set; } = "مهدی ربیع نژاد";
public List<string> Roles { get; set; }
public string UserID = "";
async Task OnclickInbox(int ID)
{
switch (ID)
{
case 1:
isSelectedInbox1 = true;
isSelectedInbox2 = false;
isSelectedInbox3 = false;
break;
case 2:
isSelectedInbox2 = true;
isSelectedInbox1 = false;
isSelectedInbox3 = false;
break;
case 3:
isSelectedInbox3 = true;
isSelectedInbox2 = false;
isSelectedInbox1 = false;
break;
}
SelectedConversation = null;
SelectedConversationItems = null;
}
async Task SendMsg()
{
if (!string.IsNullOrEmpty(MsgInput) && SelectedConversationItems!=null)
{
await conversationService.ADDConversationItemFromCompanySide(SelectedConversationItems[0].ConversationID, MsgInput);
SelectedConversationItems?.Add(new() { text = MsgInput, Type = Hushian.Enums.ConversationType.EU });
SelectedConversation.Title = MsgInput;
await Task.Yield();
await JS.InvokeVoidAsync("scrollToBottom", "B1");
MsgInput = string.Empty;
}
}
private async Task HandleKeyDown(KeyboardEventArgs e)
{
if (e.Key == "Enter")
{
await SendMsg();
}
}
async Task onClickSelectedCon(int InboxID,ConversationDto conversationDto)
{
// پر کردن SelectedCon
// مقدار دادن به SelectedChatUserName
chatloading = true;
SelectedChatUserName = "در حال گفتگو با "+ conversationDto.UserFullName;
SelectedConversation = conversationDto;
SelectedConversationItems = await conversationService.GetConversationItems(conversationDto.ID);
chatloading = false;
if (maximomeallowsize > width)
{
//await LoadSessionB(12);
await modal.ShowAsync();
}
}
}
@functions{
protected override async Task OnInitializedAsync()
{
Roles = await localStorageService.GetItem<List<string>>("Role");
UserID= await localStorageService.GetItem<string>("UserID");
convloading = true;
await LoadSessionB();
Inbox1Items =await conversationService.ConversationAwaitingOurResponse();
Inbox2Items =await conversationService.MyConversationIsInProgress();
Inbox3Items =await conversationService.MyConversationIsFinished();
convloading = false;
await base.OnInitializedAsync();
}
async Task IsrEADaCTION(int id)
{
if( await conversationService.MarkAsReadConversationItemAsync(id))
{
if (isSelectedInbox1) Inbox1Items = await conversationService.ConversationAwaitingOurResponse();
else if (isSelectedInbox2) Inbox2Items = await conversationService.MyConversationIsInProgress();
else
{
Inbox1Items = await conversationService.ConversationAwaitingOurResponse();
Inbox2Items = await conversationService.MyConversationIsInProgress();
}
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
objRef = DotNetObjectReference.Create(this);
await JS.InvokeVoidAsync("registerResizeCallback", objRef);
await GetWindowSize();
}
}
[JSInvokable]
public async Task OnResize()
{
await GetWindowSize();
if (maximomeallowsize < width)
{
await modal.HideAsync();
await LoadSessionB(9);
}
else await LoadSessionB(12);
StateHasChanged();
}
private async Task GetWindowSize()
{
var size = await JS.InvokeAsync<WindowSize>("getWindowSize");
width = size.Width;
height = size.Height;
}
async Task LoadSessionB(int md=9)
{
Content = @<div class="col-md-@md d-flex flex-column" id="B">
<div class="input-group">
@if (SelectedConversation!=null)
{
<p type="text" class="form-control fw-bold text-primary" style="border:none;align-self: center;" aria-describedby="basic-addon1">@SelectedChatUserName</p>
<span class="input-group-text-chat" id="basic-addon1">
@if ( SelectedConversation.status==Hushian.Enums.ConversationStatus.InProgress)
{
<Button Color="ButtonColor.Danger" Size=ButtonSize.ExtraSmall Outline="true"
@onclick="async()=>
{
if(await conversationService.ConversationIsFinish(SelectedConversation.ID))
SelectedConversation.status=Hushian.Enums.ConversationStatus.Finished;
}">
<Icon Name="IconName.Escape" /> اتمام گفتگو
</Button>
<Button Color="ButtonColor.Secondary" Size=ButtonSize.ExtraSmall Outline="true"
Class="m-3" >
<Icon Name="IconName.EnvelopeArrowUp" /> ارجاع به...
</Button>
}
else if (SelectedConversation.status == Hushian.Enums.ConversationStatus.Finished
&& (Roles.Contains("HushianManagerCompany") || SelectedConversation.ExperID == UserID))
{
<Button Color="ButtonColor.Success" Size=ButtonSize.ExtraSmall Outline="true"
@onclick="async()=>{
if(await conversationService.ConversationIsStart(SelectedConversation.ID))
SelectedConversation.status=Hushian.Enums.ConversationStatus.InProgress;
}"
}">
<Icon Name="IconName.Escape" /> باز کردن گفتگو
</Button>
}
</span>
}
</div>
<!-- B1: Chat area -->
<div class="flex-fill border p-2 overflow-auto" id="B1" style="height: 300px; overflow-y: auto;">
@if (SelectedConversationItems != null)
{
<HushianWebApp.Components.Base.ChatBubble Messages="SelectedConversationItems"
EventCallIsRead="EventCallback.Factory.Create<int>(this, IsrEADaCTION)" />
}
else
{
<div class="d-flex justify-content-center align-items-center flex-column" style="height: 80%;">
<Spinner Type="SpinnerType.Dots" Color="SpinnerColor.Primary" Visible="@chatloading" />
<p style="margin-top: 15px; font-size: 1.5rem; color: #0d6efd; font-weight: bold; text-shadow: 1px 1px 2px rgba(0,0,0,0.2);">
هوشیان
</p>
</div>
}
</div>
@if (SelectedConversation != null && SelectedConversation.status!=Hushian.Enums.ConversationStatus.Finished && SelectedConversationItems != null)
{
<!-- B2: Message input -->
<div class="border m-2 p-2 rounded d-flex align-items-center" id="B2">
<input @onkeydown="HandleKeyDown" type="text" @bind-value="MsgInput" class="form-control" style="margin-left:10px" placeholder="پیام خود را بنویسید..." />
<Button Color="ButtonColor.Dark" Outline="true" @onclick="SendMsg" ><Icon Name="IconName.AppIndicator" /> </Button>
</div>
}
</div>
;
}
}
<script>
window.getWindowSize = () => {
return {
width: window.innerWidth,
height: window.innerHeight
};
};
window.registerResizeCallback = (dotNetHelper) => {
window.onresize = () => {
dotNetHelper.invokeMethodAsync("OnResize");
};
};
window.scrollToBottom = (elementId) => {
const el = document.getElementById(elementId);
if (el) {
el.scrollTop = el.scrollHeight;
}
};
</script>
<style>
.input-group-text-chat {
display: flex;
align-items: center;
padding: .375rem .75rem;
font-size: 1rem;
font-weight: 400;
line-height: 1.5;
color: var(--bs-body-color);
text-align: center;
white-space: nowrap;
border-radius: var(--bs-border-radius);
}
</style>

View File

@@ -0,0 +1,6 @@
<h3>NotFound</h3>
@page "/NotFound"
@layout EmpLayout
@code {
}

View File

@@ -0,0 +1,7 @@
@layout EmpLayout
@page "/Unhandled"
<h3>خطای کنترل نشده</h3>
@code {
}

View File

@@ -0,0 +1,27 @@
@using Hushian.Application.Dtos
<div style="display: flex; "
dir="rtl" class="p-1 rounded w-100">
<div class="bg-green-100 border p-2 rounded text-end" dir="rtl">
سلام
</div>
<Icon Style="align-self: self-end;" Name="IconName.CheckLg" Size="IconSize.x5" />
</div>
<div style="display: flex; "
dir="rtl" class="p-1 rounded w-100">
<div class="bg-white border p-3 rounded text-end" dir="rtl">
جهت خرید در سایت در هنگام درج اطلاعات به‌خصوص کد اقتصادی دقت نمائید صورتحساب شما بر همین اساس ارسال خواهد شد در هنگام درج اطلاعات به‌خصوص کد اقتصادی دقت نمائید صورتحساب شما بر همین اساس ارسال خواهد شد ثبت نام نموده و سپس از منو فروشگاه اقدام به انتخاب محصول مورد نظر خود نمائید.<br /><br />
</div>
<Icon Style="align-self: self-end;" Name="IconName.CheckLg" Size="IconSize.x5" />
</div>
@code {
[Parameter] public List<ConversationDto> Conversations { get; set; }
[Parameter] public List<ConversationItemDto> SelectedConversationItems { get; set; }
}

View File

@@ -0,0 +1,53 @@
@inject ConversationService conversationService
@using Hushian.Application.Dtos
@using HushianWebApp.Service
@if (groups.Where(w => w.Available).Count() > 0)
{
@Content
}
@code {
[Parameter]
public List<GroupDto> groups { get; set; }
[Parameter] public EventCallback<int> OnMultipleOfThree { get; set; }
[Parameter] public int CompanyID { get; set; }
async Task onClickSelectedGroup(int ID)
{
await OnMultipleOfThree.InvokeAsync(ID);
}
RenderFragment Content { get; set; }
List<kv> ints = new();
protected override async Task OnParametersSetAsync()
{
foreach (var g in groups.Where(w => w.Available))
{
ints.Add(new()
{
k=g.ID,
v = await conversationService.GetCountQueueCompany(CompanyID, g.ID)
});
}
Content =@<div class="text-end mb-3">
<span class="badge bg-success p-2">گروه های فعال</span><br />
@foreach (var g in groups.Where(w=>w.Available))
{
<button class="btn btn-outline-secondary btn-sm mt-2"
@onclick="async()=>await onClickSelectedGroup(g.ID)" style="margin-left:5px">
@g.Name (@ints.FirstOrDefault(f=>f.k==g.ID)?.v)
</button>
}
</div>
;
await base.OnParametersSetAsync();
}
public class kv
{
public int k { get; set; }
public int v { get; set; }
}
}

View File

@@ -0,0 +1,70 @@
@using HushianWebApp.Service
@inject AuthService AuthService
<div class="text-end mb-3">
<span class="badge bg-info p-2">نیاز برای ارتباط با کارشناسان وارد شود</span>
</div>
<div class=" group w-full">
<Spinner Class="me-3" Type="SpinnerType.Dots" Color="SpinnerColor.Primary" Visible="@visible" />
@if (ID==0)
{
<label for="user-name" class="block mb-2 text-slate-600 font-bold">
شماره همراه / نام کاربری
</label>
<div class="d-flex">
<div class="container-input" style="width:150px;margin-left:5px">
<input disabled="@visible" style="text-align:center;height:30px" type="number" id="user-name" maxlength="64"
@bind-value=Username title="نام کاربری را وارد کنید." class="input-form input_vk_1" required="" data-val="true" data-val-required="شماره همراه / نام کاربری را وارد کنید." name="Username">
</div>
<Button disabled="visible" Color="ButtonColor.Primary" Type="ButtonType.Submit" @onclick="Login" class="btn-primary"
style="text-align:center;height:30px">
ورود
</Button>
</div>
}
else{
<label for="user-name" class="block mb-2 text-slate-600 font-bold">
جهت احراز کد ارسال شده را وارد کنید
</label>
<div class="d-flex">
<div class="container-input" style="width:150px;margin-left:5px">
<input style="text-align:center;height:30px" type="number" id="Code" maxlength="64"
@bind-value=Code title="کد احراز" class="input-form input_vk_1" required="" data-val="true" name="Code">
</div>
<Button Color="ButtonColor.Primary" Type="ButtonType.Submit" class="btn-dark"
style="text-align:center;height:30px" @onclick="ver">
احراز
</Button>
</div>
}
</div>
@code {
private bool visible = false;
[Parameter] public EventCallback OnMultipleOfThree { get; set; }
public string Username { get; set; }
public int ID { get; set; } = 0;
public string Code { get; set; } = string.Empty;
}
@functions{
async Task Login()
{
visible = true;
ID= await AuthService.login(Username);
visible = false;
}
async Task ver()
{
visible = true;
if(await AuthService.Verificationlogin(ID, Code))
await OnMultipleOfThree.InvokeAsync();
visible = false;
}
}

View File

@@ -0,0 +1,243 @@
@using Hushian.Application.Dtos
@using Hushian.Application.Dtos.Company
@using HushianWebApp.Components.UserPanel
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject IJSRuntime JSRuntime
@inject CompanyService companyService
@inject GroupService groupService
@inject ILocalStorageService localStorageService;
@inject AuthService authService;
@inject BaseController baseController;
@inject ConversationService conversationService
@layout UserPanelLayout
@page "/UserPanel/{CompanyID:int}"
@page "/UserPanel/{CompanyID:int}/{ConversationID:int?}"
<div class="card shadow chat-box-expanded">
<div class="card-header bg-success text-white d-flex justify-content-between align-items-center">
<span>
<strong>@CompanyName / @groups.FirstOrDefault(f => f.ID == SelectedGroup)?.Name / @SelectedConversation?.ExperFullName</strong><br />
<Badge Color="BadgeColor.Danger"
Position="Position.Absolute"
Placement="BadgePlacement.TopRight"
IndicatorType="BadgeIndicatorType.RoundedPill"
VisuallyHiddenText="status"></Badge>
<small>پاسخگویی سوالات شما هستیم</small>
</span>
<button class="btn-close btn-close-white" @onclick="CloseChat"></button>
</div>
<div class="card-body" style="max-height: 500px; overflow-y: auto; background-color: #f9f9f9;">
@if (!IsLogin)
{
<LoginComponent OnMultipleOfThree="EventCallback.Factory.Create(this, Login)" />
}
@if (IsLogin)
{
@if (SelectedConversation == null)
{
<button class="btn btn-outline-secondary btn-sm mt-2"
@onclick="()=> {SelectedGroup=0; StateHasChanged();}" style="margin-left:5px;margin-bottom:5px">
شرکت @CompanyName (@CountQueueCompany)
</button>
@GCContent
@if (Conversations.Count > 0)
{
@ConversationsContent
}
}
else
{
<ChatBoxComponent Conversations="Conversations" SelectedConversationItems="SelectedConversationItems" />
}
}
</div>
@if (IsLogin && (Conversations.Count == 0 && SelectedConversation == null) || (Conversations.Count > 0 && SelectedConversation != null && SelectedConversation.status == Hushian.Enums.ConversationStatus.InProgress))
{
<div class="card-header text-white d-flex justify-content-between align-items-center">
<input type="text" class="form-control" @bind-value="InputMessage" placeholder="پیام خود را بنویسید..." style="margin-left:10px" />
<Button Color="ButtonColor.Dark" Outline="true"><Icon Name="IconName.AppIndicator" @onclick="OnClickSendMssage" /> </Button>
</div>
}
</div>
<style>
.chat-box-expanded {
position: fixed;
bottom: 50%;
right: 50%;
transform: translate(50%, 50%);
width: 90vw;
height: 80%;
z-index: 1051;
transition: all 0.3s ease;
}
</style>
@code {
#region Parameter
[Parameter] public int CompanyID { get; set; }
[Parameter] public int? ConversationID { get; set; }
#endregion
#region Fild
public ConversationDto? SelectedConversation { get; set; } = null;
public List<ConversationDto> Conversations { get; set; } = new();
public List<ConversationItemDto>? SelectedConversationItems { get; set; } = null;
public RenderFragment GCContent { get; set; }
public RenderFragment ConversationsContent { get; set; }
List<GroupDto> groups = new List<GroupDto>();
public CompanyDto company { get; set; } = new();
int CountQueueCompany = 0;
public string CompanyName { get; set; } = "هوشیان";
public bool IsLogin { get; set; } = false;
public int? SelectedGroup { get; set; }
public string InputMessage { get; set; }
public bool Sending { get; set; } = false;
#endregion
}
@functions {
protected override async Task OnParametersSetAsync()
{
if (ConversationID.HasValue && ConversationID > 0 && Conversations.Count > 0)
await SelectedConv(ConversationID.Value);
await base.OnParametersSetAsync();
}
protected override async Task OnInitializedAsync()
{
await CheckOnline();
await base.OnInitializedAsync();
}
async Task CheckOnline()
{
var token = await localStorageService.GetItem<string>("key");
if (string.IsNullOrEmpty(token))
{
IsLogin = false;
}
else
{
await baseController.RemoveToken();
await baseController.SetToken(token);
if (!await authService.IsOnline())
{
await baseController.RemoveToken();
IsLogin = false;
}
else
{
IsLogin = true;
await Login();
}
}
}
async Task CallBackSelectedGroup(int ID)
{
SelectedGroup = ID;
StateHasChanged();
}
async Task Login()
{
// اینجا منطق ورود کاربر را پیاده‌سازی کنید
IsLogin = true;
var _company = await companyService.GetCompany(CompanyID);
if (_company == null)
{
// not Founf Company
}
else
{
if (!_company.Available)
{
// not Available Company
}
else
{
CompanyName = _company.Fullname;
company = _company;
var _groups = await groupService.GetGroupsCompany(CompanyID);
if (_groups != null)
{
CountQueueCompany = await conversationService.GetCountQueueCompany(CompanyID);
groups = _groups;
GCContent =@<GCComponent groups="groups"
CompanyID=CompanyID
OnMultipleOfThree="EventCallback.Factory.Create<int>(this, CallBackSelectedGroup)" />
;
Conversations = await conversationService.MyConversationUserSide(CompanyID);
if (Conversations.Count > 0)
ConversationsContent =@<ConversionHistoryComponent Conversations="Conversations"
OnMultipleOfThree="EventCallback.Factory.Create<int>(this, SelectedConv)" />
;
}
else
{
// ex Groups Company
}
}
}
StateHasChanged();
}
async Task SelectedConv(int ID)
{
if (Conversations.Any(f => f.ID == ID))
{
SelectedConversation = Conversations.FirstOrDefault(f => f.ID == ID);
SelectedConversationItems = await conversationService.GetConversationItems(ID);
SelectedGroup = SelectedConversation.GroupID;
StateHasChanged();
}
}
private void CloseChat()
{
// می‌توان اینجا حالت مخفی‌سازی کامپوننت را تنظیم کرد
}
private void GoBack()
{
// برگشت به منوی قبلی یا وضعیت قبلی
}
async Task OnClickSendMssage()
{
Sending = true;
if (SelectedConversation != null)
{
var item = new ADDConversationItemDto()
{
ConversationID = SelectedConversation.ID,
text = InputMessage
};
}
else
{
var Item = new ADDConversationDto()
{
CompanyID = CompanyID,
GroupID = SelectedGroup,
Question = InputMessage
};
}
Sending = false;
}
}

View File

@@ -0,0 +1,7 @@

<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.

View File

@@ -0,0 +1,153 @@
@page "/GroupManagement"
<Modal @ref="modal" />
<ConfirmDialog @ref="dialog" />
@using Hushian.Application.Dtos
@using HushianWebApp.Components
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject ILocalStorageService localStorageService;
@inject NavigationManager navigationManager;
@inject GroupService groupService;
<Button Color="ButtonColor.Success" Style="margin-bottom:10px"
@onclick="async()=>{
await modal.ShowAsync<ADDGroupComponent>(title,parameters:parameters);
}">
گروه جدید
</Button>
<Grid @ref="grid" TItem="GroupDto"
AllowSorting="true"
Class="table table-hover"
DataProvider="DataProvider"
HeaderRowCssClass="bg-primary text-white bg-opacity-75 border-bottom-0"
Responsive="true"
AllowPaging="true"
OnRowDoubleClick="OnRowClick"
AllowRowClick=true>
<GridColumns>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="GroupDto" HeaderText="تصویر گروه" >
@if (context.img?.Length!=0)
{
<Image Class="rounded-circle mx-auto d-block" src="@GetImageSource(context.img)" height="25" width="25" alt="Uploaded Image" />
}
else
{
<Icon Name="IconName.People" Size="IconSize.x5" />
}
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="GroupDto" HeaderText="شناسه گروه" SortKeySelector="item => item.ID">
@context.ID
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="GroupDto" HeaderText="نام گروه" SortKeySelector="item => item.Name">
@context.Name
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="GroupDto" HeaderText="توضیحات" >
@context.Info
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="GroupDto" HeaderText="وضعیت">
<Switch Value="@context.Available" ValueExpression="() => context.Available" ValueChanged="async(v)=>await SwitchChanged(context,v)" />
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="GroupDto" HeaderText="عملیات">
<Button Color="ButtonColor.Danger" Size="ButtonSize.ExtraSmall" @onclick="async()=>await DeleteGroup(context.ID,context.Name)"> حذف </Button>
<Button Color="ButtonColor.Warning" Size="ButtonSize.ExtraSmall" @onclick="async()=>await showGroupsComponent(context.ID,context.Name)"> کاربران </Button>
</GridColumn>
</GridColumns>
</Grid>
@code {
private ConfirmDialog dialog = default!;
Dictionary<string, object> parameters = new Dictionary<string, object>();
Grid<GroupDto> grid = default!;
private Modal modal = default!;
string title = "گروه جدید";
public List<GroupDto> list = new();
private async Task<GridDataProviderResult<GroupDto>> DataProvider(GridDataProviderRequest<GroupDto> request)
{
if(list.Count <= 0)
list = await groupService.GetGroupsCompany();
int skip = (request.PageNumber - 1) * request.PageSize;
return await Task.FromResult(request.ApplyTo(list != null ? list.Skip(skip).Take(request.PageSize).ToList() : new()));
}
protected override async Task OnInitializedAsync()
{
parameters.Add("OnMultipleOfThree", EventCallback.Factory.Create(this, CallBack));
if (!(await localStorageService.GetItem<List<string>>("Role")).Any(a => a == "HushianManagerCompany"))
navigationManager.NavigateTo("/NotFound");
await base.OnInitializedAsync();
}
private async Task OnRowClick(GridRowEventArgs<GroupDto> args)
{
Dictionary<string, object> eparameters = new Dictionary<string, object>();
eparameters.Add("model", args.Item);
eparameters.Add("OnMultipleOfThree", EventCallback.Factory.Create(this, CallBack));
await modal.ShowAsync<UpdateGroupComponent>($"ویرایش گروه {args.Item.Name}", parameters: eparameters);
}
private async Task SwitchChanged(GroupDto model, bool value)
{
if (model.Available != value)
{
if (await groupService.ChangeAvailableGroupFromManager(model.ID, value))
model.Available = value;
}
}
private async Task DeleteGroup(int GroupID, string name)
{
var confirmation = await dialog.ShowAsync(
title: $"مطمئنی می‌خوای {name} حذف کنی؟",
message1: "پس از حذف، نمی‌توان آن را به حالت اولیه برگرداند.",
message2: "می‌خوای ادامه بدی؟", new ConfirmDialogOptions()
{
YesButtonColor = ButtonColor.Danger,
YesButtonText = "بله",
NoButtonText = "نه !"
});
if (!confirmation) return;
if (await groupService.DeleteGroupFromManager(GroupID))
{
list = await groupService.GetGroupsCompany();
await grid.RefreshDataAsync();
}
}
async Task CallBack()
{
await modal.HideAsync();
list = await groupService.GetGroupsCompany();
await grid.RefreshDataAsync();
}
private string GetImageSource(byte[]? img)
{
if (img != null)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(img)}";
}
return string.Empty;
}
async Task showGroupsComponent(int GroupID, string name)
{
Dictionary<string, object> eparameters = new Dictionary<string, object>();
eparameters.Add("GroupID", GroupID);
modal.Size = ModalSize.Small;
await modal.ShowAsync<GroupUsersComponent>($"کارشناسان گروه {name}", parameters: eparameters);
}
}

View File

@@ -0,0 +1,166 @@
@page "/Settings"
@using Hushian.Application.Dtos.Company
@using HushianWebApp.Components
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject ILocalStorageService localStorageService;
@inject NavigationManager navigationManager;
@inject CompanyService companyService;
<style>
.section-box {
background-color: #f8f9fa;
border-radius: 1rem;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 1.5rem;
margin-bottom: 1rem;
height: 100%;
}
.section-title {
display: flex;
align-items: center;
font-size: 1.25rem;
font-weight: 600;
color: #343a40;
margin-bottom: 1rem;
border-right: 4px solid #ffc107;
padding-right: 0.75rem;
}
.section-title i {
margin-left: 0.5rem;
color: #ffc107;
}
.row-fullheight {
min-height: 100vh;
display: flex;
flex-wrap: wrap;
}
</style>
<div class="container-fluid">
<div class="row row-fullheight">
<!-- تغییر کلمه عبور -->
<div class="col-md-6 d-flex flex-column" style="height: fit-content;">
<div class="section-box w-100">
<div class="section-title">
<i class="bi bi-layout-text-window-reverse"></i> تغییر کلمه عبور
</div>
<ChangePassWordComponent/>
</div>
</div>
@if (ALLOWcompanyinfo)
{
<!-- اطلاعات شرکت -->
<div class="col-md-6 d-flex flex-column" style="height: fit-content;">
<div class="section-box w-100">
<div class="section-title">
<i class="bi bi-gear-fill"></i> اطلاعات شرکت
</div>
<div class="form-group row mb-3" style="padding-left: 10em;">
<div class="col-md-6">
<Switch @bind-Value="dto.Available" Label="در دسترس" />
</div>
<div class="col-md-6">
<Switch @bind-Value="dto.allowBot" Label="پاسخگوی هوشمند" />
</div>
</div>
<div class="col-md-12" style="margin-top:15px">
<input dir="ltr" class="form-control text-center mb-2" @bind-value="@dto.Fullname" type="text" placeholder="نام کامل" />
</div>
<div class="col-md-12">
<input dir="ltr" class="form-control text-center mb-2" @bind-value="@dto.Email" type="text" placeholder="پست الکترونیک" />
</div>
<div class="col-md-12">
<input dir="ltr" class="form-control text-center mb-2" @bind-value="@dto.WebSite" type="text" placeholder="وب سایت" />
</div>
<div class="col-md-12">
<input dir="ltr" class="form-control text-center mb-2" @bind-value="@dto.Phone" type="text" placeholder="تلفن" />
</div>
<div class="col-md-12">
<input dir="ltr" class="form-control text-center mb-2" @bind-value="@dto.Info" type="text" placeholder="توضیحات" />
</div>
<div class="col-md-12 d-flex align-items-center mb-2">
<InputFile type="file" OnChange="OnFileChange" accept=".png" />
@if (dto.img != null && dto.img.Length > 0)
{
<Image src="@GetImageSource()" class="rounded mx-2" height="25" width="25" alt="Uploaded Image" />
}
</div>
<div class="d-grid gap-2">
<Button Loading=loading LoadingText="در حال ذخیره اطلاعات..." Color="ButtonColor.Warning"
@onclick="updateItem">
ویرایش
</Button>
</div>
</div>
</div>
}
<!-- پایین چپ -->
<div class="col-md-6 d-flex flex-column">
<div class="section-box w-100">
<div class="section-title">
<i class="bi bi-graph-up"></i> بخش پایین چپ
</div>
<!-- محتوای دلخواه -->
</div>
</div>
<!-- پایین راست -->
<div class="col-md-6 d-flex flex-column">
<div class="section-box w-100">
<div class="section-title">
<i class="bi bi-chat-dots-fill"></i> بخش پایین راست
</div>
<!-- محتوای دلخواه -->
</div>
</div>
</div>
</div>
@code {
[Inject] protected ToastService ToastService { get; set; } = default!;
bool ALLOWcompanyinfo = true;
public bool loading { get; set; } = false;
public CompanyDto dto { get; set; }
= new();
protected override async Task OnInitializedAsync()
{
if (!(await localStorageService.GetItem<List<string>>("Role")).Any(a => a == "HushianManagerCompany"))
navigationManager.NavigateTo("/NotFound");
dto=await companyService.GetCompany();
await base.OnInitializedAsync();
}
private async Task OnFileChange(InputFileChangeEventArgs e)
{
var file = e.File;
using (var memoryStream = new MemoryStream())
{
await file.OpenReadStream().CopyToAsync(memoryStream);
dto.img = memoryStream.ToArray();
}
}
private string GetImageSource()
{
if (dto.img != null)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(dto.img)}";
}
return string.Empty;
}
async Task updateItem()
{
if (await companyService.UpdateCompany(dto))
ToastService.Notify(new ToastMessage(ToastType.Success, "تغییر اطلاعات شرکت با موفقیت انجام شد"));
}
}

View File

@@ -0,0 +1,155 @@
@page "/UserManagement"
<ConfirmDialog @ref="dialog" />
@using Common.Dtos.User
@using Hushian.Application.Dtos
@using HushianWebApp.Components
@using HushianWebApp.Service
@using HushianWebApp.Services
@inject ILocalStorageService localStorageService;
@inject NavigationManager navigationManager;
@inject UserService userService;
<Modal @ref="modal" />
<Button Color="ButtonColor.Success" Style="margin-bottom:10px"
@onclick="async()=>{
await modal.ShowAsync<ADDExperComponent>(title,parameters:parameters);
}">
کارشناس جدید
</Button>
<Grid @ref="grid" TItem="HushianUserDto"
AllowSorting="true"
Class="table table-hover"
DataProvider="DataProvider"
HeaderRowCssClass="bg-primary text-white bg-opacity-75 border-bottom-0"
Responsive="true"
AllowPaging="true"
OnRowDoubleClick="OnRowClick"
AllowRowClick=true>
<GridColumns>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="HushianUserDto" HeaderText="تصویر کاربر" >
@if (context.img?.Length != 0)
{
<Image Class="rounded-circle mx-auto d-block" src="@GetImageSource(context.img)" height="25" width="25" alt="Uploaded Image" />
}
else
{
<Icon Name="IconName.Person" Size="IconSize.x5" />
}
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="HushianUserDto" HeaderText="نام کاریری" SortKeySelector="item => item.UserName">
@context.UserName
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="HushianUserDto" HeaderText="نام کامل" SortKeySelector="item => item.FullName">
@context.FullName
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="HushianUserDto" HeaderText="پست اکترونیک" SortKeySelector="item => item.Email">
@context.Email
</GridColumn>
@* <GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="HushianUserDto" HeaderText="موبابل" SortKeySelector="item => item.PhoneNumber">
@context.PhoneNumber
</GridColumn> *@
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="HushianUserDto" HeaderText="وضعیت">
<Switch Value="@context.Available" ValueExpression="() => context.Available" ValueChanged="async(v)=>await SwitchChanged(context,v)" />
</GridColumn>
<GridColumn HeaderTextAlignment="Alignment.Center" TextAlignment="Alignment.Center" TItem="HushianUserDto" HeaderText="عملیات">
<Button Color="ButtonColor.Danger" Size="ButtonSize.ExtraSmall" @onclick="async()=>await DeleteExper(context.UserID,context.FullName)"> حذف </Button>
<Button Color="ButtonColor.Warning" Size="ButtonSize.ExtraSmall" @onclick="async()=>await showGroupsComponent(context.UserID,context.FullName)"> گروه ها </Button>
</GridColumn>
</GridColumns>
</Grid>
@code {
private ConfirmDialog dialog = default!;
Dictionary<string, object> parameters = new Dictionary<string, object>();
Grid<HushianUserDto> grid = default!;
private Modal modal = default!;
string title = "کارشناس جدید";
protected override async Task OnInitializedAsync()
{
parameters.Add("OnMultipleOfThree", EventCallback.Factory.Create(this, CallBack));
if (!(await localStorageService.GetItem<List<string>>("Role")).Any(a =>a== "HushianManagerCompany") )
navigationManager.NavigateTo("/NotFound");
await base.OnInitializedAsync();
}
private async Task<GridDataProviderResult<HushianUserDto>> DataProvider(GridDataProviderRequest<HushianUserDto> request)
{
var employees = await userService.GetExpersCompany(0, request.PageNumber, request.PageSize);
return await Task.FromResult(request.ApplyTo(employees != null ? employees.list : new()));
}
async Task CallBack()
{
await modal.HideAsync();
await grid.RefreshDataAsync();
}
private async Task OnRowClick(GridRowEventArgs<HushianUserDto> args)
{
var editmodel = new EditUserFromUserDto()
{
Email = args.Item.Email,
FullName = args.Item.FullName,
UserName = args.Item.UserName,
img = args.Item.img
};
Dictionary<string, object> eparameters = new Dictionary<string, object>();
eparameters.Add("model", editmodel);
eparameters.Add("OnMultipleOfThree", EventCallback.Factory.Create(this, CallBack));
await modal.ShowAsync<UpdateExperComponent>($"ویرایش کارشناس {args.Item.FullName}", parameters: eparameters);
}
private async Task SwitchChanged(HushianUserDto model,bool value)
{
if (model.Available != value)
{
if (await userService.ChangeAvailableExperFromManager(model.UserID, value))
model.Available = value;
}
}
private async Task DeleteExper(string ExperID,string name)
{
var confirmation = await dialog.ShowAsync(
title: $"مطمئنی می‌خوای {name} حذف کنی؟",
message1: "پس از حذف، نمی‌توان آن را به حالت اولیه برگرداند.",
message2: "می‌خوای ادامه بدی؟",new ConfirmDialogOptions()
{
YesButtonColor=ButtonColor.Danger,
YesButtonText="بله",
NoButtonText="نه !"
});
if (!confirmation) return;
if (await userService.DeleteExperFromManager(ExperID))
await grid.RefreshDataAsync();
}
private string GetImageSource(byte[]? img)
{
if (img != null)
{
return $"data:image/jpeg;base64,{Convert.ToBase64String(img)}";
}
return string.Empty;
}
async Task showGroupsComponent(string ExperID, string name)
{
Dictionary<string, object> eparameters = new Dictionary<string, object>();
eparameters.Add("ExperID", ExperID);
modal.Size = ModalSize.Small;
await modal.ShowAsync<UserGroupsComponent>($"گروه های کارشناس {name}", parameters: eparameters);
}
}

View File

@@ -0,0 +1,21 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using HushianWebApp;
using HushianWebApp.Services;
using HushianWebApp.Service;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri("http://localhost:5137/api/") });
builder.Services.AddScoped<ILocalStorageService, LocalStorageService>();
builder.Services.AddScoped<BaseController>();
builder.Services.AddScoped<AuthService>();
builder.Services.AddScoped<VerificationService>();
builder.Services.AddScoped<UserService>();
builder.Services.AddScoped<CompanyService>();
builder.Services.AddScoped<GroupService>();
builder.Services.AddScoped<ConversationService>();
builder.Services.AddBlazorBootstrap();
await builder.Build().RunAsync();

View File

@@ -0,0 +1,25 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "http://localhost:5165",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:7118;http://localhost:5165",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,128 @@
using BlazorBootstrap;
using Common.Dtos.User;
using Common.Models.Auth;
using Common.Models.Auth.CompanySide;
using Common.Models.Auth.UserSide;
using Common.Models.Identity;
using HushianWebApp.Services;
using Microsoft.AspNetCore.Components;
using System.Net.Http.Json;
namespace HushianWebApp.Service
{
public class AuthService
{
private readonly BaseController _baseController;
private readonly NavigationManager _NavigationManager;
private readonly ILocalStorageService _localStorage;
private readonly ToastService _ToastService;
public AuthService(BaseController baseController, NavigationManager navigationManager, ILocalStorageService localStorage, ToastService toastService)
{
_baseController = baseController;
_NavigationManager = navigationManager;
_localStorage = localStorage;
_ToastService = toastService;
}
public async Task<bool> IsOnline()
{
return await _baseController.IsOnline();
}
public async Task<string> login(AuthRequestFromCompanySide authRequest)
{
var response = await _baseController.PostLogin("v1/Auth/loginCompanySide", authRequest);
if (response.Item2.IsSuccessStatusCode)
{
var responsevalue = await response.Item2.Content.ReadFromJsonAsync<AuthResponse>();
await _localStorage.RemoveItem("C/ID");
await _localStorage.SetItem("C/ID", responsevalue.Id);
await _localStorage.RemoveItem("C/CompanyId");
await _localStorage.SetItem("C/CompanyId", responsevalue.CompanyId.GetValueOrDefault());
await _localStorage.RemoveItem("C/Fullname");
await _localStorage.SetItem("C/Fullname", responsevalue.Fullname);
await _localStorage.RemoveItem("C/MobileOrUserName");
await _localStorage.SetItem("C/MobileOrUserName", responsevalue.MobileOrUserName);
await _localStorage.RemoveItem("C/Role");
await _localStorage.SetItem("C/Role", responsevalue.Role);
await _localStorage.RemoveItem("C/img");
await _localStorage.SetItem("C/img", responsevalue.img);
await _localStorage.RemoveItem("C/key");
await _localStorage.SetItem("C/key", responsevalue.Token);
_NavigationManager.NavigateTo("/");
}
return response.Item1;
}
public async Task<int> login(AuthRequestFromUserSide model)
{
var response = await _baseController.Post($"v1/User/AuthenticationFromUser",model);
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<int>();
else if (response.StatusCode == System.Net.HttpStatusCode.BadRequest)
{
var Errors = await response.Content.ReadFromJsonAsync<List<string>>();
_ToastService.Notify(new ToastMessage(ToastType.Danger, Errors[0].Split(':').Length == 2 ? Errors[0].Split(':')[1] : Errors[0]));
}
else if (!response.IsSuccessStatusCode)
{
_NavigationManager.NavigateTo("Unhandled");
}
return 0;
}
public async Task<bool> Verificationlogin(int ID,string code)
{
var response = await _baseController.Put($"v1/Auth/UserLoginVerification/{ID}/{code}");
if (response.IsSuccessStatusCode)
{
var responsevalue = await response.Content.ReadFromJsonAsync<AuthResponse>();
await _localStorage.RemoveItem("U/ID");
await _localStorage.SetItem("U/ID", responsevalue.Id);
await _localStorage.RemoveItem("U/CompanyId");
await _localStorage.SetItem("U/CompanyId", responsevalue.CompanyId.GetValueOrDefault());
await _localStorage.RemoveItem("U/Fullname");
await _localStorage.SetItem("U/Fullname", responsevalue.Fullname);
await _localStorage.RemoveItem("U/MobileOrUserName");
await _localStorage.SetItem("U/MobileOrUserName", responsevalue.MobileOrUserName);
await _localStorage.RemoveItem("U/Role");
await _localStorage.SetItem("U/Role", responsevalue.Role);
await _localStorage.RemoveItem("U/img");
await _localStorage.SetItem("U/img", responsevalue.img);
await _localStorage.RemoveItem("U/key");
await _localStorage.SetItem("U/key", responsevalue.Token);
return true;
}
return false;
}
public async Task Logout ()
{
await _localStorage.RemoveItem("C/ID");
await _localStorage.RemoveItem("C/CompanyId");
await _localStorage.RemoveItem("C/Fullname");
await _localStorage.RemoveItem("C/MobileOrUserName");
await _localStorage.RemoveItem("C/Role");
await _localStorage.RemoveItem("C/img");
await _localStorage.RemoveItem("C/key");
await _localStorage.RemoveItem("U/ID");
await _localStorage.RemoveItem("U/CompanyId");
await _localStorage.RemoveItem("U/Fullname");
await _localStorage.RemoveItem("U/MobileOrUserName");
await _localStorage.RemoveItem("U/Role");
await _localStorage.RemoveItem("U/img");
await _localStorage.RemoveItem("U/key");
}
}
}

View File

@@ -0,0 +1,155 @@
using BlazorBootstrap;
using HushianWebApp.Services;
using Microsoft.AspNetCore.Components;
using System.Net;
using System.Net.Http.Json;
using System.Text;
using static System.Runtime.InteropServices.JavaScript.JSType;
namespace HushianWebApp.Service
{
public class BaseController
{
private readonly HttpClient _Http;
private readonly NavigationManager _NavigationManager;
private readonly ToastService _ToastService;
public BaseController(HttpClient http, NavigationManager navigationManager, ToastService toastService)
{
_Http = http;
_NavigationManager = navigationManager;
_ToastService = toastService;
}
public async Task<bool> IsOnline()
{
var result = await _Http.GetAsync("v1/Auth/IsOnline");
return result.IsSuccessStatusCode;
}
public async Task SetToken(string token)
{
_Http.DefaultRequestHeaders.Add("Authorization",
$"Bearer {token}");
}
public async Task RemoveToken()
{
if (_Http.DefaultRequestHeaders.Any(t => t.Key == "Authorization"))
_Http.DefaultRequestHeaders.Remove("Authorization");
}
public async Task<HttpResponseMessage> Get(string route)
{
var result = await _Http.GetAsync(route);
return await Check(result);
}
public async Task<HttpResponseMessage> Delete(string route)
{
var result = await _Http.DeleteAsync(route);
return await Check(result);
}
public async Task<HttpResponseMessage> Post(string route, object mode)
{
var result = await _Http.PostAsJsonAsync(route, mode);
return await Check(result);
}
public async Task<Tuple<string, HttpResponseMessage>> PostLogin(string route, object mode)
{
var result = await _Http.PostAsJsonAsync(route, mode);
if (result.IsSuccessStatusCode)
{
return Tuple.Create( "ok",result);
}
else if (result.StatusCode == System.Net.HttpStatusCode.BadRequest)
{
try
{
var Errors = await result.Content.ReadFromJsonAsync<List<string>>();
if (Errors.Count > 0)
{
_ToastService.Notify(new ToastMessage(ToastType.Danger, Errors[0]));
}
else _ToastService.Notify(new ToastMessage(ToastType.Danger, "خطا در اجرای عملیات"));
return Tuple.Create(Errors[0], result);
}
catch (Exception)
{
_ToastService.Notify(new ToastMessage(ToastType.Danger, "خطا در اجرای عملیات"));
return Tuple.Create("error", result);
}
}
else if (!result.IsSuccessStatusCode)
{
_NavigationManager.NavigateTo("Unhandled");
return Tuple.Create("Unhandled", result);
}
return Tuple.Create("no", result);
}
public async Task<HttpResponseMessage> Post(string route,bool redirectToLogin=true)
{
var jsonString = "{\"appid\":1,\"platformid\":1,\"rating\":3}";
var httpContent = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await _Http.PostAsync(route, httpContent);
return await Check(result, redirectToLogin);
}
public async Task<HttpResponseMessage> Put(string route, object mode)
{
var result = await _Http.PutAsJsonAsync(route, mode);
return await Check(result);
}
public async Task<HttpResponseMessage> Put(string route)
{
var jsonString = "{\"appid\":1,\"platformid\":1,\"rating\":3}";
var httpContent = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await _Http.PutAsync(route, httpContent);
return await Check(result);
}
private async Task<HttpResponseMessage> Check(HttpResponseMessage result, bool redirectToLogin = true)
{
if (result.StatusCode == System.Net.HttpStatusCode.Unauthorized && redirectToLogin)
_NavigationManager.NavigateTo("Login");
else if (result.StatusCode == System.Net.HttpStatusCode.BadRequest)
{
try
{
var Errors = await result.Content.ReadFromJsonAsync<List<string>>();
if (Errors.Count > 0)
{
if (Errors[0] == "PhoneNumberNotConfirmed")
{
_ToastService.Notify(new ToastMessage(ToastType.Danger, "این کاربری احراز نشده اگر مالک آن هستید احراز کنید"));
}
else
{
_ToastService.Notify(new ToastMessage(ToastType.Danger, Errors[0].Split(':').Length==2 ? Errors[0].Split(':')[1] : Errors[0]));
}
}
else _ToastService.Notify(new ToastMessage(ToastType.Danger, "خطا در اجرای عملیات"));
}
catch (Exception)
{
_ToastService.Notify(new ToastMessage(ToastType.Danger, "خطا در اجرای عملیات"));
}
}
else if (result.StatusCode == System.Net.HttpStatusCode.Forbidden)
_ToastService.Notify(new ToastMessage(ToastType.Danger, "به این بخش دسترسی ندارید"));
else if (result.StatusCode == System.Net.HttpStatusCode.NotFound)
_ToastService.Notify(new ToastMessage(ToastType.Danger, "یافت نشد"));
else if (!result.IsSuccessStatusCode)
{
_NavigationManager.NavigateTo("Unhandled");
}
return result;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Text;
namespace HushianWebApp.Service
{
public static class CaptchaService
{
public static string GetCaptchaWord(int length)
{
var random = new Random(DateTime.Now.Millisecond);
// const string chars = "ABCDEFGHJKLMNPQRSTUWYZabcdefghijkmnpqrstuwz23456789*#!$%=";
const string chars = "ABCDEFGHJKLMNPQRSTUWYZabcdefghijkmnpqrstuwz23456789";
string cw = new(Enumerable.Repeat(chars, length)
.Select(s => s[random.Next(s.Length)])
.ToArray());
return cw;
}
public static string GenerateCaptchaBase64(string text, int width = 120, int height = 40)
{
return "";
}
}
}

View File

@@ -0,0 +1,63 @@
using Common.Dtos.Company;
using System.Net.Http.Json;
namespace HushianWebApp.Service
{
public class CompanyService
{
private readonly BaseController _baseController;
const string BaseRoute = "v1/Company/";
public CompanyService(BaseController baseController)
{
_baseController = baseController;
}
public async Task<int> RegisterCompany(RegisterCompanyDto request)
{
var response = await _baseController.Post($"{BaseRoute}NewCompany", request);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<int>();
}
return 0;
}
public async Task<ReadANDUpdate_CompanyDto?> GetCompany(int CompanyID)
{
var response = await _baseController.Get($"{BaseRoute}GetCompany/{CompanyID}");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<ReadANDUpdate_CompanyDto>();
}
return null;
}
public async Task<bool> UpdateCompany(ReadANDUpdate_CompanyDto dto)
{
var response = await _baseController.Put($"{BaseRoute}UpdateCompany",dto);
return response.IsSuccessStatusCode;
}
//public async Task<bool> AddContentInfo(string str)
//{
// var response = await _baseController.Post($"{BaseRoute}AddContentInfo?ContentInfo={str}");
// return response.IsSuccessStatusCode;
//}
//public async Task<bool> DeleteContentInfo(int ID)
//{
// var response = await _baseController.Delete($"{BaseRoute}DeleteContentInfo/{ID}");
// return response.IsSuccessStatusCode;
//}
//public async Task<bool> UpdateContentInfo(int ID, string str)
//{
// var response = await _baseController.Put($"{BaseRoute}UpdateContentInfo/{ID}?ContentInfo={str}");
// return response.IsSuccessStatusCode;
//}
//public async Task<List<ContentInfoDto>?> GetContentInfos()
//{
// var response = await _baseController.Get($"{BaseRoute}GetContentInfos");
// if (response.IsSuccessStatusCode)
// {
// return await response.Content.ReadFromJsonAsync<List<ContentInfoDto>?>();
// }
// return null;
//}
}
}

View File

@@ -0,0 +1,93 @@
using Hushian.Application.Dtos;
using System.Net.Http.Json;
namespace HushianWebApp.Service
{
public class ConversationService
{
private readonly BaseController _baseController;
const string BaseRoute = "v1/Conversation/";
public ConversationService(BaseController baseController)
{
_baseController = baseController;
}
public async Task <List<ConversationDto>> MyConversationIsFinished()
{
var response = await _baseController.Get($"{BaseRoute}MyConversationIsFinished");
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<List<ConversationDto>>();
return new() ;
}
public async Task<List<ConversationDto>> MyConversationIsInProgress()
{
var response = await _baseController.Get($"{BaseRoute}MyConversationIsInProgress");
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<List<ConversationDto>>();
return new();
}
public async Task<List<ConversationDto>> ConversationAwaitingOurResponse()
{
var response = await _baseController.Get($"{BaseRoute}ConversationAwaitingOurResponse");
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<List<ConversationDto>>();
return new();
}
public async Task<bool> MarkAsReadConversationItemAsync(int ID)
{
var response = await _baseController.Put($"{BaseRoute}MarkAsReadConversationItem/{ID}");
return response.IsSuccessStatusCode;
}
public async Task<List<ConversationItemDto>> GetConversationItems(int ConversationID)
{
var response = await _baseController.Get($"{BaseRoute}ConversationItems/{ConversationID}");
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<List<ConversationItemDto>>();
return new();
}
public async Task ADDConversationItemFromCompanySide(int ConversationID,string text)
{
var response = await _baseController.Post($"{BaseRoute}ADDConversationItemFromCompanySide/{ConversationID}",new ADDConversationItemDto()
{
ConversationID = ConversationID,
text=text
});
/* if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<List<ConversationItemDto>>();
// return new();*/
}
public async Task<bool> ConversationIsFinish(int ConversationID)
{
var response = await _baseController.Put($"{BaseRoute}ConversationIsFinish/{ConversationID}");
return response.IsSuccessStatusCode;
}
public async Task<bool> ConversationIsStart(int ConversationID)
{
var response = await _baseController.Put($"{BaseRoute}ConversationIsStart/{ConversationID}");
return response.IsSuccessStatusCode;
}
public async Task<int> GetCountQueueCompany(int CompanyID,int GroupID=0)
{
var response = await _baseController.Get($"{BaseRoute}CountQueueCompany/{CompanyID}?GroupID={GroupID}");
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<int>();
return -1;
}
public async Task<List<ConversationDto>> MyConversationUserSide(int CompanyID)
{
var response = await _baseController.Get($"{BaseRoute}ConversationFromUserSide/{CompanyID}");
if (response.IsSuccessStatusCode)
return await response.Content.ReadFromJsonAsync<List<ConversationDto>>();
return new();
}
}
}

View File

@@ -0,0 +1,94 @@
using Common.Dtos.Exper;
using Common.Dtos.Group;
using System.Net.Http.Json;
namespace HushianWebApp.Service
{
public class GroupService
{
private readonly BaseController _baseController;
const string BaseRoute = "v1/Group/";
public GroupService(BaseController baseController)
{
_baseController = baseController;
}
public async Task<bool> AddGroup(ADD_GroupDto Group)
{
var response = await _baseController.Post($"{BaseRoute}AddGroup",Group);
return response.IsSuccessStatusCode;
}
public async Task<bool> UpdateGroup(Update_GroupDto Group)
{
var response = await _baseController.Put($"{BaseRoute}UpdateGroup", Group);
return response.IsSuccessStatusCode;
}
public async Task<bool> JoinExperToGroup(int GroupID, string ExperID)
{
var response = await _baseController.Put($"{BaseRoute}JoinExperToGroup/{GroupID}/{ExperID}");
return response.IsSuccessStatusCode;
}
public async Task<bool> UnJoinExperToGroup(int GroupID, string ExperID)
{
var response = await _baseController.Put($"{BaseRoute}UnJoinExperToGroup/{GroupID}/{ExperID}");
return response.IsSuccessStatusCode;
}
public async Task<bool> DeleteGroupFromManager(int GroupID)
{
var response = await _baseController.Delete ($"{BaseRoute}DeleteGroup/{GroupID}");
return response.IsSuccessStatusCode;
}
public async Task<List<Read_GroupDto>?> GetGroupsCompany()
{
var response = await _baseController.Get($"{BaseRoute}GetGroupsCompany");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<List<GroupDto>>();
}
return null;
}
public async Task<List<Read_GroupDto>?> GetGroupsCompany(int CompanyID)
{
var response = await _baseController.Get($"{BaseRoute}GetGroupsCompany?CompanyID={CompanyID}");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<List<Read_GroupDto>>();
}
return null;
}
public async Task<List<Read_GroupDto>?> GetGroupsFromExperID(string ExperID)
{
var response = await _baseController.Get($"{BaseRoute}GetGroupsFromExperID?ExperID={ExperID}");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<List<Read_GroupDto>>();
}
return new();
}
public async Task<List<Read_ExperDto>> GetExpersFromGroupID(int GroupID)
{
var response = await _baseController.Get($"{BaseRoute}GetExpersFromGroupID/{GroupID}");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<List<Read_ExperDto>>();
}
return new();
}
public async Task<bool> ChangeAvailableGroupFromManager(int GroupID, bool Available)
{
var response = await _baseController.Put($"{BaseRoute}ChangeAvailableGroupFromManager/{GroupID}?Available={Available}");
return response.IsSuccessStatusCode;
}
//public async Task<List<HushianUserDto>?> GetOnlineExpersFromGroupID(int GroupID)
//{
// var response = await _baseController.Get($"{BaseRoute}GetOnlineExpersFromGroupID/{GroupID}");
// if (response.IsSuccessStatusCode)
// {
// return await response.Content.ReadFromJsonAsync<List<HushianUserDto>>();
// }
// return null;
//}
}
}

View File

@@ -0,0 +1,42 @@
using Microsoft.JSInterop;
using System.Text.Json;
namespace HushianWebApp.Services
{
public interface ILocalStorageService
{
Task<T> GetItem<T>(string key);
Task SetItem<T>(string key, T value);
Task RemoveItem(string key);
}
public class LocalStorageService : ILocalStorageService
{
private IJSRuntime _jsRuntime;
public LocalStorageService(IJSRuntime jsRuntime)
{
_jsRuntime = jsRuntime;
}
public async Task<T> GetItem<T>(string key)
{
var json = await _jsRuntime.InvokeAsync<string>("localStorage.getItem", key);
if (json == null)
return default;
return JsonSerializer.Deserialize<T>(json);
}
public async Task SetItem<T>(string key, T value)
{
await _jsRuntime.InvokeVoidAsync("localStorage.setItem", key, JsonSerializer.Serialize(value));
}
public async Task RemoveItem(string key)
{
await _jsRuntime.InvokeVoidAsync("localStorage.removeItem", key);
}
}
}

View File

@@ -0,0 +1,108 @@
using System.Net.Http.Json;
namespace HushianWebApp.Service
{
public class UserService
{
private readonly BaseController _baseController;
const string BaseRoute = "v1/User/";
public UserService(BaseController baseController)
{
_baseController = baseController;
}
public async Task<bool> AddExper(AddUserDto request)
{
var response = await _baseController.Post($"{BaseRoute}AddExper", request);
return response.IsSuccessStatusCode;
}
public async Task<PagingDto<HushianUserDto>?> GetExpersCompany(int CompanyID, int PageIndex = 1, int PageSize = 10)
{
string route = $"{BaseRoute}GetExpersCompany?CompanyID={CompanyID}&PageIndex={PageIndex}&PageSize={PageSize}";
var response = await _baseController.Get(route);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<PagingDto<HushianUserDto>>();
}
return null;
}
public async Task<List<HushianUserDto>?> GetOnlineExpersCompany(int CompanyID)
{
string route = $"{BaseRoute}GetOnlineExpersCompany?CompanyID={CompanyID}";
var response = await _baseController.Get(route);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<List<HushianUserDto>>();
}
return null;
}
//--------------------------------------------------------------------------------------------------------------
public async Task<PagingDto<HushianUserDto>?> GetUsersCompanyFromManager(int PageIndex = 1, int PageSize = 10)
{
string route = $"{BaseRoute}GetUsersCompany?PageIndex={PageIndex}&PageSize={PageSize}";
var response = await _baseController.Get(route);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<PagingDto<HushianUserDto>>();
}
return null;
}
public async Task<bool> EditUserYourself(EditUserFromUserDto request) //ویرایش کاربران توسط خود
{
var response = await _baseController.Put($"{BaseRoute}EditUserYourself", request);
return response.IsSuccessStatusCode;
}
public async Task<HushianUserDto?> GetCurrentUser() //ویرایش کاربران توسط خود
{
var response = await _baseController.Get($"{BaseRoute}GetCurrentUser");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<HushianUserDto>();
}
return null;
}
public async Task<bool> ExperEditingFromManager(EditUserFromUserDto request) //ویرایش کاربران توسط مدیرش
{
var response = await _baseController.Put($"{BaseRoute}ExperEditingFromManager", request);
return response.IsSuccessStatusCode;
}
public async Task<bool> ChangePasswordYourself(ChangePasswordFromUserDto request) //تغییر کلمه عبور کاربران توسط خود
{
var response = await _baseController.Put($"{BaseRoute}ChangePasswordYourself", request);
return response.IsSuccessStatusCode;
}
public async Task<bool> CheckAvailableExperInCompany(string? ExperID=null)
{
string route = $"{BaseRoute}CheckAvailableExperInCompany";
if (!string.IsNullOrEmpty(ExperID))
route += $"?ExperID={ExperID}";
var response = await _baseController.Get(route);
return response.IsSuccessStatusCode;
}
public async Task<bool> ChangeAvailableExperFromManager(string ExperID,bool Available)
{
var response = await _baseController.Put($"{BaseRoute}ChangeAvailableExperFromManager/{ExperID}?Available={Available}");
return response.IsSuccessStatusCode;
}
public async Task<bool>DeleteExperFromManager(string ExperID)
{
var response = await _baseController.Delete($"{BaseRoute}DeleteExperFromManager/{ExperID}");
return response.IsSuccessStatusCode;
}
public async Task<bool> FreeExper()
{
var response = await _baseController.Delete($"{BaseRoute}FreeExper");
return response.IsSuccessStatusCode;
}
}
}

View File

@@ -0,0 +1,52 @@
using Common.Dtos.User;
using Common.Enums;
using System.Net.Http.Json;
namespace HushianWebApp.Service
{
public class VerificationService
{
private readonly BaseController _baseController;
public VerificationService(BaseController baseController)
{
_baseController = baseController;
}
public async Task<int> FromUserName(string mobile, VerificationCodeType type)
{
string route = type switch
{
VerificationCodeType.PhoneNumberConfirmed => "PhoneNumberConfirmedFromUserName",
VerificationCodeType.ForgetPassword => "ForgetPasswordFromUserName",
VerificationCodeType.ChangeMobile => throw new NotImplementedException(),
VerificationCodeType.Login => throw new NotImplementedException(),
_ => throw new NotImplementedException()
};
var response = await _baseController.Get($"v1/Verification/{route}/{mobile}");
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadFromJsonAsync<int>();
}
else
{
return 0;
}
}
public async Task<bool> ConfirmedCode(ConfirmedCodeDto dto)
{
var response = await _baseController.Post($"v1/Verification/ConfirmedCode", dto);
return response.IsSuccessStatusCode;
}
public async Task<bool> ReSendCode(int ID)
{
var response = await _baseController.Get($"v1/Verification/ReSendCode/{ID}");
return response.IsSuccessStatusCode;
}
}
}

View File

@@ -0,0 +1,11 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop
@using HushianWebApp
@using HushianWebApp.Layout
@using BlazorBootstrap;

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="250" height="250">
<path d="M0 0 C82.5 0 165 0 250 0 C250 82.5 250 165 250 250 C167.5 250 85 250 0 250 C0 167.5 0 85 0 0 Z " fill="#004F8D" transform="translate(0,0)"/>
<path d="M0 0 C16.17 0 32.34 0 49 0 C49.01458252 4.21370361 49.02916504 8.42740723 49.04418945 12.76879883 C49.09457584 26.70674526 49.16102937 40.64458109 49.23571491 54.58241749 C49.28059619 63.03108786 49.32002836 71.47971681 49.34643555 79.9284668 C49.36947793 87.29618341 49.40294513 94.66376806 49.44870156 102.03137988 C49.47255003 105.92905428 49.49133346 109.82659867 49.49761391 113.72434425 C49.50370298 117.40078543 49.52383876 121.07689431 49.55427551 124.75321198 C49.56712022 126.72987998 49.56549631 128.70662586 49.5632782 130.68333435 C49.68344397 142.19869043 51.63837021 152.82207291 59 162 C67.59080561 169.94896381 77.9881894 170.56434422 89.2421875 170.37109375 C96.97734493 169.60722685 103.578718 166.97498311 109 161.3125 C115.03058658 153.53157244 117.09771611 144.62321705 117.15821838 134.92556763 C117.1680072 133.73092392 117.17779602 132.53628021 117.18788147 131.30543518 C117.19363693 130.0085527 117.1993924 128.71167023 117.20532227 127.37548828 C117.21491036 125.98545547 117.22492098 124.59542553 117.23532104 123.20539856 C117.2622753 119.4434955 117.28333596 115.68158001 117.30332303 111.91963434 C117.3252413 107.98382479 117.35260133 104.04805312 117.37937927 100.11227417 C117.42922737 92.66451683 117.47419534 85.21673837 117.51740164 77.76893985 C117.56684152 69.28767952 117.62173455 60.80645722 117.67708123 52.3252337 C117.79078022 34.88352291 117.89692561 17.44177704 118 0 C134.5 0 151 0 168 0 C168.11326462 18.98593884 168.20520234 37.97160028 168.25906086 56.95779228 C168.28474308 65.77520802 168.31970031 74.59239753 168.37719727 83.40966797 C168.42734049 91.10295692 168.45936336 98.79608188 168.47044247 106.48952973 C168.47690948 110.55584742 168.49189464 114.62169634 168.52865028 118.6878624 C168.75848226 145.14912449 167.26381554 168.69654997 148 189 C131.35378986 205.27629436 108.54491768 212.39088523 85.69458008 212.31567383 C83.70062801 212.31252076 81.70669474 212.33683422 79.71289062 212.36132812 C57.1397995 212.37248635 36.78169045 204.81434569 20.27734375 189.30078125 C7.11347042 176.00143066 -0.13638515 158.34315833 -0.12025452 139.61549377 C-0.12162918 138.37740463 -0.12300385 137.13931549 -0.12442017 135.8637085 C-0.120882 134.51013159 -0.11724721 133.15655493 -0.11352539 131.80297852 C-0.11324302 130.36354067 -0.11340223 128.92410268 -0.1139679 127.48466492 C-0.11425392 123.59262885 -0.10838874 119.70062382 -0.10139394 115.80859494 C-0.0951279 111.73534889 -0.09455403 107.66210206 -0.09336853 103.58885193 C-0.09026479 95.88256373 -0.08206432 88.17628977 -0.07201904 80.47000784 C-0.06082817 71.69371457 -0.05533996 62.91742061 -0.05032361 54.14112198 C-0.03988089 36.09407161 -0.02154732 18.04704076 0 0 Z " fill="#FEFEFE" transform="translate(41,20)"/>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 206 KiB

View File

@@ -0,0 +1,5 @@
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M12 4C16.4183 4 20 7.58172 20 12C20 13.9745 19.2323 15.8402 18 17.2694V14.5C18 13.9477 17.5523 13.5 17 13.5C16.4477 13.5 16 13.9477 16 14.5V19.5C16 20.0523 16.4477 20.5 17 20.5H22C22.5523 20.5 23 20.0523 23 19.5C23 18.9477 22.5523 18.5 22 18.5H19.5786C21.069 16.7378 22 14.4493 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.148 5.88912 21.3862 10.8901 21.939C11.4391 21.9997 11.9333 21.6039 11.9939 21.0549C12.0546 20.506 11.6588 20.0118 11.1099 19.9511C7.11098 19.5091 4 16.1172 4 12C4 7.58172 7.58172 4 12 4Z"
fill="rgb(100 116 139)" />
</svg>

After

Width:  |  Height:  |  Size: 713 B

View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 420 180" style="enable-background:new 0 0 420 180;" xml:space="preserve">
<style type="text/css">
.st0{fill:#D5DDE6;}
.st1{fill:url(#Rectangle-Copy-5_1_);}
</style>
<title>bg02</title>
<desc>Created with Sketch.</desc>
<g id="Page-1">
<g id="bg02">
<g id="Group-2-Copy-11" transform="translate(210.000000, 100.000000) rotate(-270.000000) translate(-210.000000, -100.000000) translate(136.000000, -85.000000)">
<path id="Fill-1171" class="st0" d="M0,171.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S0,170.1,0,171.5"/>
<path id="Fill-1172" class="st0" d="M0,143.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5S3.9,141,2.5,141S0,142.1,0,143.5"/>
<path id="Fill-1173" class="st0" d="M0,115.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5S3.9,113,2.5,113S0,114.1,0,115.5"/>
<path id="Fill-1174" class="st0" d="M0,86.5C0,87.9,1.1,89,2.5,89S5,87.9,5,86.5C5,85.1,3.9,84,2.5,84S0,85.1,0,86.5"/>
<path id="Fill-1175" class="st0" d="M0,59.5C0,60.9,1.1,62,2.5,62S5,60.9,5,59.5C5,58.1,3.9,57,2.5,57S0,58.1,0,59.5"/>
<path id="Fill-1176" class="st0" d="M0,30.5C0,31.9,1.1,33,2.5,33S5,31.9,5,30.5S3.9,28,2.5,28S0,29.1,0,30.5"/>
<path id="Fill-1188" class="st0" d="M28,171.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S28,170.1,28,171.5"
/>
<path id="Fill-1189" class="st0" d="M28,143.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S28,142.1,28,143.5"/>
<path id="Fill-1190" class="st0" d="M28,115.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C29.1,113,28,114.1,28,115.5"/>
<path id="Fill-1191" class="st0" d="M28,86.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C29.1,84,28,85.1,28,86.5"/>
<path id="Fill-1192" class="st0" d="M28,59.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S28,58.1,28,59.5"/>
<path id="Fill-1193" class="st0" d="M28,30.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5S31.9,28,30.5,28S28,29.1,28,30.5"/>
<path id="Fill-1207" class="st0" d="M57,115.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C58.1,113,57,114.1,57,115.5"/>
<path id="Fill-1208" class="st0" d="M57,86.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5S60.9,84,59.5,84
C58.1,84,57,85.1,57,86.5"/>
<path id="Fill-1209" class="st0" d="M57,59.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S57,58.1,57,59.5"/>
<path id="Fill-1210" class="st0" d="M57,30.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5S60.9,28,59.5,28
C58.1,28,57,29.1,57,30.5"/>
<path id="Fill-1224" class="st0" d="M85,115.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S85,114.1,85,115.5"/>
<path id="Fill-1225" class="st0" d="M85,86.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S85,85.1,85,86.5"/>
<path id="Fill-1226" class="st0" d="M85,59.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S85,58.1,85,59.5"/>
<path id="Fill-1227" class="st0" d="M85,30.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S85,29.1,85,30.5"/>
<path id="Fill-1239" class="st0" d="M114,171.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,169,114,170.1,114,171.5"/>
<path id="Fill-1240" class="st0" d="M114,143.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,141,114,142.1,114,143.5"/>
<path id="Fill-1241" class="st0" d="M114,115.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C115.1,113,114,114.1,114,115.5"/>
<path id="Fill-1242" class="st0" d="M114,86.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,84,114,85.1,114,86.5"/>
<path id="Fill-1243" class="st0" d="M114,59.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,57,114,58.1,114,59.5"/>
<path id="Fill-1818" class="st0" d="M0,2.5C0,3.9,1.1,5,2.5,5S5,3.9,5,2.5S3.9,0,2.5,0S0,1.1,0,2.5"/>
<path id="Fill-1824" class="st0" d="M28,2.5C28,3.9,29.1,5,30.5,5S33,3.9,33,2.5S31.9,0,30.5,0S28,1.1,28,2.5"/>
<path id="Fill-1830" class="st0" d="M57,2.5C57,3.9,58.1,5,59.5,5S62,3.9,62,2.5S60.9,0,59.5,0S57,1.1,57,2.5"/>
<path id="Fill-1836" class="st0" d="M85,2.5C85,3.9,86.1,5,87.5,5S90,3.9,90,2.5C90,1.1,88.9,0,87.5,0S85,1.1,85,2.5"/>
<path id="Fill-1842" class="st0" d="M114,2.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,0,114,1.1,114,2.5"/>
<path id="Fill-1244" class="st0" d="M114,30.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,28,114,29.1,114,30.5"/>
<polygon id="Path-Copy" class="st0" points="83.3,319.6 79.7,316 91.7,304 95.3,307.6 "/>
<polygon id="Path" class="st0" points="34,30.3 38.3,34.5 34.7,38 30.5,33.8 26.3,38 22.7,34.5 27,30.3 22.7,26 26.3,22.5
30.5,26.7 34.7,22.5 38.3,26 "/>
<path id="Fill-1171_1_" class="st0" d="M0,367.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S0,366.1,0,367.5"
/>
<path id="Fill-1172_1_" class="st0" d="M0,339.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S0,338.1,0,339.5"
/>
<path id="Fill-1173_1_" class="st0" d="M0,311.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5S3.9,309,2.5,309S0,310.1,0,311.5"/>
<path id="Fill-1174_1_" class="st0" d="M0,282.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S0,281.1,0,282.5"
/>
<path id="Fill-1175_1_" class="st0" d="M0,255.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S0,254.1,0,255.5"
/>
<path id="Fill-1176_1_" class="st0" d="M0,226.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5S3.9,224,2.5,224S0,225.1,0,226.5"/>
<path id="Fill-1188_1_" class="st0" d="M28,367.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C29.1,365,28,366.1,28,367.5"/>
<path id="Fill-1189_1_" class="st0" d="M28,339.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C29.1,337,28,338.1,28,339.5"/>
<path id="Fill-1190_1_" class="st0" d="M28,311.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C29.1,309,28,310.1,28,311.5"/>
<path id="Fill-1191_1_" class="st0" d="M28,282.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C29.1,280,28,281.1,28,282.5"/>
<path id="Fill-1192_1_" class="st0" d="M28,255.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C29.1,253,28,254.1,28,255.5"/>
<path id="Fill-1193_1_" class="st0" d="M28,226.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S28,225.1,28,226.5"/>
<path id="Fill-1205" class="st0" d="M57,367.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C58.1,365,57,366.1,57,367.5"/>
<path id="Fill-1206" class="st0" d="M57,339.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C58.1,337,57,338.1,57,339.5"/>
<path id="Fill-1207_1_" class="st0" d="M57,311.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C58.1,309,57,310.1,57,311.5"/>
<path id="Fill-1208_1_" class="st0" d="M57,282.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C58.1,280,57,281.1,57,282.5"/>
<path id="Fill-1209_1_" class="st0" d="M57,255.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C58.1,253,57,254.1,57,255.5"/>
<path id="Fill-1222" class="st0" d="M85,367.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5S85,366.1,85,367.5"
/>
<path id="Fill-1223" class="st0" d="M85,339.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S85,338.1,85,339.5"/>
<path id="Fill-1224_1_" class="st0" d="M85,311.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S85,310.1,85,311.5"/>
<path id="Fill-1225_1_" class="st0" d="M85,282.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S85,281.1,85,282.5"/>
<path id="Fill-1226_1_" class="st0" d="M85,255.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
S85,254.1,85,255.5"/>
<path id="Fill-1239_1_" class="st0" d="M114,367.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,365,114,366.1,114,367.5"/>
<path id="Fill-1240_1_" class="st0" d="M114,339.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C115.1,337,114,338.1,114,339.5"/>
<path id="Fill-1241_1_" class="st0" d="M114,311.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C115.1,309,114,310.1,114,311.5"/>
<path id="Fill-1242_1_" class="st0" d="M114,282.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C115.1,280,114,281.1,114,282.5"/>
<path id="Fill-1243_1_" class="st0" d="M114,255.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,253,114,254.1,114,255.5"/>
<path id="Fill-1818_1_" class="st0" d="M0,198.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5S3.9,196,2.5,196S0,197.1,0,198.5"/>
<path id="Fill-1824_1_" class="st0" d="M28,198.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S28,197.1,28,198.5"/>
<path id="Fill-1171_2_" class="st0" d="M57,171.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
S57,170.1,57,171.5"/>
<path id="Fill-1172_2_" class="st0" d="M57,143.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S57,142.1,57,143.5"/>
<path id="Fill-1188_2_" class="st0" d="M85,171.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
S85,170.1,85,171.5"/>
<path id="Fill-1189_2_" class="st0" d="M85,143.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S85,142.1,85,143.5"/>
<path id="Fill-1176_2_" class="st0" d="M57,226.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S57,225.1,57,226.5"/>
<path id="Fill-1193_2_" class="st0" d="M85,226.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S85,225.1,85,226.5"/>
<path id="Fill-1818_2_" class="st0" d="M57,198.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S57,197.1,57,198.5"/>
<path id="Fill-1824_2_" class="st0" d="M85,198.5c0,1.4,1.1,2.5,2.5,2.5s2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5S85,197.1,85,198.5"/>
<path id="Fill-1842_1_" class="st0" d="M114,198.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,196,114,197.1,114,198.5"/>
<path id="Fill-1244_1_" class="st0" d="M114,226.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C115.1,224,114,225.1,114,226.5"/>
<path id="Fill-1239-Copy-2" class="st0" d="M143,171.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C144.1,169,143,170.1,143,171.5"/>
<path id="Fill-1240-Copy-2" class="st0" d="M143,143.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,141,143,142.1,143,143.5"/>
<path id="Fill-1241-Copy-2" class="st0" d="M143,115.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,113,143,114.1,143,115.5"/>
<path id="Fill-1242-Copy-2" class="st0" d="M143,86.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,84,143,85.1,143,86.5"/>
<path id="Fill-1243-Copy-2" class="st0" d="M143,59.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C144.1,57,143,58.1,143,59.5"/>
<path id="Fill-1842-Copy-2" class="st0" d="M143,2.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5S146.9,0,145.5,0
C144.1,0,143,1.1,143,2.5"/>
<path id="Fill-1244-Copy-2" class="st0" d="M143,30.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,28,143,29.1,143,30.5"/>
<path id="Fill-1239-Copy" class="st0" d="M143,367.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C144.1,365,143,366.1,143,367.5"/>
<path id="Fill-1240-Copy" class="st0" d="M143,339.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,337,143,338.1,143,339.5"/>
<path id="Fill-1241-Copy" class="st0" d="M143,311.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,309,143,310.1,143,311.5"/>
<path id="Fill-1242-Copy" class="st0" d="M143,282.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,280,143,281.1,143,282.5"/>
<path id="Fill-1243-Copy" class="st0" d="M143,255.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5c0-1.4-1.1-2.5-2.5-2.5
C144.1,253,143,254.1,143,255.5"/>
<path id="Fill-1842-Copy" class="st0" d="M143,198.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,196,143,197.1,143,198.5"/>
<path id="Fill-1244-Copy" class="st0" d="M143,226.5c0,1.4,1.1,2.5,2.5,2.5c1.4,0,2.5-1.1,2.5-2.5s-1.1-2.5-2.5-2.5
C144.1,224,143,225.1,143,226.5"/>
</g>
<linearGradient id="Rectangle-Copy-5_1_" gradientUnits="userSpaceOnUse" x1="-746.7155" y1="628.5056" x2="-746.7155" y2="627.5056" gradientTransform="matrix(420 0 0 -180 313831 113131)">
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0"/>
<stop offset="1" style="stop-color:#FFFFFF"/>
</linearGradient>
<rect id="Rectangle-Copy-5" x="0.5" class="st1" width="420" height="180"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,30 @@
function showPassword(e, elementId) {
let inputElem = document.getElementById(elementId);
if (inputElem.type === "password") {
inputElem.type = "text";
if (e.target.classList.contains('mdi')) {
e.target.classList.add('mdi-eye-off');
e.target.classList.remove('mdi-eye');
}
else {
let child = e.target.children[0];
if (child) {
child.classList.add('mdi-eye-off');
child.classList.remove('mdi-eye');
}
}
} else {
inputElem.type = "password";
if (e.target.classList.contains('mdi')) {
e.target.classList.add('mdi-eye');
e.target.classList.remove('mdi-eye-off');
}
else {
let child = e.target.children[0];
if (child) {
child.classList.add('mdi-eye');
child.classList.remove('mdi-eye-off');
}
}
}
}

View File

@@ -0,0 +1,174 @@
let Keyboard = window.SimpleKeyboard.default;
let keyboard;
let currentInputClass;
function setOptions() {
keyboard.setOptions({
layout: {
default: [
"q w e r t y u i o p",
"a s d f g h j k l {backspace}",
"{shift} z x c v b n m",
"{numbers} {space} {spchars}"
],
shift: [
"Q W E R T Y U I O P",
"A S D F G H J K L {backspace}",
"{shift} Z X C V B N M",
"{numbers} {space} {spchars}"
],
numbers: ["1 2 3", "4 5 6", "7 8 9", "{abc} 0 {backspace}"],
spchars: [
'! @ # $ % ^ & * ( ) _ +',
'~ - = ` \' " [ ] { }',
'< > ? | \\ / : ; , .',
'{numbers} {space} {abc}'
]
},
display: {
"{numbers}": "123",
"{escape}": "esc ⎋",
"{tab}": "tab ⇥",
"{backspace}": "⌫",
"{capslock}": "caps lock ⇪",
"{shift}": "⇧",
"{controlleft}": "ctrl ⌃",
"{controlright}": "ctrl ⌃",
"{altleft}": "alt ⌥",
"{altright}": "alt ⌥",
"{metaleft}": "cmd ⌘",
"{metaright}": "cmd ⌘",
"{abc}": "abc",
"{space}": "␣",
"{ent}": "↵",
"{spchars}": "#@$"
}
});
}
let selectedElem;
function onChange(input) {
selectedElem.value = input;
}
function onKeyPress(button) {
if (button === '{clear}') {
keyboard.setInput('');
selectedElem.value = '';
return;
}
let currentLayout = keyboard.options.layoutName;
if (currentLayout === 'numeric') {
return;
}
if (button === "{shift}") {
handleShift();
}
if (button === "{numbers}") {
handleNumbers();
}
if (button === "{abc}") {
handleAbc();
}
if (button === "{spchars}") {
handleSpecialChars();
}
}
function handleShift() {
let currentLayout = keyboard.options.layoutName;
let shiftToggle = currentLayout === "default" ? "shift" : "default";
keyboard.setOptions({
layoutName: shiftToggle
});
}
function handleNumbers() {
let currentLayout = keyboard.options.layoutName;
let numbersToggle = currentLayout !== "numbers" ? "numbers" : "default";
keyboard.setOptions({
layoutName: numbersToggle
});
}
function handleAbc() {
keyboard.setOptions({
layoutName: "default"
});
}
function handleSpecialChars() {
let currentLayout = keyboard.options.layoutName;
let spCharsToggle = currentLayout !== "spchars" ? "spchars" : "default";
keyboard.setOptions({
layoutName: spCharsToggle
});
}
function toggleKeyboard(e, inputElemClassName, maxLength) {
for (let item of document.getElementsByClassName('vr-keyboard-section')) {
item.innerHTML = '';
}
document.getElementById(inputElemClassName + "_con").innerHTML = '<div class="simple-keyboard-con"><div class="simple-keyboard"></div></div>';
if (selectedElem) {
selectedElem.removeEventListener('input', () => { });
}
if (currentInputClass === inputElemClassName) {
currentInputClass = '';
}
else {
currentInputClass = inputElemClassName;
keyboard = new Keyboard({
onChange: input => onChange(input),
onKeyPress: button => onKeyPress(button)
});
setOptions();
keyboard.setOptions({
maxLength: maxLength
});
selectedElem = document.querySelector(`.${inputElemClassName}`);
keyboard.setInput(selectedElem.value);
selectedElem.addEventListener("input", event => {
keyboard.setInput(event.target.value);
});
}
let keyboardConElem = document.querySelector('.simple-keyboard-con');
if (e.target.classList.contains('mdi')) {
if (e.target.classList.contains('mdi-keyboard')) {
document.querySelectorAll('.mdi-keyboard-off').forEach(e => {
e.classList.remove('mdi-keyboard-off');
e.classList.add('mdi-keyboard');
});
keyboardConElem.style.display = 'block';
e.target.classList.add('mdi-keyboard-off');
e.target.classList.remove('mdi-keyboard');
}
else {
keyboardConElem.style.display = 'none';
e.target.classList.add('mdi-keyboard');
e.target.classList.remove('mdi-keyboard-off');
}
}
else {
let child = e.target.children[0];
if (child) {
if (child.classList.contains('mdi-keyboard')) {
child.classList.add('mdi-keyboard-off');
child.classList.remove('mdi-keyboard');
}
else {
child.classList.add('mdi-keyboard');
child.classList.remove('mdi-keyboard-off');
}
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
// Unobtrusive Ajax support library for jQuery
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// @version v3.2.6
//
// Microsoft grants you the right to use these script files for the sole
// purpose of either: (i) interacting through your browser with the Microsoft
// website or online service, subject to the applicable licensing or use
// terms; or (ii) using the files as included with a Microsoft product subject
// to that product's license terms. Microsoft reserves all other rights to the
// files not expressly granted by Microsoft, whether by implication, estoppel
// or otherwise. Insofar as a script file is dual licensed under GPL,
// Microsoft neither took the code under GPL nor distributes it thereunder but
// under the terms set out in this paragraph. All notices and licenses
// below are for informational purposes only.
!function(t){function a(t,a){for(var e=window,r=(t||"").split(".");e&&r.length;)e=e[r.shift()];return"function"==typeof e?e:(a.push(t),Function.constructor.apply(null,a))}function e(t){return"GET"===t||"POST"===t}function r(t,a){e(a)||t.setRequestHeader("X-HTTP-Method-Override",a)}function n(a,e,r){var n;r.indexOf("application/x-javascript")===-1&&(n=(a.getAttribute("data-ajax-mode")||"").toUpperCase(),t(a.getAttribute("data-ajax-update")).each(function(a,r){switch(n){case"BEFORE":t(r).prepend(e);break;case"AFTER":t(r).append(e);break;case"REPLACE-WITH":t(r).replaceWith(e);break;default:t(r).html(e)}}))}function i(i,u){var o,c,d,s;if(o=i.getAttribute("data-ajax-confirm"),!o||window.confirm(o)){c=t(i.getAttribute("data-ajax-loading")),s=parseInt(i.getAttribute("data-ajax-loading-duration"),10)||0,t.extend(u,{type:i.getAttribute("data-ajax-method")||void 0,url:i.getAttribute("data-ajax-url")||void 0,cache:"true"===(i.getAttribute("data-ajax-cache")||"").toLowerCase(),beforeSend:function(t){var e;return r(t,d),e=a(i.getAttribute("data-ajax-begin"),["xhr"]).apply(i,arguments),e!==!1&&c.show(s),e},complete:function(){c.hide(s),a(i.getAttribute("data-ajax-complete"),["xhr","status"]).apply(i,arguments)},success:function(t,e,r){n(i,t,r.getResponseHeader("Content-Type")||"text/html"),a(i.getAttribute("data-ajax-success"),["data","status","xhr"]).apply(i,arguments)},error:function(){a(i.getAttribute("data-ajax-failure"),["xhr","status","error"]).apply(i,arguments)}}),u.data.push({name:"X-Requested-With",value:"XMLHttpRequest"}),d=u.type.toUpperCase(),e(d)||(u.type="POST",u.data.push({name:"X-HTTP-Method-Override",value:d}));var p=t(i);if(p.is("form")&&"multipart/form-data"==p.attr("enctype")){var f=new FormData;t.each(u.data,function(t,a){f.append(a.name,a.value)}),t("input[type=file]",p).each(function(){var a=this;t.each(a.files,function(t,e){f.append(a.name,e)})}),t.extend(u,{processData:!1,contentType:!1,data:f})}t.ajax(u)}}function u(a){var e=t(a).data(d);return!e||!e.validate||e.validate()}var o="unobtrusiveAjaxClick",c="unobtrusiveAjaxClickTarget",d="unobtrusiveValidation";t(document).on("click","a[data-ajax=true]",function(t){t.preventDefault(),i(this,{url:this.href,type:"GET",data:[]})}),t(document).on("click","form[data-ajax=true] input[type=image]",function(a){var e=a.target.name,r=t(a.target),n=t(r.parents("form")[0]),i=r.offset();n.data(o,[{name:e+".x",value:Math.round(a.pageX-i.left)},{name:e+".y",value:Math.round(a.pageY-i.top)}]),setTimeout(function(){n.removeData(o)},0)}),t(document).on("click","form[data-ajax=true] :submit",function(a){var e=a.currentTarget.name,r=t(a.target),n=t(r.parents("form")[0]);n.data(o,e?[{name:e,value:a.currentTarget.value}]:[]),n.data(c,r),setTimeout(function(){n.removeData(o),n.removeData(c)},0)}),t(document).on("submit","form[data-ajax=true]",function(a){var e=t(this).data(o)||[],r=t(this).data(c),n=r&&(r.hasClass("cancel")||void 0!==r.attr("formnovalidate"));a.preventDefault(),(n||u(this))&&i(this,{url:this.action,type:this.method||"GET",data:e.concat(t(this).serializeArray())})})}(jQuery);

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,12 @@
/*!
*
* simple-keyboard v2.28.46
* https://github.com/hodgef/simple-keyboard
*
* Copyright (c) Francisco Hodge (https://github.com/hodgef)
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/.hg-theme-default{width:100%;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-sizing:border-box;overflow:hidden;touch-action:manipulation}.hg-theme-default .hg-button span{pointer-events:none}.hg-theme-default button.hg-button{border-width:0;outline:0;font-size:inherit}.hg-theme-default{font-family:HelveticaNeue-Light,Helvetica Neue Light,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;background-color:#ececec;padding:5px;border-radius:5px}.hg-theme-default .hg-button{display:inline-block;flex-grow:1}.hg-theme-default .hg-row{display:flex}.hg-theme-default .hg-row:not(:last-child){margin-bottom:5px}.hg-theme-default .hg-row .hg-button-container,.hg-theme-default .hg-row .hg-button:not(:last-child){margin-right:5px}.hg-theme-default .hg-row>div:last-child{margin-right:0}.hg-theme-default .hg-row .hg-button-container{display:flex}.hg-theme-default .hg-button{box-shadow:0 0 3px -1px rgba(0,0,0,.3);height:40px;border-radius:5px;box-sizing:border-box;padding:5px;background:#fff;border-bottom:1px solid #b5b5b5;cursor:pointer;display:flex;align-items:center;justify-content:center;-webkit-tap-highlight-color:rgba(0,0,0,0)}.hg-theme-default .hg-button.hg-activeButton{background:#efefef}.hg-theme-default.hg-layout-numeric .hg-button{width:33.3%;height:60px;align-items:center;display:flex;justify-content:center}.hg-theme-default .hg-button.hg-button-numpadadd,.hg-theme-default .hg-button.hg-button-numpadenter{height:85px}.hg-theme-default .hg-button.hg-button-numpad0{width:105px}.hg-theme-default .hg-button.hg-button-com{max-width:85px}.hg-theme-default .hg-button.hg-standardBtn.hg-button-at{max-width:45px}.hg-theme-default .hg-button.hg-selectedButton{background:rgba(5,25,70,.53);color:#fff}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn=".com"]{max-width:82px}.hg-theme-default .hg-button.hg-standardBtn[data-skbtn="@"]{max-width:60px}
/*# sourceMappingURL=index.css.map */

View File

@@ -0,0 +1,943 @@
body.swal2-shown {
overflow-y: hidden
}
body.swal2-iosfix {
position: fixed;
left: 0;
right: 0
}
.swal2-container {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
padding: 10px;
background-color: transparent;
z-index: 1060
}
.swal2-container.swal2-fade {
-webkit-transition: background-color .1s;
transition: background-color .1s
}
.swal2-container.swal2-shown {
background-color: rgba(0,0,0,.4)
}
.swal2-modal {
background-color: #fff;
font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
border-radius: 5px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
text-align: center;
margin: auto;
overflow-x: hidden;
overflow-y: auto;
display: none;
position: relative;
max-width: 100%
}
.swal2-modal:focus {
outline: 0
}
.swal2-modal.swal2-loading {
overflow-y: hidden
}
.swal2-modal .swal2-title {
color: #595959;
font-size: 30px;
text-align: center;
font-weight: 600;
text-transform: none;
position: relative;
margin: 0 0 .4em;
padding: 0;
display: block;
word-wrap: break-word
}
.swal2-modal .swal2-buttonswrapper {
margin-top: 15px
}
.swal2-modal .swal2-buttonswrapper:not(.swal2-loading) .swal2-styled[disabled] {
opacity: .4;
cursor: no-drop
}
.swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-confirm {
-webkit-box-sizing: border-box;
box-sizing: border-box;
border: 4px solid transparent;
border-color: transparent;
width: 40px;
height: 40px;
padding: 0;
margin: 7.5px;
vertical-align: top;
background-color: transparent !important;
color: transparent;
cursor: default;
border-radius: 100%;
-webkit-animation: rotate-loading 1.5s linear 0s infinite normal;
animation: rotate-loading 1.5s linear 0s infinite normal;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
.swal2-modal .swal2-buttonswrapper.swal2-loading .swal2-styled.swal2-cancel {
margin-left: 30px;
margin-right: 30px
}
.swal2-modal .swal2-buttonswrapper.swal2-loading :not(.swal2-styled).swal2-confirm::after {
display: inline-block;
content: '';
margin-left: 5px;
vertical-align: -1px;
height: 15px;
width: 15px;
border: 3px solid #999;
-webkit-box-shadow: 1px 1px 1px #fff;
box-shadow: 1px 1px 1px #fff;
border-right-color: transparent;
border-radius: 50%;
-webkit-animation: rotate-loading 1.5s linear 0s infinite normal;
animation: rotate-loading 1.5s linear 0s infinite normal
}
.swal2-modal .swal2-styled {
border: 0;
border-radius: 3px;
-webkit-box-shadow: none;
box-shadow: none;
color: #fff;
cursor: pointer;
font-size: 17px;
font-weight: 500;
margin: 15px 5px 0;
padding: 10px 32px
}
.swal2-modal .swal2-styled:focus {
outline: 0;
-webkit-box-shadow: 0 0 0 2px #fff,0 0 0 4px rgba(50,100,150,.4);
box-shadow: 0 0 0 2px #fff,0 0 0 4px rgba(50,100,150,.4)
}
.swal2-modal .swal2-image {
margin: 20px auto;
max-width: 100%
}
.swal2-modal .swal2-close {
background: 0 0;
border: 0;
margin: 0;
padding: 0;
width: 38px;
height: 40px;
font-size: 36px;
line-height: 40px;
font-family: serif;
position: absolute;
top: 5px;
right: 8px;
cursor: pointer;
color: #ccc;
-webkit-transition: color .1s ease;
transition: color .1s ease
}
.swal2-modal .swal2-close:hover {
color: #d55
}
.swal2-modal > .swal2-checkbox, .swal2-modal > .swal2-file, .swal2-modal > .swal2-input, .swal2-modal > .swal2-radio, .swal2-modal > .swal2-select, .swal2-modal > .swal2-textarea {
display: none
}
.swal2-modal .swal2-content {
font-size: 18px;
text-align: center;
font-weight: 300;
position: relative;
float: none;
margin: 0;
padding: 0;
line-height: normal;
color: #545454;
word-wrap: break-word
}
.swal2-modal .swal2-checkbox, .swal2-modal .swal2-file, .swal2-modal .swal2-input, .swal2-modal .swal2-radio, .swal2-modal .swal2-select, .swal2-modal .swal2-textarea {
margin: 20px auto
}
.swal2-modal .swal2-file, .swal2-modal .swal2-input, .swal2-modal .swal2-textarea {
width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
font-size: 18px;
border-radius: 3px;
border: 1px solid #d9d9d9;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.06);
box-shadow: inset 0 1px 1px rgba(0,0,0,.06);
-webkit-transition: border-color .3s,-webkit-box-shadow .3s;
transition: border-color .3s,-webkit-box-shadow .3s;
transition: border-color .3s,box-shadow .3s;
transition: border-color .3s,box-shadow .3s,-webkit-box-shadow .3s
}
.swal2-modal .swal2-file.swal2-inputerror, .swal2-modal .swal2-input.swal2-inputerror, .swal2-modal .swal2-textarea.swal2-inputerror {
border-color: #f27474 !important;
-webkit-box-shadow: 0 0 2px #f27474 !important;
box-shadow: 0 0 2px #f27474 !important
}
.swal2-modal .swal2-file:focus, .swal2-modal .swal2-input:focus, .swal2-modal .swal2-textarea:focus {
outline: 0;
border: 1px solid #b4dbed;
-webkit-box-shadow: 0 0 3px #c4e6f5;
box-shadow: 0 0 3px #c4e6f5
}
.swal2-modal .swal2-file::-webkit-input-placeholder, .swal2-modal .swal2-input::-webkit-input-placeholder, .swal2-modal .swal2-textarea::-webkit-input-placeholder {
color: #ccc
}
.swal2-modal .swal2-file:-ms-input-placeholder, .swal2-modal .swal2-input:-ms-input-placeholder, .swal2-modal .swal2-textarea:-ms-input-placeholder {
color: #ccc
}
.swal2-modal .swal2-file::placeholder, .swal2-modal .swal2-input::placeholder, .swal2-modal .swal2-textarea::placeholder {
color: #ccc
}
.swal2-modal .swal2-range input {
float: left;
width: 80%
}
.swal2-modal .swal2-range output {
float: right;
width: 20%;
font-size: 20px;
font-weight: 600;
text-align: center
}
.swal2-modal .swal2-range input, .swal2-modal .swal2-range output {
height: 43px;
line-height: 43px;
vertical-align: middle;
margin: 20px auto;
padding: 0
}
.swal2-modal .swal2-input {
height: 43px;
padding: 0 12px
}
.swal2-modal .swal2-input[type=number] {
max-width: 150px
}
.swal2-modal .swal2-file {
font-size: 20px
}
.swal2-modal .swal2-textarea {
height: 108px;
padding: 12px
}
.swal2-modal .swal2-select {
color: #545454;
font-size: inherit;
padding: 5px 10px;
min-width: 40%;
max-width: 100%
}
.swal2-modal .swal2-radio {
border: 0
}
.swal2-modal .swal2-radio label:not(:first-child) {
margin-left: 20px
}
.swal2-modal .swal2-radio input, .swal2-modal .swal2-radio span {
vertical-align: middle
}
.swal2-modal .swal2-radio input {
margin: 0 3px 0 0
}
.swal2-modal .swal2-checkbox {
color: #545454
}
.swal2-modal .swal2-checkbox input, .swal2-modal .swal2-checkbox span {
vertical-align: middle
}
.swal2-modal .swal2-validationerror {
background-color: #f0f0f0;
margin: 0 -20px;
overflow: hidden;
padding: 10px;
color: gray;
font-size: 16px;
font-weight: 300;
display: none
}
.swal2-modal .swal2-validationerror::before {
content: '!';
display: inline-block;
width: 24px;
height: 24px;
border-radius: 50%;
background-color: #ea7d7d;
color: #fff;
line-height: 24px;
text-align: center;
margin-right: 10px
}
@supports (-ms-accelerator:true) {
.swal2-range input {
width: 100% !important
}
.swal2-range output {
display: none
}
}
@media all and (-ms-high-contrast:none),(-ms-high-contrast:active) {
.swal2-range input {
width: 100% !important
}
.swal2-range output {
display: none
}
}
.swal2-icon {
width: 80px;
height: 80px;
border: 4px solid transparent;
border-radius: 50%;
margin: 20px auto 30px;
padding: 0;
position: relative;
-webkit-box-sizing: content-box;
box-sizing: content-box;
cursor: default;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none
}
.swal2-icon.swal2-error {
border-color: #f27474
}
.swal2-icon.swal2-error .swal2-x-mark {
position: relative;
display: block
}
.swal2-icon.swal2-error [class^=swal2-x-mark-line] {
position: absolute;
height: 5px;
width: 47px;
background-color: #f27474;
display: block;
top: 37px;
border-radius: 2px
}
.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=left] {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
left: 17px
}
.swal2-icon.swal2-error [class^=swal2-x-mark-line][class$=right] {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
right: 16px
}
.swal2-icon.swal2-warning {
font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
color: #f8bb86;
border-color: #facea8;
font-size: 60px;
line-height: 80px;
text-align: center
}
.swal2-icon.swal2-info {
font-family: 'Open Sans',sans-serif;
color: #3fc3ee;
border-color: #9de0f6;
font-size: 60px;
line-height: 80px;
text-align: center
}
.swal2-icon.swal2-question {
font-family: 'Helvetica Neue',Helvetica,Arial,sans-serif;
color: #87adbd;
border-color: #c9dae1;
font-size: 60px;
line-height: 80px;
text-align: center
}
.swal2-icon.swal2-success {
border-color: #a5dc86
}
.swal2-icon.swal2-success [class^=swal2-success-circular-line] {
border-radius: 50%;
position: absolute;
width: 60px;
height: 120px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg)
}
.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=left] {
border-radius: 120px 0 0 120px;
top: -7px;
left: -33px;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
-webkit-transform-origin: 60px 60px;
transform-origin: 60px 60px
}
.swal2-icon.swal2-success [class^=swal2-success-circular-line][class$=right] {
border-radius: 0 120px 120px 0;
top: -11px;
left: 30px;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg);
-webkit-transform-origin: 0 60px;
transform-origin: 0 60px
}
.swal2-icon.swal2-success .swal2-success-ring {
width: 80px;
height: 80px;
border: 4px solid rgba(165,220,134,.2);
border-radius: 50%;
-webkit-box-sizing: content-box;
box-sizing: content-box;
position: absolute;
left: -4px;
top: -4px;
z-index: 2
}
.swal2-icon.swal2-success .swal2-success-fix {
width: 7px;
height: 90px;
position: absolute;
left: 28px;
top: 8px;
z-index: 1;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
.swal2-icon.swal2-success [class^=swal2-success-line] {
height: 5px;
background-color: #a5dc86;
display: block;
border-radius: 2px;
position: absolute;
z-index: 2
}
.swal2-icon.swal2-success [class^=swal2-success-line][class$=tip] {
width: 25px;
left: 14px;
top: 46px;
-webkit-transform: rotate(45deg);
transform: rotate(45deg)
}
.swal2-icon.swal2-success [class^=swal2-success-line][class$=long] {
width: 47px;
right: 8px;
top: 38px;
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
.swal2-progresssteps {
font-weight: 600;
margin: 0 0 20px;
padding: 0
}
.swal2-progresssteps li {
display: inline-block;
position: relative
}
.swal2-progresssteps .swal2-progresscircle {
background: #3085d6;
border-radius: 2em;
color: #fff;
height: 2em;
line-height: 2em;
text-align: center;
width: 2em;
z-index: 20
}
.swal2-progresssteps .swal2-progresscircle:first-child {
margin-left: 0
}
.swal2-progresssteps .swal2-progresscircle:last-child {
margin-right: 0
}
.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep {
background: #3085d6
}
.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progresscircle {
background: #add8e6
}
.swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progressline {
background: #add8e6
}
.swal2-progresssteps .swal2-progressline {
background: #3085d6;
height: .4em;
margin: 0 -1px;
z-index: 10
}
[class^=swal2] {
-webkit-tap-highlight-color: transparent
}
@-webkit-keyframes showSweetAlert {
0% {
-webkit-transform: scale(.7);
transform: scale(.7)
}
45% {
-webkit-transform: scale(1.05);
transform: scale(1.05)
}
80% {
-webkit-transform: scale(.95);
transform: scale(.95)
}
100% {
-webkit-transform: scale(1);
transform: scale(1)
}
}
@keyframes showSweetAlert {
0% {
-webkit-transform: scale(.7);
transform: scale(.7)
}
45% {
-webkit-transform: scale(1.05);
transform: scale(1.05)
}
80% {
-webkit-transform: scale(.95);
transform: scale(.95)
}
100% {
-webkit-transform: scale(1);
transform: scale(1)
}
}
@-webkit-keyframes hideSweetAlert {
0% {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1
}
100% {
-webkit-transform: scale(.5);
transform: scale(.5);
opacity: 0
}
}
@keyframes hideSweetAlert {
0% {
-webkit-transform: scale(1);
transform: scale(1);
opacity: 1
}
100% {
-webkit-transform: scale(.5);
transform: scale(.5);
opacity: 0
}
}
.swal2-show {
-webkit-animation: showSweetAlert .3s;
animation: showSweetAlert .3s
}
.swal2-show.swal2-noanimation {
-webkit-animation: none;
animation: none
}
.swal2-hide {
-webkit-animation: hideSweetAlert .15s forwards;
animation: hideSweetAlert .15s forwards
}
.swal2-hide.swal2-noanimation {
-webkit-animation: none;
animation: none
}
@-webkit-keyframes animate-success-tip {
0% {
width: 0;
left: 1px;
top: 19px
}
54% {
width: 0;
left: 1px;
top: 19px
}
70% {
width: 50px;
left: -8px;
top: 37px
}
84% {
width: 17px;
left: 21px;
top: 48px
}
100% {
width: 25px;
left: 14px;
top: 45px
}
}
@keyframes animate-success-tip {
0% {
width: 0;
left: 1px;
top: 19px
}
54% {
width: 0;
left: 1px;
top: 19px
}
70% {
width: 50px;
left: -8px;
top: 37px
}
84% {
width: 17px;
left: 21px;
top: 48px
}
100% {
width: 25px;
left: 14px;
top: 45px
}
}
@-webkit-keyframes animate-success-long {
0% {
width: 0;
right: 46px;
top: 54px
}
65% {
width: 0;
right: 46px;
top: 54px
}
84% {
width: 55px;
right: 0;
top: 35px
}
100% {
width: 47px;
right: 8px;
top: 38px
}
}
@keyframes animate-success-long {
0% {
width: 0;
right: 46px;
top: 54px
}
65% {
width: 0;
right: 46px;
top: 54px
}
84% {
width: 55px;
right: 0;
top: 35px
}
100% {
width: 47px;
right: 8px;
top: 38px
}
}
@-webkit-keyframes rotatePlaceholder {
0% {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
5% {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
12% {
-webkit-transform: rotate(-405deg);
transform: rotate(-405deg)
}
100% {
-webkit-transform: rotate(-405deg);
transform: rotate(-405deg)
}
}
@keyframes rotatePlaceholder {
0% {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
5% {
-webkit-transform: rotate(-45deg);
transform: rotate(-45deg)
}
12% {
-webkit-transform: rotate(-405deg);
transform: rotate(-405deg)
}
100% {
-webkit-transform: rotate(-405deg);
transform: rotate(-405deg)
}
}
.swal2-animate-success-line-tip {
-webkit-animation: animate-success-tip .75s;
animation: animate-success-tip .75s
}
.swal2-animate-success-line-long {
-webkit-animation: animate-success-long .75s;
animation: animate-success-long .75s
}
.swal2-success.swal2-animate-success-icon .swal2-success-circular-line-right {
-webkit-animation: rotatePlaceholder 4.25s ease-in;
animation: rotatePlaceholder 4.25s ease-in
}
@-webkit-keyframes animate-error-icon {
0% {
-webkit-transform: rotateX(100deg);
transform: rotateX(100deg);
opacity: 0
}
100% {
-webkit-transform: rotateX(0);
transform: rotateX(0);
opacity: 1
}
}
@keyframes animate-error-icon {
0% {
-webkit-transform: rotateX(100deg);
transform: rotateX(100deg);
opacity: 0
}
100% {
-webkit-transform: rotateX(0);
transform: rotateX(0);
opacity: 1
}
}
.swal2-animate-error-icon {
-webkit-animation: animate-error-icon .5s;
animation: animate-error-icon .5s
}
@-webkit-keyframes animate-x-mark {
0% {
-webkit-transform: scale(.4);
transform: scale(.4);
margin-top: 26px;
opacity: 0
}
50% {
-webkit-transform: scale(.4);
transform: scale(.4);
margin-top: 26px;
opacity: 0
}
80% {
-webkit-transform: scale(1.15);
transform: scale(1.15);
margin-top: -6px
}
100% {
-webkit-transform: scale(1);
transform: scale(1);
margin-top: 0;
opacity: 1
}
}
@keyframes animate-x-mark {
0% {
-webkit-transform: scale(.4);
transform: scale(.4);
margin-top: 26px;
opacity: 0
}
50% {
-webkit-transform: scale(.4);
transform: scale(.4);
margin-top: 26px;
opacity: 0
}
80% {
-webkit-transform: scale(1.15);
transform: scale(1.15);
margin-top: -6px
}
100% {
-webkit-transform: scale(1);
transform: scale(1);
margin-top: 0;
opacity: 1
}
}
.swal2-animate-x-mark {
-webkit-animation: animate-x-mark .5s;
animation: animate-x-mark .5s
}
@-webkit-keyframes rotate-loading {
0% {
-webkit-transform: rotate(0);
transform: rotate(0)
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg)
}
}
@keyframes rotate-loading {
0% {
-webkit-transform: rotate(0);
transform: rotate(0)
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg)
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

View File

@@ -0,0 +1,144 @@
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
h1:focus {
outline: none;
}
a, .btn-link {
color: #0071c1;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}
.content {
padding-top: 1.1rem;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid red;
}
.validation-message {
color: red;
}
#blazor-error-ui {
color-scheme: light only;
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
box-sizing: border-box;
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
.loading-progress {
position: relative;
display: block;
width: 8rem;
height: 8rem;
margin: 20vh auto 1rem auto;
}
.loading-progress circle {
fill: none;
stroke: #e0e0e0;
stroke-width: 0.6rem;
transform-origin: 50% 50%;
transform: rotate(-90deg);
}
.loading-progress circle:last-child {
stroke: #1b6ec2;
stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
transition: stroke-dasharray 0.05s ease-in-out;
}
.loading-progress-text {
position: absolute;
text-align: center;
font-weight: bold;
inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}
.loading-progress-text:after {
content: var(--blazor-load-percentage-text, "Loading");
}
code {
color: #c02d76;
}
.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
color: var(--bs-secondary-color);
text-align: end;
}
.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
text-align: start;
}
.loader {
--r1: 154%;
--r2: 68.5%;
width: 60px;
aspect-ratio: 1;
border-radius: 50%;
background: radial-gradient(var(--r1) var(--r2) at top,#0000 79.5%,#269af2 80%), radial-gradient(var(--r1) var(--r2) at bottom,#269af2 79.5%,#0000 80%), radial-gradient(var(--r1) var(--r2) at top,#0000 79.5%,#269af2 80%), #ccc;
background-size: 50.5% 220%;
background-position: -100% 0%,0% 0%,100% 0%;
background-repeat: no-repeat;
animation: l9 2s infinite linear;
position: relative;
display: block;
margin: 20vh auto 1rem auto;
}
@keyframes l9 {
33% {
background-position: 0% 33%,100% 33%,200% 33%
}
66% {
background-position: -100% 66%,0% 66%,100% 66%
}
100% {
background-position: 0% 100%,100% 100%,200% 100%
}
}

Some files were not shown because too many files have changed in this diff Show More