From b3e0687fbada07564f80ea976b638b1ba1a113e0 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 27 Mar 2020 01:51:13 -0300 Subject: [PATCH 01/26] directory page using react --- app/api/server/v1/misc.js | 1 + app/ui/client/index.js | 1 - .../app/components/Directory/ChannelsTab.js | 83 ++ .../components/Directory/Directory.stories.js | 19 + .../components/Directory/DirectoryTable.js | 114 ++ .../views/app/components/Directory/UserTab.js | 87 ++ .../views/app/components/Directory/index.js | 49 + app/ui/client/views/app/components/hooks.js | 67 + app/ui/client/views/app/directory.html | 173 --- app/ui/client/views/app/directory.js | 280 ---- client/components/basic/Page.js | 2 +- client/routes.js | 16 +- client/startup/startup.js | 2 + .../client/components/Section.js | 2 +- package-lock.json | 1164 ++++++++++++++--- package.json | 1 + packages/rocketchat-i18n/i18n/en.i18n.json | 1 + server/methods/browseChannels.js | 1 + 18 files changed, 1452 insertions(+), 611 deletions(-) create mode 100644 app/ui/client/views/app/components/Directory/ChannelsTab.js create mode 100644 app/ui/client/views/app/components/Directory/Directory.stories.js create mode 100644 app/ui/client/views/app/components/Directory/DirectoryTable.js create mode 100644 app/ui/client/views/app/components/Directory/UserTab.js create mode 100644 app/ui/client/views/app/components/Directory/index.js create mode 100644 app/ui/client/views/app/components/hooks.js delete mode 100644 app/ui/client/views/app/directory.html delete mode 100644 app/ui/client/views/app/directory.js diff --git a/app/api/server/v1/misc.js b/app/api/server/v1/misc.js index 033bc3b9b055..4caefb489221 100644 --- a/app/api/server/v1/misc.js +++ b/app/api/server/v1/misc.js @@ -179,6 +179,7 @@ API.v1.addRoute('directory', { authRequired: true }, { const { sort, query } = this.parseJsonQuery(); const { text, type, workspace = 'local' } = query; + if (sort && Object.keys(sort).length > 1) { return API.v1.failure('This method support only one "sort" parameter'); } diff --git a/app/ui/client/index.js b/app/ui/client/index.js index f44ba3083e41..4867309779f8 100644 --- a/app/ui/client/index.js +++ b/app/ui/client/index.js @@ -37,7 +37,6 @@ import './views/app/CreateDirectMessage'; import './views/app/editStatus'; import './views/app/fullModal'; import './views/app/home'; -import './views/app/directory'; import './views/app/roomSearch'; import './views/app/secretURL'; import './views/app/invite'; diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js new file mode 100644 index 000000000000..b410c75e007c --- /dev/null +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -0,0 +1,83 @@ +import React, { useMemo, useState, useCallback } from 'react'; +import { Box, Margins, Table, Flex, Avatar, Tag } from '@rocket.chat/fuselage'; + +import { useEndpointData } from '../../../../../../../ee/app/engagement-dashboard/client/hooks/useEndpointData'; +import { DirectoryTable, Th } from './DirectoryTable'; +import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; +import { useRoute } from '../../../../../../../client/contexts/RouterContext'; +import { useQuery, useFormatDate } from '../hooks'; + +export function ChannelsTab() { + const t = useTranslation(); + const [sort, setSort] = useState(['name', 'asc']); + const [params, setParams] = useState({}); + + const query = useQuery(params, sort, 'channels'); + + const onHeaderClick = useCallback((id) => { + const [sortBy, sortDirection] = sort; + + if (sortBy === id) { + setSort([id, sortDirection === 'asc' ? 'desc' : 'asc']); + return; + } + setSort([id, 'asc']); + }, [sort]); + + const header = [ + {t('Name')}, + {t('Users')}, + {t('Created_at')}, + {t('Last_Message')}, + {t('Topic')}, + ]; + + const go = useRoute('channel'); + + const data = useEndpointData('GET', 'directory', query) || {}; + + const onClick = useMemo(() => (name) => (e) => { + if (e.type === 'click' || e.key === 'Enter') { + go({ name }); + } + }, []); + + const formatDate = useFormatDate(); + const renderRow = useCallback(({ _id, ts, default: d, name, description, usersCount, lastMessage, topic, ...rest }) => + + {console.log(rest)} + + + + + + + + + + + {name} {d && {t('default')}} + {description && {description} } + + + + + + + + {usersCount} + + + {formatDate(ts)} + + + {lastMessage && formatDate(lastMessage.ts)} + + + {topic} + + + , []); + + return ; +} diff --git a/app/ui/client/views/app/components/Directory/Directory.stories.js b/app/ui/client/views/app/components/Directory/Directory.stories.js new file mode 100644 index 000000000000..13f1cef83ed0 --- /dev/null +++ b/app/ui/client/views/app/components/Directory/Directory.stories.js @@ -0,0 +1,19 @@ +import React from 'react'; + +import { DirectoryTable, Th } from './DirectoryTable'; + +export default { + title: 'directory/table', + component: DirectoryTable, + decorators: [(fn) =>
], +}; + +export const _default = () => { + const header = [ + Name, + Email, + Data, + Info, + ]; + return ; +}; diff --git a/app/ui/client/views/app/components/Directory/DirectoryTable.js b/app/ui/client/views/app/components/Directory/DirectoryTable.js new file mode 100644 index 000000000000..f96f023c0cbf --- /dev/null +++ b/app/ui/client/views/app/components/Directory/DirectoryTable.js @@ -0,0 +1,114 @@ +import React, { useMemo, useState, useEffect } from 'react'; +import { Box, Icon, Margins, Pagination, Skeleton, Table, Flex, Avatar, TextInput, Tile } from '@rocket.chat/fuselage'; + +import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; +import { useDebounce } from '../hooks'; + +function SortIcon({ direction }) { + return + + + ; +} + +export function Th({ children, active, direction, sort, onClick, ...props }) { + const fn = useMemo(() => () => onClick && onClick(sort), [sort, onClick]); + return + + {children}{sort && } + + ; +} + +const LoadingRow = ({ cols }) => + + + + + + + + + + + + + + + + + + + + { Array.from({ length: cols - 1 }, (_, i) => + + )} +; + +export function DirectoryTable({ + data = {}, + renderRow, + header, + searchPlaceholder = 'placeholder', + setParams = () => { }, +}) { + const t = useTranslation(); + + const [text, setText] = useState(''); + + const [itemsPerPage, setItemsPerPage] = useState(25); + + const [current, setCurrent] = useState(0); + + const term = useDebounce(text, 500); + + useEffect(() => { + setParams({ term, current, itemsPerPage }); + }, [term, current, itemsPerPage]); + + const { result: channels, total } = data; + + + const handleChange = useMemo(() => (event) => setText(event.currentTarget.value), []); + + const Loading = useMemo(() => () => Array.from({ length: 10 }, (_, i) => ), [header && header.length]); + + const showingResultsLabel = useMemo(() => ({ count, current, itemsPerPage }) => t('Showing results %s - %s of %s', current + 1, Math.min(current + itemsPerPage, count), count), []); + + return <> + + + + } onChange={handleChange} value={text} /> + + {channels && !channels.length + ? + {t('No_data_found')} + + : + + { header && + + {header} + + } + + {channels + ? channels.map(renderRow) + : } + +
+ t('Items_per_page:')} + showingResultsLabel={showingResultsLabel} + count={total || 0} + onSetItemsPerPage={setItemsPerPage} + onSetCurrent={setCurrent} + /> +
} +
+
+ ; +} diff --git a/app/ui/client/views/app/components/Directory/UserTab.js b/app/ui/client/views/app/components/Directory/UserTab.js new file mode 100644 index 000000000000..f05f99af21fe --- /dev/null +++ b/app/ui/client/views/app/components/Directory/UserTab.js @@ -0,0 +1,87 @@ +import React, { useMemo, useState, useCallback } from 'react'; +import { Box, Margins, Table, Flex, Avatar } from '@rocket.chat/fuselage'; + + +import { useEndpointData } from '../../../../../../../ee/app/engagement-dashboard/client/hooks/useEndpointData'; +import { DirectoryTable, Th } from './DirectoryTable'; +import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; +import { useRoute } from '../../../../../../../client/contexts/RouterContext'; +import { usePermission } from '../../../../../../../client/contexts/AuthorizationContext'; +import { useQuery, useFormatDate } from '../hooks'; + +export function UserTab({ + workspace = 'local', +}) { + const [params, setParams] = useState({}); + const [sort, setSort] = useState(['name', 'asc']); + const canViewFullOtherUserInfo = usePermission('view-full-other-user-info'); + const t = useTranslation(); + + const federation = workspace === 'external'; + + const query = useQuery(params, sort, 'users', workspace); + + const onHeaderClick = (id) => { + const [sortBy, sortDirection] = sort; + + if (sortBy === id) { + setSort([id, sortDirection === 'asc' ? 'desc' : 'asc']); + return; + } + setSort([id, 'asc']); + }; + + const header = [ + {t('Name')}, + canViewFullOtherUserInfo && {t('Email')}, + federation && {t('Domain')}, + {t('Joined_at')}, + ].filter(Boolean); + + const go = useRoute('direct'); + + const data = useEndpointData('GET', 'directory', query) || {}; + + const onClick = useMemo(() => (username) => (e) => { + if (e.type === 'click' || e.key === 'Enter') { + go({ rid: username }); + } + }, []); + + const formatDate = useFormatDate(); + + const renderRow = useCallback(({ createdAt, emails, _id, username, name, domain }) => + + + + + + + + + + + + {name || username} + {name && username} + + + + + + + {canViewFullOtherUserInfo + && + {emails && emails[0].address} + } + {federation + && + {domain} + } + + {formatDate(createdAt)} + + , []); + + return ; +} diff --git a/app/ui/client/views/app/components/Directory/index.js b/app/ui/client/views/app/components/Directory/index.js new file mode 100644 index 000000000000..2ac75e385004 --- /dev/null +++ b/app/ui/client/views/app/components/Directory/index.js @@ -0,0 +1,49 @@ +import React, { useMemo, useEffect } from 'react'; +import { Box, Margins, Tabs } from '@rocket.chat/fuselage'; + +import { Page } from '../../../../../../../client/components/basic/Page'; +import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; +import { UserTab } from './UserTab'; +import { ChannelsTab } from './ChannelsTab'; +import { useRoute, useRouteParameter } from '../../../../../../../client/contexts/RouterContext'; +import { useSetting } from '../../../../../../../client/contexts/SettingsContext'; + +export function DirectoryPage() { + const t = useTranslation(); + + const federationEnabled = useSetting('FEDERATION_Enabled'); + + const tab = useRouteParameter('tab'); + + const goToDirectory = useRoute('directory'); + const handleTabClick = useMemo(() => (tab) => () => goToDirectory({ tab }), [tab]); + + useEffect(() => { + if (!tab || (tab === 'external' && !federationEnabled)) { + return goToDirectory.replacingState({ tab: 'channels' }); + } + }, [tab, federationEnabled]); + + return + + + + {t('Channels')} + {t('Users')} + { federationEnabled && {t('External_Users')} } + + + + { + (tab === 'users' && ) + || (tab === 'channels' && ) + || (federationEnabled && tab === 'external' && ) + } + + + + ; +} + + +DirectoryPage.name = 'DirectoryPage'; diff --git a/app/ui/client/views/app/components/hooks.js b/app/ui/client/views/app/components/hooks.js new file mode 100644 index 000000000000..a684477b26a9 --- /dev/null +++ b/app/ui/client/views/app/components/hooks.js @@ -0,0 +1,67 @@ +import { useState, useEffect, useMemo, useCallback } from 'react'; +import moment from 'moment'; + +import { useUserPreference } from '../../../../../../client/contexts/UserContext'; +import { useSetting } from '../../../../../../client/contexts/SettingsContext'; + +export function useDebounce(value, delay) { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const handler = setTimeout(() => { + setDebouncedValue(value); + }, delay); + return () => clearTimeout(handler); + }, [value]); + + return debouncedValue; +} + +export function useQuery(params, sort, type, workspace = 'local') { + return useMemo(() => ({ + query: JSON.stringify({ + type, + text: params.term, + workspace, + }), + sort: JSON.stringify({ [sort[0]]: sort[1] === 'asc' ? 1 : 0 }), + ...params.itemsPerPage && { count: params.itemsPerPage }, + ...params.current && { offset: params.current }, + }), [params, sort, type, workspace]); +} + +const dayFormat = ['h:mm A', 'H:mm']; +export function useFormatTime() { + const clockMode = useUserPreference('clockMode', false); + const sameDay = dayFormat[clockMode - 1] || useSetting('Message_TimeFormat'); + const format = useSetting('Message_TimeFormat'); + return useCallback((time) => { + switch (clockMode) { + case 1: + case 2: + return moment(time).format(sameDay); + default: + return moment(time).format(format); + } + }, [clockMode, format]); +} + +export function useFormatDateAndTime() { + const clockMode = useUserPreference('clockMode', false); + const format = useSetting('Message_TimeAndDateFormat'); + return useCallback((time) => { + switch (clockMode) { + case 1: + return moment(time).format('MMMM D, Y h:mm A'); + case 2: + return moment(time).format('MMMM D, Y H:mm'); + default: + return moment(time).format(format); + } + }, [clockMode, format]); +} + +export function useFormatDate() { + const format = useSetting('Message_DateFormat'); + return useCallback((time) => moment(time).format(format), [format]); +} diff --git a/app/ui/client/views/app/directory.html b/app/ui/client/views/app/directory.html deleted file mode 100644 index a9c729f6b159..000000000000 --- a/app/ui/client/views/app/directory.html +++ /dev/null @@ -1,173 +0,0 @@ - diff --git a/app/ui/client/views/app/directory.js b/app/ui/client/views/app/directory.js deleted file mode 100644 index af0a22ff6822..000000000000 --- a/app/ui/client/views/app/directory.js +++ /dev/null @@ -1,280 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { ReactiveVar } from 'meteor/reactive-var'; -import { Template } from 'meteor/templating'; -import _ from 'underscore'; - -import { timeAgo } from './helpers'; -import { hasAllPermission } from '../../../../authorization/client'; -import { t, roomTypes } from '../../../../utils'; -import { settings } from '../../../../settings'; -import { hasAtLeastOnePermission } from '../../../../authorization'; -import './directory.html'; -import './directory.css'; - -function directorySearch(config, cb) { - return Meteor.call('browseChannels', config, (err, result) => { - cb(result && result.results && result.results.length && result.results.map((result) => { - if (config.type === 'channels') { - return { - name: result.name, - users: result.usersCount || 0, - createdAt: timeAgo(result.ts, t), - lastMessage: result.lastMessage && timeAgo(result.lastMessage.ts, t), - description: result.description, - archived: result.archived, - topic: result.topic, - }; - } - - if (config.type === 'users') { - return { - name: result.name, - username: result.username, - // If there is no email address (rocket.cat and app users) show the username) - email: (result.emails && result.emails[0] && result.emails[0].address) || result.username, - createdAt: timeAgo(result.createdAt, t), - origin: result.federation && result.federation.origin, - isRemote: result.isRemote, - }; - } - return null; - })); - }); -} - -Template.directory.helpers({ - federationEnabled() { - return settings.get('FEDERATION_Enabled'); - }, - searchText() { - return Template.instance().searchText.get(); - }, - searchWorkspace() { - return Template.instance().searchWorkspace.get(); - }, - showLastMessage() { - return settings.get('Store_Last_Message'); - }, - searchResults() { - return Template.instance().results.get(); - }, - searchType() { - return Template.instance().searchType.get(); - }, - sortIcon(key) { - const { sortDirection, searchSortBy } = Template.instance(); - - return key === searchSortBy.get() && sortDirection.get() === 'asc' - ? 'sort-up' - : 'sort-down'; - }, - searchSortBy(key) { - return Template.instance().searchSortBy.get() === key; - }, - createChannelOrGroup() { - return hasAtLeastOnePermission(['create-c', 'create-p']); - }, - tabsData() { - const { - sortDirection, - searchType, - searchSortBy, - results, - end, - page, - } = Template.instance(); - const channelsTab = { - label: t('Channels'), - value: 'channels', - condition() { - return true; - }, - }; - const usersTab = { - label: t('Users'), - value: 'users', - condition() { - return true; - }, - }; - if (searchType.get() === 'channels') { - channelsTab.active = true; - } else { - usersTab.active = true; - } - return { - tabs: [channelsTab, usersTab], - onChange(value) { - results.set([]); - end.set(false); - if (value === 'channels') { - searchSortBy.set('usersCount'); - sortDirection.set('desc'); - } else { - searchSortBy.set('name'); - sortDirection.set('asc'); - } - page.set(0); - searchType.set(value); - }, - }; - }, - onTableItemClick() { - const instance = Template.instance(); - - const { searchType } = instance; - - let type; - let routeConfig; - - return function(item) { - if (searchType.get() === 'channels') { - type = 'c'; - routeConfig = { name: item.name }; - } else { - type = 'd'; - routeConfig = { name: item.username }; - } - roomTypes.openRouteLink(type, routeConfig); - }; - }, - isLoading() { - return Template.instance().isLoading.get(); - }, - onTableScroll() { - const instance = Template.instance(); - if (instance.isLoading.get() || instance.end.get()) { - return; - } - return function(currentTarget) { - if ( - currentTarget.offsetHeight + currentTarget.scrollTop - >= currentTarget.scrollHeight - 100 - ) { - return instance.page.set(instance.page.get() + 1); - } - }; - }, - onTableResize() { - const { limit } = Template.instance(); - - return function() { - limit.set(Math.ceil(this.$('.table-scroll').height() / 40 + 5)); - }; - }, - onTableSort() { - const { end, page, sortDirection, searchSortBy } = Template.instance(); - - return function(type) { - end.set(false); - page.set(0); - - if (searchSortBy.get() === type) { - sortDirection.set(sortDirection.get() === 'asc' ? 'desc' : 'asc'); - return; - } - - searchSortBy.set(type); - sortDirection.set('asc'); - }; - }, - canViewOtherUserInfo() { - const { canViewOtherUserInfo } = Template.instance(); - - return canViewOtherUserInfo.get(); - }, - sumColumnCount(...args) { - return args - .slice(0, -1) - .map((value) => (typeof value === 'number' ? value : Number(!!value))) - .reduce((sum, value) => sum + value, 0); - }, -}); - -Template.directory.events({ - 'submit .js-search-form'(e) { - e.preventDefault(); - e.stopPropagation(); - }, - 'input .js-search': _.debounce((e, t) => { - t.end.set(false); - t.sortDirection.set('asc'); - t.page.set(0); - t.searchText.set(e.currentTarget.value); - }, 300), - 'change .js-workspace': (e, t) => { - t.end.set(false); - t.sortDirection.set('asc'); - t.page.set(0); - t.searchWorkspace.set(e.target.value); - }, -}); - -Template.directory.onRendered(function() { - this.$('input').focus(); - function setResults(result) { - if (!Array.isArray(result)) { - result = []; - } - - if (this.page.get() > 0) { - return this.results.set([...this.results.get(), ...result]); - } - - return this.results.set(result); - } - - this.autorun(() => { - const searchConfig = { - text: this.searchText.get(), - workspace: this.searchWorkspace.get(), - type: this.searchType.get(), - sortBy: this.searchSortBy.get(), - sortDirection: this.sortDirection.get(), - limit: this.limit.get(), - page: this.page.get(), - }; - - if (this.end.get() || this.loading) { - return; - } - - this.loading = true; - this.isLoading.set(true); - - directorySearch(searchConfig, (result) => { - this.loading = false; - this.isLoading.set(false); - this.end.set(!result); - - setResults.call(this, result); - }); - }); -}); - -Template.directory.onCreated(function() { - const viewType = settings.get('Accounts_Directory_DefaultView') || 'channels'; - this.searchType = new ReactiveVar(viewType); - if (viewType === 'channels') { - this.searchSortBy = new ReactiveVar('usersCount'); - this.sortDirection = new ReactiveVar('desc'); - } else { - this.searchSortBy = new ReactiveVar('name'); - this.sortDirection = new ReactiveVar('asc'); - } - this.searchText = new ReactiveVar(''); - this.searchWorkspace = new ReactiveVar('local'); - this.limit = new ReactiveVar(0); - this.page = new ReactiveVar(0); - this.end = new ReactiveVar(false); - - this.results = new ReactiveVar([]); - - this.isLoading = new ReactiveVar(false); - - this.canViewOtherUserInfo = new ReactiveVar(false); - - this.autorun(() => { - this.canViewOtherUserInfo.set(hasAllPermission('view-full-other-user-info')); - }); -}); diff --git a/client/components/basic/Page.js b/client/components/basic/Page.js index 37b39c81edec..e89ffbd19d34 100644 --- a/client/components/basic/Page.js +++ b/client/components/basic/Page.js @@ -16,7 +16,7 @@ export function Page(props) { export function PageHeader({ children, title, ...props }) { const [border] = useContext(PageContext); return - + diff --git a/client/routes.js b/client/routes.js index ce613e76b182..161daf76413c 100644 --- a/client/routes.js +++ b/client/routes.js @@ -39,6 +39,8 @@ const createTemplateForComponent = async ( props = {}, // eslint-disable-next-line new-cap renderContainerView = () => HTML.DIV(), + url, + ) => { const name = component.displayName || component.name; @@ -74,6 +76,13 @@ const createTemplateForComponent = async ( children: React.createElement(TemplateComponent), }), Template.instance().firstNode); }); + + Template.instance().autorun(() => { + const routeName = FlowRouter.getRouteName(); + if (routeName !== url) { + ReactDOM.unmountComponentAtNode(Template.instance().container); + } + }); }); Template[name].onDestroyed(() => { @@ -136,11 +145,12 @@ FlowRouter.route('/home', { }, }); -FlowRouter.route('/directory', { +FlowRouter.route('/directory/:tab?', { name: 'directory', - action() { - BlazeLayout.render('main', { center: 'directory' }); + async action() { + const { DirectoryPage } = await require('../app/ui/client/views/app/components/Directory'); + BlazeLayout.render('main', { center: await createTemplateForComponent(DirectoryPage, { }, () => HTML.DIV({ style }), 'directory')}); // eslint-disable-line }, triggersExit: [function() { $('.main-content').addClass('rc-old'); diff --git a/client/startup/startup.js b/client/startup/startup.js index 685428df2379..80e51c8e3b49 100644 --- a/client/startup/startup.js +++ b/client/startup/startup.js @@ -5,6 +5,8 @@ import { TimeSync } from 'meteor/mizzao:timesync'; import { UserPresence } from 'meteor/konecty:user-presence'; import { Accounts } from 'meteor/accounts-base'; import toastr from 'toastr'; +import '@rocket.chat/fuselage-polyfills'; + import hljs from '../../app/markdown/lib/hljs'; import { fireGlobalEvent } from '../../app/ui-utils'; diff --git a/ee/app/engagement-dashboard/client/components/Section.js b/ee/app/engagement-dashboard/client/components/Section.js index 94c9e22cec0e..8d52f7be6272 100644 --- a/ee/app/engagement-dashboard/client/components/Section.js +++ b/ee/app/engagement-dashboard/client/components/Section.js @@ -7,7 +7,7 @@ export function Section({ filter = , }) { return - + diff --git a/package-lock.json b/package-lock.json index f9284e1d890b..227f3e9e5587 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2372,7 +2372,8 @@ "@emotion/stylis": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==", + "dev": true }, "@emotion/unitless": { "version": "0.7.4", @@ -2864,50 +2865,904 @@ } } }, - "@rocket.chat/css-in-js": { + "@rocket.chat/eslint-config": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/eslint-config/-/eslint-config-0.3.0.tgz", + "integrity": "sha512-3AlJvlohi7uwYRbKJP/v3uFCAI69J/2bU/rDAfF0GDifGDPsHAfhLIzSOshtjjIiQHtHeJ/Hg9yz/5U6E9pCrg==", + "dev": true, + "requires": { + "eslint-plugin-import": "^2.17.2" + } + }, + "@rocket.chat/fuselage": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/css-in-js/-/css-in-js-0.6.1.tgz", - "integrity": "sha512-LNvPIj06YQmEI7kl1RFHAOk6ts95lCczafl5Nqx5jXo5SY8XKCjrR0qK1awD5sTSU9mGrDv/rE3tPTKbQPIH6A==", "requires": { - "@emotion/hash": "^0.8.0", - "@emotion/stylis": "^0.8.5" + "@rocket.chat/css-in-js": "^0.6.1", + "@rocket.chat/fuselage-tokens": "^0.6.1", + "@rocket.chat/icons": "^0.6.1" }, "dependencies": { + "@babel/generator": { + "version": "7.7.4", + "requires": { + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.7.5" + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.7.4" + }, "@emotion/hash": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@rocket.chat/css-in-js": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@rocket.chat/css-in-js/-/css-in-js-0.6.1.tgz", + "integrity": "sha512-LNvPIj06YQmEI7kl1RFHAOk6ts95lCczafl5Nqx5jXo5SY8XKCjrR0qK1awD5sTSU9mGrDv/rE3tPTKbQPIH6A==", + "requires": { + "@emotion/hash": "^0.8.0", + "@emotion/stylis": "^0.8.5" + } + }, + "@rocket.chat/fuselage-tokens": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.6.1.tgz", + "integrity": "sha512-8G3h9PTT6I57wddxvJCBqLmGJwzce3v6cSTOjcvnMAQ8xYEjY+NXK2Asq/Xh4Nxwhqwl7vsQLHbBz6XBCNqWZQ==" + }, + "@rocket.chat/icons": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.6.1.tgz", + "integrity": "sha512-uXg4oXscOQKhNP5DxF/O5f9zG8rKfLVJoXzv3AhNf/YGutqwUzLUCzt3O6bO2aeL43GjdfhxD9tZnpZlviZM9Q==" + }, + "@storybook/addon-actions": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/api": "5.2.8", + "@storybook/client-api": "5.2.8", + "@storybook/components": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/theming": "5.2.8", + "react": "^16.8.3", + "react-inspector": "^3.0.2" + }, + "dependencies": { + "@storybook/components": { + "version": "5.2.8", + "requires": { + "@storybook/theming": "5.2.8", + "markdown-to-jsx": "^6.9.1", + "react": "^16.8.3", + "react-dom": "^16.8.3", + "react-focus-lock": "^1.18.3", + "react-helmet-async": "^1.0.2", + "react-popper-tooltip": "^2.8.3", + "react-syntax-highlighter": "^8.0.1", + "react-textarea-autosize": "^7.1.0", + "simplebar-react": "^1.0.0-alpha.6" + }, + "dependencies": { + "react-dom": { + "version": "16.11.0", + "dependencies": { + "scheduler": { + "version": "0.18.0" + } + } + }, + "react-helmet-async": { + "version": "1.0.4" + }, + "react-popper-tooltip": { + "version": "2.10.0", + "requires": { + "react-popper": "^1.3.4" + } + }, + "simplebar-react": { + "version": "1.2.3" + } + } + }, + "create-react-context": { + "version": "0.3.0" + }, + "markdown-to-jsx": { + "version": "6.10.3" + }, + "react": { + "version": "16.11.0" + }, + "react-clientside-effect": { + "version": "1.2.2" + }, + "react-focus-lock": { + "version": "1.19.1", + "requires": { + "react-clientside-effect": "^1.2.0" + } + }, + "react-inspector": { + "version": "3.0.2" + }, + "react-popper": { + "version": "1.3.6", + "requires": { + "create-react-context": "^0.3.0" + } + }, + "react-syntax-highlighter": { + "version": "8.1.0" + }, + "react-textarea-autosize": { + "version": "7.1.2" + }, + "scheduler": { + "version": "0.17.0" + } + } + }, + "@storybook/addon-backgrounds": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/api": "5.2.8", + "@storybook/components": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/theming": "5.2.8", + "react": "^16.8.3" + }, + "dependencies": { + "@storybook/components": { + "version": "5.2.8", + "requires": { + "@storybook/theming": "5.2.8", + "markdown-to-jsx": "^6.9.1", + "react": "^16.8.3", + "react-dom": "^16.8.3", + "react-focus-lock": "^1.18.3", + "react-helmet-async": "^1.0.2", + "react-popper-tooltip": "^2.8.3", + "react-syntax-highlighter": "^8.0.1", + "react-textarea-autosize": "^7.1.0", + "simplebar-react": "^1.0.0-alpha.6" + }, + "dependencies": { + "react-dom": { + "version": "16.11.0", + "dependencies": { + "scheduler": { + "version": "0.18.0" + } + } + }, + "react-helmet-async": { + "version": "1.0.4" + }, + "react-popper-tooltip": { + "version": "2.10.0", + "requires": { + "react-popper": "^1.3.4" + } + }, + "simplebar-react": { + "version": "1.2.3" + } + } + }, + "create-react-context": { + "version": "0.3.0" + }, + "markdown-to-jsx": { + "version": "6.10.3" + }, + "react": { + "version": "16.11.0" + }, + "react-clientside-effect": { + "version": "1.2.2" + }, + "react-focus-lock": { + "version": "1.19.1", + "requires": { + "react-clientside-effect": "^1.2.0" + } + }, + "react-popper": { + "version": "1.3.6", + "requires": { + "create-react-context": "^0.3.0" + } + }, + "react-syntax-highlighter": { + "version": "8.1.0" + }, + "react-textarea-autosize": { + "version": "7.1.2" + }, + "scheduler": { + "version": "0.17.0" + } + } + }, + "@storybook/addon-centered": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8" + } + }, + "@storybook/addon-docs": { + "version": "5.2.8", + "requires": { + "@babel/generator": "^7.7.2", + "@babel/parser": "^7.7.3", + "@storybook/addons": "5.2.8", + "@storybook/api": "5.2.8", + "@storybook/components": "5.2.8", + "@storybook/router": "5.2.8", + "@storybook/source-loader": "5.2.8", + "@storybook/theming": "5.2.8" + } + }, + "@storybook/addon-jest": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/api": "5.2.8", + "@storybook/components": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/theming": "5.2.8", + "react": "^16.8.3", + "react-sizeme": "^2.5.2" + }, + "dependencies": { + "react": { + "version": "16.11.0" + }, + "react-sizeme": { + "version": "2.6.10" + } + } + }, + "@storybook/addon-knobs": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/api": "5.2.8", + "@storybook/client-api": "5.2.8", + "@storybook/components": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/theming": "5.2.8" + } + }, + "@storybook/addon-links": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/router": "5.2.8" + } + }, + "@storybook/addon-options": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8" + } + }, + "@storybook/addon-viewport": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/api": "5.2.8", + "@storybook/components": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/theming": "5.2.8" + } + }, + "@storybook/addons": { + "version": "5.2.8", + "requires": { + "@storybook/api": "5.2.8", + "@storybook/channels": "5.2.8", + "@storybook/core-events": "5.2.8" + } + }, + "@storybook/api": { + "version": "5.2.8", + "requires": { + "@storybook/channels": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/router": "5.2.8", + "@storybook/theming": "5.2.8", + "react": "^16.8.3" + }, + "dependencies": { + "react": { + "version": "16.11.0" + } + } + }, + "@storybook/channel-postmessage": { + "version": "5.2.8", + "requires": { + "@storybook/channels": "5.2.8" + } + }, + "@storybook/channels": { + "version": "5.2.8" + }, + "@storybook/client-api": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/channel-postmessage": "5.2.8", + "@storybook/channels": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/router": "5.2.8", + "is-plain-object": "^3.0.0" + } + }, + "@storybook/components": { + "version": "5.2.8", + "requires": { + "@storybook/theming": "5.2.8", + "markdown-to-jsx": "^6.9.1", + "react": "^16.8.3", + "react-dom": "^16.8.3", + "react-focus-lock": "^1.18.3", + "react-helmet-async": "^1.0.2", + "react-popper-tooltip": "^2.8.3", + "react-syntax-highlighter": "^8.0.1", + "react-textarea-autosize": "^7.1.0", + "simplebar-react": "^1.0.0-alpha.6" + }, + "dependencies": { + "create-react-context": { + "version": "0.3.0" + }, + "markdown-to-jsx": { + "version": "6.10.3" + }, + "react": { + "version": "16.11.0" + }, + "react-clientside-effect": { + "version": "1.2.2" + }, + "react-dom": { + "version": "16.11.0", + "dependencies": { + "scheduler": { + "version": "0.18.0" + } + } + }, + "react-focus-lock": { + "version": "1.19.1", + "requires": { + "react-clientside-effect": "^1.2.0" + } + }, + "react-helmet-async": { + "version": "1.0.4" + }, + "react-popper": { + "version": "1.3.6", + "requires": { + "create-react-context": "^0.3.0" + } + }, + "react-popper-tooltip": { + "version": "2.10.0", + "requires": { + "react-popper": "^1.3.4" + } + }, + "react-syntax-highlighter": { + "version": "8.1.0" + }, + "react-textarea-autosize": { + "version": "7.1.2" + }, + "scheduler": { + "version": "0.17.0" + }, + "simplebar-react": { + "version": "1.2.3" + } + } + }, + "@storybook/core": { + "version": "5.2.8", + "requires": { + "@babel/plugin-proposal-object-rest-spread": "^7.6.2", + "@babel/preset-env": "^7.7.1", + "@storybook/addons": "5.2.8", + "@storybook/channel-postmessage": "5.2.8", + "@storybook/client-api": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/node-logger": "5.2.8", + "@storybook/router": "5.2.8", + "@storybook/theming": "5.2.8", + "@storybook/ui": "5.2.8", + "autoprefixer": "^9.4.9", + "find-cache-dir": "^3.0.0", + "resolve": "^1.11.0", + "terser-webpack-plugin": "^1.2.4", + "webpack": "^4.33.0" + }, + "dependencies": { + "@babel/preset-env": { + "version": "7.7.6", + "requires": { + "@babel/plugin-proposal-object-rest-spread": "^7.7.4", + "browserslist": "^4.6.0", + "core-js-compat": "^3.4.7", + "semver": "^5.5.0" + }, + "dependencies": { + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.7.7" + }, + "semver": { + "version": "5.7.1" + } + } + }, + "autoprefixer": { + "version": "9.7.1", + "requires": { + "browserslist": "^4.7.2", + "caniuse-lite": "^1.0.30001006", + "postcss": "^7.0.21", + "postcss-value-parser": "^4.0.2" + }, + "dependencies": { + "browserslist": { + "version": "4.7.3", + "requires": { + "caniuse-lite": "^1.0.30001010", + "node-releases": "^1.1.40" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30001015" + } + } + } + } + }, + "caniuse-lite": { + "version": "1.0.30001012" + }, + "enhanced-resolve": { + "version": "4.1.1", + "requires": { + "memory-fs": "^0.5.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0" + } + } + }, + "find-cache-dir": { + "version": "3.2.0", + "requires": { + "make-dir": "^3.0.0", + "pkg-dir": "^4.1.0" + } + }, + "node-releases": { + "version": "1.1.42" + }, + "postcss": { + "version": "7.0.23", + "requires": { + "source-map": "^0.6.1" + } + }, + "serialize-javascript": { + "version": "1.9.1" + }, + "source-map": { + "version": "0.6.1" + }, + "terser-webpack-plugin": { + "version": "1.4.1", + "requires": { + "find-cache-dir": "^2.1.0", + "serialize-javascript": "^1.7.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "requires": { + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "requires": { + "semver": "^5.6.0" + } + }, + "pkg-dir": { + "version": "3.0.0" + }, + "semver": { + "version": "5.7.1" + } + } + }, + "webpack": { + "version": "4.41.2", + "requires": { + "acorn": "^6.2.1", + "enhanced-resolve": "^4.1.0", + "terser-webpack-plugin": "^1.4.1" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "requires": { + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "requires": { + "semver": "^5.6.0" + } + }, + "pkg-dir": { + "version": "3.0.0" + }, + "semver": { + "version": "5.7.1" + }, + "serialize-javascript": { + "version": "2.1.2" + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "requires": { + "find-cache-dir": "^2.1.0", + "serialize-javascript": "^2.1.2", + "source-map": "^0.6.1" + } + }, + "webpack": { + "version": "4.41.4", + "requires": { + "acorn": "^6.2.1", + "enhanced-resolve": "^4.1.0", + "terser-webpack-plugin": "^1.4.3" + } + } + } + } + } + }, + "@storybook/core-events": { + "version": "5.2.8" + }, + "@storybook/node-logger": { + "version": "5.2.8" + }, + "@storybook/react": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/core": "5.2.8", + "@storybook/node-logger": "5.2.8", + "mini-css-extract-plugin": "^0.7.0", + "webpack": "^4.33.0" + }, + "dependencies": { + "enhanced-resolve": { + "version": "4.1.1", + "requires": { + "memory-fs": "^0.5.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0" + } + } + }, + "mini-css-extract-plugin": { + "version": "0.7.0" + }, + "webpack": { + "version": "4.41.2", + "requires": { + "acorn": "^6.2.1", + "enhanced-resolve": "^4.1.0", + "terser-webpack-plugin": "^1.4.1" + } + } + } + }, + "@storybook/router": { + "version": "5.2.8" + }, + "@storybook/source-loader": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/router": "5.2.8" + } + }, + "@storybook/theming": { + "version": "5.2.8" + }, + "@storybook/ui": { + "version": "5.2.8", + "requires": { + "@storybook/addons": "5.2.8", + "@storybook/api": "5.2.8", + "@storybook/channels": "5.2.8", + "@storybook/components": "5.2.8", + "@storybook/core-events": "5.2.8", + "@storybook/router": "5.2.8", + "@storybook/theming": "5.2.8", + "markdown-to-jsx": "^6.9.3", + "react": "^16.8.3", + "react-dom": "^16.8.3", + "react-helmet-async": "^1.0.2", + "react-hotkeys": "2.0.0-pre4", + "react-sizeme": "^2.6.7", + "regenerator-runtime": "^0.13.2" + }, + "dependencies": { + "markdown-to-jsx": { + "version": "6.10.3" + }, + "react": { + "version": "16.11.0" + }, + "react-dom": { + "version": "16.11.0", + "requires": { + "scheduler": "^0.17.0" + } + }, + "react-helmet-async": { + "version": "1.0.4" + }, + "react-hotkeys": { + "version": "2.0.0-pre4" + }, + "react-sizeme": { + "version": "2.6.10" + }, + "regenerator-runtime": { + "version": "0.13.3" + }, + "scheduler": { + "version": "0.17.0" + } + } + }, + "acorn": { + "version": "6.4.0" + }, + "autoprefixer": { + "version": "9.7.3", + "requires": { + "browserslist": "^4.8.0", + "caniuse-lite": "^1.0.30001012", + "postcss": "^7.0.23", + "postcss-value-parser": "^4.0.2" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30001015" + } + } + }, + "browserslist": { + "version": "4.8.2", + "requires": { + "caniuse-lite": "^1.0.30001015", + "node-releases": "^1.1.42" + } + }, + "caniuse-lite": { + "version": "1.0.30001016" + }, + "core-js-compat": { + "version": "3.6.0", + "requires": { + "browserslist": "^4.8.2", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0" + } + } + }, + "emoji-regex": { + "version": "7.0.3" + }, + "enhanced-resolve": { + "version": "4.1.0" + }, + "is-plain-object": { + "version": "3.0.0", + "requires": { + "isobject": "^4.0.0" + } + }, + "isobject": { + "version": "4.0.0" + }, + "locate-path": { + "version": "5.0.0", + "requires": { + "p-locate": "^4.1.0" + } + }, + "loki": { + "version": "0.16.0", + "requires": { + "fs-extra": "^7.0.1" + }, + "dependencies": { + "fs-extra": { + "version": "7.0.1" + } + } + }, + "make-dir": { + "version": "3.0.0" + }, + "mini-css-extract-plugin": { + "version": "0.8.2" + }, + "node-releases": { + "version": "1.1.43" + }, + "p-locate": { + "version": "4.1.0" + }, + "path-exists": { + "version": "4.0.0" + }, + "pkg-dir": { + "version": "4.2.0", + "requires": { + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + } + } + }, + "postcss": { + "version": "7.0.24", + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1" + } + } + }, + "postcss-value-parser": { + "version": "4.0.2" + }, + "react-dom": { + "version": "16.12.0", + "requires": { + "scheduler": "^0.18.0" + } + }, + "resolve": { + "version": "1.12.0" + }, + "sass-loader": { + "version": "8.0.0", + "requires": { + "schema-utils": "^2.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "2.6.1" + } + } + }, + "scheduler": { + "version": "0.18.0" + }, + "source-map": { + "version": "0.5.7" + }, + "string-width": { + "version": "3.1.0", + "requires": { + "emoji-regex": "^7.0.1" + } + }, + "terser-webpack-plugin": { + "version": "1.4.3", + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1" + } + } + }, + "webpack": { + "version": "4.41.4", + "requires": { + "acorn": "^6.2.1", + "enhanced-resolve": "^4.1.0", + "terser-webpack-plugin": "^1.4.3" + }, + "dependencies": { + "enhanced-resolve": { + "version": "4.1.1", + "requires": { + "memory-fs": "^0.5.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0" + } + } + } + } + }, + "webpack-cli": { + "version": "3.3.10", + "requires": { + "enhanced-resolve": "4.1.0", + "yargs": "13.2.4" + } + }, + "yargs": { + "version": "13.2.4", + "requires": { + "string-width": "^3.0.0" + } } } }, - "@rocket.chat/eslint-config": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/eslint-config/-/eslint-config-0.3.0.tgz", - "integrity": "sha512-3AlJvlohi7uwYRbKJP/v3uFCAI69J/2bU/rDAfF0GDifGDPsHAfhLIzSOshtjjIiQHtHeJ/Hg9yz/5U6E9pCrg==", - "dev": true, - "requires": { - "eslint-plugin-import": "^2.17.2" - } - }, - "@rocket.chat/fuselage": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.6.1.tgz", - "integrity": "sha512-B3Q7hoD3gw2qfbUmqwT8byOiRnJQju3ozHJcBMyJ8z9qFDdf2qBpMbU0FQ8Gq/lrIy4cSv17+kI5RtOURyfadQ==", - "requires": { - "@rocket.chat/css-in-js": "^0.6.1", - "@rocket.chat/fuselage-tokens": "^0.6.1", - "@rocket.chat/icons": "^0.6.1" - } - }, "@rocket.chat/fuselage-hooks": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-hooks/-/fuselage-hooks-0.6.1.tgz", "integrity": "sha512-/M4lqd3D443GgKstncUokNgJYii7BgiaDLlIgV8LhDcWeLPzc2xDlRfrSmFN7MGcazmrwECq5DUmDSnbVsoCyw==" }, - "@rocket.chat/fuselage-tokens": { + "@rocket.chat/fuselage-polyfills": { "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.6.1.tgz", - "integrity": "sha512-8G3h9PTT6I57wddxvJCBqLmGJwzce3v6cSTOjcvnMAQ8xYEjY+NXK2Asq/Xh4Nxwhqwl7vsQLHbBz6XBCNqWZQ==" + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-polyfills/-/fuselage-polyfills-0.6.1.tgz", + "integrity": "sha512-vGT8GBRcq1euKv1Q8y9+Zj4UxQwc2L7fkmbcGTzk7BX+wxrmgYhX8cDHXk//Km/itDnwTsQfiwMeuJ/weNorIQ==", + "requires": { + "focus-visible": "^5.0.2" + } }, "@rocket.chat/fuselage-ui-kit": { "version": "0.6.1", @@ -15068,6 +15923,11 @@ "integrity": "sha512-Dx69IXGCq1qsUExWuG+5wkiMqVM/zGx/reXSJSLogECwp3x6KeNQZ+NAetgxEFpnC41rD8U3+jRCW68+LNzdtw==", "dev": true }, + "focus-visible": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/focus-visible/-/focus-visible-5.0.2.tgz", + "integrity": "sha512-zT2fj/bmOgEBjqGbURGlowTmCwsIs3bRDMr/sFZz8Ly7VkEiwuCn9swNTL3pPuf8Oua2de7CLuKdnuNajWdDsQ==" + }, "follow-redirects": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", @@ -15343,28 +16203,28 @@ "dependencies": { "abbrev": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true, "optional": true }, "ansi-regex": { "version": "2.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true, "optional": true }, "aproba": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", "dev": true, "optional": true }, "are-we-there-yet": { "version": "1.1.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", "dev": true, "optional": true, @@ -15375,14 +16235,14 @@ }, "balanced-match": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true, "optional": true }, "brace-expansion": { "version": "1.1.11", - "resolved": false, + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "optional": true, @@ -15400,28 +16260,28 @@ }, "code-point-at": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true, "optional": true }, "concat-map": { "version": "0.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true, "optional": true }, "console-control-strings": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=", "dev": true, "optional": true }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true, "optional": true @@ -15438,21 +16298,21 @@ }, "deep-extend": { "version": "0.6.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, "optional": true }, "delegates": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=", "dev": true, "optional": true }, "detect-libc": { "version": "1.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", "dev": true, "optional": true @@ -15469,14 +16329,14 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true, "optional": true }, "gauge": { "version": "2.7.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", "dev": true, "optional": true, @@ -15508,14 +16368,14 @@ }, "has-unicode": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=", "dev": true, "optional": true }, "iconv-lite": { "version": "0.4.24", - "resolved": false, + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", "dev": true, "optional": true, @@ -15535,7 +16395,7 @@ }, "inflight": { "version": "1.0.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "optional": true, @@ -15553,14 +16413,14 @@ }, "ini": { "version": "1.3.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true, "optional": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "optional": true, @@ -15570,14 +16430,14 @@ }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true, "optional": true }, "minimatch": { "version": "3.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "optional": true, @@ -15587,7 +16447,7 @@ }, "minimist": { "version": "0.0.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", "dev": true, "optional": true @@ -15615,7 +16475,7 @@ }, "mkdirp": { "version": "0.5.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", "dev": true, "optional": true, @@ -15670,7 +16530,7 @@ }, "nopt": { "version": "4.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", "dev": true, "optional": true, @@ -15699,7 +16559,7 @@ }, "npmlog": { "version": "4.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "dev": true, "optional": true, @@ -15712,21 +16572,21 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true, "optional": true }, "object-assign": { "version": "4.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true, "optional": true }, "once": { "version": "1.4.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "optional": true, @@ -15736,21 +16596,21 @@ }, "os-homedir": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true, "optional": true }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true, "optional": true }, "osenv": { "version": "0.1.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", "dev": true, "optional": true, @@ -15761,7 +16621,7 @@ }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true, "optional": true @@ -15775,7 +16635,7 @@ }, "rc": { "version": "1.2.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", "dev": true, "optional": true, @@ -15788,7 +16648,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true, "optional": true @@ -15797,7 +16657,7 @@ }, "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "dev": true, "optional": true, @@ -15823,21 +16683,21 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true, "optional": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, "optional": true }, "sax": { "version": "1.2.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true, "optional": true @@ -15851,21 +16711,21 @@ }, "set-blocking": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true, "optional": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", "dev": true, "optional": true }, "string-width": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "optional": true, @@ -15877,7 +16737,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "optional": true, @@ -15887,7 +16747,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "optional": true, @@ -15897,7 +16757,7 @@ }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true, "optional": true @@ -15920,14 +16780,14 @@ }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true, "optional": true }, "wide-align": { "version": "1.1.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", "dev": true, "optional": true, @@ -15937,7 +16797,7 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true, "optional": true @@ -20399,7 +21259,7 @@ "dependencies": { "asn1.js": { "version": "4.10.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "requires": { "bn.js": "^4.0.0", @@ -20409,7 +21269,7 @@ }, "assert": { "version": "1.4.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/assert/-/assert-1.4.1.tgz", "integrity": "sha1-mZEtWRg2tab1s0XA8H7vwI/GXZE=", "requires": { "util": "0.10.3" @@ -20417,7 +21277,7 @@ "dependencies": { "util": { "version": "0.10.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "requires": { "inherits": "2.0.1" @@ -20427,22 +21287,22 @@ }, "base64-js": { "version": "1.3.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz", "integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw==" }, "bn.js": { "version": "4.11.8", - "resolved": false, + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==" }, "brorand": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" }, "browserify-aes": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "requires": { "buffer-xor": "^1.0.3", @@ -20455,7 +21315,7 @@ }, "browserify-cipher": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", "requires": { "browserify-aes": "^1.0.4", @@ -20465,7 +21325,7 @@ }, "browserify-des": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", "requires": { "cipher-base": "^1.0.1", @@ -20476,7 +21336,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "requires": { "bn.js": "^4.1.0", @@ -20485,7 +21345,7 @@ }, "browserify-sign": { "version": "4.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", "requires": { "bn.js": "^4.1.1", @@ -20499,7 +21359,7 @@ }, "browserify-zlib": { "version": "0.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", "requires": { "pako": "~1.0.5" @@ -20507,7 +21367,7 @@ }, "buffer": { "version": "5.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz", "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==", "requires": { "base64-js": "^1.0.2", @@ -20516,17 +21376,17 @@ }, "buffer-xor": { "version": "1.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=" }, "builtin-status-codes": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=" }, "cipher-base": { "version": "1.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "requires": { "inherits": "^2.0.1", @@ -20535,7 +21395,7 @@ }, "console-browserify": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", "requires": { "date-now": "^0.1.4" @@ -20543,17 +21403,17 @@ }, "constants-browserify": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=" }, "core-util-is": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, "create-ecdh": { "version": "4.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", "requires": { "bn.js": "^4.1.0", @@ -20562,7 +21422,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "requires": { "cipher-base": "^1.0.1", @@ -20574,7 +21434,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": false, + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "requires": { "cipher-base": "^1.0.3", @@ -20587,7 +21447,7 @@ }, "crypto-browserify": { "version": "3.12.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", "requires": { "browserify-cipher": "^1.0.0", @@ -20605,12 +21465,12 @@ }, "date-now": { "version": "0.1.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=" }, "des.js": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", "requires": { "inherits": "^2.0.1", @@ -20619,7 +21479,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "requires": { "bn.js": "^4.1.0", @@ -20629,12 +21489,12 @@ }, "domain-browser": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==" }, "elliptic": { "version": "6.4.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.4.1.tgz", "integrity": "sha512-BsXLz5sqX8OHcsh7CqBMztyXARmGQ3LWPtGjJi6DiJHq5C/qvi9P3OqgswKSDftbu8+IoI/QDTAm2fFnQ9SZSQ==", "requires": { "bn.js": "^4.4.0", @@ -20648,12 +21508,12 @@ }, "events": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==" }, "evp_bytestokey": { "version": "1.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "requires": { "md5.js": "^1.3.4", @@ -20662,7 +21522,7 @@ }, "hash-base": { "version": "3.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "requires": { "inherits": "^2.0.1", @@ -20671,7 +21531,7 @@ }, "hash.js": { "version": "1.1.7", - "resolved": false, + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", "requires": { "inherits": "^2.0.3", @@ -20680,14 +21540,14 @@ "dependencies": { "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, "hmac-drbg": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "requires": { "hash.js": "^1.0.3", @@ -20697,27 +21557,27 @@ }, "https-browserify": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=" }, "ieee754": { "version": "1.1.13", - "resolved": false, + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" }, "inherits": { "version": "2.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=" }, "isarray": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "md5.js": { "version": "1.3.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", "requires": { "hash-base": "^3.0.0", @@ -20727,7 +21587,7 @@ }, "miller-rabin": { "version": "4.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "requires": { "bn.js": "^4.0.0", @@ -20736,27 +21596,27 @@ }, "minimalistic-assert": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" }, "minimalistic-crypto-utils": { "version": "1.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" }, "os-browserify": { "version": "0.3.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" }, "pako": { "version": "1.0.10", - "resolved": false, + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.10.tgz", "integrity": "sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw==" }, "parse-asn1": { "version": "5.1.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.4.tgz", "integrity": "sha512-Qs5duJcuvNExRfFZ99HDD3z4mAi3r9Wl/FOjEOijlxwCZs7E7mW2vjTpgQ4J8LpTF8x5v+1Vn5UQFejmWT11aw==", "requires": { "asn1.js": "^4.0.0", @@ -20769,12 +21629,12 @@ }, "path-browserify": { "version": "1.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.0.tgz", "integrity": "sha512-Hkavx/nY4/plImrZPHRk2CL9vpOymZLgEbMNX1U0bjcBL7QN9wODxyx0yaMZURSQaUtSEvDrfAvxa9oPb0at9g==" }, "pbkdf2": { "version": "3.0.17", - "resolved": false, + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", "requires": { "create-hash": "^1.1.2", @@ -20786,17 +21646,17 @@ }, "process": { "version": "0.11.10", - "resolved": false, + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "public-encrypt": { "version": "4.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "requires": { "bn.js": "^4.1.0", @@ -20809,22 +21669,22 @@ }, "punycode": { "version": "2.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "querystring": { "version": "0.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" }, "querystring-es3": { "version": "0.2.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=" }, "randombytes": { "version": "2.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "requires": { "safe-buffer": "^5.1.0" @@ -20832,7 +21692,7 @@ }, "randomfill": { "version": "1.0.4", - "resolved": false, + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "requires": { "randombytes": "^2.0.5", @@ -20841,7 +21701,7 @@ }, "readable-stream": { "version": "3.3.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.3.0.tgz", "integrity": "sha512-EsI+s3k3XsW+fU8fQACLN59ky34AZ14LoeVZpYwmZvldCFo0r0gnelwF2TcMjLor/BTL5aDJVBMkss0dthToPw==", "requires": { "inherits": "^2.0.3", @@ -20851,14 +21711,14 @@ "dependencies": { "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, "ripemd160": { "version": "2.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "requires": { "hash-base": "^3.0.0", @@ -20867,17 +21727,17 @@ }, "safe-buffer": { "version": "5.1.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "setimmediate": { "version": "1.0.5", - "resolved": false, + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" }, "sha.js": { "version": "2.4.11", - "resolved": false, + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "requires": { "inherits": "^2.0.1", @@ -20886,7 +21746,7 @@ }, "stream-browserify": { "version": "2.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", "requires": { "inherits": "~2.0.1", @@ -20895,7 +21755,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "~1.0.0", @@ -20909,14 +21769,14 @@ "dependencies": { "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, "string_decoder": { "version": "1.1.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" @@ -20926,7 +21786,7 @@ }, "stream-http": { "version": "3.0.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.0.0.tgz", "integrity": "sha512-JELJfd+btL9GHtxU3+XXhg9NLYrKFnhybfvRuDghtyVkOFydz3PKNT1df07AMr88qW03WHF+FSV0PySpXignCA==", "requires": { "builtin-status-codes": "^3.0.0", @@ -20937,7 +21797,7 @@ }, "string_decoder": { "version": "1.2.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.2.0.tgz", "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", "requires": { "safe-buffer": "~5.1.0" @@ -20945,7 +21805,7 @@ }, "timers-browserify": { "version": "2.0.10", - "resolved": false, + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.10.tgz", "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "requires": { "setimmediate": "^1.0.4" @@ -20953,12 +21813,12 @@ }, "tty-browserify": { "version": "0.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==" }, "url": { "version": "0.11.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", "requires": { "punycode": "1.3.2", @@ -20967,14 +21827,14 @@ "dependencies": { "punycode": { "version": "1.3.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=" } } }, "util": { "version": "0.11.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", "requires": { "inherits": "2.0.3" @@ -20982,24 +21842,24 @@ "dependencies": { "inherits": { "version": "2.0.3", - "resolved": false, + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, "util-deprecate": { "version": "1.0.2", - "resolved": false, + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "vm-browserify": { "version": "1.1.0", - "resolved": false, + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==" }, "xtend": { "version": "4.0.1", - "resolved": false, + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" } } diff --git a/package.json b/package.json index 44a87bc90d54..afe38f45b514 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "@nivo/heatmap": "^0.61.0", "@nivo/line": "^0.61.1", "@nivo/pie": "^0.61.1", + "@rocket.chat/fuselage-polyfills": "^0.6.1", "@rocket.chat/apps-engine": "^1.13.0-beta.2931", "@rocket.chat/fuselage": "^0.6.1", "@rocket.chat/fuselage-hooks": "^0.6.1", diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index ef37f627eed1..96d484ce0b59 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1459,6 +1459,7 @@ "expression": "Expression", "Extended": "Extended", "External_Domains": "External Domains", + "External_Users": "External Users", "External_Queue_Service_URL": "External Queue Service URL", "External_Service": "External Service", "Facebook_Page": "Facebook Page", diff --git a/server/methods/browseChannels.js b/server/methods/browseChannels.js index a0b61baad54c..4f86ceb948fb 100644 --- a/server/methods/browseChannels.js +++ b/server/methods/browseChannels.js @@ -88,6 +88,7 @@ Meteor.methods({ lastMessage: 1, ts: 1, archived: 1, + default: 1, usersCount: 1, }, }); From 4e9cacf1bac2e37b9c973315d70da94b77ed83fa Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 27 Mar 2020 14:14:07 -0300 Subject: [PATCH 02/26] Update app/ui/client/views/app/components/Directory/ChannelsTab.js Co-Authored-By: Tasso Evangelista --- app/ui/client/views/app/components/Directory/ChannelsTab.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index b410c75e007c..06b38a36f5bb 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -45,7 +45,6 @@ export function ChannelsTab() { const formatDate = useFormatDate(); const renderRow = useCallback(({ _id, ts, default: d, name, description, usersCount, lastMessage, topic, ...rest }) => - {console.log(rest)} From ce76a2a58db625a8c4a2219b7c6669d256e2faa2 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Sat, 28 Mar 2020 00:36:14 -0300 Subject: [PATCH 03/26] fix review --- .../app/components/Directory/ChannelsTab.js | 27 ++++++++++--------- .../components/Directory/DirectoryTable.js | 21 ++++++++------- .../views/app/components/Directory/UserTab.js | 8 +++--- .../views/app/components/Directory/index.js | 14 +++++----- app/ui/client/views/app/components/hooks.js | 2 +- client/main.js | 1 + client/startup/startup.js | 1 - .../components/EngagementDashboardPage.js | 8 +++--- 8 files changed, 45 insertions(+), 37 deletions(-) diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index b410c75e007c..8e53c6d72d63 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -7,6 +7,8 @@ import { useTranslation } from '../../../../../../../client/contexts/Translation import { useRoute } from '../../../../../../../client/contexts/RouterContext'; import { useQuery, useFormatDate } from '../hooks'; +const style = { whiteSpace: 'nowrap' }; + export function ChannelsTab() { const t = useTranslation(); const [sort, setSort] = useState(['name', 'asc']); @@ -24,13 +26,13 @@ export function ChannelsTab() { setSort([id, 'asc']); }, [sort]); - const header = [ - {t('Name')}, - {t('Users')}, - {t('Created_at')}, - {t('Last_Message')}, - {t('Topic')}, - ]; + const header = useMemo(() => [ + {t('Name')}, + {t('Users')}, + {t('Created_at')}, + {t('Last_Message')}, + {t('Topic')}, + ], [sort]); const go = useRoute('channel'); @@ -43,9 +45,8 @@ export function ChannelsTab() { }, []); const formatDate = useFormatDate(); - const renderRow = useCallback(({ _id, ts, default: d, name, description, usersCount, lastMessage, topic, ...rest }) => + const renderRow = useCallback(({ _id, ts, default: d, name, description, usersCount, lastMessage, topic }) => - {console.log(rest)} @@ -64,16 +65,16 @@ export function ChannelsTab() { - + {usersCount} - + {formatDate(ts)} - + {lastMessage && formatDate(lastMessage.ts)} - + {topic} diff --git a/app/ui/client/views/app/components/Directory/DirectoryTable.js b/app/ui/client/views/app/components/Directory/DirectoryTable.js index f96f023c0cbf..05b3fc1f55c3 100644 --- a/app/ui/client/views/app/components/Directory/DirectoryTable.js +++ b/app/ui/client/views/app/components/Directory/DirectoryTable.js @@ -1,5 +1,5 @@ -import React, { useMemo, useState, useEffect } from 'react'; -import { Box, Icon, Margins, Pagination, Skeleton, Table, Flex, Avatar, TextInput, Tile } from '@rocket.chat/fuselage'; +import React, { useMemo, useState, useEffect, useCallback } from 'react'; +import { Box, Icon, Margins, Pagination, Skeleton, Table, Flex, TextInput, Tile } from '@rocket.chat/fuselage'; import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; import { useDebounce } from '../hooks'; @@ -13,7 +13,7 @@ function SortIcon({ direction }) { export function Th({ children, active, direction, sort, onClick, ...props }) { const fn = useMemo(() => () => onClick && onClick(sort), [sort, onClick]); - return + return {children}{sort && } @@ -69,11 +69,13 @@ export function DirectoryTable({ const { result: channels, total } = data; - const handleChange = useMemo(() => (event) => setText(event.currentTarget.value), []); + const handleChange = useCallback((event) => setText(event.currentTarget.value), []); - const Loading = useMemo(() => () => Array.from({ length: 10 }, (_, i) => ), [header && header.length]); + const Loading = useCallback(() => Array.from({ length: 10 }, (_, i) => ), [header && header.length]); - const showingResultsLabel = useMemo(() => ({ count, current, itemsPerPage }) => t('Showing results %s - %s of %s', current + 1, Math.min(current + itemsPerPage, count), count), []); + const showingResultsLabel = useCallback(({ count, current, itemsPerPage }) => t('Showing results %s - %s of %s', current + 1, Math.min(current + itemsPerPage, count), count), []); + + const itemsPerPageLabel = useCallback(() => t('Items_per_page:'), []); return <> @@ -85,7 +87,7 @@ export function DirectoryTable({ ? {t('No_data_found')} - : + : <> { header && @@ -101,13 +103,14 @@ export function DirectoryTable({ t('Items_per_page:')} + itemsPerPageLabel={itemsPerPageLabel} showingResultsLabel={showingResultsLabel} count={total || 0} onSetItemsPerPage={setItemsPerPage} onSetCurrent={setCurrent} /> - } + + } ; diff --git a/app/ui/client/views/app/components/Directory/UserTab.js b/app/ui/client/views/app/components/Directory/UserTab.js index f05f99af21fe..3eece97cc878 100644 --- a/app/ui/client/views/app/components/Directory/UserTab.js +++ b/app/ui/client/views/app/components/Directory/UserTab.js @@ -32,10 +32,10 @@ export function UserTab({ }; const header = [ - , - canViewFullOtherUserInfo && , - federation && , - , + , + canViewFullOtherUserInfo && , + federation && , + , ].filter(Boolean); const go = useRoute('direct'); diff --git a/app/ui/client/views/app/components/Directory/index.js b/app/ui/client/views/app/components/Directory/index.js index 2ac75e385004..0908510cc2f9 100644 --- a/app/ui/client/views/app/components/Directory/index.js +++ b/app/ui/client/views/app/components/Directory/index.js @@ -1,5 +1,5 @@ -import React, { useMemo, useEffect } from 'react'; -import { Box, Margins, Tabs } from '@rocket.chat/fuselage'; +import React, { useEffect, useCallback } from 'react'; +import { Box, Margins, Tabs, Avatar } from '@rocket.chat/fuselage'; import { Page } from '../../../../../../../client/components/basic/Page'; import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; @@ -8,6 +8,8 @@ import { ChannelsTab } from './ChannelsTab'; import { useRoute, useRouteParameter } from '../../../../../../../client/contexts/RouterContext'; import { useSetting } from '../../../../../../../client/contexts/SettingsContext'; +const style = { padding: 0 }; +const avatarBase = { baseUrl: '/avatar/' }; export function DirectoryPage() { const t = useTranslation(); @@ -16,7 +18,7 @@ export function DirectoryPage() { const tab = useRouteParameter('tab'); const goToDirectory = useRoute('directory'); - const handleTabClick = useMemo(() => (tab) => () => goToDirectory({ tab }), [tab]); + const handleTabClick = useCallback((tab) => () => goToDirectory({ tab }), [tab]); useEffect(() => { if (!tab || (tab === 'external' && !federationEnabled)) { @@ -24,9 +26,9 @@ export function DirectoryPage() { } }, [tab, federationEnabled]); - return + return - + {t('Channels')} {t('Users')} @@ -42,7 +44,7 @@ export function DirectoryPage() { - ; + ; } diff --git a/app/ui/client/views/app/components/hooks.js b/app/ui/client/views/app/components/hooks.js index a684477b26a9..37c5b94d3041 100644 --- a/app/ui/client/views/app/components/hooks.js +++ b/app/ui/client/views/app/components/hooks.js @@ -33,8 +33,8 @@ export function useQuery(params, sort, type, workspace = 'local') { const dayFormat = ['h:mm A', 'H:mm']; export function useFormatTime() { const clockMode = useUserPreference('clockMode', false); - const sameDay = dayFormat[clockMode - 1] || useSetting('Message_TimeFormat'); const format = useSetting('Message_TimeFormat'); + const sameDay = dayFormat[clockMode - 1] || format; return useCallback((time) => { switch (clockMode) { case 1: diff --git a/client/main.js b/client/main.js index a1013d38d72e..33ce4ec3a119 100644 --- a/client/main.js +++ b/client/main.js @@ -1,3 +1,4 @@ +import '@rocket.chat/fuselage-polyfills'; import 'url-polyfill'; import './importsCss'; diff --git a/client/startup/startup.js b/client/startup/startup.js index 80e51c8e3b49..d9fd3f37b5aa 100644 --- a/client/startup/startup.js +++ b/client/startup/startup.js @@ -5,7 +5,6 @@ import { TimeSync } from 'meteor/mizzao:timesync'; import { UserPresence } from 'meteor/konecty:user-presence'; import { Accounts } from 'meteor/accounts-base'; import toastr from 'toastr'; -import '@rocket.chat/fuselage-polyfills'; import hljs from '../../app/markdown/lib/hljs'; diff --git a/ee/app/engagement-dashboard/client/components/EngagementDashboardPage.js b/ee/app/engagement-dashboard/client/components/EngagementDashboardPage.js index f9843adf08c4..e77a75fbac52 100644 --- a/ee/app/engagement-dashboard/client/components/EngagementDashboardPage.js +++ b/ee/app/engagement-dashboard/client/components/EngagementDashboardPage.js @@ -1,5 +1,5 @@ import { Box, Margins, Tabs } from '@rocket.chat/fuselage'; -import React from 'react'; +import React, { useMemo } from 'react'; import { useTranslation } from '../../../../../client/contexts/TranslationContext'; import { Page } from '../../../../../client/components/basic/Page'; @@ -7,13 +7,15 @@ import { UsersTab } from './UsersTab'; import { MessagesTab } from './MessagesTab'; import { ChannelsTab } from './ChannelsTab'; +const style = { padding: 0 }; + export function EngagementDashboardPage({ tab = 'users', onSelectTab, }) { const t = useTranslation(); - const handleTabClick = onSelectTab ? (tab) => () => onSelectTab(tab) : () => undefined; + const handleTabClick = useMemo(() => (onSelectTab ? (tab) => () => onSelectTab(tab) : () => undefined), [onSelectTab]); return @@ -22,7 +24,7 @@ export function EngagementDashboardPage({ {t('Messages')} {t('Channels')} - + {(tab === 'users' && ) From 34f67cfdf3e9b4bd137132013430e5492e47a8df Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Sat, 28 Mar 2020 00:49:41 -0300 Subject: [PATCH 04/26] avoiding few rerenders --- app/ui/client/views/app/components/Directory/UserTab.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/ui/client/views/app/components/Directory/UserTab.js b/app/ui/client/views/app/components/Directory/UserTab.js index 3eece97cc878..7c4b7151fb19 100644 --- a/app/ui/client/views/app/components/Directory/UserTab.js +++ b/app/ui/client/views/app/components/Directory/UserTab.js @@ -9,6 +9,7 @@ import { useRoute } from '../../../../../../../client/contexts/RouterContext'; import { usePermission } from '../../../../../../../client/contexts/AuthorizationContext'; import { useQuery, useFormatDate } from '../hooks'; +const style = { whiteSpace: 'nowrap' }; export function UserTab({ workspace = 'local', }) { @@ -31,12 +32,12 @@ export function UserTab({ setSort([id, 'asc']); }; - const header = [ + const header = useMemo(() => [ , canViewFullOtherUserInfo && , federation && , , - ].filter(Boolean); + ].filter(Boolean), [federation, canViewFullOtherUserInfo]); const go = useRoute('direct'); @@ -78,7 +79,7 @@ export function UserTab({ && {domain} } - + {formatDate(createdAt)} , []); From 5fba758e2076e913dd6cff90d1bd54d839dc3404 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Sun, 29 Mar 2020 01:20:42 -0300 Subject: [PATCH 05/26] Show correctly and search by discussions --- app/models/server/models/Rooms.js | 15 +++++++++++++++ .../views/app/components/Directory/ChannelsTab.js | 6 +++--- server/methods/browseChannels.js | 3 ++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/models/server/models/Rooms.js b/app/models/server/models/Rooms.js index 2ed0cd76c83b..059410d86316 100644 --- a/app/models/server/models/Rooms.js +++ b/app/models/server/models/Rooms.js @@ -17,6 +17,7 @@ export class Rooms extends Base { this.tryEnsureIndex({ ts: 1 }); // discussions this.tryEnsureIndex({ prid: 1 }, { sparse: true }); + this.tryEnsureIndex({ fname: 1 }, { sparse: true }); // Livechat - statistics this.tryEnsureIndex({ closedAt: 1 }, { sparse: true }); @@ -414,6 +415,20 @@ export class Rooms extends Base { return this._db.find(query, options); } + findByNameOrFNameAndType(name, type, options) { + const query = { + t: type, + $or: [{ + name, + }, { + fname: name, + }], + }; + + // do not use cache + return this._db.find(query, options); + } + findByNameAndTypeNotDefault(name, type, options) { const query = { t: type, diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index 8e53c6d72d63..45217a9b0c2a 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -45,19 +45,19 @@ export function ChannelsTab() { }, []); const formatDate = useFormatDate(); - const renderRow = useCallback(({ _id, ts, default: d, name, description, usersCount, lastMessage, topic }) => + const renderRow = useCallback(({ _id, ts, default: d, name, fname, description, usersCount, lastMessage, topic }) => - + - {name} {d && {t('default')}} + {fname || name} {d && {t('default')}} {description && {description} } diff --git a/server/methods/browseChannels.js b/server/methods/browseChannels.js index 4f86ceb948fb..38e6741576b3 100644 --- a/server/methods/browseChannels.js +++ b/server/methods/browseChannels.js @@ -78,13 +78,14 @@ Meteor.methods({ return; } - const result = Rooms.findByNameAndType(regex, 'c', { + const result = Rooms.findByNameOrFNameAndType(regex, 'c', { ...pagination, sort, fields: { description: 1, topic: 1, name: 1, + fname: 1, lastMessage: 1, ts: 1, archived: 1, From 7ae1fc4c0132809e0712075973e928fe57887e10 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Sun, 29 Mar 2020 18:53:34 -0300 Subject: [PATCH 06/26] User Bio --- app/api/server/v1/users.js | 1 + app/lib/server/functions/getFullUserData.js | 1 + app/lib/server/functions/saveUser.js | 23 ++++++++-- app/models/server/models/Users.js | 16 +++++++ app/ui-account/client/accountProfile.html | 28 ++++-------- app/ui-account/client/accountProfile.js | 44 ++++++++++++++----- app/ui-flextab/client/tabs/userEdit.html | 15 +++++++ app/ui-flextab/client/tabs/userEdit.js | 1 + app/ui-flextab/client/tabs/userInfo.html | 5 +++ app/ui-flextab/client/tabs/userInfo.js | 10 ++++- .../views/app/components/Directory/UserTab.js | 7 ++- .../server/functions/getDefaultUserFields.js | 1 + .../settings/inputs/StringSettingInput.js | 19 +++++++- client/routes.js | 12 ++--- server/methods/browseChannels.js | 4 +- server/methods/saveUserProfile.js | 9 ++++ 16 files changed, 151 insertions(+), 45 deletions(-) diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index 5570517c9c7d..8d40cbfd8d1a 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -199,6 +199,7 @@ API.v1.addRoute('users.info', { authRequired: true }, { user.rooms = Subscriptions.findByUserId(user._id, { fields: { rid: 1, + bio: 1, name: 1, t: 1, roles: 1, diff --git a/app/lib/server/functions/getFullUserData.js b/app/lib/server/functions/getFullUserData.js index b79cc953adb9..d3892bca9c51 100644 --- a/app/lib/server/functions/getFullUserData.js +++ b/app/lib/server/functions/getFullUserData.js @@ -22,6 +22,7 @@ const fullFields = { emails: 1, phone: 1, statusConnection: 1, + bio: 1, createdAt: 1, lastLogin: 1, services: 1, diff --git a/app/lib/server/functions/saveUser.js b/app/lib/server/functions/saveUser.js index 953a14e2b5c7..e4f44b78cdec 100644 --- a/app/lib/server/functions/saveUser.js +++ b/app/lib/server/functions/saveUser.js @@ -193,6 +193,20 @@ function validateUserEditing(userId, userData) { } } +const handleBio = (updateUser, bio) => { + if (bio && bio.trim()) { + if (typeof bio !== 'string') { + throw new Meteor.Error('error-invalid-field', 'bio', { + method: 'saveUserProfile', + }); + } + updateUser.$set.bio = bio; + } else { + updateUser.$unset = updateUser.$unset || {}; + updateUser.$unset.bio = 1; + } +}; + export const saveUser = function(userId, userData) { validateUserData(userId, userData); let sendPassword = false; @@ -225,14 +239,11 @@ export const saveUser = function(userId, userData) { const updateUser = { $set: { roles: userData.roles || ['user'], + ...typeof userData.name !== 'undefined' && { name: userData.name }, settings: userData.settings || {}, }, }; - if (typeof userData.name !== 'undefined') { - updateUser.$set.name = userData.name; - } - if (typeof userData.requirePasswordChange !== 'undefined') { updateUser.$set.requirePasswordChange = userData.requirePasswordChange; } @@ -241,6 +252,8 @@ export const saveUser = function(userId, userData) { updateUser.$set['emails.0.verified'] = userData.verified; } + handleBio(updateUser, userData.bio); + Meteor.users.update({ _id }, updateUser); if (userData.sendWelcomeEmail) { @@ -294,6 +307,8 @@ export const saveUser = function(userId, userData) { $set: {}, }; + handleBio(updateUser, userData.bio); + if (userData.roles) { updateUser.$set.roles = userData.roles; } diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js index c0bbea891b17..d12ac6bf82c3 100644 --- a/app/models/server/models/Users.js +++ b/app/models/server/models/Users.js @@ -30,6 +30,7 @@ export class Users extends Base { this.tryEnsureIndex({ roles: 1 }, { sparse: 1 }); this.tryEnsureIndex({ name: 1 }); + this.tryEnsureIndex({ bio: 1 }); this.tryEnsureIndex({ createdAt: 1 }); this.tryEnsureIndex({ lastLogin: 1 }); this.tryEnsureIndex({ status: 1 }); @@ -1107,6 +1108,21 @@ export class Users extends Base { return this.update(_id, update); } + setBio(_id, bio = '') { + const update = { + ...bio.trim() ? { + $set: { + bio, + }, + } : { + $unset: { + bio: 1, + }, + }, + }; + return this.update(_id, update); + } + clearSettings(_id) { const update = { $set: { diff --git a/app/ui-account/client/accountProfile.html b/app/ui-account/client/accountProfile.html index 03ee6b0da865..d160300f1c9c 100644 --- a/app/ui-account/client/accountProfile.html +++ b/app/ui-account/client/accountProfile.html @@ -70,26 +70,6 @@ {{/if}} -
- {{# with canChange=allowStatusMessageChange}} - -
- - {{# unless canChange}} -
{{_ 'StatusMessage_Change_Disabled'}}
- {{/unless}} -
- {{/with}} -
{{# with canChange=allowRealNameChange}}
@@ -129,6 +109,14 @@
{{/with}}
+
+ {{# with canChange=allowStatusMessageChange}} + {{> Input onChangeValue=(set 'statusText') value=(get 'statusText') label=(_ 'StatusMessage') maxLength="120" placeholder=(_ 'StatusMessage_Placeholder') _id='statusText' key='statusText' name='statusText' addon='edit' disabled=(ifThenElse canChange false true) hint=(ifThenElse canChange false (_ 'StatusMessage_Change_Disabled')) }} + {{/with}} +
+
+ {{> Input onChangeValue=(set 'bio') value=(get 'bio') multiline=true label=(_ 'Bio') placeholder=(_ 'User_bio') _id='bio' key='bio' }} +
{{#with canChange=allowEmailChange}}
diff --git a/app/ui-account/client/accountProfile.js b/app/ui-account/client/accountProfile.js index 79ba12d4d098..27bf103b0a8c 100644 --- a/app/ui-account/client/accountProfile.js +++ b/app/ui-account/client/accountProfile.js @@ -1,5 +1,6 @@ import { SHA256 } from 'meteor/sha'; import { ReactiveVar } from 'meteor/reactive-var'; +import { ReactiveDict } from 'meteor/reactive-dict'; import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; import { FlowRouter } from 'meteor/kadira:flow-router'; @@ -78,7 +79,7 @@ Template.accountProfile.helpers({ return !validateName(Template.instance().realname.get()); }, statusMessageInvalid() { - return !validateStatusMessage(Template.instance().statusText.get()); + return !validateStatusMessage(Template.instance().fields.get('statusText')); }, confirmationPasswordInvalid() { const { password, confirmationPassword } = Template.instance(); @@ -117,7 +118,8 @@ Template.accountProfile.helpers({ const instance = Template.instance(); instance.dep.depend(); const realname = instance.realname.get(); - const statusText = instance.statusText.get(); + const statusText = instance.fields.get('statusText'); + const bio = instance.fields.get('bio'); const username = instance.username.get(); const password = instance.password.get(); const confirmationPassword = instance.confirmationPassword.get(); @@ -135,7 +137,7 @@ Template.accountProfile.helpers({ return; } } - if (!avatar && user.name === realname && user.username === username && getUserEmailAddress(user) === email && statusText === user.statusText && !password) { + if (!avatar && user.bio === bio && user.name === realname && user.username === username && getUserEmailAddress(user) === email && statusText === user.statusText && !password) { return ret; } if (!validateEmail(email) || !validatePassword(password, confirmationPassword) || (!validateUsername(username) || usernameAvaliable !== true) || !validateName(realname) || !validateStatusMessage(statusText)) { @@ -151,9 +153,6 @@ Template.accountProfile.helpers({ username() { return Meteor.user().username; }, - statusText() { - return Meteor.user().statusText; - }, email() { const user = Meteor.user(); return getUserEmailAddress(user); @@ -187,11 +186,30 @@ Template.accountProfile.helpers({ customFields() { return Meteor.user().customFields; }, + get(field) { + return Template.instance().fields.get(field); + }, + set(field) { + const instance = Template.instance(); + const fn = (value) => instance.fields.set(field, value); + if (!instance.set[field]) { // avoid react rerender + instance.set[field] = () => fn; + } + return instance.set[field]; + }, }); Template.accountProfile.onCreated(function() { - const self = this; + this.set = {}; + const user = Meteor.user(); + + this.fields = new ReactiveDict({ + statusText: user.statusText, + bio: user.bio, + }); + + const self = this; self.dep = new Tracker.Dependency(); self.realname = new ReactiveVar(user.name); self.email = new ReactiveVar(getUserEmailAddress(user)); @@ -267,7 +285,7 @@ Template.accountProfile.onCreated(function() { } data.realname = s.trim(self.realname.get()); } - if (s.trim(self.statusText.get()) !== user.statusText) { + if (s.trim(self.fields.get('statusText')) !== user.statusText) { if (!settings.get('Accounts_AllowUserStatusMessageChange')) { toastr.remove(); toastr.error(t('StatusMessage_Change_Disabled')); @@ -275,7 +293,11 @@ Template.accountProfile.onCreated(function() { return cb && cb(); } - data.statusText = s.trim(self.statusText.get()); + data.statusText = s.trim(self.fields.get('statusText')); + } + + if (s.trim(self.fields.get('bio')) !== user.statusText) { + data.bio = s.trim(self.fields.get('bio')); } if (s.trim(self.username.get()) !== user.username) { if (!settings.get('Accounts_AllowUsernameChange')) { @@ -295,6 +317,7 @@ Template.accountProfile.onCreated(function() { } data.email = s.trim(self.email.get()); } + const customFields = {}; $('[data-customfield=true]').each(function() { customFields[this.name] = $(this).val() || ''; @@ -396,9 +419,6 @@ Template.accountProfile.events({ 'input [name=realname]'(e, instance) { instance.realname.set(e.target.value); }, - 'input [name=statusText]'(e, instance) { - instance.statusText.set(e.target.value); - }, 'input [name=password]'(e, instance) { instance.password.set(e.target.value); diff --git a/app/ui-flextab/client/tabs/userEdit.html b/app/ui-flextab/client/tabs/userEdit.html index fb83c6096fae..dceb2fcca362 100644 --- a/app/ui-flextab/client/tabs/userEdit.html +++ b/app/ui-flextab/client/tabs/userEdit.html @@ -113,6 +113,21 @@
+
+
+ +
+
+ + {{#if hasPermission 'edit-other-user-password'}}
diff --git a/app/ui-flextab/client/tabs/userEdit.js b/app/ui-flextab/client/tabs/userEdit.js index df4d933c3598..6ccae14800f9 100644 --- a/app/ui-flextab/client/tabs/userEdit.js +++ b/app/ui-flextab/client/tabs/userEdit.js @@ -205,6 +205,7 @@ Template.userEdit.onCreated(function() { userData.name = s.trim(this.$('#name').val()); userData.username = s.trim(this.$('#username').val()); userData.statusText = s.trim(this.$('#status').val()); + userData.bio = s.trim(this.$('#bio').val()); userData.email = s.trim(this.$('#email').val()); userData.verified = this.$('#verified:checked').length > 0; userData.password = s.trim(this.$('#password').val()); diff --git a/app/ui-flextab/client/tabs/userInfo.html b/app/ui-flextab/client/tabs/userInfo.html index c57a711be264..69e6128cf614 100644 --- a/app/ui-flextab/client/tabs/userInfo.html +++ b/app/ui-flextab/client/tabs/userInfo.html @@ -51,6 +51,11 @@
, + , canViewFullOtherUserInfo && , federation && , , @@ -51,7 +53,7 @@ export function UserTab({ const formatDate = useFormatDate(); - const renderRow = useCallback(({ createdAt, emails, _id, username, name, domain }) => + const renderRow = useCallback(({ createdAt, emails, _id, username, name, domain, bio }) => @@ -71,6 +73,9 @@ export function UserTab({ + + {bio} + {canViewFullOtherUserInfo && {emails && emails[0].address} diff --git a/app/utils/server/functions/getDefaultUserFields.js b/app/utils/server/functions/getDefaultUserFields.js index 492a3732018e..1fc95c087dd5 100644 --- a/app/utils/server/functions/getDefaultUserFields.js +++ b/app/utils/server/functions/getDefaultUserFields.js @@ -6,6 +6,7 @@ export const getDefaultUserFields = () => ({ statusDefault: 1, statusText: 1, statusConnection: 1, + bio: 1, avatarOrigin: 1, utcOffset: 1, language: 1, diff --git a/client/components/admin/settings/inputs/StringSettingInput.js b/client/components/admin/settings/inputs/StringSettingInput.js index e044f0dfc01a..b5ddaa78672e 100644 --- a/client/components/admin/settings/inputs/StringSettingInput.js +++ b/client/components/admin/settings/inputs/StringSettingInput.js @@ -1,8 +1,17 @@ -import { Box, Field, Flex, TextAreaInput, TextInput } from '@rocket.chat/fuselage'; +import { Box, Field, Flex, TextAreaInput, TextInput, Icon, Callout, Margins } from '@rocket.chat/fuselage'; import React from 'react'; import { ResetSettingButton } from '../ResetSettingButton'; +export function Input({ hint, callout, ...props }) { + return + + {hint && {hint}} + {callout && + {callout}} + ; +} + export function StringSettingInput({ _id, label, @@ -15,6 +24,8 @@ export function StringSettingInput({ hasResetButton, onChangeValue, onResetButtonClick, + addon, + ...props }) { const handleChange = (event) => { onChangeValue(event.currentTarget.value); @@ -39,6 +50,8 @@ export function StringSettingInput({ readOnly={readonly} autoComplete={autocomplete === false ? 'off' : undefined} onChange={handleChange} + { ...addon && { addon: }} + { ...props } /> : }} + { ...props } /> } ; } + +Input.name = 'Input'; diff --git a/client/routes.js b/client/routes.js index 161daf76413c..d49ee0cee075 100644 --- a/client/routes.js +++ b/client/routes.js @@ -34,7 +34,7 @@ FlowRouter.goToRoomById = async (rid) => { BlazeLayout.setRoot('body'); -const createTemplateForComponent = async ( +export const createTemplateForComponent = async ( component, props = {}, // eslint-disable-next-line new-cap @@ -62,7 +62,7 @@ const createTemplateForComponent = async ( const { MeteorProvider } = await import('./providers/MeteorProvider'); function TemplateComponent() { - return React.createElement(component, Template[name].props.get()); + return React.createElement(component, Template.currentData()); } Template[name].onRendered(() => { @@ -77,7 +77,7 @@ const createTemplateForComponent = async ( }), Template.instance().firstNode); }); - Template.instance().autorun(() => { + url && Template.instance().autorun(() => { const routeName = FlowRouter.getRouteName(); if (routeName !== url) { ReactDOM.unmountComponentAtNode(Template.instance().container); @@ -160,10 +160,12 @@ FlowRouter.route('/directory/:tab?', { FlowRouter.route('/account/:group?', { name: 'account', - action(params) { + async action(params) { if (!params.group) { - params.group = 'Preferences'; + params.group = 'Profile'; } + const { Input } = await require('../client/components/admin/settings/inputs/StringSettingInput'); + console.log(await createTemplateForComponent(Input, { }, () => HTML.DIV({ style }))); // eslint-disable-line params.group = s.capitalize(params.group, true); BlazeLayout.render('main', { center: `account${ params.group }` }); }, diff --git a/server/methods/browseChannels.js b/server/methods/browseChannels.js index 4f86ceb948fb..9263230b1bc4 100644 --- a/server/methods/browseChannels.js +++ b/server/methods/browseChannels.js @@ -55,7 +55,7 @@ Meteor.methods({ return; } - if (!['name', 'createdAt', 'usersCount', ...type === 'channels' ? ['usernames', 'lastMessage'] : [], ...type === 'users' ? ['username', 'email'] : []].includes(sortBy)) { + if (!['name', 'createdAt', 'usersCount', ...type === 'channels' ? ['usernames', 'lastMessage'] : [], ...type === 'users' ? ['username', 'email', 'bio'] : []].includes(sortBy)) { return; } @@ -119,6 +119,7 @@ Meteor.methods({ fields: { username: 1, name: 1, + bio: 1, createdAt: 1, emails: 1, federation: 1, @@ -148,6 +149,7 @@ Meteor.methods({ results.unshift({ username: user.username, name: user.name, + bio: user.bio, emails: user.emails, federation: user.federation, isRemote: true, diff --git a/server/methods/saveUserProfile.js b/server/methods/saveUserProfile.js index b197a3a038f4..6beb74ae9d34 100644 --- a/server/methods/saveUserProfile.js +++ b/server/methods/saveUserProfile.js @@ -57,6 +57,15 @@ Meteor.methods({ Meteor.call('setUserStatus', null, settings.statusText); } + if (settings.bio) { + if (typeof settings.bio !== 'string') { + throw new Meteor.Error('error-invalid-field', 'bio', { + method: 'saveUserProfile', + }); + } + Users.setBio(user._id, settings.bio.trim()); + } + if (settings.email) { if (!checkPassword(user, settings.typedPassword)) { throw new Meteor.Error('error-invalid-password', 'Invalid password', { From f74215e7a41b447668d72f5d35a50489afdcd672 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Sun, 29 Mar 2020 19:31:20 -0300 Subject: [PATCH 07/26] Featured channels --- .../server/methods/saveRoomSettings.js | 12 +++- app/models/server/models/Rooms.js | 14 ++++ app/ui-admin/client/rooms/adminRooms.js | 16 +++++ .../client/rooms/channelSettingsFeatured.html | 15 +++++ .../client/rooms/channelSettingsFeatured.js | 65 +++++++++++++++++++ app/ui-admin/client/rooms/views.js | 1 + .../app/components/Directory/ChannelsTab.js | 12 +++- server/methods/browseChannels.js | 1 + 8 files changed, 133 insertions(+), 3 deletions(-) create mode 100644 app/ui-admin/client/rooms/channelSettingsFeatured.html create mode 100644 app/ui-admin/client/rooms/channelSettingsFeatured.js diff --git a/app/channel-settings/server/methods/saveRoomSettings.js b/app/channel-settings/server/methods/saveRoomSettings.js index 91d7fbcecf41..bf4d741b30c6 100644 --- a/app/channel-settings/server/methods/saveRoomSettings.js +++ b/app/channel-settings/server/methods/saveRoomSettings.js @@ -17,9 +17,10 @@ import { saveRoomTokenpass } from '../functions/saveRoomTokens'; import { saveStreamingOptions } from '../functions/saveStreamingOptions'; import { RoomSettingsEnum, roomTypes } from '../../../utils'; -const fields = ['roomName', 'roomTopic', 'roomAnnouncement', 'roomCustomFields', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode', 'tokenpass', 'streamingOptions', 'retentionEnabled', 'retentionMaxAge', 'retentionExcludePinned', 'retentionFilesOnly', 'retentionOverrideGlobal', 'encrypted']; +const fields = ['featured', 'roomName', 'roomTopic', 'roomAnnouncement', 'roomCustomFields', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode', 'tokenpass', 'streamingOptions', 'retentionEnabled', 'retentionMaxAge', 'retentionExcludePinned', 'retentionFilesOnly', 'retentionOverrideGlobal', 'encrypted']; Meteor.methods({ saveRoomSettings(rid, settings, value) { + console.log(settings, value); const userId = Meteor.userId(); if (!userId) { @@ -79,6 +80,12 @@ Meteor.methods({ action: 'Viewing_room_administration', }); } + if (settings === 'featured' && !hasPermission(userId, 'view-room-administration')) { + throw new Meteor.Error('error-action-not-allowed', 'Viewing room administration is not allowed', { + method: 'saveRoomSettings', + action: 'Viewing_room_administration', + }); + } if (setting === 'roomType' && value !== room.t && value === 'c' && !hasPermission(userId, 'create-c')) { throw new Meteor.Error('error-action-not-allowed', 'Changing a private group to a public channel is not allowed', { method: 'saveRoomSettings', @@ -194,6 +201,9 @@ Meteor.methods({ case 'default': Rooms.saveDefaultById(rid, value); break; + case 'featured': + Rooms.saveFeaturedById(rid, value); + break; case 'retentionEnabled': Rooms.saveRetentionEnabledById(rid, value); break; diff --git a/app/models/server/models/Rooms.js b/app/models/server/models/Rooms.js index 059410d86316..d7a244e68008 100644 --- a/app/models/server/models/Rooms.js +++ b/app/models/server/models/Rooms.js @@ -11,6 +11,7 @@ export class Rooms extends Base { this.tryEnsureIndex({ name: 1 }, { unique: true, sparse: true }); this.tryEnsureIndex({ default: 1 }); + this.tryEnsureIndex({ featured: 1 }); this.tryEnsureIndex({ t: 1 }); this.tryEnsureIndex({ 'u._id': 1 }); this.tryEnsureIndex({ 'tokenpass.tokens.token': 1 }); @@ -888,6 +889,19 @@ export class Rooms extends Base { return this.update(query, update); } + saveFeaturedById(_id, featured) { + const query = { _id }; + const set = ['true', true].includes(featured); + + const update = { + [set ? '$set' : '$unset']: { + featured: true, + }, + }; + + return this.update(query, update); + } + saveDefaultById(_id, defaultValue) { const query = { _id }; diff --git a/app/ui-admin/client/rooms/adminRooms.js b/app/ui-admin/client/rooms/adminRooms.js index 4a7133850330..bce61d1a6a51 100644 --- a/app/ui-admin/client/rooms/adminRooms.js +++ b/app/ui-admin/client/rooms/adminRooms.js @@ -102,6 +102,7 @@ Template.adminRooms.onCreated(function() { template: 'adminRoomInfo', order: 1, }); + ChannelSettings.addOption({ group: ['admin-room'], id: 'make-default', @@ -117,6 +118,21 @@ Template.adminRooms.onCreated(function() { }, }); + ChannelSettings.addOption({ + group: ['admin-room'], + id: 'make-default', + template: 'channelSettingsFeatured', + data() { + return { + room: instance.tabBarData.get().room, + onSuccess: instance.tabBarData.get().onSuccess, + }; + }, + validation() { + return hasAllPermission('view-room-administration'); + }, + }); + this.onSuccessCallback = () => { instance.offset.set(0); return instance.loadRooms(instance.types.get(), instance.filter.get(), instance.offset.get()); diff --git a/app/ui-admin/client/rooms/channelSettingsFeatured.html b/app/ui-admin/client/rooms/channelSettingsFeatured.html new file mode 100644 index 000000000000..a6b003286736 --- /dev/null +++ b/app/ui-admin/client/rooms/channelSettingsFeatured.html @@ -0,0 +1,15 @@ + diff --git a/app/ui-admin/client/rooms/channelSettingsFeatured.js b/app/ui-admin/client/rooms/channelSettingsFeatured.js new file mode 100644 index 000000000000..a0ffb03881ee --- /dev/null +++ b/app/ui-admin/client/rooms/channelSettingsFeatured.js @@ -0,0 +1,65 @@ +import { Meteor } from 'meteor/meteor'; +import { ReactiveVar } from 'meteor/reactive-var'; +import { Template } from 'meteor/templating'; +import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; +import toastr from 'toastr'; +import './channelSettingsFeatured.html'; + +import { t, handleError } from '../../../utils'; + +Template.channelSettingsFeatured.helpers({ + editing(field) { + return Template.instance().editing.get() === field; + }, + roomFeatured() { + const room = Template.instance().room.get(); + + if (room) { + return room.featured; + } + }, + featuredDescription() { + const room = Template.instance().room.get(); + if (room && room.featured) { + return t('True'); + } + return t('False'); + }, +}); + +Template.channelSettingsFeatured.events({ + 'click [data-edit]'(e, t) { + e.preventDefault(); + t.editing.set($(e.currentTarget).data('edit')); + setTimeout(() => { + t.$('input.editing').focus().select(); + }, 100); + }, + 'click .cancel'(e, t) { + e.preventDefault(); + t.editing.set(); + }, + 'click .save'(e, t) { + e.preventDefault(); + + Meteor.call('saveRoomSettings', Template.instance().room.get()._id, 'featured', $('input[name=featured]:checked').val(), (err/* , result*/) => { + if (err) { + return handleError(err); + } + toastr.success(TAPi18n.__('Room_changed_successfully')); + }); + t.onSuccess(); + t.editing.set(); + }, +}); + +Template.channelSettingsFeatured.onCreated(function() { + this.editing = new ReactiveVar(); + this.room = new ReactiveVar(); + this.onSuccess = Template.currentData().onSuccess; + + this.autorun(() => { + const { room } = Template.currentData(); + this.room.set(room); + }); +}); diff --git a/app/ui-admin/client/rooms/views.js b/app/ui-admin/client/rooms/views.js index cfd9eee52505..9bfc9dcf830d 100644 --- a/app/ui-admin/client/rooms/views.js +++ b/app/ui-admin/client/rooms/views.js @@ -3,4 +3,5 @@ import './adminRoomInfo.html'; import './adminRoomInfo'; import './channelSettingsDefault.html'; import './channelSettingsDefault'; +import './channelSettingsFeatured'; import './adminRooms'; diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index 45217a9b0c2a..d6687b34712c 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -9,6 +9,14 @@ import { useQuery, useFormatDate } from '../hooks'; const style = { whiteSpace: 'nowrap' }; +function RoomTags({ room }) { + const t = useTranslation(); + return + {room.default && {t('default')}} + {room.featured && {t('featured')}} + ; +} + export function ChannelsTab() { const t = useTranslation(); const [sort, setSort] = useState(['name', 'asc']); @@ -45,7 +53,7 @@ export function ChannelsTab() { }, []); const formatDate = useFormatDate(); - const renderRow = useCallback(({ _id, ts, default: d, name, fname, description, usersCount, lastMessage, topic }) => + const renderRow = useCallback(({ _id, ts, name, fname, description, usersCount, lastMessage, topic, ...room }) => @@ -57,7 +65,7 @@ export function ChannelsTab() { - {fname || name} {d && {t('default')}} + {fname || name} {description && {description} } diff --git a/server/methods/browseChannels.js b/server/methods/browseChannels.js index 4b730d46e525..370b979f9f94 100644 --- a/server/methods/browseChannels.js +++ b/server/methods/browseChannels.js @@ -90,6 +90,7 @@ Meteor.methods({ ts: 1, archived: 1, default: 1, + featured: 1, usersCount: 1, }, }); From bdbe78178a6568b1967ff84cc5dab2761d054752 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Sun, 29 Mar 2020 23:11:24 -0300 Subject: [PATCH 08/26] Featured on top always --- server/methods/browseChannels.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/server/methods/browseChannels.js b/server/methods/browseChannels.js index 370b979f9f94..e1433d25d780 100644 --- a/server/methods/browseChannels.js +++ b/server/methods/browseChannels.js @@ -80,7 +80,10 @@ Meteor.methods({ const result = Rooms.findByNameOrFNameAndType(regex, 'c', { ...pagination, - sort, + sort: { + featured: -1, + ...sort, + }, fields: { description: 1, topic: 1, @@ -140,7 +143,7 @@ Meteor.methods({ const total = result.count(); // count ignores the `skip` and `limit` options const results = result.fetch(); - // Try to find federated users, when appliable + // Try to find federated users, when applicable if (isFederationEnabled() && type === 'users' && workspace === 'external' && text.indexOf('@') !== -1) { const users = federationSearchUsers(text); From a5dcdb88ad8efc9c86141b87ae9d1611444d97dc Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Sun, 29 Mar 2020 23:11:44 -0300 Subject: [PATCH 09/26] Remove topic column from users tab --- app/ui/client/views/app/components/Directory/ChannelsTab.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index d6687b34712c..ba51eca08615 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -39,7 +39,6 @@ export function ChannelsTab() { , , , - , ], [sort]); const go = useRoute('channel'); @@ -66,7 +65,7 @@ export function ChannelsTab() { {fname || name} - {description && {description} } + {topic && {topic} } @@ -82,9 +81,6 @@ export function ChannelsTab() { {lastMessage && formatDate(lastMessage.ts)} - - {topic} - , []); From b988e29c517ca885c8fb27af9e41f7b69a02425f Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Sun, 29 Mar 2020 23:11:58 -0300 Subject: [PATCH 10/26] Add bio as default field for searching --- app/lib/server/startup/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/server/startup/settings.js b/app/lib/server/startup/settings.js index ede7feccac60..399554c8e9b0 100644 --- a/app/lib/server/startup/settings.js +++ b/app/lib/server/startup/settings.js @@ -97,7 +97,7 @@ settings.addGroup('Accounts', function() { type: 'boolean', public: true, }); - this.add('Accounts_SearchFields', 'username, name', { + this.add('Accounts_SearchFields', 'username, name, bio', { type: 'string', public: true, }); From 06490a94dc5d79ed3c220c2c2901528de0224e75 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Sun, 29 Mar 2020 23:32:17 -0300 Subject: [PATCH 11/26] Sort List merged and using React --- app/ui-sidenav/client/SortList.js | 130 +++++++++++++++++++++ app/ui-sidenav/client/index.js | 2 - app/ui-sidenav/client/sidebarHeader.js | 99 ++-------------- app/ui-sidenav/client/sortlist.html | 65 ----------- app/ui-sidenav/client/sortlist.js | 52 --------- packages/rocketchat-i18n/i18n/en.i18n.json | 2 + 6 files changed, 140 insertions(+), 210 deletions(-) create mode 100644 app/ui-sidenav/client/SortList.js delete mode 100644 app/ui-sidenav/client/sortlist.html delete mode 100644 app/ui-sidenav/client/sortlist.js diff --git a/app/ui-sidenav/client/SortList.js b/app/ui-sidenav/client/SortList.js new file mode 100644 index 000000000000..0c15478e896c --- /dev/null +++ b/app/ui-sidenav/client/SortList.js @@ -0,0 +1,130 @@ +import React, { useCallback } from 'react'; +import { Icon, ToggleSwitch, RadioButton, Box, Flex, Margins } from '@rocket.chat/fuselage'; + + +import { useTranslation } from '../../../client/contexts/TranslationContext'; +import { useUserPreference } from '../../../client/contexts/UserContext'; +import { useMethod } from '../../../client/contexts/ServerContext'; + +function SortListItem({ text, icon, input }) { + return + + + + + + + + + {text} + + + + {input} + + + + + ; +} +const style = { + textTransform: 'uppercase', +}; +export function SortList() { + return <>
+ + + +
+ ; +} + +export function SortModeList() { + const t = useTranslation(); + const saveUserPreferences = useMethod('saveUserPreferences'); + const sidebarSortBy = useUserPreference('sidebarSortby', 'alphabetical'); + + const handleChange = (value) => () => saveUserPreferences({ sidebarSortby: value }); + + const setToAlphabetical = useCallback(handleChange('alphabetical'), []); + const setToActivity = useCallback(handleChange('activity'), []); + + return <> + + {t('Sort_By')} + +
    + + } /> + } /> + +
+ ; +} + + +function ViewModeList() { + const t = useTranslation(); + + const saveUserPreferences = useMethod('saveUserPreferences'); + + const handleChange = (value) => () => saveUserPreferences({ sidebarViewMode: value }); + + const sidebarViewMode = useUserPreference('sidebarViewMode', 'extended'); + const sidebarHideAvatar = useUserPreference('sidebarHideAvatar', false); + + const setToExtended = useCallback(handleChange('extended'), []); + const setToMedium = useCallback(handleChange('medium'), []); + const setToCondensed = useCallback(handleChange('condensed'), []); + + const handleChangeSidebarHideAvatar = useCallback(() => saveUserPreferences({ sidebarHideAvatar: !sidebarHideAvatar }), [sidebarHideAvatar]); + + return <> + + {t('View_mode')} + +
    + + } /> + } /> + } /> + } /> + +
+ ; +} + + +function GroupingList() { + const sidebarShowDiscussion = useUserPreference('sidebarShowDiscussion'); + const sidebarGroupByType = useUserPreference('sidebarGroupByType'); + const sidebarShowFavorites = useUserPreference('sidebarShowFavorites'); + const sidebarShowUnread = useUserPreference('sidebarShowUnread'); + + const saveUserPreferences = useMethod('saveUserPreferences'); + + const handleChange = (key, value) => () => saveUserPreferences({ [key]: value }); + + const handleChangeShowDicussion = useCallback(handleChange('sidebarShowDiscussion', !sidebarShowDiscussion), [sidebarShowDiscussion]); + const handleChangeGroupByType = useCallback(handleChange('sidebarGroupByType', !sidebarGroupByType), [sidebarGroupByType]); + const handleChangeShoFavorite = useCallback(handleChange('sidebarShowFavorites', !sidebarShowFavorites), [sidebarShowFavorites]); + const handleChangeShowUnread = useCallback(handleChange('sidebarShowUnread', !sidebarShowUnread), [sidebarShowUnread]); + + + const t = useTranslation(); + return <> + + {t('Grouping')} + +
    + + } /> + } /> + } /> + } /> + +
+ ; +} + +SortList.name = 'SortList'; diff --git a/app/ui-sidenav/client/index.js b/app/ui-sidenav/client/index.js index 216d156fe5e4..ce46c1f15fa7 100644 --- a/app/ui-sidenav/client/index.js +++ b/app/ui-sidenav/client/index.js @@ -4,14 +4,12 @@ import './sidebarItem.html'; import './sideNav.html'; import './toolbar.html'; import './roomList.html'; -import './sortlist.html'; import './userStatus.html'; import './chatRoomItem'; import { toolbarSearch } from './sidebarHeader'; import './sidebarItem'; import './sideNav'; import './roomList'; -import './sortlist'; import './toolbar'; import './userPresence'; diff --git a/app/ui-sidenav/client/sidebarHeader.js b/app/ui-sidenav/client/sidebarHeader.js index 1117e6460b5b..c9627e59e7fd 100644 --- a/app/ui-sidenav/client/sidebarHeader.js +++ b/app/ui-sidenav/client/sidebarHeader.js @@ -4,12 +4,14 @@ import { FlowRouter } from 'meteor/kadira:flow-router'; import { Template } from 'meteor/templating'; import { popover, AccountBox, menu, SideNav, modal } from '../../ui-utils'; -import { t, getUserPreference, handleError } from '../../utils'; +import { t } from '../../utils'; import { callbacks } from '../../callbacks'; import { settings } from '../../settings'; import { hasAtLeastOnePermission } from '../../authorization'; import { userStatus } from '../../user-status'; import { hasPermission } from '../../authorization/client'; +import { createTemplateForComponent } from '../../../client/routes'; + const setStatus = (status, statusText) => { AccountBox.setStatus(status, statusText); @@ -17,29 +19,6 @@ const setStatus = (status, statusText) => { popover.close(); }; -const viewModeIcon = { - extended: 'th-list', - medium: 'list', - condensed: 'list-alt', -}; - -const extendedViewOption = (user) => { - if (settings.get('Store_Last_Message')) { - return { - icon: viewModeIcon.extended, - name: t('Extended'), - modifier: getUserPreference(user, 'sidebarViewMode') === 'extended' ? 'bold' : null, - action: () => { - Meteor.call('saveUserPreferences', { sidebarViewMode: 'extended' }, function(error) { - if (error) { - return handleError(error); - } - }); - }, - }; - } -}; - const showToolbar = new ReactiveVar(false); export const toolbarSearch = { @@ -57,7 +36,7 @@ export const toolbarSearch = { }, }; -const toolbarButtons = (user) => [{ +const toolbarButtons = (/* user */) => [{ name: t('Search'), icon: 'magnifier', action: () => { @@ -72,84 +51,22 @@ const toolbarButtons = (user) => [{ FlowRouter.go('directory'); }, }, -{ - name: t('View_mode'), - icon: () => viewModeIcon[getUserPreference(user, 'sidebarViewMode') || 'condensed'], - hasPopup: true, - action: (e) => { - const hideAvatarSetting = getUserPreference(user, 'sidebarHideAvatar'); - const config = { - columns: [ - { - groups: [ - { - items: [ - extendedViewOption(user), - { - icon: viewModeIcon.medium, - name: t('Medium'), - modifier: getUserPreference(user, 'sidebarViewMode') === 'medium' ? 'bold' : null, - action: () => { - Meteor.call('saveUserPreferences', { sidebarViewMode: 'medium' }, function(error) { - if (error) { - return handleError(error); - } - }); - }, - }, - { - icon: viewModeIcon.condensed, - name: t('Condensed'), - modifier: getUserPreference(user, 'sidebarViewMode') === 'condensed' ? 'bold' : null, - action: () => { - Meteor.call('saveUserPreferences', { sidebarViewMode: 'condensed' }, function(error) { - if (error) { - return handleError(error); - } - }); - }, - }, - ], - }, - { - items: [ - { - icon: 'user-rounded', - name: hideAvatarSetting ? t('Show_Avatars') : t('Hide_Avatars'), - action: () => { - Meteor.call('saveUserPreferences', { sidebarHideAvatar: !hideAvatarSetting }, function(error) { - if (error) { - return handleError(error); - } - }); - }, - }, - ], - }, - ], - }, - ], - currentTarget: e.currentTarget, - offsetVertical: e.currentTarget.clientHeight + 10, - }; - - popover.open(config); - }, -}, { name: t('Sort'), icon: 'sort', hasPopup: true, - action: (e) => { + action: async (e) => { const options = []; const config = { - template: 'sortlist', + template: 'SortList', currentTarget: e.currentTarget, data: { options, }, offsetVertical: e.currentTarget.clientHeight + 10, }; + const { SortList } = require('./SortList'); + await createTemplateForComponent(SortList); popover.open(config); }, }, diff --git a/app/ui-sidenav/client/sortlist.html b/app/ui-sidenav/client/sortlist.html deleted file mode 100644 index fa8efb05de23..000000000000 --- a/app/ui-sidenav/client/sortlist.html +++ /dev/null @@ -1,65 +0,0 @@ - diff --git a/app/ui-sidenav/client/sortlist.js b/app/ui-sidenav/client/sortlist.js deleted file mode 100644 index 23144008b15e..000000000000 --- a/app/ui-sidenav/client/sortlist.js +++ /dev/null @@ -1,52 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { Template } from 'meteor/templating'; - -import { popover } from '../../ui-utils'; -import { getUserPreference } from '../../utils'; -import { settings } from '../../settings'; - -const checked = function(prop, field) { - const userId = Meteor.userId(); - - if (prop === 'sidebarShowDiscussion') { - return getUserPreference(userId, 'sidebarShowDiscussion'); - } - if (prop === 'sidebarShowFavorites') { - return getUserPreference(userId, 'sidebarShowFavorites'); - } - if (prop === 'sidebarGroupByType') { - return getUserPreference(userId, 'sidebarGroupByType'); - } - if (prop === 'sidebarShowUnread') { - return getUserPreference(userId, 'sidebarShowUnread'); - } - if (prop === 'sidebarSortby') { - return (getUserPreference(userId, 'sidebarSortby') || 'alphabetical') === field; - } -}; - -Template.sortlist.helpers({ - favorite() { - return settings.get('Favorite_Rooms'); - }, - checked, - bold(...props) { - return checked(...props) ? 'rc-popover__item--bold' : ''; - }, -}); - -Template.sortlist.events({ - 'change input'({ currentTarget }) { - const name = currentTarget.getAttribute('name'); - let value = currentTarget.getAttribute('type') === 'checkbox' ? currentTarget.checked : currentTarget.value; - - // TODO change mergeChannels to GroupByType - if (name === 'mergeChannels') { - value = !value; - } - Meteor.call('saveUserPreferences', { - [name]: value, - }); - popover.close(); - }, -}); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index c59ff966b502..1362ff6b4bd3 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1657,6 +1657,7 @@ "Group_favorites": "Group favorites", "Group_mentions_disabled_x_members": "Group mentions `@all` and `@here` have been disabled for rooms with more than __total__ members.", "Group_mentions_only": "Group mentions only", + "Grouping": "Grouping", "Hash": "Hash", "Header": "Header", "Header_and_Footer": "Header and Footer", @@ -3105,6 +3106,7 @@ "Social_Network": "Social Network", "Sorry_page_you_requested_does_not_exist_or_was_deleted": "Sorry, page you requested does not exist or was deleted!", "Sort": "Sort", + "Sort_By": "Sort by", "Sort_by_activity": "Sort by Activity", "Sound": "Sound", "Sound_File_mp3": "Sound File (mp3)", From 146b30f29b50a3750c238d44697f8c00ebebefa6 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 30 Mar 2020 02:52:16 -0300 Subject: [PATCH 12/26] directory ui improve --- .../app/components/Directory/ChannelsTab.js | 22 +++++++------ .../components/Directory/DirectoryTable.js | 2 +- .../views/app/components/Directory/UserTab.js | 32 +++++++++++-------- app/ui/client/views/app/components/hooks.js | 17 ++++++++++ client/components/basic/Page.js | 4 +-- 5 files changed, 51 insertions(+), 26 deletions(-) diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index ba51eca08615..f479a5afec7e 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -5,7 +5,7 @@ import { useEndpointData } from '../../../../../../../ee/app/engagement-dashboar import { DirectoryTable, Th } from './DirectoryTable'; import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; import { useRoute } from '../../../../../../../client/contexts/RouterContext'; -import { useQuery, useFormatDate } from '../hooks'; +import { useQuery, useFormatDate, useMediaQuery } from '../hooks'; const style = { whiteSpace: 'nowrap' }; @@ -22,6 +22,8 @@ export function ChannelsTab() { const [sort, setSort] = useState(['name', 'asc']); const [params, setParams] = useState({}); + const mediaQuery = useMediaQuery('(min-width: 768px)'); + const query = useQuery(params, sort, 'channels'); const onHeaderClick = useCallback((id) => { @@ -36,10 +38,10 @@ export function ChannelsTab() { const header = useMemo(() => [
, - , - , - , - ], [sort]); + , + mediaQuery && , + mediaQuery && , + ].filter(Boolean), [sort, mediaQuery]); const go = useRoute('channel'); @@ -75,14 +77,14 @@ export function ChannelsTab() { {usersCount} - + { mediaQuery && {formatDate(ts)} - - + } + { mediaQuery && {lastMessage && formatDate(lastMessage.ts)} - + } - , []); + , [mediaQuery]); return ; } diff --git a/app/ui/client/views/app/components/Directory/DirectoryTable.js b/app/ui/client/views/app/components/Directory/DirectoryTable.js index 05b3fc1f55c3..07922f28d8c8 100644 --- a/app/ui/client/views/app/components/Directory/DirectoryTable.js +++ b/app/ui/client/views/app/components/Directory/DirectoryTable.js @@ -11,7 +11,7 @@ function SortIcon({ direction }) { ; } -export function Th({ children, active, direction, sort, onClick, ...props }) { +export function Th({ children, active, direction, sort, onClick, align, ...props }) { const fn = useMemo(() => () => onClick && onClick(sort), [sort, onClick]); return diff --git a/app/ui/client/views/app/components/Directory/UserTab.js b/app/ui/client/views/app/components/Directory/UserTab.js index d376cc3b8715..8df95b1cd64a 100644 --- a/app/ui/client/views/app/components/Directory/UserTab.js +++ b/app/ui/client/views/app/components/Directory/UserTab.js @@ -7,9 +7,11 @@ import { DirectoryTable, Th } from './DirectoryTable'; import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; import { useRoute } from '../../../../../../../client/contexts/RouterContext'; import { usePermission } from '../../../../../../../client/contexts/AuthorizationContext'; -import { useQuery, useFormatDate } from '../hooks'; +import { useQuery, useFormatDate, useMediaQuery } from '../hooks'; -const style = { whiteSpace: 'nowrap' }; +const style = { whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }; + +const bioStyle = { ...style, maxWidth: '200px' }; export function UserTab({ workspace = 'local', @@ -23,6 +25,8 @@ export function UserTab({ const query = useQuery(params, sort, 'users', workspace); + const mediaQuery = useMediaQuery('(min-width: 1024px)'); + const onHeaderClick = (id) => { const [sortBy, sortDirection] = sort; @@ -35,11 +39,11 @@ export function UserTab({ const header = useMemo(() => [ , - , - canViewFullOtherUserInfo && , - federation && , - , - ].filter(Boolean), [federation, canViewFullOtherUserInfo]); + , + mediaQuery && canViewFullOtherUserInfo && , + federation && , + mediaQuery && , + ].filter(Boolean), [sort, federation, canViewFullOtherUserInfo, mediaQuery]); const go = useRoute('direct'); @@ -73,10 +77,12 @@ export function UserTab({ - - {bio} + + + {bio} + - {canViewFullOtherUserInfo + {mediaQuery && canViewFullOtherUserInfo && {emails && emails[0].address} } @@ -84,10 +90,10 @@ export function UserTab({ && {domain} } - + {mediaQuery && {formatDate(createdAt)} - - , []); + } + , [mediaQuery, federation, canViewFullOtherUserInfo]); return ; } diff --git a/app/ui/client/views/app/components/hooks.js b/app/ui/client/views/app/components/hooks.js index 37c5b94d3041..92ef5c55bb54 100644 --- a/app/ui/client/views/app/components/hooks.js +++ b/app/ui/client/views/app/components/hooks.js @@ -17,6 +17,23 @@ export function useDebounce(value, delay) { return debouncedValue; } +export function useMediaQuery(query) { + const [matches, setQuery] = useState(window.matchMedia(query).matches); + + useEffect(() => { + const resizeObserver = new ResizeObserver(() => { + setQuery(window.matchMedia(query).matches); + }); + resizeObserver.observe(document.body); + + return () => { + resizeObserver.unobserve(document.body); + }; + }, [query]); + + return matches; +} + export function useQuery(params, sort, type, workspace = 'local') { return useMemo(() => ({ query: JSON.stringify({ diff --git a/client/components/basic/Page.js b/client/components/basic/Page.js index e89ffbd19d34..d87cc9541350 100644 --- a/client/components/basic/Page.js +++ b/client/components/basic/Page.js @@ -16,9 +16,9 @@ export function Page(props) { export function PageHeader({ children, title, ...props }) { const [border] = useContext(PageContext); return - + - + From ffe552d41744d2e77549111d0ad4ab02f2f8f693 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 30 Mar 2020 12:29:04 -0300 Subject: [PATCH 13/26] revert account to blaze --- app/ui-account/client/accountProfile.html | 25 ++++++++++++++++++++-- app/ui-account/client/accountProfile.js | 3 +++ app/ui-sidenav/client/sidebarHeader.js | 2 +- packages/rocketchat-i18n/i18n/en.i18n.json | 3 +++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/app/ui-account/client/accountProfile.html b/app/ui-account/client/accountProfile.html index d160300f1c9c..671c42a9054b 100644 --- a/app/ui-account/client/accountProfile.html +++ b/app/ui-account/client/accountProfile.html @@ -111,11 +111,32 @@
{{# with canChange=allowStatusMessageChange}} - {{> Input onChangeValue=(set 'statusText') value=(get 'statusText') label=(_ 'StatusMessage') maxLength="120" placeholder=(_ 'StatusMessage_Placeholder') _id='statusText' key='statusText' name='statusText' addon='edit' disabled=(ifThenElse canChange false true) hint=(ifThenElse canChange false (_ 'StatusMessage_Change_Disabled')) }} +
+ + {{# unless canChange}} +
{{_ 'StatusMessage_Change_Disabled'}}
+ {{/unless}} +
{{/with}}
- {{> Input onChangeValue=(set 'bio') value=(get 'bio') multiline=true label=(_ 'Bio') placeholder=(_ 'User_bio') _id='bio' key='bio' }} +
+ +
{{#with canChange=allowEmailChange}} diff --git a/app/ui-account/client/accountProfile.js b/app/ui-account/client/accountProfile.js index 27bf103b0a8c..623c75979693 100644 --- a/app/ui-account/client/accountProfile.js +++ b/app/ui-account/client/accountProfile.js @@ -426,6 +426,9 @@ Template.accountProfile.events({ instance.confirmationPassword.set(''); } }, + 'input [name=bio], input [name=statusText]'(e, instance) { + instance.fields.set(e.target.name, e.target.value); + }, 'input [name=confirmation-password]'(e, instance) { instance.confirmationPassword.set(e.target.value); }, diff --git a/app/ui-sidenav/client/sidebarHeader.js b/app/ui-sidenav/client/sidebarHeader.js index 9a5ae2c379d9..a75ce5bd7c81 100644 --- a/app/ui-sidenav/client/sidebarHeader.js +++ b/app/ui-sidenav/client/sidebarHeader.js @@ -229,7 +229,7 @@ Template.sidebarHeader.helpers({ } }); }, toolbarButtons() { - return toolbarButtons(Meteor.userId()).filter((button) => !button.condition || button.condition()); + return toolbarButtons(/* Meteor.userId() */).filter((button) => !button.condition || button.condition()); }, showToolbar() { return showToolbar.get(); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 2f838378fba1..703ec2dd4124 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -519,6 +519,8 @@ "Blockstack_ButtonLabelText": "Button label text", "Blockstack_Generate_Username": "Generate username", "Body": "Body", + "Bio": "Bio", + "Bio_Placeholder": "Bio Placeholder", "bold": "bold", "bot_request": "Bot request", "BotHelpers_userFields": "User Fields", @@ -1939,6 +1941,7 @@ "Join_the_given_channel": "Join the given channel", "Join_video_call": "Join video call", "Joined": "Joined", + "Joined_at": "Joined at", "Jump": "Jump", "Jump_to_first_unread": "Jump to first unread", "Jump_to_message": "Jump to Message", From b0aecadd9b2b3607e9f725a686f4cc6c4accbcf5 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 30 Mar 2020 14:08:12 -0300 Subject: [PATCH 14/26] useMediaQuery --- .../views/app/components/Directory/ChannelsTab.js | 9 +++++---- .../views/app/components/Directory/DirectoryTable.js | 2 +- .../client/views/app/components/Directory/UserTab.js | 12 ++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index f479a5afec7e..08f0c206c491 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -1,13 +1,14 @@ import React, { useMemo, useState, useCallback } from 'react'; import { Box, Margins, Table, Flex, Avatar, Tag } from '@rocket.chat/fuselage'; +import { useMediaQuery } from '@rocket.chat/fuselage-hooks'; import { useEndpointData } from '../../../../../../../ee/app/engagement-dashboard/client/hooks/useEndpointData'; import { DirectoryTable, Th } from './DirectoryTable'; import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; import { useRoute } from '../../../../../../../client/contexts/RouterContext'; -import { useQuery, useFormatDate, useMediaQuery } from '../hooks'; +import { useQuery, useFormatDate } from '../hooks'; -const style = { whiteSpace: 'nowrap' }; +const style = { whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }; function RoomTags({ room }) { const t = useTranslation(); @@ -66,8 +67,8 @@ export function ChannelsTab() { - {fname || name} - {topic && {topic} } + {fname || name} + {topic && {topic} } diff --git a/app/ui/client/views/app/components/Directory/DirectoryTable.js b/app/ui/client/views/app/components/Directory/DirectoryTable.js index 07922f28d8c8..0a29012252a4 100644 --- a/app/ui/client/views/app/components/Directory/DirectoryTable.js +++ b/app/ui/client/views/app/components/Directory/DirectoryTable.js @@ -88,7 +88,7 @@ export function DirectoryTable({ {t('No_data_found')} : <> -
{t('Name')}{t('Email')}{t('Domain')}{t('Joined_at')}{t('Name')}{t('Email')}{t('Domain')}{t('Joined_at')}{t('Name')}{t('Email')}{t('Domain')}{t('Joined_at')}{t('Name')}{t('Bio')}{t('Email')}{t('Domain')}{t('Joined_at')}{t('Users')}{t('Created_at')}{t('Last_Message')}{t('Topic')} {t('Name')}{t('Users')}{t('Created_at')}{t('Last_Message')}{t('Users')}{t('Created_at')}{t('Last_Message')}{t('Name')}{t('Bio')}{t('Email')}{t('Domain')}{t('Joined_at')}{t('Bio')}{t('Email')}{t('Domain')}{t('Joined_at')}
+
{ header && {header} diff --git a/app/ui/client/views/app/components/Directory/UserTab.js b/app/ui/client/views/app/components/Directory/UserTab.js index 8df95b1cd64a..725b74e625d8 100644 --- a/app/ui/client/views/app/components/Directory/UserTab.js +++ b/app/ui/client/views/app/components/Directory/UserTab.js @@ -1,18 +1,16 @@ import React, { useMemo, useState, useCallback } from 'react'; import { Box, Margins, Table, Flex, Avatar } from '@rocket.chat/fuselage'; - +import { useMediaQuery } from '@rocket.chat/fuselage-hooks'; import { useEndpointData } from '../../../../../../../ee/app/engagement-dashboard/client/hooks/useEndpointData'; import { DirectoryTable, Th } from './DirectoryTable'; import { useTranslation } from '../../../../../../../client/contexts/TranslationContext'; import { useRoute } from '../../../../../../../client/contexts/RouterContext'; import { usePermission } from '../../../../../../../client/contexts/AuthorizationContext'; -import { useQuery, useFormatDate, useMediaQuery } from '../hooks'; +import { useQuery, useFormatDate } from '../hooks'; const style = { whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }; -const bioStyle = { ...style, maxWidth: '200px' }; - export function UserTab({ workspace = 'local', }) { @@ -36,10 +34,11 @@ export function UserTab({ } setSort([id, 'asc']); }; + const bioStyle = useMemo(() => ({ ...style, width: '200px' }), [mediaQuery]); const header = useMemo(() => [ , - , + , mediaQuery && canViewFullOtherUserInfo && , federation && , mediaQuery && , @@ -55,6 +54,7 @@ export function UserTab({ } }, []); + const formatDate = useFormatDate(); const renderRow = useCallback(({ createdAt, emails, _id, username, name, domain, bio }) => @@ -68,7 +68,7 @@ export function UserTab({ - + {name || username} {name && username} From 41db4ee76481f8be5a3663d07a50a3c12b8ccbd6 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 30 Mar 2020 14:21:37 -0300 Subject: [PATCH 15/26] return routes --- app/ui-account/client/accountProfile.js | 10 ---------- client/routes.js | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/app/ui-account/client/accountProfile.js b/app/ui-account/client/accountProfile.js index 623c75979693..035358f2bd7d 100644 --- a/app/ui-account/client/accountProfile.js +++ b/app/ui-account/client/accountProfile.js @@ -189,19 +189,9 @@ Template.accountProfile.helpers({ get(field) { return Template.instance().fields.get(field); }, - set(field) { - const instance = Template.instance(); - const fn = (value) => instance.fields.set(field, value); - if (!instance.set[field]) { // avoid react rerender - instance.set[field] = () => fn; - } - return instance.set[field]; - }, }); Template.accountProfile.onCreated(function() { - this.set = {}; - const user = Meteor.user(); this.fields = new ReactiveDict({ diff --git a/client/routes.js b/client/routes.js index d49ee0cee075..b14945c4ac8b 100644 --- a/client/routes.js +++ b/client/routes.js @@ -62,7 +62,7 @@ export const createTemplateForComponent = async ( const { MeteorProvider } = await import('./providers/MeteorProvider'); function TemplateComponent() { - return React.createElement(component, Template.currentData()); + return React.createElement(component, Template[name].props.get()); } Template[name].onRendered(() => { From 583179419bae8af361c72eef7004fcb7d41b000e Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 30 Mar 2020 14:50:58 -0300 Subject: [PATCH 16/26] fix member list --- app/ui-flextab/client/tabs/membersList.js | 17 +++-------------- server/methods/getUsersOfRoom.js | 14 ++++++++++---- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/app/ui-flextab/client/tabs/membersList.js b/app/ui-flextab/client/tabs/membersList.js index ac77958a13c6..bd1797578ab8 100644 --- a/app/ui-flextab/client/tabs/membersList.js +++ b/app/ui-flextab/client/tabs/membersList.js @@ -40,17 +40,6 @@ Template.membersList.helpers({ let totalOnline = 0; let users = roomUsers; - const filter = Template.instance().filter.get(); - let reg = null; - try { - reg = new RegExp(filter, 'i'); - } catch (e) { - console.log(e); - } - if (filter && reg) { - users = users.filter((user) => reg.test(user.username) || reg.test(user.name)); - } - users = users.map(function(user) { let utcOffset; if (onlineUsers[user.username] != null) { @@ -247,10 +236,10 @@ Template.membersList.events({ }, 'click .show-more-users'(e, instance) { - const { showAllUsers, usersLimit, users, total, loadingMore } = instance; + const { showAllUsers, usersLimit, users, total, loadingMore, filter } = instance; loadingMore.set(true); - Meteor.call('getUsersOfRoom', this.rid, showAllUsers.get(), { limit: usersLimit.get() + 100, skip: 0 }, (error, result) => { + Meteor.call('getUsersOfRoom', this.rid, showAllUsers.get(), { limit: usersLimit.get() + 100, skip: 0 }, filter.get(), (error, result) => { if (error) { console.error(error); loadingMore.set(false); @@ -283,7 +272,7 @@ Template.membersList.onCreated(function() { this.autorun(() => { if (this.data.rid == null) { return; } this.loading.set(true); - return Meteor.call('getUsersOfRoom', this.data.rid, this.showAllUsers.get(), { limit: 100, skip: 0 }, (error, users) => { + return Meteor.call('getUsersOfRoom', this.data.rid, this.showAllUsers.get(), { limit: 100, skip: 0 }, this.filter.get(), (error, users) => { if (error) { console.error(error); this.loading.set(false); diff --git a/server/methods/getUsersOfRoom.js b/server/methods/getUsersOfRoom.js index 951e76091e88..43e2a8dca8b3 100644 --- a/server/methods/getUsersOfRoom.js +++ b/server/methods/getUsersOfRoom.js @@ -1,12 +1,16 @@ import { Meteor } from 'meteor/meteor'; +import s from 'underscore.string'; import { Subscriptions } from '../../app/models'; import { hasPermission } from '../../app/authorization'; import { settings } from '../../app/settings'; -function findUsers({ rid, status, skip, limit }) { +function findUsers({ rid, status, skip, limit, filter = '' }) { + const regex = new RegExp(s.trim(s.escapeRegExp(filter)), 'i'); return Subscriptions.model.rawCollection().aggregate([ - { $match: { rid } }, + { + $match: { rid }, + }, { $lookup: { @@ -25,6 +29,7 @@ function findUsers({ rid, status, skip, limit }) { }, }, ...status ? [{ $match: { 'u.status': status } }] : [], + ...filter.trim() ? [{ $match: { $or: [{ 'u.name': regex }, { 'u.username': regex }] } }] : [], { $sort: { [settings.get('UI_Use_Real_Name') ? 'u.name' : 'u.username']: 1, @@ -43,7 +48,7 @@ function findUsers({ rid, status, skip, limit }) { } Meteor.methods({ - async getUsersOfRoom(rid, showAll, { limit, skip } = {}) { + async getUsersOfRoom(rid, showAll, { limit, skip } = {}, filter) { const userId = Meteor.userId(); if (!userId) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getUsersOfRoom' }); @@ -59,13 +64,14 @@ Meteor.methods({ } const total = Subscriptions.findByRoomIdWhenUsernameExists(rid).count(); - const users = await findUsers({ rid, status: { $ne: 'offline' }, limit, skip }); + const users = await findUsers({ rid, status: { $ne: 'offline' }, limit, skip, filter }); if (showAll && (!limit || users.length < limit)) { const offlineUsers = await findUsers({ rid, status: { $eq: 'offline' }, limit: limit ? limit - users.length : 0, skip: skip || 0, + filter, }); return { From 2c1fd0857753f5252c31881cdfb16540e983c93d Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 30 Mar 2020 19:13:00 -0300 Subject: [PATCH 17/26] fix text overflow --- app/lib/server/functions/saveUser.js | 20 ++++++++++--------- .../views/app/components/Directory/UserTab.js | 8 ++++---- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/lib/server/functions/saveUser.js b/app/lib/server/functions/saveUser.js index e4f44b78cdec..d70cf13f549e 100644 --- a/app/lib/server/functions/saveUser.js +++ b/app/lib/server/functions/saveUser.js @@ -194,16 +194,18 @@ function validateUserEditing(userId, userData) { } const handleBio = (updateUser, bio) => { - if (bio && bio.trim()) { - if (typeof bio !== 'string') { - throw new Meteor.Error('error-invalid-field', 'bio', { - method: 'saveUserProfile', - }); + if (bio) { + if (bio.trim()) { + if (typeof bio !== 'string') { + throw new Meteor.Error('error-invalid-field', 'bio', { + method: 'saveUserProfile', + }); + } + updateUser.$set.bio = bio; + } else { + updateUser.$unset = updateUser.$unset || {}; + updateUser.$unset.bio = 1; } - updateUser.$set.bio = bio; - } else { - updateUser.$unset = updateUser.$unset || {}; - updateUser.$unset.bio = 1; } }; diff --git a/app/ui/client/views/app/components/Directory/UserTab.js b/app/ui/client/views/app/components/Directory/UserTab.js index 725b74e625d8..4a782b0e93fa 100644 --- a/app/ui/client/views/app/components/Directory/UserTab.js +++ b/app/ui/client/views/app/components/Directory/UserTab.js @@ -69,8 +69,8 @@ export function UserTab({ - {name || username} - {name && username} + {name || username} + {name && username} @@ -83,11 +83,11 @@ export function UserTab({ {mediaQuery && canViewFullOtherUserInfo - && + && {emails && emails[0].address} } {federation - && + && {domain} } {mediaQuery && From 6233d910e1580bae02fad5461322d02a10b858ae Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Mon, 30 Mar 2020 21:34:04 -0300 Subject: [PATCH 18/26] Use text index to search for users --- app/lib/server/startup/settings.js | 2 +- app/models/server/models/Users.js | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/app/lib/server/startup/settings.js b/app/lib/server/startup/settings.js index 399554c8e9b0..597e9f3efaad 100644 --- a/app/lib/server/startup/settings.js +++ b/app/lib/server/startup/settings.js @@ -97,7 +97,7 @@ settings.addGroup('Accounts', function() { type: 'boolean', public: true, }); - this.add('Accounts_SearchFields', 'username, name, bio', { + this.add('Accounts_SearchFields', '', { type: 'string', public: true, }); diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js index d711d9a4d8a4..d665e5929631 100644 --- a/app/models/server/models/Users.js +++ b/app/models/server/models/Users.js @@ -30,7 +30,7 @@ export class Users extends Base { this.tryEnsureIndex({ roles: 1 }, { sparse: 1 }); this.tryEnsureIndex({ name: 1 }); - this.tryEnsureIndex({ bio: 1 }); + this.tryEnsureIndex({ name: 'text', username: 'text', bio: 'text' }, { default_language: 'none', language_override: 'documentLanguage' }); this.tryEnsureIndex({ createdAt: 1 }); this.tryEnsureIndex({ lastLogin: 1 }); this.tryEnsureIndex({ status: 1 }); @@ -680,16 +680,19 @@ export class Users extends Base { const searchFields = forcedSearchFields || settings.get('Accounts_SearchFields').trim().split(','); const orStmt = _.reduce(searchFields, function(acc, el) { - acc.push({ [el.trim()]: termRegex }); + if (!['name', 'username', 'bio'].includes(el.trim())) { + acc.push({ [el.trim()]: termRegex }); + } return acc; }, []); + const query = { $and: [ { active: true, - $or: orStmt, - }, - { + $or: [{ + $text: { $search: searchTerm }, + }, ...orStmt], username: { $exists: true, $nin: exceptions }, }, ...extraQuery, From bc576df03be6d75aef16ce4cc3773b6e968c3e23 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Mon, 30 Mar 2020 22:06:16 -0300 Subject: [PATCH 19/26] Fix tests --- app/models/server/models/Users.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js index d665e5929631..abcdfc3996f6 100644 --- a/app/models/server/models/Users.js +++ b/app/models/server/models/Users.js @@ -680,8 +680,9 @@ export class Users extends Base { const searchFields = forcedSearchFields || settings.get('Accounts_SearchFields').trim().split(','); const orStmt = _.reduce(searchFields, function(acc, el) { - if (!['name', 'username', 'bio'].includes(el.trim())) { - acc.push({ [el.trim()]: termRegex }); + el = el.trim(); + if (el && !['name', 'username', 'bio'].includes(el)) { + acc.push({ [el]: termRegex }); } return acc; }, []); From 5498b3e1e0c9de5f6fcd0d8d1977eab225a8fee2 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 30 Mar 2020 23:21:10 -0300 Subject: [PATCH 20/26] update fuselage --- package-lock.json | 941 +++------------------------------------------- package.json | 12 +- 2 files changed, 56 insertions(+), 897 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0776a1b1a55f..12ebb5844d59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2372,8 +2372,7 @@ "@emotion/stylis": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==", - "dev": true + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" }, "@emotion/unitless": { "version": "0.7.4", @@ -2542,6 +2541,11 @@ "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", "dev": true }, + "@juggle/resize-observer": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.1.2.tgz", + "integrity": "sha512-Yao5AFq8HKHsyLCLZn15BybqN67cdbgDbVDnnaN54IUaffkwDHj0VMgBp1C/IxOsFsNltsI7LdnW4GEHmQarLQ==" + }, "@kossnocorp/desvg": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@kossnocorp/desvg/-/desvg-0.2.0.tgz", @@ -2865,6 +2869,22 @@ } } }, + "@rocket.chat/css-in-js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@rocket.chat/css-in-js/-/css-in-js-0.6.2.tgz", + "integrity": "sha512-zcuqSqdhq6EvlJJctQkO/UG56b08DA19ERdA/mnFOlXZCFD+yba3ByUHOOLXtgN45M04Qj5zZuIheGzoa+asfQ==", + "requires": { + "@emotion/hash": "^0.8.0", + "@emotion/stylis": "^0.8.5" + }, + "dependencies": { + "@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + } + } + }, "@rocket.chat/eslint-config": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@rocket.chat/eslint-config/-/eslint-config-0.3.0.tgz", @@ -2875,907 +2895,46 @@ } }, "@rocket.chat/fuselage": { - "version": "0.6.1", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.6.2.tgz", + "integrity": "sha512-BvaoYgp4eTPv0+3sCzYMQelye4cQ/f5GRFlASFFL6kRevvczNaR/RPUKPH1oIHsbEbfioBRw9WsUjqfZ0qo8NQ==", "requires": { - "@rocket.chat/css-in-js": "^0.6.1", - "@rocket.chat/fuselage-tokens": "^0.6.1", - "@rocket.chat/icons": "^0.6.1" - }, - "dependencies": { - "@babel/generator": { - "version": "7.7.4", - "requires": { - "source-map": "^0.5.0" - } - }, - "@babel/parser": { - "version": "7.7.5" - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.7.4" - }, - "@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" - }, - "@emotion/stylis": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", - "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" - }, - "@rocket.chat/css-in-js": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/css-in-js/-/css-in-js-0.6.1.tgz", - "integrity": "sha512-LNvPIj06YQmEI7kl1RFHAOk6ts95lCczafl5Nqx5jXo5SY8XKCjrR0qK1awD5sTSU9mGrDv/rE3tPTKbQPIH6A==", - "requires": { - "@emotion/hash": "^0.8.0", - "@emotion/stylis": "^0.8.5" - } - }, - "@rocket.chat/fuselage-tokens": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.6.1.tgz", - "integrity": "sha512-8G3h9PTT6I57wddxvJCBqLmGJwzce3v6cSTOjcvnMAQ8xYEjY+NXK2Asq/Xh4Nxwhqwl7vsQLHbBz6XBCNqWZQ==" - }, - "@rocket.chat/icons": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.6.1.tgz", - "integrity": "sha512-uXg4oXscOQKhNP5DxF/O5f9zG8rKfLVJoXzv3AhNf/YGutqwUzLUCzt3O6bO2aeL43GjdfhxD9tZnpZlviZM9Q==" - }, - "@storybook/addon-actions": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/api": "5.2.8", - "@storybook/client-api": "5.2.8", - "@storybook/components": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/theming": "5.2.8", - "react": "^16.8.3", - "react-inspector": "^3.0.2" - }, - "dependencies": { - "@storybook/components": { - "version": "5.2.8", - "requires": { - "@storybook/theming": "5.2.8", - "markdown-to-jsx": "^6.9.1", - "react": "^16.8.3", - "react-dom": "^16.8.3", - "react-focus-lock": "^1.18.3", - "react-helmet-async": "^1.0.2", - "react-popper-tooltip": "^2.8.3", - "react-syntax-highlighter": "^8.0.1", - "react-textarea-autosize": "^7.1.0", - "simplebar-react": "^1.0.0-alpha.6" - }, - "dependencies": { - "react-dom": { - "version": "16.11.0", - "dependencies": { - "scheduler": { - "version": "0.18.0" - } - } - }, - "react-helmet-async": { - "version": "1.0.4" - }, - "react-popper-tooltip": { - "version": "2.10.0", - "requires": { - "react-popper": "^1.3.4" - } - }, - "simplebar-react": { - "version": "1.2.3" - } - } - }, - "create-react-context": { - "version": "0.3.0" - }, - "markdown-to-jsx": { - "version": "6.10.3" - }, - "react": { - "version": "16.11.0" - }, - "react-clientside-effect": { - "version": "1.2.2" - }, - "react-focus-lock": { - "version": "1.19.1", - "requires": { - "react-clientside-effect": "^1.2.0" - } - }, - "react-inspector": { - "version": "3.0.2" - }, - "react-popper": { - "version": "1.3.6", - "requires": { - "create-react-context": "^0.3.0" - } - }, - "react-syntax-highlighter": { - "version": "8.1.0" - }, - "react-textarea-autosize": { - "version": "7.1.2" - }, - "scheduler": { - "version": "0.17.0" - } - } - }, - "@storybook/addon-backgrounds": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/api": "5.2.8", - "@storybook/components": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/theming": "5.2.8", - "react": "^16.8.3" - }, - "dependencies": { - "@storybook/components": { - "version": "5.2.8", - "requires": { - "@storybook/theming": "5.2.8", - "markdown-to-jsx": "^6.9.1", - "react": "^16.8.3", - "react-dom": "^16.8.3", - "react-focus-lock": "^1.18.3", - "react-helmet-async": "^1.0.2", - "react-popper-tooltip": "^2.8.3", - "react-syntax-highlighter": "^8.0.1", - "react-textarea-autosize": "^7.1.0", - "simplebar-react": "^1.0.0-alpha.6" - }, - "dependencies": { - "react-dom": { - "version": "16.11.0", - "dependencies": { - "scheduler": { - "version": "0.18.0" - } - } - }, - "react-helmet-async": { - "version": "1.0.4" - }, - "react-popper-tooltip": { - "version": "2.10.0", - "requires": { - "react-popper": "^1.3.4" - } - }, - "simplebar-react": { - "version": "1.2.3" - } - } - }, - "create-react-context": { - "version": "0.3.0" - }, - "markdown-to-jsx": { - "version": "6.10.3" - }, - "react": { - "version": "16.11.0" - }, - "react-clientside-effect": { - "version": "1.2.2" - }, - "react-focus-lock": { - "version": "1.19.1", - "requires": { - "react-clientside-effect": "^1.2.0" - } - }, - "react-popper": { - "version": "1.3.6", - "requires": { - "create-react-context": "^0.3.0" - } - }, - "react-syntax-highlighter": { - "version": "8.1.0" - }, - "react-textarea-autosize": { - "version": "7.1.2" - }, - "scheduler": { - "version": "0.17.0" - } - } - }, - "@storybook/addon-centered": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8" - } - }, - "@storybook/addon-docs": { - "version": "5.2.8", - "requires": { - "@babel/generator": "^7.7.2", - "@babel/parser": "^7.7.3", - "@storybook/addons": "5.2.8", - "@storybook/api": "5.2.8", - "@storybook/components": "5.2.8", - "@storybook/router": "5.2.8", - "@storybook/source-loader": "5.2.8", - "@storybook/theming": "5.2.8" - } - }, - "@storybook/addon-jest": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/api": "5.2.8", - "@storybook/components": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/theming": "5.2.8", - "react": "^16.8.3", - "react-sizeme": "^2.5.2" - }, - "dependencies": { - "react": { - "version": "16.11.0" - }, - "react-sizeme": { - "version": "2.6.10" - } - } - }, - "@storybook/addon-knobs": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/api": "5.2.8", - "@storybook/client-api": "5.2.8", - "@storybook/components": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/theming": "5.2.8" - } - }, - "@storybook/addon-links": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/router": "5.2.8" - } - }, - "@storybook/addon-options": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8" - } - }, - "@storybook/addon-viewport": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/api": "5.2.8", - "@storybook/components": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/theming": "5.2.8" - } - }, - "@storybook/addons": { - "version": "5.2.8", - "requires": { - "@storybook/api": "5.2.8", - "@storybook/channels": "5.2.8", - "@storybook/core-events": "5.2.8" - } - }, - "@storybook/api": { - "version": "5.2.8", - "requires": { - "@storybook/channels": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/router": "5.2.8", - "@storybook/theming": "5.2.8", - "react": "^16.8.3" - }, - "dependencies": { - "react": { - "version": "16.11.0" - } - } - }, - "@storybook/channel-postmessage": { - "version": "5.2.8", - "requires": { - "@storybook/channels": "5.2.8" - } - }, - "@storybook/channels": { - "version": "5.2.8" - }, - "@storybook/client-api": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/channel-postmessage": "5.2.8", - "@storybook/channels": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/router": "5.2.8", - "is-plain-object": "^3.0.0" - } - }, - "@storybook/components": { - "version": "5.2.8", - "requires": { - "@storybook/theming": "5.2.8", - "markdown-to-jsx": "^6.9.1", - "react": "^16.8.3", - "react-dom": "^16.8.3", - "react-focus-lock": "^1.18.3", - "react-helmet-async": "^1.0.2", - "react-popper-tooltip": "^2.8.3", - "react-syntax-highlighter": "^8.0.1", - "react-textarea-autosize": "^7.1.0", - "simplebar-react": "^1.0.0-alpha.6" - }, - "dependencies": { - "create-react-context": { - "version": "0.3.0" - }, - "markdown-to-jsx": { - "version": "6.10.3" - }, - "react": { - "version": "16.11.0" - }, - "react-clientside-effect": { - "version": "1.2.2" - }, - "react-dom": { - "version": "16.11.0", - "dependencies": { - "scheduler": { - "version": "0.18.0" - } - } - }, - "react-focus-lock": { - "version": "1.19.1", - "requires": { - "react-clientside-effect": "^1.2.0" - } - }, - "react-helmet-async": { - "version": "1.0.4" - }, - "react-popper": { - "version": "1.3.6", - "requires": { - "create-react-context": "^0.3.0" - } - }, - "react-popper-tooltip": { - "version": "2.10.0", - "requires": { - "react-popper": "^1.3.4" - } - }, - "react-syntax-highlighter": { - "version": "8.1.0" - }, - "react-textarea-autosize": { - "version": "7.1.2" - }, - "scheduler": { - "version": "0.17.0" - }, - "simplebar-react": { - "version": "1.2.3" - } - } - }, - "@storybook/core": { - "version": "5.2.8", - "requires": { - "@babel/plugin-proposal-object-rest-spread": "^7.6.2", - "@babel/preset-env": "^7.7.1", - "@storybook/addons": "5.2.8", - "@storybook/channel-postmessage": "5.2.8", - "@storybook/client-api": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/node-logger": "5.2.8", - "@storybook/router": "5.2.8", - "@storybook/theming": "5.2.8", - "@storybook/ui": "5.2.8", - "autoprefixer": "^9.4.9", - "find-cache-dir": "^3.0.0", - "resolve": "^1.11.0", - "terser-webpack-plugin": "^1.2.4", - "webpack": "^4.33.0" - }, - "dependencies": { - "@babel/preset-env": { - "version": "7.7.6", - "requires": { - "@babel/plugin-proposal-object-rest-spread": "^7.7.4", - "browserslist": "^4.6.0", - "core-js-compat": "^3.4.7", - "semver": "^5.5.0" - }, - "dependencies": { - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.7.7" - }, - "semver": { - "version": "5.7.1" - } - } - }, - "autoprefixer": { - "version": "9.7.1", - "requires": { - "browserslist": "^4.7.2", - "caniuse-lite": "^1.0.30001006", - "postcss": "^7.0.21", - "postcss-value-parser": "^4.0.2" - }, - "dependencies": { - "browserslist": { - "version": "4.7.3", - "requires": { - "caniuse-lite": "^1.0.30001010", - "node-releases": "^1.1.40" - }, - "dependencies": { - "caniuse-lite": { - "version": "1.0.30001015" - } - } - } - } - }, - "caniuse-lite": { - "version": "1.0.30001012" - }, - "enhanced-resolve": { - "version": "4.1.1", - "requires": { - "memory-fs": "^0.5.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0" - } - } - }, - "find-cache-dir": { - "version": "3.2.0", - "requires": { - "make-dir": "^3.0.0", - "pkg-dir": "^4.1.0" - } - }, - "node-releases": { - "version": "1.1.42" - }, - "postcss": { - "version": "7.0.23", - "requires": { - "source-map": "^0.6.1" - } - }, - "serialize-javascript": { - "version": "1.9.1" - }, - "source-map": { - "version": "0.6.1" - }, - "terser-webpack-plugin": { - "version": "1.4.1", - "requires": { - "find-cache-dir": "^2.1.0", - "serialize-javascript": "^1.7.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "find-cache-dir": { - "version": "2.1.0", - "requires": { - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "requires": { - "semver": "^5.6.0" - } - }, - "pkg-dir": { - "version": "3.0.0" - }, - "semver": { - "version": "5.7.1" - } - } - }, - "webpack": { - "version": "4.41.2", - "requires": { - "acorn": "^6.2.1", - "enhanced-resolve": "^4.1.0", - "terser-webpack-plugin": "^1.4.1" - }, - "dependencies": { - "find-cache-dir": { - "version": "2.1.0", - "requires": { - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "requires": { - "semver": "^5.6.0" - } - }, - "pkg-dir": { - "version": "3.0.0" - }, - "semver": { - "version": "5.7.1" - }, - "serialize-javascript": { - "version": "2.1.2" - }, - "terser-webpack-plugin": { - "version": "1.4.3", - "requires": { - "find-cache-dir": "^2.1.0", - "serialize-javascript": "^2.1.2", - "source-map": "^0.6.1" - } - }, - "webpack": { - "version": "4.41.4", - "requires": { - "acorn": "^6.2.1", - "enhanced-resolve": "^4.1.0", - "terser-webpack-plugin": "^1.4.3" - } - } - } - } - } - }, - "@storybook/core-events": { - "version": "5.2.8" - }, - "@storybook/node-logger": { - "version": "5.2.8" - }, - "@storybook/react": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/core": "5.2.8", - "@storybook/node-logger": "5.2.8", - "mini-css-extract-plugin": "^0.7.0", - "webpack": "^4.33.0" - }, - "dependencies": { - "enhanced-resolve": { - "version": "4.1.1", - "requires": { - "memory-fs": "^0.5.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0" - } - } - }, - "mini-css-extract-plugin": { - "version": "0.7.0" - }, - "webpack": { - "version": "4.41.2", - "requires": { - "acorn": "^6.2.1", - "enhanced-resolve": "^4.1.0", - "terser-webpack-plugin": "^1.4.1" - } - } - } - }, - "@storybook/router": { - "version": "5.2.8" - }, - "@storybook/source-loader": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/router": "5.2.8" - } - }, - "@storybook/theming": { - "version": "5.2.8" - }, - "@storybook/ui": { - "version": "5.2.8", - "requires": { - "@storybook/addons": "5.2.8", - "@storybook/api": "5.2.8", - "@storybook/channels": "5.2.8", - "@storybook/components": "5.2.8", - "@storybook/core-events": "5.2.8", - "@storybook/router": "5.2.8", - "@storybook/theming": "5.2.8", - "markdown-to-jsx": "^6.9.3", - "react": "^16.8.3", - "react-dom": "^16.8.3", - "react-helmet-async": "^1.0.2", - "react-hotkeys": "2.0.0-pre4", - "react-sizeme": "^2.6.7", - "regenerator-runtime": "^0.13.2" - }, - "dependencies": { - "markdown-to-jsx": { - "version": "6.10.3" - }, - "react": { - "version": "16.11.0" - }, - "react-dom": { - "version": "16.11.0", - "requires": { - "scheduler": "^0.17.0" - } - }, - "react-helmet-async": { - "version": "1.0.4" - }, - "react-hotkeys": { - "version": "2.0.0-pre4" - }, - "react-sizeme": { - "version": "2.6.10" - }, - "regenerator-runtime": { - "version": "0.13.3" - }, - "scheduler": { - "version": "0.17.0" - } - } - }, - "acorn": { - "version": "6.4.0" - }, - "autoprefixer": { - "version": "9.7.3", - "requires": { - "browserslist": "^4.8.0", - "caniuse-lite": "^1.0.30001012", - "postcss": "^7.0.23", - "postcss-value-parser": "^4.0.2" - }, - "dependencies": { - "caniuse-lite": { - "version": "1.0.30001015" - } - } - }, - "browserslist": { - "version": "4.8.2", - "requires": { - "caniuse-lite": "^1.0.30001015", - "node-releases": "^1.1.42" - } - }, - "caniuse-lite": { - "version": "1.0.30001016" - }, - "core-js-compat": { - "version": "3.6.0", - "requires": { - "browserslist": "^4.8.2", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0" - } - } - }, - "emoji-regex": { - "version": "7.0.3" - }, - "enhanced-resolve": { - "version": "4.1.0" - }, - "is-plain-object": { - "version": "3.0.0", - "requires": { - "isobject": "^4.0.0" - } - }, - "isobject": { - "version": "4.0.0" - }, - "locate-path": { - "version": "5.0.0", - "requires": { - "p-locate": "^4.1.0" - } - }, - "loki": { - "version": "0.16.0", - "requires": { - "fs-extra": "^7.0.1" - }, - "dependencies": { - "fs-extra": { - "version": "7.0.1" - } - } - }, - "make-dir": { - "version": "3.0.0" - }, - "mini-css-extract-plugin": { - "version": "0.8.2" - }, - "node-releases": { - "version": "1.1.43" - }, - "p-locate": { - "version": "4.1.0" - }, - "path-exists": { - "version": "4.0.0" - }, - "pkg-dir": { - "version": "4.2.0", - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - } - } - }, - "postcss": { - "version": "7.0.24", - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1" - } - } - }, - "postcss-value-parser": { - "version": "4.0.2" - }, - "react-dom": { - "version": "16.12.0", - "requires": { - "scheduler": "^0.18.0" - } - }, - "resolve": { - "version": "1.12.0" - }, - "sass-loader": { - "version": "8.0.0", - "requires": { - "schema-utils": "^2.1.0" - }, - "dependencies": { - "schema-utils": { - "version": "2.6.1" - } - } - }, - "scheduler": { - "version": "0.18.0" - }, - "source-map": { - "version": "0.5.7" - }, - "string-width": { - "version": "3.1.0", - "requires": { - "emoji-regex": "^7.0.1" - } - }, - "terser-webpack-plugin": { - "version": "1.4.3", - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1" - } - } - }, - "webpack": { - "version": "4.41.4", - "requires": { - "acorn": "^6.2.1", - "enhanced-resolve": "^4.1.0", - "terser-webpack-plugin": "^1.4.3" - }, - "dependencies": { - "enhanced-resolve": { - "version": "4.1.1", - "requires": { - "memory-fs": "^0.5.0" - }, - "dependencies": { - "memory-fs": { - "version": "0.5.0" - } - } - } - } - }, - "webpack-cli": { - "version": "3.3.10", - "requires": { - "enhanced-resolve": "4.1.0", - "yargs": "13.2.4" - } - }, - "yargs": { - "version": "13.2.4", - "requires": { - "string-width": "^3.0.0" - } - } + "@rocket.chat/css-in-js": "^0.6.2", + "@rocket.chat/fuselage-tokens": "^0.6.2", + "@rocket.chat/icons": "^0.6.2" } }, "@rocket.chat/fuselage-hooks": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-hooks/-/fuselage-hooks-0.6.1.tgz", - "integrity": "sha512-/M4lqd3D443GgKstncUokNgJYii7BgiaDLlIgV8LhDcWeLPzc2xDlRfrSmFN7MGcazmrwECq5DUmDSnbVsoCyw==" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-hooks/-/fuselage-hooks-0.6.2.tgz", + "integrity": "sha512-43hjN6mlsUE331dq79BKncsfXD8rsoxODgBG6cEn62Y7Ghq5TKE5HYZ7UVPgeVfONarbA7QwyjSjSrNgzDvR+Q==" }, "@rocket.chat/fuselage-polyfills": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-polyfills/-/fuselage-polyfills-0.6.1.tgz", - "integrity": "sha512-vGT8GBRcq1euKv1Q8y9+Zj4UxQwc2L7fkmbcGTzk7BX+wxrmgYhX8cDHXk//Km/itDnwTsQfiwMeuJ/weNorIQ==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-polyfills/-/fuselage-polyfills-0.6.2.tgz", + "integrity": "sha512-S3nxW97C/V9/vo+eS+bPXFvi/Na/0ktmPZREi+K++ZXJAhxAI3+F5KZZKJW8bCXeo4AEfJ9+7KYgDu4mJ29GjA==", "requires": { + "@juggle/resize-observer": "^3.1.2", "focus-visible": "^5.0.2" } }, + "@rocket.chat/fuselage-tokens": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.6.2.tgz", + "integrity": "sha512-PgmagdGzPmh1Dxbkf2YLbPuPjFKYh17CXLuWo0WafxlTrIbMKfw3mq0AJJ1YZrpj6K9tsO6Ty8bIliNRRgXl2A==" + }, "@rocket.chat/fuselage-ui-kit": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.6.1.tgz", - "integrity": "sha512-Pj2vU4NXmZl+WznJVtVWBD9fHDyL5kt1y0rGDteoOobHLrCnJVwSCTvBDcgO4rTlf5seiqV/qTE7Qdo0Fm5vdg==", + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.6.2.tgz", + "integrity": "sha512-b4Q/OG/Xy7IiTvGv0YDFvMcCadGzpb5YG5AX4YhCORTGKHwi1vZYQBPvhsjtfInHUTjAmwPTP6SY2t9ryZ9YjQ==", "requires": { - "@rocket.chat/ui-kit": "^0.6.1" + "@rocket.chat/ui-kit": "^0.6.2" } }, "@rocket.chat/icons": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.6.1.tgz", - "integrity": "sha512-uXg4oXscOQKhNP5DxF/O5f9zG8rKfLVJoXzv3AhNf/YGutqwUzLUCzt3O6bO2aeL43GjdfhxD9tZnpZlviZM9Q==" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.6.2.tgz", + "integrity": "sha512-+INyHScojyrUjiJ7LWwutydFdrxzRK+QRUpT/W1R0nj1TcG4P4ey7xxad2eNt7KNCZ+Hu+AyxOeEHtp8wVEc+w==" }, "@rocket.chat/livechat": { "version": "1.4.0", @@ -3865,9 +3024,9 @@ } }, "@rocket.chat/ui-kit": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@rocket.chat/ui-kit/-/ui-kit-0.6.1.tgz", - "integrity": "sha512-YlcrDZta5CiqIF6F4w+V6zpOGlb/O9vNKctAfnM7YPBnIz2ERnjZ+jkGH5mD6yfLaQa0YMdMseJXofWlLrPayw==" + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@rocket.chat/ui-kit/-/ui-kit-0.6.2.tgz", + "integrity": "sha512-rB2a2gnGZp7wZQaV8qwg9Hqn3ltMzP9DwepRs9vLzeTh/swgpwVXY4ZcbWwaeelZNKpUqDsUxoaQqReToMRAZA==" }, "@samverschueren/stream-to-observable": { "version": "0.3.0", diff --git a/package.json b/package.json index db91f39e9325..ce8d80ed754b 100644 --- a/package.json +++ b/package.json @@ -128,13 +128,13 @@ "@nivo/heatmap": "^0.61.0", "@nivo/line": "^0.61.1", "@nivo/pie": "^0.61.1", - "@rocket.chat/fuselage-polyfills": "^0.6.1", + "@rocket.chat/fuselage-polyfills": "^0.6.2", "@rocket.chat/apps-engine": "^1.13.0-beta.3003", - "@rocket.chat/fuselage": "^0.6.1", - "@rocket.chat/fuselage-hooks": "^0.6.1", - "@rocket.chat/fuselage-ui-kit": "^0.6.1", - "@rocket.chat/icons": "^0.6.1", - "@rocket.chat/ui-kit": "^0.6.1", + "@rocket.chat/fuselage": "^0.6.2", + "@rocket.chat/fuselage-hooks": "^0.6.2", + "@rocket.chat/fuselage-ui-kit": "^0.6.2", + "@rocket.chat/icons": "^0.6.2", + "@rocket.chat/ui-kit": "^0.6.2", "@slack/client": "^4.8.0", "adm-zip": "RocketChat/adm-zip", "archiver": "^3.0.0", From 2862c2d34b999d13c3fb908822a72a546edc7268 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 31 Mar 2020 01:24:07 -0300 Subject: [PATCH 21/26] avatar size --- app/ui/client/views/app/components/Directory/ChannelsTab.js | 2 -- app/ui/client/views/app/components/Directory/DirectoryTable.js | 2 -- app/ui/client/views/app/components/Directory/UserTab.js | 2 -- 3 files changed, 6 deletions(-) diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index 08f0c206c491..78eec4627d94 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -60,9 +60,7 @@ export function ChannelsTab() { - - diff --git a/app/ui/client/views/app/components/Directory/DirectoryTable.js b/app/ui/client/views/app/components/Directory/DirectoryTable.js index 0a29012252a4..a91bc20dc35f 100644 --- a/app/ui/client/views/app/components/Directory/DirectoryTable.js +++ b/app/ui/client/views/app/components/Directory/DirectoryTable.js @@ -25,9 +25,7 @@ const LoadingRow = ({ cols }) => - - diff --git a/app/ui/client/views/app/components/Directory/UserTab.js b/app/ui/client/views/app/components/Directory/UserTab.js index 4a782b0e93fa..5361957e3c62 100644 --- a/app/ui/client/views/app/components/Directory/UserTab.js +++ b/app/ui/client/views/app/components/Directory/UserTab.js @@ -62,9 +62,7 @@ export function UserTab({ - - From 268baafb1cafb61ccbeaec1b7528cac481e9bf89 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Tue, 31 Mar 2020 01:38:40 -0300 Subject: [PATCH 22/26] Fix Lint --- app/ui/client/views/app/components/Directory/ChannelsTab.js | 2 +- app/ui/client/views/app/components/Directory/DirectoryTable.js | 2 +- app/ui/client/views/app/components/Directory/UserTab.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/ui/client/views/app/components/Directory/ChannelsTab.js b/app/ui/client/views/app/components/Directory/ChannelsTab.js index 78eec4627d94..71c0d193bfc4 100644 --- a/app/ui/client/views/app/components/Directory/ChannelsTab.js +++ b/app/ui/client/views/app/components/Directory/ChannelsTab.js @@ -60,7 +60,7 @@ export function ChannelsTab() { - + diff --git a/app/ui/client/views/app/components/Directory/DirectoryTable.js b/app/ui/client/views/app/components/Directory/DirectoryTable.js index a91bc20dc35f..30382c07205f 100644 --- a/app/ui/client/views/app/components/Directory/DirectoryTable.js +++ b/app/ui/client/views/app/components/Directory/DirectoryTable.js @@ -25,7 +25,7 @@ const LoadingRow = ({ cols }) => - + diff --git a/app/ui/client/views/app/components/Directory/UserTab.js b/app/ui/client/views/app/components/Directory/UserTab.js index 5361957e3c62..23924d11f558 100644 --- a/app/ui/client/views/app/components/Directory/UserTab.js +++ b/app/ui/client/views/app/components/Directory/UserTab.js @@ -62,7 +62,7 @@ export function UserTab({ - + From 749b92d3a88b8e0021a77c5b8e00ee18ec3c0119 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 31 Mar 2020 18:25:27 -0300 Subject: [PATCH 23/26] add bio limit to 256 --- app/lib/server/functions/saveUser.js | 2 +- app/ui-account/client/accountProfile.html | 2 +- app/ui-flextab/client/tabs/userEdit.html | 2 +- server/methods/saveUserProfile.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/lib/server/functions/saveUser.js b/app/lib/server/functions/saveUser.js index d70cf13f549e..c0ba977ed116 100644 --- a/app/lib/server/functions/saveUser.js +++ b/app/lib/server/functions/saveUser.js @@ -196,7 +196,7 @@ function validateUserEditing(userId, userData) { const handleBio = (updateUser, bio) => { if (bio) { if (bio.trim()) { - if (typeof bio !== 'string') { + if (typeof bio !== 'string' || bio.length > 256) { throw new Meteor.Error('error-invalid-field', 'bio', { method: 'saveUserProfile', }); diff --git a/app/ui-account/client/accountProfile.html b/app/ui-account/client/accountProfile.html index 671c42a9054b..6a8ade0a4c9f 100644 --- a/app/ui-account/client/accountProfile.html +++ b/app/ui-account/client/accountProfile.html @@ -133,7 +133,7 @@ diff --git a/app/ui-flextab/client/tabs/userEdit.html b/app/ui-flextab/client/tabs/userEdit.html index dceb2fcca362..2e7fe7861a4f 100644 --- a/app/ui-flextab/client/tabs/userEdit.html +++ b/app/ui-flextab/client/tabs/userEdit.html @@ -121,7 +121,7 @@
{{> icon icon='edit' }}
- + diff --git a/server/methods/saveUserProfile.js b/server/methods/saveUserProfile.js index 6beb74ae9d34..ccf3f3b9855e 100644 --- a/server/methods/saveUserProfile.js +++ b/server/methods/saveUserProfile.js @@ -58,7 +58,7 @@ Meteor.methods({ } if (settings.bio) { - if (typeof settings.bio !== 'string') { + if (typeof settings.bio !== 'string' || settings.bio.length > 256) { throw new Meteor.Error('error-invalid-field', 'bio', { method: 'saveUserProfile', }); From c2e44675c6e724f1fd1bf28c9d5b06e256045a99 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 31 Mar 2020 19:15:55 -0300 Subject: [PATCH 24/26] Update app/channel-settings/server/methods/saveRoomSettings.js Co-Authored-By: Tasso Evangelista --- app/channel-settings/server/methods/saveRoomSettings.js | 1 - 1 file changed, 1 deletion(-) diff --git a/app/channel-settings/server/methods/saveRoomSettings.js b/app/channel-settings/server/methods/saveRoomSettings.js index bf4d741b30c6..adef8f1ed12c 100644 --- a/app/channel-settings/server/methods/saveRoomSettings.js +++ b/app/channel-settings/server/methods/saveRoomSettings.js @@ -20,7 +20,6 @@ import { RoomSettingsEnum, roomTypes } from '../../../utils'; const fields = ['featured', 'roomName', 'roomTopic', 'roomAnnouncement', 'roomCustomFields', 'roomDescription', 'roomType', 'readOnly', 'reactWhenReadOnly', 'systemMessages', 'default', 'joinCode', 'tokenpass', 'streamingOptions', 'retentionEnabled', 'retentionMaxAge', 'retentionExcludePinned', 'retentionFilesOnly', 'retentionOverrideGlobal', 'encrypted']; Meteor.methods({ saveRoomSettings(rid, settings, value) { - console.log(settings, value); const userId = Meteor.userId(); if (!userId) { From aea69517eb2104dd2ca4fa98b0b037a011e95d1d Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 31 Mar 2020 19:16:03 -0300 Subject: [PATCH 25/26] Update app/lib/server/functions/saveUser.js Co-Authored-By: Tasso Evangelista --- app/lib/server/functions/saveUser.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/lib/server/functions/saveUser.js b/app/lib/server/functions/saveUser.js index c0ba977ed116..78c21fb81241 100644 --- a/app/lib/server/functions/saveUser.js +++ b/app/lib/server/functions/saveUser.js @@ -201,6 +201,7 @@ const handleBio = (updateUser, bio) => { method: 'saveUserProfile', }); } + updateUser.$set = updateUser.$set || {}; updateUser.$set.bio = bio; } else { updateUser.$unset = updateUser.$unset || {}; From e3a6508845a96440df0f1f0100b49a1943f020b3 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 31 Mar 2020 19:26:55 -0300 Subject: [PATCH 26/26] 260 --- app/lib/server/functions/saveUser.js | 2 +- app/ui-account/client/accountProfile.html | 2 +- app/ui-flextab/client/tabs/userEdit.html | 2 +- server/methods/saveUserProfile.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/lib/server/functions/saveUser.js b/app/lib/server/functions/saveUser.js index c0ba977ed116..35b38450129b 100644 --- a/app/lib/server/functions/saveUser.js +++ b/app/lib/server/functions/saveUser.js @@ -196,7 +196,7 @@ function validateUserEditing(userId, userData) { const handleBio = (updateUser, bio) => { if (bio) { if (bio.trim()) { - if (typeof bio !== 'string' || bio.length > 256) { + if (typeof bio !== 'string' || bio.length > 260) { throw new Meteor.Error('error-invalid-field', 'bio', { method: 'saveUserProfile', }); diff --git a/app/ui-account/client/accountProfile.html b/app/ui-account/client/accountProfile.html index 6a8ade0a4c9f..4f6196f3e2c9 100644 --- a/app/ui-account/client/accountProfile.html +++ b/app/ui-account/client/accountProfile.html @@ -133,7 +133,7 @@ diff --git a/app/ui-flextab/client/tabs/userEdit.html b/app/ui-flextab/client/tabs/userEdit.html index 2e7fe7861a4f..f4e17c2aef7b 100644 --- a/app/ui-flextab/client/tabs/userEdit.html +++ b/app/ui-flextab/client/tabs/userEdit.html @@ -121,7 +121,7 @@
{{> icon icon='edit' }}
- + diff --git a/server/methods/saveUserProfile.js b/server/methods/saveUserProfile.js index ccf3f3b9855e..53cd761d6a1f 100644 --- a/server/methods/saveUserProfile.js +++ b/server/methods/saveUserProfile.js @@ -58,7 +58,7 @@ Meteor.methods({ } if (settings.bio) { - if (typeof settings.bio !== 'string' || settings.bio.length > 256) { + if (typeof settings.bio !== 'string' || settings.bio.length > 260) { throw new Meteor.Error('error-invalid-field', 'bio', { method: 'saveUserProfile', });
{t('Name')}{t('Bio')}{t('Bio')}{t('Email')}{t('Domain')}{t('Joined_at')}