mirror of
https://github.com/Shchoholiev/shopping-assistant-web-client.git
synced 2025-04-11 01:18:50 +00:00
SA-240 Display messages writing in realtime
- Change SSE handling to display them as soon as they come - Change AddNewMessage() to disply messages and suggestions in realtime
This commit is contained in:
parent
fcc1edff3e
commit
20d24b8738
@ -101,17 +101,24 @@ public class ApiClient
|
|||||||
await SetAuthenticationAsync();
|
await SetAuthenticationAsync();
|
||||||
var count = 0; //
|
var count = 0; //
|
||||||
var requestUrl = $"{_httpClient.BaseAddress}{url}";
|
var requestUrl = $"{_httpClient.BaseAddress}{url}";
|
||||||
var response = await _httpClient.PostAsJsonAsync(requestUrl, obj);
|
var jsonBody = JsonConvert.SerializeObject(obj);
|
||||||
using var responseStream = await response.Content.ReadAsStreamAsync();
|
|
||||||
using var reader = new StreamReader(responseStream, Encoding.UTF8);
|
|
||||||
|
|
||||||
SearchEventType eventType = SearchEventType.Message;
|
var body = new StringContent(jsonBody, Encoding.UTF8, "application/json");
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
var request = new HttpRequestMessage(HttpMethod.Post, requestUrl)
|
||||||
{
|
{
|
||||||
var jsonChunk = await reader.ReadLineAsync(cancellationToken);
|
Content = body
|
||||||
|
};
|
||||||
|
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/event-stream"));
|
||||||
|
|
||||||
|
using var httpResponse = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
||||||
|
using var streamReader = new StreamReader(await httpResponse.Content.ReadAsStreamAsync(cancellationToken));
|
||||||
|
var eventType = SearchEventType.Message;
|
||||||
|
while (!streamReader.EndOfStream)
|
||||||
|
{
|
||||||
|
var jsonChunk = await streamReader.ReadLineAsync(cancellationToken);
|
||||||
count += 1; //
|
count += 1; //
|
||||||
if (count >=5 ){ //
|
if (count >=5 ){ //
|
||||||
break; //
|
yield break; //
|
||||||
}; //
|
}; //
|
||||||
if (jsonChunk == null) continue;
|
if (jsonChunk == null) continue;
|
||||||
if (jsonChunk.StartsWith("event: "))
|
if (jsonChunk.StartsWith("event: "))
|
||||||
|
@ -15,100 +15,107 @@ namespace ShoppingAssistantWebClient.Web.Pages;
|
|||||||
public partial class Chat : ComponentBase
|
public partial class Chat : ComponentBase
|
||||||
{
|
{
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
private ApiClient _apiClient { get; set; }
|
private ApiClient _apiClient { get; set; }
|
||||||
[Inject]
|
[Inject]
|
||||||
private NavigationManager Navigation { get; set; }
|
private NavigationManager Navigation { get; set; }
|
||||||
[Inject]
|
[Inject]
|
||||||
private SearchService _searchServise { get; set; }
|
private SearchService _searchServise { get; set; }
|
||||||
|
|
||||||
public List<Messages> Messages { get; set; }
|
public List<Messages> Messages { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public List<String> Products { get; set; } = new List<string>();
|
public List<String> Products { get; set; } = new List<string>();
|
||||||
|
|
||||||
public List<String> Suggestion { get; set; } = new List<String>();
|
public List<String> Suggestion { get; set; } = new List<String>();
|
||||||
|
|
||||||
public Messages Message { get; set; }
|
public Messages Message { get; set; }
|
||||||
public Messages MessageBot { get; set; }
|
public Messages MessageBot { get; set; }
|
||||||
|
|
||||||
private CancellationTokenSource cancelTokenSource;
|
private CancellationTokenSource cancelTokenSource;
|
||||||
private bool isWaitingForResponse = false;
|
private bool isWaitingForResponse = false;
|
||||||
private MessageCreateDto messageCreateDto;
|
private MessageCreateDto messageCreateDto;
|
||||||
public bool isLoading = true;
|
public bool isLoading = true;
|
||||||
private string name = "";
|
private string name = "";
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try{
|
var input = _searchServise.FirstMessage;
|
||||||
var input = _searchServise.FirstMessage;
|
|
||||||
|
|
||||||
if (input!=null){
|
if (input != null)
|
||||||
|
{
|
||||||
|
|
||||||
await LoadMessages();
|
await LoadMessages();
|
||||||
|
|
||||||
await AddNewMessage(input);
|
await AddNewMessage(input);
|
||||||
|
|
||||||
string wishlistId = chatId;
|
string wishlistId = chatId;
|
||||||
var request = new GraphQLRequest
|
var request = new GraphQLRequest
|
||||||
{
|
{
|
||||||
Query = @"mutation GenerateNameForPersonalWishlist($wishlistId: String!) {
|
Query = @"mutation GenerateNameForPersonalWishlist($wishlistId: String!) {
|
||||||
generateNameForPersonalWishlist(wishlistId: $wishlistId) {
|
generateNameForPersonalWishlist(wishlistId: $wishlistId) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}",
|
}",
|
||||||
Variables = new
|
Variables = new
|
||||||
{
|
{
|
||||||
wishlistId
|
wishlistId
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var response = await _apiClient.QueryAsync(request);
|
|
||||||
_searchServise.SetFirstMessage(null);
|
|
||||||
isLoading = false;
|
|
||||||
await UpdateSideMenu(wishlistId);
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
}else{
|
|
||||||
await LoadMessages();
|
|
||||||
}
|
}
|
||||||
}catch(Exception ex){
|
};
|
||||||
Console.WriteLine($"Error OnInitializedAsync: {ex.Message}");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var response = await _apiClient.QueryAsync(request);
|
||||||
|
_searchServise.SetFirstMessage(null);
|
||||||
|
isLoading = false;
|
||||||
|
await UpdateSideMenu(wishlistId);
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await LoadMessages();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error OnInitializedAsync: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private async Task LoadMessages()
|
|
||||||
|
private async Task LoadMessages()
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try{
|
string wishlistId = chatId;
|
||||||
string wishlistId = chatId;
|
|
||||||
|
|
||||||
var request = new GraphQLRequest
|
var request = new GraphQLRequest
|
||||||
{
|
{
|
||||||
Query = @"query PersonalWishlist( $wishlistId: String!) {
|
Query = @"query PersonalWishlist( $wishlistId: String!) {
|
||||||
personalWishlist(wishlistId: $wishlistId) {
|
personalWishlist(wishlistId: $wishlistId) {
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
}",
|
}",
|
||||||
|
|
||||||
Variables = new
|
Variables = new
|
||||||
{
|
{
|
||||||
wishlistId,
|
wishlistId,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var response = await _apiClient.QueryAsync(request);
|
var response = await _apiClient.QueryAsync(request);
|
||||||
var responseData = response.Data;
|
var responseData = response.Data;
|
||||||
name = responseData.personalWishlist.name;
|
name = responseData.personalWishlist.name;
|
||||||
|
|
||||||
|
|
||||||
isLoading = true;
|
isLoading = true;
|
||||||
int pageNumber = 1;
|
int pageNumber = 1;
|
||||||
request = new GraphQLRequest
|
request = new GraphQLRequest
|
||||||
{
|
{
|
||||||
Query = @"query MessagesPageFromPersonalWishlist($wishlistId: String!, $pageNumber: Int!, $pageSize: Int!) {
|
Query = @"query MessagesPageFromPersonalWishlist($wishlistId: String!, $pageNumber: Int!, $pageSize: Int!) {
|
||||||
messagesPageFromPersonalWishlist( wishlistId: $wishlistId, pageNumber: $pageNumber, pageSize: $pageSize)
|
messagesPageFromPersonalWishlist( wishlistId: $wishlistId, pageNumber: $pageNumber, pageSize: $pageSize)
|
||||||
{
|
{
|
||||||
items {
|
items {
|
||||||
@ -120,113 +127,125 @@ public partial class Chat : ComponentBase
|
|||||||
}
|
}
|
||||||
}",
|
}",
|
||||||
|
|
||||||
Variables = new
|
Variables = new
|
||||||
{
|
{
|
||||||
wishlistId,
|
wishlistId,
|
||||||
pageNumber,
|
pageNumber,
|
||||||
pageSize = 200
|
pageSize = 200
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
response = await _apiClient.QueryAsync(request);
|
response = await _apiClient.QueryAsync(request);
|
||||||
responseData = response.Data;
|
responseData = response.Data;
|
||||||
var jsonCategoriesResponse = JsonConvert.SerializeObject(responseData.messagesPageFromPersonalWishlist.items);
|
var jsonCategoriesResponse = JsonConvert.SerializeObject(responseData.messagesPageFromPersonalWishlist.items);
|
||||||
this.Messages = JsonConvert.DeserializeObject<List<Messages>>(jsonCategoriesResponse);
|
this.Messages = JsonConvert.DeserializeObject<List<Messages>>(jsonCategoriesResponse);
|
||||||
Messages.Reverse();
|
Messages.Reverse();
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
|
||||||
}catch(Exception ex){
|
|
||||||
Console.WriteLine($"Error : {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Error : {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
private async Task AddNewMessage(string inputMessage)
|
private async Task AddNewMessage(string inputMessage)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!isWaitingForResponse && !string.IsNullOrWhiteSpace(inputMessage))
|
if (!isWaitingForResponse && !string.IsNullOrWhiteSpace(inputMessage))
|
||||||
{
|
{
|
||||||
JSRuntime.InvokeVoidAsync("clearInput");
|
JSRuntime.InvokeVoidAsync("clearInput");
|
||||||
isWaitingForResponse = true;
|
isWaitingForResponse = true;
|
||||||
|
|
||||||
try{
|
try
|
||||||
messageCreateDto = new MessageCreateDto { Text = inputMessage };;
|
{
|
||||||
Message = new Messages();
|
messageCreateDto = new MessageCreateDto { Text = inputMessage }; ;
|
||||||
Message.Text = inputMessage;
|
Message = new Messages();
|
||||||
Message.Role = "User";
|
Message.Text = inputMessage;
|
||||||
Message.Id = "";
|
Message.Role = "User";
|
||||||
Message.CreatedById = "";
|
Message.Id = "";
|
||||||
|
Message.CreatedById = "";
|
||||||
Suggestion = new List<String>();
|
|
||||||
Products = new List<String>();
|
|
||||||
Messages.Add(Message);
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
cancelTokenSource = new CancellationTokenSource();
|
|
||||||
var cancellationToken = cancelTokenSource.Token;
|
|
||||||
|
|
||||||
var serverSentEvent = _apiClient.GetServerSentEventStreamed($"ProductsSearch/search/{chatId}", messageCreateDto, cancellationToken);
|
|
||||||
bool first = true;
|
|
||||||
|
|
||||||
MessageBot = new Messages();
|
|
||||||
MessageBot.Role = "bot";
|
|
||||||
MessageBot.Id = "";
|
|
||||||
MessageBot.CreatedById = "";
|
|
||||||
MessageBot.Text = "Waiting for response";
|
|
||||||
Messages.Add(MessageBot);
|
|
||||||
var lengt = Messages.Count();
|
|
||||||
StateHasChanged();
|
|
||||||
|
|
||||||
await foreach (var sseEvent in serverSentEvent.WithCancellation(cancellationToken))
|
|
||||||
{
|
|
||||||
Console.WriteLine($"Received SSE Event: {sseEvent.Event}, Data: {sseEvent.Data}");
|
|
||||||
|
|
||||||
string input = sseEvent.Data;
|
|
||||||
Regex regex = new Regex("\"(.*?)\"");
|
|
||||||
Match match = regex.Match(input);
|
|
||||||
string result = match.Groups[1].Value;
|
|
||||||
|
|
||||||
if(sseEvent.Event == SearchEventType.Message){
|
|
||||||
|
|
||||||
|
|
||||||
if (first)
|
|
||||||
{
|
|
||||||
Messages[lengt-1].Text = result;
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Messages[lengt-1].Text += result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Suggestion = new List<String>();
|
||||||
|
Products = new List<String>();
|
||||||
|
Messages.Add(Message);
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
|
|
||||||
} else if(sseEvent.Event == SearchEventType.Product){
|
cancelTokenSource = new CancellationTokenSource();
|
||||||
|
var cancellationToken = cancelTokenSource.Token;
|
||||||
|
|
||||||
string pattern = "[\\\\\"]";
|
var serverSentEvent = _apiClient.GetServerSentEventStreamed($"ProductsSearch/search/{chatId}", messageCreateDto, cancellationToken);
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
input = Regex.Replace(input, pattern, "");
|
MessageBot = new Messages();
|
||||||
|
MessageBot.Role = "bot";
|
||||||
|
MessageBot.Id = "";
|
||||||
|
MessageBot.CreatedById = "";
|
||||||
|
MessageBot.Text = "Waiting for response";
|
||||||
|
Messages.Add(MessageBot);
|
||||||
|
var lengt = Messages.Count();
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
Products.Add(input);
|
await foreach (var sseEvent in serverSentEvent.WithCancellation(cancellationToken))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Received SSE Event: {sseEvent.Event}, Data: {sseEvent.Data}");
|
||||||
|
|
||||||
} else if(sseEvent.Event == SearchEventType.Suggestion){
|
string input = sseEvent.Data;
|
||||||
if(Suggestion.Count<3){
|
Regex regex = new Regex("\"(.*?)\"");
|
||||||
Suggestion.Add(result);
|
Match match = regex.Match(input);
|
||||||
|
string result = match.Groups[1].Value;
|
||||||
|
|
||||||
|
if (sseEvent.Event == SearchEventType.Message)
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
Messages[lengt - 1].Text = result;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Messages[lengt - 1].Text += result;
|
||||||
|
}
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (sseEvent.Event == SearchEventType.Product)
|
||||||
|
{
|
||||||
|
|
||||||
|
string pattern = "[\\\\\"]";
|
||||||
|
|
||||||
|
input = Regex.Replace(input, pattern, "");
|
||||||
|
|
||||||
|
Products.Add(input);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (sseEvent.Event == SearchEventType.Suggestion)
|
||||||
|
{
|
||||||
|
if (Suggestion.Count < 3)
|
||||||
|
{
|
||||||
|
Suggestion.Add(result);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (Products.Count != 0)
|
||||||
if(Products.Count!=0) {
|
{
|
||||||
string n = name;
|
string n = name;
|
||||||
_searchServise.SetProducts(Products);
|
_searchServise.SetProducts(Products);
|
||||||
Products = null;
|
Products = null;
|
||||||
var url = $"/cards/{name}/{chatId}";
|
var url = $"/cards/{name}/{chatId}";
|
||||||
Navigation.NavigateTo(url);
|
Navigation.NavigateTo(url);
|
||||||
|
}
|
||||||
|
isWaitingForResponse = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
isWaitingForResponse = false;
|
catch (Exception ex)
|
||||||
} catch(Exception ex){
|
{
|
||||||
Console.WriteLine($"Error : {ex.Message}");
|
Console.WriteLine($"Error : {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user