From ee1d14618f42144a3aca6bc33cc6bf87292dc3fc Mon Sep 17 00:00:00 2001 From: Jorge Leite Date: Tue, 10 May 2022 19:55:46 -0300 Subject: [PATCH] Chore: Convert email inbox feature to TypeScript (#25298) * chore: email-inbox rest types * Fix email inbox types * Email inbox endpoints to TS * Fix email-inbox params * Chore: Lib emailInbox to ts * chore: migrate to typescript * chore: fix lint * chore: fix table sort * Fix endpoint types * Chore: methods to insert and update was splitted * Removed the wrong validation * Back to default types for sort and query * Purge build files before compile * Require some fields of `IEmailInbox` * Fix weird destructuring Co-authored-by: albuquerquefabio Co-authored-by: Tasso Evangelista --- _templates/package/new/package.json.ejs.t | 2 +- apps/meteor/app/api/server/lib/emailInbox.js | 79 ----------- apps/meteor/app/api/server/lib/emailInbox.ts | 101 ++++++++++++++ .../v1/{email-inbox.js => email-inbox.ts} | 62 +++++---- ...WithData.js => EmailInboxEditWithData.tsx} | 12 +- .../views/admin/emailInbox/EmailInboxTable.js | 82 ----------- .../admin/emailInbox/EmailInboxTable.tsx | 128 ++++++++++++++++++ .../views/admin/emailInbox/SendTestButton.js | 27 ---- .../views/admin/emailInbox/SendTestButton.tsx | 34 +++++ .../emailInbox/{Skeleton.js => Skeleton.tsx} | 6 +- .../rocketchat-i18n/i18n/en.i18n.json | 5 +- packages/core-typings/package.json | 2 +- packages/rest-typings/package.json | 2 +- packages/rest-typings/src/index.ts | 2 + packages/rest-typings/src/v1/email-inbox.ts | 45 ++++++ packages/ui-contexts/package.json | 2 +- 16 files changed, 363 insertions(+), 228 deletions(-) delete mode 100644 apps/meteor/app/api/server/lib/emailInbox.js create mode 100644 apps/meteor/app/api/server/lib/emailInbox.ts rename apps/meteor/app/api/server/v1/{email-inbox.js => email-inbox.ts} (68%) rename apps/meteor/client/views/admin/emailInbox/{EmailInboxEditWithData.js => EmailInboxEditWithData.tsx} (71%) delete mode 100644 apps/meteor/client/views/admin/emailInbox/EmailInboxTable.js create mode 100644 apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx delete mode 100644 apps/meteor/client/views/admin/emailInbox/SendTestButton.js create mode 100644 apps/meteor/client/views/admin/emailInbox/SendTestButton.tsx rename apps/meteor/client/views/admin/emailInbox/{Skeleton.js => Skeleton.tsx} (63%) create mode 100644 packages/rest-typings/src/v1/email-inbox.ts diff --git a/_templates/package/new/package.json.ejs.t b/_templates/package/new/package.json.ejs.t index 3a6f8f9411b..51f678564c5 100644 --- a/_templates/package/new/package.json.ejs.t +++ b/_templates/package/new/package.json.ejs.t @@ -17,7 +17,7 @@ to: packages/<%= name %>/package.json "lint": "eslint --ext .js,.jsx,.ts,.tsx .", "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx . --fix", "jest": "jest", - "build": "tsc -p tsconfig.json" + "build": "rm -rf dist && tsc -p tsconfig.json" }, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/apps/meteor/app/api/server/lib/emailInbox.js b/apps/meteor/app/api/server/lib/emailInbox.js deleted file mode 100644 index a874598197e..00000000000 --- a/apps/meteor/app/api/server/lib/emailInbox.js +++ /dev/null @@ -1,79 +0,0 @@ -import { EmailInbox } from '../../../models/server/raw'; -import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -import { Users } from '../../../models'; - -export async function findEmailInboxes({ userId, query = {}, pagination: { offset, count, sort } }) { - if (!(await hasPermissionAsync(userId, 'manage-email-inbox'))) { - throw new Error('error-not-allowed'); - } - const cursor = EmailInbox.find(query, { - sort: sort || { name: 1 }, - skip: offset, - limit: count, - }); - - const total = await cursor.count(); - - const emailInboxes = await cursor.toArray(); - - return { - emailInboxes, - count: emailInboxes.length, - offset, - total, - }; -} - -export async function findOneEmailInbox({ userId, _id }) { - if (!(await hasPermissionAsync(userId, 'manage-email-inbox'))) { - throw new Error('error-not-allowed'); - } - return EmailInbox.findOneById(_id); -} - -export async function insertOneOrUpdateEmailInbox(userId, emailInboxParams) { - const { _id, active, name, email, description, senderInfo, department, smtp, imap } = emailInboxParams; - - if (!_id) { - emailInboxParams._createdAt = new Date(); - emailInboxParams._updatedAt = new Date(); - emailInboxParams._createdBy = Users.findOne(userId, { fields: { username: 1 } }); - return EmailInbox.insertOne(emailInboxParams); - } - - const emailInbox = await findOneEmailInbox({ userId, id: _id }); - - if (!emailInbox) { - throw new Error('error-invalid-email-inbox'); - } - - const updateEmailInbox = { - $set: { - active, - name, - email, - description, - senderInfo, - smtp, - imap, - _updatedAt: new Date(), - }, - }; - - if (department === 'All') { - updateEmailInbox.$unset = { - department: 1, - }; - } else { - updateEmailInbox.$set.department = department; - } - - return EmailInbox.updateOne({ _id }, updateEmailInbox); -} - -export async function findOneEmailInboxByEmail({ userId, email }) { - if (!(await hasPermissionAsync(userId, 'manage-email-inbox'))) { - throw new Error('error-not-allowed'); - } - return EmailInbox.findOne({ email }); -} diff --git a/apps/meteor/app/api/server/lib/emailInbox.ts b/apps/meteor/app/api/server/lib/emailInbox.ts new file mode 100644 index 00000000000..c679c3d714e --- /dev/null +++ b/apps/meteor/app/api/server/lib/emailInbox.ts @@ -0,0 +1,101 @@ +import { IEmailInbox } from '@rocket.chat/core-typings'; +import { InsertOneWriteOpResult, UpdateWriteOpResult, WithId } from 'mongodb'; + +import { EmailInbox } from '../../../models/server/raw'; +import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; +import { Users } from '../../../models/server'; + +export const findEmailInboxes = async ({ + userId, + query = {}, + pagination: { offset, count, sort }, +}: { + userId: string; + query?: {}; + pagination: { + offset: number; + count: number; + sort?: {}; + }; +}): Promise<{ + emailInboxes: IEmailInbox[]; + total: number; + count: number; + offset: number; +}> => { + if (!(await hasPermissionAsync(userId, 'manage-email-inbox'))) { + throw new Error('error-not-allowed'); + } + const cursor = EmailInbox.find(query, { + sort: sort || { name: 1 }, + skip: offset, + limit: count, + }); + + const total = await cursor.count(); + + const emailInboxes = await cursor.toArray(); + + return { + emailInboxes, + count: emailInboxes.length, + offset, + total, + }; +}; + +export const findOneEmailInbox = async ({ userId, _id }: { userId: string; _id: string }): Promise => { + if (!(await hasPermissionAsync(userId, 'manage-email-inbox'))) { + throw new Error('error-not-allowed'); + } + return EmailInbox.findOneById(_id); +}; +export const insertOneEmailInbox = async ( + userId: string, + emailInboxParams: Pick, +): Promise>> => { + const obj = { + ...emailInboxParams, + _createdAt: new Date(), + _updatedAt: new Date(), + _createdBy: Users.findOne(userId, { fields: { username: 1 } }), + }; + return EmailInbox.insertOne(obj); +}; + +export const updateEmailInbox = async ( + userId: string, + emailInboxParams: Pick, +): Promise> | UpdateWriteOpResult> => { + const { _id, active, name, email, description, senderInfo, department, smtp, imap } = emailInboxParams; + + const emailInbox = await findOneEmailInbox({ userId, _id }); + + if (!emailInbox) { + throw new Error('error-invalid-email-inbox'); + } + + const updateEmailInbox = { + $set: { + active, + name, + email, + description, + senderInfo, + smtp, + imap, + _updatedAt: new Date(), + ...(department !== 'All' && { department }), + }, + ...(department === 'All' && { $unset: { department: 1 as const } }), + }; + + return EmailInbox.updateOne({ _id }, updateEmailInbox); +}; + +export const findOneEmailInboxByEmail = async ({ userId, email }: { userId: string; email: string }): Promise => { + if (!(await hasPermissionAsync(userId, 'manage-email-inbox'))) { + throw new Error('error-not-allowed'); + } + return EmailInbox.findOne({ email }); +}; diff --git a/apps/meteor/app/api/server/v1/email-inbox.js b/apps/meteor/app/api/server/v1/email-inbox.ts similarity index 68% rename from apps/meteor/app/api/server/v1/email-inbox.js rename to apps/meteor/app/api/server/v1/email-inbox.ts index e1ad7560d40..1e6392a8aad 100644 --- a/apps/meteor/app/api/server/v1/email-inbox.js +++ b/apps/meteor/app/api/server/v1/email-inbox.ts @@ -1,7 +1,7 @@ import { check, Match } from 'meteor/check'; import { API } from '../api'; -import { findEmailInboxes, findOneEmailInbox, insertOneOrUpdateEmailInbox } from '../lib/emailInbox'; +import { insertOneEmailInbox, findEmailInboxes, findOneEmailInbox, updateEmailInbox } from '../lib/emailInbox'; import { hasPermission } from '../../../authorization/server/functions/hasPermission'; import { EmailInbox } from '../../../models/server/raw'; import Users from '../../../models/server/models/Users'; @@ -11,10 +11,10 @@ API.v1.addRoute( 'email-inbox.list', { authRequired: true }, { - get() { + async get() { const { offset, count } = this.getPaginationItems(); const { sort, query } = this.parseJsonQuery(); - const emailInboxes = Promise.await(findEmailInboxes({ userId: this.userId, query, pagination: { offset, count, sort } })); + const emailInboxes = await findEmailInboxes({ userId: this.userId, query, pagination: { offset, count, sort } }); return API.v1.success(emailInboxes); }, @@ -25,40 +25,45 @@ API.v1.addRoute( 'email-inbox', { authRequired: true }, { - post() { + async post() { if (!hasPermission(this.userId, 'manage-email-inbox')) { throw new Error('error-not-allowed'); } check(this.bodyParams, { _id: Match.Maybe(String), + active: Boolean, name: String, email: String, - active: Boolean, - description: Match.Maybe(String), - senderInfo: Match.Maybe(String), - department: Match.Maybe(String), + description: String, + senderInfo: String, + department: String, smtp: Match.ObjectIncluding({ - password: String, - port: Number, - secure: Boolean, server: String, + port: Number, username: String, - }), - imap: Match.ObjectIncluding({ password: String, - port: Number, secure: Boolean, + }), + imap: Match.ObjectIncluding({ server: String, + port: Number, username: String, + password: String, + secure: Boolean, }), }); const emailInboxParams = this.bodyParams; - const { _id } = emailInboxParams; - - Promise.await(insertOneOrUpdateEmailInbox(this.userId, emailInboxParams)); + let _id: string; + if (!emailInboxParams?._id) { + const emailInbox = await insertOneEmailInbox(this.userId, emailInboxParams); + _id = emailInbox.insertedId.toString(); + } else { + _id = emailInboxParams._id; + await updateEmailInbox(this.userId, { ...emailInboxParams, _id }); + } return API.v1.success({ _id }); }, }, @@ -68,7 +73,7 @@ API.v1.addRoute( 'email-inbox/:_id', { authRequired: true }, { - get() { + async get() { check(this.urlParams, { _id: String, }); @@ -77,11 +82,12 @@ API.v1.addRoute( if (!_id) { throw new Error('error-invalid-param'); } - const emailInboxes = Promise.await(findOneEmailInbox({ userId: this.userId, _id })); + // TODO: Chapter day backend - check if user has permission to view this email inbox instead of null values + const emailInboxes = await findOneEmailInbox({ userId: this.userId, _id }); return API.v1.success(emailInboxes); }, - delete() { + async delete() { if (!hasPermission(this.userId, 'manage-email-inbox')) { throw new Error('error-not-allowed'); } @@ -94,12 +100,12 @@ API.v1.addRoute( throw new Error('error-invalid-param'); } - const emailInboxes = Promise.await(EmailInbox.findOneById(_id)); + const emailInboxes = await EmailInbox.findOneById(_id); if (!emailInboxes) { return API.v1.notFound(); } - Promise.await(EmailInbox.removeById(_id)); + await EmailInbox.removeById(_id); return API.v1.success({ _id }); }, }, @@ -109,7 +115,7 @@ API.v1.addRoute( 'email-inbox.search', { authRequired: true }, { - get() { + async get() { if (!hasPermission(this.userId, 'manage-email-inbox')) { throw new Error('error-not-allowed'); } @@ -118,7 +124,9 @@ API.v1.addRoute( }); const { email } = this.queryParams; - const emailInbox = Promise.await(EmailInbox.findOne({ email })); + + // TODO: Chapter day backend - check if user has permission to view this email inbox instead of null values + const emailInbox = await EmailInbox.findOne({ email }); return API.v1.success({ emailInbox }); }, @@ -129,7 +137,7 @@ API.v1.addRoute( 'email-inbox.send-test/:_id', { authRequired: true }, { - post() { + async post() { if (!hasPermission(this.userId, 'manage-email-inbox')) { throw new Error('error-not-allowed'); } @@ -141,7 +149,7 @@ API.v1.addRoute( if (!_id) { throw new Error('error-invalid-param'); } - const emailInbox = Promise.await(findOneEmailInbox({ userId: this.userId, _id })); + const emailInbox = await findOneEmailInbox({ userId: this.userId, _id }); if (!emailInbox) { return API.v1.notFound(); @@ -149,7 +157,7 @@ API.v1.addRoute( const user = Users.findOneById(this.userId); - Promise.await(sendTestEmailToInbox(emailInbox, user)); + await sendTestEmailToInbox(emailInbox, user); return API.v1.success({ _id }); }, diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxEditWithData.js b/apps/meteor/client/views/admin/emailInbox/EmailInboxEditWithData.tsx similarity index 71% rename from apps/meteor/client/views/admin/emailInbox/EmailInboxEditWithData.js rename to apps/meteor/client/views/admin/emailInbox/EmailInboxEditWithData.tsx index 2c5ccd6523d..3dd4484224e 100644 --- a/apps/meteor/client/views/admin/emailInbox/EmailInboxEditWithData.js +++ b/apps/meteor/client/views/admin/emailInbox/EmailInboxEditWithData.tsx @@ -1,13 +1,17 @@ import { Box } from '@rocket.chat/fuselage'; import { useTranslation } from '@rocket.chat/ui-contexts'; -import React from 'react'; +import React, { ReactElement } from 'react'; import { AsyncStatePhase } from '../../../hooks/useAsyncState'; import { useEndpointData } from '../../../hooks/useEndpointData'; import EmailInboxForm from './EmailInboxForm'; import { FormSkeleton } from './Skeleton'; -function EmailInboxEditWithData({ id }) { +type EmailInboxEditWithDataProps = { + id: string; +}; + +const EmailInboxEditWithData = ({ id }: EmailInboxEditWithDataProps): ReactElement => { const t = useTranslation(); const { value: data, error, phase: state } = useEndpointData(`email-inbox/${id}`); @@ -16,10 +20,10 @@ function EmailInboxEditWithData({ id }) { } if (error || !data) { - return {t('EmailInbox_not_found')}; + return {t('error-email-inbox-not-found')}; } return ; -} +}; export default EmailInboxEditWithData; diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.js b/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.js deleted file mode 100644 index c531624c7e5..00000000000 --- a/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.js +++ /dev/null @@ -1,82 +0,0 @@ -import { Table } from '@rocket.chat/fuselage'; -import { useDebouncedValue } from '@rocket.chat/fuselage-hooks'; -import { useRoute, useTranslation } from '@rocket.chat/ui-contexts'; -import React, { useMemo, useCallback, useState } from 'react'; - -import GenericTable from '../../../components/GenericTable'; -import { useEndpointData } from '../../../hooks/useEndpointData'; -import SendTestButton from './SendTestButton'; - -const useQuery = ({ itemsPerPage, current }, [column, direction]) => - useMemo( - () => ({ - sort: JSON.stringify({ [column]: direction === 'asc' ? 1 : -1 }), - ...(itemsPerPage && { count: itemsPerPage }), - ...(current && { offset: current }), - }), - [column, current, direction, itemsPerPage], - ); - -function EmailInboxTable() { - const t = useTranslation(); - - const [params, setParams] = useState({ current: 0, itemsPerPage: 25 }); - const [sort] = useState(['name', 'asc']); - const debouncedParams = useDebouncedValue(params, 500); - const debouncedSort = useDebouncedValue(sort, 500); - const query = useQuery(debouncedParams, debouncedSort); - const router = useRoute('admin-email-inboxes'); - - const onClick = useCallback( - (_id) => () => - router.push({ - context: 'edit', - _id, - }), - [router], - ); - - const header = useMemo( - () => - [ - - {t('Name')} - , - - {t('Email')} - , - - {t('Active')} - , - , - ].filter(Boolean), - [sort, t], - ); - - const { value: data } = useEndpointData('email-inbox.list', query); - - const renderRow = useCallback( - ({ _id, name, email, active }) => ( - - {name} - {email} - {active ? t('Yes') : t('No')} - - - ), - [onClick, t], - ); - - return ( - - ); -} - -export default EmailInboxTable; diff --git a/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx b/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx new file mode 100644 index 00000000000..499249a054c --- /dev/null +++ b/apps/meteor/client/views/admin/emailInbox/EmailInboxTable.tsx @@ -0,0 +1,128 @@ +import { Box, Pagination } from '@rocket.chat/fuselage'; +import { useRoute, useTranslation } from '@rocket.chat/ui-contexts'; +import React, { useMemo, useCallback, ReactElement } from 'react'; + +import { + GenericTable, + GenericTableBody, + GenericTableCell, + GenericTableHeader, + GenericTableHeaderCell, + GenericTableLoadingTable, + GenericTableRow, +} from '../../../components/GenericTable'; +import { usePagination } from '../../../components/GenericTable/hooks/usePagination'; +import { useSort } from '../../../components/GenericTable/hooks/useSort'; +import { useEndpointData } from '../../../hooks/useEndpointData'; +import { AsyncStatePhase } from '../../../lib/asyncState/AsyncStatePhase'; +import SendTestButton from './SendTestButton'; + +const useQuery = ( + { + itemsPerPage, + current, + }: { + itemsPerPage: number; + current: number; + }, + [column, direction]: string[], +): { + offset?: number; + count?: number; + sort: string; +} => + useMemo( + () => ({ + sort: JSON.stringify({ [column]: direction === 'asc' ? 1 : -1 }), + ...(itemsPerPage && { count: itemsPerPage }), + ...(current && { offset: current }), + }), + [column, current, direction, itemsPerPage], + ); + +const EmailInboxTable = (): ReactElement => { + const t = useTranslation(); + + const { current, itemsPerPage, setItemsPerPage: onSetItemsPerPage, setCurrent: onSetCurrent, ...paginationProps } = usePagination(); + const { sortBy, sortDirection, setSort } = useSort<'name'>('name'); + const query = useQuery({ itemsPerPage, current }, [sortBy, sortDirection]); + + const router = useRoute('admin-email-inboxes'); + + const onClick = useCallback( + (_id) => (): void => { + router.push({ + context: 'edit', + _id, + }); + }, + [router], + ); + + const { phase, value: { emailInboxes = [], count = 0 } = {} } = useEndpointData('email-inbox.list', query); + + return ( + <> + + + + {t('Name')} + + + {t('Email')} + + + {t('Active')} + + + + + {phase === AsyncStatePhase.LOADING && } + {phase === AsyncStatePhase.RESOLVED && + count > 0 && + emailInboxes.map((emailInbox) => ( + + + {emailInbox.name} + + + {emailInbox.email} + + + {emailInbox.active ? t('Yes') : t('No')} + + + + ))} + + + {phase === AsyncStatePhase.RESOLVED && ( + + )} + + ); +}; + +export default EmailInboxTable; diff --git a/apps/meteor/client/views/admin/emailInbox/SendTestButton.js b/apps/meteor/client/views/admin/emailInbox/SendTestButton.js deleted file mode 100644 index 75164019f06..00000000000 --- a/apps/meteor/client/views/admin/emailInbox/SendTestButton.js +++ /dev/null @@ -1,27 +0,0 @@ -import { Button, Table, Icon } from '@rocket.chat/fuselage'; -import { useToastMessageDispatch, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; -import React from 'react'; - -function SendTestButton({ id }) { - const t = useTranslation(); - - const dispatchToastMessage = useToastMessageDispatch(); - const sendTest = useEndpoint('POST', `email-inbox.send-test/${id}`); - - return ( - - - - ); -} - -export default SendTestButton; diff --git a/apps/meteor/client/views/admin/emailInbox/SendTestButton.tsx b/apps/meteor/client/views/admin/emailInbox/SendTestButton.tsx new file mode 100644 index 00000000000..d1d2937459c --- /dev/null +++ b/apps/meteor/client/views/admin/emailInbox/SendTestButton.tsx @@ -0,0 +1,34 @@ +import { Button, Icon, TableCell } from '@rocket.chat/fuselage'; +import { useToastMessageDispatch, useEndpoint, useTranslation } from '@rocket.chat/ui-contexts'; +import React, { ReactElement } from 'react'; + +type SendTestButtonProps = { + id: string; +}; + +const SendTestButton = ({ id }: SendTestButtonProps): ReactElement => { + const t = useTranslation(); + + const dispatchToastMessage = useToastMessageDispatch(); + const sendTest = useEndpoint('POST', `email-inbox.send-test/${id}`); + + const handleOnClick = (e: React.MouseEvent): void => { + e.preventDefault(); + e.stopPropagation(); + sendTest(); + dispatchToastMessage({ + type: 'success', + message: t('Email_sent'), + }); + }; + + return ( + + + + ); +}; + +export default SendTestButton; diff --git a/apps/meteor/client/views/admin/emailInbox/Skeleton.js b/apps/meteor/client/views/admin/emailInbox/Skeleton.tsx similarity index 63% rename from apps/meteor/client/views/admin/emailInbox/Skeleton.js rename to apps/meteor/client/views/admin/emailInbox/Skeleton.tsx index 5056e7c52cb..8532fe8b0f6 100644 --- a/apps/meteor/client/views/admin/emailInbox/Skeleton.js +++ b/apps/meteor/client/views/admin/emailInbox/Skeleton.tsx @@ -1,8 +1,8 @@ import { Box, Skeleton } from '@rocket.chat/fuselage'; -import React from 'react'; +import React, { ReactElement } from 'react'; -export const FormSkeleton = (props) => ( - +export const FormSkeleton = (): ReactElement => ( + diff --git a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json index c03b9376957..62593f02bf6 100644 --- a/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/apps/meteor/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1747,6 +1747,7 @@ "error-invalid-email": "Invalid email __email__", "error-invalid-email-address": "Invalid email address", "error-invalid-email-inbox": "Invalid Email Inbox", + "error-email-inbox-not-found": "Email Inbox not found", "error-invalid-file-height": "Invalid file height", "error-invalid-file-type": "Invalid file type", "error-invalid-file-width": "Invalid file width", @@ -3360,8 +3361,8 @@ "OTR": "OTR", "OTR_Chat_Declined_Title": "OTR Chat invite Declined", "OTR_Chat_Declined_Description": "%s declined OTR chat invite. For privacy protection local cache was deleted, including all related system messages.", - "OTR_Chat_Error_Title":"Chat ended due to failed key refresh", - "OTR_Chat_Error_Description":"For privacy protection local cache was deleted, including all related system messages.", + "OTR_Chat_Error_Title": "Chat ended due to failed key refresh", + "OTR_Chat_Error_Description": "For privacy protection local cache was deleted, including all related system messages.", "OTR_Chat_Timeout_Title": "OTR chat invite expired", "OTR_Chat_Timeout_Description": "%s failed to accept OTR chat invite in time. For privacy protection local cache was deleted, including all related system messages.", "OTR_Enable_Description": "Enable option to use off-the-record (OTR) messages in direct messages between 2 users. OTR messages are not recorded on the server and exchanged directly and encrypted between the 2 users.", diff --git a/packages/core-typings/package.json b/packages/core-typings/package.json index d077c2c9ed9..839bbad9e6d 100644 --- a/packages/core-typings/package.json +++ b/packages/core-typings/package.json @@ -17,7 +17,7 @@ "lint": "eslint --ext .js,.jsx,.ts,.tsx .", "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx . --fix", "test": "echo \"Error: no test specified\" && exit 1", - "build": "tsc -p tsconfig.json" + "build": "rm -rf dist && tsc -p tsconfig.json" }, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/rest-typings/package.json b/packages/rest-typings/package.json index 65869a5d16f..f45b551a7d2 100644 --- a/packages/rest-typings/package.json +++ b/packages/rest-typings/package.json @@ -19,7 +19,7 @@ "lint": "eslint --ext .js,.jsx,.ts,.tsx .", "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx . --fix", "jest": "jest", - "build": "tsc -p tsconfig.json" + "build": "rm -rf dist && tsc -p tsconfig.json" }, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/rest-typings/src/index.ts b/packages/rest-typings/src/index.ts index ebc65c15a3c..9d1f61c2283 100644 --- a/packages/rest-typings/src/index.ts +++ b/packages/rest-typings/src/index.ts @@ -31,6 +31,7 @@ import type { TeamsEndpoints } from './v1/teams'; import type { UsersEndpoints } from './v1/users'; import type { VideoConferenceEndpoints } from './v1/videoConference'; import type { VoipEndpoints } from './v1/voip'; +import type { EmailInboxEndpoints } from './v1/email-inbox'; import type { WebdavEndpoints } from './v1/webdav'; import type { OAuthAppsEndpoint } from './v1/oauthapps'; @@ -65,6 +66,7 @@ export interface Endpoints InvitesEndpoints, E2eEndpoints, CustomSoundEndpoint, + EmailInboxEndpoints, WebdavEndpoints, OAuthAppsEndpoint {} diff --git a/packages/rest-typings/src/v1/email-inbox.ts b/packages/rest-typings/src/v1/email-inbox.ts new file mode 100644 index 00000000000..afa4745ed86 --- /dev/null +++ b/packages/rest-typings/src/v1/email-inbox.ts @@ -0,0 +1,45 @@ +import type { IEmailInbox } from '@rocket.chat/core-typings'; + +import type { PaginatedRequest } from '../helpers/PaginatedRequest'; +import type { PaginatedResult } from '../helpers/PaginatedResult'; + +export type EmailInboxEndpoints = { + 'email-inbox.list': { + GET: (params: PaginatedRequest<{ query?: string }>) => PaginatedResult<{ emailInboxes: IEmailInbox[] }>; + }; + 'email-inbox': { + POST: (params: { + _id?: string; + name: string; + email: string; + active: boolean; + description: string; + senderInfo: string; + department: string; + smtp: { + password: string; + port: number; + secure: boolean; + server: string; + username: string; + }; + imap: { + password: string; + port: number; + secure: boolean; + server: string; + username: string; + }; + }) => { _id: string }; + }; + 'email-inbox/:_id': { + GET: (params: void) => IEmailInbox | null; + DELETE: (params: void) => { _id: string }; + }; + 'email-inbox.search': { + GET: (params: { email: string }) => { emailInbox: IEmailInbox | null }; + }; + 'email-inbox.send-test/:_id': { + POST: (params: void) => { _id: string }; + }; +}; diff --git a/packages/ui-contexts/package.json b/packages/ui-contexts/package.json index 9b868b20bf0..42a0017b89a 100644 --- a/packages/ui-contexts/package.json +++ b/packages/ui-contexts/package.json @@ -30,7 +30,7 @@ "lint": "eslint --ext .js,.jsx,.ts,.tsx .", "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx . --fix", "jest": "jest", - "build": "tsc -p tsconfig.json" + "build": "rm -rf dist && tsc -p tsconfig.json" }, "main": "./dist/index.js", "typings": "./dist/index.d.ts",