1
0
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:
Hossein 2021-12-08 10:04:19 -05:00 committed by GitHub
parent c8d4c98f8c
commit dc36afcfba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 6 deletions

View File

@ -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 {

View File

@ -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

View File

@ -0,0 +1,5 @@
.EntryComponent {
display: flex;
align-items: center;
justify-content: center;
}

View File

@ -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

View File

@ -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}

View File

@ -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')

View File

@ -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 {