Browse Source

Fix mentions for long text and fix some text

pull/1006/head
Sebastian 3 years ago
parent
commit
a3479308de
  1. 2
      backend/i18n/frontend_en.json
  2. 2
      backend/i18n/frontend_fr.json
  3. 2
      backend/i18n/frontend_it.json
  4. 2
      backend/i18n/frontend_nl.json
  5. 2
      backend/i18n/frontend_pt.json
  6. 2
      backend/i18n/frontend_zh.json
  7. 2
      backend/i18n/source/frontend_en.json
  8. 40
      backend/src/Squidex.Domain.Apps.Entities/Comments/DomainObject/CommentsCommandMiddleware.cs
  9. 20
      backend/tests/Squidex.Domain.Apps.Entities.Tests/Comments/DomainObject/CommentsCommandMiddlewareTests.cs
  10. 2
      frontend/src/app/features/content/shared/forms/chat-dialog.component.html
  11. 2
      frontend/src/app/features/content/shared/forms/chat-dialog.component.scss
  12. 4
      frontend/src/app/features/content/shared/forms/chat-dialog.component.ts

2
backend/i18n/frontend_en.json

@ -166,6 +166,8 @@
"backups.started": "Backup started, it can take several minutes to complete.",
"backups.startedLabel": "Started",
"backups.startFailed": "Failed to start backup.",
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.prompt": "Describe the content you want to generate",

2
backend/i18n/frontend_fr.json

@ -166,6 +166,8 @@
"backups.started": "La sauvegarde a commencé, cela peut prendre plusieurs minutes.",
"backups.startedLabel": "Commencé",
"backups.startFailed": "Échec du démarrage de la sauvegarde.",
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.prompt": "Describe the content you want to generate",

2
backend/i18n/frontend_it.json

@ -166,6 +166,8 @@
"backups.started": "Backup avviato, il suo completamento potrebbe richiedere alcuni minuti.",
"backups.startedLabel": "Avviato",
"backups.startFailed": "Non è stato possibile avviare il backup.",
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.prompt": "Describe the content you want to generate",

2
backend/i18n/frontend_nl.json

@ -166,6 +166,8 @@
"backups.started": "Back-up gestart, het kan enkele minuten duren om te voltooien.",
"backups.startedLabel": "Gestart",
"backups.startFailed": "Starten van back-up is mislukt.",
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.prompt": "Describe the content you want to generate",

2
backend/i18n/frontend_pt.json

@ -166,6 +166,8 @@
"backups.started": "O reforço começou, pode levar vários minutos para ser concluído.",
"backups.startedLabel": "Começou",
"backups.startFailed": "Falhou em começar o backup.",
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.prompt": "Describe the content you want to generate",

2
backend/i18n/frontend_zh.json

@ -166,6 +166,8 @@
"backups.started": "备份已开始,可能需要几分钟才能完成。",
"backups.startedLabel": "开始",
"backups.startFailed": "启动备份失败。",
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.prompt": "Describe the content you want to generate",

2
backend/i18n/source/frontend_en.json

@ -166,6 +166,8 @@
"backups.started": "Backup started, it can take several minutes to complete.",
"backups.startedLabel": "Started",
"backups.startFailed": "Failed to start backup.",
"chat.answers": "Answers",
"chat.answersEmpty": "The ChatBot does not provide an answer or has not been configured yet.",
"chat.ask": "Ask",
"chat.description": "Use the ChatBot (usually OpenAI) to generate content. Just write a prompt and describe, what you need.\n\n\nAlso add the desired format (for example Markdown or HTML) to your prompt, dependending on the editor that you use.",
"chat.prompt": "Describe the content you want to generate",

40
backend/src/Squidex.Domain.Apps.Entities/Comments/DomainObject/CommentsCommandMiddleware.cs

