fix: update mention format to use custom HTML element with usernames (#1843)
This commit is contained in:
parent
b3b420121d
commit
cfab3ff922
|
|
@ -210,7 +210,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {ref, reactive, computed, shallowReactive, watch, nextTick} from 'vue'
|
||||
import {ref, reactive, computed, shallowReactive, watch} from 'vue'
|
||||
import {useI18n} from 'vue-i18n'
|
||||
|
||||
import CustomTransition from '@/components/misc/CustomTransition.vue'
|
||||
|
|
@ -368,13 +368,6 @@ async function addComment() {
|
|||
return
|
||||
}
|
||||
|
||||
// This makes the editor trigger its mounted function again which makes it forget every input
|
||||
// it currently has in its textarea. This is a counter-hack to a hack inside of vue-easymde
|
||||
// which made it impossible to detect change from the outside. Therefore the component would
|
||||
// not update if new content from the outside was made available.
|
||||
// See https://github.com/NikulinIlya/vue-easymde/issues/3
|
||||
editorActive.value = false
|
||||
nextTick(() => (editorActive.value = true))
|
||||
creating.value = true
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
|
|
@ -27,48 +26,41 @@ import (
|
|||
)
|
||||
|
||||
func FindMentionedUsersInText(s *xorm.Session, text string) (users map[int64]*user.User, err error) {
|
||||
userIDs := extractMentionedUserIDs(text)
|
||||
if len(userIDs) == 0 {
|
||||
usernames := extractMentionedUsernames(text)
|
||||
if len(usernames) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
return user.GetUsersByIDs(s, userIDs)
|
||||
return user.GetUsersByUsername(s, usernames, true)
|
||||
}
|
||||
|
||||
// extractMentionedUserIDs parses HTML content and extracts user IDs from mention spans.
|
||||
// It looks for <span class="mention" data-id="123"> elements and returns the user IDs.
|
||||
func extractMentionedUserIDs(htmlText string) []int64 {
|
||||
// extractMentionedUsernames parses HTML content and extracts usernames from mention spans.
|
||||
// It looks for <mention-user data-id="username"> elements and returns the usernames.
|
||||
func extractMentionedUsernames(htmlText string) []string {
|
||||
doc, err := html.Parse(strings.NewReader(htmlText))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var userIDs []int64
|
||||
seen := make(map[int64]bool) // Deduplicate user IDs
|
||||
usernames := []string{}
|
||||
seen := make(map[string]bool) // Deduplicate usernames
|
||||
|
||||
var traverse func(*html.Node)
|
||||
traverse = func(n *html.Node) {
|
||||
if n.Type == html.ElementNode && n.Data == "span" {
|
||||
isMention := false
|
||||
if n.Type == html.ElementNode && n.Data == "mention-user" {
|
||||
var dataID string
|
||||
|
||||
// Check if this span has class="mention" and extract data-id
|
||||
// Extract data-id attribute
|
||||
for _, attr := range n.Attr {
|
||||
if attr.Key == "class" && strings.Contains(attr.Val, "mention") {
|
||||
isMention = true
|
||||
}
|
||||
if attr.Key == "data-id" {
|
||||
dataID = attr.Val
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a mention span with a valid data-id, extract the user ID
|
||||
if isMention && dataID != "" {
|
||||
if userID, err := strconv.ParseInt(dataID, 10, 64); err == nil {
|
||||
if !seen[userID] {
|
||||
userIDs = append(userIDs, userID)
|
||||
seen[userID] = true
|
||||
}
|
||||
if dataID != "" {
|
||||
if !seen[dataID] {
|
||||
usernames = append(usernames, dataID)
|
||||
seen[dataID] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -80,5 +72,5 @@ func extractMentionedUserIDs(htmlText string) []int64 {
|
|||
}
|
||||
|
||||
traverse(doc)
|
||||
return userIDs
|
||||
return usernames
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,27 +47,27 @@ func TestFindMentionedUsersInText(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "one user at the beginning",
|
||||
text: `<p><span class="mention" data-type="mention" data-id="1" data-label="user1">@user1</span> Lorem Ipsum</p>`,
|
||||
text: `<p><mention-user data-id="user1">@user1</mention-user> Lorem Ipsum</p>`,
|
||||
wantUsers: []*user.User{user1},
|
||||
},
|
||||
{
|
||||
name: "one user at the end",
|
||||
text: `<p>Lorem Ipsum <span class="mention" data-type="mention" data-id="1" data-label="user1">@user1</span></p>`,
|
||||
text: `<p>Lorem Ipsum <mention-user data-id="user1">@user1</mention-user></p>`,
|
||||
wantUsers: []*user.User{user1},
|
||||
},
|
||||
{
|
||||
name: "one user in the middle",
|
||||
text: `<p>Lorem <span class="mention" data-type="mention" data-id="1" data-label="user1">@user1</span> Ipsum</p>`,
|
||||
text: `<p>Lorem <mention-user data-id="user1">@user1</mention-user> Ipsum</p>`,
|
||||
wantUsers: []*user.User{user1},
|
||||
},
|
||||
{
|
||||
name: "same user multiple times",
|
||||
text: `<p>Lorem <span class="mention" data-type="mention" data-id="1" data-label="user1">@user1</span> Ipsum <span class="mention" data-type="mention" data-id="1" data-label="user1">@user1</span> <span class="mention" data-type="mention" data-id="1" data-label="user1">@user1</span></p>`,
|
||||
text: `<p>Lorem <mention-user data-id="user1">@user1</mention-user> Ipsum <mention-user data-id="user1">@user1</mention-user> <mention-user data-id="user1">@user1</mention-user></p>`,
|
||||
wantUsers: []*user.User{user1},
|
||||
},
|
||||
{
|
||||
name: "Multiple users",
|
||||
text: `<p>Lorem <span class="mention" data-type="mention" data-id="1" data-label="user1">@user1</span> Ipsum <span class="mention" data-type="mention" data-id="2" data-label="user2">@user2</span></p>`,
|
||||
text: `<p>Lorem <mention-user data-id="user1">@user1</mention-user> Ipsum <mention-user data-id="user2">@user2</mention-user></p>`,
|
||||
wantUsers: []*user.User{user1, user2},
|
||||
},
|
||||
}
|
||||
|
|
@ -103,7 +103,7 @@ func TestSendingMentionNotification(t *testing.T) {
|
|||
task, err := GetTaskByIDSimple(s, 32)
|
||||
require.NoError(t, err)
|
||||
tc := &TaskComment{
|
||||
Comment: `<p>Lorem Ipsum <span class="mention" data-type="mention" data-id="1" data-label="user1">@user1</span> <span class="mention" data-type="mention" data-id="2" data-label="user2">@user2</span> <span class="mention" data-type="mention" data-id="3" data-label="user3">@user3</span> <span class="mention" data-type="mention" data-id="4" data-label="user4">@user4</span> <span class="mention" data-type="mention" data-id="5" data-label="user5">@user5</span> <span class="mention" data-type="mention" data-id="6" data-label="user6">@user6</span></p>`,
|
||||
Comment: `<p>Lorem Ipsum <mention-user data-id="user1">@user1</mention-user> <mention-user data-id="user2">@user2</mention-user> <mention-user data-id="user3">@user3</mention-user> <mention-user data-id="user4">@user4</mention-user> <mention-user data-id="user5">@user5</mention-user> <mention-user data-id="user6">@user6</mention-user></p>`,
|
||||
TaskID: 32, // user2 has access to the project that task belongs to
|
||||
}
|
||||
err = tc.Create(s, u)
|
||||
|
|
@ -156,7 +156,7 @@ func TestSendingMentionNotification(t *testing.T) {
|
|||
task, err := GetTaskByIDSimple(s, 32)
|
||||
require.NoError(t, err)
|
||||
tc := &TaskComment{
|
||||
Comment: `<p>Lorem Ipsum <span class="mention" data-type="mention" data-id="2" data-label="user2">@user2</span></p>`,
|
||||
Comment: `<p>Lorem Ipsum <mention-user data-id="user2">@user2</mention-user></p>`,
|
||||
TaskID: 32, // user2 has access to the project that task belongs to
|
||||
}
|
||||
err = tc.Create(s, u)
|
||||
|
|
@ -170,7 +170,7 @@ func TestSendingMentionNotification(t *testing.T) {
|
|||
_, err = notifyMentionedUsers(s, &task, tc.Comment, n)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = notifyMentionedUsers(s, &task, `<p>Lorem Ipsum <span class="mention" data-type="mention" data-id="2" data-label="user2">@user2</span> <span class="mention" data-type="mention" data-id="3" data-label="user3">@user3</span></p>`, n)
|
||||
_, err = notifyMentionedUsers(s, &task, `<p>Lorem Ipsum <mention-user data-id="user2">@user2</mention-user> <mention-user data-id="user3">@user3</mention-user></p>`, n)
|
||||
require.NoError(t, err)
|
||||
|
||||
// The second time mentioning the user in the same task should not create another notification
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ func TestTaskComment_Create(t *testing.T) {
|
|||
task, err := GetTaskByIDSimple(s, 32)
|
||||
require.NoError(t, err)
|
||||
tc := &TaskComment{
|
||||
Comment: `<p>Lorem Ipsum <span class="mention" data-type="mention" data-id="2" data-label="user2">@user2</span></p>`,
|
||||
Comment: `<p>Lorem Ipsum <mention-user data-id="user2">@user2</mention-user></p>`,
|
||||
TaskID: 32, // user2 has access to the project that task belongs to
|
||||
}
|
||||
err = tc.Create(s, u)
|
||||
|
|
|
|||
Loading…
Reference in New Issue