diff --git a/.storybook/.babelrc b/.storybook/.babelrc
index 6e8b075e8c4ea27433ca8298627fe3dce6775918..3f856fec45fb179713902581c38f0757e9d8e56f 100644
--- a/.storybook/.babelrc
+++ b/.storybook/.babelrc
@@ -5,9 +5,14 @@
       {
         "shippedProposals": true,
         "useBuiltIns": "usage",
-        "corejs": "3"
+        "corejs": "3",
+        "modules": "commonjs",
       }
     ],
-    "@babel/preset-react"
+    "@babel/preset-react",
+    "@babel/preset-flow"
+  ],
+  "plugins": [
+    "@babel/plugin-proposal-class-properties"
   ]
-}
\ No newline at end of file
+}
diff --git a/.storybook/addons.js b/.storybook/addons.js
index 6aed412d04afb1e1ae1d5c1a9f9bd08904cef636..9d64a3d0a8f3342da85a92d311fd2f7f151ae9e3 100644
--- a/.storybook/addons.js
+++ b/.storybook/addons.js
@@ -1,2 +1,4 @@
 import '@storybook/addon-actions/register';
+import '@storybook/addon-knobs/register';
 import '@storybook/addon-links/register';
+import '@storybook/addon-viewport/register';
diff --git a/.storybook/config.js b/.storybook/config.js
index 984a7b25e285c92f248ef94c1bf80622e42261e0..5de80993cf9fe96c1d27725ca6eff098d0f307c2 100644
--- a/.storybook/config.js
+++ b/.storybook/config.js
@@ -1,3 +1,49 @@
-import { configure } from '@storybook/react';
+import { action } from '@storybook/addon-actions';
+import { withKnobs }from '@storybook/addon-knobs';
+import { MINIMAL_VIEWPORTS, INITIAL_VIEWPORTS } from '@storybook/addon-viewport/dist/defaults';
+import { addDecorator, addParameters, configure } from '@storybook/react';
+import React from 'react';
+
+import { ConnectionStatusProvider } from '../client/components/providers/ConnectionStatusProvider.mock';
+import { TranslationProvider } from '../client/components/providers/TranslationProvider.mock';
+
+addParameters({
+	viewport: {
+		viewports: {
+			...MINIMAL_VIEWPORTS,
+			...INITIAL_VIEWPORTS,
+		},
+		defaultViewport: 'responsive',
+	},
+})
+
+addDecorator(function RocketChatDecorator(fn) {
+	const linkElement = document.getElementById('theme-styles') || document.createElement('link');
+	if (linkElement.id !== 'theme-styles') {
+		require('../app/theme/client/main.css');
+		require('../app/theme/client/vendor/fontello/css/fontello.css');
+		require('../client/RocketChat.font.css');
+		linkElement.setAttribute('id', 'theme-styles');
+		linkElement.setAttribute('rel', 'stylesheet');
+		linkElement.setAttribute('href', 'https://open.rocket.chat/theme.css');
+		document.head.appendChild(linkElement);
+	}
+
+	return <ConnectionStatusProvider connected status='connected' reconnect={action('reconnect')}>
+		<TranslationProvider>
+			<style>{`
+				body {
+					background-color: white;
+				}
+			`}</style>
+			<div dangerouslySetInnerHTML={{ __html: require('!!raw-loader!../private/public/icons.svg').default }} />
+			<div className='global-font-family color-primary-font-color'>
+				{fn()}
+			</div>
+		</TranslationProvider>
+	</ConnectionStatusProvider>;
+});
+
+addDecorator(withKnobs);
 
 configure(require.context('../client', true, /\.stories\.js$/), module);
diff --git a/.storybook/empty.js b/.storybook/empty.js
new file mode 100644
index 0000000000000000000000000000000000000000..ff8b4c56321a3362fc00224b01800f62466f9a1f
--- /dev/null
+++ b/.storybook/empty.js
@@ -0,0 +1 @@
+export default {};
diff --git a/.storybook/helpers.js b/.storybook/helpers.js
index 00ad512dc47bba6305253ab4c2acc77bcca42bde..63e4e038a4445eecfe278990a19dde5ec44ae341 100644
--- a/.storybook/helpers.js
+++ b/.storybook/helpers.js
@@ -1,44 +1 @@
-import { action } from '@storybook/addon-actions';
-import '@rocket.chat/icons/dist/font/RocketChat.minimal.css';
-import React from 'react';
-
-import '../app/theme/client/main.css';
-import { ConnectionStatusProvider } from '../client/components/providers/ConnectionStatusProvider.mock';
-import { TranslationProvider } from '../client/components/providers/TranslationProvider.mock';
-
-export const rocketChatWrapper = (fn) =>
-	<ConnectionStatusProvider connected status='connected' reconnect={action('reconnect')}>
-		<TranslationProvider>
-			<style>{`
-				body {
-					background-color: white;
-				}
-
-				.global-font-family {
-					font-family:
-						-apple-system,
-						BlinkMacSystemFont,
-						'Segoe UI',
-						Roboto,
-						Oxygen,
-						Ubuntu,
-						Cantarell,
-						'Helvetica Neue',
-						'Apple Color Emoji',
-						'Segoe UI Emoji',
-						'Segoe UI Symbol',
-						'Meiryo UI',
-						Arial,
-						sans-serif;
-				}
-
-				.color-primary-font-color {
-					color: #444;
-				}
-			`}</style>
-			<div dangerouslySetInnerHTML={{__html: require('!!raw-loader!../private/public/icons.svg').default}} />
-			<div className='global-font-family color-primary-font-color'>
-				{fn()}
-			</div>
-		</TranslationProvider>
-</ConnectionStatusProvider>;
+export const dummyDate = new Date(2015, 4, 19);
diff --git a/.storybook/meteor.js b/.storybook/meteor.js
new file mode 100644
index 0000000000000000000000000000000000000000..13f507c7ef32a9ee9f7237c6d094a10aabd25dc3
--- /dev/null
+++ b/.storybook/meteor.js
@@ -0,0 +1,74 @@
+export const Meteor = {
+	isClient: true,
+	isServer: false,
+	_localStorage: window.localStorage,
+	absoluteUrl: () => {},
+	userId: () => {},
+	Streamer: () => {},
+	startup: () => {},
+	methods: () => {},
+	call: () => {},
+};
+
+Meteor.absoluteUrl.defaultOptions = {};
+
+export const Tracker = {
+	autorun: () => ({
+		stop: () => {},
+	}),
+	nonreactive: (fn) => fn(),
+	Dependency: () => {},
+};
+
+export const Accounts = {};
+
+export const Mongo = {
+	Collection: () => ({
+		find: () => ({
+			observe: () => {},
+			fetch: () => [],
+		})
+	}),
+};
+
+export const ReactiveVar = () => ({
+	get: () => {},
+	set: () => {},
+});
+
+export const ReactiveDict = () => ({
+	get: () => {},
+	set: () => {},
+	all: () => {},
+});
+
+export const Template = () => ({
+	onCreated: () => {},
+	onRendered: () => {},
+	onDestroyed: () => {},
+	helpers: () => {},
+	events: () => {},
+});
+
+Template.registerHelper = () => {};
+Template.__checkName = () => {};
+
+export const Blaze = {
+	Template,
+	registerHelper: () => {},
+};
+
+window.Blaze = Blaze;
+
+export const check = () => {};
+
+export const FlowRouter = {
+	route: () => {}
+};
+
+export const BlazeLayout = {};
+
+export const Session = {
+	get: () => {},
+	set: () => {},
+};
diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js
index b9ededccd61c9b3f2d6059868c0e5d12e5bed3a4..b9d6efb821d66c9c929bd1f9d89f15913acd46c6 100644
--- a/.storybook/webpack.config.js
+++ b/.storybook/webpack.config.js
@@ -1,14 +1,11 @@
 'use strict';
 
-module.exports = async ({ config, mode }) => {
-	const cssRule = config.module.rules.find(({ test }) => test.test('index.css'));
-  cssRule.use[1].options.url = (url, resourcePath) => {
-		if (/^(\.\/)?images\//.test(url)) {
-			return false;
-		}
+const path = require('path');
+
+const webpack = require('webpack');
 
-		return true;
-	};
+module.exports = async ({ config }) => {
+	const cssRule = config.module.rules.find(({ test }) => test.test('index.css'));
 
 	cssRule.use[2].options.plugins = [
 		require('postcss-custom-properties')({ preserve: true }),
@@ -16,7 +13,36 @@ module.exports = async ({ config, mode }) => {
 		require('postcss-selector-not')(),
 		require('postcss-nested')(),
 		require('autoprefixer')(),
+		require('postcss-url')({ url: ({ absolutePath, relativePath, url }) => {
+			const absoluteDir = absolutePath.slice(0, -relativePath.length);
+			const relativeDir = path.relative(absoluteDir, path.resolve(__dirname, '../public'));
+			const newPath = path.join(relativeDir, url);
+			return newPath;
+		} }),
 	];
 
-  return config;
+	config.module.rules.push({
+		test: /\.info$/,
+		type: 'json',
+	});
+
+	config.module.rules.push({
+		test: /\.html$/,
+		use: '@settlin/spacebars-loader',
+	});
+
+	config.plugins.push(new webpack.NormalModuleReplacementPlugin(
+		/^meteor/,
+		require.resolve('./meteor.js'),
+	));
+
+	config.plugins.push(new webpack.NormalModuleReplacementPlugin(
+		/\.\/server\/index.js/,
+		require.resolve('./empty.js'),
+	));
+
+	config.mode = 'development';
+	config.optimization.usedExports = true;
+
+	return config;
 };
diff --git a/app/apps/client/admin/views.js b/app/apps/client/admin/views.js
new file mode 100644
index 0000000000000000000000000000000000000000..83f4f0a0e69e52afc82051c7c006e026ccbecfa9
--- /dev/null
+++ b/app/apps/client/admin/views.js
@@ -0,0 +1,11 @@
+import './modalTemplates/iframeModal.html';
+import './modalTemplates/iframeModal';
+import './marketplace';
+import './apps';
+import './appInstall.html';
+import './appInstall';
+import './appLogs.html';
+import './appLogs';
+import './appManage';
+import './appWhatIsIt.html';
+import './appWhatIsIt';
diff --git a/app/apps/client/index.js b/app/apps/client/index.js
index 887964154a900ee0bd72386f401662688e592b5b..a89134a70f5480e64084e78b1c06f086a5cd0a5c 100644
--- a/app/apps/client/index.js
+++ b/app/apps/client/index.js
@@ -1,14 +1,3 @@
-import './admin/modalTemplates/iframeModal.html';
-import './admin/modalTemplates/iframeModal';
-import './admin/marketplace';
-import './admin/apps';
-import './admin/appInstall.html';
-import './admin/appInstall';
-import './admin/appLogs.html';
-import './admin/appLogs';
-import './admin/appManage';
-import './admin/appWhatIsIt.html';
-import './admin/appWhatIsIt';
 import './routes';
 
 export { Apps } from './orchestrator';
diff --git a/app/apps/client/routes.js b/app/apps/client/routes.js
index 1a44f4d74bffeb03d803a5fe21388d33b1b6b7ec..914137e5f72fcb00fadb3f1a9c581b0ed0d9c18d 100644
--- a/app/apps/client/routes.js
+++ b/app/apps/client/routes.js
@@ -7,6 +7,7 @@ FlowRouter.route('/admin/apps/what-is-it', {
 	name: 'apps-what-is-it',
 	action: async () => {
 		// TODO: render loading indicator
+		await import('./admin/views');
 		if (await Apps.isEnabled()) {
 			FlowRouter.go('apps');
 		} else {
@@ -18,6 +19,7 @@ FlowRouter.route('/admin/apps/what-is-it', {
 const createAppsRouteAction = (centerTemplate) => async () => {
 	// TODO: render loading indicator
 	if (await Apps.isEnabled()) {
+		await import('./admin/views');
 		BlazeLayout.render('main', { center: centerTemplate, old: true }); // TODO remove old
 	} else {
 		FlowRouter.go('apps-what-is-it');
diff --git a/app/authorization/client/index.js b/app/authorization/client/index.js
index 709df4e2f38c80cef8d3a187afd16624148ae797..7ff5353f1f7956ae534b5be4c78ae8ab5713494b 100644
--- a/app/authorization/client/index.js
+++ b/app/authorization/client/index.js
@@ -4,10 +4,6 @@ import './usersNameChanged';
 import './requiresPermission.html';
 import './route';
 import './startup';
-import './views/permissions.html';
-import './views/permissions';
-import './views/permissionsRole.html';
-import './views/permissionsRole';
 
 export {
 	hasAllPermission,
diff --git a/app/authorization/client/route.js b/app/authorization/client/route.js
index 5d54d53c8888d264620582a4ab602eb168badf6f..2415242d6eb9e59803640712a3628f8a94dc0dbf 100644
--- a/app/authorization/client/route.js
+++ b/app/authorization/client/route.js
@@ -5,7 +5,8 @@ import { t } from '../../utils/client';
 
 FlowRouter.route('/admin/permissions', {
 	name: 'admin-permissions',
-	action(/* params*/) {
+	async action(/* params*/) {
+		await import('./views');
 		return BlazeLayout.render('main', {
 			center: 'permissions',
 			pageTitle: t('Permissions'),
@@ -15,7 +16,8 @@ FlowRouter.route('/admin/permissions', {
 
 FlowRouter.route('/admin/permissions/:name?/edit', {
 	name: 'admin-permissions-edit',
-	action(/* params*/) {
+	async action(/* params*/) {
+		await import('./views');
 		return BlazeLayout.render('main', {
 			center: 'pageContainer',
 			pageTitle: t('Role_Editing'),
@@ -26,7 +28,8 @@ FlowRouter.route('/admin/permissions/:name?/edit', {
 
 FlowRouter.route('/admin/permissions/new', {
 	name: 'admin-permissions-new',
-	action(/* params*/) {
+	async action(/* params*/) {
+		await import('./views');
 		return BlazeLayout.render('main', {
 			center: 'pageContainer',
 			pageTitle: t('Role_Editing'),
diff --git a/app/authorization/client/views/index.js b/app/authorization/client/views/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..ba54dffa5c020615b38e1f33577649bceb6a574f
--- /dev/null
+++ b/app/authorization/client/views/index.js
@@ -0,0 +1,4 @@
+import './permissions.html';
+import './permissions';
+import './permissionsRole.html';
+import './permissionsRole';
diff --git a/app/callbacks/lib/callbacks.js b/app/callbacks/lib/callbacks.js
index 193b6be06ed6f4a9e48125c8ccd9603470ef9700..efc44c0ee59dc53e090be090e0fbd74f9741ac6b 100644
--- a/app/callbacks/lib/callbacks.js
+++ b/app/callbacks/lib/callbacks.js
@@ -56,7 +56,7 @@ const createCallbackTimed = (hook, callbacks) =>
 const create = (hook, cbs) =>
 	(timed ? createCallbackTimed(hook, cbs) : createCallback(hook, cbs));
 const combinedCallbacks = new Map();
-this.combinedCallbacks = combinedCallbacks;
+
 /*
 * Callback priorities
 */
diff --git a/app/cloud/client/admin/index.js b/app/cloud/client/admin/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..92cb6032c24ef91a09c3b4d2c36fb08eda0fd537
--- /dev/null
+++ b/app/cloud/client/admin/index.js
@@ -0,0 +1,2 @@
+import './cloud';
+import './callback';
diff --git a/app/cloud/client/index.js b/app/cloud/client/index.js
index d0241a21c12e2e2ebc417510703e054d312d26a0..c757fa04a0b11bdb434368ee3128c542cb2ab354 100644
--- a/app/cloud/client/index.js
+++ b/app/cloud/client/index.js
@@ -1,6 +1,3 @@
-import './admin/callback';
-import './admin/cloud';
-
 import { BlazeLayout } from 'meteor/kadira:blaze-layout';
 import { FlowRouter } from 'meteor/kadira:flow-router';
 
@@ -9,14 +6,16 @@ import { hasAtLeastOnePermission } from '../../authorization';
 
 FlowRouter.route('/admin/cloud', {
 	name: 'cloud-config',
-	action() {
+	async action() {
+		await import('./admin');
 		BlazeLayout.render('main', { center: 'cloud', old: true });
 	},
 });
 
 FlowRouter.route('/admin/cloud/oauth-callback', {
 	name: 'cloud-oauth-callback',
-	action() {
+	async action() {
+		await import('./admin');
 		BlazeLayout.render('main', { center: 'cloudCallback', old: true });
 	},
 });
diff --git a/app/custom-sounds/client/admin/route.js b/app/custom-sounds/client/admin/route.js
index cf12f9949f6a84878776e5fe1cbdf0e8bc971ec9..5aebea1934f887430bc98a4cc5442b870afa46b6 100644
--- a/app/custom-sounds/client/admin/route.js
+++ b/app/custom-sounds/client/admin/route.js
@@ -7,7 +7,8 @@ FlowRouter.route('/admin/custom-sounds', {
 	subscriptions(/* params, queryParams*/) {
 		this.register('customSounds', Meteor.subscribe('customSounds'));
 	},
-	action(/* params*/) {
+	async action(/* params*/) {
+		await import('./views');
 		BlazeLayout.render('main', { center: 'adminSounds' });
 	},
 });
diff --git a/app/custom-sounds/client/admin/views.js b/app/custom-sounds/client/admin/views.js
new file mode 100644
index 0000000000000000000000000000000000000000..3a2397b2bdaa6c48443c4b0e75f44a963df53777
--- /dev/null
+++ b/app/custom-sounds/client/admin/views.js
@@ -0,0 +1,8 @@
+import './adminSoundEdit.html';
+import './adminSoundInfo.html';
+import './adminSounds.html';
+import './adminSounds';
+import './soundEdit.html';
+import './soundEdit';
+import './soundInfo.html';
+import './soundInfo';
diff --git a/app/custom-sounds/client/index.js b/app/custom-sounds/client/index.js
index ca11995874f103131f15e6c74ced19c9e88bc2b9..918e3247240ca92bdde71a733de4768b3678c359 100644
--- a/app/custom-sounds/client/index.js
+++ b/app/custom-sounds/client/index.js
@@ -1,13 +1,5 @@
 import './notifications/deleteCustomSound';
 import './notifications/updateCustomSound';
-import './admin/adminSoundEdit.html';
-import './admin/adminSoundInfo.html';
-import './admin/adminSounds.html';
-import './admin/adminSounds';
-import './admin/soundEdit.html';
-import './admin/soundEdit';
-import './admin/soundInfo.html';
-import './admin/soundInfo';
 import './admin/route';
 import './admin/startup';
 
diff --git a/app/emoji-custom/client/admin/route.js b/app/emoji-custom/client/admin/route.js
index 1b20c5a0abe2f3ac45fded4b934c188d8f674751..169ff2bb637a215815ce65c150dd522fd4f1dc7d 100644
--- a/app/emoji-custom/client/admin/route.js
+++ b/app/emoji-custom/client/admin/route.js
@@ -3,7 +3,8 @@ import { BlazeLayout } from 'meteor/kadira:blaze-layout';
 
 FlowRouter.route('/admin/emoji-custom', {
 	name: 'emoji-custom',
-	action(/* params*/) {
+	async action(/* params*/) {
+		await import('./views');
 		BlazeLayout.render('main', { center: 'adminEmoji' });
 	},
 });
diff --git a/app/emoji-custom/client/admin/views.js b/app/emoji-custom/client/admin/views.js
new file mode 100644
index 0000000000000000000000000000000000000000..9c058a4610eb345286faaeaa8fab9071a21abc09
--- /dev/null
+++ b/app/emoji-custom/client/admin/views.js
@@ -0,0 +1,9 @@
+import './adminEmoji.html';
+import './adminEmoji';
+import './adminEmojiEdit.html';
+import './adminEmojiInfo.html';
+import './emojiEdit.html';
+import './emojiEdit';
+import './emojiInfo.html';
+import './emojiInfo';
+import './emojiPreview.html';
diff --git a/app/emoji-custom/client/index.js b/app/emoji-custom/client/index.js
index 06b3776947690c3fd85a76e0504d2650cae20b43..8b6f4fc9c0fc1b8831cb618dadb1bb181b46ac1c 100644
--- a/app/emoji-custom/client/index.js
+++ b/app/emoji-custom/client/index.js
@@ -2,13 +2,4 @@ import './lib/emojiCustom';
 import './notifications/deleteEmojiCustom';
 import './notifications/updateEmojiCustom';
 import './admin/startup';
-import './admin/adminEmoji.html';
-import './admin/adminEmoji';
-import './admin/adminEmojiEdit.html';
-import './admin/adminEmojiInfo.html';
-import './admin/emojiEdit.html';
-import './admin/emojiEdit';
-import './admin/emojiInfo.html';
-import './admin/emojiInfo';
-import './admin/emojiPreview.html';
 import './admin/route';
diff --git a/app/importer/client/admin/views.js b/app/importer/client/admin/views.js
new file mode 100644
index 0000000000000000000000000000000000000000..5e6c2fc3ed0e483a3ff449714286d1f827d0f538
--- /dev/null
+++ b/app/importer/client/admin/views.js
@@ -0,0 +1,8 @@
+import './adminImport.html';
+import './adminImport';
+import './adminImportHistory.html';
+import './adminImportHistory';
+import './adminImportPrepare.html';
+import './adminImportPrepare';
+import './adminImportProgress.html';
+import './adminImportProgress';
diff --git a/app/importer/client/index.js b/app/importer/client/index.js
index ff06c8ee496b17e5feac1d518b5db25ca1af5c1d..68c66ec4b4eabdc4c8a42e5255abbc056766bc2b 100644
--- a/app/importer/client/index.js
+++ b/app/importer/client/index.js
@@ -1,15 +1,43 @@
+import { FlowRouter } from 'meteor/kadira:flow-router';
+import { BlazeLayout } from 'meteor/kadira:blaze-layout';
+
 import { ImporterWebsocketReceiver } from './ImporterWebsocketReceiver';
 import { Importers } from '../lib/Importers';
 import { ImporterInfo } from '../lib/ImporterInfo';
 import { ProgressStep } from '../lib/ImporterProgressStep';
-import './admin/adminImport.html';
-import './admin/adminImport';
-import './admin/adminImportHistory.html';
-import './admin/adminImportHistory';
-import './admin/adminImportPrepare.html';
-import './admin/adminImportPrepare';
-import './admin/adminImportProgress.html';
-import './admin/adminImportProgress';
+
+
+FlowRouter.route('/admin/import', {
+	name: 'admin-import',
+	async action() {
+		await import('./admin/views');
+		BlazeLayout.render('main', { center: 'adminImport' });
+	},
+});
+
+FlowRouter.route('/admin/import/history', {
+	name: 'admin-import-history',
+	async action() {
+		await import('./admin/views');
+		BlazeLayout.render('main', { center: 'adminImportHistory' });
+	},
+});
+
+FlowRouter.route('/admin/import/prepare/:importer', {
+	name: 'admin-import-prepare',
+	async action() {
+		await import('./admin/views');
+		BlazeLayout.render('main', { center: 'adminImportPrepare' });
+	},
+});
+
+FlowRouter.route('/admin/import/progress/:importer', {
+	name: 'admin-import-progress',
+	async action() {
+		await import('./admin/views');
+		BlazeLayout.render('main', { center: 'adminImportProgress' });
+	},
+});
 
 export {
 	Importers,
diff --git a/app/integrations/client/index.js b/app/integrations/client/index.js
index 2da38377a2f02f601627f467dac20c4cae439300..87ac557c71d989d75ccdd840543732a73df3efd6 100644
--- a/app/integrations/client/index.js
+++ b/app/integrations/client/index.js
@@ -2,14 +2,3 @@ import '../lib/rocketchat';
 import './collections';
 import './startup';
 import './route';
-import './views/integrations.html';
-import './views/integrations';
-import './views/integrationsNew.html';
-import './views/integrationsNew';
-import './views/integrationsIncoming.html';
-import './views/integrationsIncoming';
-import './views/integrationsOutgoing.html';
-import './views/integrationsOutgoing';
-import './views/integrationsOutgoingHistory.html';
-import './views/integrationsOutgoingHistory';
-import './views/additional/zapier.html';
diff --git a/app/integrations/client/route.js b/app/integrations/client/route.js
index 944188db98cd4cad3a02860bef4f75bab77fb7a7..d9b85202579a8d72c926c04ca1a68f2ee824dc4d 100644
--- a/app/integrations/client/route.js
+++ b/app/integrations/client/route.js
@@ -4,12 +4,17 @@ import { BlazeLayout } from 'meteor/kadira:blaze-layout';
 
 import { t } from '../../utils';
 
+const dynamic = () => {
+	import('./views');
+};
+
 FlowRouter.route('/admin/integrations', {
 	name: 'admin-integrations',
 	subscriptions() {
 		this.register('integrations', Meteor.subscribe('integrations'));
 	},
-	action() {
+	async action() {
+		await dynamic();
 		return BlazeLayout.render('main', {
 			center: 'integrations',
 			pageTitle: t('Integrations'),
@@ -22,7 +27,8 @@ FlowRouter.route('/admin/integrations/new', {
 	subscriptions() {
 		this.register('integrations', Meteor.subscribe('integrations'));
 	},
-	action() {
+	async action() {
+		await dynamic();
 		return BlazeLayout.render('main', {
 			center: 'integrationsNew',
 			pageTitle: t('Integration_New'),
@@ -35,7 +41,8 @@ FlowRouter.route('/admin/integrations/incoming/:id?', {
 	subscriptions() {
 		this.register('integrations', Meteor.subscribe('integrations'));
 	},
-	action(params) {
+	async action(params) {
+		await dynamic();
 		return BlazeLayout.render('main', {
 			center: 'pageSettingsContainer',
 			pageTitle: t('Integration_Incoming_WebHook'),
@@ -47,7 +54,8 @@ FlowRouter.route('/admin/integrations/incoming/:id?', {
 
 FlowRouter.route('/admin/integrations/outgoing/:id?', {
 	name: 'admin-integrations-outgoing',
-	action(params) {
+	async action(params) {
+		await dynamic();
 		return BlazeLayout.render('main', {
 			center: 'integrationsOutgoing',
 			pageTitle: t('Integration_Outgoing_WebHook'),
@@ -58,7 +66,8 @@ FlowRouter.route('/admin/integrations/outgoing/:id?', {
 
 FlowRouter.route('/admin/integrations/outgoing/:id?/history', {
 	name: 'admin-integrations-outgoing-history',
-	action(params) {
+	async action(params) {
+		await dynamic();
 		return BlazeLayout.render('main', {
 			center: 'integrationsOutgoingHistory',
 			pageTitle: t('Integration_Outgoing_WebHook_History'),
@@ -69,7 +78,8 @@ FlowRouter.route('/admin/integrations/outgoing/:id?/history', {
 
 FlowRouter.route('/admin/integrations/additional/zapier', {
 	name: 'admin-integrations-additional-zapier',
-	action() {
+	async action() {
+		await dynamic();
 		BlazeLayout.render('main', {
 			center: 'integrationsAdditionalZapier',
 		});
diff --git a/app/integrations/client/views/index.js b/app/integrations/client/views/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..f7c6282cbd3538ca7746070f7cad628133428d47
--- /dev/null
+++ b/app/integrations/client/views/index.js
@@ -0,0 +1,11 @@
+import './integrations.html';
+import './integrations';
+import './integrationsNew.html';
+import './integrationsNew';
+import './integrationsIncoming.html';
+import './integrationsIncoming';
+import './integrationsOutgoing.html';
+import './integrationsOutgoing';
+import './integrationsOutgoingHistory.html';
+import './integrationsOutgoingHistory';
+import './additional/zapier.html';
diff --git a/app/logger/client/index.js b/app/logger/client/index.js
index 1cdc33f64edfd81d684b5bb4416da782a065d2f4..689a3ac95d83db440427c5076fa2c21ad2b3c2ae 100644
--- a/app/logger/client/index.js
+++ b/app/logger/client/index.js
@@ -1,3 +1,2 @@
 import './logger';
 import './viewLogs';
-import './views/viewLogs';
diff --git a/app/logger/client/viewLogs.js b/app/logger/client/viewLogs.js
index 112a947fc70b67e99058ce55fc5fde9118a2fa60..9c488140b920799345bf4ae62a538caa0bc9cffb 100644
--- a/app/logger/client/viewLogs.js
+++ b/app/logger/client/viewLogs.js
@@ -22,7 +22,8 @@ Meteor.startup(function() {
 
 FlowRouter.route('/admin/view-logs', {
 	name: 'admin-view-logs',
-	action() {
+	async action() {
+		await import('./views/viewLogs');
 		return BlazeLayout.render('main', {
 			center: 'pageSettingsContainer',
 			pageTitle: t('View_Logs'),
diff --git a/app/mail-messages/client/index.js b/app/mail-messages/client/index.js
index 75419b8457309430f6af5d28863ab90db913551c..09634cf5172b24a8e3b611728a6dd6cf70eec9b1 100644
--- a/app/mail-messages/client/index.js
+++ b/app/mail-messages/client/index.js
@@ -1,6 +1,2 @@
 import './startup';
 import './router';
-import './views/mailer.html';
-import './views/mailer';
-import './views/mailerUnsubscribe.html';
-import './views/mailerUnsubscribe';
diff --git a/app/mail-messages/client/router.js b/app/mail-messages/client/router.js
index 9e706f11be74ef826b01856fb832c9f568a1f951..fd738b632d8bde6ae4f78e813ac8c5eae2d409d1 100644
--- a/app/mail-messages/client/router.js
+++ b/app/mail-messages/client/router.js
@@ -4,7 +4,8 @@ import { BlazeLayout } from 'meteor/kadira:blaze-layout';
 
 FlowRouter.route('/admin/mailer', {
 	name: 'admin-mailer',
-	action() {
+	async action() {
+		await import('./views');
 		return BlazeLayout.render('main', {
 			center: 'mailer',
 		});
@@ -13,7 +14,8 @@ FlowRouter.route('/admin/mailer', {
 
 FlowRouter.route('/mailer/unsubscribe/:_id/:createdAt', {
 	name: 'mailer-unsubscribe',
-	action(params) {
+	async action(params) {
+		await import('./views');
 		Meteor.call('Mailer:unsubscribe', params._id, params.createdAt);
 		return BlazeLayout.render('mailerUnsubscribe');
 	},
diff --git a/app/mail-messages/client/views/index.js b/app/mail-messages/client/views/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..55bb6a5d7a7772c92fc108d87857d6a3de3b9e17
--- /dev/null
+++ b/app/mail-messages/client/views/index.js
@@ -0,0 +1,4 @@
+import './mailer.html';
+import './mailer';
+import './mailerUnsubscribe.html';
+import './mailerUnsubscribe';
diff --git a/app/oauth2-server-config/client/admin/route.js b/app/oauth2-server-config/client/admin/route.js
index df568f2bca603c62f58f201bc757f144ed0e5d0a..340f403b935140821fae845bbe24dc6221860297 100644
--- a/app/oauth2-server-config/client/admin/route.js
+++ b/app/oauth2-server-config/client/admin/route.js
@@ -5,7 +5,8 @@ import { t } from '../../../utils';
 
 FlowRouter.route('/admin/oauth-apps', {
 	name: 'admin-oauth-apps',
-	action() {
+	async action() {
+		await import('./views');
 		return BlazeLayout.render('main', {
 			center: 'oauthApps',
 			pageTitle: t('OAuth_Applications'),
@@ -15,7 +16,8 @@ FlowRouter.route('/admin/oauth-apps', {
 
 FlowRouter.route('/admin/oauth-app/:id?', {
 	name: 'admin-oauth-app',
-	action(params) {
+	async action(params) {
+		await import('./views');
 		return BlazeLayout.render('main', {
 			center: 'pageSettingsContainer',
 			pageTitle: t('OAuth_Application'),
diff --git a/app/oauth2-server-config/client/admin/views/index.js b/app/oauth2-server-config/client/admin/views/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..071605a56b89c37ce20723d7f3cac749408268c3
--- /dev/null
+++ b/app/oauth2-server-config/client/admin/views/index.js
@@ -0,0 +1,4 @@
+import './oauthApp.html';
+import './oauthApp';
+import './oauthApps.html';
+import './oauthApps';
diff --git a/app/oauth2-server-config/client/index.js b/app/oauth2-server-config/client/index.js
index 27d8d4052ce88ce44c485411ee4ef3f0666bb354..1c579a2712b01b852111666f3a94a379e2cd1dbc 100644
--- a/app/oauth2-server-config/client/index.js
+++ b/app/oauth2-server-config/client/index.js
@@ -2,7 +2,3 @@ import './oauth/oauth2-client.html';
 import './oauth/oauth2-client';
 import './admin/startup';
 import './admin/route';
-import './admin/views/oauthApp.html';
-import './admin/views/oauthApp';
-import './admin/views/oauthApps.html';
-import './admin/views/oauthApps';
diff --git a/app/theme/client/imports/general/base_old.css b/app/theme/client/imports/general/base_old.css
index 71374c4145f96465f7a2c62cfcffb160c01b6b9f..183a7e9f732bdb1c9276153abbda2fe66b98300e 100644
--- a/app/theme/client/imports/general/base_old.css
+++ b/app/theme/client/imports/general/base_old.css
@@ -383,7 +383,7 @@
 
 /* input & form styles */
 
-.rc-old input:focus {
+.rc-old :not(.rcx-input-control):focus {
 	outline: none;
 	box-shadow: 0 0 0;
 }
@@ -4196,20 +4196,6 @@ rc-old select,
 		}
 	}
 
-	& a.meteor {
-		position: fixed;
-		right: 30px;
-		bottom: 20px;
-
-		width: 100px;
-		height: 50px;
-
-		text-indent: -9999em;
-
-		background: url(images/meteor.png) no-repeat center center;
-		background-size: 100% auto;
-	}
-
 	& .share {
 		min-height: 40px;
 
diff --git a/app/theme/client/vendor/fontello/css/fontello.css b/app/theme/client/vendor/fontello/css/fontello.css
index 0caceef9127f7d89d165ead214b75e0562c6a307..47c2859f0c774542268b0d7e06c4792ce5af86b0 100755
--- a/app/theme/client/vendor/fontello/css/fontello.css
+++ b/app/theme/client/vendor/fontello/css/fontello.css
@@ -1,60 +1,50 @@
 @font-face {
   font-family: 'fontello';
-  src: url('../font/fontello.eot?9377982');
-  src: url('../font/fontello.eot?9377982#iefix') format('embedded-opentype'),
-       url('../font/fontello.woff2?9377982') format('woff2'),
-       url('../font/fontello.woff?9377982') format('woff'),
-       url('../font/fontello.ttf?9377982') format('truetype'),
-       url('../font/fontello.svg?9377982#fontello') format('svg');
+  src: url('/font/fontello.eot');
+  src: url('/font/fontello.eot#iefix') format('embedded-opentype'),
+       url('/font/fontello.woff2') format('woff2'),
+       url('/font/fontello.woff') format('woff'),
+       url('/font/fontello.ttf') format('truetype'),
+       url('/font/fontello.svg#fontello') format('svg');
   font-weight: normal;
   font-style: normal;
 }
-/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
-/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
-/*
-@media screen and (-webkit-min-device-pixel-ratio:0) {
-  @font-face {
-    font-family: 'fontello';
-    src: url('../font/fontello.svg?9377982#fontello') format('svg');
-  }
-}
-*/
- 
+
  [class^="icon-"]:before, [class*=" icon-"]:before {
   font-family: "fontello";
   font-style: normal;
   font-weight: normal;
   speak: none;
- 
+
   display: inline-block;
   text-decoration: inherit;
   width: 1em;
   margin-right: .2em;
   text-align: center;
   /* opacity: .8; */
- 
+
   /* For safety - reset parent styles, that can break glyph codes*/
   font-variant: normal;
   text-transform: none;
- 
+
   /* fix buttons height, for twitter bootstrap */
   line-height: 1em;
- 
+
   /* Animation center compensation - margins should be symmetric */
   /* remove if not needed */
   margin-left: .2em;
- 
+
   /* you can be more comfortable with increased icons size */
   /* font-size: 120%; */
- 
+
   /* Font smoothing. That was taken from TWBS */
   -webkit-font-smoothing: antialiased;
   -moz-osx-font-smoothing: grayscale;
- 
+
   /* Uncomment for 3D effect */
   /* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
 }
- 
+
 .icon-parking:before { content: '\21'; } /* '!' */
 .icon-bedroom:before { content: '\22'; } /* '&quot;' */
 .icon-elevator:before { content: '\23'; } /* '#' */
@@ -540,4 +530,4 @@
 .icon-markdown:before { content: '\e98c'; } /* '' */
 .icon-no-newline:before { content: '\e98d'; } /* '' */
 .icon-tools:before { content: '\e98e'; } /* '' */
-.icon-tape:before { content: '\e98f'; } /* '' */
\ No newline at end of file
+.icon-tape:before { content: '\e98f'; } /* '' */
diff --git a/app/ui-admin/client/SettingsCachedCollection.js b/app/ui-admin/client/SettingsCachedCollection.js
index edfbb64c69fb3c54440b299fd637e932d52ff1c8..6637eee28940e9559ad7a903b032db0887308c8c 100644
--- a/app/ui-admin/client/SettingsCachedCollection.js
+++ b/app/ui-admin/client/SettingsCachedCollection.js
@@ -6,7 +6,6 @@ export class PrivateSettingsCachedCollection extends CachedCollection {
 		super({
 			name: 'private-settings',
 			eventType: 'onLogged',
-			useCache: false,
 		});
 	}
 
diff --git a/app/ui-admin/client/index.js b/app/ui-admin/client/index.js
index 2a0a65da65cba4798ae5483d516dc0b09194da24..8f4ee8618186845dbbbc20a90b18160843c06ced 100644
--- a/app/ui-admin/client/index.js
+++ b/app/ui-admin/client/index.js
@@ -1,18 +1,9 @@
 import './admin.html';
 import './adminFlex.html';
-import './rooms/adminRooms.html';
-import './rooms/adminRoomInfo.html';
-import './rooms/adminRoomInfo';
-import './rooms/channelSettingsDefault.html';
-import './rooms/channelSettingsDefault';
-import './users/adminInviteUser.html';
-import './users/adminUserChannels.html';
-import './users/adminUserEdit.html';
-import './users/adminUserInfo.html';
-import './users/adminUsers.html';
 import './admin';
 import './adminFlex';
-import './rooms/adminRooms';
-import './users/adminInviteUser';
-import './users/adminUserChannels';
-import './users/adminUsers';
+import './routes';
+
+
+// import './users/adminUserChannels';
+// import './users/adminUserChannels.html';
diff --git a/app/ui-admin/client/rooms/views.js b/app/ui-admin/client/rooms/views.js
new file mode 100644
index 0000000000000000000000000000000000000000..cfd9eee52505e5ace807a7486fb54c73cddef995
--- /dev/null
+++ b/app/ui-admin/client/rooms/views.js
@@ -0,0 +1,6 @@
+import './adminRooms.html';
+import './adminRoomInfo.html';
+import './adminRoomInfo';
+import './channelSettingsDefault.html';
+import './channelSettingsDefault';
+import './adminRooms';
diff --git a/app/ui-admin/client/routes.js b/app/ui-admin/client/routes.js
new file mode 100644
index 0000000000000000000000000000000000000000..cf87a26258f5dd8eff8d3f5cab83b18791e09937
--- /dev/null
+++ b/app/ui-admin/client/routes.js
@@ -0,0 +1,19 @@
+import { FlowRouter } from 'meteor/kadira:flow-router';
+import { BlazeLayout } from 'meteor/kadira:blaze-layout';
+
+FlowRouter.route('/admin/users', {
+	name: 'admin-users',
+	async action() {
+		await import('./users/views');
+		BlazeLayout.render('main', { center: 'adminUsers' });
+	},
+});
+
+
+FlowRouter.route('/admin/rooms', {
+	name: 'admin-rooms',
+	async action() {
+		await import('./rooms/views');
+		BlazeLayout.render('main', { center: 'adminRooms' });
+	},
+});
diff --git a/app/ui-admin/client/users/adminUserChannels.html b/app/ui-admin/client/users/adminUserChannels.html
deleted file mode 100644
index a1b85e7fc76f378634c5b952aadd090588199be2..0000000000000000000000000000000000000000
--- a/app/ui-admin/client/users/adminUserChannels.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<template name="adminUserChannels">
-	{{#unless hasPermission 'view-full-other-user-info'}}
-		<p>{{_ "You_are_not_authorized_to_view_this_page"}}</p>
-	{{else}}
-		<div class="user-info-channel">
-			<h3><a href="{{route}}"><i class="icon-{{type}}"></i> {{name}}</a></h3>
-		</div>
-	{{/unless}}
-</template>
\ No newline at end of file
diff --git a/app/ui-admin/client/users/adminUserChannels.js b/app/ui-admin/client/users/adminUserChannels.js
deleted file mode 100644
index 3eeacc50e7a33096b54459712fbba992e820c71e..0000000000000000000000000000000000000000
--- a/app/ui-admin/client/users/adminUserChannels.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { FlowRouter } from 'meteor/kadira:flow-router';
-import { Template } from 'meteor/templating';
-
-Template.adminUserChannels.helpers({
-	type() {
-		if (this.t === 'd') {
-			return 'at';
-		} if (this.t === 'p') {
-			return 'lock';
-		}
-		return 'hash';
-	},
-	route() {
-		switch (this.t) {
-			case 'd':
-				return FlowRouter.path('direct', {
-					username: this.name,
-				});
-			case 'p':
-				return FlowRouter.path('group', {
-					name: this.name,
-				});
-			case 'c':
-				return FlowRouter.path('channel', {
-					name: this.name,
-				});
-		}
-	},
-});
diff --git a/app/ui-admin/client/users/views.js b/app/ui-admin/client/users/views.js
new file mode 100644
index 0000000000000000000000000000000000000000..da3c6d5414b18652062e073bdeeb9d42f057d4e9
--- /dev/null
+++ b/app/ui-admin/client/users/views.js
@@ -0,0 +1,6 @@
+import './adminInviteUser.html';
+import './adminUserEdit.html';
+import './adminUserInfo.html';
+import './adminUsers.html';
+import './adminInviteUser';
+import './adminUsers';
diff --git a/app/ui-cached-collection/client/models/CachedCollection.js b/app/ui-cached-collection/client/models/CachedCollection.js
index 9dfa24856c020874177b39b5368a70a1ec230974..ea305ba81c00f765f6936f4a9dcbe7ee45edbe67 100644
--- a/app/ui-cached-collection/client/models/CachedCollection.js
+++ b/app/ui-cached-collection/client/models/CachedCollection.js
@@ -131,7 +131,6 @@ export class CachedCollection extends EventEmitter {
 		userRelated = true,
 		listenChangesForLoggedUsersOnly = false,
 		useSync = true,
-		useCache = true,
 		version = 8,
 		maxCacheTime = 60 * 60 * 24 * 30,
 		onSyncData = (/* action, record */) => {},
@@ -146,7 +145,6 @@ export class CachedCollection extends EventEmitter {
 		this.eventName = eventName || `${ name }-changed`;
 		this.eventType = eventType;
 		this.useSync = useSync;
-		this.useCache = useCache;
 		this.listenChangesForLoggedUsersOnly = listenChangesForLoggedUsersOnly;
 		this.version = version;
 		this.userRelated = userRelated;
diff --git a/app/user-status/client/admin/route.js b/app/user-status/client/admin/route.js
index d5c8c6be1e21a7e2daefd48a15233433b1481a35..fec4bab8d92c1c40a16eb4b68bd6de19f0569962 100644
--- a/app/user-status/client/admin/route.js
+++ b/app/user-status/client/admin/route.js
@@ -3,7 +3,8 @@ import { BlazeLayout } from 'meteor/kadira:blaze-layout';
 
 FlowRouter.route('/admin/user-status-custom', {
 	name: 'user-status-custom',
-	action(/* params */) {
+	async action(/* params */) {
+		await import('./views');
 		BlazeLayout.render('main', { center: 'adminUserStatus' });
 	},
 });
diff --git a/app/user-status/client/admin/views.js b/app/user-status/client/admin/views.js
new file mode 100644
index 0000000000000000000000000000000000000000..f7a4098c9b9d9f2cc203044e14aad6f412bee3fb
--- /dev/null
+++ b/app/user-status/client/admin/views.js
@@ -0,0 +1,9 @@
+import './adminUserStatus.html';
+import './adminUserStatus';
+import './adminUserStatusEdit.html';
+import './adminUserStatusInfo.html';
+import './userStatusEdit.html';
+import './userStatusEdit';
+import './userStatusInfo.html';
+import './userStatusInfo';
+import './userStatusPreview.html';
diff --git a/app/user-status/client/index.js b/app/user-status/client/index.js
index cd0736a72021e9f27874c1b8bc9b8cb688e96b7a..84c2a9c7579d1eca33ce61e4fd4576be305911f7 100644
--- a/app/user-status/client/index.js
+++ b/app/user-status/client/index.js
@@ -1,12 +1,3 @@
-import './admin/adminUserStatus.html';
-import './admin/adminUserStatus';
-import './admin/adminUserStatusEdit.html';
-import './admin/adminUserStatusInfo.html';
-import './admin/userStatusEdit.html';
-import './admin/userStatusEdit';
-import './admin/userStatusInfo.html';
-import './admin/userStatusInfo';
-import './admin/userStatusPreview.html';
 import './admin/route';
 import './admin/startup';
 
diff --git a/client/RocketChat.font.css b/client/RocketChat.font.css
deleted file mode 100644
index 7b9074ad89b9c7279d7d92898ef12a7927c67558..0000000000000000000000000000000000000000
--- a/client/RocketChat.font.css
+++ /dev/null
@@ -1,14 +0,0 @@
-@font-face {
-	font-family: 'RocketChat';
-	font-weight: 400;
-	font-style: normal;
-	font-display: auto;
-
-	src: url('/fonts/RocketChat.eot');
-	src:
-		url('/fonts/RocketChat.eot?#iefix') format('embedded-opentype'),
-		url('/fonts/RocketChat.woff2') format('woff2'),
-		url('/fonts/RocketChat.woff') format('woff'),
-		url('/fonts/RocketChat.ttf') format('truetype'),
-		url('/fonts/RocketChat.svg#RocketChat') format('svg');
-}
diff --git a/client/components/admin/hooks.js b/client/components/admin/hooks.js
new file mode 100644
index 0000000000000000000000000000000000000000..da2ac3b93ef7a8b143459797dfe5f84c69ab3668
--- /dev/null
+++ b/client/components/admin/hooks.js
@@ -0,0 +1,10 @@
+import { useEffect } from 'react';
+
+import { SideNav } from '../../../app/ui-utils/client';
+
+export const useAdminSideNav = () => {
+	useEffect(() => {
+		SideNav.setFlex('adminFlex');
+		SideNav.openFlex();
+	}, []);
+};
diff --git a/client/components/admin/info/BuildEnvironmentSection.js b/client/components/admin/info/BuildEnvironmentSection.js
index 22163c75ec2e76c17d6381e3f3211b2d13e67d8d..140ac47b98aa98d7f28983afe26a7bcdf5a1e7ff 100644
--- a/client/components/admin/info/BuildEnvironmentSection.js
+++ b/client/components/admin/info/BuildEnvironmentSection.js
@@ -1,8 +1,7 @@
 import React from 'react';
 
-import { useTranslation } from '../../contexts/TranslationContext';
-import { InformationList } from './InformationList';
-import { InformationEntry } from './InformationEntry';
+import { useTranslation } from '../../providers/TranslationProvider';
+import { DescriptionList } from './DescriptionList';
 import { formatDate } from './formatters';
 
 export function BuildEnvironmentSection({ info }) {
@@ -11,12 +10,12 @@ export function BuildEnvironmentSection({ info }) {
 
 	return <>
 		<h3>{t('Build_Environment')}</h3>
-		<InformationList>
-			<InformationEntry label={t('OS_Platform')}>{build.platform}</InformationEntry>
-			<InformationEntry label={t('OS_Arch')}>{build.arch}</InformationEntry>
-			<InformationEntry label={t('OS_Release')}>{build.osRelease}</InformationEntry>
-			<InformationEntry label={t('Node_version')}>{build.nodeVersion}</InformationEntry>
-			<InformationEntry label={t('Date')}>{formatDate(build.date)}</InformationEntry>
-		</InformationList>
+		<DescriptionList>
+			<DescriptionList.Entry label={t('OS_Platform')}>{build.platform}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Arch')}>{build.arch}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Release')}>{build.osRelease}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Node_version')}>{build.nodeVersion}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Date')}>{formatDate(build.date)}</DescriptionList.Entry>
+		</DescriptionList>
 	</>;
 }
diff --git a/client/components/admin/info/BuildEnvironmentSection.stories.js b/client/components/admin/info/BuildEnvironmentSection.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..b825ffd1751fab652c1db076ef626b46e45df891
--- /dev/null
+++ b/client/components/admin/info/BuildEnvironmentSection.stories.js
@@ -0,0 +1,24 @@
+import React from 'react';
+
+import { dummyDate } from '../../../../.storybook/helpers';
+import { BuildEnvironmentSection } from './BuildEnvironmentSection';
+
+export default {
+	title: 'admin/info/BuildEnvironmentSection',
+	component: BuildEnvironmentSection,
+	decorators: [
+		(fn) => <div className='rc-old'>{fn()}</div>,
+	],
+};
+
+const info = {
+	compile: {
+		platform: 'info.compile.platform',
+		arch: 'info.compile.arch',
+		osRelease: 'info.compile.osRelease',
+		nodeVersion: 'info.compile.nodeVersion',
+		date: dummyDate,
+	},
+};
+
+export const _default = () => <BuildEnvironmentSection info={info} />;
diff --git a/client/components/admin/info/CommitSection.js b/client/components/admin/info/CommitSection.js
index f814bc5c7037716e871f114952dc311476043e68..1617c422c63ee3a19ecf0f9e2b64f2320b6c336b 100644
--- a/client/components/admin/info/CommitSection.js
+++ b/client/components/admin/info/CommitSection.js
@@ -1,8 +1,7 @@
 import React from 'react';
 
-import { useTranslation } from '../../contexts/TranslationContext';
-import { InformationList } from './InformationList';
-import { InformationEntry } from './InformationEntry';
+import { useTranslation } from '../../providers/TranslationProvider';
+import { DescriptionList } from './DescriptionList';
 
 export function CommitSection({ info }) {
 	const t = useTranslation();
@@ -10,13 +9,13 @@ export function CommitSection({ info }) {
 
 	return <>
 		<h3>{t('Commit')}</h3>
-		<InformationList>
-			<InformationEntry label={t('Hash')}>{commit.hash}</InformationEntry>
-			<InformationEntry label={t('Date')}>{commit.date}</InformationEntry>
-			<InformationEntry label={t('Branch')}>{commit.branch}</InformationEntry>
-			<InformationEntry label={t('Tag')}>{commit.tag}</InformationEntry>
-			<InformationEntry label={t('Author')}>{commit.author}</InformationEntry>
-			<InformationEntry label={t('Subject')}>{commit.subject}</InformationEntry>
-		</InformationList>
+		<DescriptionList>
+			<DescriptionList.Entry label={t('Hash')}>{commit.hash}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Date')}>{commit.date}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Branch')}>{commit.branch}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Tag')}>{commit.tag}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Author')}>{commit.author}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Subject')}>{commit.subject}</DescriptionList.Entry>
+		</DescriptionList>
 	</>;
 }
diff --git a/client/components/admin/info/CommitSection.stories.js b/client/components/admin/info/CommitSection.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..80f1d1133fc01f67b3d128d32a6b2000367dddba
--- /dev/null
+++ b/client/components/admin/info/CommitSection.stories.js
@@ -0,0 +1,24 @@
+import React from 'react';
+
+import { CommitSection } from './CommitSection';
+
+export default {
+	title: 'admin/info/CommitSection',
+	component: CommitSection,
+	decorators: [
+		(fn) => <div className='rc-old'>{fn()}</div>,
+	],
+};
+
+const info = {
+	commit: {
+		hash: 'info.commit.hash',
+		date: 'info.commit.date',
+		branch: 'info.commit.branch',
+		tag: 'info.commit.tag',
+		author: 'info.commit.author',
+		subject: 'info.commit.subject',
+	},
+};
+
+export const _default = () => <CommitSection info={info} />;
diff --git a/client/components/admin/info/DescriptionList.js b/client/components/admin/info/DescriptionList.js
new file mode 100644
index 0000000000000000000000000000000000000000..af12fe4d34122038a4be378ebb6b70299c7e4855
--- /dev/null
+++ b/client/components/admin/info/DescriptionList.js
@@ -0,0 +1,16 @@
+import React from 'react';
+
+export const DescriptionList = ({ children }) =>
+	<table className='statistics-table secondary-background-color'>
+		<tbody>
+			{children}
+		</tbody>
+	</table>;
+
+const Entry = ({ children, label }) =>
+	<tr className='admin-table-row'>
+		<th className='content-background-color border-component-color'>{label}</th>
+		<td className='border-component-color'>{children}</td>
+	</tr>;
+
+DescriptionList.Entry = Entry;
diff --git a/client/components/admin/info/DescriptionList.stories.js b/client/components/admin/info/DescriptionList.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..0db82d0d5e365ab5512a1b08713d719dcf5aa019
--- /dev/null
+++ b/client/components/admin/info/DescriptionList.stories.js
@@ -0,0 +1,20 @@
+import React from 'react';
+
+import { DescriptionList } from './DescriptionList';
+
+export default {
+	title: 'admin/info/DescriptionList',
+	component: DescriptionList,
+	decorators: [
+		(fn) => <div className='rc-old'>{fn()}</div>,
+		(fn) => <section className='page-container page-list'>
+			<div className='content'>
+				{fn()}
+			</div>
+		</section>,
+	],
+};
+
+export const _default = () => <DescriptionList>
+	<DescriptionList.Entry label='Key'>Value</DescriptionList.Entry>
+</DescriptionList>;
diff --git a/client/components/admin/info/InformationEntry.js b/client/components/admin/info/InformationEntry.js
deleted file mode 100644
index bb90111ed1d4d782e4cee0770787b5b7fa8320c7..0000000000000000000000000000000000000000
--- a/client/components/admin/info/InformationEntry.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import React from 'react';
-
-export const InformationEntry = ({ children, label }) =>
-	<tr className='admin-table-row'>
-		<th className='content-background-color border-component-color'>{label}</th>
-		<td className='border-component-color'>{children}</td>
-	</tr>;
diff --git a/client/components/admin/info/InformationList.js b/client/components/admin/info/InformationList.js
deleted file mode 100644
index 7cbc85048acd0f69ed118519f29ca2325c252a68..0000000000000000000000000000000000000000
--- a/client/components/admin/info/InformationList.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import React from 'react';
-
-export const InformationList = ({ children }) =>
-	<table className='statistics-table secondary-background-color'>
-		<tbody>
-			{children}
-		</tbody>
-	</table>;
diff --git a/client/components/admin/info/InformationPage.js b/client/components/admin/info/InformationPage.js
index cdcc1280651130b14ce5e2250f612eb6974ccd45..cd564cc2ecb6cb74f17a5178d759cbf0dedd57c1 100644
--- a/client/components/admin/info/InformationPage.js
+++ b/client/components/admin/info/InformationPage.js
@@ -1,15 +1,10 @@
 import { Button, Icon } from '@rocket.chat/fuselage';
-import React, { useEffect, useState } from 'react';
+import React from 'react';
 
-import { call } from '../../../../app/ui-utils/client/lib/callMethod';
-import { useViewStatisticsPermission } from '../../../hooks/usePermissions';
-import { useReactiveValue } from '../../../hooks/useReactiveValue';
-import { Info } from '../../../../app/utils';
-import { SideNav } from '../../../../app/ui-utils/client/lib/SideNav';
-import { Header } from '../../header/Header';
 import { Link } from '../../basic/Link';
 import { ErrorAlert } from '../../basic/ErrorAlert';
-import { useTranslation } from '../../contexts/TranslationContext';
+import { Header } from '../../header/Header';
+import { useTranslation } from '../../providers/TranslationProvider';
 import { RocketChatSection } from './RocketChatSection';
 import { CommitSection } from './CommitSection';
 import { RuntimeEnvironmentSection } from './RuntimeEnvironmentSection';
@@ -17,95 +12,30 @@ import { BuildEnvironmentSection } from './BuildEnvironmentSection';
 import { UsageSection } from './UsageSection';
 import { InstancesSection } from './InstancesSection';
 
-const useStatistics = (canViewStatistics) => {
-	const [isLoading, setLoading] = useState(true);
-	const [statistics, setStatistics] = useState({});
-	const [instances, setInstances] = useState([]);
-	const [fetchStatistics, setFetchStatistics] = useState(() => () => ({}));
-
-	useEffect(() => {
-		let didCancel = false;
-
-		const fetchStatistics = async () => {
-			if (!canViewStatistics) {
-				setStatistics(null);
-				setInstances(null);
-				return;
-			}
-
-			setLoading(true);
-
-			try {
-				const [statistics, instances] = await Promise.all([
-					call('getStatistics'),
-					call('instances/get'),
-				]);
-
-				if (didCancel) {
-					return;
-				}
-
-				setStatistics(statistics);
-				setInstances(instances);
-			} finally {
-				setLoading(false);
-			}
-		};
-
-		setFetchStatistics(() => fetchStatistics);
-
-		fetchStatistics();
-
-		return () => {
-			didCancel = true;
-		};
-	}, [canViewStatistics]);
-
-	return {
-		isLoading,
-		statistics,
-		instances,
-		fetchStatistics,
-	};
-};
-
-export function InformationPage() {
-	const canViewStatistics = useViewStatisticsPermission();
-
-	const {
-		isLoading,
-		statistics,
-		instances,
-		fetchStatistics,
-	} = useStatistics(canViewStatistics);
-
-	const info = useReactiveValue(() => Info, []);
-
+export function InformationPage({
+	canViewStatistics,
+	isLoading,
+	info,
+	statistics,
+	instances,
+	onClickRefreshButton,
+}) {
 	const t = useTranslation();
 
-	const handleRefreshClick = () => {
-		if (isLoading) {
-			return;
-		}
-
-		fetchStatistics();
-	};
-
-	useEffect(() => {
-		SideNav.setFlex('adminFlex');
-		SideNav.openFlex();
-	}, []);
+	if (!info) {
+		return null;
+	}
 
 	const alertOplogForMultipleInstances = statistics && statistics.instanceCount > 1 && !statistics.oplogEnabled;
 
-	return <section className='page-container page-list Admin__InformationPage'>
+	return <section className='page-container'>
 		<Header rawSectionName={t('Info')} hideHelp>
 			{canViewStatistics
-				&& <div className='rc-header__block rc-header__block-action'>
-					<Button primary type='button' onClick={handleRefreshClick}>
-						<Icon iconName='reload' /> {t('Refresh')}
+				&& <Header.ActionBlock>
+					<Button disabled={isLoading} primary type='button' onClick={onClickRefreshButton}>
+						<Icon name='reload' /> {t('Refresh')}
 					</Button>
-				</div>}
+				</Header.ActionBlock>}
 		</Header>
 
 		<div className='content'>
@@ -121,11 +51,11 @@ export function InformationPage() {
 					</p>
 				</ErrorAlert>}
 
-			<RocketChatSection info={info} statistics={statistics} isLoading={isLoading} />
+			{canViewStatistics && <RocketChatSection info={info} statistics={statistics} isLoading={isLoading} />}
 			<CommitSection info={info} />
-			<RuntimeEnvironmentSection statistics={statistics} isLoading={isLoading} />
+			{canViewStatistics && <RuntimeEnvironmentSection statistics={statistics} isLoading={isLoading} />}
 			<BuildEnvironmentSection info={info} />
-			<UsageSection statistics={statistics} isLoading={isLoading} />
+			{canViewStatistics && <UsageSection statistics={statistics} isLoading={isLoading} />}
 			<InstancesSection instances={instances} />
 		</div>
 	</section>;
diff --git a/client/components/admin/info/InformationPage.stories.js b/client/components/admin/info/InformationPage.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..e85c6b9957dd433fb62061aad819ca729fc6335d
--- /dev/null
+++ b/client/components/admin/info/InformationPage.stories.js
@@ -0,0 +1,151 @@
+import { action } from '@storybook/addon-actions';
+import { boolean, object } from '@storybook/addon-knobs/react';
+import React from 'react';
+
+import { dummyDate } from '../../../../.storybook/helpers';
+import { InformationPage } from './InformationPage';
+
+export default {
+	title: 'admin/info/InformationPage',
+	component: InformationPage,
+	decorators: [
+		(fn) => <div className='rc-old'>{fn()}</div>,
+	],
+};
+
+const info = {
+	marketplaceApiVersion: 'info.marketplaceApiVersion',
+	commit: {
+		hash: 'info.commit.hash',
+		date: 'info.commit.date',
+		branch: 'info.commit.branch',
+		tag: 'info.commit.tag',
+		author: 'info.commit.author',
+		subject: 'info.commit.subject',
+	},
+	compile: {
+		platform: 'info.compile.platform',
+		arch: 'info.compile.arch',
+		osRelease: 'info.compile.osRelease',
+		nodeVersion: 'info.compile.nodeVersion',
+		date: dummyDate,
+	},
+};
+
+const statistics = {
+	version: 'statistics.version',
+	migration: {
+		version: 'statistics.migration.version',
+		lockedAt: dummyDate,
+	},
+	installedAt: dummyDate,
+	process: {
+		nodeVersion: 'statistics.process.nodeVersion',
+		uptime: 10 * 24 * 60 * 60,
+		pid: 'statistics.process.pid',
+	},
+	uniqueId: 'statistics.uniqueId',
+	instanceCount: 1,
+	oplogEnabled: true,
+	os: {
+		type: 'statistics.os.type',
+		platform: 'statistics.os.platform',
+		arch: 'statistics.os.arch',
+		release: 'statistics.os.release',
+		uptime: 10 * 24 * 60 * 60,
+		loadavg: [1.1, 1.5, 1.15],
+		totalmem: 1024,
+		freemem: 1024,
+		cpus: [{}],
+	},
+	mongoVersion: 'statistics.mongoVersion',
+	mongoStorageEngine: 'statistics.mongoStorageEngine',
+	totalUsers: 'statistics.totalUsers',
+	nonActiveUsers: 'nonActiveUsers',
+	activeUsers: 'statistics.activeUsers',
+	totalConnectedUsers: 'statistics.totalConnectedUsers',
+	onlineUsers: 'statistics.onlineUsers',
+	awayUsers: 'statistics.awayUsers',
+	offlineUsers: 'statistics.offlineUsers',
+	totalRooms: 'statistics.totalRooms',
+	totalChannels: 'statistics.totalChannels',
+	totalPrivateGroups: 'statistics.totalPrivateGroups',
+	totalDirect: 'statistics.totalDirect',
+	totalLivechat: 'statistics.totalLivechat',
+	totalDiscussions: 'statistics.totalDiscussions',
+	totalThreads: 'statistics.totalThreads',
+	totalMessages: 'statistics.totalMessages',
+	totalChannelMessages: 'statistics.totalChannelMessages',
+	totalPrivateGroupMessages: 'statistics.totalPrivateGroupMessages',
+	totalDirectMessages: 'statistics.totalDirectMessages',
+	totalLivechatMessages: 'statistics.totalLivechatMessages',
+	uploadsTotal: 'statistics.uploadsTotal',
+	uploadsTotalSize: 1024,
+	integrations: {
+		totalIntegrations: 'statistics.integrations.totalIntegrations',
+		totalIncoming: 'statistics.integrations.totalIncoming',
+		totalIncomingActive: 'statistics.integrations.totalIncomingActive',
+		totalOutgoing: 'statistics.integrations.totalOutgoing',
+		totalOutgoingActive: 'statistics.integrations.totalOutgoingActive',
+		totalWithScriptEnabled: 'statistics.integrations.totalWithScriptEnabled',
+	},
+};
+
+const instances = [
+	{
+		address: 'instances[].address',
+		broadcastAuth: 'instances[].broadcastAuth',
+		currentStatus: {
+			connected: 'instances[].currentStatus.connected',
+			retryCount: 'instances[].currentStatus.retryCount',
+			status: 'instances[].currentStatus.status',
+		},
+		instanceRecord: {
+			_id: 'instances[].instanceRecord._id',
+			pid: 'instances[].instanceRecord.pid',
+			_createdAt: dummyDate,
+			_updatedAt: dummyDate,
+		},
+	},
+];
+
+export const _default = () =>
+	<InformationPage
+		canViewStatistics={boolean('canViewStatistics', true)}
+		isLoading={boolean('isLoading', false)}
+		info={object('info', info)}
+		statistics={object('statistics', statistics)}
+		instances={object('instances', instances)}
+		onClickRefreshButton={action('clickRefreshButton')}
+	/>;
+
+export const withoutCanViewStatisticsPermission = () =>
+	<InformationPage
+		info={info}
+		onClickRefreshButton={action('clickRefreshButton')}
+	/>;
+
+export const loading = () =>
+	<InformationPage
+		canViewStatistics
+		isLoading
+		info={info}
+		onClickRefreshButton={action('clickRefreshButton')}
+	/>;
+
+export const withStatistics = () =>
+	<InformationPage
+		canViewStatistics
+		info={info}
+		statistics={statistics}
+		onClickRefreshButton={action('clickRefreshButton')}
+	/>;
+
+export const withOneInstance = () =>
+	<InformationPage
+		canViewStatistics
+		info={info}
+		statistics={statistics}
+		instances={instances}
+		onClickRefreshButton={action('clickRefreshButton')}
+	/>;
diff --git a/client/components/admin/info/InformationRoute.js b/client/components/admin/info/InformationRoute.js
new file mode 100644
index 0000000000000000000000000000000000000000..4442c7e61dba1619e4b22a2e96456b432cd0dcec
--- /dev/null
+++ b/client/components/admin/info/InformationRoute.js
@@ -0,0 +1,77 @@
+import React, { useState, useEffect } from 'react';
+
+import { useMethod } from '../../../hooks/useMethod';
+import { useViewStatisticsPermission } from '../../../hooks/usePermissions';
+import { useRocketChatInformation } from '../../../hooks/useRocketChatInformation';
+import { useAdminSideNav } from '../hooks';
+import { InformationPage } from './InformationPage';
+
+export function InformationRoute() {
+	useAdminSideNav();
+
+	const canViewStatistics = useViewStatisticsPermission();
+
+	const [isLoading, setLoading] = useState(true);
+	const [statistics, setStatistics] = useState({});
+	const [instances, setInstances] = useState([]);
+	const [fetchStatistics, setFetchStatistics] = useState(() => () => ({}));
+	const getStatistics = useMethod('getStatistics');
+	const getInstances = useMethod('instances/get');
+
+	useEffect(() => {
+		let didCancel = false;
+
+		const fetchStatistics = async () => {
+			if (!canViewStatistics) {
+				setStatistics(null);
+				setInstances(null);
+				return;
+			}
+
+			setLoading(true);
+
+			try {
+				const [statistics, instances] = await Promise.all([
+					getStatistics(),
+					getInstances(),
+				]);
+
+				if (didCancel) {
+					return;
+				}
+
+				setStatistics(statistics);
+				setInstances(instances);
+			} finally {
+				setLoading(false);
+			}
+		};
+
+		setFetchStatistics(() => fetchStatistics);
+
+		fetchStatistics();
+
+		return () => {
+			didCancel = true;
+		};
+	}, [canViewStatistics]);
+
+	const info = useRocketChatInformation();
+
+	const handleClickRefreshButton = () => {
+		if (isLoading) {
+			return;
+		}
+
+		fetchStatistics();
+	};
+
+	return <InformationPage
+		canViewStatistics={canViewStatistics}
+		isLoading={isLoading}
+		info={info}
+		statistics={statistics}
+		instances={instances}
+		onClickRefreshButton={handleClickRefreshButton}
+	/>;
+}
diff --git a/client/components/admin/info/InstancesSection.js b/client/components/admin/info/InstancesSection.js
index 855d2c9520b2b4b79fe8f0a0998d91a1d43d1c5a..087f1d0b39d80c6f6f5e1794f8bc88a9f8e27309 100644
--- a/client/components/admin/info/InstancesSection.js
+++ b/client/components/admin/info/InstancesSection.js
@@ -1,9 +1,8 @@
 import React from 'react';
 
+import { useTranslation } from '../../providers/TranslationProvider';
+import { DescriptionList } from './DescriptionList';
 import { formatDate } from './formatters';
-import { useTranslation } from '../../contexts/TranslationContext';
-import { InformationList } from './InformationList';
-import { InformationEntry } from './InformationEntry';
 
 export function InstancesSection({ instances }) {
 	const t = useTranslation();
@@ -15,17 +14,17 @@ export function InstancesSection({ instances }) {
 	return <>
 		<h3>{t('Broadcast_Connected_Instances')}</h3>
 		{instances.map(({ address, broadcastAuth, currentStatus, instanceRecord }, i) =>
-			<InformationList key={i}>
-				<InformationEntry label={t('Address')}>{address}</InformationEntry>
-				<InformationEntry label={t('Auth')}>{broadcastAuth ? 'true' : 'false'}</InformationEntry>
-				<InformationEntry label={<>{t('Current_Status')} > {t('Connected')}</>}>{currentStatus.connected ? 'true' : 'false'}</InformationEntry>
-				<InformationEntry label={<>{t('Current_Status')} > {t('Retry_Count')}</>}>{currentStatus.retryCount}</InformationEntry>
-				<InformationEntry label={<>{t('Current_Status')} > {t('Status')}</>}>{currentStatus.status}</InformationEntry>
-				<InformationEntry label={<>{t('Instance_Record')} > {t('ID')}</>}>{instanceRecord._id}</InformationEntry>
-				<InformationEntry label={<>{t('Instance_Record')} > {t('PID')}</>}>{instanceRecord.pid}</InformationEntry>
-				<InformationEntry label={<>{t('Instance_Record')} > {t('Created_at')}</>}>{formatDate(instanceRecord._createdAt)}</InformationEntry>
-				<InformationEntry label={<>{t('Instance_Record')} > {t('Updated_at')}</>}>{formatDate(instanceRecord._updatedAt)}</InformationEntry>
-			</InformationList>
+			<DescriptionList key={i}>
+				<DescriptionList.Entry label={t('Address')}>{address}</DescriptionList.Entry>
+				<DescriptionList.Entry label={t('Auth')}>{broadcastAuth ? 'true' : 'false'}</DescriptionList.Entry>
+				<DescriptionList.Entry label={<>{t('Current_Status')} > {t('Connected')}</>}>{currentStatus.connected ? 'true' : 'false'}</DescriptionList.Entry>
+				<DescriptionList.Entry label={<>{t('Current_Status')} > {t('Retry_Count')}</>}>{currentStatus.retryCount}</DescriptionList.Entry>
+				<DescriptionList.Entry label={<>{t('Current_Status')} > {t('Status')}</>}>{currentStatus.status}</DescriptionList.Entry>
+				<DescriptionList.Entry label={<>{t('Instance_Record')} > {t('ID')}</>}>{instanceRecord._id}</DescriptionList.Entry>
+				<DescriptionList.Entry label={<>{t('Instance_Record')} > {t('PID')}</>}>{instanceRecord.pid}</DescriptionList.Entry>
+				<DescriptionList.Entry label={<>{t('Instance_Record')} > {t('Created_at')}</>}>{formatDate(instanceRecord._createdAt)}</DescriptionList.Entry>
+				<DescriptionList.Entry label={<>{t('Instance_Record')} > {t('Updated_at')}</>}>{formatDate(instanceRecord._updatedAt)}</DescriptionList.Entry>
+			</DescriptionList>
 		)}
 	</>;
 }
diff --git a/client/components/admin/info/InstancesSection.stories.js b/client/components/admin/info/InstancesSection.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..8f0f8729765fa764ba6c063cf6277fc8e07738d3
--- /dev/null
+++ b/client/components/admin/info/InstancesSection.stories.js
@@ -0,0 +1,32 @@
+import React from 'react';
+
+import { dummyDate } from '../../../../.storybook/helpers';
+import { InstancesSection } from './InstancesSection';
+
+export default {
+	title: 'admin/info/InstancesSection',
+	component: InstancesSection,
+	decorators: [
+		(fn) => <div className='rc-old'>{fn()}</div>,
+	],
+};
+
+const instances = [
+	{
+		address: 'instances[].address',
+		broadcastAuth: 'instances[].broadcastAuth',
+		currentStatus: {
+			connected: 'instances[].currentStatus.connected',
+			retryCount: 'instances[].currentStatus.retryCount',
+			status: 'instances[].currentStatus.status',
+		},
+		instanceRecord: {
+			_id: 'instances[].instanceRecord._id',
+			pid: 'instances[].instanceRecord.pid',
+			_createdAt: dummyDate,
+			_updatedAt: dummyDate,
+		},
+	},
+];
+
+export const _default = () => <InstancesSection instances={instances} />;
diff --git a/client/components/admin/info/RocketChatSection.js b/client/components/admin/info/RocketChatSection.js
index 7c10d79f66f3f34e534cb2ceb670e56b4add842d..1b380054f253da65bb6a9c00c1f777842cf375ac 100644
--- a/client/components/admin/info/RocketChatSection.js
+++ b/client/components/admin/info/RocketChatSection.js
@@ -1,34 +1,29 @@
+import { Text } from '@rocket.chat/fuselage';
 import React from 'react';
 
-import { useTranslation } from '../../contexts/TranslationContext';
-import { SkeletonText } from './SkeletonText';
+import { useTranslation } from '../../providers/TranslationProvider';
 import { formatDate, formatHumanReadableTime } from './formatters';
-import { InformationList } from './InformationList';
-import { InformationEntry } from './InformationEntry';
+import { DescriptionList } from './DescriptionList';
 
 export function RocketChatSection({ info, statistics, isLoading }) {
-	const s = (fn) => (isLoading ? <SkeletonText /> : fn());
+	const s = (fn) => (isLoading ? <Text.Skeleton animated width={'1/2'} /> : fn());
 	const t = useTranslation();
 
-	const appsEngineVersion = info.marketplaceApiVersion;
-
-	if (!statistics) {
-		return null;
-	}
+	const appsEngineVersion = info && info.marketplaceApiVersion;
 
 	return <>
 		<h3>{t('Rocket.Chat')}</h3>
-		<InformationList>
-			<InformationEntry label={t('Version')}>{s(() => statistics.version)}</InformationEntry>
-			{appsEngineVersion && <InformationEntry label={t('Apps_Engine_Version')}>{appsEngineVersion}</InformationEntry>}
-			<InformationEntry label={t('DB_Migration')}>{s(() => statistics.migration.version)}</InformationEntry>
-			<InformationEntry label={t('DB_Migration_Date')}>{s(() => formatDate(statistics.migration.lockedAt))}</InformationEntry>
-			<InformationEntry label={t('Installed_at')}>{s(() => formatDate(statistics.installedAt))}</InformationEntry>
-			<InformationEntry label={t('Uptime')}>{s(() => formatHumanReadableTime(statistics.process.uptime, t))}</InformationEntry>
-			<InformationEntry label={t('Deployment_ID')}>{s(() => statistics.uniqueId)}</InformationEntry>
-			<InformationEntry label={t('PID')}>{s(() => statistics.process.pid)}</InformationEntry>
-			<InformationEntry label={t('Running_Instances')}>{s(() => statistics.instanceCount)}</InformationEntry>
-			<InformationEntry label={t('OpLog')}>{s(() => (statistics.oplogEnabled ? t('Enabled') : t('Disabled')))}</InformationEntry>
-		</InformationList>
+		<DescriptionList>
+			<DescriptionList.Entry label={t('Version')}>{s(() => statistics.version)}</DescriptionList.Entry>
+			{appsEngineVersion && <DescriptionList.Entry label={t('Apps_Engine_Version')}>{appsEngineVersion}</DescriptionList.Entry>}
+			<DescriptionList.Entry label={t('DB_Migration')}>{s(() => statistics.migration.version)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('DB_Migration_Date')}>{s(() => formatDate(statistics.migration.lockedAt))}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Installed_at')}>{s(() => formatDate(statistics.installedAt))}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Uptime')}>{s(() => formatHumanReadableTime(statistics.process.uptime, t))}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Deployment_ID')}>{s(() => statistics.uniqueId)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('PID')}>{s(() => statistics.process.pid)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Running_Instances')}>{s(() => statistics.instanceCount)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OpLog')}>{s(() => (statistics.oplogEnabled ? t('Enabled') : t('Disabled')))}</DescriptionList.Entry>
+		</DescriptionList>
 	</>;
 }
diff --git a/client/components/admin/info/RocketChatSection.stories.js b/client/components/admin/info/RocketChatSection.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..e859eee72b5a583716bfa84f172c2b4156c259ca
--- /dev/null
+++ b/client/components/admin/info/RocketChatSection.stories.js
@@ -0,0 +1,36 @@
+import React from 'react';
+
+import { dummyDate } from '../../../../.storybook/helpers';
+import { RocketChatSection } from './RocketChatSection';
+
+export default {
+	title: 'admin/info/RocketChatSection',
+	component: RocketChatSection,
+	decorators: [
+		(fn) => <div className='rc-old'>{fn()}</div>,
+	],
+};
+
+const info = {
+	marketplaceApiVersion: 'info.marketplaceApiVersion',
+};
+
+const statistics = {
+	version: 'statistics.version',
+	migration: {
+		version: 'statistics.migration.version',
+		lockedAt: dummyDate,
+	},
+	installedAt: dummyDate,
+	process: {
+		uptime: 10 * 24 * 60 * 60,
+		pid: 'statistics.process.pid',
+	},
+	uniqueId: 'statistics.uniqueId',
+	instanceCount: 1,
+	oplogEnabled: true,
+};
+
+export const _default = () => <RocketChatSection info={info} statistics={statistics} />;
+
+export const loading = () => <RocketChatSection info={{}} statistics={{}} isLoading />;
diff --git a/client/components/admin/info/RuntimeEnvironmentSection.js b/client/components/admin/info/RuntimeEnvironmentSection.js
index 01c2a9ff78ea8f73561fd6e1c32ee6512e5c1983..f5a3a3ce928bdeb786c9729aa6eb895d4b9cfb7c 100644
--- a/client/components/admin/info/RuntimeEnvironmentSection.js
+++ b/client/components/admin/info/RuntimeEnvironmentSection.js
@@ -1,34 +1,29 @@
+import { Text } from '@rocket.chat/fuselage';
 import React from 'react';
 
-import { useTranslation } from '../../contexts/TranslationContext';
-import { SkeletonText } from './SkeletonText';
+import { useTranslation } from '../../providers/TranslationProvider';
+import { DescriptionList } from './DescriptionList';
 import { formatMemorySize, formatHumanReadableTime, formatCPULoad } from './formatters';
-import { InformationList } from './InformationList';
-import { InformationEntry } from './InformationEntry';
 
 export function RuntimeEnvironmentSection({ statistics, isLoading }) {
-	const s = (fn) => (isLoading ? <SkeletonText /> : fn());
+	const s = (fn) => (isLoading ? <Text.Skeleton animated width={'1/2'} /> : fn());
 	const t = useTranslation();
 
-	if (!statistics) {
-		return null;
-	}
-
 	return <>
 		<h3>{t('Runtime_Environment')}</h3>
-		<InformationList>
-			<InformationEntry label={t('OS_Type')}>{s(() => statistics.os.type)}</InformationEntry>
-			<InformationEntry label={t('OS_Platform')}>{s(() => statistics.os.platform)}</InformationEntry>
-			<InformationEntry label={t('OS_Arch')}>{s(() => statistics.os.arch)}</InformationEntry>
-			<InformationEntry label={t('OS_Release')}>{s(() => statistics.os.release)}</InformationEntry>
-			<InformationEntry label={t('Node_version')}>{s(() => statistics.process.nodeVersion)}</InformationEntry>
-			<InformationEntry label={t('Mongo_version')}>{s(() => statistics.mongoVersion)}</InformationEntry>
-			<InformationEntry label={t('Mongo_storageEngine')}>{s(() => statistics.mongoStorageEngine)}</InformationEntry>
-			<InformationEntry label={t('OS_Uptime')}>{s(() => formatHumanReadableTime(statistics.os.uptime, t))}</InformationEntry>
-			<InformationEntry label={t('OS_Loadavg')}>{s(() => formatCPULoad(statistics.os.loadavg))}</InformationEntry>
-			<InformationEntry label={t('OS_Totalmem')}>{s(() => formatMemorySize(statistics.os.totalmem))}</InformationEntry>
-			<InformationEntry label={t('OS_Freemem')}>{s(() => formatMemorySize(statistics.os.freemem))}</InformationEntry>
-			<InformationEntry label={t('OS_Cpus')}>{s(() => statistics.os.cpus.length)}</InformationEntry>
-		</InformationList>
+		<DescriptionList>
+			<DescriptionList.Entry label={t('OS_Type')}>{s(() => statistics.os.type)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Platform')}>{s(() => statistics.os.platform)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Arch')}>{s(() => statistics.os.arch)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Release')}>{s(() => statistics.os.release)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Node_version')}>{s(() => statistics.process.nodeVersion)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Mongo_version')}>{s(() => statistics.mongoVersion)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Mongo_storageEngine')}>{s(() => statistics.mongoStorageEngine)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Uptime')}>{s(() => formatHumanReadableTime(statistics.os.uptime, t))}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Loadavg')}>{s(() => formatCPULoad(statistics.os.loadavg))}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Totalmem')}>{s(() => formatMemorySize(statistics.os.totalmem))}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Freemem')}>{s(() => formatMemorySize(statistics.os.freemem))}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('OS_Cpus')}>{s(() => statistics.os.cpus.length)}</DescriptionList.Entry>
+		</DescriptionList>
 	</>;
 }
diff --git a/client/components/admin/info/RuntimeEnvironmentSection.stories.js b/client/components/admin/info/RuntimeEnvironmentSection.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..3270bbfe081496566150b41d2c0a47d6fdb642ab
--- /dev/null
+++ b/client/components/admin/info/RuntimeEnvironmentSection.stories.js
@@ -0,0 +1,34 @@
+import React from 'react';
+
+import { RuntimeEnvironmentSection } from './RuntimeEnvironmentSection';
+
+export default {
+	title: 'admin/info/RuntimeEnvironmentSection',
+	component: RuntimeEnvironmentSection,
+	decorators: [
+		(fn) => <div className='rc-old'>{fn()}</div>,
+	],
+};
+
+const statistics = {
+	os: {
+		type: 'statistics.os.type',
+		platform: 'statistics.os.platform',
+		arch: 'statistics.os.arch',
+		release: 'statistics.os.release',
+		uptime: 10 * 24 * 60 * 60,
+		loadavg: [1.1, 1.5, 1.15],
+		totalmem: 1024,
+		freemem: 1024,
+		cpus: [{}],
+	},
+	process: {
+		nodeVersion: 'statistics.process.nodeVersion',
+	},
+	mongoVersion: 'statistics.mongoVersion',
+	mongoStorageEngine: 'statistics.mongoStorageEngine',
+};
+
+export const _default = () => <RuntimeEnvironmentSection statistics={statistics} />;
+
+export const loading = () => <RuntimeEnvironmentSection statistics={{}} isLoading />;
diff --git a/client/components/admin/info/SkeletonText.css b/client/components/admin/info/SkeletonText.css
deleted file mode 100644
index baac1e70e96760d6fbd9adb4a6322cd00760985f..0000000000000000000000000000000000000000
--- a/client/components/admin/info/SkeletonText.css
+++ /dev/null
@@ -1,28 +0,0 @@
-.Admin__InformationPage__SkeletonText {
-	display: inline-flex;
-
-	min-width: 10em;
-	height: 1em;
-
-	animation: Admin__InformationPage__SkeletonText__animation 1s linear 1s infinite running;
-
-	opacity: 0.25;
-	background:
-		linear-gradient(
-			to right,
-			transparent,
-			currentColor 50%,
-			transparent 100%
-		);
-	background-size: 100vw 100vh;
-}
-
-@keyframes Admin__InformationPage__SkeletonText__animation {
-	0% {
-		background-position: 0 0;
-	}
-
-	100% {
-		background-position: 100vw 0;
-	}
-}
diff --git a/client/components/admin/info/SkeletonText.js b/client/components/admin/info/SkeletonText.js
deleted file mode 100644
index 3c5cdcb1df79c2875779f79a67377cd15168e34f..0000000000000000000000000000000000000000
--- a/client/components/admin/info/SkeletonText.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import React, { useMemo } from 'react';
-import './SkeletonText.css';
-
-
-export function SkeletonText() {
-	const width = useMemo(() => `${ Math.random() * 10 + 10 }em`, []);
-
-	return <span className='Admin__InformationPage__SkeletonText' style={{ width }} />;
-}
diff --git a/client/components/admin/info/UsageSection.js b/client/components/admin/info/UsageSection.js
index 64b76ea0d358a3c943bfd1a22a22244d9c2ec42f..171ef59d9486cbc15476d14d021800a94467f87e 100644
--- a/client/components/admin/info/UsageSection.js
+++ b/client/components/admin/info/UsageSection.js
@@ -1,53 +1,48 @@
+import { Text } from '@rocket.chat/fuselage';
 import React from 'react';
 
-import { useTranslation } from '../../contexts/TranslationContext';
-import { SkeletonText } from './SkeletonText';
+import { useTranslation } from '../../providers/TranslationProvider';
+import { DescriptionList } from './DescriptionList';
 import { formatMemorySize } from './formatters';
-import { InformationList } from './InformationList';
-import { InformationEntry } from './InformationEntry';
 
 export function UsageSection({ statistics, isLoading }) {
-	const s = (fn) => (isLoading ? <SkeletonText /> : fn());
+	const s = (fn) => (isLoading ? <Text.Skeleton animated width={'1/2'} /> : fn());
 	const t = useTranslation();
 
-	if (!statistics) {
-		return null;
-	}
-
 	return <>
 		<h3>{t('Usage')}</h3>
-		<InformationList>
-			<InformationEntry label={t('Stats_Total_Users')}>{s(() => statistics.totalUsers)}</InformationEntry>
-			<InformationEntry label={t('Stats_Active_Users')}>{s(() => statistics.activeUsers)}</InformationEntry>
-			<InformationEntry label={t('Stats_Non_Active_Users')}>{s(() => statistics.nonActiveUsers)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Connected_Users')}>{s(() => statistics.totalConnectedUsers)}</InformationEntry>
-			<InformationEntry label={t('Stats_Online_Users')}>{s(() => statistics.onlineUsers)}</InformationEntry>
-			<InformationEntry label={t('Stats_Away_Users')}>{s(() => statistics.awayUsers)}</InformationEntry>
-			<InformationEntry label={t('Stats_Offline_Users')}>{s(() => statistics.offlineUsers)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Rooms')}>{s(() => statistics.totalRooms)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Channels')}>{s(() => statistics.totalChannels)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Private_Groups')}>{s(() => statistics.totalPrivateGroups)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Direct_Messages')}>{s(() => statistics.totalDirect)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Livechat_Rooms')}>{s(() => statistics.totalLivechat)}</InformationEntry>
-			<InformationEntry label={t('Total_Discussions')}>{s(() => statistics.totalDiscussions)}</InformationEntry>
-			<InformationEntry label={t('Total_Threads')}>{s(() => statistics.totalThreads)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Messages')}>{s(() => statistics.totalMessages)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Messages_Channel')}>{s(() => statistics.totalChannelMessages)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Messages_PrivateGroup')}>{s(() => statistics.totalPrivateGroupMessages)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Messages_Direct')}>{s(() => statistics.totalDirectMessages)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Messages_Livechat')}>{s(() => statistics.totalLivechatMessages)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Uploads')}>{s(() => statistics.uploadsTotal)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Uploads_Size')}>{s(() => formatMemorySize(statistics.uploadsTotalSize))}</InformationEntry>
-			{statistics.apps && <>
-					<InformationEntry label={t('Stats_Total_Installed_Apps')}>{statistics.apps.totalInstalled}</InformationEntry>
-					<InformationEntry label={t('Stats_Total_Active_Apps')}>{statistics.apps.totalActive}</InformationEntry>
+		<DescriptionList>
+			<DescriptionList.Entry label={t('Stats_Total_Users')}>{s(() => statistics.totalUsers)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Active_Users')}>{s(() => statistics.activeUsers)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Non_Active_Users')}>{s(() => statistics.nonActiveUsers)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Connected_Users')}>{s(() => statistics.totalConnectedUsers)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Online_Users')}>{s(() => statistics.onlineUsers)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Away_Users')}>{s(() => statistics.awayUsers)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Offline_Users')}>{s(() => statistics.offlineUsers)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Rooms')}>{s(() => statistics.totalRooms)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Channels')}>{s(() => statistics.totalChannels)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Private_Groups')}>{s(() => statistics.totalPrivateGroups)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Direct_Messages')}>{s(() => statistics.totalDirect)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Livechat_Rooms')}>{s(() => statistics.totalLivechat)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Total_Discussions')}>{s(() => statistics.totalDiscussions)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Total_Threads')}>{s(() => statistics.totalThreads)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Messages')}>{s(() => statistics.totalMessages)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Messages_Channel')}>{s(() => statistics.totalChannelMessages)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Messages_PrivateGroup')}>{s(() => statistics.totalPrivateGroupMessages)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Messages_Direct')}>{s(() => statistics.totalDirectMessages)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Messages_Livechat')}>{s(() => statistics.totalLivechatMessages)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Uploads')}>{s(() => statistics.uploadsTotal)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Uploads_Size')}>{s(() => formatMemorySize(statistics.uploadsTotalSize))}</DescriptionList.Entry>
+			{statistics && statistics.apps && <>
+					<DescriptionList.Entry label={t('Stats_Total_Installed_Apps')}>{statistics.apps.totalInstalled}</DescriptionList.Entry>
+					<DescriptionList.Entry label={t('Stats_Total_Active_Apps')}>{statistics.apps.totalActive}</DescriptionList.Entry>
 				</>}
-			<InformationEntry label={t('Stats_Total_Integrations')}>{s(() => statistics.integrations.totalIntegrations)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Incoming_Integrations')}>{s(() => statistics.integrations.totalIncoming)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Active_Incoming_Integrations')}>{s(() => statistics.integrations.totalIncomingActive)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Outgoing_Integrations')}>{s(() => statistics.integrations.totalOutgoing)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Active_Outgoing_Integrations')}>{s(() => statistics.integrations.totalOutgoingActive)}</InformationEntry>
-			<InformationEntry label={t('Stats_Total_Integrations_With_Script_Enabled')}>{s(() => statistics.integrations.totalWithScriptEnabled)}</InformationEntry>
-		</InformationList>
+			<DescriptionList.Entry label={t('Stats_Total_Integrations')}>{s(() => statistics.integrations.totalIntegrations)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Incoming_Integrations')}>{s(() => statistics.integrations.totalIncoming)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Active_Incoming_Integrations')}>{s(() => statistics.integrations.totalIncomingActive)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Outgoing_Integrations')}>{s(() => statistics.integrations.totalOutgoing)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Active_Outgoing_Integrations')}>{s(() => statistics.integrations.totalOutgoingActive)}</DescriptionList.Entry>
+			<DescriptionList.Entry label={t('Stats_Total_Integrations_With_Script_Enabled')}>{s(() => statistics.integrations.totalWithScriptEnabled)}</DescriptionList.Entry>
+		</DescriptionList>
 	</>;
 }
diff --git a/client/components/admin/info/UsageSection.stories.js b/client/components/admin/info/UsageSection.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..81653490717440c8319c00c681ce6e88f9236272
--- /dev/null
+++ b/client/components/admin/info/UsageSection.stories.js
@@ -0,0 +1,54 @@
+import React from 'react';
+
+import { UsageSection } from './UsageSection';
+
+export default {
+	title: 'admin/info/UsageSection',
+	component: UsageSection,
+	decorators: [
+		(fn) => <div className='rc-old'>{fn()}</div>,
+	],
+};
+
+const statistics = {
+	totalUsers: 'statistics.totalUsers',
+	nonActiveUsers: 'nonActiveUsers',
+	activeUsers: 'statistics.activeUsers',
+	totalConnectedUsers: 'statistics.totalConnectedUsers',
+	onlineUsers: 'statistics.onlineUsers',
+	awayUsers: 'statistics.awayUsers',
+	offlineUsers: 'statistics.offlineUsers',
+	totalRooms: 'statistics.totalRooms',
+	totalChannels: 'statistics.totalChannels',
+	totalPrivateGroups: 'statistics.totalPrivateGroups',
+	totalDirect: 'statistics.totalDirect',
+	totalLivechat: 'statistics.totalLivechat',
+	totalDiscussions: 'statistics.totalDiscussions',
+	totalThreads: 'statistics.totalThreads',
+	totalMessages: 'statistics.totalMessages',
+	totalChannelMessages: 'statistics.totalChannelMessages',
+	totalPrivateGroupMessages: 'statistics.totalPrivateGroupMessages',
+	totalDirectMessages: 'statistics.totalDirectMessages',
+	totalLivechatMessages: 'statistics.totalLivechatMessages',
+	uploadsTotal: 'statistics.uploadsTotal',
+	uploadsTotalSize: 1024,
+	integrations: {
+		totalIntegrations: 'statistics.integrations.totalIntegrations',
+		totalIncoming: 'statistics.integrations.totalIncoming',
+		totalIncomingActive: 'statistics.integrations.totalIncomingActive',
+		totalOutgoing: 'statistics.integrations.totalOutgoing',
+		totalOutgoingActive: 'statistics.integrations.totalOutgoingActive',
+		totalWithScriptEnabled: 'statistics.integrations.totalWithScriptEnabled',
+	},
+};
+
+const apps = {
+	totalInstalled: 'statistics.apps.totalInstalled',
+	totalActive: 'statistics.apps.totalActive',
+};
+
+export const _default = () => <UsageSection statistics={statistics} />;
+
+export const withApps = () => <UsageSection statistics={{ ...statistics, apps }} />;
+
+export const loading = () => <UsageSection statistics={{}} isLoading />;
diff --git a/client/components/admin/settings/GroupPage.js b/client/components/admin/settings/GroupPage.js
new file mode 100644
index 0000000000000000000000000000000000000000..9840b97e75b848b217f7cc3404c38ba08a55d9c9
--- /dev/null
+++ b/client/components/admin/settings/GroupPage.js
@@ -0,0 +1,92 @@
+import { Accordion, Button, Paragraph, Text } from '@rocket.chat/fuselage';
+import React from 'react';
+import styled from 'styled-components';
+
+import { Header } from '../../header/Header';
+import { useTranslation } from '../../providers/TranslationProvider';
+import { Section } from './Section';
+
+const Wrapper = styled.div`
+	margin: 0 auto;
+	width: 100%;
+	max-width: 590px;
+`;
+
+export function GroupPage({ children, group, headerButtons }) {
+	const t = useTranslation();
+
+	const handleSubmit = (event) => {
+		event.preventDefault();
+		group.save();
+	};
+
+	const handleCancelClick = (event) => {
+		event.preventDefault();
+		group.cancel();
+	};
+
+	const handleSaveClick = (event) => {
+		event.preventDefault();
+		group.save();
+	};
+
+	if (!group) {
+		return <section className='page-container page-static page-settings'>
+			<Header />
+			<div className='content' />
+		</section>;
+	}
+
+	return <form action='#' className='page-container' method='post' onSubmit={handleSubmit}>
+		<Header rawSectionName={t(group.i18nLabel)}>
+			<Header.ButtonSection>
+				{group.changed && <Button danger primary type='reset' onClick={handleCancelClick}>{t('Cancel')}</Button>}
+				<Button
+					children={t('Save_changes')}
+					className='save'
+					disabled={!group.changed}
+					primary
+					type='submit'
+					onClick={handleSaveClick}
+				/>
+				{headerButtons}
+			</Header.ButtonSection>
+		</Header>
+
+		<div className='content'>
+			<Wrapper>
+				{t.has(group.i18nDescription) && <Paragraph hintColor>{t(group.i18nDescription)}</Paragraph>}
+
+				<Accordion className='page-settings'>
+					{children}
+				</Accordion>
+			</Wrapper>
+		</div>
+	</form>;
+}
+
+GroupPage.Skeleton = function Skeleton() {
+	const t = useTranslation();
+
+	return <div className='page-container'>
+		<Header rawSectionName={<div style={{ width: '20rem' }}><Text.Skeleton animated headline /></div>}>
+			<Header.ButtonSection>
+				<Button
+					children={t('Save_changes')}
+					disabled
+					primary
+				/>
+			</Header.ButtonSection>
+		</Header>
+
+		<div className='content'>
+			<Wrapper>
+				<Paragraph.Skeleton animated />
+
+				<Accordion className='page-settings'>
+					<Section.Skeleton />
+				</Accordion>
+			</Wrapper>
+		</div>
+	</div>;
+};
diff --git a/client/components/admin/settings/GroupSelector.js b/client/components/admin/settings/GroupSelector.js
new file mode 100644
index 0000000000000000000000000000000000000000..a07d54709e640806a7669f10d46c8493a454af5f
--- /dev/null
+++ b/client/components/admin/settings/GroupSelector.js
@@ -0,0 +1,23 @@
+import React, { useMemo } from 'react';
+
+import { AssetsGroupPage } from './groups/AssetsGroupPage';
+import { OAuthGroupPage } from './groups/OAuthGroupPage';
+import { GenericGroupPage } from './groups/GenericGroupPage';
+import { GroupPage } from './GroupPage';
+import { useGroup } from './SettingsState';
+
+export function GroupSelector({ groupId }) {
+	const group = useGroup(groupId);
+
+	const children = useMemo(() => {
+		if (!group) {
+			return <GroupPage.Skeleton />;
+		}
+
+		return (group._id === 'Assets' && <AssetsGroupPage group={group} />)
+			|| (group._id === 'OAuth' && <OAuthGroupPage group={group} />)
+			|| <GenericGroupPage group={group} />;
+	}, [group]);
+
+	return children;
+}
diff --git a/client/components/admin/settings/NotAuthorizedPage.js b/client/components/admin/settings/NotAuthorizedPage.js
new file mode 100644
index 0000000000000000000000000000000000000000..f65ffd19cc0e59b147520889cca1e5c91927e38a
--- /dev/null
+++ b/client/components/admin/settings/NotAuthorizedPage.js
@@ -0,0 +1,13 @@
+import React from 'react';
+
+import { useTranslation } from '../../providers/TranslationProvider';
+
+export function NotAuthorizedPage() {
+	const t = useTranslation();
+
+	return <section className='page-container page-static page-settings'>
+		<div className='content'>
+			<p>{t('You_are_not_authorized_to_view_this_page')}</p>
+		</div>
+	</section>;
+}
diff --git a/client/components/admin/settings/NotAuthorizedPage.stories.js b/client/components/admin/settings/NotAuthorizedPage.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..df29af858e1404c3c3dfe6d522593f958937d50a
--- /dev/null
+++ b/client/components/admin/settings/NotAuthorizedPage.stories.js
@@ -0,0 +1,11 @@
+import React from 'react';
+
+import { NotAuthorizedPage } from './NotAuthorizedPage';
+
+export default {
+	title: 'admin/settings/NotAuthorizedPage',
+	component: NotAuthorizedPage,
+};
+
+export const _default = () =>
+	<NotAuthorizedPage />;
diff --git a/client/components/admin/settings/ResetSettingButton.js b/client/components/admin/settings/ResetSettingButton.js
new file mode 100644
index 0000000000000000000000000000000000000000..69655de70cfa66bb8679acb99a77d0b645a95f40
--- /dev/null
+++ b/client/components/admin/settings/ResetSettingButton.js
@@ -0,0 +1,27 @@
+import { Button, Icon } from '@rocket.chat/fuselage';
+import React from 'react';
+import styled from 'styled-components';
+
+import { useTranslation } from '../../providers/TranslationProvider';
+
+// TODO: get rid of it
+const StyledResetSettingButton = styled(Button)`
+	padding-block: 0 !important;
+	padding-top: 0 !important;
+	padding-bottom: 0 !important;
+`;
+
+export function ResetSettingButton(props) {
+	const t = useTranslation();
+
+	return <StyledResetSettingButton
+		aria-label={t('Reset')}
+		danger
+		ghost
+		small
+		title={t('Reset')}
+		{...props}
+	>
+		<Icon name='undo' />
+	</StyledResetSettingButton>;
+}
diff --git a/client/components/admin/settings/Section.js b/client/components/admin/settings/Section.js
new file mode 100644
index 0000000000000000000000000000000000000000..95e8280cf7f4bbd752da6daa2c96abdd69855bb8
--- /dev/null
+++ b/client/components/admin/settings/Section.js
@@ -0,0 +1,51 @@
+import { Accordion, Button, FieldGroup, Paragraph, Text } from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { useTranslation } from '../../providers/TranslationProvider';
+import { Setting } from './Setting';
+import { useSection } from './SettingsState';
+
+export function Section({ children, groupId, hasReset = true, help, sectionName, solo }) {
+	const section = useSection(groupId, sectionName);
+	const t = useTranslation();
+
+	const handleResetSectionClick = () => {
+		section.reset();
+	};
+
+	return <Accordion.Item
+		data-qa-section={sectionName}
+		noncollapsible={solo || !section.name}
+		title={section.name && t(section.name)}
+	>
+		{help && <Paragraph hintColor>{help}</Paragraph>}
+
+		<FieldGroup>
+			{section.settings.map((settingId) => <Setting key={settingId} settingId={settingId} />)}
+
+			{hasReset && section.canReset && <Button
+				children={t('Reset_section_settings')}
+				className='reset-group'
+				danger
+				data-section={section.name}
+				ghost
+				onClick={handleResetSectionClick}
+			/>}
+
+			{children}
+		</FieldGroup>
+	</Accordion.Item>;
+}
+
+Section.Skeleton = function Skeleton() {
+	return <Accordion.Item
+		noncollapsible
+		title={<Text.Skeleton animated subtitle />}
+	>
+		<Paragraph.Skeleton animated />
+
+		<FieldGroup>
+			{Array.from({ length: 10 }).map((_, i) => <Setting.Skeleton key={i} />)}
+		</FieldGroup>
+	</Accordion.Item>;
+};
diff --git a/client/components/admin/settings/Setting.js b/client/components/admin/settings/Setting.js
new file mode 100644
index 0000000000000000000000000000000000000000..9d3a5c8e503294309b4aa0276db5e464fc473b52
--- /dev/null
+++ b/client/components/admin/settings/Setting.js
@@ -0,0 +1,131 @@
+import { Callout, Field, InputBox, Label, Text } from '@rocket.chat/fuselage';
+import { useDebouncedCallback } from '@rocket.chat/fuselage-hooks';
+import React, { useEffect, useMemo, useState } from 'react';
+
+import { MarkdownText } from '../../basic/MarkdownText';
+import { RawText } from '../../basic/RawText';
+import { useTranslation } from '../../providers/TranslationProvider';
+import { GenericSettingInput } from './inputs/GenericSettingInput';
+import { BooleanSettingInput } from './inputs/BooleanSettingInput';
+import { StringSettingInput } from './inputs/StringSettingInput';
+import { RelativeUrlSettingInput } from './inputs/RelativeUrlSettingInput';
+import { PasswordSettingInput } from './inputs/PasswordSettingInput';
+import { IntSettingInput } from './inputs/IntSettingInput';
+import { SelectSettingInput } from './inputs/SelectSettingInput';
+import { LanguageSettingInput } from './inputs/LanguageSettingInput';
+import { ColorSettingInput } from './inputs/ColorSettingInput';
+import { FontSettingInput } from './inputs/FontSettingInput';
+import { CodeSettingInput } from './inputs/CodeSettingInput';
+import { ActionSettingInput } from './inputs/ActionSettingInput';
+import { AssetSettingInput } from './inputs/AssetSettingInput';
+import { RoomPickSettingInput } from './inputs/RoomPickSettingInput';
+import { useSetting } from './SettingsState';
+
+const getInputComponentByType = (type) => ({
+	boolean: BooleanSettingInput,
+	string: StringSettingInput,
+	relativeUrl: RelativeUrlSettingInput,
+	password: PasswordSettingInput,
+	int: IntSettingInput,
+	select: SelectSettingInput,
+	language: LanguageSettingInput,
+	color: ColorSettingInput,
+	font: FontSettingInput,
+	code: CodeSettingInput,
+	action: ActionSettingInput,
+	asset: AssetSettingInput,
+	roomPick: RoomPickSettingInput,
+})[type] || GenericSettingInput;
+
+const MemoizedSetting = React.memo(function MemoizedSetting({
+	type,
+	hint,
+	callout,
+	...inputProps
+}) {
+	const InputComponent = getInputComponentByType(type);
+
+	return <Field>
+		<InputComponent {...inputProps} />
+		{hint && <Field.Hint>{hint}</Field.Hint>}
+		{callout && <Callout type='warning' title={callout} />}
+	</Field>;
+});
+
+export function Setting({ settingId }) {
+	const {
+		value: contextValue,
+		editor: contextEditor,
+		...setting
+	} = useSetting(settingId);
+
+	const t = useTranslation();
+
+	const [value, setValue] = useState(contextValue);
+	const setContextValue = useDebouncedCallback((value) => setting.update({ value }), 70, []);
+
+	useEffect(() => {
+		setValue(contextValue);
+	}, [contextValue]);
+
+	const [editor, setEditor] = useState(contextEditor);
+	const setContextEditor = useDebouncedCallback((editor) => setting.update({ editor }), 70, []);
+
+	useEffect(() => {
+		setEditor(contextEditor);
+	}, [contextEditor]);
+
+	const onChangeValue = (value) => {
+		setValue(value);
+		setContextValue(value);
+	};
+
+	const onChangeEditor = (editor) => {
+		setEditor(editor);
+		setContextEditor(editor);
+	};
+
+	const onResetButtonClick = () => {
+		setting.reset();
+	};
+
+	const {
+		_id,
+		disableReset,
+		readonly,
+		type,
+		packageValue,
+		blocked,
+		i18nLabel,
+		i18nDescription,
+		alert,
+	} = setting;
+
+	const label = (i18nLabel && t(i18nLabel)) || (_id || t(_id));
+	const hint = useMemo(() => t.has(i18nDescription) && <MarkdownText>{t(i18nDescription)}</MarkdownText>, [i18nDescription]);
+	const callout = useMemo(() => alert && <RawText>{t(alert)}</RawText>, [alert]);
+	const hasResetButton = !disableReset && !readonly && type !== 'asset' && value !== packageValue && !blocked;
+
+	return <MemoizedSetting
+		type={type}
+		label={label}
+		hint={hint}
+		callout={callout}
+		{...setting}
+		value={value}
+		editor={editor}
+		hasResetButton={hasResetButton}
+		onChangeValue={onChangeValue}
+		onChangeEditor={onChangeEditor}
+		onResetButtonClick={onResetButtonClick}
+	/>;
+}
+
+Setting.Skeleton = function Skeleton() {
+	return <Field>
+		<Label>
+			<Text.Skeleton animated width='1/4' />
+		</Label>
+		<InputBox.Skeleton animated />
+	</Field>;
+};
diff --git a/client/components/admin/settings/SettingsRoute.js b/client/components/admin/settings/SettingsRoute.js
new file mode 100644
index 0000000000000000000000000000000000000000..778e85f2365632e948433ed7956871d4ad6b887e
--- /dev/null
+++ b/client/components/admin/settings/SettingsRoute.js
@@ -0,0 +1,27 @@
+import React from 'react';
+
+import { useAtLeastOnePermission } from '../../../hooks/usePermissions';
+import { useAdminSideNav } from '../hooks';
+import { GroupSelector } from './GroupSelector';
+import { NotAuthorizedPage } from './NotAuthorizedPage';
+import { SettingsState } from './SettingsState';
+
+export function SettingsRoute({
+	group: groupId,
+}) {
+	useAdminSideNav();
+
+	const hasPermission = useAtLeastOnePermission([
+		'view-privileged-setting',
+		'edit-privileged-setting',
+		'manage-selected-settings',
+	]);
+
+	if (!hasPermission) {
+		return <NotAuthorizedPage />;
+	}
+
+	return <SettingsState>
+		<GroupSelector groupId={groupId} />
+	</SettingsState>;
+}
diff --git a/client/components/admin/settings/SettingsState.js b/client/components/admin/settings/SettingsState.js
new file mode 100644
index 0000000000000000000000000000000000000000..5d39179e11edbf47604363ba2ee99e4ff0d4af0d
--- /dev/null
+++ b/client/components/admin/settings/SettingsState.js
@@ -0,0 +1,384 @@
+import { Meteor } from 'meteor/meteor';
+import { Mongo } from 'meteor/mongo';
+import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
+import React, { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from 'react';
+import toastr from 'toastr';
+
+import { PrivateSettingsCachedCollection } from '../../../../app/ui-admin/client/SettingsCachedCollection';
+import { handleError } from '../../../../app/utils/client/lib/handleError';
+import { useBatchSetSettings } from '../../../hooks/useBatchSetSettings';
+import { useEventCallback } from '../../../hooks/useEventCallback';
+import { useReactiveValue } from '../../../hooks/useReactiveValue';
+
+const SettingsContext = createContext({});
+
+let privateSettingsCachedCollection; // Remove this singleton (╯°□°)╯︵ ┻━┻
+
+const getPrivateSettingsCachedCollection = () => {
+	if (privateSettingsCachedCollection) {
+		return [privateSettingsCachedCollection, Promise.resolve()];
+	}
+
+	privateSettingsCachedCollection = new PrivateSettingsCachedCollection();
+
+	return [privateSettingsCachedCollection, privateSettingsCachedCollection.init()];
+};
+
+const compareStrings = (a = '', b = '') => {
+	if (a === b || (!a && !b)) {
+		return 0;
+	}
+
+	return a > b ? 1 : -1;
+};
+
+const compareSettings = (a, b) =>
+	compareStrings(a.section, b.section)
+	|| compareStrings(a.sorter, b.sorter)
+	|| compareStrings(a.i18nLabel, b.i18nLabel);
+
+const settingsReducer = (states, { type, payload }) => {
+	const {
+		settings,
+		persistedSettings,
+	} = states;
+
+	switch (type) {
+		case 'add': {
+			return {
+				settings: [...settings, ...payload].sort(compareSettings),
+				persistedSettings: [...persistedSettings, ...payload].sort(compareSettings),
+			};
+		}
+
+		case 'change': {
+			const mapping = (setting) => (setting._id !== payload._id ? setting : payload);
+
+			return {
+				settings: settings.map(mapping),
+				persistedSettings: settings.map(mapping),
+			};
+		}
+
+		case 'remove': {
+			const mapping = (setting) => setting._id !== payload;
+
+			return {
+				settings: settings.filter(mapping),
+				persistedSettings: persistedSettings.filter(mapping),
+			};
+		}
+
+		case 'hydrate': {
+			const map = {};
+			payload.forEach((setting) => {
+				map[setting._id] = setting;
+			});
+
+			const mapping = (setting) => (map[setting._id] ? { ...setting, ...map[setting._id] } : setting);
+
+			return {
+				settings: settings.map(mapping),
+				persistedSettings,
+			};
+		}
+	}
+
+	return states;
+};
+
+export function SettingsState({ children }) {
+	const [isLoading, setLoading] = useState(true);
+
+	const [subscribers] = useState(new Set());
+
+	const stateRef = useRef({ settings: [], persistedSettings: [] });
+
+	const enhancedReducer = useCallback((state, action) => {
+		const newState = settingsReducer(state, action);
+
+		stateRef.current = newState;
+
+		subscribers.forEach((subscriber) => {
+			subscriber(newState);
+		});
+
+		return newState;
+	}, [settingsReducer, subscribers]);
+
+	const [, dispatch] = useReducer(enhancedReducer, { settings: [], persistedSettings: [] });
+
+	const collectionsRef = useRef({});
+
+	useEffect(() => {
+		const [privateSettingsCachedCollection, loadingPromise] = getPrivateSettingsCachedCollection();
+
+		const stopLoading = () => {
+			setLoading(false);
+		};
+
+		loadingPromise.then(stopLoading, stopLoading);
+
+		const { collection: persistedSettingsCollection } = privateSettingsCachedCollection;
+		const settingsCollection = new Mongo.Collection(null);
+
+		collectionsRef.current = {
+			persistedSettingsCollection,
+			settingsCollection,
+		};
+	}, [collectionsRef]);
+
+	useEffect(() => {
+		if (isLoading) {
+			return;
+		}
+
+		const { current: { persistedSettingsCollection, settingsCollection } } = collectionsRef;
+
+		const query = persistedSettingsCollection.find();
+
+		const syncCollectionsHandle = query.observe({
+			added: (data) => settingsCollection.insert(data),
+			changed: (data) => settingsCollection.update(data._id, data),
+			removed: ({ _id }) => settingsCollection.remove(_id),
+		});
+
+		const addedQueue = [];
+		let addedActionTimer;
+
+		const syncStateHandle = query.observe({
+			added: (data) => {
+				addedQueue.push(data);
+				clearTimeout(addedActionTimer);
+				addedActionTimer = setTimeout(() => {
+					dispatch({ type: 'add', payload: addedQueue });
+				}, 70);
+			},
+			changed: (data) => {
+				dispatch({ type: 'change', payload: data });
+			},
+			removed: ({ _id }) => {
+				dispatch({ type: 'remove', payload: _id });
+			},
+		});
+
+		return () => {
+			syncCollectionsHandle.stop();
+			syncStateHandle.stop();
+			clearTimeout(addedActionTimer);
+		};
+	}, [isLoading, collectionsRef]);
+
+	const updateTimersRef = useRef({});
+
+	const updateAtCollection = useCallback(({ _id, ...data }) => {
+		const { current: { settingsCollection } } = collectionsRef;
+		const { current: updateTimers } = updateTimersRef;
+		clearTimeout(updateTimers[_id]);
+		updateTimers[_id] = setTimeout(() => {
+			settingsCollection.update(_id, { $set: data });
+		}, 70);
+	}, [collectionsRef, updateTimersRef]);
+
+	const hydrate = useCallback((changes) => {
+		changes.forEach(updateAtCollection);
+		dispatch({ type: 'hydrate', payload: changes });
+	}, [updateAtCollection, dispatch]);
+
+	const isDisabled = useCallback(({ blocked, enableQuery }) => {
+		if (blocked) {
+			return true;
+		}
+
+		if (!enableQuery) {
+			return false;
+		}
+
+		const { current: { settingsCollection } } = collectionsRef;
+
+		const queries = [].concat(typeof enableQuery === 'string' ? JSON.parse(enableQuery) : enableQuery);
+		return !queries.every((query) => !!settingsCollection.findOne(query));
+	}, [collectionsRef]);
+
+	const contextValue = useMemo(() => ({
+		subscribers,
+		stateRef,
+		hydrate,
+		isDisabled,
+	}), [
+		subscribers,
+		stateRef,
+		hydrate,
+		isDisabled,
+	]);
+
+	return <SettingsContext.Provider children={children} value={contextValue} />;
+}
+
+const useSelector = (selector, equalityFunction = (a, b) => a === b) => {
+	const { subscribers, stateRef } = useContext(SettingsContext);
+	const [value, setValue] = useState(() => selector(stateRef.current));
+
+	const handleUpdate = useEventCallback((selector, equalityFunction, value, state) => {
+		const newValue = selector(state);
+
+		if (!equalityFunction(newValue, value)) {
+			setValue(newValue);
+		}
+	}, selector, equalityFunction, value);
+
+	useEffect(() => {
+		subscribers.add(handleUpdate);
+
+		return () => {
+			subscribers.delete(handleUpdate);
+		};
+	}, [handleUpdate]);
+
+	useLayoutEffect(() => {
+		handleUpdate(stateRef.current);
+	});
+
+	return value;
+};
+
+export const useGroup = (groupId) => {
+	const group = useSelector((state) => state.settings.find(({ _id, type }) => _id === groupId && type === 'group'));
+
+	const filterSettings = (settings) => settings.filter(({ group }) => group === groupId);
+
+	const changed = useSelector((state) => filterSettings(state.settings).some(({ changed }) => changed));
+	const sections = useSelector((state) => Array.from(new Set(filterSettings(state.settings).map(({ section }) => section || ''))), (a, b) => a.length === b.length && a.join() === b.join());
+
+	const batchSetSettings = useBatchSetSettings();
+	const { stateRef, hydrate } = useContext(SettingsContext);
+
+	const save = useEventCallback(async (filterSettings, { current: state }, batchSetSettings) => {
+		const settings = filterSettings(state.settings);
+
+		const changes = settings.filter(({ changed }) => changed)
+			.map(({ _id, value, editor }) => ({ _id, value, editor }));
+
+		if (changes.length === 0) {
+			return;
+		}
+
+		try {
+			await batchSetSettings(changes);
+
+			if (changes.some(({ _id }) => _id === 'Language')) {
+				const lng = Meteor.user().language
+					|| changes.filter(({ _id }) => _id === 'Language').shift().value
+					|| 'en';
+
+				TAPi18n._loadLanguage(lng)
+					.then(() => toastr.success(TAPi18n.__('Settings_updated', { lng })))
+					.catch(handleError);
+
+				return;
+			}
+
+			toastr.success(TAPi18n.__('Settings_updated'));
+		} catch (error) {
+			handleError(error);
+		}
+	}, filterSettings, stateRef, batchSetSettings);
+
+	const cancel = useEventCallback((filterSettings, { current: state }, hydrate) => {
+		const settings = filterSettings(state.settings);
+		const persistedSettings = filterSettings(state.persistedSettings);
+
+		const changes = settings.filter(({ changed }) => changed)
+			.map((field) => {
+				const { _id, value, editor } = persistedSettings.find(({ _id }) => _id === field._id);
+				return { _id, value, editor, changed: false };
+			});
+
+		hydrate(changes);
+	}, filterSettings, stateRef, hydrate);
+
+	return group && { ...group, sections, changed, save, cancel };
+};
+
+export const useSection = (groupId, sectionName) => {
+	sectionName = sectionName || '';
+
+	const filterSettings = (settings) =>
+		settings.filter(({ group, section }) => group === groupId && ((!sectionName && !section) || (sectionName === section)));
+
+	const changed = useSelector((state) => filterSettings(state.settings).some(({ changed }) => changed));
+	const canReset = useSelector((state) => filterSettings(state.settings).some(({ value, packageValue }) => value !== packageValue));
+	const settingsIds = useSelector((state) => filterSettings(state.settings).map(({ _id }) => _id), (a, b) => a.length === b.length && a.join() === b.join());
+
+	const { stateRef, hydrate } = useContext(SettingsContext);
+
+	const reset = useEventCallback((filterSettings, { current: state }, hydrate) => {
+		const settings = filterSettings(state.settings);
+		const persistedSettings = filterSettings(state.persistedSettings);
+
+		const changes = settings.map((setting) => {
+			const { _id, value, packageValue, editor } = persistedSettings.find(({ _id }) => _id === setting._id);
+			return {
+				_id,
+				value: packageValue,
+				editor,
+				changed: packageValue !== value,
+			};
+		});
+
+		hydrate(changes);
+	}, filterSettings, stateRef, hydrate);
+
+	return {
+		name: sectionName,
+		changed,
+		canReset,
+		settings: settingsIds,
+		reset,
+	};
+};
+
+export const useSetting = (_id) => {
+	const { stateRef, hydrate, isDisabled } = useContext(SettingsContext);
+
+	const selectSetting = (settings) => settings.find((setting) => setting._id === _id);
+
+	const setting = useSelector((state) => selectSetting(state.settings));
+	const sectionChanged = useSelector((state) => state.settings.some(({ section, changed }) => section === setting.section && changed));
+	const disabled = useReactiveValue(() => isDisabled(setting), [setting.blocked, setting.enableQuery]);
+
+	const update = useEventCallback((selectSetting, { current: state }, hydrate, data) => {
+		const setting = { ...selectSetting(state.settings), ...data };
+		const persistedSetting = selectSetting(state.persistedSettings);
+
+		const changes = [{
+			_id: setting._id,
+			value: setting.value,
+			editor: setting.editor,
+			changed: (setting.value !== persistedSetting.value) || (setting.editor !== persistedSetting.editor),
+		}];
+
+		hydrate(changes);
+	}, selectSetting, stateRef, hydrate);
+
+	const reset = useEventCallback((selectSetting, { current: state }, hydrate) => {
+		const { _id, value, packageValue, editor } = selectSetting(state.persistedSettings);
+
+		const changes = [{
+			_id,
+			value: packageValue,
+			editor,
+			changed: packageValue !== value,
+		}];
+
+		hydrate(changes);
+	}, selectSetting, stateRef, hydrate);
+
+	return {
+		...setting,
+		sectionChanged,
+		disabled,
+		update,
+		reset,
+	};
+};
diff --git a/client/components/admin/settings/groups/AssetsGroupPage.js b/client/components/admin/settings/groups/AssetsGroupPage.js
new file mode 100644
index 0000000000000000000000000000000000000000..7f9b49f93965e31d73d0359282c4e0228f69ffeb
--- /dev/null
+++ b/client/components/admin/settings/groups/AssetsGroupPage.js
@@ -0,0 +1,23 @@
+import { Button } from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { useTranslation } from '../../../providers/TranslationProvider';
+import { GroupPage } from '../GroupPage';
+import { Section } from '../Section';
+
+export function AssetsGroupPage({ group }) {
+	const solo = group.sections.length === 1;
+	const t = useTranslation();
+
+	return <GroupPage group={group} headerButtons={<>
+		<Button className='refresh-clients'>{t('Apply_and_refresh_all_clients')}</Button>
+	</>}>
+		{group.sections.map((sectionName) => <Section
+			key={sectionName}
+			groupId={group._id}
+			hasReset={false}
+			sectionName={sectionName}
+			solo={solo}
+		/>)}
+	</GroupPage>;
+}
diff --git a/client/components/admin/settings/groups/GenericGroupPage.js b/client/components/admin/settings/groups/GenericGroupPage.js
new file mode 100644
index 0000000000000000000000000000000000000000..09b4e190f85c2b21c050b758c4c848d500d5fa9e
--- /dev/null
+++ b/client/components/admin/settings/groups/GenericGroupPage.js
@@ -0,0 +1,17 @@
+import React from 'react';
+
+import { GroupPage } from '../GroupPage';
+import { Section } from '../Section';
+
+export function GenericGroupPage({ group }) {
+	const solo = group.sections.length === 1;
+
+	return <GroupPage group={group}>
+		{group.sections.map((sectionName) => <Section
+			key={sectionName}
+			groupId={group._id}
+			sectionName={sectionName}
+			solo={solo}
+		/>)}
+	</GroupPage>;
+}
diff --git a/client/components/admin/settings/groups/OAuthGroupPage.js b/client/components/admin/settings/groups/OAuthGroupPage.js
new file mode 100644
index 0000000000000000000000000000000000000000..44bf71af1671fcd88aed26fa0e86c9259ec23058
--- /dev/null
+++ b/client/components/admin/settings/groups/OAuthGroupPage.js
@@ -0,0 +1,40 @@
+import { Button } from '@rocket.chat/fuselage';
+import { Meteor } from 'meteor/meteor';
+import React from 'react';
+import s from 'underscore.string';
+
+import { RawText } from '../../../basic/RawText';
+import { useTranslation } from '../../../providers/TranslationProvider';
+import { GroupPage } from '../GroupPage';
+import { Section } from '../Section';
+
+export function OAuthGroupPage({ group }) {
+	const solo = group.sections.length === 1;
+	const t = useTranslation();
+
+	const sectionIsCustomOAuth = (sectionName) => sectionName && /^Custom OAuth:\s.+/.test(sectionName);
+
+	const callbackURL = (sectionName) => {
+		const id = s.strRight(sectionName, 'Custom OAuth: ').toLowerCase();
+		return Meteor.absoluteUrl(`_oauth/${ id }`);
+	};
+
+	return <GroupPage group={group} headerButtons={<>
+		<Button className='refresh-oauth'>{t('Refresh_oauth_services')}</Button>
+		<Button className='add-custom-oauth'>{t('Add_custom_oauth')}</Button>
+	</>}>
+		{group.sections.map((sectionName) => (sectionIsCustomOAuth(sectionName)
+			? <Section
+				key={sectionName}
+				groupId={group._id}
+				help={<RawText>{t('Custom_oauth_helper', callbackURL(sectionName))}</RawText>}
+				sectionName={sectionName}
+				solo={solo}
+			>
+				<div className='submit'>
+					<Button cancel className='remove-custom-oauth'>{t('Remove_custom_oauth')}</Button>
+				</div>
+			</Section>
+			: <Section key={sectionName} groupId={group._id} sectionName={sectionName} solo={solo} />))}
+	</GroupPage>;
+}
diff --git a/client/components/admin/settings/inputs/ActionSettingInput.js b/client/components/admin/settings/inputs/ActionSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..bdcad8acf14902e3950bca00e6513fd35a298647
--- /dev/null
+++ b/client/components/admin/settings/inputs/ActionSettingInput.js
@@ -0,0 +1,44 @@
+import { Button, Field } from '@rocket.chat/fuselage';
+import { Meteor } from 'meteor/meteor';
+import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
+import React from 'react';
+import toastr from 'toastr';
+
+import { useTranslation } from '../../../providers/TranslationProvider';
+import { handleError } from '../../../../../app/utils/client';
+
+export function ActionSettingInput({
+	_id,
+	actionText,
+	value,
+	disabled,
+	sectionChanged,
+}) {
+	const t = useTranslation();
+
+	const handleClick = async () => {
+		Meteor.call(value, (err, data) => {
+			if (err) {
+				err.details = Object.assign(err.details || {}, {
+					errorTitle: 'Error',
+				});
+				handleError(err);
+				return;
+			}
+
+			const args = [data.message].concat(data.params);
+			toastr.success(TAPi18n.__.apply(TAPi18n, args), TAPi18n.__('Success'));
+		});
+	};
+
+	return <>
+		<Button
+			data-qa-setting-id={_id}
+			children={t(actionText)}
+			disabled={disabled || sectionChanged}
+			primary
+			onClick={handleClick}
+		/>
+		{sectionChanged && <Field.Hint>{t('Save_to_enable_this_action')}</Field.Hint>}
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/AssetSettingInput.js b/client/components/admin/settings/inputs/AssetSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..22abcbcf90edbaecc2ed6bada98d307785603955
--- /dev/null
+++ b/client/components/admin/settings/inputs/AssetSettingInput.js
@@ -0,0 +1,72 @@
+import { Button, Icon, Label } from '@rocket.chat/fuselage';
+import { Meteor } from 'meteor/meteor';
+import { Random } from 'meteor/random';
+import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
+import React from 'react';
+import toastr from 'toastr';
+
+import { handleError } from '../../../../../app/utils/client';
+import { useTranslation } from '../../../providers/TranslationProvider';
+
+export function AssetSettingInput({
+	_id,
+	label,
+	value,
+	asset,
+	fileConstraints,
+}) {
+	const t = useTranslation();
+
+	const handleUpload = (event) => {
+		event = event.originalEvent || event;
+
+		let { files } = event.target;
+		if (!files || files.length === 0) {
+			if (event.dataTransfer && event.dataTransfer.files) {
+				files = event.dataTransfer.files;
+			} else {
+				files = [];
+			}
+		}
+
+		Object.values(files).forEach((blob) => {
+			toastr.info(TAPi18n.__('Uploading_file'));
+			const reader = new FileReader();
+			reader.readAsBinaryString(blob);
+			reader.onloadend = () => Meteor.call('setAsset', reader.result, blob.type, asset, function(err) {
+				if (err != null) {
+					handleError(err);
+					console.log(err);
+					return;
+				}
+				return toastr.success(TAPi18n.__('File_uploaded'));
+			});
+		});
+	};
+
+	const handleDeleteButtonClick = () => {
+		Meteor.call('unsetAsset', asset);
+	};
+
+	return <>
+		<Label htmlFor={_id} text={label} title={_id} />
+		<div className='settings-file-preview'>
+			{value.url
+				? <div className='preview' style={{ backgroundImage: `url(${ value.url }?_dc=${ Random.id() })` }} />
+				: <div className='preview no-file background-transparent-light secondary-font-color'><Icon icon='icon-upload' /></div>}
+			<div className='action'>
+				{value.url
+					? <Button onClick={handleDeleteButtonClick}>
+						<Icon name='trash' />{t('Delete')}
+					</Button>
+					: <div className='rc-button rc-button--primary'>{t('Select_file')}
+						<input
+							type='file'
+							accept={fileConstraints.extensions && fileConstraints.extensions.length && `.${ fileConstraints.extensions.join(', .') }`}
+							onChange={handleUpload}
+						/>
+					</div>}
+			</div>
+		</div>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/BooleanSettingInput.js b/client/components/admin/settings/inputs/BooleanSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..b48508b45dbcedcd5fefab056c81b78fdb012fec
--- /dev/null
+++ b/client/components/admin/settings/inputs/BooleanSettingInput.js
@@ -0,0 +1,40 @@
+import {
+	Field,
+	Label,
+	ToggleSwitch,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function BooleanSettingInput({
+	_id,
+	label,
+	disabled,
+	readonly,
+	autocomplete,
+	value,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const handleChange = (event) => {
+		const value = event.currentTarget.checked;
+		onChangeValue(value);
+	};
+
+	return <Field.Row>
+		<Label position='end' text={label} title={_id}>
+			<ToggleSwitch
+				data-qa-setting-id={_id}
+				value='true'
+				checked={value === true}
+				disabled={disabled}
+				readOnly={readonly}
+				autoComplete={autocomplete === false ? 'off' : undefined}
+				onChange={handleChange}
+			/>
+		</Label>
+		{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+	</Field.Row>;
+}
diff --git a/client/components/admin/settings/inputs/CodeSettingInput.js b/client/components/admin/settings/inputs/CodeSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..daed128d7c6c743ce1f06d4dfcf7a06475383964
--- /dev/null
+++ b/client/components/admin/settings/inputs/CodeSettingInput.js
@@ -0,0 +1,143 @@
+import { Button, Field, Label } from '@rocket.chat/fuselage';
+import { useToggle } from '@rocket.chat/fuselage-hooks';
+import React, { useEffect, useRef, useState } from 'react';
+
+import { useTranslation } from '../../../providers/TranslationProvider';
+import { ResetSettingButton } from '../ResetSettingButton';
+
+function CodeMirror({
+	lineNumbers = true,
+	lineWrapping = true,
+	mode = 'javascript',
+	gutters = ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
+	foldGutter = true,
+	matchBrackets = true,
+	autoCloseBrackets = true,
+	matchTags = true,
+	showTrailingSpace = true,
+	highlightSelectionMatches = true,
+	readOnly,
+	value: valueProp,
+	defaultValue,
+	onChange,
+	...props
+}) {
+	const [editor, setEditor] = useState();
+	const [value, setValue] = useState(valueProp || defaultValue);
+	const ref = useRef();
+
+	useEffect(() => {
+		let editor;
+
+		const setupCodeMirror = async () => {
+			const CodeMirror = await import('codemirror/lib/codemirror.js');
+			await import('../../../../../app/ui/client/lib/codeMirror/codeMirror');
+			await import('codemirror/lib/codemirror.css');
+
+			const { current: textarea } = ref;
+
+			if (!textarea) {
+				return;
+			}
+
+			editor = CodeMirror.fromTextArea(textarea, {
+				lineNumbers,
+				lineWrapping,
+				mode,
+				gutters,
+				foldGutter,
+				matchBrackets,
+				autoCloseBrackets,
+				matchTags,
+				showTrailingSpace,
+				highlightSelectionMatches,
+				readOnly,
+			});
+
+			editor.on('change', (doc) => {
+				const value = doc.getValue();
+				setValue(value);
+				onChange(value);
+			});
+
+			setEditor(editor);
+		};
+
+		setupCodeMirror();
+
+		return () => {
+			if (!editor) {
+				return;
+			}
+
+			editor.toTextArea();
+		};
+	}, [ref]);
+
+	useEffect(() => {
+		setValue(valueProp);
+	}, [valueProp]);
+
+	useEffect(() => {
+		if (!editor) {
+			return;
+		}
+
+		if (value !== editor.getValue()) {
+			editor.setValue(value);
+		}
+	}, [editor, ref, value]);
+
+	return <textarea readOnly ref={ref} style={{ display: 'none' }} value={value} {...props}/>;
+}
+
+export function CodeSettingInput({
+	_id,
+	label,
+	value,
+	code,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const t = useTranslation();
+
+	const [fullScreen, toggleFullScreen] = useToggle(false);
+
+	const handleChange = (value) => {
+		onChangeValue(value);
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<div
+			className={[
+				'code-mirror-box',
+				fullScreen && 'code-mirror-box-fullscreen content-background-color',
+			].filter(Boolean).join(' ')}
+		>
+			<div className='title'>{label}</div>
+			<CodeMirror
+				data-qa-setting-id={_id}
+				id={_id}
+				mode={code}
+				value={value}
+				placeholder={placeholder}
+				disabled={disabled}
+				readOnly={readonly}
+				autoComplete={autocomplete === false ? 'off' : undefined}
+				onChange={handleChange}
+			/>
+			<div className='buttons'>
+				<Button primary onClick={() => toggleFullScreen()}>{fullScreen ? t('Exit_Full_Screen') : t('Full_Screen')}</Button>
+			</div>
+		</div>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/ColorSettingInput.js b/client/components/admin/settings/inputs/ColorSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..a5523ac60f541e6d44c57fd2e0c60ba06f767bd8
--- /dev/null
+++ b/client/components/admin/settings/inputs/ColorSettingInput.js
@@ -0,0 +1,112 @@
+import {
+	Field,
+	InputBox,
+	Label,
+	SelectInput,
+	TextInput,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { useTranslation } from '../../../providers/TranslationProvider';
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function ColorSettingInput({
+	_id,
+	label,
+	value,
+	editor,
+	allowedTypes,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	hasResetButton,
+	onChangeValue,
+	onChangeEditor,
+	onResetButtonClick,
+}) {
+	const t = useTranslation();
+
+	const handleChange = (event) => {
+		onChangeValue(event.currentTarget.value);
+	};
+
+	const handleEditorTypeChange = (event) => {
+		const editor = event.currentTarget.value.trim();
+		onChangeEditor(editor);
+	};
+
+	return <>
+		<div
+			style={{
+				display: 'flex',
+				flexFlow: 'row nowrap',
+				margin: '0 -0.5rem',
+			}}
+		>
+			<Field
+				style={{
+					flex: '2 2 0',
+					margin: '0 0.5rem',
+				}}
+			>
+				<Label htmlFor={_id} text={label} title={_id} />
+				{editor === 'color' && <InputBox
+					data-qa-setting-id={_id}
+					type='color'
+					id={_id}
+					value={value}
+					placeholder={placeholder}
+					disabled={disabled}
+					readOnly={readonly}
+					autoComplete={autocomplete === false ? 'off' : undefined}
+					onChange={handleChange}
+					style={{
+						width: '100%',
+					}}
+				/>}
+				{editor === 'expression' && <TextInput
+					data-qa-setting-id={_id}
+					id={_id}
+					value={value}
+					placeholder={placeholder}
+					disabled={disabled}
+					readOnly={readonly}
+					autoComplete={autocomplete === false ? 'off' : undefined}
+					onChange={handleChange}
+					style={{
+						width: '100%',
+					}}
+				/>}
+			</Field>
+			<Field
+				style={{
+					flex: '1 1 0',
+					margin: '0 0.5rem',
+				}}
+			>
+				<Field.Row>
+					<Label htmlFor={`${ _id }_editor`} text={t('Type')} title={_id} />
+					{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+				</Field.Row>
+				<SelectInput
+					data-qa-setting-id={`${ _id }_editor`}
+					type='color'
+					id={`${ _id }_editor`}
+					value={editor}
+					disabled={disabled}
+					readOnly={readonly}
+					autoComplete={autocomplete === false ? 'off' : undefined}
+					onChange={handleEditorTypeChange}
+				>
+					{allowedTypes && allowedTypes.map((allowedType) =>
+						<SelectInput.Option key={allowedType} value={allowedType}>{t(allowedType)}</SelectInput.Option>
+					)}
+				</SelectInput>
+			</Field>
+		</div>
+		<Field.Hint>
+			Variable name: {_id.replace(/theme-color-/, '@')}
+		</Field.Hint>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/FontSettingInput.js b/client/components/admin/settings/inputs/FontSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..899e28271195ff50f99c4eecf43db4058595f178
--- /dev/null
+++ b/client/components/admin/settings/inputs/FontSettingInput.js
@@ -0,0 +1,42 @@
+import {
+	Field,
+	Label,
+	TextInput,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function FontSettingInput({
+	_id,
+	label,
+	value,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const handleChange = (event) => {
+		onChangeValue(event.currentTarget.value);
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<TextInput
+			data-qa-setting-id={_id}
+			id={_id}
+			value={value}
+			placeholder={placeholder}
+			disabled={disabled}
+			readOnly={readonly}
+			autoComplete={autocomplete === false ? 'off' : undefined}
+			onChange={handleChange}
+		/>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/GenericSettingInput.js b/client/components/admin/settings/inputs/GenericSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..c21892ae5f082c3e7583e9200f47e0e125b8ffcc
--- /dev/null
+++ b/client/components/admin/settings/inputs/GenericSettingInput.js
@@ -0,0 +1,42 @@
+import {
+	Field,
+	Label,
+	TextInput,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function GenericSettingInput({
+	_id,
+	label,
+	value,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const handleChange = (event) => {
+		onChangeValue(event.currentTarget.value);
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<TextInput
+			data-qa-setting-id={_id}
+			id={_id}
+			value={value}
+			placeholder={placeholder}
+			disabled={disabled}
+			readOnly={readonly}
+			autoComplete={autocomplete === false ? 'off' : undefined}
+			onChange={handleChange}
+		/>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/IntSettingInput.js b/client/components/admin/settings/inputs/IntSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..1e5048d0addb6e35f984f2fae556a77a9e9814c7
--- /dev/null
+++ b/client/components/admin/settings/inputs/IntSettingInput.js
@@ -0,0 +1,43 @@
+import {
+	Field,
+	Label,
+	InputBox,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function IntSettingInput({
+	_id,
+	label,
+	value,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	onChangeValue,
+	hasResetButton,
+	onResetButtonClick,
+}) {
+	const handleChange = (event) => {
+		onChangeValue(parseInt(event.currentTarget.value, 10));
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<InputBox
+			data-qa-setting-id={_id}
+			id={_id}
+			type='number'
+			value={value}
+			placeholder={placeholder}
+			disabled={disabled}
+			readOnly={readonly}
+			autoComplete={autocomplete === false ? 'off' : undefined}
+			onChange={handleChange}
+		/>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/LanguageSettingInput.js b/client/components/admin/settings/inputs/LanguageSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..f5e9eb73ffa10354b98e681ad6c6b60de27f669e
--- /dev/null
+++ b/client/components/admin/settings/inputs/LanguageSettingInput.js
@@ -0,0 +1,49 @@
+import {
+	Field,
+	Label,
+	SelectInput,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { useLanguages } from '../../../providers/TranslationProvider';
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function LanguageSettingInput({
+	_id,
+	label,
+	value,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const languages = useLanguages();
+
+	const handleChange = (event) => {
+		onChangeValue(event.currentTarget.value);
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<SelectInput
+			data-qa-setting-id={_id}
+			id={_id}
+			value={value}
+			placeholder={placeholder}
+			disabled={disabled}
+			readOnly={readonly}
+			autoComplete={autocomplete === false ? 'off' : undefined}
+			onChange={handleChange}
+		>
+			{languages.map(({ key, name }) =>
+				<SelectInput.Option key={key} value={key} dir='auto'>{name}</SelectInput.Option>
+			)}
+		</SelectInput>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/PasswordSettingInput.js b/client/components/admin/settings/inputs/PasswordSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..77cd9525b3c56ec1e9357e0d94c6608e63365be5
--- /dev/null
+++ b/client/components/admin/settings/inputs/PasswordSettingInput.js
@@ -0,0 +1,42 @@
+import {
+	Field,
+	Label,
+	PasswordInput,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function PasswordSettingInput({
+	_id,
+	label,
+	value,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const handleChange = (event) => {
+		onChangeValue(event.currentTarget.value);
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<PasswordInput
+			data-qa-setting-id={_id}
+			id={_id}
+			value={value}
+			placeholder={placeholder}
+			disabled={disabled}
+			readOnly={readonly}
+			autoComplete={autocomplete === false ? 'off' : undefined}
+			onChange={handleChange}
+		/>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/RelativeUrlSettingInput.js b/client/components/admin/settings/inputs/RelativeUrlSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..a675a4550497789009ebb7c576a16cce791d3528
--- /dev/null
+++ b/client/components/admin/settings/inputs/RelativeUrlSettingInput.js
@@ -0,0 +1,43 @@
+import {
+	Field,
+	Label,
+	UrlInput,
+} from '@rocket.chat/fuselage';
+import { Meteor } from 'meteor/meteor';
+import React from 'react';
+
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function RelativeUrlSettingInput({
+	_id,
+	label,
+	value,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const handleChange = (event) => {
+		onChangeValue(event.currentTarget.value);
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<UrlInput
+			data-qa-setting-id={_id}
+			id={_id}
+			value={Meteor.absoluteUrl(value)}
+			placeholder={placeholder}
+			disabled={disabled}
+			readOnly={readonly}
+			autoComplete={autocomplete === false ? 'off' : undefined}
+			onChange={handleChange}
+		/>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/RoomPickSettingInput.js b/client/components/admin/settings/inputs/RoomPickSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..c59be9b192df6b793a0bb9a25345d3fa157f4cb3
--- /dev/null
+++ b/client/components/admin/settings/inputs/RoomPickSettingInput.js
@@ -0,0 +1,88 @@
+import { Field, Icon, Label } from '@rocket.chat/fuselage';
+import { Blaze } from 'meteor/blaze';
+import { Template } from 'meteor/templating';
+import React, { useRef, useEffect, useLayoutEffect } from 'react';
+
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function RoomPickSettingInput({
+	_id,
+	label,
+	value,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	value = value || [];
+
+	const wrapperRef = useRef();
+	const valueRef = useRef(value);
+
+	const handleRemoveRoomButtonClick = (rid) => () => {
+		onChangeValue(value.filter(({ _id }) => _id !== rid));
+	};
+
+	useLayoutEffect(() => {
+		valueRef.current = value;
+	});
+
+	useEffect(() => {
+		const view = Blaze.renderWithData(Template.inputAutocomplete, {
+			id: _id,
+			name: _id,
+			class: 'search autocomplete rc-input__element',
+			autocomplete: autocomplete === false ? 'off' : undefined,
+			readOnly: readonly,
+			placeholder,
+			disabled,
+			settings: {
+				limit: 10,
+				// inputDelay: 300
+				rules: [
+					{
+						// @TODO maybe change this 'collection' and/or template
+						collection: 'CachedChannelList',
+						subscription: 'channelAndPrivateAutocomplete',
+						field: 'name',
+						template: Template.roomSearch,
+						noMatchTemplate: Template.roomSearchEmpty,
+						matchAll: true,
+						selector: (match) => ({ name: match }),
+						sort: 'name',
+					},
+				],
+			},
+
+		}, wrapperRef.current);
+
+		$('.autocomplete', wrapperRef.current).on('autocompleteselect', (event, doc) => {
+			const { current: value } = valueRef;
+			onChangeValue([...value.filter(({ _id }) => _id !== doc._id), doc]);
+			event.currentTarget.value = '';
+			event.currentTarget.focus();
+		});
+
+		return () => {
+			Blaze.remove(view);
+		};
+	}, [valueRef]);
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<div style={{ position: 'relative' }} ref={wrapperRef} />
+		<ul className='selected-rooms'>
+			{value.map(({ _id, name }) =>
+				<li key={_id} className='remove-room' onClick={handleRemoveRoomButtonClick(_id)}>
+					{name} <Icon name='cross' />
+				</li>
+			)}
+		</ul>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/SelectSettingInput.js b/client/components/admin/settings/inputs/SelectSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..8ad1ac8ca3c0899acaee11db72b18f8a82e3c367
--- /dev/null
+++ b/client/components/admin/settings/inputs/SelectSettingInput.js
@@ -0,0 +1,50 @@
+import {
+	Field,
+	Label,
+	SelectInput,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { useTranslation } from '../../../providers/TranslationProvider';
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function SelectSettingInput({
+	_id,
+	label,
+	value,
+	placeholder,
+	readonly,
+	autocomplete,
+	disabled,
+	values,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const t = useTranslation();
+
+	const handleChange = (event) => {
+		onChangeValue(event.currentTarget.value);
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		<SelectInput
+			data-qa-setting-id={_id}
+			id={_id}
+			value={value}
+			placeholder={placeholder}
+			disabled={disabled}
+			readOnly={readonly}
+			autoComplete={autocomplete === false ? 'off' : undefined}
+			onChange={handleChange}
+		>
+			{values.map(({ key, i18nLabel }) =>
+				<SelectInput.Option key={key} value={key}>{t(i18nLabel)}</SelectInput.Option>
+			)}
+		</SelectInput>
+	</>;
+}
diff --git a/client/components/admin/settings/inputs/StringSettingInput.js b/client/components/admin/settings/inputs/StringSettingInput.js
new file mode 100644
index 0000000000000000000000000000000000000000..17c9b1e451d6ff4873048cd6e13145b7f876b0da
--- /dev/null
+++ b/client/components/admin/settings/inputs/StringSettingInput.js
@@ -0,0 +1,56 @@
+import {
+	Field,
+	Label,
+	TextAreaInput,
+	TextInput,
+} from '@rocket.chat/fuselage';
+import React from 'react';
+
+import { ResetSettingButton } from '../ResetSettingButton';
+
+export function StringSettingInput({
+	_id,
+	label,
+	disabled,
+	multiline,
+	placeholder,
+	readonly,
+	autocomplete,
+	value,
+	hasResetButton,
+	onChangeValue,
+	onResetButtonClick,
+}) {
+	const handleChange = (event) => {
+		onChangeValue(event.currentTarget.value);
+	};
+
+	return <>
+		<Field.Row>
+			<Label htmlFor={_id} text={label} title={_id} />
+			{hasResetButton && <ResetSettingButton data-qa-reset-setting-id={_id} onClick={onResetButtonClick} />}
+		</Field.Row>
+		{multiline
+			? <TextAreaInput
+				data-qa-setting-id={_id}
+				id={_id}
+				rows={4}
+				value={value}
+				placeholder={placeholder}
+				disabled={disabled}
+				readOnly={readonly}
+				autoComplete={autocomplete === false ? 'off' : undefined}
+				onChange={handleChange}
+			/>
+			: <TextInput
+				data-qa-setting-id={_id}
+				id={_id}
+				value={value}
+				placeholder={placeholder}
+				disabled={disabled}
+				readOnly={readonly}
+				autoComplete={autocomplete === false ? 'off' : undefined}
+				onChange={handleChange}
+			/> }
+	</>;
+}
diff --git a/client/components/basic/Button.js b/client/components/basic/Button.js
index 60cd9708a2eca8ea5d693089eb986e467cb9d769..187409e31e962f93599367799bc7746a48de35a1 100644
--- a/client/components/basic/Button.js
+++ b/client/components/basic/Button.js
@@ -6,6 +6,8 @@ export const Button = ({
 	invisible,
 	primary,
 	secondary,
+	cancel,
+	nude,
 	submit,
 	...props
 }) => <button
@@ -15,6 +17,8 @@ export const Button = ({
 		primary && 'rc-button--primary',
 		secondary && 'rc-button--secondary',
 		invisible && 'rc-button--invisible',
+		cancel && 'rc-button--cancel',
+		nude && 'rc-button--nude',
 		className,
 	].filter(Boolean).join(' ')}
 	{...props}
diff --git a/client/components/basic/Button.stories.js b/client/components/basic/Button.stories.js
index 27428a33ba6ac268a46e21e675c3ae4919a20f39..435dc9569ce991c12ea627f48715aabe819bec98 100644
--- a/client/components/basic/Button.stories.js
+++ b/client/components/basic/Button.stories.js
@@ -1,20 +1,33 @@
+import { action } from '@storybook/addon-actions';
+import { boolean, text } from '@storybook/addon-knobs';
 import React from 'react';
 
-import { rocketChatWrapper } from '../../../.storybook/helpers';
 import { Button } from './Button';
 
 export default {
 	title: 'basic/Button',
 	component: Button,
-	decorators: [
-		rocketChatWrapper,
-	],
 };
 
-export const _default = () => <Button>Button</Button>;
+export const _default = () => <Button
+	children={text('children', 'Button')}
+	invisible={boolean('invisible')}
+	primary={boolean('primary')}
+	secondary={boolean('secondary')}
+	cancel={boolean('cancel')}
+	nude={boolean('nude')}
+	submit={boolean('submit')}
+	onClick={action('click')}
+/>;
 
 export const invisible = () => <Button invisible>Button</Button>;
 
 export const primary = () => <Button primary>Button</Button>;
 
 export const secondary = () => <Button secondary>Button</Button>;
+
+export const cancel = () => <Button cancel>Button</Button>;
+
+export const nude = () => <Button nude>Button</Button>;
+
+export const submit = () => <Button submit>Button</Button>;
diff --git a/client/components/basic/ErrorAlert.stories.js b/client/components/basic/ErrorAlert.stories.js
index a5b8731620eede38f23aadc8c94829ed0217330d..1419157742e8a9d9100d9b5b7391b25054a84645 100644
--- a/client/components/basic/ErrorAlert.stories.js
+++ b/client/components/basic/ErrorAlert.stories.js
@@ -1,14 +1,10 @@
 import React from 'react';
 
-import { rocketChatWrapper } from '../../../.storybook/helpers';
 import { ErrorAlert } from './ErrorAlert';
 
 export default {
 	title: 'basic/ErrorAlert',
 	component: ErrorAlert,
-	decorators: [
-		rocketChatWrapper,
-	],
 };
 
 export const _default = () => <ErrorAlert>Content</ErrorAlert>;
diff --git a/client/components/basic/Icon.js b/client/components/basic/Icon.js
index 2fc4eb3322c6b509463cd14a68b56a7e9a491d50..88cc2478681b32313fff4b0db3ba404992cd3b55 100644
--- a/client/components/basic/Icon.js
+++ b/client/components/basic/Icon.js
@@ -1,6 +1,6 @@
 import React from 'react';
 
-export const Icon = ({ icon, block = '', baseUrl = '', className }) => <svg
+const SvgIcon = ({ icon, block = '', baseUrl = '', className }) => <svg
 	className={[
 		'rc-icon',
 		block,
@@ -11,3 +11,12 @@ export const Icon = ({ icon, block = '', baseUrl = '', className }) => <svg
 >
 	<use xlinkHref={`${ baseUrl }#icon-${ icon }`} />
 </svg>;
+
+const FontIcon = ({ icon, className }) => <i
+	className={[icon, className].filter(Boolean).join(' ')}
+/>;
+
+export const Icon = ({ icon, ...props }) =>
+	(/^icon-/.test(icon)
+		? <FontIcon icon={icon} {...props} />
+		: <SvgIcon icon={icon} {...props} />);
diff --git a/client/components/basic/Input.stories.js b/client/components/basic/Input.stories.js
index 43d1885c743c2b4e859b800a13f5d280fb2cabc4..95891b0c6fd7eb20d3dea0fdc030f33134232c50 100644
--- a/client/components/basic/Input.stories.js
+++ b/client/components/basic/Input.stories.js
@@ -1,14 +1,10 @@
 import React from 'react';
 
-import { rocketChatWrapper } from '../../../.storybook/helpers';
 import { Input } from './Input';
 
 export default {
 	title: 'basic/Input',
 	component: Input,
-	decorators: [
-		rocketChatWrapper,
-	],
 };
 
 export const _default = () => <Input />;
diff --git a/client/components/basic/Link.stories.js b/client/components/basic/Link.stories.js
index 6423435215e3c083dfa53e8ce9eb0c3ca3382000..90694dae63694b8e5803364c6334c2fad5041443 100644
--- a/client/components/basic/Link.stories.js
+++ b/client/components/basic/Link.stories.js
@@ -1,14 +1,10 @@
 import React from 'react';
 
-import { rocketChatWrapper } from '../../../.storybook/helpers';
 import { Link } from './Link';
 
 export default {
 	title: 'basic/Link',
 	component: Link,
-	decorators: [
-		rocketChatWrapper,
-	],
 };
 
 export const _default = () => <Link href='#'>Link</Link>;
diff --git a/client/components/basic/MarkdownText.js b/client/components/basic/MarkdownText.js
new file mode 100644
index 0000000000000000000000000000000000000000..698d5bde6b2b6863b38ed38434ffe47bca2d0bf2
--- /dev/null
+++ b/client/components/basic/MarkdownText.js
@@ -0,0 +1,5 @@
+import React from 'react';
+
+import { Markdown } from '../../../app/markdown/client';
+
+export const MarkdownText = ({ children }) => <span dangerouslySetInnerHTML={{ __html: Markdown.parseNotEscaped(children) }} />;
diff --git a/client/components/basic/RawText.js b/client/components/basic/RawText.js
new file mode 100644
index 0000000000000000000000000000000000000000..70cd93393365ed8921b6fd9b9c76523b6e579fa1
--- /dev/null
+++ b/client/components/basic/RawText.js
@@ -0,0 +1,3 @@
+import React from 'react';
+
+export const RawText = ({ children }) => <span dangerouslySetInnerHTML={{ __html: children }} />;
diff --git a/client/components/connectionStatus/ConnectionStatusAlert.js b/client/components/connectionStatus/ConnectionStatusAlert.js
index 24bb99718b13537ac331cced0fd4477714d27f78..37a2ee58833ce9a1611c89fadacaa7149e29c38e 100644
--- a/client/components/connectionStatus/ConnectionStatusAlert.js
+++ b/client/components/connectionStatus/ConnectionStatusAlert.js
@@ -1,8 +1,8 @@
 import { Icon } from '@rocket.chat/fuselage';
 import React, { useEffect, useRef, useState } from 'react';
 
-import { useConnectionStatus, useReconnect } from '../contexts/ConnectionStatusContext';
-import { useTranslation } from '../contexts/TranslationContext';
+import { useConnectionStatus, useReconnect } from '../providers/ConnectionStatusProvider';
+import { useTranslation } from '../providers/TranslationProvider';
 import './ConnectionStatusAlert.css';
 
 export function ConnectionStatusAlert() {
@@ -48,7 +48,7 @@ export function ConnectionStatusAlert() {
 
 	return <div className='ConnectionStatusAlert' role='alert'>
 		<strong>
-			<Icon iconName='warning' /> {t('meteor_status', { context: status })}
+			<Icon name='warning' /> {t('meteor_status', { context: status })}
 		</strong>
 
 		{status === 'waiting' && <>
diff --git a/client/components/connectionStatus/ConnectionStatusAlert.stories.js b/client/components/connectionStatus/ConnectionStatusAlert.stories.js
index 896d6376c8e76ef8ebec5f95e09f3aea80d4a6d5..91c20b065acba899e1eed83c0908ace9f0a8d064 100644
--- a/client/components/connectionStatus/ConnectionStatusAlert.stories.js
+++ b/client/components/connectionStatus/ConnectionStatusAlert.stories.js
@@ -1,16 +1,12 @@
 import { action } from '@storybook/addon-actions';
 import React from 'react';
 
-import { rocketChatWrapper } from '../../../.storybook/helpers';
 import { ConnectionStatusAlert } from './ConnectionStatusAlert';
 import { ConnectionStatusProvider } from '../providers/ConnectionStatusProvider.mock';
 
 export default {
 	title: 'connectionStatus/ConnectionStatusAlert',
 	component: ConnectionStatusAlert,
-	decorators: [
-		rocketChatWrapper,
-	],
 };
 
 export const connected = () => <ConnectionStatusProvider connected status='connected' reconnect={action('reconnect')}>
diff --git a/client/components/contexts/ConnectionStatusContext.js b/client/components/contexts/ConnectionStatusContext.js
deleted file mode 100644
index a8f33e99a4db978703cab901f14f5df6e48d4464..0000000000000000000000000000000000000000
--- a/client/components/contexts/ConnectionStatusContext.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { createContext, useContext } from 'react';
-
-export const ConnectionStatusContext = createContext({
-	status: {
-		connected: true,
-		status: 'connected',
-		retryCount: 0,
-	},
-	reconnect: () => {},
-});
-
-export const useConnectionStatus = () => useContext(ConnectionStatusContext).status;
-
-export const useReconnect = () => useContext(ConnectionStatusContext).reconnect;
diff --git a/client/components/contexts/RouterContext.js b/client/components/contexts/RouterContext.js
deleted file mode 100644
index bc9d41d31c532895fa7e224b57a04469f111fe8e..0000000000000000000000000000000000000000
--- a/client/components/contexts/RouterContext.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import { createContext, useContext, useEffect, useMemo, useState } from 'react';
-
-export const RouterContext = createContext({
-	navigateTo: () => {},
-	replaceWith: () => {},
-	getRouteParameter: () => {},
-	watchRouteParameter: () => {},
-	getQueryStringParameter: () => {},
-	watchQueryStringParameter: () => {},
-});
-
-export const useRoute = (pathDefinition) => {
-	const { navigateTo, replaceWith } = useContext(RouterContext);
-
-	return useMemo(() => {
-		const navigate = (...args) => navigateTo(pathDefinition, ...args);
-		navigate.replacingState = (...args) => replaceWith(pathDefinition, ...args);
-		return navigate;
-	}, [navigateTo, replaceWith]);
-};
-
-export const useRouteParameter = (name) => {
-	const { getRouteParameter, watchRouteParameter } = useContext(RouterContext);
-	const [parameter, setParameter] = useState(getRouteParameter(name));
-
-	useEffect(() => watchRouteParameter(name, setParameter), [watchRouteParameter, name]);
-
-	return parameter;
-};
-
-export const useQueryStringParameter = (name) => {
-	const { getQueryStringParameter, watchQueryStringParameter } = useContext(RouterContext);
-	const [parameter, setParameter] = useState(getQueryStringParameter(name));
-
-	useEffect(() => watchQueryStringParameter(name, setParameter), [watchQueryStringParameter, name]);
-
-	return parameter;
-};
diff --git a/client/components/contexts/TranslationContext.js b/client/components/contexts/TranslationContext.js
deleted file mode 100644
index 67986658f6a659301eac394863939c3f3b550f2e..0000000000000000000000000000000000000000
--- a/client/components/contexts/TranslationContext.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { createContext, useContext } from 'react';
-
-const translate = function(key) {
-	return key;
-};
-
-translate.has = () => true;
-
-export const TranslationContext = createContext(translate);
-
-export const useTranslation = () => useContext(TranslationContext);
diff --git a/client/components/header/BurgerMenuButton.js b/client/components/header/BurgerMenuButton.js
index 42ade4c25f50e09bcddbab0471bfa217e0e342b7..0cff17f9c64eb23143ee42396a08ef7202097142 100644
--- a/client/components/header/BurgerMenuButton.js
+++ b/client/components/header/BurgerMenuButton.js
@@ -1,83 +1,27 @@
-import React, { useMemo } from 'react';
-
-import { ChatSubscription } from '../../../app/models/client/models/ChatSubscription';
-import { menu } from '../../../app/ui-utils/client/lib/menu';
-import { useEmbeddedLayout } from '../../hooks/useEmbeddedLayout';
-import { useReactiveValue } from '../../hooks/useReactiveValue';
-import { useSession } from '../../hooks/useSession';
-import { useUserPreference } from '../../hooks/useUserPreference';
+import React from 'react';
 
 import './BurgerMenuButton.css';
 
-const useSidebarState = () => {
-	const isOpen = useSession('isMenuOpen');
-	const toggle = () => menu.toggle();
-	return [isOpen, toggle];
-};
-
-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]);
-};
-
-export function BurgerMenuButton() {
-	const [isSidebarOpen, toggleSidebarOpen] = useSidebarState();
-	const isLayoutEmbedded = useEmbeddedLayout();
-	const unreadMessagesBadge = useUnreadMessagesBadge();
-
-	const handleClick = () => {
-		toggleSidebarOpen();
-	};
-
-	return <button
-		aria-label={isSidebarOpen ? 'Close menu' : 'Open menu'}
-		className={[
-			'rc-old',
-			'burger',
-			!!isSidebarOpen && 'menu-opened',
-		].filter(Boolean).join(' ')}
-		type='button'
-		onClick={handleClick}
-	>
-		<i className='burger__line' aria-hidden='true' />
-		<i className='burger__line' aria-hidden='true' />
-		<i className='burger__line' aria-hidden='true' />
-		{!isLayoutEmbedded && unreadMessagesBadge
-			&& <div className='unread-burger-alert color-error-contrast background-error-color'>
-				{unreadMessagesBadge}
-			</div>}
-	</button>;
-}
+export const BurgerMenuButton = ({
+	isSidebarOpen,
+	isLayoutEmbedded,
+	unreadMessagesBadge,
+	onClick,
+}) => <button
+	aria-label={isSidebarOpen ? 'Close menu' : 'Open menu'}
+	className={[
+		'rc-old',
+		'burger',
+		!!isSidebarOpen && 'menu-opened',
+	].filter(Boolean).join(' ')}
+	type='button'
+	onClick={onClick}
+>
+	<i className='burger__line' aria-hidden='true' />
+	<i className='burger__line' aria-hidden='true' />
+	<i className='burger__line' aria-hidden='true' />
+	{!isLayoutEmbedded && unreadMessagesBadge
+		&& <div className='unread-burger-alert color-error-contrast background-error-color'>
+			{unreadMessagesBadge}
+		</div>}
+</button>;
diff --git a/client/components/header/BurgerMenuButton.stories.js b/client/components/header/BurgerMenuButton.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..e81574d9d4c68306fcc97f1ae2422fbafa4cbdd2
--- /dev/null
+++ b/client/components/header/BurgerMenuButton.stories.js
@@ -0,0 +1,25 @@
+import { action } from '@storybook/addon-actions';
+import { boolean, text } from '@storybook/addon-knobs/react';
+import React from 'react';
+
+import { BurgerMenuButton } from './BurgerMenuButton';
+
+export default {
+	title: 'header/BurgerMenuButton',
+	component: BurgerMenuButton,
+	decorators: [(fn) => <div style={{ margin: '1rem' }}>{fn()}</div>],
+	parameters: {
+		viewport: { defaultViewport: 'mobile1' },
+	},
+};
+
+export const _default = () => <BurgerMenuButton
+	isSidebarOpen={boolean('isSidebarOpen')}
+	isLayoutEmbedded={boolean('isLayoutEmbedded')}
+	unreadMessagesBadge={text('unreadMessagesBadge')}
+	onClick={action('click')}
+/>;
+
+export const whenSidebarOpen = () => <BurgerMenuButton isSidebarOpen />;
+
+export const unreadMessagesBadge = () => <BurgerMenuButton unreadMessagesBadge='99' />;
diff --git a/client/components/header/Header.js b/client/components/header/Header.js
index c3a3f4ff829dc7e708cbb222d1de6c32d488131d..36cf9af7e88066f6a67657c798a8a387dbf039db 100644
--- a/client/components/header/Header.js
+++ b/client/components/header/Header.js
@@ -1,7 +1,10 @@
+import { Text } from '@rocket.chat/fuselage';
 import React from 'react';
 
-import { useTranslation } from '../contexts/TranslationContext';
+import { useEmbeddedLayout } from '../../hooks/useEmbeddedLayout';
+import { useTranslation } from '../providers/TranslationProvider';
 import { BurgerMenuButton } from './BurgerMenuButton';
+import { useSidebarState, useUnreadMessagesBadge } from './hooks';
 
 export function Header({
 	children,
@@ -9,15 +12,31 @@ export function Header({
 	rawSectionName,
 	sectionName,
 }) {
+	const [isSidebarOpen, toggleSidebarOpen] = useSidebarState();
+	const isLayoutEmbedded = useEmbeddedLayout();
+	const unreadMessagesBadge = useUnreadMessagesBadge();
 	const t = useTranslation();
 
+	const handleClick = () => {
+		toggleSidebarOpen();
+	};
+
 	return <header className='rc-header'>
 		<div className='rc-header__wrap'>
 			<div className='rc-header__block rc-header--burger'>
-				<BurgerMenuButton />
+				<BurgerMenuButton
+					isSidebarOpen={isSidebarOpen}
+					isLayoutEmbedded={isLayoutEmbedded}
+					unreadMessagesBadge={unreadMessagesBadge}
+					onClick={handleClick}
+				/>
 			</div>
 
-			<span className='rc-header__block'>{rawSectionName || t(sectionName)}</span>
+			<span className='rc-header__block'>
+				<Text is='h1' headline defaultColor>
+					{rawSectionName || t(sectionName)}
+				</Text>
+			</span>
 
 			{children}
 
@@ -25,3 +44,7 @@ export function Header({
 		</div>
 	</header>;
 }
+
+Header.ActionBlock = (props) => <div className='rc-header__block rc-header__block-action' {...props} />;
+
+Header.ButtonSection = (props) => <div className='rc-header__section-button' {...props} />;
diff --git a/client/components/header/Header.stories.js b/client/components/header/Header.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..68142c7c47bb094127e5210629edb7a6b2564cbb
--- /dev/null
+++ b/client/components/header/Header.stories.js
@@ -0,0 +1,32 @@
+import { boolean, text } from '@storybook/addon-knobs/react';
+import React from 'react';
+
+import { Button } from '../basic/Button';
+import { Header } from './Header';
+
+export default {
+	title: 'header/Header',
+	component: Header,
+};
+
+export const _default = () =>
+	<Header
+		hideHelp={boolean('hideHelp')}
+		rawSectionName={text('rawSectionName')}
+		sectionName={text('sectionName')}
+	/>;
+
+export const withRawSectionName = () =>
+	<Header rawSectionName='Welcome to Rocket.Chat' />;
+
+export const withSectionName = () =>
+	<Header sectionName='Accounts_Enrollment_Email_Subject_Default' />;
+
+export const withButton = () =>
+	<Header rawSectionName='Welcome to Rocket.Chat' hideHelp>
+		<Header.ActionBlock>
+			<Button primary type='button'>
+				Hooray!
+			</Button>
+		</Header.ActionBlock>
+	</Header>;
diff --git a/client/components/header/hooks.js b/client/components/header/hooks.js
new file mode 100644
index 0000000000000000000000000000000000000000..7594890786295149c304f6dfc3a40dba151010b3
--- /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/components/pageNotFound/PageNotFound.js b/client/components/pageNotFound/PageNotFound.js
index 0b6e77a0078ff76f6e44ce48dc55a209dbc3f6a1..15f4d11c0c69d69da2c2c904923cd17f3fd87332 100644
--- a/client/components/pageNotFound/PageNotFound.js
+++ b/client/components/pageNotFound/PageNotFound.js
@@ -1,10 +1,11 @@
 import { Button, ButtonGroup } from '@rocket.chat/fuselage';
 import React from 'react';
 
-import { useTranslation } from '../contexts/TranslationContext';
+import { useTranslation } from '../providers/TranslationProvider';
 import { useWipeInitialPageLoading } from '../../hooks/useWipeInitialPageLoading';
 import { ConnectionStatusAlert } from '../connectionStatus/ConnectionStatusAlert';
-import { useRoute } from '../contexts/RouterContext';
+import { useRoute } from '../providers/RouterProvider';
+import './PageNotFound.css';
 
 export function PageNotFound() {
 	useWipeInitialPageLoading();
diff --git a/client/components/pageNotFound/PageNotFound.stories.js b/client/components/pageNotFound/PageNotFound.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..44c6e33737d583d2e8890016829ab4ec92c2cc10
--- /dev/null
+++ b/client/components/pageNotFound/PageNotFound.stories.js
@@ -0,0 +1,10 @@
+import React from 'react';
+
+import { PageNotFound } from './PageNotFound';
+
+export default {
+	title: 'pageNotFound/PageNotFound',
+	component: PageNotFound,
+};
+
+export const _default = () => <PageNotFound />;
diff --git a/client/components/providers/ConnectionStatusProvider.js b/client/components/providers/ConnectionStatusProvider.js
index 954136ef3d5fdd8c920b518c76f20eac229e256f..aa284d5807073cb58f94203d26c3ebb82932de0b 100644
--- a/client/components/providers/ConnectionStatusProvider.js
+++ b/client/components/providers/ConnectionStatusProvider.js
@@ -1,9 +1,17 @@
 import { Meteor } from 'meteor/meteor';
-import React, { useMemo } from 'react';
+import React, { createContext, useContext, useMemo } from 'react';
 
-import { ConnectionStatusContext } from '../contexts/ConnectionStatusContext';
 import { useReactiveValue } from '../../hooks/useReactiveValue';
 
+export const ConnectionStatusContext = createContext({
+	status: {
+		connected: true,
+		status: 'connected',
+		retryCount: 0,
+	},
+	reconnect: () => {},
+});
+
 export function ConnectionStatusProvider({ children }) {
 	const status = useReactiveValue(() => ({ ...Meteor.status() }));
 
@@ -16,3 +24,7 @@ export function ConnectionStatusProvider({ children }) {
 		{children}
 	</ConnectionStatusContext.Provider>;
 }
+
+export const useConnectionStatus = () => useContext(ConnectionStatusContext).status;
+
+export const useReconnect = () => useContext(ConnectionStatusContext).reconnect;
diff --git a/client/components/providers/ConnectionStatusProvider.mock.js b/client/components/providers/ConnectionStatusProvider.mock.js
index cab3c974e1448e98d567fe7e13cf6b35d1624cde..4997341ebc6ee1f69153be621db9735a80cd0769 100644
--- a/client/components/providers/ConnectionStatusProvider.mock.js
+++ b/client/components/providers/ConnectionStatusProvider.mock.js
@@ -1,6 +1,6 @@
 import React from 'react';
 
-import { ConnectionStatusContext } from '../contexts/ConnectionStatusContext';
+import { ConnectionStatusContext } from './ConnectionStatusProvider';
 
 export function ConnectionStatusProvider({
 	children,
diff --git a/client/components/providers/RouterProvider.js b/client/components/providers/RouterProvider.js
index 6074ee072a351d2f8267a91bc6aeeba6f65baf0d..9ff3e65a53988c0df1d01795dc08e25a4bf43e9d 100644
--- a/client/components/providers/RouterProvider.js
+++ b/client/components/providers/RouterProvider.js
@@ -1,8 +1,15 @@
 import { FlowRouter } from 'meteor/kadira:flow-router';
 import { Tracker } from 'meteor/tracker';
-import React from 'react';
+import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
 
-import { RouterContext } from '../contexts/RouterContext';
+export const RouterContext = createContext({
+	navigateTo: () => {},
+	replaceWith: () => {},
+	getRouteParameter: () => {},
+	watchRouteParameter: () => {},
+	getQueryStringParameter: () => {},
+	watchQueryStringParameter: () => {},
+});
 
 const navigateTo = (pathDefinition, parameters, queryStringParameters) => {
 	FlowRouter.go(pathDefinition, parameters, queryStringParameters);
@@ -48,3 +55,31 @@ export function RouterProvider({ children }) {
 		{children}
 	</RouterContext.Provider>;
 }
+
+export const useRoute = (pathDefinition) => {
+	const { navigateTo, replaceWith } = useContext(RouterContext);
+
+	return useMemo(() => {
+		const navigate = (...args) => navigateTo(pathDefinition, ...args);
+		navigate.replacingState = (...args) => replaceWith(pathDefinition, ...args);
+		return navigate;
+	}, [navigateTo, replaceWith]);
+};
+
+export const useRouteParameter = (name) => {
+	const { getRouteParameter, watchRouteParameter } = useContext(RouterContext);
+	const [parameter, setParameter] = useState(getRouteParameter(name));
+
+	useEffect(() => watchRouteParameter(name, setParameter), [watchRouteParameter, name]);
+
+	return parameter;
+};
+
+export const useQueryStringParameter = (name) => {
+	const { getQueryStringParameter, watchQueryStringParameter } = useContext(RouterContext);
+	const [parameter, setParameter] = useState(getQueryStringParameter(name));
+
+	useEffect(() => watchQueryStringParameter(name, setParameter), [watchQueryStringParameter, name]);
+
+	return parameter;
+};
diff --git a/client/components/providers/TranslationProvider.js b/client/components/providers/TranslationProvider.js
index 6baeb569e959fc12c00bd82e17fc4f8ee55ede14..2b2e169eddc005b03f9e8ca4cf4ef0ca532384a1 100644
--- a/client/components/providers/TranslationProvider.js
+++ b/client/components/providers/TranslationProvider.js
@@ -1,9 +1,16 @@
-import React, { useMemo } from 'react';
+import React, { createContext, useContext, useMemo } from 'react';
 import { TAPi18n, TAPi18next } from 'meteor/rocketchat:tap-i18n';
 
-import { TranslationContext } from '../contexts/TranslationContext';
 import { useReactiveValue } from '../../hooks/useReactiveValue';
 
+const translate = function(key) {
+	return key;
+};
+
+translate.has = () => true;
+
+export const TranslationContext = createContext(translate);
+
 const createContextValue = (language) => {
 	const translate = (key, ...replaces) => {
 		if (typeof replaces[0] === 'object') {
@@ -30,7 +37,11 @@ const createContextValue = (language) => {
 	const has = (key, { lng = language, ...options } = {}) => TAPi18next.exists(key, { ...options, lng });
 
 	translate.has = has;
-	return translate;
+
+	return {
+		language,
+		translate,
+	};
 };
 
 export function TranslationProvider({ children }) {
@@ -42,3 +53,23 @@ export function TranslationProvider({ children }) {
 		{children}
 	</TranslationContext.Provider>;
 }
+
+export const useTranslation = () => useContext(TranslationContext).translate;
+
+export const useLanguage = () => useContext(TranslationContext).language;
+
+export const useLanguages = () => useReactiveValue(() => {
+	const languages = TAPi18n.getLanguages();
+
+	const result = Object.entries(languages)
+		.map(([key, language]) => ({ ...language, key: key.toLowerCase() }))
+		.sort((a, b) => a.key - b.key);
+
+	result.unshift({
+		name: 'Default',
+		en: 'Default',
+		key: '',
+	});
+
+	return result;
+}, []);
diff --git a/client/components/providers/TranslationProvider.mock.js b/client/components/providers/TranslationProvider.mock.js
index 0337567be6bc053c7272527325d5044948672328..81e537da958c8908e76d18fc37681e5241f7cd6e 100644
--- a/client/components/providers/TranslationProvider.mock.js
+++ b/client/components/providers/TranslationProvider.mock.js
@@ -1,7 +1,7 @@
 import React, { useEffect, useState } from 'react';
 import i18next from 'i18next';
 
-import { TranslationContext } from '../contexts/TranslationContext';
+import { TranslationContext } from './TranslationProvider';
 
 export function TranslationProvider({ children }) {
 	const [contextValue, setContextValue] = useState();
diff --git a/client/components/setupWizard/Epilogue.js b/client/components/setupWizard/Epilogue.js
index 9206532ca2269c3d10dbf14b0dc898770968366a..2ab1e76efc5e2b6130e69f03cfefdadb51779d41 100644
--- a/client/components/setupWizard/Epilogue.js
+++ b/client/components/setupWizard/Epilogue.js
@@ -1,22 +1,25 @@
-import React from 'react';
 import { Button } from '@rocket.chat/fuselage';
+import React from 'react';
 
-import { useTranslation } from '../contexts/TranslationContext';
+import { useSetSetting } from '../../hooks/useSetSetting';
 import { useSetting } from '../../hooks/useSetting';
-import { setSetting } from './functions';
+import { useTranslation } from '../providers/TranslationProvider';
 import './Epilogue.css';
 
-export function Epilogue() {
+export function Epilogue({
+	logoSrc = 'images/logo/logo.svg',
+}) {
 	const t = useTranslation();
 	const siteUrl = useSetting('Site_Url');
+	const setShowSetupWizard = useSetSetting('Show_Setup_Wizard');
 
 	const handleClick = () => {
-		setSetting('Show_Setup_Wizard', 'completed');
+		setShowSetupWizard('completed');
 	};
 
 	return <section className='SetupWizard__Epilogue'>
 		<header className='SetupWizard__Epilogue-header'>
-			<img className='SetupWizard__Epilogue-headerLogo' src='images/logo/logo.svg' />
+			<img className='SetupWizard__Epilogue-headerLogo' src={logoSrc} />
 		</header>
 
 		<main className='SetupWizard__Epilogue-content'>
@@ -24,7 +27,7 @@ export function Epilogue() {
 			<h1 className='SetupWizard__Epilogue-title'>{t('Your_workspace_is_ready')}</h1>
 			<span className='SetupWizard__Epilogue-linkLabel'>{t('Your_server_link')}</span>
 			<span className='SetupWizard__Epilogue-link'>{siteUrl}</span>
-			<Button type='button' primary onClick={handleClick} className='SetupWizard__Epilogue__goToWorkspace'>
+			<Button primary onClick={handleClick} className='SetupWizard__Epilogue__goToWorkspace'>
 				{t('Go_to_your_workspace')}
 			</Button>
 		</main>
diff --git a/client/components/setupWizard/Epilogue.stories.js b/client/components/setupWizard/Epilogue.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..0674903dae94e5364ec423bb64988f48cc6d2e12
--- /dev/null
+++ b/client/components/setupWizard/Epilogue.stories.js
@@ -0,0 +1,11 @@
+import React from 'react';
+
+import { Epilogue } from './Epilogue';
+
+export default {
+	title: 'setupWizard/Epilogue',
+	component: Epilogue,
+};
+
+export const _default = () =>
+	<Epilogue logoSrc='https://open.rocket.chat/images/logo/logo.svg' />;
diff --git a/client/components/setupWizard/Pager.js b/client/components/setupWizard/Pager.js
index 018e3a18ecd81acaaabbb46ef8e841c7d6158e07..5fe1373d02881f3ea2616a89fc0aec85aa3b74be 100644
--- a/client/components/setupWizard/Pager.js
+++ b/client/components/setupWizard/Pager.js
@@ -1,7 +1,7 @@
 import { Button, ButtonGroup } from '@rocket.chat/fuselage';
 import React from 'react';
 
-import { useTranslation } from '../contexts/TranslationContext';
+import { useTranslation } from '../providers/TranslationProvider';
 
 export function Pager({ disabled, onBackClick, isContinueEnabled = true }) {
 	const t = useTranslation();
diff --git a/client/components/setupWizard/Pager.stories.js b/client/components/setupWizard/Pager.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..5bdfdb6cf0f0c2c33f9c9e7a6afa7f8252ba4152
--- /dev/null
+++ b/client/components/setupWizard/Pager.stories.js
@@ -0,0 +1,25 @@
+import { action } from '@storybook/addon-actions';
+import { boolean } from '@storybook/addon-knobs';
+import React from 'react';
+
+import { Pager } from './Pager';
+
+export default {
+	title: 'setupWizard/Pager',
+	component: Pager,
+};
+
+export const _default = () =>
+	<Pager
+		disabled={boolean('disabled')}
+		isContinueEnabled={boolean('isContinueEnabled')}
+	/>;
+
+export const withBackButton = () =>
+	<Pager onBackClick={action('backClick')} />;
+
+export const disabled = () =>
+	<Pager disabled onBackClick={action('backClick')} />;
+
+export const withContinueDisabled = () =>
+	<Pager isContinueEnabled={false} onBackClick={action('backClick')} />;
diff --git a/client/components/setupWizard/SetupWizardRoute.js b/client/components/setupWizard/SetupWizardRoute.js
new file mode 100644
index 0000000000000000000000000000000000000000..d7ec333383e98dd2f69e450b739e6200188ac216
--- /dev/null
+++ b/client/components/setupWizard/SetupWizardRoute.js
@@ -0,0 +1,7 @@
+import React from 'react';
+
+import { SetupWizard } from './SetupWizard';
+
+export function SetupWizardRoute() {
+	return <SetupWizard />;
+}
diff --git a/client/components/setupWizard/SideBar.js b/client/components/setupWizard/SideBar.js
index efcb2dbc768c576c8337ec5465a200ea07f8e5b3..4429e9b365afec97bdbb5b3e4fb3e1095cd97410 100644
--- a/client/components/setupWizard/SideBar.js
+++ b/client/components/setupWizard/SideBar.js
@@ -1,17 +1,18 @@
 import React from 'react';
 
-import { useTranslation } from '../contexts/TranslationContext';
-import { useSetupWizardStepsState } from './StepsState';
+import { useTranslation } from '../providers/TranslationProvider';
 import './SideBar.css';
 
-export function SideBar({ steps = [] }) {
-	const { currentStep } = useSetupWizardStepsState();
-
+export function SideBar({
+	logoSrc = 'images/logo/logo.svg',
+	currentStep = 1,
+	steps = [],
+}) {
 	const t = useTranslation();
 
 	return <aside className='SetupWizard__SideBar'>
 		<header className='SetupWizard__SideBar-header'>
-			<img className='SetupWizard__SideBar-headerLogo' src='images/logo/logo.svg' />
+			<img className='SetupWizard__SideBar-headerLogo' src={logoSrc} />
 			<span className='SetupWizard__SideBar-headerTag'>{t('Setup_Wizard')}</span>
 		</header>
 
diff --git a/client/components/setupWizard/SideBar.stories.js b/client/components/setupWizard/SideBar.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..ec2cf54d4ccd846278ff5f338b3537cc05592bab
--- /dev/null
+++ b/client/components/setupWizard/SideBar.stories.js
@@ -0,0 +1,57 @@
+import { select } from '@storybook/addon-knobs';
+import React from 'react';
+
+import { SideBar } from './SideBar';
+
+export default {
+	title: 'setupWizard/SideBar',
+	component: SideBar,
+};
+
+export const _default = () =>
+	<SideBar
+		logoSrc='https://open.rocket.chat/images/logo/logo.svg'
+		steps={[
+			{
+				step: 1,
+				title: 'Define the problem',
+			},
+			{
+				step: 2,
+				title: 'Generate alternative solutions',
+			},
+			{
+				step: 3,
+				title: 'Select an alternative',
+			},
+			{
+				step: 4,
+				title: 'Implement the solution',
+			},
+		]}
+		currentStep={select('currentStep', [1, 2, 3, 4])}
+	/>;
+
+export const atSomeStep = () =>
+	<SideBar
+		logoSrc='https://open.rocket.chat/images/logo/logo.svg'
+		steps={[
+			{
+				step: 1,
+				title: 'Define the problem',
+			},
+			{
+				step: 2,
+				title: 'Generate alternative solutions',
+			},
+			{
+				step: 3,
+				title: 'Select an alternative',
+			},
+			{
+				step: 4,
+				title: 'Implement the solution',
+			},
+		]}
+		currentStep={2}
+	/>;
diff --git a/client/components/setupWizard/StateChecker.js b/client/components/setupWizard/StateChecker.js
index ccc27966a146308a57fedf7986b70ddbb8899520..6ed11fd31a47a1b632e585317953f5d9f1840e03 100644
--- a/client/components/setupWizard/StateChecker.js
+++ b/client/components/setupWizard/StateChecker.js
@@ -5,7 +5,7 @@ import { Users } from '../../../app/models';
 import { useSetting } from '../../hooks/useSetting';
 import { useUserId } from '../../hooks/useUserId';
 import { useReactiveValue } from '../../hooks/useReactiveValue';
-import { useRoute } from '../contexts/RouterContext';
+import { useRoute } from '../providers/RouterProvider';
 
 export function StateChecker({ children }) {
 	const setupWizardState = useSetting('Show_Setup_Wizard');
diff --git a/client/components/setupWizard/StepHeader.js b/client/components/setupWizard/StepHeader.js
index 2d3560479749343a6b071e8f4cc873899ea990df..6a801872d27544a24562c2bfa40d313a3163f658 100644
--- a/client/components/setupWizard/StepHeader.js
+++ b/client/components/setupWizard/StepHeader.js
@@ -1,7 +1,7 @@
 import { Headline } from '@rocket.chat/fuselage';
 import React from 'react';
 
-import { useTranslation } from '../contexts/TranslationContext';
+import { useTranslation } from '../providers/TranslationProvider';
 import './StepHeader.css';
 
 export function StepHeader({ number, title }) {
diff --git a/client/components/setupWizard/StepHeader.stories.js b/client/components/setupWizard/StepHeader.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..ece0dba6ee9046260e7aa15afeda58bc613cef95
--- /dev/null
+++ b/client/components/setupWizard/StepHeader.stories.js
@@ -0,0 +1,15 @@
+import { number, text } from '@storybook/addon-knobs';
+import React from 'react';
+
+import { StepHeader } from './StepHeader';
+
+export default {
+	title: 'setupWizard/StepHeader',
+	component: StepHeader,
+};
+
+export const _default = () =>
+	<StepHeader
+		number={number('number', 1)}
+		title={text('title', 'Title')}
+	/>;
diff --git a/client/components/setupWizard/Steps.js b/client/components/setupWizard/Steps.js
index e8dff18514a21f48c46e6abf5a9b13ccf0c97dbc..d3378f4082fe21390cd6af8a3e2af627364498e8 100644
--- a/client/components/setupWizard/Steps.js
+++ b/client/components/setupWizard/Steps.js
@@ -1,9 +1,9 @@
 import React from 'react';
 
+import { useTranslation } from '../providers/TranslationProvider';
 import { AdminUserInformationStep } from './steps/AdminUserInformationStep';
 import { SettingsBasedStep } from './steps/SettingsBasedStep';
 import { RegisterServerStep } from './steps/RegisterServerStep';
-import { useTranslation } from '../contexts/TranslationContext';
 import { Epilogue } from './Epilogue';
 import { SideBar } from './SideBar';
 import { useSetupWizardStepsState, finalStep } from './StepsState';
@@ -36,13 +36,14 @@ export function Steps() {
 					title: t('Register_Server'),
 				},
 			]}
+			currentStep={currentStep}
 		/>
 		<section className='SetupWizard__Steps'>
 			<div className='SetupWizard__Steps-wrapper'>
-				<AdminUserInformationStep step={1} title={t('Admin_Info')} />
-				<SettingsBasedStep step={2} title={t('Organization_Info')} />
-				<SettingsBasedStep step={3} title={t('Server_Info')} />
-				<RegisterServerStep step={4} title={t('Register_Server')} />
+				<AdminUserInformationStep step={1} title={t('Admin_Info')} active={currentStep === 1} />
+				<SettingsBasedStep step={2} title={t('Organization_Info')} active={currentStep === 2} />
+				<SettingsBasedStep step={3} title={t('Server_Info')} active={currentStep === 3} />
+				<RegisterServerStep step={4} title={t('Register_Server')} active={currentStep === 4} />
 			</div>
 		</section>
 	</>;
diff --git a/client/components/setupWizard/StepsState.js b/client/components/setupWizard/StepsState.js
index 40c120fe5ed062efca1f7fc4fb26ccc52b718a20..00faf62966e25d540e51e029246da8aaf0fc2889 100644
--- a/client/components/setupWizard/StepsState.js
+++ b/client/components/setupWizard/StepsState.js
@@ -1,9 +1,9 @@
 import React, { createContext, useContext, useEffect, useMemo, useState } from 'react';
 
 import { useUserId } from '../../hooks/useUserId';
-import { useRouteParameter, useRoute } from '../contexts/RouterContext';
+import { useRouteParameter, useRoute } from '../providers/RouterProvider';
 
-const Context = createContext();
+const Context = createContext({});
 
 export const useSetupWizardStepsState = () => useContext(Context);
 
diff --git a/client/components/setupWizard/functions.js b/client/components/setupWizard/functions.js
deleted file mode 100644
index d96e0a33e90bce890149c1b7bae22fd6b4b21981..0000000000000000000000000000000000000000
--- a/client/components/setupWizard/functions.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Meteor } from 'meteor/meteor';
-
-import { settings } from '../../../app/settings/lib/settings';
-
-const withPromisifiedReturn = (f) => (...args) => new Promise((resolve, reject) => {
-	f(...args, (error, ...returnedValues) => {
-		if (error) {
-			reject(error);
-			return;
-		}
-
-		resolve(returnedValues);
-	});
-});
-
-export const loginWithPassword = withPromisifiedReturn(Meteor.loginWithPassword.bind(Meteor));
-
-export const batchSetSettings = withPromisifiedReturn(settings.batchSet.bind(settings));
-
-export const setSetting = withPromisifiedReturn(settings.set.bind(settings));
diff --git a/client/components/setupWizard/steps/AdminUserInformationStep.js b/client/components/setupWizard/steps/AdminUserInformationStep.js
index 0a278badf4cd3aaecc18923e5676927c6c84ffc8..e99663aa2f02e5a5989d5c9e1e13e3f9fc8cdad9 100644
--- a/client/components/setupWizard/steps/AdminUserInformationStep.js
+++ b/client/components/setupWizard/steps/AdminUserInformationStep.js
@@ -1,46 +1,57 @@
-import { Input, Field, FieldGroup, Label } from '@rocket.chat/fuselage';
+import {
+	EmailInput,
+	Field,
+	FieldGroup,
+	Icon,
+	Label,
+	PasswordInput,
+	TextInput,
+} from '@rocket.chat/fuselage';
 import { Session } from 'meteor/session';
 import React, { useMemo, useState } from 'react';
 import toastr from 'toastr';
 
-import { call } from '../../../../app/ui-utils/client';
 import { handleError } from '../../../../app/utils/client';
 import { callbacks } from '../../../../app/callbacks/client';
 import { useFocus } from '../../../hooks/useFocus';
+import { useLoginWithPassword } from '../../../hooks/useLoginWithPassword';
+import { useMethod } from '../../../hooks/useMethod';
 import { useSetting } from '../../../hooks/useSetting';
-import { useTranslation } from '../../contexts/TranslationContext';
+import { useTranslation } from '../../providers/TranslationProvider';
 import { useSetupWizardStepsState } from '../StepsState';
 import { Step } from '../Step';
 import { StepHeader } from '../StepHeader';
 import { Pager } from '../Pager';
 import { StepContent } from '../StepContent';
-import { loginWithPassword } from '../functions';
 
-const registerAdminUser = async ({ name, username, email, password, onRegistrationEmailSent }) => {
-	await call('registerUser', { name, username, email, pass: password });
-	callbacks.run('userRegistered');
+export function AdminUserInformationStep({ step, title, active }) {
+	const { goToNextStep } = useSetupWizardStepsState();
 
-	try {
-		await loginWithPassword(email, password);
-	} catch (error) {
-		if (error.error === 'error-invalid-email') {
-			onRegistrationEmailSent && onRegistrationEmailSent();
-			return;
-		}
-		handleError(error);
-		throw error;
-	}
+	const loginWithPassword = useLoginWithPassword();
+	const registerUser = useMethod('registerUser');
+	const defineUsername = useMethod('setUsername');
 
-	Session.set('forceLogin', false);
+	const registerAdminUser = async ({ name, username, email, password, onRegistrationEmailSent }) => {
+		await registerUser({ name, username, email, pass: password });
+		callbacks.run('userRegistered');
 
-	await call('setUsername', username);
+		try {
+			await loginWithPassword(email, password);
+		} catch (error) {
+			if (error.error === 'error-invalid-email') {
+				onRegistrationEmailSent && onRegistrationEmailSent();
+				return;
+			}
+			handleError(error);
+			throw error;
+		}
+
+		Session.set('forceLogin', false);
 
-	callbacks.run('usernameSet');
-};
+		await defineUsername(username);
 
-export function AdminUserInformationStep({ step, title }) {
-	const { currentStep, goToNextStep } = useSetupWizardStepsState();
-	const active = step === currentStep;
+		callbacks.run('usernameSet');
+	};
 
 	const regexpForUsernameValidation = useSetting('UTF8_Names_Validation');
 	const usernameRegExp = useMemo(() => new RegExp(`^${ regexpForUsernameValidation }$`), [regexpForUsernameValidation]);
@@ -111,53 +122,52 @@ export function AdminUserInformationStep({ step, title }) {
 		<StepContent>
 			<FieldGroup>
 				<Field>
-					<Label text={t('Name')}>
-						<Input
-							ref={autoFocusRef}
-							type='text'
-							icon='user'
-							placeholder={t('Type_your_name')}
-							value={name}
-							onChange={({ currentTarget: { value } }) => setName(value)}
-							error={!isNameValid}
-						/>
-					</Label>
+					<Label text={t('Name')} />
+					<TextInput
+						ref={autoFocusRef}
+						addon={<Icon name='user' />}
+						placeholder={t('Type_your_name')}
+						value={name}
+						onChange={({ currentTarget: { value } }) => setName(value)}
+						error={!isNameValid}
+					/>
 				</Field>
 				<Field>
-					<Label text={t('Username')}>
-						<Input
-							type='text'
-							icon='at'
-							placeholder={t('Type_your_username')}
-							value={username}
-							onChange={({ currentTarget: { value } }) => setUsername(value)}
-							error={!isUsernameValid && t('Invalid_username')}
-						/>
-					</Label>
+					<Field.Row>
+						<Label text={t('Username')} />
+						{!isUsernameValid && <Field.Error>{t('Invalid_username')}</Field.Error>}
+					</Field.Row>
+					<TextInput
+						addon={<Icon name='at' />}
+						placeholder={t('Type_your_username')}
+						value={username}
+						onChange={({ currentTarget: { value } }) => setUsername(value)}
+						error={!isUsernameValid}
+					/>
 				</Field>
 				<Field>
-					<Label text={t('Organization_Email')}>
-						<Input
-							type='email'
-							icon='mail'
-							placeholder={t('Type_your_email')}
-							value={email}
-							onChange={({ currentTarget: { value } }) => setEmail(value)}
-							error={!isEmailValid && t('Invalid_email')}
-						/>
-					</Label>
+					<Field.Row>
+						<Label text={t('Organization_Email')} />
+						{!isEmailValid && <Field.Error>{t('Invalid_email')}</Field.Error>}
+					</Field.Row>
+					<EmailInput
+						addon={<Icon name='mail' />}
+						placeholder={t('Type_your_email')}
+						value={email}
+						onChange={({ currentTarget: { value } }) => setEmail(value)}
+						error={!isEmailValid}
+					/>
 				</Field>
 				<Field>
-					<Label text={t('Password')}>
-						<Input
-							type='password'
-							icon='key'
-							placeholder={t('Type_your_password')}
-							value={password}
-							onChange={({ currentTarget: { value } }) => setPassword(value)}
-							error={!isPasswordValid}
-						/>
-					</Label>
+					<Label text={t('Password')} />
+					<PasswordInput
+						type='password'
+						addon={<Icon name='key' />}
+						placeholder={t('Type_your_password')}
+						value={password}
+						onChange={({ currentTarget: { value } }) => setPassword(value)}
+						error={!isPasswordValid}
+					/>
 				</Field>
 			</FieldGroup>
 		</StepContent>
diff --git a/client/components/setupWizard/steps/AdminUserInformationStep.stories.js b/client/components/setupWizard/steps/AdminUserInformationStep.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..4a9fc568d10044285dc873aeec8938e5ae22999a
--- /dev/null
+++ b/client/components/setupWizard/steps/AdminUserInformationStep.stories.js
@@ -0,0 +1,16 @@
+import { boolean, select, text } from '@storybook/addon-knobs';
+import React from 'react';
+
+import { AdminUserInformationStep } from './AdminUserInformationStep';
+
+export default {
+	title: 'setupWizard/steps/AdminUserInformationStep',
+	component: AdminUserInformationStep,
+};
+
+export const _default = () =>
+	<AdminUserInformationStep
+		step={select('step', [1, 2, 3, 4, 'final'], 1)}
+		title={text('title', 'Admin Info')}
+		active={boolean('active', true)}
+	/>;
diff --git a/client/components/setupWizard/steps/RegisterServerStep.js b/client/components/setupWizard/steps/RegisterServerStep.js
index 8a29c8d00393262f00bb752fdc95cce0a50e4fce..c57f15ea228c25dc84f00ff269d73527b738ca49 100644
--- a/client/components/setupWizard/steps/RegisterServerStep.js
+++ b/client/components/setupWizard/steps/RegisterServerStep.js
@@ -1,18 +1,20 @@
-import { CheckBox, Label, RadioButton, useMergedRefs } from '@rocket.chat/fuselage';
+import { CheckBox, Label, RadioButton } from '@rocket.chat/fuselage';
+import { useMergedRefs } from '@rocket.chat/fuselage-hooks';
 import React, { useRef, useState } from 'react';
 
-import { call } from '../../../../app/ui-utils/client';
 import { handleError } from '../../../../app/utils/client';
-import { useTranslation } from '../../contexts/TranslationContext';
+import { useBatchSetSettings } from '../../../hooks/useBatchSetSettings';
+import { useFocus } from '../../../hooks/useFocus';
+import { useMethod } from '../../../hooks/useMethod';
 import { Icon } from '../../basic/Icon';
+import { useTranslation } from '../../providers/TranslationProvider';
 import { Pager } from '../Pager';
 import { useSetupWizardParameters } from '../ParametersProvider';
 import { Step } from '../Step';
 import { StepContent } from '../StepContent';
 import { StepHeader } from '../StepHeader';
 import { useSetupWizardStepsState } from '../StepsState';
-import { batchSetSettings } from '../functions';
-import { useFocus } from '../../../hooks/useFocus';
+import './RegisterServerStep.css';
 
 const Option = React.forwardRef(({ children, label, selected, disabled, ...props }, ref) => {
 	const innerRef = useRef();
@@ -43,11 +45,9 @@ const Item = ({ children, icon, ...props }) =>
 		{children}
 	</li>;
 
-export function RegisterServerStep({ step, title }) {
+export function RegisterServerStep({ step, title, active }) {
 	const { canDeclineServerRegistration } = useSetupWizardParameters();
-	const { currentStep, goToPreviousStep, goToFinalStep } = useSetupWizardStepsState();
-
-	const active = step === currentStep;
+	const { goToPreviousStep, goToFinalStep } = useSetupWizardStepsState();
 
 	const [registerServer, setRegisterServer] = useState(true);
 	const [optInMarketingEmails, setOptInMarketingEmails] = useState(true);
@@ -56,6 +56,10 @@ export function RegisterServerStep({ step, title }) {
 
 	const [commiting, setComitting] = useState(false);
 
+	const batchSetSettings = useBatchSetSettings();
+
+	const registerCloudWorkspace = useMethod('cloud:registerWorkspace');
+
 	const handleBackClick = () => {
 		goToPreviousStep();
 	};
@@ -86,7 +90,7 @@ export function RegisterServerStep({ step, title }) {
 			]);
 
 			if (registerServer) {
-				await call('cloud:registerWorkspace');
+				await registerCloudWorkspace();
 			}
 
 			setComitting(false);
diff --git a/client/components/setupWizard/steps/RegisterServerStep.stories.js b/client/components/setupWizard/steps/RegisterServerStep.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..cccb66ea23c8bf0810122643f73629e6fff4f757
--- /dev/null
+++ b/client/components/setupWizard/steps/RegisterServerStep.stories.js
@@ -0,0 +1,16 @@
+import { boolean, select, text } from '@storybook/addon-knobs';
+import React from 'react';
+
+import { RegisterServerStep } from './RegisterServerStep';
+
+export default {
+	title: 'setupWizard/steps/RegisterServerStep',
+	component: RegisterServerStep,
+};
+
+export const _default = () =>
+	<RegisterServerStep
+		step={select('step', [1, 2, 3, 4, 'final'], 4)}
+		title={text('title', 'Register Server')}
+		active={boolean('active', true)}
+	/>;
diff --git a/client/components/setupWizard/steps/SettingsBasedStep.js b/client/components/setupWizard/steps/SettingsBasedStep.js
index 6c0aed84efab34d9c960971aa1c8e82c0c18cd51..5123dd1e6a637ad7e97692af7ee50e2c3aaa1573 100644
--- a/client/components/setupWizard/steps/SettingsBasedStep.js
+++ b/client/components/setupWizard/steps/SettingsBasedStep.js
@@ -1,18 +1,18 @@
-import { Input, Field, FieldGroup, Label } from '@rocket.chat/fuselage';
+import { Field, FieldGroup, Label, SelectInput, TextInput } from '@rocket.chat/fuselage';
 import { TAPi18n } from 'meteor/rocketchat:tap-i18n';
 import React, { useEffect, useReducer, useState } from 'react';
 
 import { handleError } from '../../../../app/utils/client';
+import { useBatchSetSettings } from '../../../hooks/useBatchSetSettings';
 import { useFocus } from '../../../hooks/useFocus';
-import { useTranslation } from '../../contexts/TranslationContext';
 import { useReactiveValue } from '../../../hooks/useReactiveValue';
+import { useTranslation } from '../../providers/TranslationProvider';
 import { Pager } from '../Pager';
 import { useSetupWizardParameters } from '../ParametersProvider';
 import { useSetupWizardStepsState } from '../StepsState';
 import { Step } from '../Step';
 import { StepHeader } from '../StepHeader';
 import { StepContent } from '../StepContent';
-import { batchSetSettings } from '../functions';
 
 const useFields = () => {
 	const reset = 'RESET';
@@ -37,15 +37,13 @@ const useFields = () => {
 	return { fields, resetFields, setFieldValue };
 };
 
-export function SettingsBasedStep({ step, title }) {
+export function SettingsBasedStep({ step, title, active }) {
 	const { settings } = useSetupWizardParameters();
 	const { currentStep, goToPreviousStep, goToNextStep } = useSetupWizardStepsState();
 	const { fields, resetFields, setFieldValue } = useFields();
 	const [commiting, setCommiting] = useState(false);
 
-	const active = step === currentStep;
-
-	const languages = useReactiveValue(() => TAPi18n.getLanguages(), []);
+	const languages = useReactiveValue(() => TAPi18n && TAPi18n.getLanguages(), []);
 
 	useEffect(() => {
 		resetFields(
@@ -59,6 +57,8 @@ export function SettingsBasedStep({ step, title }) {
 
 	const t = useTranslation();
 
+	const batchSetSettings = useBatchSetSettings();
+
 	const handleBackClick = () => {
 		goToPreviousStep();
 	};
@@ -88,42 +88,41 @@ export function SettingsBasedStep({ step, title }) {
 			<FieldGroup>
 				{fields.map(({ _id, type, i18nLabel, value, values }, i) =>
 					<Field key={i}>
-						<Label text={t(i18nLabel)}>
-							{type === 'string' && <Input
-								type='text'
-								name={_id}
-								ref={i === 0 ? autoFocusRef : undefined}
-								value={value}
-								onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
-							/>}
-
-							{type === 'select' && <Input
-								type='select'
-								name={_id}
-								placeholder={t('Select_an_option')}
-								ref={i === 0 ? autoFocusRef : undefined}
-								value={value}
-								onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
-							>
-								{values
-									.map(({ i18nLabel, key }) => ({ label: t(i18nLabel), value: key }))
-									.map(({ label, value }) => <option key={value} value={value}>{label}</option>)}
-							</Input>}
-
-							{type === 'language' && <Input
-								type='select'
-								name={_id}
-								placeholder={t('Default')}
-								ref={i === 0 ? autoFocusRef : undefined}
-								value={value}
-								onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
-							>
-								{Object.entries(languages)
-									.map(([key, { name }]) => ({ label: name, value: key }))
-									.sort((a, b) => a.key - b.key)
-									.map(({ label, value }) => <option key={value} value={value}>{label}</option>)}
-							</Input>}
-						</Label>
+						<Label text={t(i18nLabel)} />
+						{type === 'string' && <TextInput
+							type='text'
+							name={_id}
+							ref={i === 0 ? autoFocusRef : undefined}
+							value={value}
+							onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
+						/>}
+
+						{type === 'select' && <SelectInput
+							type='select'
+							name={_id}
+							placeholder={t('Select_an_option')}
+							ref={i === 0 ? autoFocusRef : undefined}
+							value={value}
+							onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
+						>
+							{values
+								.map(({ i18nLabel, key }) => ({ label: t(i18nLabel), value: key }))
+								.map(({ label, value }) => <SelectInput.Option key={value} value={value}>{label}</SelectInput.Option>)}
+						</SelectInput>}
+
+						{type === 'language' && <SelectInput
+							type='select'
+							name={_id}
+							placeholder={t('Default')}
+							ref={i === 0 ? autoFocusRef : undefined}
+							value={value}
+							onChange={({ currentTarget: { value } }) => setFieldValue(_id, value)}
+						>
+							{Object.entries(languages)
+								.map(([key, { name }]) => ({ label: name, value: key }))
+								.sort((a, b) => a.key - b.key)
+								.map(({ label, value }) => <SelectInput.Option key={value} value={value}>{label}</SelectInput.Option>)}
+						</SelectInput>}
 					</Field>
 				)}
 			</FieldGroup>
diff --git a/client/components/setupWizard/steps/SettingsBasedStep.stories.js b/client/components/setupWizard/steps/SettingsBasedStep.stories.js
new file mode 100644
index 0000000000000000000000000000000000000000..9d9a1ec10be6c0a2701e3fe7227f4dfa2fc77c87
--- /dev/null
+++ b/client/components/setupWizard/steps/SettingsBasedStep.stories.js
@@ -0,0 +1,16 @@
+import { boolean, select, text } from '@storybook/addon-knobs';
+import React from 'react';
+
+import { SettingsBasedStep } from './SettingsBasedStep';
+
+export default {
+	title: 'setupWizard/steps/SettingsBasedStep',
+	component: SettingsBasedStep,
+};
+
+export const _default = () =>
+	<SettingsBasedStep
+		step={select('step', [1, 2, 3, 4, 'final'], 2)}
+		title={text('title', 'Settings-Based Step')}
+		active={boolean('active', true)}
+	/>;
diff --git a/client/hooks/useAutorun.js b/client/hooks/useAutorun.js
new file mode 100644
index 0000000000000000000000000000000000000000..a0bc30c9a4f18df4bf28d3023790f229350930f2
--- /dev/null
+++ b/client/hooks/useAutorun.js
@@ -0,0 +1,12 @@
+import { Tracker } from 'meteor/tracker';
+import { useEffect } from 'react';
+
+export const useAutorun = (autorunFunction, deps = []) => {
+	useEffect(() => {
+		const computation = Tracker.autorun(autorunFunction);
+
+		return () => {
+			computation.stop();
+		};
+	}, deps);
+};
diff --git a/client/hooks/useBatchSetSettings.js b/client/hooks/useBatchSetSettings.js
new file mode 100644
index 0000000000000000000000000000000000000000..7f9ef583a093d31cef79d84e0e94fde4e1c0e9c1
--- /dev/null
+++ b/client/hooks/useBatchSetSettings.js
@@ -0,0 +1,14 @@
+import { useCallback } from 'react';
+
+import { settings } from '../../app/settings/lib/settings';
+
+export const useBatchSetSettings = () => useCallback((entries) => new Promise((resolve, reject) => {
+	settings.batchSet(entries, (error, result) => {
+		if (error) {
+			reject(error);
+			return;
+		}
+
+		resolve(result);
+	});
+}), []);
diff --git a/client/hooks/useEmbeddedLayout.js b/client/hooks/useEmbeddedLayout.js
index 1c4456b1389a7f7d2a5507c623181f595a4a4411..fa6da02c4227809313cbe13f0051348efc7beca9 100644
--- a/client/hooks/useEmbeddedLayout.js
+++ b/client/hooks/useEmbeddedLayout.js
@@ -1,3 +1,3 @@
-import { useQueryStringParameter } from '../components/contexts/RouterContext';
+import { useQueryStringParameter } from '../components/providers/RouterProvider';
 
 export const useEmbeddedLayout = () => useQueryStringParameter('layout') === 'embedded';
diff --git a/client/hooks/useEventCallback.js b/client/hooks/useEventCallback.js
new file mode 100644
index 0000000000000000000000000000000000000000..f623844f961282b4b51fd9bcca0b2df95f7b21a5
--- /dev/null
+++ b/client/hooks/useEventCallback.js
@@ -0,0 +1,13 @@
+import { useCallback, useLayoutEffect, useRef } from 'react';
+
+export const useEventCallback = (fn, ...deps) => {
+	const fnRef = useRef(fn);
+	const depsRef = useRef(deps);
+
+	useLayoutEffect(() => {
+		fnRef.current = fn;
+		depsRef.current = deps;
+	});
+
+	return useCallback((...args) => (0, fnRef.current)(...depsRef.current, ...args), []);
+};
diff --git a/client/hooks/useLazyRef.js b/client/hooks/useLazyRef.js
new file mode 100644
index 0000000000000000000000000000000000000000..a45e92a3828d336f74288bdcaf7de51906c6dd45
--- /dev/null
+++ b/client/hooks/useLazyRef.js
@@ -0,0 +1,6 @@
+import { useRef, useState } from 'react';
+
+export const useLazyRef = (fn) => {
+	const [value] = useState(fn);
+	return useRef(value);
+};
diff --git a/client/hooks/useLoginWithPassword.js b/client/hooks/useLoginWithPassword.js
new file mode 100644
index 0000000000000000000000000000000000000000..f28c29fdec0cab0c8b4a5465b43537d65aa757f7
--- /dev/null
+++ b/client/hooks/useLoginWithPassword.js
@@ -0,0 +1,13 @@
+import { Meteor } from 'meteor/meteor';
+import { useCallback } from 'react';
+
+export const useLoginWithPassword = () => useCallback((user, password) => new Promise((resolve, reject) => {
+	Meteor.loginWithPassword(user, password, (error, result) => {
+		if (error) {
+			reject(error);
+			return;
+		}
+
+		resolve(result);
+	});
+}), []);
diff --git a/client/hooks/useMethod.js b/client/hooks/useMethod.js
new file mode 100644
index 0000000000000000000000000000000000000000..f2d76e6bb90a39f4dcc1264ed87f21cf345b6fb8
--- /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/useNonReactiveValue.js b/client/hooks/useNonReactiveValue.js
new file mode 100644
index 0000000000000000000000000000000000000000..7f833801cbf21fbc2dfebae0c7d1cc8bd4a3a7a6
--- /dev/null
+++ b/client/hooks/useNonReactiveValue.js
@@ -0,0 +1,4 @@
+import { Tracker } from 'meteor/tracker';
+import { useMemo } from 'react';
+
+export const useNonReactiveValue = (getValue) => useMemo(() => Tracker.nonreactive(getValue), []);
diff --git a/client/hooks/useReactiveValue.js b/client/hooks/useReactiveValue.js
index 00e63cad57cc7e9a2966fa232ac2f60fbcd134a4..99f38345d5db6f03a83fb5dcc3151bf36d94ebb0 100644
--- a/client/hooks/useReactiveValue.js
+++ b/client/hooks/useReactiveValue.js
@@ -1,18 +1,15 @@
-import { Tracker } from 'meteor/tracker';
-import { useEffect, useState } from 'react';
+import { useState } from 'react';
 
-export const useReactiveValue = (getValue, deps = []) => {
-	const [value, setValue] = useState(getValue);
+import { useAutorun } from './useAutorun';
+import { useNonReactiveValue } from './useNonReactiveValue';
 
-	useEffect(() => {
-		const computation = Tracker.autorun(() => {
-			const newValue = getValue();
-			setValue(() => newValue);
-		});
+export const useReactiveValue = (getValue, deps = []) => {
+	const initialValue = useNonReactiveValue(getValue);
+	const [value, setValue] = useState(() => initialValue);
 
-		return () => {
-			computation.stop();
-		};
+	useAutorun(() => {
+		const newValue = getValue();
+		setValue(() => newValue);
 	}, deps);
 
 	return value;
diff --git a/client/hooks/useRocketChatInformation.js b/client/hooks/useRocketChatInformation.js
new file mode 100644
index 0000000000000000000000000000000000000000..8432c9195e69cd70c6cbd83edefbf756b4f912ef
--- /dev/null
+++ b/client/hooks/useRocketChatInformation.js
@@ -0,0 +1,3 @@
+import { Info } from '../../app/utils';
+
+export const useRocketChatInformation = () => Info;
diff --git a/client/hooks/useSetSetting.js b/client/hooks/useSetSetting.js
new file mode 100644
index 0000000000000000000000000000000000000000..6dca2f21e1c9e22a790fa35ed8e53ad9f20cd463
--- /dev/null
+++ b/client/hooks/useSetSetting.js
@@ -0,0 +1,14 @@
+import { useCallback } from 'react';
+
+import { settings } from '../../app/settings/lib/settings';
+
+export const useSetSetting = (settingName) => useCallback((value) => new Promise((resolve, reject) => {
+	settings.set(settingName, value, (error, result) => {
+		if (error) {
+			reject(error);
+			return;
+		}
+
+		resolve(result);
+	});
+}), [settingName]);
diff --git a/client/hooks/useSetting.js b/client/hooks/useSetting.js
index 1d287c2e8196bf9ff8bb52dbd3ac5c4a9b38232b..e67f2fbac18db5da8b303280c7945db6263621b7 100644
--- a/client/hooks/useSetting.js
+++ b/client/hooks/useSetting.js
@@ -1,4 +1,4 @@
 import { settings } from '../../app/settings/client';
 import { useReactiveValue } from './useReactiveValue';
 
-export const useSetting = (settingName) => useReactiveValue(() => settings.get(settingName));
+export const useSetting = (settingName) => useReactiveValue(() => settings.get(settingName), [settingName]);
diff --git a/client/importsCss.js b/client/importsCss.js
index 2fb3453faa9d20302d1c402afe9c42d798aba51c..0947ae6763026b5d807a40afa484988a382aaab6 100644
--- a/client/importsCss.js
+++ b/client/importsCss.js
@@ -1,4 +1,4 @@
-import './RocketChat.font.css';
+import './rocketchat.font.css';
 import '../app/chatpal-search/client/style.css';
 import '../app/theme/client/main.css';
 import '../app/theme/client/vendor/photoswipe.css';
diff --git a/client/rocketchat.font.css b/client/rocketchat.font.css
new file mode 100644
index 0000000000000000000000000000000000000000..b1d1a2b3dcd5251560b1a183e4a17d952b6b50bc
--- /dev/null
+++ b/client/rocketchat.font.css
@@ -0,0 +1,14 @@
+@font-face {
+	font-family: 'RocketChat';
+	font-weight: 400;
+	font-style: normal;
+	font-display: auto;
+
+	src: url('/fonts/rocketchat.eot');
+	src:
+		url('/fonts/rocketchat.eot?#iefix') format('embedded-opentype'),
+		url('/fonts/rocketchat.woff2') format('woff2'),
+		url('/fonts/rocketchat.woff') format('woff'),
+		url('/fonts/rocketchat.ttf') format('truetype'),
+		url('/fonts/rocketchat.svg#RocketChat') format('svg');
+}
diff --git a/client/routes.js b/client/routes.js
index 6fc5cbde8994e6133e8b36b9b0e1b01980e0d034..2f768d11e89998da2f22f58fb966011bc7ab9d8e 100644
--- a/client/routes.js
+++ b/client/routes.js
@@ -7,8 +7,9 @@ import { Blaze } from 'meteor/blaze';
 import { HTML } from 'meteor/htmljs';
 import { FlowRouter } from 'meteor/kadira:flow-router';
 import { BlazeLayout } from 'meteor/kadira:blaze-layout';
-import { Template } from 'meteor/templating';
+import { ReactiveVar } from 'meteor/reactive-var';
 import { Session } from 'meteor/session';
+import { Template } from 'meteor/templating';
 
 import { KonchatNotification } from '../app/ui';
 import { ChatSubscription } from '../app/models';
@@ -39,18 +40,29 @@ const createTemplateForComponent = async (
 	// eslint-disable-next-line new-cap
 	renderContainerView = () => HTML.DIV()
 ) => {
-	const React = await import('react');
-	const ReactDOM = await import('react-dom');
-	const { MeteorProvider } = await import('./components/providers/MeteorProvider');
-
 	const name = component.displayName || component.name;
 
 	if (!name) {
 		throw new Error('the component must have a name');
 	}
 
+	if (Template[name]) {
+		Template[name].props.set(props);
+		return name;
+	}
+
 	Template[name] = new Blaze.Template(name, renderContainerView);
 
+	Template[name].props = new ReactiveVar(props);
+
+	const React = await import('react');
+	const ReactDOM = await import('react-dom');
+	const { MeteorProvider } = await import('./components/providers/MeteorProvider');
+
+	function TemplateComponent() {
+		return React.createElement(component, Template[name].props.get());
+	}
+
 	Template[name].onRendered(() => {
 		Template.instance().autorun((computation) => {
 			if (computation.firstRun) {
@@ -59,7 +71,7 @@ const createTemplateForComponent = async (
 
 			ReactDOM.render(
 				React.createElement(MeteorProvider, {
-					children: React.createElement(component, props),
+					children: React.createElement(TemplateComponent),
 				}), Template.instance().firstNode);
 		});
 	});
@@ -221,60 +233,21 @@ FlowRouter.route('/setup-wizard/:step?', {
 	},
 });
 
-FlowRouter.route('/admin/users', {
-	name: 'admin-users',
-	action() {
-		BlazeLayout.render('main', { center: 'adminUsers' });
-	},
-});
-
-FlowRouter.route('/admin/rooms', {
-	name: 'admin-rooms',
-	action() {
-		BlazeLayout.render('main', { center: 'adminRooms' });
-	},
-});
-
-FlowRouter.route('/admin/import', {
-	name: 'admin-import',
-	action() {
-		BlazeLayout.render('main', { center: 'adminImport' });
-	},
-});
-
-FlowRouter.route('/admin/import/history', {
-	name: 'admin-import-history',
-	action() {
-		BlazeLayout.render('main', { center: 'adminImportHistory' });
-	},
-});
-
-FlowRouter.route('/admin/import/prepare/:importer', {
-	name: 'admin-import-prepare',
-	action() {
-		BlazeLayout.render('main', { center: 'adminImportPrepare' });
-	},
-});
-
-FlowRouter.route('/admin/import/progress/:importer', {
-	name: 'admin-import-progress',
-	action() {
-		BlazeLayout.render('main', { center: 'adminImportProgress' });
-	},
-});
-
 FlowRouter.route('/admin/:group?', {
 	name: 'admin',
 	action: async ({ group = 'info' } = {}) => {
 		switch (group) {
 			case 'info': {
-				const { InformationPage } = await import('./components/admin/info/InformationPage');
-				BlazeLayout.render('main', { center: await createTemplateForComponent(InformationPage) });
+				const { InformationRoute } = await import('./components/admin/info/InformationRoute');
+				BlazeLayout.render('main', { center: await createTemplateForComponent(InformationRoute) });
 				break;
 			}
 
-			default:
-				BlazeLayout.render('main', { center: 'admin' });
+			default: {
+				const { SettingsRoute } = await import('./components/admin/settings/SettingsRoute');
+				BlazeLayout.render('main', { center: await createTemplateForComponent(SettingsRoute, { group }) });
+				// BlazeLayout.render('main', { center: 'admin' });
+			}
 		}
 	},
 });
diff --git a/package-lock.json b/package-lock.json
index ca9f47010a58f5c330320fed50e68b5b3c931176..3f502cf95d352aec4484dbe9b6f08b21fce9080e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -181,7 +181,7 @@
 				},
 				"minimist": {
 					"version": "1.2.0",
-					"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+					"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 					"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
 					"dev": true
 				},
@@ -374,9 +374,9 @@
 					}
 				},
 				"@babel/types": {
-					"version": "7.6.1",
-					"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz",
-					"integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==",
+					"version": "7.6.3",
+					"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz",
+					"integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==",
 					"dev": true,
 					"requires": {
 						"esutils": "^2.0.2",
@@ -1292,9 +1292,9 @@
 			}
 		},
 		"@babel/plugin-transform-flow-strip-types": {
-			"version": "7.4.4",
-			"resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.4.tgz",
-			"integrity": "sha512-WyVedfeEIILYEaWGAUWzVNyqG4sfsNooMhXWsu/YzOvVGcsnPb5PguysjJqI3t3qiaYj0BR8T2f5njdjTGe44Q==",
+			"version": "7.6.3",
+			"resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.6.3.tgz",
+			"integrity": "sha512-l0ETkyEofkqFJ9LS6HChNIKtVJw2ylKbhYMlJ5C6df+ldxxaLIyXY4yOdDQQspfFpV8/vDiaWoJlvflstlYNxg==",
 			"dev": true,
 			"requires": {
 				"@babel/helper-plugin-utils": "^7.0.0",
@@ -1468,9 +1468,9 @@
 			}
 		},
 		"@babel/plugin-transform-react-constant-elements": {
-			"version": "7.6.0",
-			"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.6.0.tgz",
-			"integrity": "sha512-np/nPuII8DHOZWB3u8u+NSeKlEz0eBrOlnVksIQog4C9NGVzXO+NLxMcXn4Eu4GMFzOw2W6Tyo6L3+Wv8z9Y5w==",
+			"version": "7.6.3",
+			"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.6.3.tgz",
+			"integrity": "sha512-1/YogSSU7Tby9rq2VCmhuRg+6pxsHy2rI7w/oo8RKoBt6uBUFG+mk6x13kK+FY1/ggN92HAfg7ADd1v1+NCOKg==",
 			"dev": true,
 			"requires": {
 				"@babel/helper-annotate-as-pure": "^7.0.0",
@@ -1606,9 +1606,9 @@
 			}
 		},
 		"@babel/plugin-transform-typescript": {
-			"version": "7.6.0",
-			"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.6.0.tgz",
-			"integrity": "sha512-yzw7EopOOr6saONZ3KA3lpizKnWRTe+rfBqg4AmQbSow7ik7fqmzrfIqt053osLwLE2AaTqGinLM2tl6+M/uog==",
+			"version": "7.6.3",
+			"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.6.3.tgz",
+			"integrity": "sha512-aiWINBrPMSC3xTXRNM/dfmyYuPNKY/aexYqBgh0HBI5Y+WO5oRAqW/oROYeYHrF4Zw12r9rK4fMk/ZlAmqx/FQ==",
 			"dev": true,
 			"requires": {
 				"@babel/helper-create-class-features-plugin": "^7.6.0",
@@ -1846,9 +1846,9 @@
 			}
 		},
 		"@emotion/core": {
-			"version": "10.0.17",
-			"resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.0.17.tgz",
-			"integrity": "sha512-gykyjjr0sxzVuZBVTVK4dUmYsorc2qLhdYgSiOVK+m7WXgcYTKZevGWZ7TLAgTZvMelCTvhNq8xnf8FR1IdTbg==",
+			"version": "10.0.21",
+			"resolved": "https://registry.npmjs.org/@emotion/core/-/core-10.0.21.tgz",
+			"integrity": "sha512-U9zbc7ovZ2ceIwbLXYZPJy6wPgnOdTNT4jENZ31ee6v2lojetV5bTbCVk6ciT8G3wQRyVaTTfUCH9WCrMzpRIw==",
 			"dev": true,
 			"requires": {
 				"@babel/runtime": "^7.5.5",
@@ -1860,9 +1860,9 @@
 			},
 			"dependencies": {
 				"@babel/runtime": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
-					"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
+					"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"
@@ -1948,9 +1948,9 @@
 			},
 			"dependencies": {
 				"@babel/runtime": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
-					"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
+					"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"
@@ -2370,17 +2370,28 @@
 			}
 		},
 		"@rocket.chat/fuselage": {
-			"version": "0.2.0-alpha.4",
-			"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.2.0-alpha.4.tgz",
-			"integrity": "sha512-LMmzAAUZk1TYSUKURZWv2KMuc96sOsrb8j+/U7fBfW14bpzSDmsw7q6SmnVKYAfoZ6Cxa6nO77ZSxwY3/p/aMA==",
+			"version": "0.2.0-dev.53",
+			"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.2.0-dev.53.tgz",
+			"integrity": "sha512-f3TGZKgXhTRRTyNDhCUOLTPJN+I3uwi1F3s4ZoC4JAge0gM5VG5RzHDbDw9rHe7RhMEYKfxvCOTNunBkCFmTXA==",
 			"requires": {
-				"@rocket.chat/icons": "^0.2.0-alpha.0"
+				"@rocket.chat/fuselage-tokens": "^0.2.0-alpha.15",
+				"@rocket.chat/icons": "^0.2.0-alpha.16"
 			}
 		},
+		"@rocket.chat/fuselage-hooks": {
+			"version": "0.2.0-dev.50",
+			"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-hooks/-/fuselage-hooks-0.2.0-dev.50.tgz",
+			"integrity": "sha512-58SuGnso0EvZlmSMjwm6Mhuv27VYdGtPV4RfU7MKtPLzgfzW5VFxLdHBCfiHLIvMlu4hQKEKsfk544Eob5ztag=="
+		},
+		"@rocket.chat/fuselage-tokens": {
+			"version": "0.2.0-alpha.15",
+			"resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.2.0-alpha.15.tgz",
+			"integrity": "sha512-vMaBpfFCYJFe4oS1YhYhOJfTNMxwwkv2Rl0KDo2OuWp4kRyNhfQG2sEDvGTM/EcZsCh0//mcbJ6neufh3jA4iQ=="
+		},
 		"@rocket.chat/icons": {
-			"version": "0.2.0-alpha.0",
-			"resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.2.0-alpha.0.tgz",
-			"integrity": "sha512-7bzc7frrOfSypD/QvJ+eBfiD5XZSpxzN8taaOB2g0AHDUYcS/yIDpZLRH0Eq0fVe4A4gXsg0MRgcU0cJzuXQ+g=="
+			"version": "0.2.0-dev.49",
+			"resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.2.0-dev.49.tgz",
+			"integrity": "sha512-Mk27YutpExRyBqT1ULn+6RsbzBFBpZ0dYh4EoV09eHMO9FRraK5pXJpBmqfv2+yJPff163Yu1AReNc/NICQ1Og=="
 		},
 		"@rocket.chat/livechat": {
 			"version": "1.2.5",
@@ -2475,6 +2486,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",
@@ -2506,17 +2552,17 @@
 			}
 		},
 		"@storybook/addon-actions": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-5.2.1.tgz",
-			"integrity": "sha512-tu4LGeRGAq+sLlsRPE1PzGyYU9JyM3HMLXnOCh5dvRSS8wnoDw1zQ55LPOXH6aoJGdsrvktiw+uTVf4OyN7ryg==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-5.2.4.tgz",
+			"integrity": "sha512-5E8uXopy6Gq5R3MXrPf0VM9QiLaGLxLCXtDYHQ0gku+HhPYR25KQudS/PyuO+OWzuyB0fsvTi240B3zw+zilOg==",
 			"dev": true,
 			"requires": {
-				"@storybook/addons": "5.2.1",
-				"@storybook/api": "5.2.1",
-				"@storybook/client-api": "5.2.1",
-				"@storybook/components": "5.2.1",
-				"@storybook/core-events": "5.2.1",
-				"@storybook/theming": "5.2.1",
+				"@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",
 				"core-js": "^3.0.1",
 				"fast-deep-equal": "^2.0.1",
 				"global": "^4.3.2",
@@ -2528,25 +2574,26 @@
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				}
 			}
 		},
 		"@storybook/addon-knobs": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/addon-knobs/-/addon-knobs-5.2.1.tgz",
-			"integrity": "sha512-JCSqrGYyVVBNkudhvla7qc9m0/Mn1UMaMzIxH5kewEE1KWZcCkdXD5hDASN39pkn3mX1yyqveP8jiyIL9vVBLg==",
-			"dev": true,
-			"requires": {
-				"@storybook/addons": "5.2.1",
-				"@storybook/api": "5.2.1",
-				"@storybook/client-api": "5.2.1",
-				"@storybook/components": "5.2.1",
-				"@storybook/core-events": "5.2.1",
-				"@storybook/theming": "5.2.1",
+			"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",
@@ -2561,9 +2608,9 @@
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"qs": {
@@ -2575,14 +2622,14 @@
 			}
 		},
 		"@storybook/addon-links": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-5.2.1.tgz",
-			"integrity": "sha512-N5f+lzai+ctHfzHoYWECYsg3lKGJuqhkVctro46fHSW7s/GB8+l78nDcV7hDjNEXDES8QN5C1fPYihatdgpSJA==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-5.2.4.tgz",
+			"integrity": "sha512-MG+Qne4gUWGYx2qQuLQXNcl7oOBF4PbIcR0oboZNrkZ+D+6f3nHwyb53CTtzVTc+SF45CFFYLHvFdGZvv5fcAw==",
 			"dev": true,
 			"requires": {
-				"@storybook/addons": "5.2.1",
-				"@storybook/core-events": "5.2.1",
-				"@storybook/router": "5.2.1",
+				"@storybook/addons": "5.2.4",
+				"@storybook/core-events": "5.2.4",
+				"@storybook/router": "5.2.4",
 				"common-tags": "^1.8.0",
 				"core-js": "^3.0.1",
 				"global": "^4.3.2",
@@ -2591,9 +2638,9 @@
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"qs": {
@@ -2604,40 +2651,67 @@
 				}
 			}
 		},
+		"@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.1",
-			"resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-5.2.1.tgz",
-			"integrity": "sha512-kdx97tTKsMf/lBlT40uLYsHMF1J71mn2j41RNaCXmWw/PrKCDmiNfinemN2wtbwRSvGqb3q/BAqjKLvUtWynGg==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-5.2.4.tgz",
+			"integrity": "sha512-Q+bnVlBA308qnELxnh18hBDRSUgltR9KbV537285dUL/okv/NC6n51mxJwIaG+ksBW2wU+5e6tqSayaKF3uHLw==",
 			"dev": true,
 			"requires": {
-				"@storybook/api": "5.2.1",
-				"@storybook/channels": "5.2.1",
-				"@storybook/client-logger": "5.2.1",
-				"@storybook/core-events": "5.2.1",
+				"@storybook/api": "5.2.4",
+				"@storybook/channels": "5.2.4",
+				"@storybook/client-logger": "5.2.4",
+				"@storybook/core-events": "5.2.4",
 				"core-js": "^3.0.1",
 				"global": "^4.3.2",
 				"util-deprecate": "^1.0.2"
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				}
 			}
 		},
 		"@storybook/api": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/api/-/api-5.2.1.tgz",
-			"integrity": "sha512-EXN6sqkGHRuNq0W6BZXOlxe2I2dmN0yUdQLiUOpzH2I3mXnVHpad/0v76dRc9fZbC4LaYUSxR8lBTr0rqIb4mA==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/api/-/api-5.2.4.tgz",
+			"integrity": "sha512-KqAB+NkHIHdwu749NDP+7i44jy1bFgpq7GTJlG+sx/XLZHQveK/8yn109g9bXHFth7SvdXI1+9GA/apzwBU/Mw==",
 			"dev": true,
 			"requires": {
-				"@storybook/channels": "5.2.1",
-				"@storybook/client-logger": "5.2.1",
-				"@storybook/core-events": "5.2.1",
-				"@storybook/router": "5.2.1",
-				"@storybook/theming": "5.2.1",
+				"@storybook/channels": "5.2.4",
+				"@storybook/client-logger": "5.2.4",
+				"@storybook/core-events": "5.2.4",
+				"@storybook/router": "5.2.4",
+				"@storybook/theming": "5.2.4",
 				"core-js": "^3.0.1",
 				"fast-deep-equal": "^2.0.1",
 				"global": "^4.3.2",
@@ -2648,14 +2722,14 @@
 				"semver": "^6.0.0",
 				"shallow-equal": "^1.1.0",
 				"store2": "^2.7.1",
-				"telejson": "^2.2.2",
+				"telejson": "^3.0.2",
 				"util-deprecate": "^1.0.2"
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"semver": {
@@ -2667,55 +2741,55 @@
 			}
 		},
 		"@storybook/channel-postmessage": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-5.2.1.tgz",
-			"integrity": "sha512-gmnn9qU1iLCpfF6bZuEM3QQOZsAviWeIpiezjrd/qkxatgr3qtbXd4EoZpcVuQw314etarWtNxVpcX6PXcASjQ==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-5.2.4.tgz",
+			"integrity": "sha512-ic7/Ho8z2/aOMjoEbr5p8rijOfO3SZdJnwMvDdUxrqvYq7yACZWidPo3w2+iBwQi9HLqEsWesP1c2doJBxVGRw==",
 			"dev": true,
 			"requires": {
-				"@storybook/channels": "5.2.1",
-				"@storybook/client-logger": "5.2.1",
+				"@storybook/channels": "5.2.4",
+				"@storybook/client-logger": "5.2.4",
 				"core-js": "^3.0.1",
 				"global": "^4.3.2",
-				"telejson": "^2.2.2"
+				"telejson": "^3.0.2"
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				}
 			}
 		},
 		"@storybook/channels": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-5.2.1.tgz",
-			"integrity": "sha512-AsF/Hwx91SDOgiOGOBSWS8EJAgqVm939n2nkfdLSJQQmX5EdPRAc3EIE3f13tyQub2yNx0OR4UzQDWgjwfVsEQ==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-5.2.4.tgz",
+			"integrity": "sha512-/r39yEZ5QiGdiq95DhXBypdBo7urkD3Sp1WDyK48uGkZ0gdHWSPy3BBy8OJhEhfNz7nVisTiVIBr4gIrubKDjw==",
 			"dev": true,
 			"requires": {
 				"core-js": "^3.0.1"
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				}
 			}
 		},
 		"@storybook/client-api": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-5.2.1.tgz",
-			"integrity": "sha512-VxexqxrbORCGqwx2j0/91Eu1A/vq+rSVIesWwzIowmoLfBwRwDdskO20Yn9U7iMSpux4RvHGF6y1Q1ZtnXm9aA==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-5.2.4.tgz",
+			"integrity": "sha512-SOwzEFHoNapURhNqdcI7HA76o5tkWvs2+2s++i/S7xsAd3KyefIVDOdqSMlAxJkxZb8Mlrb3UNRxlrpA8SZqNA==",
 			"dev": true,
 			"requires": {
-				"@storybook/addons": "5.2.1",
-				"@storybook/channel-postmessage": "5.2.1",
-				"@storybook/channels": "5.2.1",
-				"@storybook/client-logger": "5.2.1",
-				"@storybook/core-events": "5.2.1",
-				"@storybook/router": "5.2.1",
+				"@storybook/addons": "5.2.4",
+				"@storybook/channel-postmessage": "5.2.4",
+				"@storybook/channels": "5.2.4",
+				"@storybook/client-logger": "5.2.4",
+				"@storybook/core-events": "5.2.4",
+				"@storybook/router": "5.2.4",
 				"common-tags": "^1.8.0",
 				"core-js": "^3.0.1",
 				"eventemitter3": "^4.0.0",
@@ -2728,9 +2802,9 @@
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"eventemitter3": {
@@ -2763,30 +2837,30 @@
 			}
 		},
 		"@storybook/client-logger": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-5.2.1.tgz",
-			"integrity": "sha512-wzxSE9t3DaLCdd/gnGFnjevmYRZ92F3TEwhUP/QDXM9cZkNsRKHkjE61qjiO5aQPaZQG6Ea9ayWEQEMgZXDucg==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-5.2.4.tgz",
+			"integrity": "sha512-ofp6QQPQZBU+RvlAH5KpZRsfAFHecCZDnl/7YG6FwjHseJr3jHTYmBGGjJDMHFHq+Q7FGQu/yVb9lMFgoQ43QQ==",
 			"dev": true,
 			"requires": {
 				"core-js": "^3.0.1"
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				}
 			}
 		},
 		"@storybook/components": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/components/-/components-5.2.1.tgz",
-			"integrity": "sha512-cik5J/mTm1b1TOI17qM+2Mikk3rjb3SbBD4WlNz3Zvn+Hw0ukgbx6kQwVBgujhMlDtsHreidyEgIg4TM13S0Tg==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/components/-/components-5.2.4.tgz",
+			"integrity": "sha512-APhw+XGag0RTCRJ8eCWKVr8dLt9SRqnS8LtzcZJbokCYRxRTFzhmX2eVEE1v+d0gHib1/yh2COxOjMzv3m/rQA==",
 			"dev": true,
 			"requires": {
-				"@storybook/client-logger": "5.2.1",
-				"@storybook/theming": "5.2.1",
+				"@storybook/client-logger": "5.2.4",
+				"@storybook/theming": "5.2.4",
 				"@types/react-syntax-highlighter": "10.1.0",
 				"core-js": "^3.0.1",
 				"global": "^4.3.2",
@@ -2806,17 +2880,17 @@
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				}
 			}
 		},
 		"@storybook/core": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/core/-/core-5.2.1.tgz",
-			"integrity": "sha512-mGGvN3GWeLxZ9lYZ4IuD1IoJD+cn6XXm2Arzw+k6KEtJJDFrC5SjESTDGLVFienX5s2tgH4FjYb9Ps9sKfhHlg==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/core/-/core-5.2.4.tgz",
+			"integrity": "sha512-r5kDgZETNawHxpsAPw+h+pRk6l/mJhsSHeDo9/OdYtYFW7lmk2gadViXOTM+6gIWc6vQ8y750bgkahmyIIY0nQ==",
 			"dev": true,
 			"requires": {
 				"@babel/plugin-proposal-class-properties": "^7.3.3",
@@ -2824,15 +2898,15 @@
 				"@babel/plugin-syntax-dynamic-import": "^7.2.0",
 				"@babel/plugin-transform-react-constant-elements": "^7.2.0",
 				"@babel/preset-env": "^7.4.5",
-				"@storybook/addons": "5.2.1",
-				"@storybook/channel-postmessage": "5.2.1",
-				"@storybook/client-api": "5.2.1",
-				"@storybook/client-logger": "5.2.1",
-				"@storybook/core-events": "5.2.1",
-				"@storybook/node-logger": "5.2.1",
-				"@storybook/router": "5.2.1",
-				"@storybook/theming": "5.2.1",
-				"@storybook/ui": "5.2.1",
+				"@storybook/addons": "5.2.4",
+				"@storybook/channel-postmessage": "5.2.4",
+				"@storybook/client-api": "5.2.4",
+				"@storybook/client-logger": "5.2.4",
+				"@storybook/core-events": "5.2.4",
+				"@storybook/node-logger": "5.2.4",
+				"@storybook/router": "5.2.4",
+				"@storybook/theming": "5.2.4",
+				"@storybook/ui": "5.2.4",
 				"airbnb-js-shims": "^1 || ^2",
 				"ansi-to-html": "^0.6.11",
 				"autoprefixer": "^9.4.9",
@@ -3105,9 +3179,9 @@
 					"dev": true
 				},
 				"bluebird": {
-					"version": "3.7.0",
-					"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.0.tgz",
-					"integrity": "sha512-aBQ1FxIa7kSWCcmKHlcHFlT2jt6J/l4FzC7KcPELkOJOsPOb/bccdhmIrKDfXhwFrmc7vDoDrrepFvGqjyXGJg==",
+					"version": "3.7.1",
+					"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz",
+					"integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==",
 					"dev": true
 				},
 				"body-parser": {
@@ -3227,9 +3301,9 @@
 					"dev": true
 				},
 				"commander": {
-					"version": "2.20.1",
-					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
-					"integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==",
+					"version": "2.20.3",
+					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+					"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
 					"dev": true
 				},
 				"content-disposition": {
@@ -3248,9 +3322,9 @@
 					"dev": true
 				},
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"ejs": {
@@ -3461,9 +3535,9 @@
 					"dev": true
 				},
 				"json5": {
-					"version": "2.1.0",
-					"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
-					"integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
+					"version": "2.1.1",
+					"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz",
+					"integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==",
 					"dev": true,
 					"requires": {
 						"minimist": "^1.2.0"
@@ -3808,9 +3882,9 @@
 					"dev": true
 				},
 				"terser": {
-					"version": "4.3.4",
-					"resolved": "https://registry.npmjs.org/terser/-/terser-4.3.4.tgz",
-					"integrity": "sha512-Kcrn3RiW8NtHBP0ssOAzwa2MsIRQ8lJWiBG/K7JgqPlomA3mtb2DEmp4/hrUA+Jujx+WZ02zqd7GYD+QRBB/2Q==",
+					"version": "4.3.8",
+					"resolved": "https://registry.npmjs.org/terser/-/terser-4.3.8.tgz",
+					"integrity": "sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ==",
 					"dev": true,
 					"requires": {
 						"commander": "^2.20.0",
@@ -3960,9 +4034,9 @@
 					"dev": true
 				},
 				"webpack": {
-					"version": "4.41.0",
-					"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.0.tgz",
-					"integrity": "sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g==",
+					"version": "4.41.2",
+					"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz",
+					"integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==",
 					"dev": true,
 					"requires": {
 						"@webassemblyjs/ast": "1.8.5",
@@ -4038,26 +4112,26 @@
 			}
 		},
 		"@storybook/core-events": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-5.2.1.tgz",
-			"integrity": "sha512-AIYV/I+baQ0KxvEM7QAKqUedLn2os0XU9HTdtfZJTC3U9wjmR2ah2ScD6T0n7PBz3MderkvZG6dNjs9h8gRquQ==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-5.2.4.tgz",
+			"integrity": "sha512-nQknCmaz2S2HW6PSGcuFzve7Y1Js2Cb268vUG0ZMNtJZwFawqYc+KSQHqmOY0pVm8dyROTcWCudPA0k+hk6N5Q==",
 			"dev": true,
 			"requires": {
 				"core-js": "^3.0.1"
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				}
 			}
 		},
 		"@storybook/node-logger": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-5.2.1.tgz",
-			"integrity": "sha512-rz+snXZyKwTegKEf15w4uaFWIKpgaWzTw+Ar8mxa+mX7C2DP65TOc+JGYZ7lsXdred+0WP0DhnmhGu2cX8z3lA==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-5.2.4.tgz",
+			"integrity": "sha512-4OOzce02IAfrRv+Y7h3icyw6WIuDekpWF2eYjgYVVvAJYklCEwgeBTBCY0/2TJjPPTBDPUKHVP1Bdz3Vpci9pA==",
 			"dev": true,
 			"requires": {
 				"chalk": "^2.4.2",
@@ -4103,9 +4177,9 @@
 					"dev": true
 				},
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"supports-color": {
@@ -4120,18 +4194,19 @@
 			}
 		},
 		"@storybook/react": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/react/-/react-5.2.1.tgz",
-			"integrity": "sha512-brUG8iK2+1Fk5VFZWpAoSokCx21MaPX1zSAVA+Z/Ia0I0sFfurhpQgAGlVePTy9r7dtEEEdniZVtJOH/tHqk4Q==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/react/-/react-5.2.4.tgz",
+			"integrity": "sha512-AO0qwbD/2UGe5CrVizbaek+gCAPWkPVc0KUk38cT1mcuLpXwt1zZe7iHLQf2zOeBVSiBkPLOHrEtzDfnIJXKFQ==",
 			"dev": true,
 			"requires": {
 				"@babel/plugin-transform-react-constant-elements": "^7.2.0",
 				"@babel/preset-flow": "^7.0.0",
 				"@babel/preset-react": "^7.0.0",
-				"@storybook/addons": "5.2.1",
-				"@storybook/core": "5.2.1",
-				"@storybook/node-logger": "5.2.1",
+				"@storybook/addons": "5.2.4",
+				"@storybook/core": "5.2.4",
+				"@storybook/node-logger": "5.2.4",
 				"@svgr/webpack": "^4.0.3",
+				"@types/webpack-env": "^1.13.7",
 				"babel-plugin-add-react-displayname": "^0.0.5",
 				"babel-plugin-named-asset-import": "^0.3.1",
 				"babel-plugin-react-docgen": "^3.0.0",
@@ -4361,9 +4436,9 @@
 					"dev": true
 				},
 				"bluebird": {
-					"version": "3.7.0",
-					"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.0.tgz",
-					"integrity": "sha512-aBQ1FxIa7kSWCcmKHlcHFlT2jt6J/l4FzC7KcPELkOJOsPOb/bccdhmIrKDfXhwFrmc7vDoDrrepFvGqjyXGJg==",
+					"version": "3.7.1",
+					"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz",
+					"integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==",
 					"dev": true
 				},
 				"browserify-zlib": {
@@ -4419,15 +4494,15 @@
 					}
 				},
 				"commander": {
-					"version": "2.20.1",
-					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
-					"integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==",
+					"version": "2.20.3",
+					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+					"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
 					"dev": true
 				},
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"eslint-scope": {
@@ -4652,9 +4727,9 @@
 					"dev": true
 				},
 				"terser": {
-					"version": "4.3.4",
-					"resolved": "https://registry.npmjs.org/terser/-/terser-4.3.4.tgz",
-					"integrity": "sha512-Kcrn3RiW8NtHBP0ssOAzwa2MsIRQ8lJWiBG/K7JgqPlomA3mtb2DEmp4/hrUA+Jujx+WZ02zqd7GYD+QRBB/2Q==",
+					"version": "4.3.8",
+					"resolved": "https://registry.npmjs.org/terser/-/terser-4.3.8.tgz",
+					"integrity": "sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ==",
 					"dev": true,
 					"requires": {
 						"commander": "^2.20.0",
@@ -4722,9 +4797,9 @@
 					"dev": true
 				},
 				"webpack": {
-					"version": "4.41.0",
-					"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.0.tgz",
-					"integrity": "sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g==",
+					"version": "4.41.2",
+					"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz",
+					"integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==",
 					"dev": true,
 					"requires": {
 						"@webassemblyjs/ast": "1.8.5",
@@ -4780,9 +4855,9 @@
 			}
 		},
 		"@storybook/router": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/router/-/router-5.2.1.tgz",
-			"integrity": "sha512-Mlk275cyPoKtnP4DwQ5D8gTfnaRPL6kDZOSn0wbTMa6pQOfYKgJsa7tjzeAtZuZ/j8hKI4gAfT/auMgH6g+94A==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/router/-/router-5.2.4.tgz",
+			"integrity": "sha512-GL7eGdj5oYST0mE9fThJB9ye9tTTgrP+aP3okZ6MeMGtNytb7bmJRpAD2E4ouuPTQVppyHI5re8g/HUxUNOT1g==",
 			"dev": true,
 			"requires": {
 				"@reach/router": "^1.2.1",
@@ -4795,9 +4870,9 @@
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"qs": {
@@ -4809,14 +4884,14 @@
 			}
 		},
 		"@storybook/theming": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-5.2.1.tgz",
-			"integrity": "sha512-lbAfcyI7Tx8swduIPmlu/jdWzqTBN/v82IEQbZbPR4LS5OHRPmhXPNgFGrcH4kFAiD0GoezSsdum1x0ZZpsQUQ==",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-5.2.4.tgz",
+			"integrity": "sha512-2ZlqBrmnm8N0352Fnu2+GB3pEsHL4Eb2eKxV0VLLgkjJuAlm7CK6+I/e4ZknQWxwYm2pQj1y6ta68A62fGBYyA==",
 			"dev": true,
 			"requires": {
 				"@emotion/core": "^10.0.14",
 				"@emotion/styled": "^10.0.14",
-				"@storybook/client-logger": "5.2.1",
+				"@storybook/client-logger": "5.2.4",
 				"common-tags": "^1.8.0",
 				"core-js": "^3.0.1",
 				"deep-object-diff": "^1.1.0",
@@ -4829,9 +4904,9 @@
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"resolve-from": {
@@ -4843,21 +4918,19 @@
 			}
 		},
 		"@storybook/ui": {
-			"version": "5.2.1",
-			"resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-5.2.1.tgz",
-			"integrity": "sha512-h6Yf1ro/nZcz4nQAU+eSVPxVmpqv7uT7RMb3Vz+VLTY59IEA/sWcoIgA4MIxwf14nVcWOqSmVBJzNKWwc+NGJw==",
-			"dev": true,
-			"requires": {
-				"@storybook/addon-actions": "5.2.1",
-				"@storybook/addon-knobs": "5.2.1",
-				"@storybook/addons": "5.2.1",
-				"@storybook/api": "5.2.1",
-				"@storybook/channels": "5.2.1",
-				"@storybook/client-logger": "5.2.1",
-				"@storybook/components": "5.2.1",
-				"@storybook/core-events": "5.2.1",
-				"@storybook/router": "5.2.1",
-				"@storybook/theming": "5.2.1",
+			"version": "5.2.4",
+			"resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-5.2.4.tgz",
+			"integrity": "sha512-zsS43k1h4bWEW6oj9FNHlUL3niHoJJ8v7iqYbRtVM12rxrYhV3K8TGVG3LCuNB75i3Be0Myy+/RHA4x9kco08A==",
+			"dev": true,
+			"requires": {
+				"@storybook/addons": "5.2.4",
+				"@storybook/api": "5.2.4",
+				"@storybook/channels": "5.2.4",
+				"@storybook/client-logger": "5.2.4",
+				"@storybook/components": "5.2.4",
+				"@storybook/core-events": "5.2.4",
+				"@storybook/router": "5.2.4",
+				"@storybook/theming": "5.2.4",
 				"copy-to-clipboard": "^3.0.8",
 				"core-js": "^3.0.1",
 				"core-js-pure": "^3.0.1",
@@ -4873,7 +4946,7 @@
 				"qs": "^6.6.0",
 				"react": "^16.8.3",
 				"react-dom": "^16.8.3",
-				"react-draggable": "^3.3.2",
+				"react-draggable": "^4.0.3",
 				"react-helmet-async": "^1.0.2",
 				"react-hotkeys": "2.0.0-pre4",
 				"react-sizeme": "^2.6.7",
@@ -4881,14 +4954,14 @@
 				"resolve-from": "^5.0.0",
 				"semver": "^6.0.0",
 				"store2": "^2.7.1",
-				"telejson": "^2.2.2",
+				"telejson": "^3.0.2",
 				"util-deprecate": "^1.0.2"
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"qs": {
@@ -5048,9 +5121,9 @@
 			},
 			"dependencies": {
 				"@babel/types": {
-					"version": "7.6.1",
-					"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz",
-					"integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==",
+					"version": "7.6.3",
+					"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz",
+					"integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==",
 					"dev": true,
 					"requires": {
 						"esutils": "^2.0.2",
@@ -5211,7 +5284,7 @@
 		},
 		"@types/events": {
 			"version": "1.2.0",
-			"resolved": "http://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
+			"resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz",
 			"integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA=="
 		},
 		"@types/express": {
@@ -5247,6 +5320,12 @@
 			"integrity": "sha512-cS5owqtwzLN5kY+l+KgKdRJ/Cee8tlmQoGQuIE9tWnSmS3JMKzmxo2HIAk2wODMifGwO20d62xZQLYz+RLfXmw==",
 			"dev": true
 		},
+		"@types/is-function": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/@types/is-function/-/is-function-1.0.0.tgz",
+			"integrity": "sha512-iTs9HReBu7evG77Q4EC8hZnqRt57irBDkK9nvmHroiOIVwYMQc4IvYvdRgwKfYepunIY7Oh/dBuuld+Gj9uo6w==",
+			"dev": true
+		},
 		"@types/is-stream": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/@types/is-stream/-/is-stream-1.1.0.tgz",
@@ -5316,9 +5395,9 @@
 			"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
 		},
 		"@types/reach__router": {
-			"version": "1.2.5",
-			"resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.2.5.tgz",
-			"integrity": "sha512-Lna9cD38dN3deqJ6ThZgMKoAzW1LE3u+uUbPGdHUqquoM/fnZitSV1xfJxHjovu4SsNkpN9udkte3wEyrBPawQ==",
+			"version": "1.2.6",
+			"resolved": "https://registry.npmjs.org/@types/reach__router/-/reach__router-1.2.6.tgz",
+			"integrity": "sha512-Oh5DAVr/L2svBvubw6QEFpXGu295Y406BPs4i9t1n2pp7M+q3pmCmhzb9oZV5wncR41KCD3NHl1Yhi7uKnTPsA==",
 			"dev": true,
 			"requires": {
 				"@types/history": "*",
@@ -5326,15 +5405,24 @@
 			}
 		},
 		"@types/react": {
-			"version": "16.9.4",
-			"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.4.tgz",
-			"integrity": "sha512-ItGNmJvQ0IvWt8rbk5PLdpdQhvBVxAaXI9hDlx7UMd8Ie1iMIuwMNiKeTfmVN517CdplpyXvA22X4zm4jGGZnw==",
+			"version": "16.9.6",
+			"resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.6.tgz",
+			"integrity": "sha512-ulPWlBFO0DQiObqxEm3t4icozuakPy5O81g6QyHv+Nyo1UPL+QVq2rmq1e4J8oHY7jl0HEtMAHNwNIzv6FRuTQ==",
 			"dev": true,
 			"requires": {
 				"@types/prop-types": "*",
 				"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",
@@ -5374,6 +5462,12 @@
 			"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.4.tgz",
 			"integrity": "sha512-Set5ZdrAaKI/qHdFlVMgm/GsAv/wkXhSTuZFkJ+JI7HK+wIkIlOaUXSXieIvJ0+OvGIqtREFoE+NHJtEq0gtEw=="
 		},
+		"@types/webpack-env": {
+			"version": "1.14.1",
+			"resolved": "https://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.14.1.tgz",
+			"integrity": "sha512-0Ki9jAAhKDSuLDXOIMADg54Hu60SuBTEsWaJGGy5cV+SSUQ63J2a+RrYYGrErzz39fXzTibhKrAQJAb8M7PNcA==",
+			"dev": true
+		},
 		"@types/ws": {
 			"version": "5.1.2",
 			"resolved": "https://registry.npmjs.org/@types/ws/-/ws-5.1.2.tgz",
@@ -5846,12 +5940,12 @@
 			"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
 		},
 		"ansi-to-html": {
-			"version": "0.6.11",
-			"resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.11.tgz",
-			"integrity": "sha512-88XZtrcwrfkyn6fGstHnkaF1kl7hGtNCYh4vSmItgEV+6JnQHryDBf7udF4f2RhTRQmYvJvPcTtqgaqrxzc9oA==",
+			"version": "0.6.12",
+			"resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.6.12.tgz",
+			"integrity": "sha512-qBkIqLW979675mP76yB7yVkzeAWtATegdnDQ0RA3CZzknx0yUlNxMSML4xFdBfTs2GWYFQ1FELfbGbVSPzJ+LA==",
 			"dev": true,
 			"requires": {
-				"entities": "^1.1.1"
+				"entities": "^1.1.2"
 			}
 		},
 		"anymatch": {
@@ -6113,25 +6207,77 @@
 			"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg="
 		},
 		"array.prototype.flat": {
-			"version": "1.2.1",
-			"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.1.tgz",
-			"integrity": "sha512-rVqIs330nLJvfC7JqYvEWwqVr5QjYF1ib02i3YJtR/fICO6527Tjpc/e4Mvmxh3GIePPreRXMdaGyC99YphWEw==",
+			"version": "1.2.2",
+			"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.2.tgz",
+			"integrity": "sha512-VXjh7lAL4KXKF2hY4FnEW9eRW6IhdvFW1sN/JwLbmECbCgACCnBHNyP3lFiYuttr0jxRN9Bsc5+G27dMseSWqQ==",
 			"dev": true,
 			"requires": {
-				"define-properties": "^1.1.2",
-				"es-abstract": "^1.10.0",
+				"define-properties": "^1.1.3",
+				"es-abstract": "^1.15.0",
 				"function-bind": "^1.1.1"
+			},
+			"dependencies": {
+				"es-abstract": {
+					"version": "1.15.0",
+					"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz",
+					"integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==",
+					"dev": true,
+					"requires": {
+						"es-to-primitive": "^1.2.0",
+						"function-bind": "^1.1.1",
+						"has": "^1.0.3",
+						"has-symbols": "^1.0.0",
+						"is-callable": "^1.1.4",
+						"is-regex": "^1.0.4",
+						"object-inspect": "^1.6.0",
+						"object-keys": "^1.1.1",
+						"string.prototype.trimleft": "^2.1.0",
+						"string.prototype.trimright": "^2.1.0"
+					}
+				},
+				"object-keys": {
+					"version": "1.1.1",
+					"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+					"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+					"dev": true
+				}
 			}
 		},
 		"array.prototype.flatmap": {
-			"version": "1.2.1",
-			"resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.1.tgz",
-			"integrity": "sha512-i18e2APdsiezkcqDyZor78Pbfjfds3S94dG6dgIV2ZASJaUf1N0dz2tGdrmwrmlZuNUgxH+wz6Z0zYVH2c5xzQ==",
+			"version": "1.2.2",
+			"resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.2.tgz",
+			"integrity": "sha512-ZZtPLE74KNE+0XcPv/vQmcivxN+8FhwOLvt2udHauO0aDEpsXDQrmd5HuJGpgPVyaV8HvkDPWnJ2iaem0oCKtA==",
 			"dev": true,
 			"requires": {
-				"define-properties": "^1.1.2",
-				"es-abstract": "^1.10.0",
+				"define-properties": "^1.1.3",
+				"es-abstract": "^1.15.0",
 				"function-bind": "^1.1.1"
+			},
+			"dependencies": {
+				"es-abstract": {
+					"version": "1.15.0",
+					"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz",
+					"integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==",
+					"dev": true,
+					"requires": {
+						"es-to-primitive": "^1.2.0",
+						"function-bind": "^1.1.1",
+						"has": "^1.0.3",
+						"has-symbols": "^1.0.0",
+						"is-callable": "^1.1.4",
+						"is-regex": "^1.0.4",
+						"object-inspect": "^1.6.0",
+						"object-keys": "^1.1.1",
+						"string.prototype.trimleft": "^2.1.0",
+						"string.prototype.trimright": "^2.1.0"
+					}
+				},
+				"object-keys": {
+					"version": "1.1.1",
+					"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+					"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+					"dev": true
+				}
 			}
 		},
 		"arraybuffer-to-string": {
@@ -6364,7 +6510,7 @@
 			"dependencies": {
 				"buffer": {
 					"version": "4.9.1",
-					"resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
+					"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz",
 					"integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=",
 					"requires": {
 						"base64-js": "^1.0.2",
@@ -6396,7 +6542,7 @@
 		},
 		"axios": {
 			"version": "0.18.0",
-			"resolved": "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
+			"resolved": "https://registry.npmjs.org/axios/-/axios-0.18.0.tgz",
 			"integrity": "sha1-MtU+SFHv3AoRmTts0AB4nXDAUQI=",
 			"requires": {
 				"follow-redirects": "^1.3.0",
@@ -6481,7 +6627,7 @@
 			"dependencies": {
 				"jsesc": {
 					"version": "1.3.0",
-					"resolved": "http://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
+					"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz",
 					"integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=",
 					"dev": true
 				}
@@ -6796,7 +6942,7 @@
 		},
 		"babel-plugin-add-module-exports": {
 			"version": "0.2.1",
-			"resolved": "http://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz",
 			"integrity": "sha1-mumh9KjcZ/DN7E9K7aHkOl/2XiU=",
 			"dev": true
 		},
@@ -6831,9 +6977,9 @@
 			}
 		},
 		"babel-plugin-emotion": {
-			"version": "10.0.19",
-			"resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.0.19.tgz",
-			"integrity": "sha512-1pJb5uKN/gx6bi3gGr588Krj49sxARI9KmxhtMUa+NRJb6lR3OfC51mh3NlWRsOqdjWlT4cSjnZpnFq5K3T5ZA==",
+			"version": "10.0.21",
+			"resolved": "https://registry.npmjs.org/babel-plugin-emotion/-/babel-plugin-emotion-10.0.21.tgz",
+			"integrity": "sha512-03o+T6sfVAJhNDcSdLapgv4IeewcFPzxlvBUVdSf7o5PI57ZSxoDvmy+ZulVWSu+rOWAWkEejNcsb29TuzJHbg==",
 			"dev": true,
 			"requires": {
 				"@babel/helper-module-imports": "^7.0.0",
@@ -6860,9 +7006,9 @@
 			},
 			"dependencies": {
 				"@babel/runtime": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
-					"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
+					"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"
@@ -7047,78 +7193,78 @@
 		},
 		"babel-plugin-syntax-async-functions": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
 			"integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=",
 			"dev": true
 		},
 		"babel-plugin-syntax-async-generators": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz",
 			"integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=",
 			"dev": true
 		},
 		"babel-plugin-syntax-class-constructor-call": {
 			"version": "6.18.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz",
 			"integrity": "sha1-nLnTn+Q8hgC+yBRkVt3L1OGnZBY=",
 			"dev": true
 		},
 		"babel-plugin-syntax-class-properties": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
 			"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=",
 			"dev": true
 		},
 		"babel-plugin-syntax-decorators": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz",
 			"integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
 			"dev": true
 		},
 		"babel-plugin-syntax-do-expressions": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz",
 			"integrity": "sha1-V0d1YTmqJtOQ0JQQsDdEugfkeW0=",
 			"dev": true
 		},
 		"babel-plugin-syntax-dynamic-import": {
 			"version": "6.18.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
 			"integrity": "sha1-jWomIpyDdFqZgqRBBRVyyqF5sdo=",
 			"dev": true
 		},
 		"babel-plugin-syntax-exponentiation-operator": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz",
 			"integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=",
 			"dev": true
 		},
 		"babel-plugin-syntax-export-extensions": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz",
 			"integrity": "sha1-cKFITw+QiaToStRLrDU8lbmxJyE=",
 			"dev": true
 		},
 		"babel-plugin-syntax-flow": {
 			"version": "6.18.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz",
 			"integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=",
 			"dev": true
 		},
 		"babel-plugin-syntax-function-bind": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz",
 			"integrity": "sha1-SMSV8Xe98xqYHnMvVa3AvdJgH0Y=",
 			"dev": true
 		},
 		"babel-plugin-syntax-jsx": {
 			"version": "6.18.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz",
 			"integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY="
 		},
 		"babel-plugin-syntax-object-rest-spread": {
 			"version": "6.13.0",
-			"resolved": "http://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
+			"resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz",
 			"integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=",
 			"dev": true
 		},
@@ -7593,7 +7739,7 @@
 		},
 		"babel-preset-es2015": {
 			"version": "6.3.13",
-			"resolved": "http://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.3.13.tgz",
+			"resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.3.13.tgz",
 			"integrity": "sha1-l9zn7ykuGMubK3VF2AxZPCjZUX8=",
 			"dev": true,
 			"requires": {
@@ -7652,7 +7798,7 @@
 		},
 		"babel-preset-react": {
 			"version": "6.3.13",
-			"resolved": "http://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.3.13.tgz",
+			"resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.3.13.tgz",
 			"integrity": "sha1-E9VeBqZfqqoHw5v2Op2DbgMhFvo=",
 			"dev": true,
 			"requires": {
@@ -7720,12 +7866,12 @@
 					}
 				},
 				"@babel/generator": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.2.tgz",
-					"integrity": "sha512-j8iHaIW4gGPnViaIHI7e9t/Hl8qLjERI6DcV9kEpAIDJsAOrcnXqRS7t+QbhL76pwbtqP+QCQLL0z1CyVmtjjQ==",
+					"version": "7.6.4",
+					"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.6.4.tgz",
+					"integrity": "sha512-jsBuXkFoZxk0yWLyGI9llT9oiQ2FeTASmRFE32U+aaDTfoE92t78eroO7PTpU/OrYq38hlcDM6vbfLDaOLy+7w==",
 					"dev": true,
 					"requires": {
-						"@babel/types": "^7.6.0",
+						"@babel/types": "^7.6.3",
 						"jsesc": "^2.5.1",
 						"lodash": "^4.17.13",
 						"source-map": "^0.5.0"
@@ -7741,9 +7887,9 @@
 					}
 				},
 				"@babel/parser": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.2.tgz",
-					"integrity": "sha512-mdFqWrSPCmikBoaBYMuBulzTIKuXVPtEISFbRRVNwMWpCms/hmE2kRq0bblUHaNRKrjRlmVbx1sDHmjmRgD2Xg==",
+					"version": "7.6.4",
+					"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.6.4.tgz",
+					"integrity": "sha512-D8RHPW5qd0Vbyo3qb+YjO5nvUVRTXFLQ/FsDxJU2Nqz4uB5EnUN0ZQSEYpvTIbRuttig1XbHWU5oMeQwQSAA+A==",
 					"dev": true
 				},
 				"@babel/plugin-proposal-object-rest-spread": {
@@ -7756,6 +7902,16 @@
 						"@babel/plugin-syntax-object-rest-spread": "^7.2.0"
 					}
 				},
+				"@babel/plugin-transform-flow-strip-types": {
+					"version": "7.4.4",
+					"resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.4.tgz",
+					"integrity": "sha512-WyVedfeEIILYEaWGAUWzVNyqG4sfsNooMhXWsu/YzOvVGcsnPb5PguysjJqI3t3qiaYj0BR8T2f5njdjTGe44Q==",
+					"dev": true,
+					"requires": {
+						"@babel/helper-plugin-utils": "^7.0.0",
+						"@babel/plugin-syntax-flow": "^7.2.0"
+					}
+				},
 				"@babel/preset-env": {
 					"version": "7.6.0",
 					"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.0.tgz",
@@ -7835,26 +7991,26 @@
 					}
 				},
 				"@babel/traverse": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.2.tgz",
-					"integrity": "sha512-8fRE76xNwNttVEF2TwxJDGBLWthUkHWSldmfuBzVRmEDWOtu4XdINTgN7TDWzuLg4bbeIMLvfMFD9we5YcWkRQ==",
+					"version": "7.6.3",
+					"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.6.3.tgz",
+					"integrity": "sha512-unn7P4LGsijIxaAJo/wpoU11zN+2IaClkQAxcJWBNCMS6cmVh802IyLHNkAjQ0iYnRS3nnxk5O3fuXW28IMxTw==",
 					"dev": true,
 					"requires": {
 						"@babel/code-frame": "^7.5.5",
-						"@babel/generator": "^7.6.2",
+						"@babel/generator": "^7.6.3",
 						"@babel/helper-function-name": "^7.1.0",
 						"@babel/helper-split-export-declaration": "^7.4.4",
-						"@babel/parser": "^7.6.2",
-						"@babel/types": "^7.6.0",
+						"@babel/parser": "^7.6.3",
+						"@babel/types": "^7.6.3",
 						"debug": "^4.1.0",
 						"globals": "^11.1.0",
 						"lodash": "^4.17.13"
 					}
 				},
 				"@babel/types": {
-					"version": "7.6.1",
-					"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.1.tgz",
-					"integrity": "sha512-X7gdiuaCmA0uRjCmRtYJNAVCc/q+5xSgsfKJHqMN4iNLILX39677fJE1O40arPMh0TTtS9ItH67yre6c7k6t0g==",
+					"version": "7.6.3",
+					"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.6.3.tgz",
+					"integrity": "sha512-CqbcpTxMcpuQTMhjI37ZHVgjBkysg5icREQIEZ0eG1yCNwg3oy+5AaLiOKmjsCj6nqOsa6Hf0ObjRVwokb7srA==",
 					"dev": true,
 					"requires": {
 						"esutils": "^2.0.2",
@@ -7872,9 +8028,9 @@
 					}
 				},
 				"json5": {
-					"version": "2.1.0",
-					"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz",
-					"integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==",
+					"version": "2.1.1",
+					"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz",
+					"integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==",
 					"dev": true,
 					"requires": {
 						"minimist": "^1.2.0"
@@ -7908,7 +8064,7 @@
 		},
 		"babel-preset-stage-0": {
 			"version": "6.3.13",
-			"resolved": "http://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.3.13.tgz",
+			"resolved": "https://registry.npmjs.org/babel-preset-stage-0/-/babel-preset-stage-0-6.3.13.tgz",
 			"integrity": "sha1-eKN8VvCzmI8qeZMtywzrj/N3sNE=",
 			"dev": true,
 			"requires": {
@@ -8821,7 +8977,7 @@
 		},
 		"bl": {
 			"version": "1.2.2",
-			"resolved": "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
+			"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
 			"integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==",
 			"requires": {
 				"readable-stream": "^2.3.5",
@@ -9086,7 +9242,7 @@
 		},
 		"browserify-aes": {
 			"version": "1.2.0",
-			"resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+			"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
 			"integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
 			"requires": {
 				"buffer-xor": "^1.0.3",
@@ -9120,7 +9276,7 @@
 		},
 		"browserify-rsa": {
 			"version": "4.0.1",
-			"resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
+			"resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz",
 			"integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=",
 			"requires": {
 				"bn.js": "^4.1.0",
@@ -9308,7 +9464,7 @@
 				},
 				"readable-stream": {
 					"version": "1.1.14",
-					"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
 					"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
 					"requires": {
 						"core-util-is": "~1.0.0",
@@ -9420,7 +9576,7 @@
 			"dependencies": {
 				"callsites": {
 					"version": "2.0.0",
-					"resolved": "http://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
+					"resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
 					"integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=",
 					"dev": true
 				}
@@ -9511,7 +9667,7 @@
 			"dependencies": {
 				"cheerio": {
 					"version": "0.19.0",
-					"resolved": "http://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz",
+					"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.19.0.tgz",
 					"integrity": "sha1-dy5wFfLuKZZQltcepBdbdas1SSU=",
 					"requires": {
 						"css-select": "~1.0.0",
@@ -9523,7 +9679,7 @@
 				},
 				"css-select": {
 					"version": "1.0.0",
-					"resolved": "http://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz",
+					"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz",
 					"integrity": "sha1-sRIcpRhI3SZOIkTQWM7iVN7rRLA=",
 					"requires": {
 						"boolbase": "~1.0.0",
@@ -9534,7 +9690,7 @@
 				},
 				"css-what": {
 					"version": "1.0.0",
-					"resolved": "http://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz",
+					"resolved": "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz",
 					"integrity": "sha1-18wt9FGAZm+Z0rFEYmOUaeAPc2w="
 				},
 				"domhandler": {
@@ -9555,7 +9711,7 @@
 				},
 				"htmlparser2": {
 					"version": "3.8.3",
-					"resolved": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
+					"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
 					"integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=",
 					"requires": {
 						"domelementtype": "1",
@@ -9576,7 +9732,7 @@
 						},
 						"entities": {
 							"version": "1.0.0",
-							"resolved": "http://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
+							"resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz",
 							"integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY="
 						}
 					}
@@ -9588,12 +9744,12 @@
 				},
 				"lodash": {
 					"version": "3.10.1",
-					"resolved": "http://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
+					"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
 					"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
 				},
 				"readable-stream": {
 					"version": "1.1.14",
-					"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
 					"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
 					"requires": {
 						"core-util-is": "~1.0.0",
@@ -9604,7 +9760,7 @@
 				},
 				"string_decoder": {
 					"version": "0.10.31",
-					"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+					"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
 					"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
 				}
 			}
@@ -9682,7 +9838,7 @@
 		},
 		"chalk": {
 			"version": "1.1.3",
-			"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+			"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
 			"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
 			"requires": {
 				"ansi-styles": "^2.2.1",
@@ -9756,7 +9912,7 @@
 		},
 		"cheerio": {
 			"version": "0.22.0",
-			"resolved": "http://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
+			"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
 			"integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
 			"requires": {
 				"css-select": "~1.2.0",
@@ -9785,7 +9941,7 @@
 		},
 		"chimp": {
 			"version": "0.51.1",
-			"resolved": "http://registry.npmjs.org/chimp/-/chimp-0.51.1.tgz",
+			"resolved": "https://registry.npmjs.org/chimp/-/chimp-0.51.1.tgz",
 			"integrity": "sha1-6hIbzfJsidV/jvNBlUDPPCeaPMU=",
 			"dev": true,
 			"requires": {
@@ -9831,7 +9987,7 @@
 			"dependencies": {
 				"async": {
 					"version": "0.9.2",
-					"resolved": "http://registry.npmjs.org/async/-/async-0.9.2.tgz",
+					"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
 					"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
 					"dev": true
 				},
@@ -9903,7 +10059,7 @@
 				},
 				"minimist": {
 					"version": "1.2.0",
-					"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+					"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 					"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
 					"dev": true
 				},
@@ -9955,7 +10111,7 @@
 				},
 				"progress": {
 					"version": "1.1.8",
-					"resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
+					"resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
 					"integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=",
 					"dev": true
 				},
@@ -9978,7 +10134,7 @@
 		},
 		"chokidar": {
 			"version": "1.6.1",
-			"resolved": "http://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz",
+			"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.6.1.tgz",
 			"integrity": "sha1-L0RHq16W5Q+z14n9kNTHLg5McMI=",
 			"dev": true,
 			"requires": {
@@ -10377,7 +10533,7 @@
 		},
 		"color-convert": {
 			"version": "0.5.3",
-			"resolved": "http://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
+			"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz",
 			"integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0="
 		},
 		"color-name": {
@@ -10396,7 +10552,7 @@
 		},
 		"colors": {
 			"version": "1.1.2",
-			"resolved": "http://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
+			"resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz",
 			"integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=",
 			"dev": true
 		},
@@ -10638,9 +10794,9 @@
 			}
 		},
 		"core-js-pure": {
-			"version": "3.2.1",
-			"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.2.1.tgz",
-			"integrity": "sha512-+qpvnYrsi/JDeQTArB7NnNc2VoMYLE1YSkziCDHgjexC2KH7OFiGhLUd3urxfyWmNjSwSW7NYXPWHMhuIJx9Ow==",
+			"version": "3.3.2",
+			"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.3.2.tgz",
+			"integrity": "sha512-sw695hB0UxFXrSkUthEby5tMdjOYN3hVC8IGQePF1m3JYb9e/KjT0TOFWzaSzlKwGNglKCgLYUjiJ7uZvactiw==",
 			"dev": true
 		},
 		"core-util-is": {
@@ -10871,9 +11027,9 @@
 					"dev": true
 				},
 				"bluebird": {
-					"version": "3.7.0",
-					"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.0.tgz",
-					"integrity": "sha512-aBQ1FxIa7kSWCcmKHlcHFlT2jt6J/l4FzC7KcPELkOJOsPOb/bccdhmIrKDfXhwFrmc7vDoDrrepFvGqjyXGJg==",
+					"version": "3.7.1",
+					"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.1.tgz",
+					"integrity": "sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg==",
 					"dev": true
 				},
 				"browserify-zlib": {
@@ -10929,9 +11085,9 @@
 					}
 				},
 				"commander": {
-					"version": "2.20.1",
-					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
-					"integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==",
+					"version": "2.20.3",
+					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+					"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
 					"dev": true
 				},
 				"eslint-scope": {
@@ -11148,9 +11304,9 @@
 					"dev": true
 				},
 				"terser": {
-					"version": "4.3.4",
-					"resolved": "https://registry.npmjs.org/terser/-/terser-4.3.4.tgz",
-					"integrity": "sha512-Kcrn3RiW8NtHBP0ssOAzwa2MsIRQ8lJWiBG/K7JgqPlomA3mtb2DEmp4/hrUA+Jujx+WZ02zqd7GYD+QRBB/2Q==",
+					"version": "4.3.8",
+					"resolved": "https://registry.npmjs.org/terser/-/terser-4.3.8.tgz",
+					"integrity": "sha512-otmIRlRVmLChAWsnSFNO0Bfk6YySuBp6G9qrHiJwlLDd4mxe2ta4sjI7TzIR+W1nBMjilzrMcPOz9pSusgx3hQ==",
 					"dev": true,
 					"requires": {
 						"commander": "^2.20.0",
@@ -11218,9 +11374,9 @@
 					"dev": true
 				},
 				"webpack": {
-					"version": "4.41.0",
-					"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.0.tgz",
-					"integrity": "sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g==",
+					"version": "4.41.2",
+					"resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.2.tgz",
+					"integrity": "sha512-Zhw69edTGfbz9/8JJoyRQ/pq8FYUoY0diOXqW0T6yhgdhCv6wr0hra5DwwWexNRns2Z2+gsnrNcbe9hbGBgk/A==",
 					"dev": true,
 					"requires": {
 						"@webassemblyjs/ast": "1.8.5",
@@ -11342,7 +11498,7 @@
 		},
 		"create-hash": {
 			"version": "1.2.0",
-			"resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+			"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",
@@ -11354,7 +11510,7 @@
 		},
 		"create-hmac": {
 			"version": "1.1.7",
-			"resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+			"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",
@@ -11386,7 +11542,7 @@
 			"dependencies": {
 				"node-fetch": {
 					"version": "2.1.2",
-					"resolved": "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz",
+					"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz",
 					"integrity": "sha1-q4hOjn5X44qUR1POxwb3iNF2i7U="
 				}
 			}
@@ -11611,9 +11767,9 @@
 					"dev": true
 				},
 				"schema-utils": {
-					"version": "2.4.1",
-					"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.4.1.tgz",
-					"integrity": "sha512-RqYLpkPZX5Oc3fw/kHHHyP56fg5Y+XBpIpV8nCg0znIALfq3OH+Ea9Hfeac9BAMwG5IICltiZ0vxFvJQONfA5w==",
+					"version": "2.5.0",
+					"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz",
+					"integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==",
 					"dev": true,
 					"requires": {
 						"ajv": "^6.10.2",
@@ -11648,7 +11804,7 @@
 		},
 		"css-select": {
 			"version": "1.2.0",
-			"resolved": "http://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
+			"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
 			"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
 			"requires": {
 				"boolbase": "~1.0.0",
@@ -11741,9 +11897,9 @@
 			}
 		},
 		"csstype": {
-			"version": "2.6.6",
-			"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.6.tgz",
-			"integrity": "sha512-RpFbQGUE74iyPgvr46U9t1xoQBM8T4BL8SxrN66Le2xYAPSaDJJKeztV3awugusb3g3G9iL8StmkBBXhcbbXhg==",
+			"version": "2.6.7",
+			"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.7.tgz",
+			"integrity": "sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ==",
 			"dev": true
 		},
 		"csv-parse": {
@@ -11799,11 +11955,17 @@
 			"dependencies": {
 				"core-js": {
 					"version": "1.2.7",
-					"resolved": "http://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
 					"integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY="
 				}
 			}
 		},
+		"cuint": {
+			"version": "0.2.2",
+			"resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz",
+			"integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=",
+			"dev": true
+		},
 		"currently-unhandled": {
 			"version": "0.4.1",
 			"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
@@ -12201,7 +12363,7 @@
 					"dependencies": {
 						"pify": {
 							"version": "2.3.0",
-							"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+							"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
 							"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
 							"dev": true
 						}
@@ -12294,7 +12456,7 @@
 				},
 				"readable-stream": {
 					"version": "1.1.14",
-					"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
 					"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
 					"requires": {
 						"core-util-is": "~1.0.0",
@@ -12323,7 +12485,7 @@
 		},
 		"diffie-hellman": {
 			"version": "5.0.3",
-			"resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+			"resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
 			"integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
 			"requires": {
 				"bn.js": "^4.1.0",
@@ -12342,7 +12504,7 @@
 		},
 		"doctrine": {
 			"version": "1.5.0",
-			"resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
+			"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
 			"integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
 			"dev": true,
 			"requires": {
@@ -12379,7 +12541,7 @@
 			"dependencies": {
 				"domelementtype": {
 					"version": "1.1.3",
-					"resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
+					"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz",
 					"integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs="
 				}
 			}
@@ -12647,9 +12809,9 @@
 			},
 			"dependencies": {
 				"@babel/runtime": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
-					"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
+					"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"
@@ -12841,7 +13003,7 @@
 		},
 		"es6-promisify": {
 			"version": "5.0.0",
-			"resolved": "http://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+			"resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
 			"integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
 			"requires": {
 				"es6-promise": "^4.0.3"
@@ -13326,7 +13488,7 @@
 		},
 		"events": {
 			"version": "1.1.1",
-			"resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz",
+			"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
 			"integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ="
 		},
 		"eventsource": {
@@ -13564,7 +13726,7 @@
 				},
 				"finalhandler": {
 					"version": "1.1.1",
-					"resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
+					"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz",
 					"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
 					"requires": {
 						"debug": "2.6.9",
@@ -13583,7 +13745,7 @@
 				},
 				"http-errors": {
 					"version": "1.6.3",
-					"resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+					"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
 					"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
 					"requires": {
 						"depd": "~1.1.2",
@@ -13753,7 +13915,7 @@
 		},
 		"external-editor": {
 			"version": "2.2.0",
-			"resolved": "http://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
+			"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
 			"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
 			"dev": true,
 			"requires": {
@@ -13955,13 +14117,13 @@
 			"dependencies": {
 				"lodash": {
 					"version": "2.4.2",
-					"resolved": "http://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
+					"resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz",
 					"integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=",
 					"dev": true
 				},
 				"underscore.string": {
 					"version": "2.3.3",
-					"resolved": "http://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
+					"resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz",
 					"integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=",
 					"dev": true
 				}
@@ -15120,7 +15282,7 @@
 		},
 		"get-stream": {
 			"version": "3.0.0",
-			"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
+			"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
 			"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
 		},
 		"get-value": {
@@ -15369,7 +15531,7 @@
 			"dependencies": {
 				"minimist": {
 					"version": "1.1.3",
-					"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz",
+					"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.3.tgz",
 					"integrity": "sha1-O+39kaktOQFvz6ocaB6Pqhoe/ag=",
 					"dev": true
 				}
@@ -16065,7 +16227,7 @@
 		},
 		"hapi": {
 			"version": "8.8.0",
-			"resolved": "http://registry.npmjs.org/hapi/-/hapi-8.8.0.tgz",
+			"resolved": "https://registry.npmjs.org/hapi/-/hapi-8.8.0.tgz",
 			"integrity": "sha1-h+N6Bum0meiXkOLcERqpZotuYX8=",
 			"dev": true,
 			"requires": {
@@ -16135,7 +16297,7 @@
 				},
 				"catbox": {
 					"version": "4.3.0",
-					"resolved": "http://registry.npmjs.org/catbox/-/catbox-4.3.0.tgz",
+					"resolved": "https://registry.npmjs.org/catbox/-/catbox-4.3.0.tgz",
 					"integrity": "sha1-IiN3vWfxKRrA4l0AAC0GWp3385o=",
 					"dev": true,
 					"requires": {
@@ -16232,7 +16394,7 @@
 				},
 				"joi": {
 					"version": "6.4.1",
-					"resolved": "http://registry.npmjs.org/joi/-/joi-6.4.1.tgz",
+					"resolved": "https://registry.npmjs.org/joi/-/joi-6.4.1.tgz",
 					"integrity": "sha1-9Q9CRTVgBo5jg9oVrC0w3Xzra24=",
 					"dev": true,
 					"requires": {
@@ -16244,7 +16406,7 @@
 					"dependencies": {
 						"isemail": {
 							"version": "1.1.1",
-							"resolved": "http://registry.npmjs.org/isemail/-/isemail-1.1.1.tgz",
+							"resolved": "https://registry.npmjs.org/isemail/-/isemail-1.1.1.tgz",
 							"integrity": "sha1-4Mj23D9HCX53dzlcaJYnGqJWw7U=",
 							"dev": true
 						},
@@ -16277,7 +16439,7 @@
 					"dependencies": {
 						"mime-db": {
 							"version": "1.14.0",
-							"resolved": "http://registry.npmjs.org/mime-db/-/mime-db-1.14.0.tgz",
+							"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.14.0.tgz",
 							"integrity": "sha1-1WHxC27mbbUflK5leilRp0IX7YM=",
 							"dev": true
 						}
@@ -16678,9 +16840,9 @@
 			},
 			"dependencies": {
 				"commander": {
-					"version": "2.20.1",
-					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
-					"integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==",
+					"version": "2.20.3",
+					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+					"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
 					"dev": true
 				},
 				"source-map": {
@@ -16690,13 +16852,21 @@
 					"dev": true
 				},
 				"uglify-js": {
-					"version": "3.6.0",
-					"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
-					"integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==",
+					"version": "3.6.1",
+					"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.1.tgz",
+					"integrity": "sha512-+dSJLJpXBb6oMHP+Yvw8hUgElz4gLTh82XuX68QiJVTXaE5ibl6buzhNkQdYhBlIhozWOC9ge16wyRmjG4TwVQ==",
 					"dev": true,
 					"requires": {
-						"commander": "~2.20.0",
+						"commander": "2.20.0",
 						"source-map": "~0.6.1"
+					},
+					"dependencies": {
+						"commander": {
+							"version": "2.20.0",
+							"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
+							"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
+							"dev": true
+						}
 					}
 				}
 			}
@@ -16787,7 +16957,7 @@
 			"dependencies": {
 				"domelementtype": {
 					"version": "1.3.0",
-					"resolved": "http://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
+					"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz",
 					"integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI="
 				},
 				"readable-stream": {
@@ -16804,7 +16974,7 @@
 		},
 		"http-errors": {
 			"version": "1.6.3",
-			"resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+			"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
 			"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
 			"requires": {
 				"depd": "~1.1.2",
@@ -17242,7 +17412,7 @@
 				},
 				"readable-stream": {
 					"version": "1.1.14",
-					"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
 					"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
 					"requires": {
 						"core-util-is": "~1.0.0",
@@ -17602,7 +17772,7 @@
 		},
 		"is-builtin-module": {
 			"version": "1.0.0",
-			"resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
+			"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
 			"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
 			"dev": true,
 			"requires": {
@@ -17779,7 +17949,7 @@
 		},
 		"is-obj": {
 			"version": "1.0.1",
-			"resolved": "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+			"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
 			"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
 		},
 		"is-object": {
@@ -17957,7 +18127,7 @@
 		},
 		"isemail": {
 			"version": "1.2.0",
-			"resolved": "http://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
+			"resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
 			"integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo="
 		},
 		"isexe": {
@@ -18010,7 +18180,7 @@
 		},
 		"jasmine-core": {
 			"version": "2.99.1",
-			"resolved": "http://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
+			"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-2.99.1.tgz",
 			"integrity": "sha1-5kAN8ea1bhMLYcS80JPap/boyhU=",
 			"dev": true
 		},
@@ -18221,12 +18391,12 @@
 		},
 		"json5": {
 			"version": "0.5.1",
-			"resolved": "http://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
+			"resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
 			"integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE="
 		},
 		"jsonfile": {
 			"version": "2.4.0",
-			"resolved": "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
+			"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
 			"integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
 			"dev": true,
 			"requires": {
@@ -18469,18 +18639,18 @@
 			},
 			"dependencies": {
 				"@babel/runtime": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
-					"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
+					"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"
 					}
 				},
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				},
 				"dotenv": {
@@ -18605,7 +18775,7 @@
 				},
 				"promise": {
 					"version": "6.1.0",
-					"resolved": "http://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
+					"resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz",
 					"integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=",
 					"optional": true,
 					"requires": {
@@ -18837,7 +19007,7 @@
 		},
 		"load-json-file": {
 			"version": "2.0.0",
-			"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
+			"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
 			"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
 			"dev": true,
 			"requires": {
@@ -18849,7 +19019,7 @@
 			"dependencies": {
 				"pify": {
 					"version": "2.3.0",
-					"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
 					"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
 					"dev": true
 				}
@@ -19412,7 +19582,7 @@
 		},
 		"media-typer": {
 			"version": "0.3.0",
-			"resolved": "http://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+			"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
 			"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
 		},
 		"mem": {
@@ -19658,6 +19828,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",
@@ -19777,7 +19981,7 @@
 				},
 				"readable-stream": {
 					"version": "2.3.6",
-					"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+					"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",
@@ -19799,7 +20003,7 @@
 				},
 				"string_decoder": {
 					"version": "1.1.1",
-					"resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+					"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"
@@ -19834,6 +20038,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",
@@ -19995,7 +20210,7 @@
 		},
 		"minimist": {
 			"version": "0.0.8",
-			"resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+			"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
 			"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
 		},
 		"minimist-options": {
@@ -20101,7 +20316,7 @@
 		},
 		"mkdirp": {
 			"version": "0.5.1",
-			"resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
 			"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
 			"requires": {
 				"minimist": "0.0.8"
@@ -20134,7 +20349,7 @@
 				},
 				"commander": {
 					"version": "2.15.1",
-					"resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+					"resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
 					"integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
 					"dev": true
 				},
@@ -20482,7 +20697,7 @@
 		},
 		"ncp": {
 			"version": "2.0.0",
-			"resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
+			"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
 			"integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
 			"optional": true
 		},
@@ -20858,7 +21073,7 @@
 		},
 		"npm-install-package": {
 			"version": "2.1.0",
-			"resolved": "http://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz",
+			"resolved": "https://registry.npmjs.org/npm-install-package/-/npm-install-package-2.1.0.tgz",
 			"integrity": "sha1-1+/jz816sAYUuJbqUxGdyaslkSU=",
 			"dev": true
 		},
@@ -21139,7 +21354,7 @@
 		},
 		"os-locale": {
 			"version": "1.4.0",
-			"resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
+			"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
 			"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
 			"requires": {
 				"lcid": "^1.0.0"
@@ -21229,7 +21444,7 @@
 		},
 		"pako": {
 			"version": "0.2.9",
-			"resolved": "http://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
+			"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
 			"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
 		},
 		"parallel-transform": {
@@ -21254,7 +21469,7 @@
 		},
 		"parse-asn1": {
 			"version": "5.1.1",
-			"resolved": "http://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
+			"resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.1.tgz",
 			"integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==",
 			"requires": {
 				"asn1.js": "^4.0.0",
@@ -21481,7 +21696,7 @@
 				},
 				"es6-promise": {
 					"version": "4.0.5",
-					"resolved": "http://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz",
+					"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz",
 					"integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI=",
 					"dev": true
 				},
@@ -21537,7 +21752,7 @@
 				},
 				"progress": {
 					"version": "1.1.8",
-					"resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
+					"resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
 					"integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=",
 					"dev": true
 				},
@@ -21585,7 +21800,7 @@
 				},
 				"tough-cookie": {
 					"version": "2.3.4",
-					"resolved": "http://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
+					"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz",
 					"integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==",
 					"dev": true,
 					"requires": {
@@ -21818,9 +22033,9 @@
 			},
 			"dependencies": {
 				"@babel/runtime": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
-					"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
+					"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"
@@ -22003,7 +22218,7 @@
 				},
 				"globby": {
 					"version": "6.1.0",
-					"resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
+					"resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
 					"integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=",
 					"dev": true,
 					"requires": {
@@ -22016,7 +22231,7 @@
 					"dependencies": {
 						"pify": {
 							"version": "2.3.0",
-							"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+							"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
 							"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
 							"dev": true
 						}
@@ -22486,6 +22701,19 @@
 			"integrity": "sha512-L36NZwq2UK743US+vl1CRMdBRZCBmFYfThP9n9jCFhX1Wfk6BqnRSgt0Fy8q44IwxPee/GCzlo7T1c1JIeUDlQ==",
 			"dev": true
 		},
+		"postcss-url": {
+			"version": "8.0.0",
+			"resolved": "https://registry.npmjs.org/postcss-url/-/postcss-url-8.0.0.tgz",
+			"integrity": "sha512-E2cbOQ5aii2zNHh8F6fk1cxls7QVFZjLPSrqvmiza8OuXLzIpErij8BDS5Y3STPfJgpIMNCPEr8JlKQWEoozUw==",
+			"dev": true,
+			"requires": {
+				"mime": "^2.3.1",
+				"minimatch": "^3.0.4",
+				"mkdirp": "^0.5.0",
+				"postcss": "^7.0.2",
+				"xxhashjs": "^0.2.1"
+			}
+		},
 		"postcss-value-parser": {
 			"version": "3.3.1",
 			"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
@@ -22848,9 +23076,9 @@
 			},
 			"dependencies": {
 				"es-abstract": {
-					"version": "1.14.2",
-					"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.2.tgz",
-					"integrity": "sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg==",
+					"version": "1.15.0",
+					"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz",
+					"integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==",
 					"dev": true,
 					"requires": {
 						"es-to-primitive": "^1.2.0",
@@ -22861,8 +23089,8 @@
 						"is-regex": "^1.0.4",
 						"object-inspect": "^1.6.0",
 						"object-keys": "^1.1.1",
-						"string.prototype.trimleft": "^2.0.0",
-						"string.prototype.trimright": "^2.0.0"
+						"string.prototype.trimleft": "^2.1.0",
+						"string.prototype.trimright": "^2.1.0"
 					}
 				},
 				"object-keys": {
@@ -22885,9 +23113,9 @@
 			},
 			"dependencies": {
 				"es-abstract": {
-					"version": "1.14.2",
-					"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.14.2.tgz",
-					"integrity": "sha512-DgoQmbpFNOofkjJtKwr87Ma5EW4Dc8fWhD0R+ndq7Oc456ivUfGOOP6oAZTTKl5/CcNMP+EN+e3/iUzgE0veZg==",
+					"version": "1.15.0",
+					"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz",
+					"integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==",
 					"dev": true,
 					"requires": {
 						"es-to-primitive": "^1.2.0",
@@ -22898,8 +23126,8 @@
 						"is-regex": "^1.0.4",
 						"object-inspect": "^1.6.0",
 						"object-keys": "^1.1.1",
-						"string.prototype.trimleft": "^2.0.0",
-						"string.prototype.trimright": "^2.0.0"
+						"string.prototype.trimleft": "^2.1.0",
+						"string.prototype.trimright": "^2.1.0"
 					}
 				},
 				"object-keys": {
@@ -22921,9 +23149,9 @@
 			}
 		},
 		"property-information": {
-			"version": "5.2.2",
-			"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.2.2.tgz",
-			"integrity": "sha512-N2moasZmjn2mjVGIWpaqz5qnz6QyeQSGgGvMtl81gA9cPTWa6wpesRSe/quNnOjUHpvSH1oZx0pdz0EEckLFnA==",
+			"version": "5.3.0",
+			"resolved": "https://registry.npmjs.org/property-information/-/property-information-5.3.0.tgz",
+			"integrity": "sha512-IslotQn1hBCZDY7SaJ3zmCjVea219VTwmOk6Pu3z9haU9m4+T8GwaDubur+6NMHEU+Fjs/6/p66z6QULPkcL1w==",
 			"dev": true,
 			"requires": {
 				"xtend": "^4.0.1"
@@ -23099,15 +23327,6 @@
 			"integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=",
 			"dev": true
 		},
-		"raf": {
-			"version": "3.4.1",
-			"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
-			"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
-			"dev": true,
-			"requires": {
-				"performance-now": "^2.1.0"
-			}
-		},
 		"ramda": {
 			"version": "0.21.0",
 			"resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz",
@@ -23218,7 +23437,7 @@
 			"dependencies": {
 				"minimist": {
 					"version": "1.2.0",
-					"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+					"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 					"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
 				}
 			}
@@ -23258,9 +23477,9 @@
 			}
 		},
 		"react-dev-utils": {
-			"version": "9.0.4",
-			"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-9.0.4.tgz",
-			"integrity": "sha512-VwR+mBUXPLdYk/rOz6s6qpasIFGd7GW0KXd/3bih+/qGcMQvPG19XxtjDMtiAg0zWiFwp1ugCzAjLThbzFjVqw==",
+			"version": "9.1.0",
+			"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-9.1.0.tgz",
+			"integrity": "sha512-X2KYF/lIGyGwP/F/oXgGDF24nxDA2KC4b7AFto+eqzc/t838gpSGiaU8trTqHXOohuLxxc5qi1eDzsl9ucPDpg==",
 			"dev": true,
 			"requires": {
 				"@babel/code-frame": "7.5.5",
@@ -23282,7 +23501,7 @@
 				"loader-utils": "1.2.3",
 				"open": "^6.3.0",
 				"pkg-up": "2.0.0",
-				"react-error-overlay": "^6.0.2",
+				"react-error-overlay": "^6.0.3",
 				"recursive-readdir": "2.2.2",
 				"shell-quote": "1.7.2",
 				"sockjs-client": "1.4.0",
@@ -23380,9 +23599,9 @@
 					}
 				},
 				"electron-to-chromium": {
-					"version": "1.3.272",
-					"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.272.tgz",
-					"integrity": "sha512-TjsDKYOZGgaD8tUJtRiiBNlIrv2Ol6SxNMy4yeTX0goRmoBhV941m4EN8QjA3vfshs16F5KLDyUv2m7GdTqIgg==",
+					"version": "1.3.282",
+					"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.282.tgz",
+					"integrity": "sha512-irSaDeCGgfMu1OA30bhqIBr+dx+pDJjRbwCpob7YWqVZbzXblybNzPGklVnWqv4EXxbkEAzQYqiNCqNTgu00lQ==",
 					"dev": true
 				},
 				"external-editor": {
@@ -23500,12 +23719,12 @@
 					"dev": true
 				},
 				"node-releases": {
-					"version": "1.1.33",
-					"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.33.tgz",
-					"integrity": "sha512-I0V30bWQEoHb+10W8oedVoUrdjW5wIkYm0w7vvcrPO95pZY738m1k77GF5sO0vKg5eXYg9oGtrMAETbgZGm11A==",
+					"version": "1.1.35",
+					"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.35.tgz",
+					"integrity": "sha512-JGcM/wndCN/2elJlU0IGdVEJQQnJwsLbgPCFd2pY7V0mxf17bZ0Gb/lgOtL29ZQhvEX5shnVhxQyZz3ex94N8w==",
 					"dev": true,
 					"requires": {
-						"semver": "^5.3.0"
+						"semver": "^6.3.0"
 					}
 				},
 				"rxjs": {
@@ -23517,6 +23736,12 @@
 						"tslib": "^1.9.0"
 					}
 				},
+				"semver": {
+					"version": "6.3.0",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+					"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+					"dev": true
+				},
 				"string-width": {
 					"version": "2.1.1",
 					"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
@@ -23588,9 +23813,9 @@
 					"dev": true
 				},
 				"commander": {
-					"version": "2.20.1",
-					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
-					"integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==",
+					"version": "2.20.3",
+					"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+					"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
 					"dev": true
 				},
 				"doctrine": {
@@ -23640,9 +23865,9 @@
 			}
 		},
 		"react-draggable": {
-			"version": "3.3.2",
-			"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-3.3.2.tgz",
-			"integrity": "sha512-oaz8a6enjbPtx5qb0oDWxtDNuybOylvto1QLydsXgKmwT7e3GXC2eMVDwEMIUYJIFqVG72XpOv673UuuAq6LhA==",
+			"version": "4.0.3",
+			"resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.0.3.tgz",
+			"integrity": "sha512-4vD6zms+9QGeZ2RQXzlUBw8PBYUXy+dzYX5r22idjp9YwQKIIvD/EojL0rbjS1GK4C3P0rAJnmKa8gDQYWUDyA==",
 			"dev": true,
 			"requires": {
 				"classnames": "^2.2.5",
@@ -23650,9 +23875,9 @@
 			}
 		},
 		"react-error-overlay": {
-			"version": "6.0.2",
-			"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.2.tgz",
-			"integrity": "sha512-DHRuRk3K4Lg9obI6J4Y+nKvtwjasYRU9CFL3ud42x9YJG1HbQjSNublapC/WBJOA726gNUbqbj0U2df9+uzspQ==",
+			"version": "6.0.3",
+			"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.3.tgz",
+			"integrity": "sha512-bOUvMWFQVk5oz8Ded9Xb7WVdEi3QGLC8tH7HmYP0Fdp4Bn3qw0tRFmr5TW6mvahzvmrK4a6bqWGfCevBflP+Xw==",
 			"dev": true
 		},
 		"react-fast-compare": {
@@ -23773,19 +23998,19 @@
 			}
 		},
 		"react-popper-tooltip": {
-			"version": "2.8.3",
-			"resolved": "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-2.8.3.tgz",
-			"integrity": "sha512-g5tfxmuj8ClNVwH4zswYJcD3GKoc5RMeRawd/WZnbyZGEDecsRKaVL+Kj7L3BG7w5qb6/MHcLTG8yE4CidwezQ==",
+			"version": "2.9.1",
+			"resolved": "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-2.9.1.tgz",
+			"integrity": "sha512-LSbvXLEQlNKWig2GMKQW/1bBwCkWIr9cpJ+WJpSGGGhX45CthRtwyilPPLJQkc3qI6UMTAXPp0Fe/pj9E77trg==",
 			"dev": true,
 			"requires": {
-				"@babel/runtime": "^7.4.5",
-				"react-popper": "^1.3.3"
+				"@babel/runtime": "^7.6.3",
+				"react-popper": "^1.3.4"
 			},
 			"dependencies": {
 				"@babel/runtime": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
-					"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
+					"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"
@@ -23800,27 +24025,25 @@
 			}
 		},
 		"react-select": {
-			"version": "3.0.7",
-			"resolved": "https://registry.npmjs.org/react-select/-/react-select-3.0.7.tgz",
-			"integrity": "sha512-m4DKFUGvjjghxovuo4NyGltq/qPwFV5LV1Bo8wl1tUt1UQZO0Lvru1yC62wkTsittf5A+k4gyM4c+MhfEiERSQ==",
+			"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",
-				"classnames": "^2.2.5",
 				"memoize-one": "^5.0.0",
 				"prop-types": "^15.6.0",
-				"raf": "^3.4.0",
 				"react-input-autosize": "^2.2.2",
 				"react-transition-group": "^2.2.1"
 			},
 			"dependencies": {
 				"@babel/runtime": {
-					"version": "7.6.2",
-					"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.2.tgz",
-					"integrity": "sha512-EXxN64agfUqqIGeEjI5dL5z0Sw0ZwWo1mLTi4mQowCZ42O59b7DRpZAnTC6OqdF28wMBMFKNb/4uFGrVaigSpg==",
+					"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"
@@ -23835,9 +24058,9 @@
 			}
 		},
 		"react-sizeme": {
-			"version": "2.6.7",
-			"resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-2.6.7.tgz",
-			"integrity": "sha512-xCjPoBP5jmeW58TxIkcviMZqabZis7tTvDFWf0/Wa5XCgVWQTIe74NQBes2N1Kmp64GRLkpm60BaP0kk+v8aCQ==",
+			"version": "2.6.8",
+			"resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-2.6.8.tgz",
+			"integrity": "sha512-eJKHV226d/S3st2He7bLIlY7FAmi2ItvZmUCmLLNjIvYjtiv58BksuFhTBQmvAxWaXZGb3Ao/44wfAS1voRdjA==",
 			"dev": true,
 			"requires": {
 				"element-resize-detector": "^1.1.15",
@@ -23909,7 +24132,7 @@
 			"dependencies": {
 				"pify": {
 					"version": "2.3.0",
-					"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
 					"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
 					"dev": true
 				}
@@ -23943,7 +24166,7 @@
 				},
 				"pify": {
 					"version": "2.3.0",
-					"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+					"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
 					"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
 					"dev": true
 				}
@@ -24006,7 +24229,7 @@
 		},
 		"readable-stream": {
 			"version": "2.3.6",
-			"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
+			"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",
@@ -24191,7 +24414,7 @@
 		},
 		"regjsgen": {
 			"version": "0.2.0",
-			"resolved": "http://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
+			"resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz",
 			"integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=",
 			"dev": true
 		},
@@ -24396,7 +24619,7 @@
 		},
 		"requestretry": {
 			"version": "1.5.0",
-			"resolved": "http://registry.npmjs.org/requestretry/-/requestretry-1.5.0.tgz",
+			"resolved": "https://registry.npmjs.org/requestretry/-/requestretry-1.5.0.tgz",
 			"integrity": "sha1-7RV7ulNSbt6z7DKo5wSkmYvs5ic=",
 			"dev": true,
 			"requires": {
@@ -24534,7 +24757,7 @@
 		},
 		"rimraf": {
 			"version": "2.4.5",
-			"resolved": "http://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
+			"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz",
 			"integrity": "sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto=",
 			"requires": {
 				"glob": "^6.0.1"
@@ -24629,7 +24852,7 @@
 		},
 		"safe-regex": {
 			"version": "1.1.0",
-			"resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
+			"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
 			"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
 			"requires": {
 				"ret": "~0.1.10"
@@ -24660,7 +24883,7 @@
 		},
 		"sax": {
 			"version": "1.2.1",
-			"resolved": "http://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
+			"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
 			"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
 		},
 		"scandirectory": {
@@ -24693,7 +24916,7 @@
 			"dependencies": {
 				"async": {
 					"version": "1.5.2",
-					"resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz",
+					"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
 					"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
 				}
 			}
@@ -24778,7 +25001,7 @@
 				},
 				"minimist": {
 					"version": "1.2.0",
-					"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
+					"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
 					"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
 					"dev": true
 				},
@@ -24975,7 +25198,7 @@
 		},
 		"sha.js": {
 			"version": "2.4.11",
-			"resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+			"resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
 			"integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
 			"requires": {
 				"inherits": "^2.0.1",
@@ -25151,9 +25374,9 @@
 			},
 			"dependencies": {
 				"core-js": {
-					"version": "3.2.1",
-					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz",
-					"integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==",
+					"version": "3.3.2",
+					"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.2.tgz",
+					"integrity": "sha512-S1FfZpeBchkhyoY76YAdFzKS4zz9aOK7EeFaNA2aJlyXyA+sgqz6xdxmLPGXEAf0nF44MVN1kSjrA9Kt3ATDQg==",
 					"dev": true
 				}
 			}
@@ -25654,7 +25877,7 @@
 		},
 		"stream-browserify": {
 			"version": "2.0.1",
-			"resolved": "http://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
+			"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.1.tgz",
 			"integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=",
 			"requires": {
 				"inherits": "~2.0.1",
@@ -25686,7 +25909,7 @@
 		},
 		"stream-http": {
 			"version": "2.8.1",
-			"resolved": "http://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz",
+			"resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.1.tgz",
 			"integrity": "sha512-cQ0jo17BLca2r0GfRdZKYAGLU6JRoIWxqSOakUMuKOT6MOK7AAlE856L33QuDmAy/eeOrhLee3dZKX0Uadu93A==",
 			"requires": {
 				"builtin-status-codes": "^3.0.0",
@@ -25742,16 +25965,42 @@
 			}
 		},
 		"string.prototype.matchall": {
-			"version": "3.0.1",
-			"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-3.0.1.tgz",
-			"integrity": "sha512-NSiU0ILQr9PQ1SZmM1X327U5LsM+KfDTassJfqN1al1+0iNpKzmQ4BfXOJwRnTEqv8nKJ67mFpqRoPaGWwvy5A==",
+			"version": "3.0.2",
+			"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-3.0.2.tgz",
+			"integrity": "sha512-hsRe42jQ8+OJej2GVjhnSVodQ3NQgHV0FDD6dW7ZTM22J4uIbuYiAADCCc1tfyN7ocEl/KUUbudM36E2tZcF8w==",
 			"dev": true,
 			"requires": {
 				"define-properties": "^1.1.3",
-				"es-abstract": "^1.12.0",
+				"es-abstract": "^1.14.2",
 				"function-bind": "^1.1.1",
 				"has-symbols": "^1.0.0",
 				"regexp.prototype.flags": "^1.2.0"
+			},
+			"dependencies": {
+				"es-abstract": {
+					"version": "1.15.0",
+					"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.15.0.tgz",
+					"integrity": "sha512-bhkEqWJ2t2lMeaJDuk7okMkJWI/yqgH/EoGwpcvv0XW9RWQsRspI4wt6xuyuvMvvQE3gg/D9HXppgk21w78GyQ==",
+					"dev": true,
+					"requires": {
+						"es-to-primitive": "^1.2.0",
+						"function-bind": "^1.1.1",
+						"has": "^1.0.3",
+						"has-symbols": "^1.0.0",
+						"is-callable": "^1.1.4",
+						"is-regex": "^1.0.4",
+						"object-inspect": "^1.6.0",
+						"object-keys": "^1.1.1",
+						"string.prototype.trimleft": "^2.1.0",
+						"string.prototype.trimright": "^2.1.0"
+					}
+				},
+				"object-keys": {
+					"version": "1.1.1",
+					"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+					"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+					"dev": true
+				}
 			}
 		},
 		"string.prototype.padend": {
@@ -25834,7 +26083,7 @@
 		},
 		"strip-ansi": {
 			"version": "3.0.1",
-			"resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
 			"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
 			"requires": {
 				"ansi-regex": "^2.0.0"
@@ -25857,7 +26106,7 @@
 		},
 		"strip-eof": {
 			"version": "1.0.0",
-			"resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
+			"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
 			"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
 		},
 		"strip-indent": {
@@ -26515,18 +26764,33 @@
 			}
 		},
 		"telejson": {
-			"version": "2.2.2",
-			"resolved": "https://registry.npmjs.org/telejson/-/telejson-2.2.2.tgz",
-			"integrity": "sha512-YyNwnKY0ilabOwYgC/J754En1xOe5PBIUIw+C9e0+5HjVVcnQE5/gdu2yET2pmSbp5bxIDqYNjvndj2PUkIiYA==",
+			"version": "3.0.3",
+			"resolved": "https://registry.npmjs.org/telejson/-/telejson-3.0.3.tgz",
+			"integrity": "sha512-gUOh6wox1zJjbGMg+e26NquZcp/F18EbIaqVvjiGqikRqVB4fYEAM8Nyin8smgwX30XhaRBOg+kCj4vInmvwAg==",
 			"dev": true,
 			"requires": {
-				"global": "^4.3.2",
+				"@types/is-function": "^1.0.0",
+				"global": "^4.4.0",
 				"is-function": "^1.0.1",
 				"is-regex": "^1.0.4",
 				"is-symbol": "^1.0.2",
-				"isobject": "^3.0.1",
-				"lodash": "^4.17.11",
+				"isobject": "^4.0.0",
+				"lodash": "^4.17.15",
 				"memoizerific": "^1.11.3"
+			},
+			"dependencies": {
+				"isobject": {
+					"version": "4.0.0",
+					"resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz",
+					"integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==",
+					"dev": true
+				},
+				"lodash": {
+					"version": "4.17.15",
+					"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+					"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+					"dev": true
+				}
 			}
 		},
 		"term-size": {
@@ -26660,7 +26924,7 @@
 		},
 		"through": {
 			"version": "2.3.8",
-			"resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz",
+			"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
 			"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
 			"dev": true
 		},
@@ -26884,7 +27148,7 @@
 			"dependencies": {
 				"progress": {
 					"version": "1.1.8",
-					"resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
+					"resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz",
 					"integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74="
 				}
 			}
@@ -27449,14 +27713,14 @@
 			"integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA=="
 		},
 		"url-loader": {
-			"version": "2.1.0",
-			"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.1.0.tgz",
-			"integrity": "sha512-kVrp/8VfEm5fUt+fl2E0FQyrpmOYgMEkBsv8+UDP1wFhszECq5JyGF33I7cajlVY90zRZ6MyfgKXngLvHYZX8A==",
+			"version": "2.2.0",
+			"resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.2.0.tgz",
+			"integrity": "sha512-G8nk3np8ZAnwhHXas1JxJEwJyQdqFXAKJehfgZ/XrC48volFBRtO+FIKtF2u0Ma3bw+4vnDVjHPAQYlF9p2vsw==",
 			"dev": true,
 			"requires": {
 				"loader-utils": "^1.2.3",
 				"mime": "^2.4.4",
-				"schema-utils": "^2.0.0"
+				"schema-utils": "^2.4.1"
 			},
 			"dependencies": {
 				"ajv": {
@@ -27516,9 +27780,9 @@
 					"dev": true
 				},
 				"schema-utils": {
-					"version": "2.4.1",
-					"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.4.1.tgz",
-					"integrity": "sha512-RqYLpkPZX5Oc3fw/kHHHyP56fg5Y+XBpIpV8nCg0znIALfq3OH+Ea9Hfeac9BAMwG5IICltiZ0vxFvJQONfA5w==",
+					"version": "2.5.0",
+					"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz",
+					"integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==",
 					"dev": true,
 					"requires": {
 						"ajv": "^6.10.2",
@@ -27580,14 +27844,14 @@
 			"dependencies": {
 				"semver": {
 					"version": "5.3.0",
-					"resolved": "http://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
+					"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
 					"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
 				}
 			}
 		},
 		"util": {
 			"version": "0.10.3",
-			"resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz",
+			"resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
 			"integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=",
 			"requires": {
 				"inherits": "2.0.1"
@@ -27642,7 +27906,7 @@
 		},
 		"valid-data-url": {
 			"version": "0.1.6",
-			"resolved": "http://registry.npmjs.org/valid-data-url/-/valid-data-url-0.1.6.tgz",
+			"resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-0.1.6.tgz",
 			"integrity": "sha512-FXg2qXMzfAhZc0y2HzELNfUeiOjPr+52hU1DNBWiJJ2luXD+dD1R9NA48Ug5aj0ibbxroeGDc/RJv6ThiGgkDw=="
 		},
 		"validate-npm-package-license": {
@@ -28215,7 +28479,7 @@
 		},
 		"whatwg-fetch": {
 			"version": "2.0.4",
-			"resolved": "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
+			"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz",
 			"integrity": "sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng=="
 		},
 		"whatwg-mimetype": {
@@ -28362,7 +28626,7 @@
 		},
 		"wrap-ansi": {
 			"version": "2.1.0",
-			"resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
+			"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
 			"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
 			"requires": {
 				"string-width": "^1.0.1",
@@ -28449,7 +28713,7 @@
 			"dependencies": {
 				"xmlbuilder": {
 					"version": "9.0.7",
-					"resolved": "http://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
+					"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
 					"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
 				}
 			}
@@ -28466,7 +28730,7 @@
 		},
 		"xolvio-ddp": {
 			"version": "0.12.3",
-			"resolved": "http://registry.npmjs.org/xolvio-ddp/-/xolvio-ddp-0.12.3.tgz",
+			"resolved": "https://registry.npmjs.org/xolvio-ddp/-/xolvio-ddp-0.12.3.tgz",
 			"integrity": "sha1-NqarlhKyQLWg0cCoNJCK8XwLjwI=",
 			"dev": true,
 			"requires": {
@@ -28491,7 +28755,7 @@
 				},
 				"async": {
 					"version": "0.9.2",
-					"resolved": "http://registry.npmjs.org/async/-/async-0.9.2.tgz",
+					"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
 					"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=",
 					"dev": true
 				},
@@ -28503,7 +28767,7 @@
 				},
 				"bl": {
 					"version": "0.9.5",
-					"resolved": "http://registry.npmjs.org/bl/-/bl-0.9.5.tgz",
+					"resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz",
 					"integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=",
 					"dev": true,
 					"requires": {
@@ -28512,7 +28776,7 @@
 				},
 				"bluebird": {
 					"version": "2.11.0",
-					"resolved": "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
+					"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz",
 					"integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=",
 					"dev": true
 				},
@@ -28524,7 +28788,7 @@
 				},
 				"combined-stream": {
 					"version": "0.0.7",
-					"resolved": "http://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz",
+					"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz",
 					"integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=",
 					"dev": true,
 					"requires": {
@@ -28545,7 +28809,7 @@
 				},
 				"form-data": {
 					"version": "0.2.0",
-					"resolved": "http://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz",
+					"resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz",
 					"integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=",
 					"dev": true,
 					"requires": {
@@ -28585,13 +28849,13 @@
 				},
 				"mime-db": {
 					"version": "1.12.0",
-					"resolved": "http://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz",
+					"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz",
 					"integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=",
 					"dev": true
 				},
 				"mime-types": {
 					"version": "2.0.14",
-					"resolved": "http://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz",
+					"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz",
 					"integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=",
 					"dev": true,
 					"requires": {
@@ -28618,7 +28882,7 @@
 				},
 				"readable-stream": {
 					"version": "1.0.34",
-					"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
+					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
 					"integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=",
 					"dev": true,
 					"requires": {
@@ -28630,7 +28894,7 @@
 				},
 				"request": {
 					"version": "2.53.0",
-					"resolved": "http://registry.npmjs.org/request/-/request-2.53.0.tgz",
+					"resolved": "https://registry.npmjs.org/request/-/request-2.53.0.tgz",
 					"integrity": "sha1-GAo66St7Y5gC5PlUXdj83rcddgw=",
 					"dev": true,
 					"requires": {
@@ -28669,7 +28933,7 @@
 		},
 		"xolvio-fiber-utils": {
 			"version": "2.0.3",
-			"resolved": "http://registry.npmjs.org/xolvio-fiber-utils/-/xolvio-fiber-utils-2.0.3.tgz",
+			"resolved": "https://registry.npmjs.org/xolvio-fiber-utils/-/xolvio-fiber-utils-2.0.3.tgz",
 			"integrity": "sha1-vsjXDHQGGjFjFbun0w0lyz6C3FA=",
 			"dev": true,
 			"requires": {
@@ -28687,7 +28951,7 @@
 		},
 		"xolvio-jasmine-expect": {
 			"version": "1.1.0",
-			"resolved": "http://registry.npmjs.org/xolvio-jasmine-expect/-/xolvio-jasmine-expect-1.1.0.tgz",
+			"resolved": "https://registry.npmjs.org/xolvio-jasmine-expect/-/xolvio-jasmine-expect-1.1.0.tgz",
 			"integrity": "sha1-vCud1ghCMR8EV59agtzqaisxnH0=",
 			"dev": true,
 			"requires": {
@@ -28737,6 +29001,15 @@
 			"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
 			"integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
 		},
+		"xxhashjs": {
+			"version": "0.2.2",
+			"resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz",
+			"integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==",
+			"dev": true,
+			"requires": {
+				"cuint": "^0.2.2"
+			}
+		},
 		"y18n": {
 			"version": "3.2.1",
 			"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
@@ -28754,7 +29027,7 @@
 		},
 		"yargs": {
 			"version": "3.32.0",
-			"resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
+			"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz",
 			"integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=",
 			"requires": {
 				"camelcase": "^2.0.1",
diff --git a/package.json b/package.json
index b89d9c8a938e48ce31333b20b84d9283f9b6f807..4ad88fa8a9981317647c2136690ab872d9e634f6 100644
--- a/package.json
+++ b/package.json
@@ -99,10 +99,13 @@
 		"@octokit/rest": "^16.1.0",
 		"@rocket.chat/eslint-config": "^0.3.0",
 		"@rocket.chat/livechat": "^1.2.5",
-		"@storybook/addon-actions": "^5.2.1",
-		"@storybook/addon-links": "^5.2.1",
-		"@storybook/addons": "^5.2.1",
-		"@storybook/react": "^5.2.1",
+		"@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",
 		"autoprefixer": "^9.6.1",
 		"babel-eslint": "^10.0.1",
@@ -131,6 +134,7 @@
 		"postcss-media-minmax": "^4.0.0",
 		"postcss-nested": "^4.1.0",
 		"postcss-selector-not": "^4.0.0",
+		"postcss-url": "^8.0.0",
 		"progress": "^2.0.2",
 		"proxyquire": "^2.1.0",
 		"simple-git": "^1.107.0",
@@ -147,8 +151,9 @@
 		"@google-cloud/storage": "^2.3.1",
 		"@google-cloud/vision": "^0.23.0",
 		"@rocket.chat/apps-engine": "^1.7.0",
-		"@rocket.chat/fuselage": "^0.2.0-alpha.4",
-		"@rocket.chat/icons": "^0.2.0-alpha.0",
+		"@rocket.chat/fuselage": "^0.2.0-dev.53",
+		"@rocket.chat/fuselage-hooks": "^0.2.0-dev.50",
+		"@rocket.chat/icons": "^0.2.0-dev.49",
 		"@slack/client": "^4.8.0",
 		"adm-zip": "^0.4.13",
 		"archiver": "^3.0.0",
diff --git a/public/fonts/RocketChat.eot b/public/fonts/RocketChat.eot
deleted file mode 120000
index 25d326d7e00f764a00fd5bc312968713c2565da0..0000000000000000000000000000000000000000
--- a/public/fonts/RocketChat.eot
+++ /dev/null
@@ -1 +0,0 @@
-../../node_modules/@rocket.chat/icons/dist/font/RocketChat.eot
\ No newline at end of file
diff --git a/public/fonts/RocketChat.svg b/public/fonts/RocketChat.svg
deleted file mode 120000
index 6360397c7a6665cf23355edf1606af0ea2e1909b..0000000000000000000000000000000000000000
--- a/public/fonts/RocketChat.svg
+++ /dev/null
@@ -1 +0,0 @@
-../../node_modules/@rocket.chat/icons/dist/font/RocketChat.svg
\ No newline at end of file
diff --git a/public/fonts/RocketChat.ttf b/public/fonts/RocketChat.ttf
deleted file mode 120000
index 4a2797b73b608d185924ab41f9aa5122ecdb58f6..0000000000000000000000000000000000000000
--- a/public/fonts/RocketChat.ttf
+++ /dev/null
@@ -1 +0,0 @@
-../../node_modules/@rocket.chat/icons/dist/font/RocketChat.ttf
\ No newline at end of file
diff --git a/public/fonts/RocketChat.woff b/public/fonts/RocketChat.woff
deleted file mode 120000
index 5530527154cae2944c2079e2d23b81964bc16cfb..0000000000000000000000000000000000000000
--- a/public/fonts/RocketChat.woff
+++ /dev/null
@@ -1 +0,0 @@
-../../node_modules/@rocket.chat/icons/dist/font/RocketChat.woff
\ No newline at end of file
diff --git a/public/fonts/RocketChat.woff2 b/public/fonts/RocketChat.woff2
deleted file mode 120000
index 85ba5007685169b8d2aaac7ddb37a7415f5b1e0f..0000000000000000000000000000000000000000
--- a/public/fonts/RocketChat.woff2
+++ /dev/null
@@ -1 +0,0 @@
-../../node_modules/@rocket.chat/icons/dist/font/RocketChat.woff2
\ No newline at end of file
diff --git a/public/fonts/rocketchat.eot b/public/fonts/rocketchat.eot
new file mode 120000
index 0000000000000000000000000000000000000000..7a5f9168dbbadf308bb201bcd233a964a3e0a551
--- /dev/null
+++ b/public/fonts/rocketchat.eot
@@ -0,0 +1 @@
+../../node_modules/@rocket.chat/icons/dist/font/rocketchat.eot
\ No newline at end of file
diff --git a/public/fonts/rocketchat.svg b/public/fonts/rocketchat.svg
new file mode 120000
index 0000000000000000000000000000000000000000..593ff6fd9f450bc4dac07e212b72226cea58fe8d
--- /dev/null
+++ b/public/fonts/rocketchat.svg
@@ -0,0 +1 @@
+../../node_modules/@rocket.chat/icons/dist/font/rocketchat.svg
\ No newline at end of file
diff --git a/public/fonts/rocketchat.ttf b/public/fonts/rocketchat.ttf
new file mode 120000
index 0000000000000000000000000000000000000000..9597549fd452f859da20e00b6effc3701c587cd7
--- /dev/null
+++ b/public/fonts/rocketchat.ttf
@@ -0,0 +1 @@
+../../node_modules/@rocket.chat/icons/dist/font/rocketchat.ttf
\ No newline at end of file
diff --git a/public/fonts/rocketchat.woff b/public/fonts/rocketchat.woff
new file mode 120000
index 0000000000000000000000000000000000000000..911157e471894e8fc642e16c9493004da2a01b40
--- /dev/null
+++ b/public/fonts/rocketchat.woff
@@ -0,0 +1 @@
+../../node_modules/@rocket.chat/icons/dist/font/rocketchat.woff
\ No newline at end of file
diff --git a/public/fonts/rocketchat.woff2 b/public/fonts/rocketchat.woff2
new file mode 120000
index 0000000000000000000000000000000000000000..1ef2c05eba19c911854e087577f4e32d52bcf4b5
--- /dev/null
+++ b/public/fonts/rocketchat.woff2
@@ -0,0 +1 @@
+../../node_modules/@rocket.chat/icons/dist/font/rocketchat.woff2
\ No newline at end of file
diff --git a/tests/end-to-end/ui/11-admin.js b/tests/end-to-end/ui/11-admin.js
index 1e9e588173ef06ac8e288ddaee53532750294b2b..15dc2e4b5691ee939c1a71bd5e5a142d07676a6c 100644
--- a/tests/end-to-end/ui/11-admin.js
+++ b/tests/end-to-end/ui/11-admin.js
@@ -481,13 +481,14 @@ describe('[Administration]', () => {
 					admin.generalLanguageReset.click();
 				});
 
-				it('it should show invalid self signed certs checkboxes', () => {
-					admin.generalSelfSignedCertsFalse.isVisible().should.be.true;
-					admin.generalSelfSignedCertsTrue.isVisible().should.be.true;
+				it('it should show invalid self signed certs toggle', () => {
+					admin.generalSelfSignedCerts.$('..').isVisible().should.be.true;
 				});
 
-				it('it should change the invalid self signed certs checkboxes', () => {
-					admin.generalSelfSignedCertsTrue.click();
+				it('it should change the invalid self signed certs toggle', () => {
+					if (!admin.generalSelfSignedCerts.isSelected()) {
+						admin.generalSelfSignedCerts.$('..').click();
+					}
 				});
 
 				it('it should show the reset button', () => {
@@ -500,12 +501,13 @@ describe('[Administration]', () => {
 				});
 
 				it('it should show favorite rooms checkboxes', () => {
-					admin.generalFavoriteRoomFalse.isVisible().should.be.true;
-					admin.generalFavoriteRoomTrue.isVisible().should.be.true;
+					admin.generalFavoriteRoom.$('..').isVisible().should.be.true;
 				});
 
-				it('it should change the favorite rooms checkboxes', () => {
-					admin.generalFavoriteRoomFalse.click();
+				it('it should change the favorite rooms toggle', () => {
+					if (admin.generalFavoriteRoom.isSelected()) {
+						admin.generalFavoriteRoom.$('..').click();
+					}
 				});
 
 				it('it should show the reset button', () => {
@@ -552,13 +554,14 @@ describe('[Administration]', () => {
 					admin.generalCdnPrefixReset.click();
 				});
 
-				it('it should show the force SSL checkboxes', () => {
-					admin.generalForceSSLTrue.isVisible().should.be.true;
-					admin.generalForceSSLFalse.isVisible().should.be.true;
+				it('it should show the force SSL toggle', () => {
+					admin.generalForceSSL.$('..').isVisible().should.be.true;
 				});
 
-				it('it should change the force ssl checkboxes', () => {
-					admin.generalForceSSLTrue.click();
+				it('it should change the force ssl toggle', () => {
+					if (!admin.generalForceSSL.isSelected()) {
+						admin.generalForceSSL.$('..').click();
+					}
 				});
 
 				it('it should show the reset button', () => {
@@ -607,24 +610,21 @@ describe('[Administration]', () => {
 
 			describe('iframe:', () => {
 				before(() => {
-					admin.generalButtonExpandIframe.waitForVisible(5000);
-					admin.generalButtonExpandIframe.click();
-					admin.generalIframeSendTrue.waitForVisible(5000);
-					admin.generalIframeSendTrue.scroll();
+					admin.generalSectionIframeIntegration.waitForVisible(5000);
+					admin.generalSectionIframeIntegration.$('[aria-expanded="false"]').click();
+					admin.generalIframeSend.$('..').scroll();
 				});
 
-				it('it should show iframe send checkboxes', () => {
-					admin.generalIframeSendTrue.isVisible().should.be.true;
-					admin.generalIframeSendFalse.isVisible().should.be.true;
+				it('it should show iframe send toggle', () => {
+					admin.generalIframeSend.$('..').isVisible().should.be.true;
 				});
 
 				it('it should show send origin field', () => {
 					admin.generalIframeSendTargetOrigin.isVisible().should.be.true;
 				});
 
-				it('it should show iframe send checkboxes', () => {
-					admin.generalIframeRecieveFalse.isVisible().should.be.true;
-					admin.generalIframeRecieveTrue.isVisible().should.be.true;
+				it('it should show iframe send toggle', () => {
+					admin.generalIframeRecieve.$('..').isVisible().should.be.true;
 				});
 
 				it('it should show send origin field', () => {
@@ -634,9 +634,8 @@ describe('[Administration]', () => {
 
 			describe('notifications:', () => {
 				before(() => {
-					admin.generalButtonExpandNotifications.waitForVisible(5000);
-					admin.generalButtonExpandNotifications.click();
-					admin.generalNotificationsMaxRoomMembers.waitForVisible(5000);
+					admin.generalSectionNotifications.waitForVisible(5000);
+					admin.generalSectionNotifications.$('[aria-expanded="false"]').click();
 					admin.generalNotificationsMaxRoomMembers.scroll();
 				});
 
@@ -647,8 +646,8 @@ describe('[Administration]', () => {
 
 			describe('rest api:', () => {
 				before(() => {
-					admin.generalButtonExpandRest.waitForVisible(5000);
-					admin.generalButtonExpandRest.click();
+					admin.generalSectionRestApi.waitForVisible(5000);
+					admin.generalSectionRestApi.$('[aria-expanded="false"]').click();
 					admin.generalRestApiUserLimit.waitForVisible(5000);
 					admin.generalRestApiUserLimit.scroll();
 				});
@@ -660,22 +659,20 @@ describe('[Administration]', () => {
 
 			describe('reporting:', () => {
 				before(() => {
-					admin.generalButtonExpandReporting.waitForVisible(5000);
-					admin.generalButtonExpandReporting.click();
-					admin.generalReportingTrue.waitForVisible(5000);
-					admin.generalReportingTrue.scroll();
+					admin.generalSectionReporting.waitForVisible(5000);
+					admin.generalSectionReporting.$('[aria-expanded="false"]').click();
+					admin.generalReporting.$('..').scroll();
 				});
 
-				it('it should show the report to rocket.chat checkboxes', () => {
-					admin.generalReportingTrue.isVisible().should.be.true;
-					admin.generalReportingFalse.isVisible().should.be.true;
+				it('it should show the report to rocket.chat toggle', () => {
+					admin.generalReporting.$('..').isVisible().should.be.true;
 				});
 			});
 
 			describe('stream cast:', () => {
 				before(() => {
-					admin.generalButtonExpandStreamCast.waitForVisible(5000);
-					admin.generalButtonExpandStreamCast.click();
+					admin.generalSectionStreamCast.waitForVisible(5000);
+					admin.generalSectionStreamCast.$('[aria-expanded="false"]').click();
 					admin.generalStreamCastAdress.waitForVisible(5000);
 					admin.generalStreamCastAdress.scroll();
 				});
@@ -685,10 +682,10 @@ describe('[Administration]', () => {
 				});
 			});
 
-			describe('stream cast:', () => {
+			describe('utf8:', () => {
 				before(() => {
-					admin.generalButtonExpandUTF8.waitForVisible(5000);
-					admin.generalButtonExpandUTF8.click();
+					admin.generalSectionUTF8.waitForVisible(5000);
+					admin.generalSectionUTF8.$('[aria-expanded="false"]').click();
 					admin.generalUTF8Regex.waitForVisible(5000);
 					admin.generalUTF8Regex.scroll();
 				});
@@ -698,8 +695,7 @@ describe('[Administration]', () => {
 				});
 
 				it('it should show the utf8 names slug checkboxes', () => {
-					admin.generalUTF8NamesSlugTrue.isVisible().should.be.true;
-					admin.generalUTF8NamesSlugFalse.isVisible().should.be.true;
+					admin.generalUTF8NamesSlug.$('..').isVisible().should.be.true;
 				});
 			});
 		});
@@ -714,22 +710,20 @@ describe('[Administration]', () => {
 
 			describe('default user preferences', () => {
 				before(() => {
-					if (admin.accountsButtonCollapseDefaultUserPreferences.isVisible()) {
-						admin.accountsButtonCollapseDefaultUserPreferences.click();
+					if (admin.accountsSectionDefaultUserPreferences.$('[aria-expanded="true"]').isVisible()) {
+						admin.accountsSectionDefaultUserPreferences.$('[aria-expanded="true"]').click();
 					}
-					admin.accountsButtonExpandDefaultUserPreferences.waitForVisible(5000);
-					admin.accountsButtonExpandDefaultUserPreferences.click();
+					admin.accountsSectionDefaultUserPreferences.$('[aria-expanded="false"]').waitForVisible(5000);
+					admin.accountsSectionDefaultUserPreferences.$('[aria-expanded="false"]').click();
 					admin.accountsNotificationDuration.waitForVisible(5000);
 				});
 
 				it('it should show the enable auto away field', () => {
-					admin.accountsEnableAutoAwayTrue.scroll();
-					admin.accountsEnableAutoAwayTrue.isVisible().should.be.true;
-					admin.accountsEnableAutoAwayFalse.isVisible().should.be.true;
+					admin.accountsEnableAutoAway.$('..').scroll();
+					admin.accountsEnableAutoAway.$('..').isVisible().should.be.true;
 				});
 				it('the enable auto away field value should be true', () => {
-					admin.accountsEnableAutoAwayTrue.isSelected().should.be.true;
-					admin.accountsEnableAutoAwayFalse.isSelected().should.be.false;
+					admin.accountsEnableAutoAway.isSelected().should.be.true;
 				});
 
 				it('it should show the idle timeout limit field', () => {
@@ -773,103 +767,83 @@ describe('[Administration]', () => {
 				});
 
 				it('it should show the unread tray icon alert field', () => {
-					admin.accountsUnreadAlertTrue.scroll();
-					admin.accountsUnreadAlertTrue.isVisible().should.be.true;
-					admin.accountsUnreadAlertFalse.isVisible().should.be.true;
+					admin.accountsUnreadAlert.$('..').scroll();
+					admin.accountsUnreadAlert.$('..').isVisible().should.be.true;
 				});
 				it('the unread tray icon alert field value should be true', () => {
-					admin.accountsUnreadAlertTrue.isSelected().should.be.true;
-					admin.accountsUnreadAlertFalse.isSelected().should.be.false;
+					admin.accountsUnreadAlert.isSelected().should.be.true;
 				});
 
 				it('it should show the use emojis field', () => {
-					admin.accountsUseEmojisTrue.scroll();
-					admin.accountsUseEmojisTrue.isVisible().should.be.true;
-					admin.accountsUseEmojisFalse.isVisible().should.be.true;
+					admin.accountsUseEmojis.$('..').scroll();
+					admin.accountsUseEmojis.$('..').isVisible().should.be.true;
 				});
 				it('the use emojis field value should be true', () => {
-					admin.accountsUseEmojisTrue.isSelected().should.be.true;
-					admin.accountsUseEmojisFalse.isSelected().should.be.false;
+					admin.accountsUseEmojis.isSelected().should.be.true;
 				});
 
 				it('it should show the convert ascii to emoji field', () => {
-					admin.accountsConvertAsciiEmojiTrue.scroll();
-					admin.accountsConvertAsciiEmojiTrue.isVisible().should.be.true;
-					admin.accountsConvertAsciiEmojiFalse.isVisible().should.be.true;
+					admin.accountsConvertAsciiEmoji.$('..').scroll();
+					admin.accountsConvertAsciiEmoji.$('..').isVisible().should.be.true;
 				});
 				it('the convert ascii to emoji field value should be true', () => {
-					admin.accountsConvertAsciiEmojiTrue.isSelected().should.be.true;
-					admin.accountsConvertAsciiEmojiFalse.isSelected().should.be.false;
+					admin.accountsConvertAsciiEmoji.isSelected().should.be.true;
 				});
 
 				it('it should show the auto load images field', () => {
-					admin.accountsAutoImageLoadTrue.scroll();
-					admin.accountsAutoImageLoadTrue.isVisible().should.be.true;
-					admin.accountsAutoImageLoadFalse.isVisible().should.be.true;
+					admin.accountsAutoImageLoad.$('..').scroll();
+					admin.accountsAutoImageLoad.$('..').isVisible().should.be.true;
 				});
 				it('the auto load images field value should be true', () => {
-					admin.accountsAutoImageLoadTrue.isSelected().should.be.true;
-					admin.accountsAutoImageLoadFalse.isSelected().should.be.false;
+					admin.accountsAutoImageLoad.isSelected().should.be.true;
 				});
 
 				it('it should show the save mobile bandwidth field', () => {
-					admin.accountsSaveMobileBandwidthTrue.scroll();
-					admin.accountsSaveMobileBandwidthTrue.isVisible().should.be.true;
-					admin.accountsSaveMobileBandwidthFalse.isVisible().should.be.true;
+					admin.accountsSaveMobileBandwidth.$('..').scroll();
+					admin.accountsSaveMobileBandwidth.$('..').isVisible().should.be.true;
 				});
 				it('the save mobile bandwidth field value should be true', () => {
-					admin.accountsSaveMobileBandwidthTrue.isSelected().should.be.true;
-					admin.accountsSaveMobileBandwidthFalse.isSelected().should.be.false;
+					admin.accountsSaveMobileBandwidth.isSelected().should.be.true;
 				});
 
 				it('it should show the collapse embedded media by default field', () => {
-					admin.accountsCollapseMediaByDefaultTrue.scroll();
-					admin.accountsCollapseMediaByDefaultTrue.isVisible().should.be.true;
-					admin.accountsCollapseMediaByDefaultFalse.isVisible().should.be.true;
+					admin.accountsCollapseMediaByDefault.$('..').scroll();
+					admin.accountsCollapseMediaByDefault.$('..').isVisible().should.be.true;
 				});
 				it('the collapse embedded media by default field value should be false', () => {
-					admin.accountsCollapseMediaByDefaultTrue.isSelected().should.be.false;
-					admin.accountsCollapseMediaByDefaultFalse.isSelected().should.be.true;
+					admin.accountsCollapseMediaByDefault.isSelected().should.be.false;
 				});
 
 				it('it should show the hide usernames field', () => {
-					admin.accountsHideUsernamesTrue.scroll();
-					admin.accountsHideUsernamesTrue.isVisible().should.be.true;
-					admin.accountsHideUsernamesFalse.isVisible().should.be.true;
+					admin.accountsHideUsernames.$('..').scroll();
+					admin.accountsHideUsernames.$('..').isVisible().should.be.true;
 				});
 				it('the hide usernames field value should be false', () => {
-					admin.accountsHideUsernamesTrue.isSelected().should.be.false;
-					admin.accountsHideUsernamesFalse.isSelected().should.be.true;
+					admin.accountsHideUsernames.isSelected().should.be.false;
 				});
 
 				it('it should show the hide roles field', () => {
-					admin.accountsHideRolesTrue.scroll();
-					admin.accountsHideRolesTrue.isVisible().should.be.true;
-					admin.accountsHideRolesFalse.isVisible().should.be.true;
+					admin.accountsHideRoles.$('..').scroll();
+					admin.accountsHideRoles.$('..').isVisible().should.be.true;
 				});
 				it('the hide roles field value should be false', () => {
-					admin.accountsHideRolesTrue.isSelected().should.be.false;
-					admin.accountsHideRolesFalse.isSelected().should.be.true;
+					admin.accountsHideRoles.isSelected().should.be.false;
 				});
 
 				it('it should show the hide right sidebar with click field', () => {
-					admin.accountsHideFlexTabTrue.scroll();
-					admin.accountsHideFlexTabTrue.isVisible().should.be.true;
-					admin.accountsHideFlexTabFalse.isVisible().should.be.true;
+					admin.accountsHideFlexTab.$('..').scroll();
+					admin.accountsHideFlexTab.$('..').isVisible().should.be.true;
 				});
 				it('the hide right sidebar with click field value should be false', () => {
-					admin.accountsHideFlexTabTrue.isSelected().should.be.false;
-					admin.accountsHideFlexTabFalse.isSelected().should.be.true;
+					admin.accountsHideFlexTab.isSelected().should.be.false;
 				});
 
 				it('it should show the hide avatars field', () => {
-					admin.accountsHideAvatarsTrue.scroll();
-					admin.accountsHideAvatarsTrue.isVisible().should.be.true;
-					admin.accountsHideAvatarsFalse.isVisible().should.be.true;
+					admin.accountsHideAvatars.$('..').scroll();
+					admin.accountsHideAvatars.$('..').isVisible().should.be.true;
 				});
 				it('the hide avatars field value should be false', () => {
-					admin.accountsHideAvatarsTrue.isSelected().should.be.false;
-					admin.accountsHideAvatarsFalse.isSelected().should.be.true;
+					admin.accountsHideAvatars.isSelected().should.be.false;
 				});
 
 				it('it should show the enter key behavior field', () => {
@@ -899,13 +873,11 @@ describe('[Administration]', () => {
 				});
 
 				it('it should show the room counter sidebar field', () => {
-					admin.accountsRoomCounterSidebarTrue.scroll();
-					admin.accountsRoomCounterSidebarTrue.isVisible().should.be.true;
-					admin.accountsRoomCounterSidebarFalse.isVisible().should.be.true;
+					admin.accountsRoomCounterSidebar.$('..').scroll();
+					admin.accountsRoomCounterSidebar.$('..').isVisible().should.be.true;
 				});
 				it('the room counter sidebar field value should be false', () => {
-					admin.accountsRoomCounterSidebarTrue.isSelected().should.be.false;
-					admin.accountsRoomCounterSidebarFalse.isSelected().should.be.true;
+					admin.accountsRoomCounterSidebar.isSelected().should.be.false;
 				});
 
 				it('it should show the new room notification field', () => {
diff --git a/tests/pageobjects/administration.page.js b/tests/pageobjects/administration.page.js
index a2b9461a5ecb762ffcb6fd6997b07f984829f930..45f5700cf5abd6f035f874febebdf414d31425aa 100644
--- a/tests/pageobjects/administration.page.js
+++ b/tests/pageobjects/administration.page.js
@@ -126,262 +126,208 @@ class Administration extends Page {
 	// settings
 	get buttonSave() { return browser.element('button.save'); }
 
-	get generalButtonExpandIframe() { return browser.element('.section:nth-of-type(3) .expand'); }
+	get generalSectionIframeIntegration() { return browser.element('[data-qa-section="Iframe_Integration"]'); }
 
-	get generalButtonExpandNotifications() { return browser.element('.section:nth-of-type(4) .expand'); }
+	get generalSectionNotifications() { return browser.element('[data-qa-section="Notifications"]'); }
 
-	get generalButtonExpandRest() { return browser.element('.section:nth-of-type(5) .expand'); }
+	get generalSectionRestApi() { return browser.element('[data-qa-section="REST API"]'); }
 
-	get generalButtonExpandReporting() { return browser.element('.section:nth-of-type(6) .expand'); }
+	get generalSectionReporting() { return browser.element('[data-qa-section="Reporting"]'); }
 
-	get generalButtonExpandStreamCast() { return browser.element('.section:nth-of-type(7) .expand'); }
+	get generalSectionStreamCast() { return browser.element('[data-qa-section="Stream_Cast"]'); }
 
-	get generalButtonExpandTranslations() { return browser.element('.section:nth-of-type(8) .expand'); }
+	get generalSectionUTF8() { return browser.element('[data-qa-section="UTF8"]'); }
 
-	get generalButtonExpandUTF8() { return browser.element('.section:nth-of-type(9) .expand'); }
+	get generalSiteUrl() { return browser.element('[data-qa-setting-id="Site_Url"]'); }
 
-	get generalSiteUrl() { return browser.element('[name="Site_Url"]'); }
+	get generalSiteUrlReset() { return browser.element('[data-qa-reset-setting-id="Site_Url"]'); }
 
-	get generalSiteUrlReset() { return browser.element('.reset-setting[data-setting="Site_Url"]'); }
+	get generalSiteName() { return browser.element('[data-qa-setting-id="Site_Name"]'); }
 
-	get generalSiteName() { return browser.element('[name="Site_Name"]'); }
+	get generalSiteNameReset() { return browser.element('[data-qa-reset-setting-id="Site_Name"]'); }
 
-	get generalSiteNameReset() { return browser.element('.reset-setting[data-setting="Site_Name"]'); }
-
-	get generalLanguage() { return browser.element('[name="Language"]'); }
+	get generalLanguage() { return browser.element('[data-qa-setting-id="Language"]'); }
 
 	get generalLanguagePtOption() { return browser.element('[value="pt"]'); }
 
-	get generalLanguageReset() { return browser.element('.reset-setting[data-setting="Language"]'); }
-
-	get generalSelfSignedCertsTrue() { return browser.element('label:nth-of-type(1) [name="Allow_Invalid_SelfSigned_Certs"]'); }
-
-	get generalSelfSignedCertsFalse() { return browser.element('label:nth-of-type(2) [name="Allow_Invalid_SelfSigned_Certs"]'); }
-
-	get generalSelfSignedCertsReset() { return browser.element('.reset-setting[data-setting="Allow_Invalid_SelfSigned_Certs"]'); }
-
-	get generalFavoriteRoomTrue() { return browser.element('label:nth-of-type(1) [name="Favorite_Rooms"]'); }
-
-	get generalFavoriteRoomFalse() { return browser.element('label:nth-of-type(2) [name="Favorite_Rooms"]'); }
-
-	get generalFavoriteRoomReset() { return browser.element('.reset-setting[data-setting="Favorite_Rooms"]'); }
+	get generalLanguageReset() { return browser.element('[data-qa-reset-setting-id="Language"]'); }
 
-	get generalOpenFirstChannel() { return browser.element('[name="First_Channel_After_Login"]'); }
+	get generalSelfSignedCerts() { return browser.element('[data-qa-setting-id="Allow_Invalid_SelfSigned_Certs"]'); }
 
-	get generalOpenFirstChannelReset() { return browser.element('.reset-setting[data-setting="First_Channel_After_Login"]'); }
+	get generalSelfSignedCertsReset() { return browser.element('[data-qa-reset-setting-id="Allow_Invalid_SelfSigned_Certs"]'); }
 
-	get generalCdnPrefix() { return browser.element('[name="CDN_PREFIX"]'); }
+	get generalFavoriteRoom() { return browser.element('[data-qa-setting-id="Favorite_Rooms"]'); }
 
-	get generalCdnPrefixReset() { return browser.element('.reset-setting[data-setting="CDN_PREFIX"]'); }
+	get generalFavoriteRoomReset() { return browser.element('[data-qa-reset-setting-id="Favorite_Rooms"]'); }
 
-	get generalForceSSLTrue() { return browser.element('label:nth-of-type(1) [name="Force_SSL"]'); }
+	get generalOpenFirstChannel() { return browser.element('[data-qa-setting-id="First_Channel_After_Login"]'); }
 
-	get generalForceSSLFalse() { return browser.element('label:nth-of-type(2) [name="Force_SSL"]'); }
+	get generalOpenFirstChannelReset() { return browser.element('[data-qa-reset-setting-id="First_Channel_After_Login"]'); }
 
-	get generalForceSSLReset() { return browser.element('.reset-setting[data-setting="Force_SSL"]'); }
+	get generalCdnPrefix() { return browser.element('[data-qa-setting-id="CDN_PREFIX"]'); }
 
-	get generalGoogleTagId() { return browser.element('[name="GoogleTagManager_id"]'); }
+	get generalCdnPrefixReset() { return browser.element('[data-qa-reset-setting-id="CDN_PREFIX"]'); }
 
-	get generalGoogleTagIdReset() { return browser.element('.reset-setting[data-setting="GoogleTagManager_id"]'); }
+	get generalForceSSL() { return browser.element('[data-qa-setting-id="Force_SSL"]'); }
 
-	get generalBugsnagKey() { return browser.element('[name="Bugsnag_api_key"]'); }
+	get generalForceSSLReset() { return browser.element('[data-qa-reset-setting-id="Force_SSL"]'); }
 
-	get generalBugsnagKeyReset() { return browser.element('.reset-setting[data-setting="Bugsnag_api_key"]'); }
+	get generalGoogleTagId() { return browser.element('[data-qa-setting-id="GoogleTagManager_id"]'); }
 
-	get generalIframeSendTrue() { return browser.element('label:nth-of-type(1) [name="Iframe_Integration_send_enable"]'); }
+	get generalGoogleTagIdReset() { return browser.element('[data-qa-reset-setting-id="GoogleTagManager_id"]'); }
 
-	get generalIframeSendFalse() { return browser.element('label:nth-of-type(2) [name="Iframe_Integration_send_enable"]'); }
+	get generalBugsnagKey() { return browser.element('[data-qa-setting-id="Bugsnag_api_key"]'); }
 
-	get generalIframeSendReset() { return browser.element('.reset-setting[data-setting="Iframe_Integration_send_enable"]'); }
+	get generalBugsnagKeyReset() { return browser.element('[data-qa-reset-setting-id="Bugsnag_api_key"]'); }
 
-	get generalIframeSendTargetOrigin() { return browser.element('[name="Iframe_Integration_send_target_origin"]'); }
+	get generalIframeSend() { return browser.element('[data-qa-setting-id="Iframe_Integration_send_enable"]'); }
 
-	get generalIframeSendTargetOriginReset() { return browser.element('.reset-setting[data-setting="Iframe_Integration_send_target_origin"]'); }
+	get generalIframeSendReset() { return browser.element('[data-qa-reset-setting-id="Iframe_Integration_send_enable"]'); }
 
-	get generalIframeRecieveTrue() { return browser.element('label:nth-of-type(1) [name="Iframe_Integration_receive_enable"]'); }
+	get generalIframeSendTargetOrigin() { return browser.element('[data-qa-setting-id="Iframe_Integration_send_target_origin"]'); }
 
-	get generalIframeRecieveFalse() { return browser.element('label:nth-of-type(2) [name="Iframe_Integration_receive_enable"]'); }
+	get generalIframeSendTargetOriginReset() { return browser.element('[data-qa-reset-setting-id="Iframe_Integration_send_target_origin"]'); }
 
-	get generalIframeRecieveFalseReset() { return browser.element('.reset-setting[data-setting="Iframe_Integration_receive_enable"]'); }
+	get generalIframeRecieve() { return browser.element('[data-qa-setting-id="Iframe_Integration_receive_enable"]'); }
 
-	get generalIframeRecieveOrigin() { return browser.element('[name="Iframe_Integration_receive_origin"]'); }
+	get generalIframeRecieveOrigin() { return browser.element('[data-qa-setting-id="Iframe_Integration_receive_origin"]'); }
 
-	get generalIframeRecieveOriginReset() { return browser.element('.reset-setting[data-setting="Iframe_Integration_receive_origin"]'); }
+	get generalIframeRecieveOriginReset() { return browser.element('[data-qa-reset-setting-id="Iframe_Integration_receive_origin"]'); }
 
-	get generalNotificationsMaxRoomMembers() { return browser.element('[name="Notifications_Max_Room_Members"]'); }
+	get generalNotificationsMaxRoomMembers() { return browser.element('[data-qa-setting-id="Notifications_Max_Room_Members"]'); }
 
-	get generalNotificationsMaxRoomMembersReset() { return browser.element('.reset-setting[data-setting="Notifications_Max_Room_Members"]'); }
+	get generalNotificationsMaxRoomMembersReset() { return browser.element('[data-qa-reset-setting-id="Notifications_Max_Room_Members"]'); }
 
-	get generalRestApiUserLimit() { return browser.element('[name="API_User_Limit"]'); }
+	get generalRestApiUserLimit() { return browser.element('[data-qa-setting-id="API_User_Limit"]'); }
 
-	get generalRestApiUserLimitReset() { return browser.element('.reset-setting[data-setting="API_User_Limit"]'); }
+	get generalRestApiUserLimitReset() { return browser.element('[data-qa-reset-setting-id="API_User_Limit"]'); }
 
-	get generalReportingTrue() { return browser.element('label:nth-of-type(1) [name="Statistics_reporting"]'); }
+	get generalReporting() { return browser.element('[data-qa-setting-id="Statistics_reporting"]'); }
 
-	get generalReportingFalse() { return browser.element('label:nth-of-type(2) [name="Statistics_reporting"]'); }
+	get generalReportingReset() { return browser.element('[data-qa-reset-setting-id="Statistics_reporting"]'); }
 
-	get generalReportingReset() { return browser.element('.reset-setting[data-setting="Statistics_reporting"]'); }
+	get generalStreamCastAdress() { return browser.element('[data-qa-setting-id="Stream_Cast_Address"]'); }
 
-	get generalStreamCastAdress() { return browser.element('[name="Stream_Cast_Address"]'); }
+	get generalStreamCastAdressReset() { return browser.element('[data-qa-reset-setting-id="Stream_Cast_Address"]'); }
 
-	get generalStreamCastAdressReset() { return browser.element('.reset-setting[data-setting="Stream_Cast_Address"]'); }
+	get generalUTF8Regex() { return browser.element('[data-qa-setting-id="UTF8_Names_Validation"]'); }
 
-	get generalUTF8Regex() { return browser.element('[name="UTF8_Names_Validation"]'); }
+	get generalUTF8RegexReset() { return browser.element('[data-qa-reset-setting-id="UTF8_Names_Validation"]'); }
 
-	get generalUTF8RegexReset() { return browser.element('.reset-setting[data-setting="UTF8_Names_Validation"]'); }
+	get generalUTF8NamesSlug() { return browser.element('[data-qa-setting-id="UTF8_Names_Slugify"]'); }
 
-	get generalUTF8NamesSlugTrue() { return browser.element('label:nth-of-type(1) [name="UTF8_Names_Slugify"]'); }
+	get generalUTF8NamesSlugReset() { return browser.element('[data-qa-reset-setting-id="UTF8_Names_Slugify"]'); }
 
-	get generalUTF8NamesSlugFalse() { return browser.element('label:nth-of-type(2) [name="UTF8_Names_Slugify"]'); }
-
-	get generalUTF8NamesSlugReset() { return browser.element('.reset-setting[data-setting="UTF8_Names_Slugify"]'); }
-
-	get generalLayoutTitle() { return browser.element('[name="Layout_Home_Title"]'); }
+	get generalLayoutTitle() { return browser.element('[data-qa-setting-id="Layout_Home_Title"]'); }
 
 	// accounts
-	get accountsButtonExpandDefaultUserPreferences() { return browser.element('.section:nth-of-type(2) .expand'); }
-
-	get accountsButtonCollapseDefaultUserPreferences() { return browser.element('.section:nth-of-type(2) .collapse'); }
-
-	get accountsEnableAutoAwayTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_enableAutoAway"]'); }
-
-	get accountsEnableAutoAwayFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_enableAutoAway"]'); }
-
-	get accountsEnableAutoAwayReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_enableAutoAway"]'); }
-
-	get accountsidleTimeLimit() { return browser.element('[name="Accounts_Default_User_Preferences_idleTimeLimit"]'); }
-
-	get accountsidleTimeLimitReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_idleTimeLimit"]'); }
-
-	get accountsNotificationDuration() { return browser.element('[name="Accounts_Default_User_Preferences_desktopNotificationDuration"]'); }
-
-	get accountsNotificationDurationReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_desktopNotificationDuration"]'); }
-
-	get accountsAudioNotifications() { return browser.element('[name="Accounts_Default_User_Preferences_audioNotifications"]'); }
-
-	get accountsAudioNotificationsReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_audioNotifications"]'); }
-
-	get accountsDesktopNotifications() { return browser.element('[name="Accounts_Default_User_Preferences_desktopNotifications"]'); }
-
-	get accountsDesktopNotificationsReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_desktopNotifications"]'); }
-
-	get accountsMobileNotifications() { return browser.element('[name="Accounts_Default_User_Preferences_mobileNotifications"]'); }
-
-	get accountsMobileNotificationsReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_mobileNotifications"]'); }
-
-	get accountsUnreadAlertTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_unreadAlert"]'); }
-
-	get accountsUnreadAlertFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_unreadAlert"]'); }
-
-	get accountsUnreadAlertReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_unreadAlert"]'); }
-
-	get accountsUseEmojisTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_useEmojis"]'); }
+	get accountsSectionDefaultUserPreferences() { return browser.element('[data-qa-section="Accounts_Default_User_Preferences"]'); }
 
-	get accountsUseEmojisFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_useEmojis"]'); }
+	get accountsEnableAutoAway() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_enableAutoAway"]'); }
 
-	get accountsUseEmojisReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_useEmojis"]'); }
+	get accountsEnableAutoAwayReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_enableAutoAway"]'); }
 
-	get accountsConvertAsciiEmojiTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_convertAsciiEmoji"]'); }
+	get accountsidleTimeLimit() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_idleTimeLimit"]'); }
 
-	get accountsConvertAsciiEmojiFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_convertAsciiEmoji"]'); }
+	get accountsidleTimeLimitReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_idleTimeLimit"]'); }
 
-	get accountsConvertAsciiEmojiReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_convertAsciiEmoji"]'); }
+	get accountsNotificationDuration() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_desktopNotificationDuration"]'); }
 
-	get accountsAutoImageLoadTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_autoImageLoad"]'); }
+	get accountsNotificationDurationReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_desktopNotificationDuration"]'); }
 
-	get accountsAutoImageLoadFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_autoImageLoad"]'); }
+	get accountsAudioNotifications() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_audioNotifications"]'); }
 
-	get accountsAutoImageLoadReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_autoImageLoad"]'); }
+	get accountsAudioNotificationsReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_audioNotifications"]'); }
 
-	get accountsSaveMobileBandwidthTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_saveMobileBandwidth"]'); }
+	get accountsDesktopNotifications() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_desktopNotifications"]'); }
 
-	get accountsSaveMobileBandwidthFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_saveMobileBandwidth"]'); }
+	get accountsDesktopNotificationsReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_desktopNotifications"]'); }
 
-	get accountsSaveMobileBandwidthReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_saveMobileBandwidth"]'); }
+	get accountsMobileNotifications() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_mobileNotifications"]'); }
 
-	get accountsCollapseMediaByDefaultTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_collapseMediaByDefault"]'); }
+	get accountsMobileNotificationsReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_mobileNotifications"]'); }
 
-	get accountsCollapseMediaByDefaultFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_collapseMediaByDefault"]'); }
+	get accountsUnreadAlert() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_unreadAlert"]'); }
 
-	get accountsCollapseMediaByDefaultReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_collapseMediaByDefault"]'); }
+	get accountsUnreadAlertReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_unreadAlert"]'); }
 
-	get accountsHideUsernamesTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_hideUsernames"]'); }
+	get accountsUseEmojis() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_useEmojis"]'); }
 
-	get accountsHideUsernamesFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_hideUsernames"]'); }
+	get accountsUseEmojisReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_useEmojis"]'); }
 
-	get accountsHideUsernamesReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_hideUsernames"]'); }
+	get accountsConvertAsciiEmoji() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_convertAsciiEmoji"]'); }
 
-	get accountsHideRolesTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_hideRoles"]'); }
+	get accountsConvertAsciiEmojiReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_convertAsciiEmoji"]'); }
 
-	get accountsHideRolesFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_hideRoles"]'); }
+	get accountsAutoImageLoad() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_autoImageLoad"]'); }
 
-	get accountsHideRolesReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_hideRoles"]'); }
+	get accountsAutoImageLoadReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_autoImageLoad"]'); }
 
-	get accountsHideFlexTabTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_hideFlexTab"]'); }
+	get accountsSaveMobileBandwidth() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_saveMobileBandwidth"]'); }
 
-	get accountsHideFlexTabFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_hideFlexTab"]'); }
+	get accountsSaveMobileBandwidthReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_saveMobileBandwidth"]'); }
 
-	get accountsHideFlexTabReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_hideFlexTab"]'); }
+	get accountsCollapseMediaByDefault() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_collapseMediaByDefault"]'); }
 
-	get accountsHideAvatarsTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_hideAvatars"]'); }
+	get accountsCollapseMediaByDefaultReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_collapseMediaByDefault"]'); }
 
-	get accountsHideAvatarsFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_hideAvatars"]'); }
+	get accountsHideUsernames() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_hideUsernames"]'); }
 
-	get accountsHideAvatarsReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_hideAvatars"]'); }
+	get accountsHideUsernamesReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_hideUsernames"]'); }
 
-	get accountsMergeChannelsTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_mergeChannels"]'); }
+	get accountsHideRoles() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_hideRoles"]'); }
 
-	get accountsMergeChannelsFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_mergeChannels"]'); }
+	get accountsHideRolesReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_hideRoles"]'); }
 
-	get accountsMergeChannelsReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_mergeChannels"]'); }
+	get accountsHideFlexTab() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_hideFlexTab"]'); }
 
-	get accountsSendOnEnter() { return browser.element('[name="Accounts_Default_User_Preferences_sendOnEnter"]'); }
+	get accountsHideFlexTabReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_hideFlexTab"]'); }
 
-	get accountsSendOnEnterReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_sendOnEnter"]'); }
+	get accountsHideAvatars() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_hideAvatars"]'); }
 
-	get accountsMessageViewMode() { return browser.element('[name="Accounts_Default_User_Preferences_messageViewMode"]'); }
+	get accountsHideAvatarsReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_hideAvatars"]'); }
 
-	get accountsMessageViewModeReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_messageViewMode"]'); }
+	get accountsMergeChannels() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_mergeChannels"]'); }
 
-	get accountsEmailNotificationMode() { return browser.element('[name="Accounts_Default_User_Preferences_emailNotificationMode"]'); }
+	get accountsMergeChannelsReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_mergeChannels"]'); }
 
-	get accountsEmailNotificationModeReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_emailNotificationMode"]'); }
+	get accountsSendOnEnter() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_sendOnEnter"]'); }
 
-	get accountsRoomCounterSidebarTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_roomCounterSidebar"]'); }
+	get accountsSendOnEnterReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_sendOnEnter"]'); }
 
-	get accountsRoomCounterSidebarFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_roomCounterSidebar"]'); }
+	get accountsMessageViewMode() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_messageViewMode"]'); }
 
-	get accountsRoomCounterSidebarReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_roomCounterSidebar"]'); }
+	get accountsMessageViewModeReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_messageViewMode"]'); }
 
-	get accountsNewRoomNotification() { return browser.element('[name="Accounts_Default_User_Preferences_newRoomNotification"]'); }
+	get accountsEmailNotificationMode() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_emailNotificationMode"]'); }
 
-	get accountsNewRoomNotificationReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_newRoomNotification"]'); }
+	get accountsEmailNotificationModeReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_emailNotificationMode"]'); }
 
-	get accountsNewMessageNotification() { return browser.element('[name="Accounts_Default_User_Preferences_newMessageNotification"]'); }
+	get accountsRoomCounterSidebar() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_roomCounterSidebar"]'); }
 
-	get accountsNewMessageNotificationReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_newMessageNotification"]'); }
+	get accountsRoomCounterSidebarReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_roomCounterSidebar"]'); }
 
-	get accountsMuteFocusedConversationsTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_Default_User_Preferences_muteFocusedConversations"]'); }
+	get accountsNewRoomNotification() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_newRoomNotification"]'); }
 
-	get accountsMuteFocusedConversationsFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_Default_User_Preferences_muteFocusedConversations"]'); }
+	get accountsNewRoomNotificationReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_newRoomNotification"]'); }
 
-	get accountsMuteFocusedConversationsReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_muteFocusedConversations"]'); }
+	get accountsNewMessageNotification() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_newMessageNotification"]'); }
 
-	get accountsNotificationsSoundVolume() { return browser.element('[name="Accounts_Default_User_Preferences_notificationsSoundVolume"]'); }
+	get accountsNewMessageNotificationReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_newMessageNotification"]'); }
 
-	get accountsNotificationsSoundVolumeReset() { return browser.element('.reset-setting[data-setting="Accounts_Default_User_Preferences_notificationsSoundVolume"]'); }
+	get accountsMuteFocusedConversations() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_muteFocusedConversations"]'); }
 
-	get accountsRealNameChangeTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_AllowRealNameChange"]'); }
+	get accountsMuteFocusedConversationsReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_muteFocusedConversations"]'); }
 
-	get accountsRealNameChangeFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_AllowRealNameChange"]'); }
+	get accountsNotificationsSoundVolume() { return browser.element('[data-qa-setting-id="Accounts_Default_User_Preferences_notificationsSoundVolume"]'); }
 
-	get accountsUserStatusMessageChangeTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_AllowUserStatusMessageChange"]'); }
+	get accountsNotificationsSoundVolumeReset() { return browser.element('[data-qa-reset-setting-id="Accounts_Default_User_Preferences_notificationsSoundVolume"]'); }
 
-	get accountsUserStatusMessageChangeFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_AllowUserStatusMessageChange"]'); }
+	get accountsRealNameChange() { return browser.element('[data-qa-setting-id="Accounts_AllowRealNameChange"]'); }
 
-	get accountsUsernameChangeTrue() { return browser.element('label:nth-of-type(1) [name="Accounts_AllowUsernameChange"]'); }
+	get accountsUserStatusMessageChange() { return browser.element('[data-qa-setting-id="Accounts_AllowUserStatusMessageChange"]'); }
 
-	get accountsUsernameChangeFalse() { return browser.element('label:nth-of-type(2) [name="Accounts_AllowUsernameChange"]'); }
+	get accountsUsernameChange() { return browser.element('[data-qa-setting-id="Accounts_AllowUsernameChange"]'); }
 
 	get layoutButtonExpandContent() { return browser.element('.section:nth-of-type(2) .rc-button.rc-button--nude'); }