diff --git a/frontend/src/components/misc/User.vue b/frontend/src/components/misc/User.vue index 6e3820c18..5570f11d6 100644 --- a/frontend/src/components/misc/User.vue +++ b/frontend/src/components/misc/User.vue @@ -15,6 +15,10 @@ v-if="showUsername" class="username" >{{ displayName }} + {{ $t('user.bot.badge') }} @@ -36,6 +40,7 @@ const props = withDefaults(defineProps<{ }) const displayName = computed(() => getDisplayName(props.user)) +const isBot = computed(() => ((props.user as IUser & {botOwnerId?: number}).botOwnerId ?? 0) > 0) const avatarSrc = ref('') async function loadAvatar() { @@ -60,4 +65,17 @@ watch(() => [props.user, props.avatarSize], loadAvatar, { immediate: true }) vertical-align: middle; margin-inline-end: .5rem; } + +.bot-badge { + display: inline-block; + align-self: center; + margin-inline-start: .5rem; + padding: 0 .4rem; + font-size: .75rem; + line-height: 1.2; + color: var(--grey-700); + background: var(--grey-200); + border-radius: 4px; + text-transform: uppercase; +} diff --git a/frontend/src/i18n/lang/en.json b/frontend/src/i18n/lang/en.json index 3b8eab1a6..07f5d376a 100644 --- a/frontend/src/i18n/lang/en.json +++ b/frontend/src/i18n/lang/en.json @@ -59,6 +59,9 @@ "text": "Please check your network connection and try again." }, "user": { + "bot": { + "badge": "Bot" + }, "auth": { "username": "Username", "usernameEmail": "Username Or Email Address", diff --git a/frontend/src/modelTypes/IUser.ts b/frontend/src/modelTypes/IUser.ts index 470ceb7ae..ae2f6ee45 100644 --- a/frontend/src/modelTypes/IUser.ts +++ b/frontend/src/modelTypes/IUser.ts @@ -24,4 +24,5 @@ export interface IUser extends IAbstract { isLocalUser: boolean deletionScheduledAt: string | Date | null isAdmin?: boolean + botOwnerId?: number } diff --git a/frontend/src/models/user.ts b/frontend/src/models/user.ts index d3cba06dd..e3fe2b128 100644 --- a/frontend/src/models/user.ts +++ b/frontend/src/models/user.ts @@ -82,6 +82,7 @@ export default class UserModel extends AbstractModel implements IUser { isLocalUser: boolean deletionScheduledAt: null isAdmin?: boolean + botOwnerId = 0 constructor(data: Partial = {}) { super() @@ -92,4 +93,8 @@ export default class UserModel extends AbstractModel implements IUser { this.settings = new UserSettingsModel(this.settings || {}) } + + get isBot(): boolean { + return (this.botOwnerId ?? 0) > 0 + } } diff --git a/frontend/src/stores/config.ts b/frontend/src/stores/config.ts index 6ca087ff4..7784e0507 100644 --- a/frontend/src/stores/config.ts +++ b/frontend/src/stores/config.ts @@ -44,6 +44,7 @@ export interface ConfigState { }, }, publicTeamsEnabled: boolean, + botUsersEnabled: boolean, enabledProFeatures: string[], } @@ -84,6 +85,7 @@ export const useConfigStore = defineStore('config', () => { }, }, publicTeamsEnabled: false, + botUsersEnabled: false, enabledProFeatures: [], })