...
This commit is contained in:
@@ -4,6 +4,7 @@ using Hushian.Application.Contracts.Persistence;
|
|||||||
using Hushian.Application.Models;
|
using Hushian.Application.Models;
|
||||||
using Hushian.Domain.Entites;
|
using Hushian.Domain.Entites;
|
||||||
using Hushian.WebApi;
|
using Hushian.WebApi;
|
||||||
|
using Microsoft.AspNetCore.Routing.Constraints;
|
||||||
using Microsoft.AspNetCore.SignalR;
|
using Microsoft.AspNetCore.SignalR;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
using System;
|
||||||
@@ -278,6 +279,23 @@ namespace Hushian.Application.Services
|
|||||||
}
|
}
|
||||||
if (dto.Type != ConversationType.UE)
|
if (dto.Type != ConversationType.UE)
|
||||||
await WriteInHubFromCompany(Response.Value, convModel.UserID);
|
await WriteInHubFromCompany(Response.Value, convModel.UserID);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var modelA = convModel.ConversationResponses.OrderBy(o => o.ID)
|
||||||
|
.LastOrDefault(l => l.Type == ConversationType.EU || l.Type == ConversationType.CU);
|
||||||
|
if (modelA != null)
|
||||||
|
{
|
||||||
|
int userid = 0;
|
||||||
|
|
||||||
|
if (modelA.Type == ConversationType.EU) userid = modelA.ExperID.Value;
|
||||||
|
|
||||||
|
else if (modelA.Type == ConversationType.CU) userid = modelA.conversation.CompanyID;
|
||||||
|
|
||||||
|
await WriteInHubFromUser(Response.Value, userid);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else Response.Errors.Add("گفتگویی یافت نشد");
|
else Response.Errors.Add("گفتگویی یافت نشد");
|
||||||
@@ -360,8 +378,23 @@ namespace Hushian.Application.Services
|
|||||||
{
|
{
|
||||||
item.IsRead = true;
|
item.IsRead = true;
|
||||||
item.ReadDateTime = DateTime.Now;
|
item.ReadDateTime = DateTime.Now;
|
||||||
|
if (!item.ExperID.HasValue)
|
||||||
item.ExperID = ExperID;
|
item.ExperID = ExperID;
|
||||||
return (await _ConversationResponseRepository.UPDATE(item)) != null;
|
|
||||||
|
|
||||||
|
if( (await _ConversationResponseRepository.UPDATE(item)) != null)
|
||||||
|
{
|
||||||
|
int userID = 0;
|
||||||
|
if (item.Type == ConversationType.EU) userID = item.ExperID.Value;
|
||||||
|
|
||||||
|
else if (item.Type == ConversationType.CU) userID = item.conversation.CompanyID;
|
||||||
|
|
||||||
|
else if (item.Type == ConversationType.UE) userID = item.conversation.UserID;
|
||||||
|
|
||||||
|
await CheckMarkAsReadInHub(item.ID, userID);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,19 +498,16 @@ namespace Hushian.Application.Services
|
|||||||
// // .SendAsync("ReceiveNewConversation", conv.Id, conv.Title);
|
// // .SendAsync("ReceiveNewConversation", conv.Id, conv.Title);
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
public async Task WriteInHubFromUser(ChatItemResponseDto item)
|
public async Task WriteInHubFromUser(ChatItemResponseDto item, int UserID)
|
||||||
{
|
{
|
||||||
await _hubContext.Clients.User(UserID.ToString())
|
await _hubContext.Clients.User(UserID.ToString())
|
||||||
.SendAsync("ReceiveNewChatItemFromCompany", item);
|
.SendAsync("ReceiveNewChatItemFromUser", item);
|
||||||
|
}
|
||||||
|
public async Task CheckMarkAsReadInHub(int item, int UserID)
|
||||||
|
{
|
||||||
|
await _hubContext.Clients.User(UserID.ToString())
|
||||||
|
.SendAsync("CheckMarkAsRead", item);
|
||||||
|
}
|
||||||
|
|
||||||
//// فرض: لیستی از کاربرانی که به گفتگو دسترسی دارند
|
|
||||||
//var usernames = new List<string>();
|
|
||||||
|
|
||||||
//foreach (var usn in usernames)
|
|
||||||
//{
|
|
||||||
// //await _hubContext.Clients.User(usn)
|
|
||||||
// // .SendAsync("ReceiveNewConversation", conv.Id, conv.Title);
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -206,12 +206,12 @@ namespace Hushian.WebApi.Controllers.v1
|
|||||||
[Authorize(Roles = "Company,User,Exper")]
|
[Authorize(Roles = "Company,User,Exper")]
|
||||||
public async Task<ActionResult> MarkAsReadChatItem(int ConversationItemID)
|
public async Task<ActionResult> MarkAsReadChatItem(int ConversationItemID)
|
||||||
{
|
{
|
||||||
int? ExperID = null;
|
int? ID = null;
|
||||||
ConversationType Type = ConversationType.UE;
|
ConversationType Type = ConversationType.UE;
|
||||||
if (User.IsInRole("Exper"))
|
if (User.IsInRole("Exper"))
|
||||||
{
|
{
|
||||||
string strExperID = User.Claims.Where(w => w.Type == CustomClaimTypes.Uid).Select(s => s.Value).First();
|
string strExperID = User.Claims.Where(w => w.Type == CustomClaimTypes.Uid).Select(s => s.Value).First();
|
||||||
ExperID = Convert.ToInt32(strExperID);
|
ID = Convert.ToInt32(strExperID);
|
||||||
Type = ConversationType.EU;
|
Type = ConversationType.EU;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ namespace Hushian.WebApi.Controllers.v1
|
|||||||
}
|
}
|
||||||
else return Unauthorized();
|
else return Unauthorized();
|
||||||
|
|
||||||
return await _chatService.MarkAsReadChatItem(ConversationItemID, Type, ExperID) ? NoContent()
|
return await _chatService.MarkAsReadChatItem(ConversationItemID, Type, ID) ? NoContent()
|
||||||
: BadRequest(new List<string>() { "خطا در بروزرسانی گفتگو" });
|
: BadRequest(new List<string>() { "خطا در بروزرسانی گفتگو" });
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -5,11 +5,15 @@
|
|||||||
@using Common.Enums
|
@using Common.Enums
|
||||||
@using HushianWebApp.Components
|
@using HushianWebApp.Components
|
||||||
@using HushianWebApp.Service
|
@using HushianWebApp.Service
|
||||||
|
@using HushianWebApp.Services
|
||||||
|
@using Microsoft.AspNetCore.SignalR.Client
|
||||||
@inject ChatService chatService
|
@inject ChatService chatService
|
||||||
@inject GroupService groupService
|
@inject GroupService groupService
|
||||||
@inject UserService userService
|
@inject UserService userService
|
||||||
@inject IJSRuntime JS
|
@inject IJSRuntime JS
|
||||||
@inject ToastService toastService
|
@inject ToastService toastService
|
||||||
|
@inject ILocalStorageService localStorageService;
|
||||||
|
@inject HttpClient _Http;
|
||||||
<ConfirmDialog @ref="dialog" />
|
<ConfirmDialog @ref="dialog" />
|
||||||
<Modal @ref="modal" IsVerticallyCentered="true" IsScrollable="true" />
|
<Modal @ref="modal" IsVerticallyCentered="true" IsScrollable="true" />
|
||||||
<PageTitle>گفتمان</PageTitle>
|
<PageTitle>گفتمان</PageTitle>
|
||||||
@@ -63,7 +67,8 @@
|
|||||||
<div class="item-content">
|
<div class="item-content">
|
||||||
<div class="item-header">
|
<div class="item-header">
|
||||||
<strong class="item-name">@item.UserFullName </strong>
|
<strong class="item-name">@item.UserFullName </strong>
|
||||||
@if(!string.IsNullOrEmpty(item.GroupName)){
|
@if (!string.IsNullOrEmpty(item.GroupName))
|
||||||
|
{
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<Badge Color="BadgeColor.Info" VisuallyHiddenText="Visually hidden text for Info">@item.GroupName</Badge>
|
<Badge Color="BadgeColor.Info" VisuallyHiddenText="Visually hidden text for Info">@item.GroupName</Badge>
|
||||||
</div>
|
</div>
|
||||||
@@ -161,8 +166,7 @@
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button Color="ButtonColor.Secondary" Size=ButtonSize.ExtraSmall Outline="true" Class="toexper-btn" @onclick="onclickAttachedto">
|
<Button Color="ButtonColor.Secondary" Size=ButtonSize.ExtraSmall Outline="true" Class="toexper-btn" @onclick="onclickAttachedto">
|
||||||
<Icon Name="IconName.EnvelopeArrowUp"
|
<Icon Name="IconName.EnvelopeArrowUp" /> پیوست به...
|
||||||
/> پیوست به...
|
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
else if (ChatCurrent.status == Common.Enums.ConversationStatus.Finished
|
else if (ChatCurrent.status == Common.Enums.ConversationStatus.Finished
|
||||||
@@ -270,23 +274,24 @@
|
|||||||
|
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
public Common.Dtos.CurrentUserInfo CurrentUser { get; set; }
|
Common.Dtos.CurrentUserInfo CurrentUser { get; set; }
|
||||||
List<Read_GroupDto> _Group = new List<Read_GroupDto>();
|
List<Read_GroupDto> _Group = new List<Read_GroupDto>();
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
bool isSelectedInbox1 = false;
|
bool isSelectedInbox1 = false;
|
||||||
public List<ChatItemDto> Inbox1Items { get; set; } = new();
|
List<ChatItemDto> Inbox1Items { get; set; } = new();
|
||||||
bool isSelectedInbox2 = true;
|
bool isSelectedInbox2 = true;
|
||||||
public List<ChatItemDto> Inbox2Items { get; set; } = new();
|
List<ChatItemDto> Inbox2Items { get; set; } = new();
|
||||||
bool isSelectedInbox3 = false;
|
bool isSelectedInbox3 = false;
|
||||||
public List<ChatItemDto> Inbox3Items { get; set; } = new();
|
List<ChatItemDto> Inbox3Items { get; set; } = new();
|
||||||
/////////////
|
/////////////
|
||||||
public ChatItemDto? ChatCurrent { get; set; } = null;
|
ChatItemDto? ChatCurrent { get; set; } = null;
|
||||||
public string MsgInput { get; set; }
|
string MsgInput { get; set; }
|
||||||
bool chatloading = false;
|
bool chatloading = false;
|
||||||
string SelectedChatUserName = "مهدی ربیع نژاد";
|
string SelectedChatUserName = "مهدی ربیع نژاد";
|
||||||
private bool _shouldObserveVisibility = false;
|
private bool _shouldObserveVisibility = false;
|
||||||
private ConfirmDialog dialog = default!;
|
private ConfirmDialog dialog = default!;
|
||||||
private Modal modal = default!;
|
private Modal modal = default!;
|
||||||
|
private HubConnection? hubConnection;
|
||||||
}
|
}
|
||||||
@functions {
|
@functions {
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
@@ -297,6 +302,39 @@
|
|||||||
Inbox2Items = await chatService.MyChatsIsInProgress();
|
Inbox2Items = await chatService.MyChatsIsInProgress();
|
||||||
Inbox3Items = await chatService.MyChatsIsFinished();
|
Inbox3Items = await chatService.MyChatsIsFinished();
|
||||||
|
|
||||||
|
//-------------hub
|
||||||
|
var token = await localStorageService.GetItem<string>("U/key");
|
||||||
|
string AddressHub = _Http.BaseAddress.AbsoluteUri.Replace("api/", "");
|
||||||
|
|
||||||
|
hubConnection = new HubConnectionBuilder()
|
||||||
|
.WithUrl($"{_Http.BaseAddress.AbsoluteUri.Replace("api/", "")}chatNotificationHub", options =>
|
||||||
|
{
|
||||||
|
options.AccessTokenProvider = () => Task.FromResult(token);
|
||||||
|
})
|
||||||
|
.WithAutomaticReconnect()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
hubConnection.On<ChatItemResponseDto>("ReceiveNewChatItemFromUser", async (chatitem) =>
|
||||||
|
{
|
||||||
|
if (ChatCurrent.ID == chatitem.ChatItemID)
|
||||||
|
{
|
||||||
|
ChatCurrent.Responses.Add(chatitem);
|
||||||
|
StateHasChanged();
|
||||||
|
await MarkAsRead(chatitem.ID);
|
||||||
|
// Scroll to target if exists, otherwise scroll to bottom
|
||||||
|
await JS.InvokeVoidAsync("scrollToTargetOrBottom");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
hubConnection.On<int>("CheckMarkAsRead", async (chatresponseid) =>
|
||||||
|
{
|
||||||
|
if (ChatCurrent.Responses.Any(a => a.ID == chatresponseid && !a.IsRead && (a.Type == Common.Enums.ConversationType.EU || a.Type == Common.Enums.ConversationType.CU)))
|
||||||
|
{ ChatCurrent.Responses.First(a => a.ID == chatresponseid).IsRead = true; StateHasChanged(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
await hubConnection.StartAsync();
|
||||||
|
//---------end hub
|
||||||
|
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
}
|
}
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
@@ -339,12 +377,13 @@
|
|||||||
if (!string.IsNullOrEmpty(MsgInput) && ChatCurrent != null)
|
if (!string.IsNullOrEmpty(MsgInput) && ChatCurrent != null)
|
||||||
{
|
{
|
||||||
Common.Enums.ConversationType type = CurrentUser.Role == "Company" ? Common.Enums.ConversationType.CU : Common.Enums.ConversationType.EU;
|
Common.Enums.ConversationType type = CurrentUser.Role == "Company" ? Common.Enums.ConversationType.CU : Common.Enums.ConversationType.EU;
|
||||||
await chatService.ADDChatResponse(ChatCurrent.ID, MsgInput, type);
|
var geter= await chatService.ADDChatResponse(ChatCurrent.ID, MsgInput, type);
|
||||||
ChatCurrent?.Responses.Add(new() { text = MsgInput, Type = type });
|
if(geter!=null)
|
||||||
|
{ChatCurrent?.Responses.Add(geter);
|
||||||
ChatCurrent.LastText = MsgInput;
|
ChatCurrent.LastText = MsgInput;
|
||||||
await Task.Yield();
|
await Task.Yield();
|
||||||
await JS.InvokeVoidAsync("scrollToBottom", "B1");
|
await JS.InvokeVoidAsync("scrollToBottom", "B1");
|
||||||
MsgInput = string.Empty;
|
MsgInput = string.Empty;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async Task onClickSelectedChat(int InboxID, ChatItemDto chatItem)
|
async Task onClickSelectedChat(int InboxID, ChatItemDto chatItem)
|
||||||
@@ -467,8 +506,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@@keyframes shimmer {
|
@@keyframes shimmer {
|
||||||
0% { transform: translateX(-100%) translateY(-100%) rotate(45deg); }
|
0% {
|
||||||
100% { transform: translateX(100%) translateY(100%) rotate(45deg); }
|
transform: translateX(-100%) translateY(-100%) rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(100%) translateY(100%) rotate(45deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-content {
|
.header-content {
|
||||||
@@ -776,6 +820,7 @@
|
|||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
box-shadow: 0 2px 4px rgba(220, 53, 69, 0.3);
|
box-shadow: 0 2px 4px rgba(220, 53, 69, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
box-shadow: 0 4px 8px rgba(220, 53, 69, 0.4);
|
box-shadow: 0 4px 8px rgba(220, 53, 69, 0.4);
|
||||||
@@ -1015,7 +1060,6 @@
|
|||||||
|
|
||||||
/* Empty state styling */
|
/* Empty state styling */
|
||||||
.chat-area-container .d-flex.justify-content-center {
|
.chat-area-container .d-flex.justify-content-center {
|
||||||
|
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
margin: 1rem;
|
margin: 1rem;
|
||||||
@@ -1190,14 +1234,20 @@
|
|||||||
0%, 100% {
|
0%, 100% {
|
||||||
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.2), 0 2px 4px rgba(0, 0, 0, 0.1);
|
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.2), 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
box-shadow: 0 6px 16px rgba(255, 193, 7, 0.3), 0 4px 8px rgba(0, 0, 0, 0.15);
|
box-shadow: 0 6px 16px rgba(255, 193, 7, 0.3), 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@keyframes warningShimmer {
|
@@keyframes warningShimmer {
|
||||||
0% { left: -100%; }
|
0% {
|
||||||
100% { left: 100%; }
|
left: -100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
left: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.warning-icon {
|
.warning-icon {
|
||||||
@@ -1218,6 +1268,7 @@
|
|||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.4);
|
box-shadow: 0 4px 12px rgba(255, 193, 7, 0.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
transform: scale(1.05);
|
transform: scale(1.05);
|
||||||
box-shadow: 0 6px 16px rgba(255, 193, 7, 0.6);
|
box-shadow: 0 6px 16px rgba(255, 193, 7, 0.6);
|
||||||
@@ -1291,6 +1342,7 @@
|
|||||||
background-color: #23caba;
|
background-color: #23caba;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.toexper-btn {
|
.toexper-btn {
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
@inject ChatService chatService
|
@inject ChatService chatService
|
||||||
@inject IJSRuntime JS
|
@inject IJSRuntime JS
|
||||||
@inject ToastService toastService
|
@inject ToastService toastService
|
||||||
|
@inject HttpClient _Http;
|
||||||
@layout UserPanelLayout
|
@layout UserPanelLayout
|
||||||
<ConfirmDialog @ref="dialog" />
|
<ConfirmDialog @ref="dialog" />
|
||||||
|
|
||||||
@@ -262,14 +263,14 @@
|
|||||||
}
|
}
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
Console.WriteLine($"🔔 welcome");
|
|
||||||
|
|
||||||
await IsOnline();
|
await IsOnline();
|
||||||
//-------------hub
|
//-------------hub
|
||||||
var token = await localStorageService.GetItem<string>("U/key");
|
var token = await localStorageService.GetItem<string>("U/key");
|
||||||
|
string AddressHub = _Http.BaseAddress.AbsoluteUri.Replace("api/", "");
|
||||||
|
|
||||||
hubConnection = new HubConnectionBuilder()
|
hubConnection = new HubConnectionBuilder()
|
||||||
.WithUrl("http://localhost:5089/chatNotificationHub", options =>
|
.WithUrl($"{AddressHub}chatNotificationHub", options =>
|
||||||
{
|
{
|
||||||
options.AccessTokenProvider = () => Task.FromResult(token);
|
options.AccessTokenProvider = () => Task.FromResult(token);
|
||||||
})
|
})
|
||||||
@@ -287,6 +288,15 @@
|
|||||||
await JS.InvokeVoidAsync("scrollToTargetOrBottom");
|
await JS.InvokeVoidAsync("scrollToTargetOrBottom");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
//-------------------------------------
|
||||||
|
hubConnection.On<int>("CheckMarkAsRead", async (chatresponseid) =>
|
||||||
|
{
|
||||||
|
if (LastOpenChat.Responses.Any(a=>a.ID==chatresponseid && !a.IsRead && a.Type==Common.Enums.ConversationType.UE))
|
||||||
|
{
|
||||||
|
LastOpenChat.Responses.First(a => a.ID == chatresponseid).IsRead = true;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
await hubConnection.StartAsync();
|
await hubConnection.StartAsync();
|
||||||
//---------end hub
|
//---------end hub
|
||||||
|
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Components;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using static System.Net.WebRequestMethods;
|
||||||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||||
|
|
||||||
namespace HushianWebApp.Service
|
namespace HushianWebApp.Service
|
||||||
@@ -54,6 +55,7 @@ namespace HushianWebApp.Service
|
|||||||
}
|
}
|
||||||
public async Task<Tuple<string, HttpResponseMessage>> PostLogin(string route, object mode)
|
public async Task<Tuple<string, HttpResponseMessage>> PostLogin(string route, object mode)
|
||||||
{
|
{
|
||||||
|
|
||||||
var result = await _Http.PostAsJsonAsync(route, mode);
|
var result = await _Http.PostAsJsonAsync(route, mode);
|
||||||
if (result.IsSuccessStatusCode)
|
if (result.IsSuccessStatusCode)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user