-
+
{rawSectionName || t(sectionName)}
diff --git a/client/components/header/Header.stories.js b/client/components/header/Header.stories.js
new file mode 100644
index 00000000000..01e20581fce
--- /dev/null
+++ b/client/components/header/Header.stories.js
@@ -0,0 +1,19 @@
+import { boolean, text } from '@storybook/addon-knobs/react';
+import React from 'react';
+
+import { Header } from './Header';
+
+export default {
+ title: 'header/Header',
+ component: Header,
+};
+
+export const _default = () =>
;
+
+export const withRawSectionName = () =>
;
+
+export const withSectionName = () =>
;
diff --git a/client/components/header/hooks.js b/client/components/header/hooks.js
new file mode 100644
index 00000000000..75948907862
--- /dev/null
+++ b/client/components/header/hooks.js
@@ -0,0 +1,53 @@
+import { useMemo } from 'react';
+
+import { ChatSubscription } from '../../../app/models/client/models/ChatSubscription';
+import { menu } from '../../../app/ui-utils/client/lib/menu';
+import { useReactiveValue } from '../../hooks/useReactiveValue';
+import { useSession } from '../../hooks/useSession';
+import { useUserPreference } from '../../hooks/useUserPreference';
+
+import './BurgerMenuButton.css';
+
+export const useSidebarState = () => {
+ const isOpen = useSession('isMenuOpen');
+ const toggle = () => menu.toggle();
+ return [isOpen, toggle];
+};
+
+export const useUnreadMessagesBadge = () => {
+ const alertUnreadMessages = useUserPreference('unreadAlert') !== false;
+ const openedRoom = useSession('openedRoom');
+ const [unreadCount, unreadAlert] = useReactiveValue(() => ChatSubscription
+ .find({
+ open: true,
+ hideUnreadStatus: { $ne: true },
+ rid: { $ne: openedRoom },
+ }, {
+ fields: {
+ unread: 1,
+ alert: 1,
+ unreadAlert: 1,
+ },
+ })
+ .fetch()
+ .reduce(([unreadCount, unreadAlert], { alert, unread, unreadAlert: alertType }) => {
+ if (alert || unread > 0) {
+ unreadCount += unread;
+ if (alert === true && alertType !== 'nothing') {
+ if (alertType === 'all' || alertUnreadMessages !== false) {
+ unreadAlert = '•';
+ }
+ }
+ }
+
+ return [unreadCount, unreadAlert];
+ }, [0, false]), [openedRoom, alertUnreadMessages]);
+
+ return useMemo(() => {
+ if (unreadCount > 0) {
+ return unreadCount > 99 ? '99+' : unreadCount.toString(10);
+ }
+
+ return unreadAlert || '';
+ }, [unreadCount, unreadAlert]);
+};
diff --git a/client/hooks/useMethod.js b/client/hooks/useMethod.js
new file mode 100644
index 00000000000..f2d76e6bb90
--- /dev/null
+++ b/client/hooks/useMethod.js
@@ -0,0 +1,13 @@
+import { Meteor } from 'meteor/meteor';
+import { useCallback } from 'react';
+
+export const useMethod = (methodName) => useCallback((...args) => new Promise((resolve, reject) => {
+ Meteor.call(methodName, ...args, (error, result) => {
+ if (error) {
+ reject(error);
+ return;
+ }
+
+ resolve(result);
+ });
+}), [methodName]);
diff --git a/client/hooks/useRocketChatInformation.js b/client/hooks/useRocketChatInformation.js
new file mode 100644
index 00000000000..8432c9195e6
--- /dev/null
+++ b/client/hooks/useRocketChatInformation.js
@@ -0,0 +1,3 @@
+import { Info } from '../../app/utils';
+
+export const useRocketChatInformation = () => Info;
diff --git a/client/routes.js b/client/routes.js
index 6fc5cbde899..4b6af08d82f 100644
--- a/client/routes.js
+++ b/client/routes.js
@@ -35,6 +35,7 @@ BlazeLayout.setRoot('body');
const createTemplateForComponent = async (
component,
+ hook = () => ({}),
props = {},
// eslint-disable-next-line new-cap
renderContainerView = () => HTML.DIV()
@@ -59,7 +60,7 @@ const createTemplateForComponent = async (
ReactDOM.render(
React.createElement(MeteorProvider, {
- children: React.createElement(component, props),
+ children: React.createElement(() => React.createElement(component, { ...props, ...hook() })),
}), Template.instance().firstNode);
});
});
@@ -268,8 +269,8 @@ FlowRouter.route('/admin/:group?', {
action: async ({ group = 'info' } = {}) => {
switch (group) {
case 'info': {
- const { InformationPage } = await import('./components/admin/info/InformationPage');
- BlazeLayout.render('main', { center: await createTemplateForComponent(InformationPage) });
+ const { InformationPage, useInformationPage } = await import('./components/admin/info/InformationPage');
+ BlazeLayout.render('main', { center: await createTemplateForComponent(InformationPage, useInformationPage) });
break;
}
diff --git a/package-lock.json b/package-lock.json
index 120d6823786..90882f5895e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2204,6 +2204,12 @@
"protobufjs": "^6.8.6"
}
},
+ "@icons/material": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz",
+ "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==",
+ "dev": true
+ },
"@kossnocorp/desvg": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@kossnocorp/desvg/-/desvg-0.2.0.tgz",
@@ -2469,6 +2475,41 @@
}
}
},
+ "@settlin/spacebars-loader": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/@settlin/spacebars-loader/-/spacebars-loader-1.0.7.tgz",
+ "integrity": "sha512-i/1mtmE/53v6Kc342iJnt3HvjMVdeS/o/TEYFnxJ4oL7lF7+dK47npYmyMYAH0jj2PGl5xhyt/syGDfV35J+9Q==",
+ "dev": true,
+ "requires": {
+ "loader-utils": "0.2.x",
+ "lodash": "^4.17.15",
+ "meteor-blaze-tools": "^1.2.4",
+ "meteor-core": "^1.2.4",
+ "meteor-html-tools": "^1.2.4",
+ "meteor-htmljs": "^1.2.4",
+ "meteor-spacebars-compiler": "^1.2.4"
+ },
+ "dependencies": {
+ "loader-utils": {
+ "version": "0.2.17",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
+ "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=",
+ "dev": true,
+ "requires": {
+ "big.js": "^3.1.3",
+ "emojis-list": "^2.0.0",
+ "json5": "^0.5.0",
+ "object-assign": "^4.0.1"
+ }
+ },
+ "lodash": {
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+ "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "dev": true
+ }
+ }
+ },
"@slack/client": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@slack/client/-/client-4.8.0.tgz",
@@ -2529,6 +2570,46 @@
}
}
},
+ "@storybook/addon-knobs": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-knobs/-/addon-knobs-5.2.4.tgz",
+ "integrity": "sha512-VYxbDARJs5RwTEOlcfa98tkDXLcRocB7QXLqt8wwCdXPIqkuoVeQLROXGYJm2NzSn49RyHPKUuVWnRhy34qBbQ==",
+ "dev": true,
+ "requires": {
+ "@storybook/addons": "5.2.4",
+ "@storybook/api": "5.2.4",
+ "@storybook/client-api": "5.2.4",
+ "@storybook/components": "5.2.4",
+ "@storybook/core-events": "5.2.4",
+ "@storybook/theming": "5.2.4",
+ "@types/react-color": "^3.0.1",
+ "copy-to-clipboard": "^3.0.8",
+ "core-js": "^3.0.1",
+ "escape-html": "^1.0.3",
+ "fast-deep-equal": "^2.0.1",
+ "global": "^4.3.2",
+ "lodash": "^4.17.11",
+ "prop-types": "^15.7.2",
+ "qs": "^6.6.0",
+ "react-color": "^2.17.0",
+ "react-lifecycles-compat": "^3.0.4",
+ "react-select": "^3.0.0"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+ "integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.9.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.0.tgz",
+ "integrity": "sha512-27RP4UotQORTpmNQDX8BHPukOnBP3p1uUJY5UnDhaJB+rMt9iMsok724XL+UHU23bEFOHRMQ2ZhI99qOWUMGFA==",
+ "dev": true
+ }
+ }
+ },
"@storybook/addon-links": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-5.2.4.tgz",
@@ -2559,6 +2640,33 @@
}
}
},
+ "@storybook/addon-viewport": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-5.2.4.tgz",
+ "integrity": "sha512-R49wSaiouSVBYeus5Xibv+XXX9Nc3/rZ1NB5yIgj658aDeuB8WgkHbM3dKd/GrWeVZWv3o4CjW81ernd3f8sdw==",
+ "dev": true,
+ "requires": {
+ "@storybook/addons": "5.2.4",
+ "@storybook/api": "5.2.4",
+ "@storybook/client-logger": "5.2.4",
+ "@storybook/components": "5.2.4",
+ "@storybook/core-events": "5.2.4",
+ "@storybook/theming": "5.2.4",
+ "core-js": "^3.0.1",
+ "global": "^4.3.2",
+ "memoizerific": "^1.11.3",
+ "prop-types": "^15.7.2",
+ "util-deprecate": "^1.0.2"
+ },
+ "dependencies": {
+ "core-js": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+ "integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
+ "dev": true
+ }
+ }
+ },
"@storybook/addons": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-5.2.4.tgz",
@@ -5295,6 +5403,15 @@
"csstype": "^2.2.0"
}
},
+ "@types/react-color": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@types/react-color/-/react-color-3.0.1.tgz",
+ "integrity": "sha512-J6mYm43Sid9y+OjZ7NDfJ2VVkeeuTPNVImNFITgQNXodHteKfl/t/5pAR5Z9buodZ2tCctsZjgiMlQOpfntakw==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/react-syntax-highlighter": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-10.1.0.tgz",
@@ -12387,6 +12504,15 @@
"utila": "~0.4"
}
},
+ "dom-helpers": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
+ "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.1.2"
+ }
+ },
"dom-serializer": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz",
@@ -19399,6 +19525,12 @@
"resolved": "https://registry.npmjs.org/match-at/-/match-at-0.1.1.tgz",
"integrity": "sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q=="
},
+ "material-colors": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz",
+ "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==",
+ "dev": true
+ },
"math-interval-parser": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-interval-parser/-/math-interval-parser-1.1.0.tgz",
@@ -19705,6 +19837,40 @@
}
}
},
+ "meteor-blaze-tools": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/meteor-blaze-tools/-/meteor-blaze-tools-1.5.0.tgz",
+ "integrity": "sha1-Ooyy2puO9fFP+Tc4VrjEqYeTvRw=",
+ "dev": true,
+ "requires": {
+ "meteor-core": "^1.2.0",
+ "meteor-htmljs": "^1.2.0"
+ }
+ },
+ "meteor-core": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/meteor-core/-/meteor-core-1.3.1.tgz",
+ "integrity": "sha1-Ql3Py8oLRQQjAlBKXnF9wRN6os8=",
+ "dev": true
+ },
+ "meteor-html-tools": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/meteor-html-tools/-/meteor-html-tools-1.5.0.tgz",
+ "integrity": "sha1-RGnGNccrKqtSUnAIFkAK5DMwQ8M=",
+ "dev": true,
+ "requires": {
+ "meteor-core": "^1.2.0"
+ }
+ },
+ "meteor-htmljs": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/meteor-htmljs/-/meteor-htmljs-1.5.0.tgz",
+ "integrity": "sha1-FMxvcfvK9XBSCR61vq5Z8vBbc98=",
+ "dev": true,
+ "requires": {
+ "meteor-core": "^1.2.0"
+ }
+ },
"meteor-node-stubs": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/meteor-node-stubs/-/meteor-node-stubs-0.4.1.tgz",
@@ -19881,6 +20047,17 @@
"integrity": "sha512-HP6tOr67z/9XU2Dr0F2SSr8WRTuE23AG9Dj578DCJPEYHs67OLKBviU8A8rwvbwMD7Lu2+Of+yAMz2Wd8r4yxg==",
"dev": true
},
+ "meteor-spacebars-compiler": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/meteor-spacebars-compiler/-/meteor-spacebars-compiler-1.3.2.tgz",
+ "integrity": "sha1-KcRzTt1FgfRk1w4UMD8N7A3RSVs=",
+ "dev": true,
+ "requires": {
+ "meteor-blaze-tools": "^1.2.0",
+ "meteor-html-tools": "^1.2.0",
+ "meteor-htmljs": "^1.2.0"
+ }
+ },
"methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
@@ -23281,6 +23458,20 @@
"@babel/runtime": "^7.0.0"
}
},
+ "react-color": {
+ "version": "2.17.3",
+ "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.17.3.tgz",
+ "integrity": "sha512-1dtO8LqAVotPIChlmo6kLtFS1FP89ll8/OiA8EcFRDR+ntcK+0ukJgByuIQHRtzvigf26dV5HklnxDIvhON9VQ==",
+ "dev": true,
+ "requires": {
+ "@icons/material": "^0.2.4",
+ "lodash": "^4.17.11",
+ "material-colors": "^1.2.1",
+ "prop-types": "^15.5.10",
+ "reactcss": "^1.2.0",
+ "tinycolor2": "^1.4.1"
+ }
+ },
"react-dev-utils": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-9.1.0.tgz",
@@ -23736,6 +23927,15 @@
"prop-types": "^15.6.1"
}
},
+ "react-input-autosize": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz",
+ "integrity": "sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw==",
+ "dev": true,
+ "requires": {
+ "prop-types": "^15.5.8"
+ }
+ },
"react-inspector": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-3.0.2.tgz",
@@ -23820,6 +24020,39 @@
}
}
},
+ "react-select": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/react-select/-/react-select-3.0.8.tgz",
+ "integrity": "sha512-v9LpOhckLlRmXN5A6/mGGEft4FMrfaBFTGAnuPHcUgVId7Je42kTq9y0Z+Ye5z8/j0XDT3zUqza8gaRaI1PZIg==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.4.4",
+ "@emotion/cache": "^10.0.9",
+ "@emotion/core": "^10.0.9",
+ "@emotion/css": "^10.0.9",
+ "memoize-one": "^5.0.0",
+ "prop-types": "^15.6.0",
+ "react-input-autosize": "^2.2.2",
+ "react-transition-group": "^2.2.1"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.3.tgz",
+ "integrity": "sha512-kq6anf9JGjW8Nt5rYfEuGRaEAaH1mkv3Bbu6rYvLOpPh/RusSJXuKPEAoZ7L7gybZkchE8+NV5g9vKF4AGAtsA==",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.2"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.3",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
+ "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==",
+ "dev": true
+ }
+ }
+ },
"react-sizeme": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-2.6.8.tgz",
@@ -23863,6 +24096,27 @@
"prop-types": "^15.6.0"
}
},
+ "react-transition-group": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
+ "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==",
+ "dev": true,
+ "requires": {
+ "dom-helpers": "^3.4.0",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
+ "reactcss": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz",
+ "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==",
+ "dev": true,
+ "requires": {
+ "lodash": "^4.0.1"
+ }
+ },
"read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
diff --git a/package.json b/package.json
index 3d2ac4104ff..df56236eef0 100644
--- a/package.json
+++ b/package.json
@@ -99,8 +99,11 @@
"@octokit/rest": "^16.1.0",
"@rocket.chat/eslint-config": "^0.3.0",
"@rocket.chat/livechat": "^1.2.5",
+ "@settlin/spacebars-loader": "^1.0.7",
"@storybook/addon-actions": "^5.2.4",
+ "@storybook/addon-knobs": "^5.2.4",
"@storybook/addon-links": "^5.2.4",
+ "@storybook/addon-viewport": "^5.2.4",
"@storybook/addons": "^5.2.4",
"@storybook/react": "^5.2.4",
"acorn": "^6.0.7",