From 29f17994c6689a9c067449f179612a40a900f06b Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Fri, 12 Jun 2020 13:24:51 -0300 Subject: [PATCH 1/5] Move counter components to outside ee/ --- .../components/data/Counter.js | 6 +++-- client/components/data/Counter.stories.js | 20 ++++++++++++++ .../components/data/CounterSet.js | 6 +++-- .../components/data/CounterSet.stories.js | 4 +-- .../components/data/Growth.js | 8 +++--- client/components/data/Growth.stories.js | 26 +++++++++++++++++++ .../components/data/NegativeGrowthSymbol.js | 4 ++- .../data/NegativeGrowthSymbol.stories.js | 22 ++++++++++++++++ .../components/data/PositiveGrowthSymbol.js | 4 ++- .../data/PositiveGrowthSymbol.stories.js | 24 +++++++++++++++++ .../components/ChannelsTab/TableSection.js | 2 +- .../MessagesTab/MessagesSentSection.js | 2 +- .../components/UsersTab/ActiveUsersSection.js | 2 +- .../components/UsersTab/NewUsersSection.js | 2 +- .../client/components/data/Counter.stories.js | 16 ------------ .../client/components/data/Growth.stories.js | 23 ---------------- .../data/NegativeGrowthSymbol.stories.js | 16 ------------ .../data/PositiveGrowthSymbol.stories.js | 16 ------------ 18 files changed, 117 insertions(+), 86 deletions(-) rename {ee/app/engagement-dashboard/client => client}/components/data/Counter.js (82%) create mode 100644 client/components/data/Counter.stories.js rename {ee/app/engagement-dashboard/client => client}/components/data/CounterSet.js (73%) rename {ee/app/engagement-dashboard/client => client}/components/data/CounterSet.stories.js (72%) rename {ee/app/engagement-dashboard/client => client}/components/data/Growth.js (62%) create mode 100644 client/components/data/Growth.stories.js rename {ee/app/engagement-dashboard/client => client}/components/data/NegativeGrowthSymbol.js (92%) create mode 100644 client/components/data/NegativeGrowthSymbol.stories.js rename {ee/app/engagement-dashboard/client => client}/components/data/PositiveGrowthSymbol.js (92%) create mode 100644 client/components/data/PositiveGrowthSymbol.stories.js delete mode 100644 ee/app/engagement-dashboard/client/components/data/Counter.stories.js delete mode 100644 ee/app/engagement-dashboard/client/components/data/Growth.stories.js delete mode 100644 ee/app/engagement-dashboard/client/components/data/NegativeGrowthSymbol.stories.js delete mode 100644 ee/app/engagement-dashboard/client/components/data/PositiveGrowthSymbol.stories.js diff --git a/ee/app/engagement-dashboard/client/components/data/Counter.js b/client/components/data/Counter.js similarity index 82% rename from ee/app/engagement-dashboard/client/components/data/Counter.js rename to client/components/data/Counter.js index 396e66e37515..b216b781958d 100644 --- a/ee/app/engagement-dashboard/client/components/data/Counter.js +++ b/client/components/data/Counter.js @@ -1,9 +1,9 @@ import { Box, Flex, Margins } from '@rocket.chat/fuselage'; import React from 'react'; -import { Growth } from './Growth'; +import Growth from './Growth'; -export function Counter({ count, variation = 0, description }) { +function Counter({ count, variation = 0, description }) { return <> @@ -22,3 +22,5 @@ export function Counter({ count, variation = 0, description }) { ; } + +export default Counter; diff --git a/client/components/data/Counter.stories.js b/client/components/data/Counter.stories.js new file mode 100644 index 000000000000..d9c9ca93c94f --- /dev/null +++ b/client/components/data/Counter.stories.js @@ -0,0 +1,20 @@ +import React from 'react'; + +import Counter from './Counter'; + +export default { + title: 'components/data/Counter', + component: Counter, +}; + +export const Default = () => + ; + +export const WithPositiveVariation = () => + ; + +export const WithNegativeVariation = () => + ; + +export const WithDescription = () => + ; diff --git a/ee/app/engagement-dashboard/client/components/data/CounterSet.js b/client/components/data/CounterSet.js similarity index 73% rename from ee/app/engagement-dashboard/client/components/data/CounterSet.js rename to client/components/data/CounterSet.js index 26cbc5863f59..298f0d258a6f 100644 --- a/ee/app/engagement-dashboard/client/components/data/CounterSet.js +++ b/client/components/data/CounterSet.js @@ -1,9 +1,9 @@ import { Grid } from '@rocket.chat/fuselage'; import React from 'react'; -import { Counter } from './Counter'; +import Counter from './Counter'; -export function CounterSet({ counters = [] }) { +function CounterSet({ counters = [] }) { return {counters.map(({ count, variation, description }, i) => )} ; } + +export default CounterSet; diff --git a/ee/app/engagement-dashboard/client/components/data/CounterSet.stories.js b/client/components/data/CounterSet.stories.js similarity index 72% rename from ee/app/engagement-dashboard/client/components/data/CounterSet.stories.js rename to client/components/data/CounterSet.stories.js index fe23896f6a96..9354c6f62978 100644 --- a/ee/app/engagement-dashboard/client/components/data/CounterSet.stories.js +++ b/client/components/data/CounterSet.stories.js @@ -1,9 +1,9 @@ import React from 'react'; -import { CounterSet } from './CounterSet'; +import CounterSet from './CounterSet'; export default { - title: 'admin/enterprise/engagement/data/CounterSet', + title: 'components/data/CounterSet', component: CounterSet, }; diff --git a/ee/app/engagement-dashboard/client/components/data/Growth.js b/client/components/data/Growth.js similarity index 62% rename from ee/app/engagement-dashboard/client/components/data/Growth.js rename to client/components/data/Growth.js index e7babfefcfa3..bd1eb09ee8ac 100644 --- a/ee/app/engagement-dashboard/client/components/data/Growth.js +++ b/client/components/data/Growth.js @@ -1,10 +1,10 @@ import { Box } from '@rocket.chat/fuselage'; import React from 'react'; -import { NegativeGrowthSymbol } from './NegativeGrowthSymbol'; -import { PositiveGrowthSymbol } from './PositiveGrowthSymbol'; +import NegativeGrowthSymbol from './NegativeGrowthSymbol'; +import PositiveGrowthSymbol from './PositiveGrowthSymbol'; -export function Growth({ children, ...props }) { +function Growth({ children, ...props }) { if (children === 0) { return null; } @@ -14,3 +14,5 @@ export function Growth({ children, ...props }) { {String(Math.abs(children))} ; } + +export default Growth; diff --git a/client/components/data/Growth.stories.js b/client/components/data/Growth.stories.js new file mode 100644 index 000000000000..cf5123e88b6a --- /dev/null +++ b/client/components/data/Growth.stories.js @@ -0,0 +1,26 @@ +import { Box } from '@rocket.chat/fuselage'; +import React from 'react'; + +import Growth from './Growth'; + +export default { + title: 'components/data/Growth', + component: Growth, + decorators: [(fn) => ], +}; + +export const Positive = () => + {3}; + +export const Zero = () => + {0}; + +export const Negative = () => + {-3}; + +export const WithTextStyle = () => + ['h1', 's1', 'c1', 'micro'] + .map((fontScale) => + {3} + {-3} + ); diff --git a/ee/app/engagement-dashboard/client/components/data/NegativeGrowthSymbol.js b/client/components/data/NegativeGrowthSymbol.js similarity index 92% rename from ee/app/engagement-dashboard/client/components/data/NegativeGrowthSymbol.js rename to client/components/data/NegativeGrowthSymbol.js index bb7a0944a686..eaeb68f05c40 100644 --- a/ee/app/engagement-dashboard/client/components/data/NegativeGrowthSymbol.js +++ b/client/components/data/NegativeGrowthSymbol.js @@ -2,7 +2,7 @@ import React from 'react'; const style = { width: '1.5em', height: '1.5em', verticalAlign: '-0.5em' }; -export const NegativeGrowthSymbol = (props) => +const NegativeGrowthSymbol = (props) => 7.4768 4.3166 8.10996 4.70712 8.50049Z`} /> ; + +export default NegativeGrowthSymbol; diff --git a/client/components/data/NegativeGrowthSymbol.stories.js b/client/components/data/NegativeGrowthSymbol.stories.js new file mode 100644 index 000000000000..a9645555cdce --- /dev/null +++ b/client/components/data/NegativeGrowthSymbol.stories.js @@ -0,0 +1,22 @@ +import { Box } from '@rocket.chat/fuselage'; +import React from 'react'; + +import NegativeGrowthSymbol from './NegativeGrowthSymbol'; + +export default { + title: 'components/data/NegativeGrowthSymbol', + component: NegativeGrowthSymbol, + decorators: [ + (fn) => , + ], +}; + +export const Default = () => ; + +export const WithColor = () => ; + +WithColor.story = { + decorators: [ + (storyFn) => {storyFn()}, + ], +}; diff --git a/ee/app/engagement-dashboard/client/components/data/PositiveGrowthSymbol.js b/client/components/data/PositiveGrowthSymbol.js similarity index 92% rename from ee/app/engagement-dashboard/client/components/data/PositiveGrowthSymbol.js rename to client/components/data/PositiveGrowthSymbol.js index 15d485dadafe..7f5d61cb239c 100644 --- a/ee/app/engagement-dashboard/client/components/data/PositiveGrowthSymbol.js +++ b/client/components/data/PositiveGrowthSymbol.js @@ -2,7 +2,7 @@ import React from 'react'; const style = { width: '1.5em', height: '1.5em', verticalAlign: '-0.5em' }; -export const PositiveGrowthSymbol = (props) => +const PositiveGrowthSymbol = (props) => 16.3502 4.3166 15.7171 4.70712 15.3265Z`} /> ; + +export default PositiveGrowthSymbol; diff --git a/client/components/data/PositiveGrowthSymbol.stories.js b/client/components/data/PositiveGrowthSymbol.stories.js new file mode 100644 index 000000000000..53b65a1eb703 --- /dev/null +++ b/client/components/data/PositiveGrowthSymbol.stories.js @@ -0,0 +1,24 @@ +import { Box } from '@rocket.chat/fuselage'; +import React from 'react'; + +import PositiveGrowthSymbol from './PositiveGrowthSymbol'; + +export default { + title: 'components/data/PositiveGrowthSymbol', + component: PositiveGrowthSymbol, + decorators: [ + (fn) => , + ], +}; + +export const Default = () => + ; + +export const WithColor = () => + ; + +WithColor.story = { + decorators: [ + (storyFn) => {storyFn()}, + ], +}; diff --git a/ee/app/engagement-dashboard/client/components/ChannelsTab/TableSection.js b/ee/app/engagement-dashboard/client/components/ChannelsTab/TableSection.js index 55424e16244b..dc6c083438d8 100644 --- a/ee/app/engagement-dashboard/client/components/ChannelsTab/TableSection.js +++ b/ee/app/engagement-dashboard/client/components/ChannelsTab/TableSection.js @@ -4,7 +4,7 @@ import React, { useMemo, useState } from 'react'; import { useTranslation } from '../../../../../../client/contexts/TranslationContext'; import { useEndpointData } from '../../../../../../client/hooks/useEndpointData'; -import { Growth } from '../data/Growth'; +import Growth from '../../../../../../client/components/data/Growth'; import { Section } from '../Section'; export function TableSection() { diff --git a/ee/app/engagement-dashboard/client/components/MessagesTab/MessagesSentSection.js b/ee/app/engagement-dashboard/client/components/MessagesTab/MessagesSentSection.js index 0908351bcd0d..d4fb1ccf674b 100644 --- a/ee/app/engagement-dashboard/client/components/MessagesTab/MessagesSentSection.js +++ b/ee/app/engagement-dashboard/client/components/MessagesTab/MessagesSentSection.js @@ -5,7 +5,7 @@ import React, { useMemo, useState } from 'react'; import { useTranslation } from '../../../../../../client/contexts/TranslationContext'; import { useEndpointData } from '../../../../../../client/hooks/useEndpointData'; -import { CounterSet } from '../data/CounterSet'; +import CounterSet from '../../../../../../client/components/data/CounterSet'; import { Section } from '../Section'; export function MessagesSentSection() { diff --git a/ee/app/engagement-dashboard/client/components/UsersTab/ActiveUsersSection.js b/ee/app/engagement-dashboard/client/components/UsersTab/ActiveUsersSection.js index 4a471d2e923b..d11392fe5d30 100644 --- a/ee/app/engagement-dashboard/client/components/UsersTab/ActiveUsersSection.js +++ b/ee/app/engagement-dashboard/client/components/UsersTab/ActiveUsersSection.js @@ -5,7 +5,7 @@ import React, { useMemo } from 'react'; import { useTranslation } from '../../../../../../client/contexts/TranslationContext'; import { useEndpointData } from '../../../../../../client/hooks/useEndpointData'; -import { CounterSet } from '../data/CounterSet'; +import CounterSet from '../../../../../../client/components/data/CounterSet'; import { LegendSymbol } from '../data/LegendSymbol'; import { Section } from '../Section'; diff --git a/ee/app/engagement-dashboard/client/components/UsersTab/NewUsersSection.js b/ee/app/engagement-dashboard/client/components/UsersTab/NewUsersSection.js index 9d76708d5237..a5c185fd826c 100644 --- a/ee/app/engagement-dashboard/client/components/UsersTab/NewUsersSection.js +++ b/ee/app/engagement-dashboard/client/components/UsersTab/NewUsersSection.js @@ -5,7 +5,7 @@ import React, { useMemo, useState } from 'react'; import { useTranslation } from '../../../../../../client/contexts/TranslationContext'; import { useEndpointData } from '../../../../../../client/hooks/useEndpointData'; -import { CounterSet } from '../data/CounterSet'; +import CounterSet from '../../../../../../client/components/data/CounterSet'; import { Section } from '../Section'; export function NewUsersSection() { diff --git a/ee/app/engagement-dashboard/client/components/data/Counter.stories.js b/ee/app/engagement-dashboard/client/components/data/Counter.stories.js deleted file mode 100644 index 75966df87f99..000000000000 --- a/ee/app/engagement-dashboard/client/components/data/Counter.stories.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; - -import { Counter } from './Counter'; - -export default { - title: 'admin/enterprise/engagement/data/Counter', - component: Counter, -}; - -export const _default = () => ; - -export const withPositiveVariation = () => ; - -export const withNegativeVariation = () => ; - -export const withDescription = () => ; diff --git a/ee/app/engagement-dashboard/client/components/data/Growth.stories.js b/ee/app/engagement-dashboard/client/components/data/Growth.stories.js deleted file mode 100644 index 6c04a30ee55c..000000000000 --- a/ee/app/engagement-dashboard/client/components/data/Growth.stories.js +++ /dev/null @@ -1,23 +0,0 @@ -import { Box, Margins } from '@rocket.chat/fuselage'; -import React from 'react'; - -import { Growth } from './Growth'; - -export default { - title: 'admin/enterprise/engagement/data/Growth', - component: Growth, - decorators: [(fn) => ], -}; - -export const positive = () => {3}; - -export const zero = () => {0}; - -export const negative = () => {-3}; - -export const withTextStyle = () => - ['h1', 's1', 'c1', 'micro'] - .map((fontScale) => - {3} - {-3} - ); diff --git a/ee/app/engagement-dashboard/client/components/data/NegativeGrowthSymbol.stories.js b/ee/app/engagement-dashboard/client/components/data/NegativeGrowthSymbol.stories.js deleted file mode 100644 index f7b7a2197f79..000000000000 --- a/ee/app/engagement-dashboard/client/components/data/NegativeGrowthSymbol.stories.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Box, Margins } from '@rocket.chat/fuselage'; -import React from 'react'; - -import { NegativeGrowthSymbol } from './NegativeGrowthSymbol'; - -export default { - title: 'admin/enterprise/engagement/data/NegativeGrowthSymbol', - component: NegativeGrowthSymbol, - decorators: [(fn) => ], -}; - -export const _default = () => ; - -export const withColor = () => - -; diff --git a/ee/app/engagement-dashboard/client/components/data/PositiveGrowthSymbol.stories.js b/ee/app/engagement-dashboard/client/components/data/PositiveGrowthSymbol.stories.js deleted file mode 100644 index f750dad10150..000000000000 --- a/ee/app/engagement-dashboard/client/components/data/PositiveGrowthSymbol.stories.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Box, Margins } from '@rocket.chat/fuselage'; -import React from 'react'; - -import { PositiveGrowthSymbol } from './PositiveGrowthSymbol'; - -export default { - title: 'admin/enterprise/engagement/data/PositiveGrowthSymbol', - component: PositiveGrowthSymbol, - decorators: [(fn) => ], -}; - -export const _default = () => ; - -export const withColor = () => - -; From fb47a7fb7c6dfeacb342f437225170d37f64004f Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Fri, 12 Jun 2020 18:47:09 -0300 Subject: [PATCH 2/5] Add more helpful hooks in ServerContext --- client/contexts/ServerContext.js | 28 -------- client/contexts/ServerContext.ts | 111 +++++++++++++++++++++++++++++ client/providers/ServerProvider.js | 7 +- 3 files changed, 116 insertions(+), 30 deletions(-) delete mode 100644 client/contexts/ServerContext.js create mode 100644 client/contexts/ServerContext.ts diff --git a/client/contexts/ServerContext.js b/client/contexts/ServerContext.js deleted file mode 100644 index f2ba6ebf69c8..000000000000 --- a/client/contexts/ServerContext.js +++ /dev/null @@ -1,28 +0,0 @@ -import { createContext, useCallback, useContext } from 'react'; - -export const ServerContext = createContext({ - info: {}, - absoluteUrl: (path) => path, - callMethod: async () => {}, - callEndpoint: async () => {}, - upload: async () => {}, -}); - -export const useServerInformation = () => useContext(ServerContext).info; - -export const useAbsoluteUrl = () => useContext(ServerContext).absoluteUrl; - -export const useMethod = (methodName) => { - const { callMethod } = useContext(ServerContext); - return useCallback((...args) => callMethod(methodName, ...args), [callMethod, methodName]); -}; - -export const useEndpoint = (httpMethod, endpoint) => { - const { callEndpoint } = useContext(ServerContext); - return useCallback((...args) => callEndpoint(httpMethod, endpoint, ...args), [callEndpoint, httpMethod, endpoint]); -}; - -export const useUpload = (endpoint) => { - const { upload } = useContext(ServerContext); - return useCallback((...args) => upload(endpoint, ...args), [upload]); -}; diff --git a/client/contexts/ServerContext.ts b/client/contexts/ServerContext.ts new file mode 100644 index 000000000000..7934932a5fb2 --- /dev/null +++ b/client/contexts/ServerContext.ts @@ -0,0 +1,111 @@ +import { createContext, useCallback, useContext, useMemo, useState, useEffect, useRef } from 'react'; + +interface IServerStream { + on(eventName: string, callback: (data: any) => void): void; + off(eventName: string, callback: (data: any) => void): void; +} + +type ServerContextValue = { + info: object; + absoluteUrl: (path: string) => string; + callMethod: (methodName: string, ...args: any[]) => Promise; + callEndpoint: (httpMethod: 'GET' | 'POST' | 'DELETE', endpoint: string, ...args: any[]) => Promise; + uploadToEndpoint: (endpoint: string) => Promise; + getStream: (streamName: string, options?: object) => IServerStream; +}; + +export const ServerContext = createContext({ + info: {}, + absoluteUrl: (path) => path, + callMethod: async () => undefined, + callEndpoint: async () => undefined, + uploadToEndpoint: async () => undefined, + getStream: () => ({ + on: (): void => undefined, + off: (): void => undefined, + }), +}); + +export const useServerInformation = (): object => useContext(ServerContext).info; + +export const useAbsoluteUrl = (): ((path: string) => string) => useContext(ServerContext).absoluteUrl; + +export const useMethod = (methodName: string): (...args: any[]) => Promise => { + const { callMethod } = useContext(ServerContext); + return useCallback((...args) => callMethod(methodName, ...args), [callMethod, methodName]); +}; + +export const useEndpoint = (httpMethod: 'GET' | 'POST' | 'DELETE', endpoint: string): (...args: any[]) => Promise => { + const { callEndpoint } = useContext(ServerContext); + return useCallback((...args) => callEndpoint(httpMethod, endpoint, ...args), [callEndpoint, httpMethod, endpoint]); +}; + +export const useUpload = (endpoint: string): () => Promise => { + const { uploadToEndpoint } = useContext(ServerContext); + return useCallback((...args) => uploadToEndpoint(endpoint, ...args), [endpoint, uploadToEndpoint]); +}; + +export const useStream = (streamName: string, options?: object): IServerStream => { + const { getStream } = useContext(ServerContext); + return useMemo(() => getStream(streamName, options), [streamName, options]); +}; + +export enum AsyncState { + LOADING = 'loading', + DONE = 'done', + ERROR = 'error', +} + +export const useMethodData = (methodName: string, args: any[] = []): [T | null, AsyncState, () => void] => { + const getData = useMethod(methodName); + const [[data, state], updateState] = useState<[T | null, AsyncState]>([null, AsyncState.LOADING]); + + const isMountedRef = useRef(true); + + useEffect(() => (): void => { + isMountedRef.current = false; + }, []); + + const fetchData = useCallback(() => { + updateState(([data]) => [data, AsyncState.LOADING]); + + getData(...args) + .then((data) => { + if (!isMountedRef.current) { + return; + } + + updateState([data, AsyncState.DONE]); + }) + .catch((error) => { + if (!isMountedRef.current) { + return; + } + + updateState(([data]) => [data, AsyncState.ERROR]); + console.error(error); + }); + }, [getData, ...args]); + + useEffect(() => { + fetchData(); + }, [fetchData]); + + return [data, state, fetchData]; +}; + +export const usePolledMethodData = (methodName: string, args: any[] = [], intervalMs: number): [T | null, AsyncState, () => void] => { + const [data, state, fetchData] = useMethodData(methodName, args); + + useEffect(() => { + const timer = setInterval(() => { + fetchData(); + }, intervalMs); + + return (): void => { + clearInterval(timer); + }; + }, []); + + return [data, state, fetchData]; +}; diff --git a/client/providers/ServerProvider.js b/client/providers/ServerProvider.js index a6d9cf7e10f4..8c2190a22127 100644 --- a/client/providers/ServerProvider.js +++ b/client/providers/ServerProvider.js @@ -32,14 +32,17 @@ const callEndpoint = (httpMethod, endpoint, ...args) => { return APIClient.v1[httpMethod.toLowerCase()](endpoint, ...args); }; -const upload = (endpoint, params, formData) => APIClient.v1.upload(endpoint, params, formData); +const uploadToEndpoint = (endpoint, params, formData) => APIClient.v1.upload(endpoint, params, formData); + +const getStream = (streamName, options = {}) => new Meteor.Streamer(streamName, options); const contextValue = { info, absoluteUrl, callMethod, callEndpoint, - upload, + uploadToEndpoint, + getStream, }; export function ServerProvider({ children }) { From a8b6349c65dbb223cae09c8389a4f4447f7696c7 Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Fri, 12 Jun 2020 18:48:12 -0300 Subject: [PATCH 3/5] Add FederationDashboardRoute --- app/federation/client/admin/dashboard.js | 22 ---------- .../FederationDashboardPage.js | 23 +++++++++++ .../FederationDashboardPage.stories.js | 10 +++++ .../FederationDashboardRoute.tsx | 17 ++++++++ .../federationDashboard/OverviewSection.js | 40 +++++++++++++++++++ .../OverviewSection.stories.js | 10 +++++ client/admin/routes.js | 5 +++ client/admin/sidebarItems.js | 14 +++++-- 8 files changed, 115 insertions(+), 26 deletions(-) create mode 100644 client/admin/federationDashboard/FederationDashboardPage.js create mode 100644 client/admin/federationDashboard/FederationDashboardPage.stories.js create mode 100644 client/admin/federationDashboard/FederationDashboardRoute.tsx create mode 100644 client/admin/federationDashboard/OverviewSection.js create mode 100644 client/admin/federationDashboard/OverviewSection.stories.js diff --git a/app/federation/client/admin/dashboard.js b/app/federation/client/admin/dashboard.js index a0d6aa6594c6..28f0987def72 100644 --- a/app/federation/client/admin/dashboard.js +++ b/app/federation/client/admin/dashboard.js @@ -2,10 +2,6 @@ import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; import { Template } from 'meteor/templating'; import { ReactiveVar } from 'meteor/reactive-var'; -import { BlazeLayout } from 'meteor/kadira:blaze-layout'; - -import { hasRole } from '../../../authorization'; -import { registerAdminRoute, registerAdminSidebarItem } from '../../../../client/admin'; import './dashboard.html'; import './dashboard.css'; @@ -65,21 +61,3 @@ Template.dashboard.onRendered(() => { setInterval(updateData, 10000); }); - -// Route setup - -registerAdminRoute('/federation-dashboard', { - name: 'federation-dashboard', - action() { - BlazeLayout.render('main', { center: 'dashboard', old: true }); - }, -}); - -registerAdminSidebarItem({ - icon: 'discover', - href: 'federation-dashboard', - i18nLabel: 'Federation Dashboard', - permissionGranted() { - return hasRole(Meteor.userId(), 'admin'); - }, -}); diff --git a/client/admin/federationDashboard/FederationDashboardPage.js b/client/admin/federationDashboard/FederationDashboardPage.js new file mode 100644 index 000000000000..bed04f5606ad --- /dev/null +++ b/client/admin/federationDashboard/FederationDashboardPage.js @@ -0,0 +1,23 @@ +import { Box } from '@rocket.chat/fuselage'; +import React from 'react'; + +import Page from '../../components/basic/Page'; +import { useTranslation } from '../../contexts/TranslationContext'; +// import { usePolledMethodData } from '../../contexts/ServerContext'; +import OverviewSection from './OverviewSection'; + +function FederationDashboardPage() { + const t = useTranslation(); + // const [serversData, serversStatus] = usePolledMethodData('federation:getServers', [], 10000); + + return + + + + + + + ; +} + +export default FederationDashboardPage; diff --git a/client/admin/federationDashboard/FederationDashboardPage.stories.js b/client/admin/federationDashboard/FederationDashboardPage.stories.js new file mode 100644 index 000000000000..f696bd5be6fa --- /dev/null +++ b/client/admin/federationDashboard/FederationDashboardPage.stories.js @@ -0,0 +1,10 @@ +import React from 'react'; + +import FederationDashboardPage from './FederationDashboardPage'; + +export default { + title: 'admin/federationDashboard/FederationDashboardPage', + component: FederationDashboardPage, +}; + +export const Default = () => ; diff --git a/client/admin/federationDashboard/FederationDashboardRoute.tsx b/client/admin/federationDashboard/FederationDashboardRoute.tsx new file mode 100644 index 000000000000..5460cee93e1a --- /dev/null +++ b/client/admin/federationDashboard/FederationDashboardRoute.tsx @@ -0,0 +1,17 @@ +import React, { FC } from 'react'; + +import { useRole } from '../../contexts/AuthorizationContext'; +import NotAuthorizedPage from '../NotAuthorizedPage'; +import FederationDashboardPage from './FederationDashboardPage'; + +const FederationDashboardRoute: FC<{}> = () => { + const authorized = useRole('admin'); + + if (!authorized) { + return ; + } + + return ; +}; + +export default FederationDashboardRoute; diff --git a/client/admin/federationDashboard/OverviewSection.js b/client/admin/federationDashboard/OverviewSection.js new file mode 100644 index 000000000000..328948e31d61 --- /dev/null +++ b/client/admin/federationDashboard/OverviewSection.js @@ -0,0 +1,40 @@ +import { Box, Skeleton } from '@rocket.chat/fuselage'; +import React from 'react'; + +import { useTranslation } from '../../contexts/TranslationContext'; +import CounterSet from '../../components/data/CounterSet'; +import { usePolledMethodData, AsyncState } from '../../contexts/ServerContext'; + +function OverviewSection() { + const t = useTranslation(); + const [overviewData, overviewStatus] = usePolledMethodData('federation:getOverviewData', [], 10000); + + const eventCount = (overviewStatus === AsyncState.LOADING && ) + || (overviewStatus === AsyncState.ERROR && Error) + || overviewData?.data[0]?.value; + const userCount = (overviewStatus === AsyncState.LOADING && ) + || (overviewStatus === AsyncState.ERROR && Error) + || overviewData?.data[1]?.value; + const serverCount = (overviewStatus === AsyncState.LOADING && ) + || (overviewStatus === AsyncState.ERROR && Error) + || overviewData?.data[2]?.value; + + return ; +} + +export default OverviewSection; diff --git a/client/admin/federationDashboard/OverviewSection.stories.js b/client/admin/federationDashboard/OverviewSection.stories.js new file mode 100644 index 000000000000..dce647e09b16 --- /dev/null +++ b/client/admin/federationDashboard/OverviewSection.stories.js @@ -0,0 +1,10 @@ +import React from 'react'; + +import OverviewSection from './OverviewSection'; + +export default { + title: 'admin/federationDashboard/OverviewSection', + component: OverviewSection, +}; + +export const Default = () => ; diff --git a/client/admin/routes.js b/client/admin/routes.js index 6ede81d1ef1d..3b68e59ae315 100644 --- a/client/admin/routes.js +++ b/client/admin/routes.js @@ -117,6 +117,11 @@ registerAdminRoute('/view-logs', { lazyRouteComponent: () => import('./viewLogs/ViewLogsRoute'), }); +registerAdminRoute('/federation-dashboard', { + name: 'federation-dashboard', + lazyRouteComponent: () => import('./federationDashboard/FederationDashboardRoute'), +}); + Meteor.startup(() => { registerAdminRoute('/:group+', { name: 'admin', diff --git a/client/admin/sidebarItems.js b/client/admin/sidebarItems.js index 657069b63a10..77a3d3230952 100644 --- a/client/admin/sidebarItems.js +++ b/client/admin/sidebarItems.js @@ -1,6 +1,7 @@ +import { Meteor } from 'meteor/meteor'; import { ReactiveVar } from 'meteor/reactive-var'; -import { hasPermission } from '../../app/authorization/client'; +import { hasPermission, hasRole } from '../../app/authorization/client'; import { createTemplateForComponent } from '../reactAdapters'; export const sidebarItems = new ReactiveVar([]); @@ -63,7 +64,12 @@ registerAdminSidebarItem({ href: 'custom-sounds', i18nLabel: 'Custom_Sounds', icon: 'volume', - permissionGranted() { - return hasPermission(['manage-sounds']); - }, + permissionGranted: () => hasPermission(['manage-sounds']), +}); + +registerAdminSidebarItem({ + icon: 'discover', + href: 'federation-dashboard', + i18nLabel: 'Federation Dashboard', + permissionGranted: () => hasRole(Meteor.userId(), 'admin'), }); From 8f4bf90f083618880d94689024a64101d2ceee14 Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Fri, 12 Jun 2020 19:09:17 -0300 Subject: [PATCH 4/5] Add ServersSection prototype --- .../FederationDashboardPage.js | 4 +-- .../federationDashboard/ServersSection.js | 26 +++++++++++++++++++ .../ServersSection.stories.js | 10 +++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 client/admin/federationDashboard/ServersSection.js create mode 100644 client/admin/federationDashboard/ServersSection.stories.js diff --git a/client/admin/federationDashboard/FederationDashboardPage.js b/client/admin/federationDashboard/FederationDashboardPage.js index bed04f5606ad..e3277926d442 100644 --- a/client/admin/federationDashboard/FederationDashboardPage.js +++ b/client/admin/federationDashboard/FederationDashboardPage.js @@ -3,18 +3,18 @@ import React from 'react'; import Page from '../../components/basic/Page'; import { useTranslation } from '../../contexts/TranslationContext'; -// import { usePolledMethodData } from '../../contexts/ServerContext'; import OverviewSection from './OverviewSection'; +import ServersSection from './ServersSection'; function FederationDashboardPage() { const t = useTranslation(); - // const [serversData, serversStatus] = usePolledMethodData('federation:getServers', [], 10000); return + ; diff --git a/client/admin/federationDashboard/ServersSection.js b/client/admin/federationDashboard/ServersSection.js new file mode 100644 index 000000000000..d679b9fc988f --- /dev/null +++ b/client/admin/federationDashboard/ServersSection.js @@ -0,0 +1,26 @@ +import { Box, Throbber } from '@rocket.chat/fuselage'; +import React from 'react'; + +import { usePolledMethodData, AsyncState } from '../../contexts/ServerContext'; + +function ServersSection() { + const [serversData, serversStatus] = usePolledMethodData('federation:getServers', [], 10000); + + if (serversStatus === AsyncState.LOADING) { + return ; + } + + if (serversData?.data?.length === 0) { + return null; + } + + return +
    + {serversData?.data?.map(({ domain }) => ( +
  • {domain}
  • + ))} +
+
; +} + +export default ServersSection; diff --git a/client/admin/federationDashboard/ServersSection.stories.js b/client/admin/federationDashboard/ServersSection.stories.js new file mode 100644 index 000000000000..744f3f659fcf --- /dev/null +++ b/client/admin/federationDashboard/ServersSection.stories.js @@ -0,0 +1,10 @@ +import React from 'react'; + +import ServersSection from './ServersSection'; + +export default { + title: 'admin/federationDashboard/ServersSection', + component: ServersSection, +}; + +export const Default = () => ; From f4f6ae05972e7337df47a397bf6b6971a6bdef4e Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Fri, 12 Jun 2020 19:09:36 -0300 Subject: [PATCH 5/5] Remove federation dashboard templates --- app/federation/client/admin/dashboard.css | 141 --------------------- app/federation/client/admin/dashboard.html | 32 ----- app/federation/client/admin/dashboard.js | 63 --------- app/federation/client/index.js | 1 - client/importPackages.js | 1 - 5 files changed, 238 deletions(-) delete mode 100644 app/federation/client/admin/dashboard.css delete mode 100644 app/federation/client/admin/dashboard.html delete mode 100644 app/federation/client/admin/dashboard.js delete mode 100644 app/federation/client/index.js diff --git a/app/federation/client/admin/dashboard.css b/app/federation/client/admin/dashboard.css deleted file mode 100644 index 31b7ade58d7a..000000000000 --- a/app/federation/client/admin/dashboard.css +++ /dev/null @@ -1,141 +0,0 @@ -.status { - flex: 0 0 auto; - - width: 6px; - height: 6px; - margin: 0 7px; - - border-radius: 50%; -} - -.status.stable { - background-color: #2de0a5; -} - -.status.unstable { - background-color: #ffd21f; -} - -.status.failing { - background-color: #f5455c; -} - -.frame { - display: flex; - flex-direction: row; -} - -.group { - display: flex; - flex-direction: row; - flex: 100%; - - max-width: 100%; - margin: 10px; - - border-width: 1px; - align-items: center; - justify-content: center; -} - -.group.left { - justify-content: flex-start; -} - -.group.wrap { - flex-wrap: wrap; -} - -.overview-column { - flex: 100%; - - min-height: 20px; - margin: 15px 0; -} - -.overview-column.small { - max-width: 20%; -} - -.group .overview-column:not(:last-child) { - border-right: 1px solid #e9e9e9; -} - -.group .overview-column:nth-child(5n) { - border-right: 0; -} - -.overview-pill { - display: flex; - - width: 100%; - padding: 0 10px; - - user-select: text; - text-align: center; - align-items: center; -} - -.overview-item { - width: 100%; - - user-select: text; - text-align: center; -} - -.overview-item > .title { - display: inline-block; - - margin-top: 8px; - - text-transform: uppercase; - - color: #9ea2a8; - - font-size: 0.875rem; - font-weight: 300; -} - -.overview-item > .value { - display: inline-block; - - width: 100%; - - text-transform: capitalize; - - color: #383838; - - font-size: 1.75rem; - font-weight: 400; - line-height: 1; -} - -@media screen and (max-width: 925px) { - .overview-item > .title { - font-size: 0.5rem; - } - - .overview-item > .value { - font-size: 1rem; - } -} - -@media screen and (max-width: 800px) { - .overview-item > .title { - font-size: 0.875rem; - } - - .overview-item > .value { - font-size: 1.75rem; - } -} - -@media screen and (max-width: 600px) { - .overview-item > .title { - font-size: 0.5rem; - } - - .overview-item > .value { - font-size: 1rem; - } -} diff --git a/app/federation/client/admin/dashboard.html b/app/federation/client/admin/dashboard.html deleted file mode 100644 index ff303fd90abc..000000000000 --- a/app/federation/client/admin/dashboard.html +++ /dev/null @@ -1,32 +0,0 @@ - diff --git a/app/federation/client/admin/dashboard.js b/app/federation/client/admin/dashboard.js deleted file mode 100644 index 28f0987def72..000000000000 --- a/app/federation/client/admin/dashboard.js +++ /dev/null @@ -1,63 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { Tracker } from 'meteor/tracker'; -import { Template } from 'meteor/templating'; -import { ReactiveVar } from 'meteor/reactive-var'; - -import './dashboard.html'; -import './dashboard.css'; - -// Template controller -let templateInstance; // current template instance/context - -// Methods -const updateOverviewData = () => { - Meteor.call('federation:getOverviewData', (error, result) => { - if (error) { - return; - } - - const { data } = result; - - templateInstance.federationOverviewData.set(data); - }); -}; - -const updateServers = () => { - Meteor.call('federation:getServers', (error, result) => { - if (error) { - return; - } - - const { data } = result; - - templateInstance.federationPeers.set(data); - }); -}; - -const updateData = () => { - updateOverviewData(); - updateServers(); -}; - -Template.dashboard.helpers({ - federationOverviewData() { - return templateInstance.federationOverviewData.get(); - }, - federationPeers() { - return templateInstance.federationPeers.get(); - }, -}); - -// Events -Template.dashboard.onCreated(function() { - templateInstance = Template.instance(); - - this.federationOverviewData = new ReactiveVar(); - this.federationPeers = new ReactiveVar(); -}); - -Template.dashboard.onRendered(() => { - Tracker.autorun(updateData); - - setInterval(updateData, 10000); -}); diff --git a/app/federation/client/index.js b/app/federation/client/index.js deleted file mode 100644 index 1a16fba9d1f5..000000000000 --- a/app/federation/client/index.js +++ /dev/null @@ -1 +0,0 @@ -import './admin/dashboard'; diff --git a/client/importPackages.js b/client/importPackages.js index 115a1d35665f..fb24b0971b56 100644 --- a/client/importPackages.js +++ b/client/importPackages.js @@ -17,7 +17,6 @@ import '../app/emoji'; import '../app/emoji-custom/client'; import '../app/emoji-emojione/client'; import '../app/favico'; -import '../app/federation/client'; import '../app/file-upload'; import '../app/github-enterprise/client'; import '../app/gitlab/client';