Skip to content

Commit

Permalink
Merge branch 'develop' into feat/livechat-hide-system-messages
Browse files Browse the repository at this point in the history
  • Loading branch information
kodiakhq[bot] authored Mar 21, 2024
2 parents 00997b0 + d742b25 commit a222f18
Show file tree
Hide file tree
Showing 122 changed files with 2,173 additions and 753 deletions.
5 changes: 5 additions & 0 deletions .changeset/breezy-fireants-float.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Fixes an issue not allowing edit webhooks properly
5 changes: 5 additions & 0 deletions .changeset/brown-houses-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Fixed a problem that caused Business Hours feature (Multiple) to make bot agents not available when turning on the feature, and not making them available after that. Now, Business Hours will ignore Bot users, allowing admins to decide manually if a bot should be or not be active during a period of time
5 changes: 5 additions & 0 deletions .changeset/lovely-berries-type.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

Allowed upload of `lst` files
5 changes: 5 additions & 0 deletions .changeset/moody-ghosts-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---

Don't use the registration.yaml file to configure Matrix Federation anymore.
6 changes: 6 additions & 0 deletions .changeset/polite-cars-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/livechat": patch
---

Fixes issue where the livechat offline form would render even when disabled
5 changes: 5 additions & 0 deletions .changeset/spotty-students-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---

fix: Show always all rooms when requesting chat history, even unserved ones. A faulty condition caused an issue where chat history was only able to present either served or unserved chats at once, without a proper way to get both. Now, the Chat history feature will showcase all closed rooms for the requested visitor.
9 changes: 9 additions & 0 deletions .changeset/tough-doors-juggle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@rocket.chat/meteor": patch
---

Introduced a new step to the queue worker: when an inquiry that's on an improper status is selected for processing, queue worker will first check its status and will attempt to fix it.
For example, if an inquiry points to a closed room, there's no point in processing, system will now remove the inquiry
If an inquiry is already taken, the inquiry will be updated to reflect the new status and clean the queue.

