Skip to content

Commit

Permalink
Merge branch 'new/threadTemplate' of github.com:RocketChat/Rocket.Cha…
Browse files Browse the repository at this point in the history
…t into new/threadTemplate-thread-components

* 'new/threadTemplate' of github.com:RocketChat/Rocket.Chat:
  Chore: migrate from cypress to pw 14-setting-permission (#25523)
  Chore: Tests with Playwright (task: ROC-31, 12-settings) (#25253)
  Chore: Migrate 15-message-popup from cypress to playwright (#25462)
  Chore: Convert apps/meteor/client/views/admin/settings/inputs folder (#25427)
  [FIX] UI/UX issues on Live Chat widget (#25407)
  Chore: Convert Admin -> Rooms to TS (#25348)
  • Loading branch information
gabriellsh committed May 17, 2022
2 parents 6735044 + 0e05742 commit 382cec3
Show file tree
Hide file tree
Showing 66 changed files with 1,487 additions and 404 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

{{#if canSend}}
{{> messageBoxAudioMessage rid=rid tmid=tmid}}
<span class="rc-message-box__action-menu js-action-menu" data-desktop aria-haspopup="true">
<span class="rc-message-box__action-menu js-action-menu" data-desktop aria-haspopup="true" data-qa-id="menu-more-actions">
{{#if actions}}
<span class="rc-message-box__icon">
{{> icon block="rc-input__icon-svg" icon="plus"}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<div class="rc-message-box__icon rc-message-box__audio-message-done js-audio-message-done">
{{> icon block="rc-input__icon-svg" icon="checkmark-circled"}}
</div>
<div class="rc-message-box__icon rc-message-box__audio-message-mic js-audio-message-record">
<div class="rc-message-box__icon rc-message-box__audio-message-mic js-audio-message-record" data-qa-id="audio-record">
{{> icon block="rc-input__icon-svg" icon="mic"}}
</div>
<div class="rc-message-box__icon rc-message-box__audio-message-loading js-audio-message-loading">
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/client/components/avatar/RoomAvatarEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IRoom } from '@rocket.chat/core-typings';
import { IRoom, RoomAdminFieldsType } from '@rocket.chat/core-typings';
import { css } from '@rocket.chat/css-in-js';
import { Box, Button, ButtonGroup, Icon } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
Expand All @@ -10,7 +10,7 @@ import { useFileInput } from '../../hooks/useFileInput';
import RoomAvatar from './RoomAvatar';

type RoomAvatarEditorProps = {
room: IRoom;
room: Pick<IRoom, RoomAdminFieldsType>;
roomAvatar?: string;
onChangeAvatar: (url: string | null) => void;
};
Expand Down
4 changes: 2 additions & 2 deletions apps/meteor/client/lib/rooms/roomCoordinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class RoomCoordinatorClient extends RoomCoordinator {
getAvatarPath(_room): string {
return '';
},
getIcon(_room: Partial<IRoom>): string | undefined {
getIcon(_room: Partial<IRoom>): IRoomTypeConfig['icon'] {
return this.config.icon;
},
getUserStatus(_roomId: string): string | undefined {
Expand Down Expand Up @@ -92,7 +92,7 @@ class RoomCoordinatorClient extends RoomCoordinator {
openRoom(type, name, render);
}

getIcon(room: Partial<IRoom>): string | undefined {
getIcon(room: Partial<IRoom>): IRoomTypeConfig['icon'] {
return room?.t && this.getRoomDirectives(room.t)?.getIcon(room);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,20 @@ const PermissionsTable = (): ReactElement => {
</Page.Header>
<Margins blockEnd='x16'>
<Tabs>
<Tabs.Item selected={type === 'permissions'} onClick={handlePermissionsTab} disabled={!canViewPermission}>
<Tabs.Item
data-qa='PermissionTable-Permissions'
selected={type === 'permissions'}
onClick={handlePermissionsTab}
disabled={!canViewPermission}
>
{t('Permissions')}
</Tabs.Item>
<Tabs.Item selected={type === 'settings'} onClick={handleSettingsTab} disabled={!canViewSettingPermission}>
<Tabs.Item
data-qa='PermissionTable-Settings'
selected={type === 'settings'}
onClick={handleSettingsTab}
disabled={!canViewSettingPermission}
>
{t('Settings')}
</Tabs.Item>
</Tabs>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ const PermissionsTableFilter = ({ onChange }: { onChange: (debouncedFilter: stri
setFilter(value);
});

return <TextInput value={filter} onChange={handleFilter} placeholder={t('Search')} flexGrow={0} />;
return (
<TextInput
data-qa='PermissionTable-PermissionsTableFilter'
value={filter}
onChange={handleFilter}
placeholder={t('Search')}
flexGrow={0}
/>
);
};

export default PermissionsTableFilter;
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { IRoom, RoomAdminFieldsType } from '@rocket.chat/core-typings';
import { Box, Button, ButtonGroup, TextInput, Field, ToggleSwitch, Icon, TextAreaInput } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import {
Expand All @@ -9,7 +10,7 @@ import {
useMethod,
useTranslation,
} from '@rocket.chat/ui-contexts';
import React, { useState, useMemo } from 'react';
import React, { useState, useMemo, ReactElement } from 'react';

import { RoomSettingsEnum } from '../../../../definition/IRoomTypeConfig';
import GenericModal from '../../../components/GenericModal';
Expand All @@ -18,10 +19,30 @@ import RoomAvatarEditor from '../../../components/avatar/RoomAvatarEditor';
import { useEndpointActionExperimental } from '../../../hooks/useEndpointActionExperimental';
import { useForm } from '../../../hooks/useForm';
import { roomCoordinator } from '../../../lib/rooms/roomCoordinator';
import DeleteTeamModal from '../../teams/contextualBar/info/Delete/DeleteTeamModal';
import DeleteTeamModalWithRooms from '../../teams/contextualBar/info/Delete';

const getInitialValues = (room) => ({
roomName: room.t === 'd' ? room.usernames.join(' x ') : roomCoordinator.getRoomName(room.t, { type: room.t, ...room }),
type EditRoomProps = {
room: Pick<IRoom, RoomAdminFieldsType>;
onChange: () => void;
onDelete: () => void;
};

type EditRoomFormValues = {
roomName: IRoom['name'];
roomTopic: string;
roomType: IRoom['t'];
readOnly: boolean;
isDefault: boolean;
favorite: boolean;
featured: boolean;
roomDescription: string;
roomAnnouncement: string;
roomAvatar: IRoom['avatarETag'];
archived: boolean;
};

const getInitialValues = (room: Pick<IRoom, RoomAdminFieldsType>): EditRoomFormValues => ({
roomName: room.t === 'd' ? room.usernames?.join(' x ') : roomCoordinator.getRoomName(room.t, room),
roomType: room.t,
readOnly: !!room.ro,
archived: !!room.archived,
Expand All @@ -34,26 +55,27 @@ const getInitialValues = (room) => ({
roomAvatar: undefined,
});

function EditRoom({ room, onChange, onDelete }) {
const EditRoom = ({ room, onChange, onDelete }: EditRoomProps): ReactElement => {
const t = useTranslation();

const [deleting, setDeleting] = useState(false);

const setModal = useSetModal();
const dispatchToastMessage = useToastMessageDispatch();

const { values, handlers, hasUnsavedChanges, reset } = useForm(getInitialValues(room));

const [canViewName, canViewTopic, canViewAnnouncement, canViewArchived, canViewDescription, canViewType, canViewReadOnly] =
useMemo(() => {
const isAllowed = roomCoordinator.getRoomDirectives(room.t)?.allowRoomSettingChange;
return [
isAllowed(room, RoomSettingsEnum.NAME),
isAllowed(room, RoomSettingsEnum.TOPIC),
isAllowed(room, RoomSettingsEnum.ANNOUNCEMENT),
isAllowed(room, RoomSettingsEnum.ARCHIVE_OR_UNARCHIVE),
isAllowed(room, RoomSettingsEnum.DESCRIPTION),
isAllowed(room, RoomSettingsEnum.TYPE),
isAllowed(room, RoomSettingsEnum.READ_ONLY),
isAllowed?.(room, RoomSettingsEnum.NAME),
isAllowed?.(room, RoomSettingsEnum.TOPIC),
isAllowed?.(room, RoomSettingsEnum.ANNOUNCEMENT),
isAllowed?.(room, RoomSettingsEnum.ARCHIVE_OR_UNARCHIVE),
isAllowed?.(room, RoomSettingsEnum.DESCRIPTION),
isAllowed?.(room, RoomSettingsEnum.TYPE),
isAllowed?.(room, RoomSettingsEnum.READ_ONLY),
];
}, [room]);

Expand All @@ -69,7 +91,7 @@ function EditRoom({ room, onChange, onDelete }) {
roomAvatar,
roomDescription,
roomAnnouncement,
} = values;
} = values as EditRoomFormValues;

const {
handleIsDefault,
Expand Down Expand Up @@ -98,7 +120,7 @@ function EditRoom({ room, onChange, onDelete }) {
const archiveAction = useEndpointActionExperimental('POST', 'rooms.changeArchivationState', t(archiveMessage));

const handleSave = useMutableCallback(async () => {
const save = () =>
const save = (): Promise<{ success: boolean; rid: string }> =>
saveAction({
rid: room._id,
roomName: roomType === 'd' ? undefined : roomName,
Expand All @@ -113,9 +135,12 @@ function EditRoom({ room, onChange, onDelete }) {
roomAvatar,
});

const archive = () => archiveAction({ rid: room._id, action: archiveSelector });
const archive = (): Promise<{ success: boolean }> => archiveAction({ rid: room._id, action: archiveSelector });

await Promise.all([hasUnsavedChanges && save(), changeArchivation && archive()].filter(Boolean));
const promises = [];
hasUnsavedChanges && promises.push(save());
changeArchivation && promises.push(archive());
await Promise.all(promises);
onChange();
});

Expand All @@ -129,25 +154,25 @@ function EditRoom({ room, onChange, onDelete }) {
const handleDelete = useMutableCallback(() => {
if (room.teamMain) {
setModal(
<DeleteTeamModal
onConfirm={async (deletedRooms) => {
const roomsToRemove = Array.isArray(deletedRooms) && deletedRooms.length > 0 ? deletedRooms : [];
<DeleteTeamModalWithRooms
onConfirm={async (deletedRooms: IRoom[]): Promise<void> => {
const roomsToRemove = Array.isArray(deletedRooms) && deletedRooms.length > 0 ? deletedRooms.map((room) => room._id) : [];

try {
setDeleting(true);
setModal(null);
await deleteTeam({ teamId: room.teamId, ...(roomsToRemove.length && { roomsToRemove }) });
await deleteTeam({ teamId: room.teamId as string, ...(roomsToRemove.length && { roomsToRemove }) });
dispatchToastMessage({ type: 'success', message: t('Team_has_been_deleted') });
roomsRoute.push({});
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
dispatchToastMessage({ type: 'error', message: String(error) });
setDeleting(false);
} finally {
onDelete();
}
}}
onCancel={() => setModal(null)}
teamId={room.teamId}
onCancel={(): void => setModal(null)}
teamId={room.teamId as string}
/>,
);

Expand All @@ -157,21 +182,22 @@ function EditRoom({ room, onChange, onDelete }) {
setModal(
<GenericModal
variant='danger'
onConfirm={async () => {
onConfirm={async (): Promise<void> => {
try {
setDeleting(true);
setModal(null);
await eraseRoom(room._id);
dispatchToastMessage({ type: 'success', message: t('Room_has_been_deleted') });
roomsRoute.push({});
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
dispatchToastMessage({ type: 'error', message: String(error) });
setDeleting(false);
} finally {
onDelete();
}
}}
onCancel={() => setModal(null)}
onClose={(): void => setModal(null)}
onCancel={(): void => setModal(null)}
confirmText={t('Yes_delete_it')}
>
{t('Delete_Room_Warning')}
Expand Down Expand Up @@ -304,6 +330,6 @@ function EditRoom({ room, onChange, onDelete }) {
</Field>
</VerticalBar.ScrollableContent>
);
}
};

export default EditRoom;
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { usePermission } from '@rocket.chat/ui-contexts';
import React from 'react';
import React, { ReactElement } from 'react';

import NotAuthorizedPage from '../../notAuthorized/NotAuthorizedPage';
import EditRoomWithData from './EditRoomWithData';

function EditRoomContextBar({ rid, onReload }) {
const EditRoomContextBar = ({ rid, onReload }: { rid: string | undefined; onReload: () => void }): ReactElement => {
const canViewRoomAdministration = usePermission('view-room-administration');
return canViewRoomAdministration ? <EditRoomWithData rid={rid} onReload={onReload} /> : <NotAuthorizedPage />;
}
};

export default EditRoomContextBar;
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Box, Skeleton } from '@rocket.chat/fuselage';
import React, { useMemo } from 'react';
import React, { useMemo, FC } from 'react';

import { AsyncStatePhase } from '../../../hooks/useAsyncState';
import { useEndpointData } from '../../../hooks/useEndpointData';
import EditRoom from './EditRoom';

function EditRoomWithData({ rid, onReload }) {
const EditRoomWithData: FC<{ rid?: string; onReload: () => void }> = ({ rid, onReload }) => {
const {
value: data = {},
value: data,
phase: state,
error,
reload,
Expand All @@ -30,19 +30,19 @@ function EditRoomWithData({ rid, onReload }) {
}

if (state === AsyncStatePhase.REJECTED) {
return error.message;
return <>{error?.message}</>;
}

const handleChange = () => {
const handleChange = (): void => {
reload();
onReload();
};

const handleDelete = () => {
const handleDelete = (): void => {
onReload();
};

return <EditRoom room={{ type: data.t, ...data }} onChange={handleChange} onDelete={handleDelete} />;
}
return data ? <EditRoom room={data} onChange={handleChange} onDelete={handleDelete} /> : null;
};

export default EditRoomWithData;
Loading

0 comments on commit 382cec3

Please sign in to comment.