diff --git a/apps/meteor/app/api/server/v1/rooms.ts b/apps/meteor/app/api/server/v1/rooms.ts index ae08dae049382..47e2c03e6064d 100644 --- a/apps/meteor/app/api/server/v1/rooms.ts +++ b/apps/meteor/app/api/server/v1/rooms.ts @@ -322,7 +322,7 @@ API.v1.addRoute( { async post() { // eslint-disable-next-line @typescript-eslint/naming-convention - const { prid, pmid, reply, t_name, users, encrypted } = this.bodyParams; + const { prid, pmid, reply, t_name, users, encrypted, topic } = this.bodyParams; if (!prid) { return API.v1.failure('Body parameter "prid" is required.'); } @@ -344,6 +344,7 @@ API.v1.addRoute( reply, users: users?.filter(isTruthy) || [], encrypted, + topic, }); return API.v1.success({ discussion }); diff --git a/apps/meteor/app/discussion/server/methods/createDiscussion.ts b/apps/meteor/app/discussion/server/methods/createDiscussion.ts index 6d60e9af24bc5..18b42ba1a31f2 100644 --- a/apps/meteor/app/discussion/server/methods/createDiscussion.ts +++ b/apps/meteor/app/discussion/server/methods/createDiscussion.ts @@ -62,6 +62,7 @@ type CreateDiscussionProperties = { users: Array>; user: IUser; encrypted?: boolean; + topic?: string; }; const create = async ({ @@ -72,6 +73,7 @@ const create = async ({ users, user, encrypted, + topic, }: CreateDiscussionProperties): Promise => { // if you set both, prid and pmid, and the rooms dont match... should throw an error) let message: null | IMessage = null; @@ -145,7 +147,7 @@ const create = async ({ const type = await roomCoordinator.getRoomDirectives(parentRoom.t).getDiscussionType(parentRoom); const description = parentRoom.encrypted ? '' : message?.msg; - const topic = parentRoom.name; + const discussionTopic = topic || parentRoom.name; if (!type) { throw new Meteor.Error('error-invalid-type', 'Cannot define discussion room type', { @@ -163,7 +165,7 @@ const create = async ({ { fname: discussionName, description, // TODO discussions remove - topic, // TODO discussions remove + topic: discussionTopic, prid, encrypted, }, @@ -203,7 +205,7 @@ declare module '@rocket.chat/ui-contexts' { export const createDiscussion = async ( userId: string, - { prid, pmid, t_name: discussionName, reply, users, encrypted }: Omit, + { prid, pmid, t_name: discussionName, reply, users, encrypted, topic }: Omit, ): Promise< IRoom & { rid: string; @@ -229,7 +231,7 @@ export const createDiscussion = async ( }); } - return create({ prid, pmid, t_name: discussionName, reply, users, user, encrypted }); + return create({ prid, pmid, t_name: discussionName, reply, users, user, encrypted, topic }); }; Meteor.methods({ diff --git a/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx b/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx index c191fb1508733..e6bce31b0b87e 100644 --- a/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx +++ b/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx @@ -32,6 +32,7 @@ type CreateDiscussionFormValues = { encrypted: boolean; usernames: Array; firstMessage: string; + topic: string; }; type CreateDiscussionProps = { @@ -49,6 +50,7 @@ const CreateDiscussion = ({ onClose, defaultParentRoom, parentMessageId, nameSug handleSubmit, control, watch, + register, } = useForm({ mode: 'onBlur', defaultValues: { @@ -57,6 +59,7 @@ const CreateDiscussion = ({ onClose, defaultParentRoom, parentMessageId, nameSug encrypted: false, usernames: [], firstMessage: '', + topic: '', }, }); @@ -72,21 +75,23 @@ const CreateDiscussion = ({ onClose, defaultParentRoom, parentMessageId, nameSug }, }); - const handleCreate = async ({ name, parentRoom, encrypted, usernames, firstMessage }: CreateDiscussionFormValues) => { + const handleCreate = async ({ name, parentRoom, encrypted, usernames, firstMessage, topic }: CreateDiscussionFormValues) => { createDiscussionMutation.mutate({ prid: defaultParentRoom || parentRoom, t_name: name, users: usernames, reply: encrypted ? undefined : firstMessage, + topic, ...(parentMessageId && { pmid: parentMessageId }), }); }; - const targetChannelField = useUniqueId(); - const encryptedField = useUniqueId(); - const discussionField = useUniqueId(); - const usersField = useUniqueId(); - const firstMessageField = useUniqueId(); + const parentRoomId = useUniqueId(); + const encryptedId = useUniqueId(); + const discussionNameId = useUniqueId(); + const membersId = useUniqueId(); + const firstMessageId = useUniqueId(); + const topicId = useUniqueId(); return ( {t('Discussion_description')} - + {t('Discussion_target_channel')} @@ -123,36 +128,26 @@ const CreateDiscussion = ({ onClose, defaultParentRoom, parentMessageId, nameSug onBlur={onBlur} onChange={onChange} value={value} - id={targetChannelField} - placeholder={t('Discussion_target_channel_description')} + id={parentRoomId} + placeholder={t('Search_options')} disabled={Boolean(defaultParentRoom)} aria-invalid={Boolean(errors.parentRoom)} aria-required='true' - aria-describedby={`${targetChannelField}-error`} + aria-describedby={`${parentRoomId}-error`} /> )} /> )} {errors.parentRoom && ( - + {errors.parentRoom.message} )} - - {t('Encrypted')} - } - /> - - - - - {t('Discussion_name')} + + {t('Name')} ( } /> )} /> {errors.name && ( - + {errors.name.message} )} - {t('Invite_Users')} + {t('Topic')} + + + + + {t('Displayed_next_to_name')} + + + + {t('Members')} ( )} /> - {t('Discussion_first_message_title')} + {t('Discussion_first_message_title')} ( )} /> - {encrypted && {t('Discussion_first_message_disabled_due_to_e2e')}} + {encrypted ? ( + {t('Discussion_first_message_disabled_due_to_e2e')} + ) : ( + {t('First_message_hint')} + )} + + + + {t('Encrypted')} + } + /> + + {encrypted ? ( + {t('Encrypted_messages', { roomType: 'discussion' })} + ) : ( + {t('Encrypted_messages_false')} + )} diff --git a/apps/meteor/client/components/InfoPanel/InfoPanelActionGroup.tsx b/apps/meteor/client/components/InfoPanel/InfoPanelActionGroup.tsx index 3bf9f7e33c707..00af64b0fa618 100644 --- a/apps/meteor/client/components/InfoPanel/InfoPanelActionGroup.tsx +++ b/apps/meteor/client/components/InfoPanel/InfoPanelActionGroup.tsx @@ -6,7 +6,7 @@ import Section from './InfoPanelSection'; const InfoPanelActionGroup: FC> = (props) => (
- +
); diff --git a/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx b/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx index 2708e6e0a1e3f..cd5e19947991d 100644 --- a/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx +++ b/apps/meteor/client/sidebar/header/CreateChannel/CreateChannelModal.tsx @@ -30,6 +30,7 @@ import { useForm, Controller } from 'react-hook-form'; import { useHasLicenseModule } from '../../../../ee/client/hooks/useHasLicenseModule'; import UserAutoCompleteMultipleFederated from '../../../components/UserAutoCompleteMultiple/UserAutoCompleteMultipleFederated'; import { goToRoomById } from '../../../lib/utils/goToRoomById'; +import { useEncryptedRoomDescription } from '../hooks/useEncryptedRoomDescription'; type CreateChannelModalProps = { teamId?: string; @@ -68,6 +69,7 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): const canCreateChannel = usePermission('create-c'); const canCreatePrivateChannel = usePermission('create-p'); + const getEncryptedHint = useEncryptedRoomDescription('channel'); const channelNameRegex = useMemo(() => new RegExp(`^${namesValidation}$`), [namesValidation]); const federatedModule = useHasLicenseModule('federation'); @@ -110,7 +112,7 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): }, }); - const { isPrivate, broadcast, readOnly, federated } = watch(); + const { isPrivate, broadcast, readOnly, federated, encrypted } = watch(); useEffect(() => { if (!isPrivate) { @@ -137,7 +139,7 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): } if (!allowSpecialNames && !channelNameRegex.test(name)) { - return t('error-invalid-name'); + return t('Name_cannot_have_special_characters'); } const { exists } = await channelNameExists({ roomName: name }); @@ -209,7 +211,7 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): - {t('Channel_name')} + {t('Name')} } aria-invalid={errors.name ? 'true' : 'false'} - aria-describedby={`${nameId}-error`} + aria-describedby={`${nameId}-error ${nameId}-hint`} aria-required='true' /> @@ -231,13 +233,24 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): {errors.name.message} )} + {!allowSpecialNames && {t('No_spaces')}} {t('Topic')} - {t('Channel_what_is_this_channel_about')} + {t('Displayed_next_to_name')} + + + {t('Members')} + ( + + )} + /> @@ -258,7 +271,7 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): /> - {isPrivate ? t('Only_invited_users_can_acess_this_channel') : t('Everyone_can_access_this_channel')} + {isPrivate ? t('People_can_only_join_by_being_invited') : t('Anyone_can_access')} @@ -283,48 +296,46 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): - {t('Read_only')} + {t('Encrypted')} ( )} /> - - {readOnly ? t('Only_authorized_users_can_write_new_messages') : t('All_users_in_the_channel_can_write_new_messages')} - + {getEncryptedHint({ isPrivate, broadcast, encrypted })} - {t('Encrypted')} + {t('Read_only')} ( )} /> - - {isPrivate ? t('Encrypted_channel_Description') : t('Encrypted_not_available')} - + + {readOnly ? t('Read_only_field_hint_enabled', { roomType: 'channel' }) : t('Anyone_can_send_new_messages')} + @@ -344,17 +355,7 @@ const CreateChannelModal = ({ teamId = '', onClose }: CreateChannelModalProps): )} /> - {t('Broadcast_channel_Description')} - - - {t('Add_members')} - ( - - )} - /> + {broadcast && {t('Broadcast_hint_enabled', { roomType: 'channel' })}} diff --git a/apps/meteor/client/sidebar/header/CreateDirectMessage.tsx b/apps/meteor/client/sidebar/header/CreateDirectMessage.tsx index 626d1202a8e03..7c34f7ac01a32 100644 --- a/apps/meteor/client/sidebar/header/CreateDirectMessage.tsx +++ b/apps/meteor/client/sidebar/header/CreateDirectMessage.tsx @@ -1,5 +1,5 @@ import type { IUser } from '@rocket.chat/core-typings'; -import { Box, Modal, Button, FieldGroup, Field, FieldRow, FieldLabel, FieldError } from '@rocket.chat/fuselage'; +import { Box, Modal, Button, FieldGroup, Field, FieldRow, FieldError, FieldHint } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { useTranslation, useEndpoint, useToastMessageDispatch, useSetting } from '@rocket.chat/ui-contexts'; import { useMutation } from '@tanstack/react-query'; @@ -20,7 +20,7 @@ const CreateDirectMessage = ({ onClose }: { onClose: () => void }) => { const { control, handleSubmit, - formState: { isDirty, isSubmitting, isValidating, errors }, + formState: { isSubmitting, isValidating, errors }, } = useForm({ mode: 'onBlur', defaultValues: { users: [] } }); const mutateDirectMessage = useMutation({ @@ -47,17 +47,14 @@ const CreateDirectMessage = ({ onClose }: { onClose: () => void }) => { - {t('Direct_message_creation_description')} - - {t('Members')} - + {t('Direct_message_creation_description')} users.length + 1 > directMaxUsers ? t('error-direct-message-max-user-exceeded', { maxUsers: directMaxUsers }) @@ -71,7 +68,7 @@ const CreateDirectMessage = ({ onClose }: { onClose: () => void }) => { value={value} onBlur={onBlur} id={membersFieldId} - aria-describedby={`${membersFieldId}-error`} + aria-describedby={`${membersFieldId}-hint ${membersFieldId}-error`} aria-required='true' aria-invalid={Boolean(errors.users)} /> @@ -83,13 +80,14 @@ const CreateDirectMessage = ({ onClose }: { onClose: () => void }) => { {errors.users.message} )} + {t('Direct_message_creation_description_hint')} - diff --git a/apps/meteor/client/sidebar/header/CreateTeam/CreateTeamModal.tsx b/apps/meteor/client/sidebar/header/CreateTeam/CreateTeamModal.tsx index 115a8563f3932..b56bb003aa9e7 100644 --- a/apps/meteor/client/sidebar/header/CreateTeam/CreateTeamModal.tsx +++ b/apps/meteor/client/sidebar/header/CreateTeam/CreateTeamModal.tsx @@ -11,6 +11,7 @@ import { FieldRow, FieldError, FieldDescription, + FieldHint, } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; import { @@ -27,6 +28,7 @@ import { Controller, useForm } from 'react-hook-form'; import UserAutoCompleteMultiple from '../../../components/UserAutoCompleteMultiple'; import { goToRoomById } from '../../../lib/utils/goToRoomById'; +import { useEncryptedRoomDescription } from '../hooks/useEncryptedRoomDescription'; type CreateTeamModalInputs = { name: string; @@ -65,7 +67,7 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => } if (teamNameRegex && !teamNameRegex?.test(name)) { - return t('Teams_Errors_team_name', { name }); + return t('Name_cannot_have_special_characters'); } const { exists } = await checkTeamNameExists({ roomName: name }); @@ -80,7 +82,7 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => handleSubmit, setValue, watch, - formState: { isDirty, errors, isSubmitting }, + formState: { errors, isSubmitting }, } = useForm({ defaultValues: { isPrivate: true, @@ -91,7 +93,7 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => }, }); - const { isPrivate, broadcast, readOnly } = watch(); + const { isPrivate, broadcast, readOnly, encrypted } = watch(); useEffect(() => { if (!isPrivate) { @@ -107,7 +109,7 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => const canChangeReadOnly = !broadcast; const canChangeEncrypted = isPrivate && !broadcast && e2eEnabled && !e2eEnabledForPrivateByDefault; - const isButtonEnabled = isDirty && canCreateTeam; + const getEncryptedHint = useEncryptedRoomDescription('team'); const handleCreateTeam = async ({ name, @@ -164,6 +166,9 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => + + {t('Teams_new_description')} + @@ -177,10 +182,9 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => required: t('error-the-field-is-required', { field: t('Name') }), validate: (value) => validateTeamName(value), })} - placeholder={t('Team_Name')} addon={} error={errors.name?.message} - aria-describedby={`${nameId}-error`} + aria-describedby={`${nameId}-error ${nameId}-hint`} aria-required='true' /> @@ -189,23 +193,27 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => {errors.name.message} )} + {!allowSpecialNames && {t('No_spaces')}} - - {t('Teams_New_Description_Label')}{' '} - - ({t('optional')}) - - + {t('Topic')} - + + + + {t('Displayed_next_to_name')} + + {t('Teams_New_Add_members_Label')} + ( + + )} + /> + {t('Teams_New_Private_Label')} @@ -218,7 +226,7 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => /> - {isPrivate ? t('Teams_New_Private_Description_Enabled') : t('Teams_New_Private_Description_Disabled')} + {isPrivate ? t('People_can_only_join_by_being_invited') : t('Anyone_can_access')} @@ -240,7 +248,7 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => /> - {readOnly ? t('Only_authorized_users_can_write_new_messages') : t('Teams_New_Read_only_Description')} + {readOnly ? t('Read_only_field_hint_enabled', { roomType: 'team' }) : t('Anyone_can_send_new_messages')} @@ -261,9 +269,7 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => )} /> - - {isPrivate ? t('Teams_New_Encrypted_Description_Enabled') : t('Teams_New_Encrypted_Description_Disabled')} - + {getEncryptedHint({ isPrivate, broadcast, encrypted })} @@ -276,27 +282,14 @@ const CreateTeamModal = ({ onClose }: { onClose: () => void }): ReactElement => )} /> - {t('Teams_New_Broadcast_Description')} - - - - {t('Teams_New_Add_members_Label')}{' '} - - ({t('optional')}) - - - } - /> + {broadcast && {t('Teams_New_Broadcast_Description')}} - diff --git a/apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomItems.tsx b/apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomItems.tsx index c6847fbe7d1ca..7b2770a60ab5a 100644 --- a/apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomItems.tsx +++ b/apps/meteor/client/sidebar/header/actions/hooks/useCreateRoomItems.tsx @@ -44,7 +44,7 @@ export const useCreateRoomItems = (): GenericMenuItemProps[] => { }; const createDirectMessageItem: GenericMenuItemProps = { id: 'direct', - content: t('Direct_Messages'), + content: t('Direct_message'), icon: 'balloon', onClick: () => { createDirectMessage(); @@ -60,9 +60,9 @@ export const useCreateRoomItems = (): GenericMenuItemProps[] => { }; return [ - ...(canCreateChannel ? [createChannelItem] : []), - ...(canCreateTeam ? [createTeamItem] : []), ...(canCreateDirectMessages ? [createDirectMessageItem] : []), ...(canCreateDiscussion && discussionEnabled ? [createDiscussionItem] : []), + ...(canCreateChannel ? [createChannelItem] : []), + ...(canCreateTeam ? [createTeamItem] : []), ]; }; diff --git a/apps/meteor/client/sidebar/header/hooks/useEncryptedRoomDescription.tsx b/apps/meteor/client/sidebar/header/hooks/useEncryptedRoomDescription.tsx new file mode 100644 index 0000000000000..09796dd7a6b7e --- /dev/null +++ b/apps/meteor/client/sidebar/header/hooks/useEncryptedRoomDescription.tsx @@ -0,0 +1,23 @@ +import { useSetting, useTranslation } from '@rocket.chat/ui-contexts'; + +export const useEncryptedRoomDescription = (roomType: 'channel' | 'team') => { + const t = useTranslation(); + const e2eEnabled = useSetting('E2E_Enable'); + const e2eEnabledForPrivateByDefault = useSetting('E2E_Enabled_Default_PrivateRooms'); + + return ({ isPrivate, broadcast, encrypted }: { isPrivate: boolean; broadcast: boolean; encrypted: boolean }) => { + if (!e2eEnabled) { + return t('Not_available_for_this_workspace'); + } + if (!isPrivate) { + return t('Encrypted_not_available', { roomType }); + } + if (broadcast) { + return t('Not_available_for_broadcast', { roomType }); + } + if (e2eEnabledForPrivateByDefault || encrypted) { + return t('Encrypted_messages', { roomType }); + } + return t('Encrypted_messages_false'); + }; +}; diff --git a/apps/meteor/client/views/hooks/roomActions/useDeleteRoom.tsx b/apps/meteor/client/views/hooks/roomActions/useDeleteRoom.tsx index be4728732284f..48b6507a331d6 100644 --- a/apps/meteor/client/views/hooks/roomActions/useDeleteRoom.tsx +++ b/apps/meteor/client/views/hooks/roomActions/useDeleteRoom.tsx @@ -15,7 +15,8 @@ export const useDeleteRoom = (room: IRoom | Pick, { const dispatchToastMessage = useToastMessageDispatch(); const hasPermissionToDelete = usePermission(`delete-${room.t}`, room._id); const canDeleteRoom = isRoomFederated(room) ? false : hasPermissionToDelete; - + // eslint-disable-next-line no-nested-ternary + const roomType = 'prid' in room ? 'discussion' : room.teamId && room.teamMain ? 'team' : 'channel'; const isAdminRoute = router.getRouteName() === 'admin-rooms'; const deleteRoomEndpoint = useEndpoint('POST', '/v1/rooms.delete'); @@ -24,7 +25,7 @@ export const useDeleteRoom = (room: IRoom | Pick, { const deleteRoomMutation = useMutation({ mutationFn: deleteRoomEndpoint, onSuccess: () => { - dispatchToastMessage({ type: 'success', message: t('Room_has_been_deleted') }); + dispatchToastMessage({ type: 'success', message: t('Deleted_roomType', { roomName: room.name, roomType }) }); if (isAdminRoute) { return router.navigate('/admin/rooms'); } @@ -79,8 +80,14 @@ export const useDeleteRoom = (room: IRoom | Pick, { }; setModal( - setModal(null)} confirmText={t('Yes_delete_it')}> - {t('Delete_Room_Warning')} + setModal(null)} + confirmText={t('Yes_delete_it')} + > + {t('Delete_Room_Warning', { roomType })} , ); }); diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx index 2a9397364757a..bc7714da06ae2 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx @@ -39,7 +39,6 @@ import RawText from '../../../../../components/RawText'; import RoomAvatarEditor from '../../../../../components/avatar/RoomAvatarEditor'; import { getDirtyFields } from '../../../../../lib/getDirtyFields'; import { useArchiveRoom } from '../../../../hooks/roomActions/useArchiveRoom'; -import { useDeleteRoom } from '../../../../hooks/roomActions/useDeleteRoom'; import { useEditRoomInitialValues } from './useEditRoomInitialValues'; import { useEditRoomPermissions } from './useEditRoomPermissions'; @@ -49,20 +48,39 @@ type EditRoomInfoProps = { onClickBack: () => void; }; +const title = { + team: 'Edit_team' as TranslationKey, + channel: 'Edit_channel' as TranslationKey, + discussion: 'Edit_discussion' as TranslationKey, +}; + const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => { const t = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); const isFederated = useMemo(() => isRoomFederated(room), [room]); + // eslint-disable-next-line no-nested-ternary + const roomType = 'prid' in room ? 'discussion' : room.teamId ? 'team' : 'channel'; const retentionPolicy = useSetting('RetentionPolicy_Enabled'); - const { handleDelete, canDeleteRoom } = useDeleteRoom(room); const defaultValues = useEditRoomInitialValues(room); + const namesValidation = useSetting('UTF8_Channel_Names_Validation'); + const allowSpecialNames = useSetting('UI_Allow_room_names_with_special_chars'); + const checkTeamNameExists = useEndpoint('GET', '/v1/rooms.nameExists'); + + const teamNameRegex = useMemo(() => { + if (allowSpecialNames) { + return null; + } + + return new RegExp(`^${namesValidation}$`); + }, [allowSpecialNames, namesValidation]); const { watch, reset, control, handleSubmit, + getFieldState, formState: { isDirty, dirtyFields, errors, isSubmitting }, } = useForm({ mode: 'onBlur', defaultValues }); @@ -71,7 +89,19 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => [t], ); - const { readOnly, archived, joinCodeRequired, hideSysMes, retentionEnabled, retentionMaxAge, retentionOverrideGlobal } = watch(); + const { isDirty: isRoomNameDirty } = getFieldState('roomName'); + + const { + readOnly, + archived, + joinCodeRequired, + hideSysMes, + retentionEnabled, + retentionMaxAge, + retentionOverrideGlobal, + roomType: roomTypeP, + reactWhenReadOnly, + } = watch(); const { canChangeType, @@ -123,6 +153,20 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => Promise.all([isDirty && handleUpdateRoomData(data), changeArchiving && handleArchive()].filter(Boolean)), ); + const validateName = async (name: string): Promise => { + if (!name || !isRoomNameDirty) return; + if (roomType === 'discussion') return; + + if (teamNameRegex && !teamNameRegex?.test(name)) { + return t('Name_cannot_have_special_characters'); + } + + const { exists } = await checkTeamNameExists({ roomName: name }); + if (exists) { + return t('Teams_Errors_Already_exists', { name }); + } + }; + const formId = useUniqueId(); const roomNameField = useUniqueId(); const roomDescriptionField = useUniqueId(); @@ -145,7 +189,7 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => <> {onClickBack && } - {room.teamId ? t('edit-team') : t('edit-room')} + {t(`${title[roomType]}`)} {onClickClose && } @@ -166,22 +210,37 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => } + rules={{ + required: t('error-the-field-is-required', { field: t('Name') }), + validate: (value) => validateName(value), + }} + render={({ field }) => ( + + )} /> - {errors.roomName && {errors.roomName.message}} + {errors.roomName && {errors.roomName.message}} - {canViewDescription && ( + {canViewTopic && ( - {t('Description')} + {t('Topic')} } + render={({ field }) => } /> + + {t('Displayed_next_to_name')} + )} {canViewAnnouncement && ( @@ -191,23 +250,34 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => } + render={({ field }) => ( + + )} /> + + {t('Information_to_keep_top_of_mind')} + )} - {canViewTopic && ( + {canViewDescription && ( - {t('Topic')} + {t('Description')} } + render={({ field }) => } /> )} + {canViewType && ( @@ -229,7 +299,11 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => )} /> - {t('Teams_New_Private_Description_Enabled')} + + + {roomTypeP === 'p' ? t('Only_invited_people') : t('Anyone_can_access')} + + )} {canViewReadOnly && ( @@ -250,7 +324,9 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => )} /> - {t('Only_authorized_users_can_write_new_messages')} + + {readOnly ? t('Read_only_field_hint_enabled', { roomType }) : t('Read_only_field_hint_disabled')} + )} {readOnly && ( @@ -271,7 +347,11 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => )} /> - {t('Only_authorized_users_can_react_to_messages')} + + + {reactWhenReadOnly ? t('Anyone_can_react_to_messages') : t('Only_authorized_users_can_react_to_messages')} + + )} {canViewArchived && ( @@ -282,10 +362,21 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => control={control} name='archived' render={({ field: { value, ...field } }) => ( - + )} /> + {archived && ( + + {t('New_messages_cannot_be_sent')} + + )} )} {canViewJoinCode && ( @@ -300,13 +391,15 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => )} /> - - } - /> - + {joinCodeRequired && ( + + } + /> + + )} )} {canViewHideSysMes && ( @@ -330,27 +423,13 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => {...field} options={sysMesOptions} disabled={!hideSysMes || isFederated} - placeholder={t('Select_an_option')} + placeholder={t('Select_messages_to_hide')} /> )} /> )} - {canViewEncrypted && ( - - - {t('Encrypted')} - ( - - )} - /> - - - )} {retentionPolicy && ( @@ -428,6 +507,29 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => /> + {canViewEncrypted && ( + + + {t('Encrypted')} + ( + + )} + /> + + + {t('Encrypted_field_hint')} + + + )} )} @@ -441,17 +543,10 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => - - - - - - ); diff --git a/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx index 38a7593937ff4..80abe104c88e7 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx @@ -34,6 +34,7 @@ const RoomInfo = ({ room, icon, onClickBack, onClickClose, onClickEnterRoom, onC const t = useTranslation(); const { name, fname, description, topic, archived, broadcast, announcement } = room; const roomTitle = fname || name; + const isDiscussion = 'prid' in room; const retentionPolicy = useRetentionPolicy(room); const memoizedActions = useRoomActions(room, { onClickEnterRoom, onClickEdit }, resetState); @@ -48,7 +49,7 @@ const RoomInfo = ({ room, icon, onClickBack, onClickClose, onClickEnterRoom, onC {onClickBack ? : } - {t('Room_Info')} + {isDiscussion ? t('Discussion_info') : t('Channel_info')} {onClickClose && } - - - + + + + - {actions} + {actions} + {archived && ( diff --git a/apps/meteor/client/views/teams/contextualBar/info/DeleteTeam/DeleteTeamConfirmation.tsx b/apps/meteor/client/views/teams/contextualBar/info/DeleteTeam/DeleteTeamConfirmation.tsx index 06d47d7bec376..d7c711cf2d429 100644 --- a/apps/meteor/client/views/teams/contextualBar/info/DeleteTeam/DeleteTeamConfirmation.tsx +++ b/apps/meteor/client/views/teams/contextualBar/info/DeleteTeam/DeleteTeamConfirmation.tsx @@ -20,14 +20,14 @@ const DeleteTeamConfirmation = ({ deletedRooms, keptRooms, onConfirm, onReturn, return ( onConfirm(roomIds)} onCancel={onReturn} - confirmText={t('Remove')} + confirmText={t('Yes_delete_it')} cancelText={t('Back')} onClose={onCancel} > -

{t('Teams_delete_team')}

+

{t('Delete_roomType_description', { roomType: 'team' })}

{!!Object.values(deletedRooms).length && ( <>
diff --git a/apps/meteor/client/views/teams/contextualBar/info/TeamsInfo.tsx b/apps/meteor/client/views/teams/contextualBar/info/TeamsInfo.tsx index 8fd6623c8d9f7..809e20100c9ba 100644 --- a/apps/meteor/client/views/teams/contextualBar/info/TeamsInfo.tsx +++ b/apps/meteor/client/views/teams/contextualBar/info/TeamsInfo.tsx @@ -105,7 +105,7 @@ const TeamsInfo = ({ - - - + + + + - {actions} + {actions} + {room.archived && ( diff --git a/apps/meteor/package.json b/apps/meteor/package.json index 7c51c1a92a3ac..098c488b83c22 100644 --- a/apps/meteor/package.json +++ b/apps/meteor/package.json @@ -242,7 +242,7 @@ "@rocket.chat/favicon": "workspace:^", "@rocket.chat/forked-matrix-appservice-bridge": "^4.0.2", "@rocket.chat/forked-matrix-bot-sdk": "^0.6.0-beta.3", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/fuselage-hooks": "^0.33.0", "@rocket.chat/fuselage-polyfills": "~0.31.25", "@rocket.chat/fuselage-toastbar": "^0.31.26", diff --git a/apps/meteor/tests/e2e/channel-management.spec.ts b/apps/meteor/tests/e2e/channel-management.spec.ts index 0586598a5dda1..efa39e0773b38 100644 --- a/apps/meteor/tests/e2e/channel-management.spec.ts +++ b/apps/meteor/tests/e2e/channel-management.spec.ts @@ -162,7 +162,7 @@ test.describe.serial('channel-management', () => { await poHomeChannel.sidenav.openChat(targetChannel); await poHomeChannel.content.btnMenuMoreActions.click(); await page.getByRole('menuitem', { name: 'Discussion' }).click(); - await page.getByRole('textbox', { name: 'Discussion name' }).fill(discussionName); + await page.getByRole('textbox', { name: 'Name' }).fill(discussionName); await page.getByRole('button', { name: 'Create' }).click(); await expect(page.getByRole('heading', { name: discussionName })).toBeVisible(); diff --git a/apps/meteor/tests/e2e/create-direct.spec.ts b/apps/meteor/tests/e2e/create-direct.spec.ts index 4e74840619bad..1b4e2d7c752d3 100644 --- a/apps/meteor/tests/e2e/create-direct.spec.ts +++ b/apps/meteor/tests/e2e/create-direct.spec.ts @@ -14,7 +14,7 @@ test.describe.serial('channel-direct-message', () => { }); test('expect create a direct room', async ({ page }) => { - await poHomeChannel.sidenav.openNewByLabel('Direct messages'); + await poHomeChannel.sidenav.openNewByLabel('Direct message'); await poHomeChannel.sidenav.inputDirectUsername.click(); await page.keyboard.type('rocket.cat'); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts index c711d6bcdc30c..d7b0b3c2d9cd2 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts @@ -28,7 +28,7 @@ export class HomeFlextabRoom { } get checkboxReadOnly(): Locator { - return this.page.locator('text=Read OnlyOnly authorized users can write new messages >> i'); + return this.page.locator('label', { has: this.page.getByRole('checkbox', { name: 'Read-only' }) }); } get btnSave(): Locator { diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts index 12a38f3b61851..ec085dce6bc7c 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-sidenav.ts @@ -10,15 +10,15 @@ export class HomeSidenav { } get checkboxPrivateChannel(): Locator { - return this.page.locator('role=dialog[name="Create Channel"] >> label >> text="Private"'); + return this.page.locator('label', { has: this.page.getByRole('checkbox', { name: 'Private' }) }); } get checkboxEncryption(): Locator { - return this.page.locator('role=dialog[name="Create Channel"] >> label >> text="Encrypted"'); + return this.page.locator('role=dialog[name="Create channel"] >> label >> text="Encrypted"'); } get checkboxReadOnly(): Locator { - return this.page.locator('role=dialog[name="Create Channel"] >> label >> text="Read Only"'); + return this.page.locator('label', { has: this.page.getByRole('checkbox', { name: 'Read-only' }) }); } get inputChannelName(): Locator { diff --git a/apps/meteor/tests/e2e/page-objects/home-discussion.ts b/apps/meteor/tests/e2e/page-objects/home-discussion.ts index dc055df73bce8..58e129d745a18 100644 --- a/apps/meteor/tests/e2e/page-objects/home-discussion.ts +++ b/apps/meteor/tests/e2e/page-objects/home-discussion.ts @@ -19,18 +19,18 @@ export class HomeDiscussion { } get inputChannelName(): Locator { - return this.page.locator('.rcx-input-box--undecorated.rcx-input-box').first(); + return this.page.locator('role=textbox[name="Parent channel or team"]'); } get inputName(): Locator { - return this.page.locator('[placeholder="A meaningful name for the discussion room"]'); + return this.page.locator('role=textbox[name="Name"]'); } get inputMessage(): Locator { - return this.page.locator('textarea.rcx-input-box'); + return this.page.locator('role=textbox[name="Message"]'); } get btnCreate(): Locator { - return this.page.locator('button.rcx-button--primary.rcx-button >> text="Create"'); + return this.page.locator('role=dialog >> role=group >> role=button[name="Create"]'); } } diff --git a/apps/meteor/tests/e2e/page-objects/home-team.ts b/apps/meteor/tests/e2e/page-objects/home-team.ts index 9c890da05db8c..a3b9130eb3415 100644 --- a/apps/meteor/tests/e2e/page-objects/home-team.ts +++ b/apps/meteor/tests/e2e/page-objects/home-team.ts @@ -19,11 +19,11 @@ export class HomeTeam { } get inputTeamName(): Locator { - return this.page.locator('.rcx-field-group__item:nth-child(1) input'); + return this.page.locator('role=textbox[name="Name"]'); } async addMember(memberName: string): Promise { - await this.page.locator('.rcx-field-group__item:nth-child(7) input').type(memberName, { delay: 100 }); + await this.page.locator('role=textbox[name="Members"]').type(memberName, { delay: 100 }); await this.page.locator(`.rcx-option__content:has-text("${memberName}")`).click(); } @@ -32,10 +32,10 @@ export class HomeTeam { } get textPrivate(): Locator { - return this.page.locator('role=dialog[name="Create Team"] >> label >> text="Private"'); + return this.page.locator('label', {has: this.page.getByRole('checkbox', {name: 'Private'})}); } get textReadOnly(): Locator { - return this.page.locator('role=dialog[name="Create Team"] >> label >> text="Read Only"'); + return this.page.locator('label', {has: this.page.getByRole('checkbox', {name: 'Read-only'})}); } } diff --git a/ee/packages/ui-theming/package.json b/ee/packages/ui-theming/package.json index e4b2908ff0a75..32b628c6835af 100644 --- a/ee/packages/ui-theming/package.json +++ b/ee/packages/ui-theming/package.json @@ -4,7 +4,7 @@ "private": true, "devDependencies": { "@rocket.chat/css-in-js": "~0.31.25", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/fuselage-hooks": "^0.33.0", "@rocket.chat/icons": "^0.34.0", "@rocket.chat/ui-contexts": "workspace:~", diff --git a/packages/fuselage-ui-kit/package.json b/packages/fuselage-ui-kit/package.json index 36b7cde2fb971..216efd02ef542 100644 --- a/packages/fuselage-ui-kit/package.json +++ b/packages/fuselage-ui-kit/package.json @@ -63,7 +63,7 @@ "@babel/preset-typescript": "~7.22.15", "@rocket.chat/apps-engine": "1.42.0-alpha.619", "@rocket.chat/eslint-config": "workspace:^", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/fuselage-hooks": "^0.33.0", "@rocket.chat/fuselage-polyfills": "~0.31.25", "@rocket.chat/icons": "^0.34.0", diff --git a/packages/gazzodown/package.json b/packages/gazzodown/package.json index 791a0129f18d1..368f8b18e5a97 100644 --- a/packages/gazzodown/package.json +++ b/packages/gazzodown/package.json @@ -6,7 +6,7 @@ "@babel/core": "~7.22.20", "@rocket.chat/core-typings": "workspace:^", "@rocket.chat/css-in-js": "~0.31.25", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/fuselage-tokens": "^0.33.0", "@rocket.chat/message-parser": "workspace:^", "@rocket.chat/styled": "~0.31.25", diff --git a/packages/i18n/src/locales/en.i18n.json b/packages/i18n/src/locales/en.i18n.json index 8b9ab62fe910b..bd3222cdce93f 100644 --- a/packages/i18n/src/locales/en.i18n.json +++ b/packages/i18n/src/locales/en.i18n.json @@ -912,7 +912,7 @@ "Canned_Responses": "Canned Responses", "Canned_Responses_Enable": "Enable Canned Responses", "Create_department": "Create department", - "Create_direct_message": "Create direct message", + "Create_direct_message": "New direct message", "Create_tag": "Create tag", "Create_trigger": "Create trigger", "Create_SLA_policy": "Create SLA policy", @@ -959,6 +959,7 @@ "Changing_email": "Changing email", "channel": "channel", "Channel": "Channel", + "Channel_info": "Channel info", "Channel_already_exist": "The channel `#%s` already exists.", "Channel_already_exist_static": "The channel already exists.", "Channel_already_Unarchived": "Channel with name `#%s` is already in Unarchived state", @@ -1436,7 +1437,7 @@ "Create": "Create", "Create_canned_response": "Create canned response", "Create_custom_field": "Create custom field", - "Create_channel": "Create Channel", + "Create_channel": "Create channel", "Create_channels": "Create channels", "Create_a_public_channel_that_new_workspace_members_can_join": "Create a public channel that new workspace members can join.", "Create_A_New_Channel": "Create a New Channel", @@ -1581,7 +1582,7 @@ "Delete_my_account": "Delete my account", "Delete_Role_Warning": "This cannot be undone", "Delete_Role_Warning_Not_Enterprise": "This cannot be undone. You won't be able to create a new custom role, since that feature is no longer available for your current plan.", - "Delete_Room_Warning": "Deleting a room will delete all messages posted within the room. This cannot be undone.", + "Delete_Room_Warning": "Deleting this {{roomType}} will also delete all contained message. This cannot be undone.", "Delete_User_Warning": "Deleting a user will delete all messages from that user as well. This cannot be undone.", "Delete_User_Warning_Delete": "Deleting a user will delete all messages from that user as well. This cannot be undone.", "Delete_User_Warning_Keep": "The user will be deleted, but their messages will remain visible. This cannot be undone.", @@ -1661,10 +1662,13 @@ "DirectMesssage_maxUsers": "Max users in direct messages", "Direct_Message": "Direct message", "Livechat_Facebook_Enabled": "Facebook integration enabled", - "Direct_message_creation_description": "You are about to create a chat with multiple users. Add the ones you would like to talk, everyone in the same place, using direct messages.", + "Direct_message_creation_description": "Select one or more people to message", + "Direct_message_creation_error": "Please select at least one person", + "Direct_message_creation_description_hint": "More people cannot be added once created", "Direct_message_someone": "Direct message someone", "Direct_message_you_have_joined": "You have joined a new direct message with", "Direct_Messages": "Direct messages", + "Direct_message": "Direct message", "Direct_Reply": "Direct Reply", "Direct_Reply_Advice": "You can directly reply to this email. Do not modify previous emails in the thread.", "Direct_Reply_Debug": "Debug Direct Reply", @@ -1697,13 +1701,14 @@ "Disconnect": "Disconnect", "Discover_public_channels_and_teams_in_the_workspace_directory": "Discover public channels and teams in the workspace directory.", "Discussion": "Discussion", + "Discussion_info": "Discussion info", "Discussion_Description": "Discussions are an additional way to organize conversations that allows inviting users from outside channels to participate in specific conversations.", - "Discussion_description": "Help keep an overview of what's going on! By creating a discussion, a sub-channel of the one you selected is created and both are linked.", + "Discussion_description": "Discussions allow separate conversations around a specific topic inside a channel or team where any workspace member can be added.", "Discussion_first_message_disabled_due_to_e2e": "You can start sending End-to-end encrypted messages in this discussion after its creation.", - "Discussion_first_message_title": "Your message", + "Discussion_first_message_title": "Message", "Discussion_name": "Discussion name", "Discussion_start": "Start a Discussion", - "Discussion_target_channel": "Parent channel or group", + "Discussion_target_channel": "Parent channel or team", "Discussion_target_channel_description": "Select a channel which is related to what you want to ask", "Discussion_target_channel_prefix": "You are creating a discussion in", "Discussion_title": "Create discussion", @@ -1719,6 +1724,7 @@ "Display_setting_permissions": "Display permissions to change settings", "Display_unread_counter": "Display room as unread when there are unread messages", "Displays_action_text": "Displays action text", + "Displayed_next_to_name": "Displayed next to name", "Do_It_Later": "Do It Later", "Do_not_display_unread_counter": "Do not display any counter of this channel", "Do_not_provide_this_code_to_anyone": "Do not provide this code to anyone.", @@ -1788,6 +1794,9 @@ "E2E_unavailable_for_federation": "E2E is unavailable for federated rooms", "ECDH_Enabled": "Enable second layer encryption for data transport", "Edit": "Edit", + "Edit_team": "Edit team", + "Edit_channel": "Edit channel", + "Edit_discussion": "Edit discussion", "Edit_Business_Hour": "Edit Business Hour", "Edit_Canned_Response": "Edit Canned Response", "Edit_Canned_Responses": "Edit Canned Responses", @@ -1888,6 +1897,7 @@ "Email_two-factor_authentication": "Email two-factor authentication", "Email_verified": "Email verified", "Enterprise_Only": "Enterprise only", + "Encrypted_field_hint": "Messages are end-to-end encrypted, search will not work and notifications may not show message content", "Email_sent": "Email sent", "Emoji": "Emoji", "Emoji_picker": "Emoji picker", @@ -1914,11 +1924,11 @@ "Enable_unlimited_apps": "Enable unlimited apps", "Enabled": "Enabled", "Encrypted": "Encrypted", - "Encrypted_channel_Description": "End-to-end encrypted channel. Search will not work with encrypted channels and notifications may not show the messages content.", + "Encrypted_channel_Description": "Messages are end-to-end encrypted, search will not work and notifications may not show message content", "Encrypted_key_title": "Click here to disable end-to-end encryption for this channel (requires e2ee-permission)", "Encrypted_message": "Encrypted message", "Encrypted_setting_changed_successfully": "Encrypted setting changed successfully", - "Encrypted_not_available": "Not available for Public Channels", + "Encrypted_not_available": "Not available for public {{roomType}}", "Encryption_key_saved_successfully": "Your encryption key was saved successfully.", "EncryptionKey_Change_Disabled": "You can't set a password for your encryption key because your private key is not present on this client. In order to set a new password you need load your private key using your existing password or use a client where the key is already loaded.", "End": "End", @@ -2125,7 +2135,7 @@ "error-tags-must-be-assigned-before-closing-chat": "Tag(s) must be assigned before closing the chat", "error-the-field-is-required": "The field {{field}} is required.", "error-this-is-not-a-livechat-room": "This is not a Omnichannel room", - "error-this-is-a-premium-feature": "This is from a premium feature", + "error-this-is-a-premium-feature": "Only available on premium plans", "error-token-already-exists": "A token with this name already exists", "error-token-does-not-exists": "Token does not exists", "error-too-many-requests": "Error, too many requests. Please slow down. You must wait {{seconds}} seconds before trying again.", @@ -2269,7 +2279,7 @@ "Federation_Matrix_Enabled_Alert": "More Information about Matrix Federation support can be found here (After any configuration, a restart is required to the changes take effect)", "Federation_Matrix_Federated": "Federated", "Federation_Matrix_Federated_Description": "By creating a federated room you'll not be able to enable encryption nor broadcast", - "Federation_Matrix_Federated_Description_disabled": "Federation is currently disabled in this workspace.", + "Federation_Matrix_Federated_Description_disabled": "Federation is currently disabled on this workspace", "Federation_Matrix_id": "AppService ID", "Federation_Matrix_hs_token": "Homeserver Token", "Federation_Matrix_as_token": "AppService Token", @@ -2526,7 +2536,7 @@ "Hide_roles": "Hide Roles", "Hide_room": "Hide", "Hide_Room_Warning": "Are you sure you want to hide the channel \"%s\"?", - "Hide_System_Messages": "Hide System Messages", + "Hide_System_Messages": "Hide system messages", "Hide_Unread_Room_Status": "Hide Unread Room Status", "Hide_usernames": "Hide Usernames", "Hide_video": "Hide video", @@ -2657,6 +2667,7 @@ "Incoming_WebHook": "Incoming WebHook", "Industry": "Industry", "Info": "Info", + "Information_to_keep_top_of_mind": "Information to keep top-of-mind", "initials_avatar": "Initials Avatar", "Inline_code": "Inline code", "Install": "Install", @@ -3506,40 +3517,40 @@ "Message_has_been_starred": "Message has been starred", "Message_has_been_unpinned": "Message has been unpinned", "Message_has_been_unstarred": "Message has been unstarred", - "Message_HideType_au": "Hide \"User Added\" messages", - "Message_HideType_added_user_to_team": "Hide \"User Added to Team\" messages", - "Message_HideType_mute_unmute": "Hide \"User Muted / Unmuted\" messages", - "Message_HideType_r": "Hide \"Room Name Changed\" messages", - "Message_HideType_rm": "Hide \"Message Removed\" messages", - "Message_HideType_room_allowed_reacting": "Hide \"Room allowed reacting\" messages", - "Message_HideType_room_archived": "Hide \"Room Archived\" messages", - "Message_HideType_room_changed_avatar": "Hide \"Room avatar changed\" messages", - "Message_HideType_room_changed_privacy": "Hide \"Room type changed\" messages", - "Message_HideType_room_changed_topic": "Hide \"Room topic changed\" messages", - "Message_HideType_room_disallowed_reacting": "Hide \"Room disallowed reacting\" messages", - "Message_HideType_room_enabled_encryption": "Hide \"Room encryption enabled\" messages", - "Message_HideType_room_disabled_encryption": "Hide \"Room encryption disabled\" messages", - "Message_HideType_room_set_read_only": "Hide \"Room set Read Only\" messages", - "Message_HideType_room_removed_read_only": "Hide \"Room added writing permission\" messages", - "Message_HideType_room_unarchived": "Hide \"Room Unarchived\" messages", - "Message_HideType_ru": "Hide \"User Removed\" messages", - "Message_HideType_removed_user_from_team": "Hide \"User Removed from Team\" messages", - "Message_HideType_subscription_role_added": "Hide \"Was Set Role\" messages", - "Message_HideType_subscription_role_removed": "Hide \"Role No Longer Defined\" messages", - "Message_HideType_uj": "Hide \"User Join\" messages", - "Message_HideType_ujt": "Hide \"User Joined Team\" messages", + "Message_HideType_au": "User added", + "Message_HideType_added_user_to_team": "User added to team", + "Message_HideType_mute_unmute": "User muted / unmuted", + "Message_HideType_r": "Room name changed", + "Message_HideType_rm": "Message removed", + "Message_HideType_room_allowed_reacting": "Room allowed reacting", + "Message_HideType_room_archived": "Room archived", + "Message_HideType_room_changed_avatar": "Room avatar changed", + "Message_HideType_room_changed_privacy": "Room type changed", + "Message_HideType_room_changed_topic": "Room topic changed", + "Message_HideType_room_disallowed_reacting": "Room disallowed reacting", + "Message_HideType_room_enabled_encryption": "Room encryption enabled", + "Message_HideType_room_disabled_encryption": "Room encryption disabled", + "Message_HideType_room_set_read_only": "Room set to Read Only", + "Message_HideType_room_removed_read_only": "Room added writing permission", + "Message_HideType_room_unarchived": "Room unarchived", + "Message_HideType_ru": "User removed", + "Message_HideType_removed_user_from_team": "User removed from team", + "Message_HideType_subscription_role_added": "Was set role", + "Message_HideType_subscription_role_removed": "Role no longer defined", + "Message_HideType_uj": "User joined", + "Message_HideType_ujt": "User joined team", "New_Call_Enterprise_Edition_Only": "New Call (Enterprise Edition Only)", - "Message_HideType_ul": "Hide \"User Leave\" messages", - "Message_HideType_ult": "Hide \"User Left Team\" messages", - "Message_HideType_user_added_room_to_team": "Hide \"User Added Room to Team\" messages", - "Message_HideType_user_converted_to_channel": "Hide \"User converted team to a Channel\" messages", - "Message_HideType_user_converted_to_team": "Hide \"User converted channel to a Team\" messages", - "Message_HideType_user_deleted_room_from_team": "Hide \"User deleted room from Team\" messages", - "Message_HideType_user_removed_room_from_team": "Hide \"User removed room from Team\" messages", - "Message_HideType_changed_description": "Hide \"Room description changed to\" messages", - "Message_HideType_changed_announcement": "Hide \"Room announcement changed to\" messages", - "Message_HideType_ut": "Hide \"User Joined Conversation\" messages", - "Message_HideType_wm": "Hide \"Welcome\" messages", + "Message_HideType_ul": "User left", + "Message_HideType_ult": "User left team", + "Message_HideType_user_added_room_to_team": "User added room to team", + "Message_HideType_user_converted_to_channel": "User converted team to a channel", + "Message_HideType_user_converted_to_team": "User converted channel to a team", + "Message_HideType_user_deleted_room_from_team": "User deleted room from team", + "Message_HideType_user_removed_room_from_team": "User removed room from team", + "Message_HideType_changed_description": "Room description changed", + "Message_HideType_changed_announcement": "Room announcement changed", + "Message_HideType_ut": "User joined conversation", + "Message_HideType_wm": "Welcome", "Message_HideType_livechat_closed": "Hide \"Conversation finished\" messages", "Message_HideType_livechat_started": "Hide \"Conversation started\" messages", "Message_HideType_livechat_transfer_history": "Hide \"Conversation transfered\" messages", @@ -3731,7 +3742,7 @@ "New_Custom_Field": "New Custom Field", "New_Department": "New Department", "New_discussion": "New discussion", - "New_discussion_first_message": "Usually, a discussion starts with a question, like \"How do I upload a picture?\"", + "New_discussion_first_message": "Usually, a discussion starts with a question, like “How do I upload a picture?”", "New_discussion_name": "A meaningful name for the discussion room", "New_Email_Inbox": "New Email Inbox", "New_encryption_password": "New encryption password", @@ -3759,6 +3770,7 @@ "New_workspace_confirmed": "New workspace confirmed", "New_workspace": "New workspace", "Newer_than": "Newer than", + "New_messages_cannot_be_sent": "New messages cannot be sent", "Newer_than_may_not_exceed_Older_than": "\"Newer than\" may not exceed \"Older than\"", "Nickname": "Nickname", "Nickname_Placeholder": "Enter your nickname...", @@ -3961,7 +3973,7 @@ "Only_On_Desktop": "Desktop mode (only sends with enter on desktop)", "Only_works_with_chrome_version_greater_50": "Only works with Chrome browser versions > 50", "Only_you_can_see_this_message": "Only you can see this message", - "Only_invited_users_can_acess_this_channel": "Only invited users can access this Channel", + "Only_invited_users_can_acess_this_channel": "Only invited users can access this channel", "Oops_page_not_found": "Oops, page not found", "Oops!": "Oops", "Person_Or_Channel": "Person or Channel", @@ -4052,6 +4064,7 @@ "Page_URL": "Page URL", "Pages": "Pages", "Parent_channel_doesnt_exist": "Channel does not exist.", + "Parent_channel_or_team": "Parent channel or team", "Participants": "Participants", "Password": "Password", "Password_Change_Disabled": "Your Rocket.Chat administrator has disabled the changing of passwords", @@ -4261,12 +4274,14 @@ "Rate Limiter_Description": "Control the rate of requests sent or received by your server to prevent cyber attacks and scraping.", "Rate_Limiter_Limit_RegisterUser": "Default number calls to the rate limiter for registering a user", "Rate_Limiter_Limit_RegisterUser_Description": "Number of default calls for user registering endpoints(REST and real-time API's), allowed within the time range defined in the API Rate Limiter section.", - "React_when_read_only": "Allow Reacting", + "React_when_read_only": "Allow reacting", "React_when_read_only_changed_successfully": "Allow reacting when read only changed successfully", "Reacted_with": "Reacted with", "Reactions": "Reactions", "Read_by": "Read by", - "Read_only": "Read Only", + "Read_only": "Read-only", + "Read_only_field_hint_enabled": "Only {{roomType}} owners can send new messages", + "Read_only_field_hint_disabled": "Anyone can send new messages", "Read_Receipts": "Read receipts", "Readability": "Readability", "This_room_is_read_only": "This room is read only", @@ -5079,7 +5094,7 @@ "Teams_channels_last_owner_delete_channel_warning": "You are the last owner of this Channel. Once you convert the Team into a channel, the Channel will be moved to the Workspace.", "Teams_channels_last_owner_leave_channel_warning": "You are the last owner of this Channel. Once you leave the Team, the Channel will be kept inside the Team but you will managing it from outside.", "Teams_leaving_team": "You are leaving this Team.", - "Teams_channels": "Team's Channels", + "Teams_channels": "Team channels", "Teams_convert_channel_to_team": "Convert to Team", "Teams_delete_team_choose_channels": "Select the Channels you would like to delete. The ones you decide to keep, will be available on your workspace.", "Teams_delete_team_public_notice": "Notice that public Channels will still be public and visible to everyone.", @@ -5094,25 +5109,26 @@ "Teams_move_channel_to_team_description_third": "Team’s members and even Team’s owners, if not a member of this Channel, can not have access to the Channel’s content.", "Teams_move_channel_to_team_description_fourth": "Please notice that the Team’s owner will be able to remove members from the Channel.", "Teams_move_channel_to_team_confirm_description": "After reading the previous instructions about this behavior, do you want to move forward with this action?", - "Teams_New_Title": "Create Team", + "Teams_New_Title": "Create team", + "Teams_new_description": "Teams allow a group of people to collaborate and can contain multiple channels.", "Teams_New_Name_Label": "Name", - "Teams_Info": "Team Information", + "Teams_Info": "Team info", "Teams_kept_channels": "You did not select the following Channels so they will be moved to the Workspace:", "Teams_kept__username__channels": "You did not select the following Channels so {{username}} will be kept on them:", "Teams_leave_channels": "Select the Team’s Channels you would like to leave.", "Teams_leave": "Leave Team", "Teams_left_team_successfully": "Left the Team successfully", "Teams_members": "Teams Members", - "Teams_New_Add_members_Label": "Add Members", - "Teams_New_Broadcast_Description": "Only authorized users can write new messages, but the other users will be able to reply", + "Teams_New_Add_members_Label": "Members", + "Teams_New_Broadcast_Description": "Only team owners can write new messages but anyone can reply in a thread", "Teams_New_Broadcast_Label": "Broadcast", "Teams_New_Description_Label": "Topic", "Teams_New_Description_Placeholder": "What is this team about", "Teams_New_Encrypted_Description_Disabled": "Only available for private team", "Teams_New_Encrypted_Description_Enabled": "End-to-end encrypted team. Search will not work with encrypted Teams and notifications may not show the messages content.", "Teams_New_Encrypted_Label": "Encrypted", - "Teams_New_Private_Description_Disabled": "When disabled, anyone can join the team", - "Teams_New_Private_Description_Enabled": "Only invited people can join", + "Teams_New_Private_Description_Disabled": "Anyone can access", + "Teams_New_Private_Description_Enabled": "People can only join by being invited", "Teams_New_Private_Label": "Private", "Teams_New_Read_only_Description": "All users in this team can write messages", "Teams_Public_Team": "Public Team", @@ -5122,7 +5138,7 @@ "Teams_removing__username__from_team_and_channels": "You are removing {{username}} from this Team and all its Channels.", "Teams_Select_a_team": "Select a team", "Teams_Search_teams": "Search Teams", - "Teams_New_Read_only_Label": "Read Only", + "Teams_New_Read_only_Label": "Read-only", "Technology_Services": "Technology Services", "Upgrade_tab_connection_error_description": "Looks like you have no internet connection. This may be because your workspace is installed on a fully-secured air-gapped server", "Terms": "Terms", @@ -5659,7 +5675,7 @@ "Videos": "Videos", "View_mode": "View Mode", "View_All": "View All Members", - "View_channels": "View Channels", + "View_channels": "View channels", "view-agent-canned-responses": "View Agent Canned Responses", "view-agent-canned-responses_description": "Permission to view agent canned responses", "view-agent-extension-association": "View Agent Extension Association", @@ -5887,7 +5903,7 @@ "Yes_clear_all": "Yes, clear all!", "Yes_continue": "Yes, continue!", "Yes_deactivate_it": "Yes, deactivate it!", - "Yes_delete_it": "Yes, delete it!", + "Yes_delete_it": "Yes, delete", "Yes_hide_it": "Yes, hide it!", "Yes_leave_it": "Yes, leave it!", "Yes_mute_user": "Yes, mute user!", @@ -6333,7 +6349,28 @@ "Seat_limit_reached": "Seat limit reached", "Seat_limit_reached_Description": "Your workspace reached its contractual seat limit. Buy more seats to add more users.", "Buy_more_seats": "Buy more seats", + "Anyone_can_react_to_messages": "Anyone can react to messages", + "Name_cannot_have_spaces": "Name cannot have spaces", + "No_spaces": "No spaces", + "Add_people": "Add people", + "Anyone_can_access": "Anyone can access", + "Only_invited_people": "People can only join by being invited", + "Broadcast_hint_enabled": "Only {{roomType}} owners can write new messages but anyone can reply in a thread", + "Federation_is_currently_disabled_on_this_workspace": "Federation is currently disabled on this workspace", + "Search_options": "Search options", + "First_message_hint": "A discussion can start with a question like \"How do I upload a picture?\"", + "Delete_roomType": "Delete {{roomType}}", + "Delete_roomType_description": "Deleting this {{roomType}} will also delete all contained message. This cannot be undone.", + "Deleted_roomType": "{{roomName}} {{roomType}} has been deleted", "unread_messages_one": "{{count}} unread message", "unread_messages_other": "{{count}} unread messages", - "Go_to_href": "Go to: {{href}}" + "Encrypted_messages": "End-to-end encrypted {{roomType}}. Search will not work with encrypted {{roomType}} and notifications may not show the messages content.", + "Encrypted_messages_false": "Messages are not encrypted", + "Not_available_for_broadcast": "Not available for broadcast {{roomType}}", + "Not_available_for_this_workspace": "Not available for this workspace", + "People_can_only_join_by_being_invited": "People can only join by being invited", + "Go_to_href": "Go to: {{href}}", + "Anyone_can_send_new_messages": "Anyone can send new messages", + "Select_messages_to_hide": "Select messages to hide", + "Name_cannot_have_special_characters": "Name cannot have spaces or special characters" } diff --git a/packages/rest-typings/src/v1/rooms.ts b/packages/rest-typings/src/v1/rooms.ts index 8d6a7476d939b..ab0046bdc38bc 100644 --- a/packages/rest-typings/src/v1/rooms.ts +++ b/packages/rest-typings/src/v1/rooms.ts @@ -130,6 +130,7 @@ type RoomsCreateDiscussionProps = { users?: IUser['username'][]; encrypted?: boolean; reply?: string; + topic?: string; }; const RoomsCreateDiscussionSchema = { diff --git a/packages/ui-avatar/package.json b/packages/ui-avatar/package.json index 30a7eda16e624..1d16fadf11f54 100644 --- a/packages/ui-avatar/package.json +++ b/packages/ui-avatar/package.json @@ -4,7 +4,7 @@ "private": true, "devDependencies": { "@babel/core": "~7.22.20", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/ui-contexts": "workspace:^", "@types/babel__core": "~7.20.3", "@types/react": "~17.0.69", diff --git a/packages/ui-client/package.json b/packages/ui-client/package.json index 0d099721c9a9d..936497ef732f2 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -6,7 +6,7 @@ "@babel/core": "~7.22.20", "@react-aria/toolbar": "^3.0.0-beta.1", "@rocket.chat/css-in-js": "~0.31.25", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/fuselage-hooks": "^0.33.0", "@rocket.chat/icons": "^0.34.0", "@rocket.chat/mock-providers": "workspace:^", diff --git a/packages/ui-composer/package.json b/packages/ui-composer/package.json index 37599b373ddd6..fec0f71679373 100644 --- a/packages/ui-composer/package.json +++ b/packages/ui-composer/package.json @@ -6,7 +6,7 @@ "@babel/core": "~7.22.20", "@react-aria/toolbar": "^3.0.0-beta.1", "@rocket.chat/eslint-config": "workspace:^", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/icons": "^0.34.0", "@storybook/addon-actions": "~6.5.16", "@storybook/addon-docs": "~6.5.16", diff --git a/packages/ui-video-conf/package.json b/packages/ui-video-conf/package.json index 05a5e390f25b1..8839e6c1b5b5a 100644 --- a/packages/ui-video-conf/package.json +++ b/packages/ui-video-conf/package.json @@ -6,7 +6,7 @@ "@babel/core": "~7.22.20", "@rocket.chat/css-in-js": "~0.31.25", "@rocket.chat/eslint-config": "workspace:^", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/fuselage-hooks": "^0.33.0", "@rocket.chat/icons": "^0.34.0", "@rocket.chat/styled": "~0.31.25", diff --git a/packages/uikit-playground/package.json b/packages/uikit-playground/package.json index 6ed09b1265e2a..b3d1683b7455b 100644 --- a/packages/uikit-playground/package.json +++ b/packages/uikit-playground/package.json @@ -15,7 +15,7 @@ "@codemirror/tooltip": "^0.19.16", "@lezer/highlight": "^1.1.6", "@rocket.chat/css-in-js": "~0.31.25", - "@rocket.chat/fuselage": "^0.51.1", + "@rocket.chat/fuselage": "^0.52.0", "@rocket.chat/fuselage-hooks": "^0.33.0", "@rocket.chat/fuselage-polyfills": "~0.31.25", "@rocket.chat/fuselage-toastbar": "^0.31.26", diff --git a/yarn.lock b/yarn.lock index dba696d109dc2..ba550482d1190 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8732,7 +8732,7 @@ __metadata: "@babel/preset-typescript": ~7.22.15 "@rocket.chat/apps-engine": 1.42.0-alpha.619 "@rocket.chat/eslint-config": "workspace:^" - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/fuselage-hooks": ^0.33.0 "@rocket.chat/fuselage-polyfills": ~0.31.25 "@rocket.chat/gazzodown": "workspace:^" @@ -8787,9 +8787,9 @@ __metadata: languageName: unknown linkType: soft -"@rocket.chat/fuselage@npm:^0.51.1": - version: 0.51.1 - resolution: "@rocket.chat/fuselage@npm:0.51.1" +"@rocket.chat/fuselage@npm:^0.52.0": + version: 0.52.0 + resolution: "@rocket.chat/fuselage@npm:0.52.0" dependencies: "@rocket.chat/css-in-js": ^0.31.25 "@rocket.chat/css-supports": ^0.31.25 @@ -8807,7 +8807,7 @@ __metadata: react: ^17.0.2 react-dom: ^17.0.2 react-virtuoso: 1.2.4 - checksum: f7f49a59d67a485a4aff8aa2684fb0bb290c73b643763c867da23ed00c19994b24b994c554d2bd63d48657ca7fdfbff9bf34bbe2436376972809b56cb15ee456 + checksum: 518c96ad67dcb2395c6299842250c1e87959e53ee54fee2bb4d813a41a8e78913e599adc4c73258f7e99249bb2351cf8b94dd8a3bfb2ba5473aa80f051cfac40 languageName: node linkType: hard @@ -8818,7 +8818,7 @@ __metadata: "@babel/core": ~7.22.20 "@rocket.chat/core-typings": "workspace:^" "@rocket.chat/css-in-js": ~0.31.25 - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/fuselage-tokens": ^0.33.0 "@rocket.chat/message-parser": "workspace:^" "@rocket.chat/styled": ~0.31.25 @@ -9178,7 +9178,7 @@ __metadata: "@rocket.chat/favicon": "workspace:^" "@rocket.chat/forked-matrix-appservice-bridge": ^4.0.2 "@rocket.chat/forked-matrix-bot-sdk": ^0.6.0-beta.3 - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/fuselage-hooks": ^0.33.0 "@rocket.chat/fuselage-polyfills": ~0.31.25 "@rocket.chat/fuselage-toastbar": ^0.31.26 @@ -10060,7 +10060,7 @@ __metadata: resolution: "@rocket.chat/ui-avatar@workspace:packages/ui-avatar" dependencies: "@babel/core": ~7.22.20 - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/ui-contexts": "workspace:^" "@types/babel__core": ~7.20.3 "@types/react": ~17.0.69 @@ -10086,7 +10086,7 @@ __metadata: "@babel/core": ~7.22.20 "@react-aria/toolbar": ^3.0.0-beta.1 "@rocket.chat/css-in-js": ~0.31.25 - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/fuselage-hooks": ^0.33.0 "@rocket.chat/icons": ^0.34.0 "@rocket.chat/mock-providers": "workspace:^" @@ -10139,7 +10139,7 @@ __metadata: "@babel/core": ~7.22.20 "@react-aria/toolbar": ^3.0.0-beta.1 "@rocket.chat/eslint-config": "workspace:^" - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/icons": ^0.34.0 "@storybook/addon-actions": ~6.5.16 "@storybook/addon-docs": ~6.5.16 @@ -10231,7 +10231,7 @@ __metadata: resolution: "@rocket.chat/ui-theming@workspace:ee/packages/ui-theming" dependencies: "@rocket.chat/css-in-js": ~0.31.25 - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/fuselage-hooks": ^0.33.0 "@rocket.chat/icons": ^0.34.0 "@rocket.chat/ui-contexts": "workspace:~" @@ -10274,7 +10274,7 @@ __metadata: "@rocket.chat/css-in-js": ~0.31.25 "@rocket.chat/emitter": ~0.31.25 "@rocket.chat/eslint-config": "workspace:^" - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/fuselage-hooks": ^0.33.0 "@rocket.chat/icons": ^0.34.0 "@rocket.chat/styled": ~0.31.25 @@ -10319,7 +10319,7 @@ __metadata: "@codemirror/tooltip": ^0.19.16 "@lezer/highlight": ^1.1.6 "@rocket.chat/css-in-js": ~0.31.25 - "@rocket.chat/fuselage": ^0.51.1 + "@rocket.chat/fuselage": ^0.52.0 "@rocket.chat/fuselage-hooks": ^0.33.0 "@rocket.chat/fuselage-polyfills": ~0.31.25 "@rocket.chat/fuselage-toastbar": ^0.31.26