This prevents issues where the queue worker attempted to process an inquiry _forever_ because it was in an improper state.
Original file line number Diff line number Diff line change
Expand Up @@ -52,37 +52,31 @@ export class LivechatAgentActivityMonitor {
// TODO use service event socket.connected instead
Meteor.onConnection((connection: unknown) => this._handleMeteorConnection(connection as ISocketConnection));
callbacks.add('livechat.agentStatusChanged', this._handleAgentStatusChanged);
callbacks.add('livechat.setUserStatusLivechat', async (...args) => {
callbacks.add('livechat.setUserStatusLivechat', (...args) => {
return this._handleUserStatusLivechatChanged(...args);
});
this._started = true;
}

async _startMonitoring(): Promise<void> {
await this.scheduler.add(this._name, '0 0 * * *', async () => this._updateActiveSessions());
await this.scheduler.add(this._name, '0 0 * * *', () => this._updateActiveSessions());
}

async _updateActiveSessions(): Promise<void> {
const openLivechatAgentSessions = await LivechatAgentActivity.findOpenSessions();
if (!(await openLivechatAgentSessions.count())) {
return;
}
const openLivechatAgentSessions = LivechatAgentActivity.findOpenSessions();

const today = moment(new Date());
const startedAt = new Date(today.year(), today.month(), today.date());
for await (const session of openLivechatAgentSessions) {
const startDate = moment(session.lastStartedAt);
const stoppedAt = new Date(startDate.year(), startDate.month(), startDate.date(), 23, 59, 59);
const data = { ...formatDate(startDate.toDate()), agentId: session.agentId };
const availableTime = moment(stoppedAt).diff(moment(new Date(session.lastStartedAt)), 'seconds');
await LivechatAgentActivity.updateLastStoppedAt({
...data,
availableTime,
lastStoppedAt: stoppedAt,
});
await LivechatAgentActivity.updateServiceHistory({
...data,
serviceHistory: { startedAt: session.lastStartedAt, stoppedAt },
});

await Promise.all([
LivechatAgentActivity.updateLastStoppedAt({ ...data, availableTime, lastStoppedAt: stoppedAt }),
LivechatAgentActivity.updateServiceHistory({ ...data, serviceHistory: { startedAt: session.lastStartedAt, stoppedAt } }),
]);
await this._createOrUpdateSession(session.agentId, startedAt);
}
}
Expand All @@ -96,7 +90,9 @@ export class LivechatAgentActivityMonitor {
if (!session) {
return;
}
const user = await Users.findOneById<ILivechatAgent>(session.userId);
const user = await Users.findOneById<Pick<ILivechatAgent, '_id' | 'statusLivechat' | 'status'>>(session.userId, {
projection: { _id: 1, status: 1, statusLivechat: 1 },
});
if (user && user.status !== 'offline' && user.statusLivechat === 'available') {
await this._createOrUpdateSession(user._id);
}
Expand All @@ -112,7 +108,7 @@ export class LivechatAgentActivityMonitor {
return;
}

const user = await Users.findOneById<ILivechatAgent>(userId);
const user = await Users.findOneById<Pick<ILivechatAgent, '_id' | 'statusLivechat'>>(userId, { projection: { statusLivechat: 1 } });
if (!user || user.statusLivechat !== 'available') {
return;
}
Expand All @@ -129,7 +125,7 @@ export class LivechatAgentActivityMonitor {
return;
}

const user = await Users.findOneById(userId);
const user = await Users.findOneById<Pick<ILivechatAgent, '_id' | 'status'>>(userId, { projection: { status: 1 } });
if (user && user.status === 'offline') {
return;
}
Expand Down Expand Up @@ -158,16 +154,13 @@ export class LivechatAgentActivityMonitor {
const stoppedAt = new Date();
const availableTime = moment(stoppedAt).diff(moment(new Date(livechatSession.lastStartedAt)), 'seconds');

await LivechatAgentActivity.updateLastStoppedAt({
agentId,
date,
availableTime,
lastStoppedAt: stoppedAt,
});
await LivechatAgentActivity.updateServiceHistory({
agentId,
date,
serviceHistory: { startedAt: livechatSession.lastStartedAt, stoppedAt },
});
await Promise.all([
LivechatAgentActivity.updateLastStoppedAt({ agentId, date, availableTime, lastStoppedAt: stoppedAt }),
LivechatAgentActivity.updateServiceHistory({
agentId,
date,
serviceHistory: { startedAt: livechatSession.lastStartedAt, stoppedAt },
}),
]);
}
}
1 change: 1 addition & 0 deletions apps/meteor/app/utils/lib/mimeTypes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import mime from 'mime-type/with-db';

mime.types.wav = 'audio/wav';
mime.types.lst = 'text/plain';
mime.define('image/vnd.microsoft.icon', { source: '', extensions: ['ico'] }, mime.dupAppend);
mime.define('image/x-icon', { source: '', extensions: ['ico'] }, mime.dupAppend);
mime.types.ico = 'image/x-icon';
Expand Down
17 changes: 0 additions & 17 deletions apps/meteor/client/components/Contextualbar/Contextualbar.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { Contextualbar } from '@rocket.chat/fuselage';
import { useLayoutSizes, useLayoutContextualBarPosition } from '@rocket.chat/ui-contexts';
import type { ComponentProps, KeyboardEvent } from 'react';
import React, { useCallback, useRef } from 'react';
import type { AriaDialogProps } from 'react-aria';
import { FocusScope, useDialog } from 'react-aria';

import { useRoomToolbox } from '../../views/room/contexts/RoomToolboxContext';

type ContextualbarDialogProps = AriaDialogProps & ComponentProps<typeof Contextualbar>;

/**
* TODO: inside administration it should have a mechanism to display the contextualbar programmatically
* @prop closeTab only work inside a room
* */
const ContextualbarDialog = (props: ContextualbarDialogProps) => {
const ref = useRef(null);
const { dialogProps } = useDialog({ 'aria-labelledby': 'contextualbarTitle', ...props }, ref);
const sizes = useLayoutSizes();
const position = useLayoutContextualBarPosition();
const { closeTab } = useRoomToolbox();

const callbackRef = useCallback(
(node) => {
if (!node) {
return;
}

ref.current = node;
node.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'Escape') {
closeTab();
}
});
},
[closeTab],
);

return (
<FocusScope autoFocus restoreFocus>
<Contextualbar ref={callbackRef} width={sizes.contextualBar} position={position} {...dialogProps} {...props} />
</FocusScope>
);
};

export default ContextualbarDialog;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ContextualbarTitle as ContextualbarTitleComponent } from '@rocket.chat/fuselage';
import type { ComponentProps } from 'react';
import React from 'react';

const ContextualbarTitle = (props: ComponentProps<typeof ContextualbarTitleComponent>) => (
<ContextualbarTitleComponent id='contextualbarTitle' {...props} />
);

export default ContextualbarTitle;
6 changes: 4 additions & 2 deletions apps/meteor/client/components/Contextualbar/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import {
Contextualbar,
ContextualbarAction,
ContextualbarActions,
ContextualbarContent,
ContextualbarSkeleton,
ContextualbarIcon,
ContextualbarFooter,
ContextualbarTitle,
ContextualbarEmptyContent,
} from '@rocket.chat/fuselage';

import Contextualbar from './Contextualbar';
import ContextualbarBack from './ContextualbarBack';
import ContextualbarClose from './ContextualbarClose';
import ContextualbarDialog from './ContextualbarDialog';
import ContextualbarHeader from './ContextualbarHeader';
import ContextualbarInnerContent from './ContextualbarInnerContent';
import ContextualbarScrollableContent from './ContextualbarScrollableContent';
import ContextualbarTitle from './ContextualbarTitle';