@ -14,7 +14,7 @@ namespace Squidex.Domain.Apps.Entities.Comments.DomainObject;
public sealed class CommentsCommandMiddleware : AggregateCommandMiddleware<CommentsCommandBase, CommentsStream>
{
private static readonly Regex MentionRegex = new Regex(@"@(?=.{1,254}$)(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*", RegexOptions.Compiled | RegexOptions.ExplicitCapture, TimeSpan.FromMilliseconds(100));
private static readonly Regex MentionRegex = new Regex(@"@(?=.{1,64}@)[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+(\.[-!#$%&'*+\/0-9=?A-Z^_`a-z{|}~]+)*@[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?(\.[A-Za-z0-9]([A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*", RegexOptions.Compiled | RegexOptions.ExplicitCapture, TimeSpan.FromMilliseconds(100));
private readonly IUserResolver userResolver;
public CommentsCommandMiddleware(IDomainObjectFactory domainObjectFactory, IUserResolver userResolver)
@ -44,29 +44,33 @@ public sealed class CommentsCommandMiddleware : AggregateCommandMiddleware<Comme
private async Task MentionUsersAsync(CommentTextCommand command)
{
if (!string.IsNullOrWhiteSpace(command.Text))
if (string.IsNullOrWhiteSpace(command.Text))
{
var emails = MentionRegex.Matches(command.Text).Select(x => x.Value[1..]).ToArray();
return;
}
if (emails.Length > 0)
{
var mentions = new List<string>();
var emails = MentionRegex.Matches(command.Text).Select(x => x.Value[1..]).ToArray();
if (emails.Length == 0)
{
return;
}
foreach (var email in emails)
{
var user = await userResolver.FindByIdOrEmailAsync(email);
var mentions = new List<string>();
if (user != null)
{
mentions.Add(user.Id);
}
}
foreach (var email in emails)
{
var user = await userResolver.FindByIdOrEmailAsync(email);
if (mentions.Count > 0)
{
command.Mentions = mentions.ToArray();
}
if (user != null)
{
mentions.Add(user.Id);
}
}
if (mentions.Count > 0)
{
command.Mentions = mentions.ToArray();
}
}
}

20
backend/tests/Squidex.Domain.Apps.Entities.Tests/Comments/DomainObject/CommentsCommandMiddlewareTests.cs

@ -5,6 +5,7 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using LoremNET;
using Squidex.Domain.Apps.Core.TestHelpers;
using Squidex.Domain.Apps.Entities.Comments.Commands;
using Squidex.Domain.Apps.Entities.TestHelpers;
@ -76,6 +77,25 @@ public class CommentsCommandMiddlewareTests : GivenContext
Assert.Equal(command.Mentions, new[] { "id1", "id2" });
}
[Fact]
public async Task Should_enrich_with_mentioned_user_ids_if_found_and_long_text()
{
SetupUser("id1", "mail1@squidex.io");
SetupUser("id2", "mail2@squidex.io");
var command = CreateCommentsCommand(new CreateComment
{
Text = $"Hi @mail1@squidex.io, @mail2@squidex.io and @notfound@squidex.io {Lorem.Paragraph(200, 10)}",
IsMention = false
});
var context = CrateCommandContext(command);
await sut.HandleAsync(context, CancellationToken);
Assert.Equal(command.Mentions, new[] { "id1", "id2" });
}
[Fact]
public async Task Should_not_invoke_commands_for_mentioned_users()
{

2
frontend/src/app/features/content/shared/forms/chat-dialog.component.html

@ -31,7 +31,7 @@
<h4 class="mt-4">{{ 'chat.answers' | sqxTranslate }}</h4>
<div *ngIf="snapshot.chatAnswers?.length === 0">
{{ 'chat.noAnswers' | sqxTranslate }}
<small class="text-muted">{{ 'chat.answersEmpty' | sqxTranslate }}</small>
</div>
<div class="row g-2 answer" *ngFor="let answer of (snapshot.chatAnswers || [])">

2
frontend/src/app/features/content/shared/forms/chat-dialog.component.scss

@ -2,5 +2,5 @@
@import 'vars';
textarea {
height: 100px;
height: 300px;
}

4
frontend/src/app/features/content/shared/forms/chat-dialog.component.ts

@ -52,10 +52,10 @@ export class ChatDialogComponent extends StatefulComponent<State> {
this.translator.ask(this.appsState.appName, { prompt: this.snapshot.chatQuestion })
.subscribe({
next: chatAnswers => {
this.next({ chatAnswers });
this.next({ chatAnswers, isRunning: false });
},
error: () => {
this.next({ chatAnswers: [] });
this.next({ chatAnswers: [], isRunning: false });
},
complete: () => {
this.next({ isRunning: false });

Loading…
Cancel
Save