mirror of
https://github.com/mattermost/focalboard.git
synced 2025-01-05 14:50:29 +02:00
GH-1878: Display Bot Badge in Auto Complete (#1906)
This commit is contained in:
parent
c8d4c98f8c
commit
dc36afcfba
@ -47,6 +47,10 @@ type User struct {
|
|||||||
// Deleted time, set to indicate user is deleted
|
// Deleted time, set to indicate user is deleted
|
||||||
// required: true
|
// required: true
|
||||||
DeleteAt int64 `json:"delete_at"`
|
DeleteAt int64 `json:"delete_at"`
|
||||||
|
|
||||||
|
// If the user is a bot or not
|
||||||
|
// required: true
|
||||||
|
IsBot bool `json:"is_bot"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
|
@ -284,10 +284,11 @@ func (s *MattermostAuthLayer) getQueryBuilder() sq.StatementBuilderType {
|
|||||||
func (s *MattermostAuthLayer) GetUsersByWorkspace(workspaceID string) ([]*model.User, error) {
|
func (s *MattermostAuthLayer) GetUsersByWorkspace(workspaceID string) ([]*model.User, error) {
|
||||||
query := s.getQueryBuilder().
|
query := s.getQueryBuilder().
|
||||||
Select("id", "username", "email", "password", "MFASecret as mfa_secret", "AuthService as auth_service", "COALESCE(AuthData, '') as auth_data",
|
Select("id", "username", "email", "password", "MFASecret as mfa_secret", "AuthService as auth_service", "COALESCE(AuthData, '') as auth_data",
|
||||||
"props", "CreateAt as create_at", "UpdateAt as update_at", "DeleteAt as delete_at").
|
"props", "Users.CreateAt as create_at", "Users.UpdateAt as update_at", "Users.DeleteAt as delete_at", "b.UserId IS NOT NULL AS is_bot").
|
||||||
From("Users").
|
From("Users").
|
||||||
Join("ChannelMembers ON ChannelMembers.UserID = Users.ID").
|
Join("ChannelMembers ON ChannelMembers.UserID = Users.ID").
|
||||||
Where(sq.Eq{"deleteAt": 0}).
|
LeftJoin("Bots b ON ( b.UserId = Users.ID )").
|
||||||
|
Where(sq.Eq{"Users.deleteAt": 0}).
|
||||||
Where(sq.Eq{"ChannelMembers.ChannelId": workspaceID})
|
Where(sq.Eq{"ChannelMembers.ChannelId": workspaceID})
|
||||||
|
|
||||||
rows, err := query.Query()
|
rows, err := query.Query()
|
||||||
@ -323,6 +324,7 @@ func (s *MattermostAuthLayer) usersFromRows(rows *sql.Rows) ([]*model.User, erro
|
|||||||
&user.CreateAt,
|
&user.CreateAt,
|
||||||
&user.UpdateAt,
|
&user.UpdateAt,
|
||||||
&user.DeleteAt,
|
&user.DeleteAt,
|
||||||
|
&user.IsBot,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
.EntryComponent {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||||
|
// See LICENSE.txt for license information.
|
||||||
|
import React, {ReactElement} from 'react'
|
||||||
|
import {EntryComponentProps} from '@draft-js-plugins/mention/lib/MentionSuggestions/Entry/Entry'
|
||||||
|
import './entryComponent.scss'
|
||||||
|
|
||||||
|
const BotBadge = (window as any).Components?.BotBadge
|
||||||
|
|
||||||
|
const Entry = (props: EntryComponentProps): ReactElement => {
|
||||||
|
const {
|
||||||
|
mention,
|
||||||
|
theme,
|
||||||
|
...parentProps
|
||||||
|
} = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
{...parentProps}
|
||||||
|
>
|
||||||
|
<div className={`${theme?.mentionSuggestionsEntryContainer} EntryComponent`}>
|
||||||
|
<img
|
||||||
|
src={mention.avatar}
|
||||||
|
className={theme?.mentionSuggestionsEntryAvatar}
|
||||||
|
role='presentation'
|
||||||
|
/>
|
||||||
|
<div className={theme?.mentionSuggestionsEntryText}>
|
||||||
|
{mention.name}
|
||||||
|
{BotBadge &&
|
||||||
|
<BotBadge
|
||||||
|
show={mention.isBot}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Entry
|
@ -24,6 +24,8 @@ import {getWorkspaceUsersList} from '../../store/users'
|
|||||||
import {useAppSelector} from '../../store/hooks'
|
import {useAppSelector} from '../../store/hooks'
|
||||||
import {IUser} from '../../user'
|
import {IUser} from '../../user'
|
||||||
|
|
||||||
|
import Entry from './entryComponent/entryComponent'
|
||||||
|
|
||||||
const imageURLForUser = (window as any).Components?.imageURLForUser
|
const imageURLForUser = (window as any).Components?.imageURLForUser
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -38,7 +40,14 @@ type Props = {
|
|||||||
const MarkdownEditorInput = (props: Props): ReactElement => {
|
const MarkdownEditorInput = (props: Props): ReactElement => {
|
||||||
const {onChange, onFocus, onBlur, initialText, id, isEditing} = props
|
const {onChange, onFocus, onBlur, initialText, id, isEditing} = props
|
||||||
const workspaceUsers = useAppSelector<IUser[]>(getWorkspaceUsersList)
|
const workspaceUsers = useAppSelector<IUser[]>(getWorkspaceUsersList)
|
||||||
const mentions: MentionData[] = useMemo(() => workspaceUsers.map((user) => ({name: user.username, avatar: `${imageURLForUser ? imageURLForUser(user.id) : ''}`})), [workspaceUsers])
|
const mentions: MentionData[] = useMemo(() =>
|
||||||
|
workspaceUsers.map((user) =>
|
||||||
|
({
|
||||||
|
name: user.username,
|
||||||
|
avatar: `${imageURLForUser ? imageURLForUser(user.id) : ''}`,
|
||||||
|
isBot: user.is_bot,
|
||||||
|
}))
|
||||||
|
, [workspaceUsers])
|
||||||
const ref = useRef<Editor>(null)
|
const ref = useRef<Editor>(null)
|
||||||
const [editorState, setEditorState] = useState(() => {
|
const [editorState, setEditorState] = useState(() => {
|
||||||
const state = EditorState.createWithContent(ContentState.createFromText(initialText || ''))
|
const state = EditorState.createWithContent(ContentState.createFromText(initialText || ''))
|
||||||
@ -160,6 +169,7 @@ const MarkdownEditorInput = (props: Props): ReactElement => {
|
|||||||
onOpenChange={onMentionPopoverOpenChange}
|
onOpenChange={onMentionPopoverOpenChange}
|
||||||
suggestions={suggestions}
|
suggestions={suggestions}
|
||||||
onSearchChange={onSearchChange}
|
onSearchChange={onSearchChange}
|
||||||
|
entryComponent={Entry}
|
||||||
/>
|
/>
|
||||||
<EmojiSuggestions
|
<EmojiSuggestions
|
||||||
onOpen={onEmojiPopoverOpen}
|
onOpen={onEmojiPopoverOpen}
|
||||||
|
@ -75,7 +75,7 @@ card3.id = 'card3'
|
|||||||
card3.title = 'card-3'
|
card3.title = 'card-3'
|
||||||
card3.workspaceId = workspace1.id
|
card3.workspaceId = workspace1.id
|
||||||
|
|
||||||
const me: IUser = {id: 'user-id-1', username: 'username_1', email: '', props: {}, createAt: 0, updateAt: 0}
|
const me: IUser = {id: 'user-id-1', username: 'username_1', email: '', props: {}, create_at: 0, update_at: 0, is_bot: false}
|
||||||
|
|
||||||
jest.mock('react-router-dom', () => {
|
jest.mock('react-router-dom', () => {
|
||||||
const originalModule = jest.requireActual('react-router-dom')
|
const originalModule = jest.requireActual('react-router-dom')
|
||||||
|
@ -7,8 +7,9 @@ interface IUser {
|
|||||||
email: string,
|
email: string,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
props: Record<string, any>,
|
props: Record<string, any>,
|
||||||
createAt: number,
|
create_at: number,
|
||||||
updateAt: number,
|
update_at: number,
|
||||||
|
is_bot: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UserWorkspace {
|
interface UserWorkspace {
|
||||||
|
Loading…
Reference in New Issue
Block a user