export {
Contextualbar,
ContextualbarDialog,
ContextualbarHeader,
ContextualbarAction,
ContextualbarActions,
Expand Down
19 changes: 13 additions & 6 deletions apps/meteor/client/components/MarkdownText.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { Box } from '@rocket.chat/fuselage';
import { isExternal, getBaseURI } from '@rocket.chat/ui-client';
import { useTranslation } from '@rocket.chat/ui-contexts';
import dompurify from 'dompurify';
import { marked } from 'marked';
import type { ComponentProps, FC } from 'react';
Expand All @@ -25,7 +27,7 @@ marked.Lexer.rules.gfm = {
};

const linkMarked = (href: string | null, _title: string | null, text: string): string =>
`<a href="${href}" target="_blank" rel="nofollow noopener noreferrer">${text}</a> `;
`<a href="${href}" rel="nofollow noopener noreferrer">${text}</a> `;
const paragraphMarked = (text: string): string => text;
const brMarked = (): string => ' ';
const listItemMarked = (text: string): string => {
Expand Down Expand Up @@ -85,7 +87,7 @@ const MarkdownText: FC<Partial<MarkdownTextParams>> = ({
...props
}) => {
const sanitizer = dompurify.sanitize;

const t = useTranslation();
let markedOptions: marked.MarkedOptions;

const schemes = 'http,https,notes,ftp,ftps,tel,mailto,sms,cid';
Expand Down Expand Up @@ -120,17 +122,22 @@ const MarkdownText: FC<Partial<MarkdownTextParams>> = ({
}
})();

// Add a hook to make all links open a new window
// Add a hook to make all external links open a new window
dompurify.addHook('afterSanitizeAttributes', (node) => {
// set all elements owning target to target=_blank
if ('target' in node) {
node.setAttribute('target', '_blank');
const href = node.getAttribute('href') || '';

node.setAttribute('title', `${t('Go_to_href', { href: href.replace(getBaseURI(), '') })}`);
node.setAttribute('rel', 'nofollow noopener noreferrer');
if (isExternal(node.getAttribute('href') || '')) {
node.setAttribute('target', '_blank');
node.setAttribute('title', href);
}
}
});

return preserveHtml ? html : html && sanitizer(html, { ADD_ATTR: ['target'], ALLOWED_URI_REGEXP: getRegexp(schemes) });
}, [preserveHtml, sanitizer, content, variant, markedOptions, parseEmoji, schemes]);
}, [preserveHtml, sanitizer, content, variant, markedOptions, parseEmoji, t]);

return __html ? (
<Box
Expand Down
2 changes: 1 addition & 1 deletion apps/meteor/client/components/UserInfo/UserInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const UserInfo = ({
</InfoPanel.Avatar>
)}

{actions && <InfoPanel.Section>{actions}</InfoPanel.Section>}
{actions && <InfoPanel.ActionGroup>{actions}</InfoPanel.ActionGroup>}

<InfoPanel.Section>
{userDisplayName && <InfoPanel.Title icon={status} title={userDisplayName} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useSetting } from '@rocket.chat/ui-contexts';
import { useMemo } from 'react';

import type { MessageWithMdEnforced } from '../../../lib/parseMessageTextToAstMarkdown';
import { parseMessageTextToAstMarkdown, removePossibleNullMessageValues } from '../../../lib/parseMessageTextToAstMarkdown';
import { parseMessageTextToAstMarkdown } from '../../../lib/parseMessageTextToAstMarkdown';
import { useAutoLinkDomains } from '../../../views/room/MessageList/hooks/useAutoLinkDomains';
import { useAutoTranslate } from '../../../views/room/MessageList/hooks/useAutoTranslate';
import { useKatex } from '../../../views/room/MessageList/hooks/useKatex';
Expand All @@ -30,6 +30,6 @@ export const useNormalizedMessage = <TMessage extends IMessage>(message: TMessag
}),
};

return parseMessageTextToAstMarkdown(removePossibleNullMessageValues(message), parseOptions, autoTranslateOptions);
return parseMessageTextToAstMarkdown(message, parseOptions, autoTranslateOptions);
}, [showColors, customDomains, katexEnabled, katexDollarSyntaxEnabled, katexParenthesisSyntaxEnabled, message, autoTranslateOptions]);
};
2 changes: 1 addition & 1 deletion apps/meteor/client/hooks/useRoomInfoEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { Meteor } from 'meteor/meteor';

export const useRoomInfoEndpoint = (rid: IRoom['_id']): UseQueryResult<OperationResult<'GET', '/v1/rooms.info'>> => {
const getRoomInfo = useEndpoint('GET', '/v1/rooms.info');
return useQuery(['rooms/info', rid], () => getRoomInfo({ roomId: rid }), {
return useQuery(['/v1/rooms.info', rid], () => getRoomInfo({ roomId: rid }), {
cacheTime: minutesToMilliseconds(15),
staleTime: minutesToMilliseconds(5),
retry: (count, error: Meteor.Error) => {
Expand Down
Loading

0 comments on commit a222f18

Please sign in to comment.