diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index a730683608..e3bc3e0276 100755
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -319,6 +319,14 @@
"admin.general.localization.serverLocaleTitle": "Default Server Language:",
"admin.general.log": "Logging",
"admin.general.policy": "Policy",
+ "admin.general.policy.enableBannerTitle": "Enable Announcement Banner:",
+ "admin.general.policy.enableBannerDesc": "Enable an announcement banner across all teams.",
+ "admin.general.policy.bannerTextTitle": "Banner Text:",
+ "admin.general.policy.bannerTextDesc": "Text that will appear in the announcement banner.",
+ "admin.general.policy.bannerColorTitle": "Banner Color:",
+ "admin.general.policy.bannerTextColorTitle": "Banner Text Color:",
+ "admin.general.policy.allowBannerDismissalTitle": "Allow Banner Dismissal:",
+ "admin.general.policy.allowBannerDismissalDesc": "When true, users can dismiss the banner until its next update. When false, the banner is permanently visible until it is turned off by the System Admin.",
"admin.general.policy.allowEditPostAlways": "Any time",
"admin.general.policy.allowEditPostDescription": "Set policy on the length of time authors have to edit their messages after posting.",
"admin.general.policy.allowEditPostNever": "Never",
diff --git a/webapp/package.json b/webapp/package.json
index 3b2e8792a2..dc32b6d2ec 100644
--- a/webapp/package.json
+++ b/webapp/package.json
@@ -30,6 +30,7 @@
"react": "15.5.4",
"react-addons-pure-render-mixin": "15.5.2",
"react-bootstrap": "0.31.0",
+ "react-color": "2.11.7",
"react-custom-scrollbars": "4.1.2",
"react-dom": "15.5.4",
"react-intl": "2.3.0",
diff --git a/webapp/root.jsx b/webapp/root.jsx
index 6c7643f174..161eff48e5 100644
--- a/webapp/root.jsx
+++ b/webapp/root.jsx
@@ -25,9 +25,11 @@ import 'katex/dist/katex.min.css';
import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
+import EventEmitter from 'mattermost-redux/utils/event_emitter';
import {viewChannel} from 'mattermost-redux/actions/channels';
-import {getClientConfig, getLicenseConfig, setUrl} from 'mattermost-redux/actions/general';
+import {getClientConfig, getLicenseConfig, setUrl, setServerVersion as setServerVersionRedux} from 'mattermost-redux/actions/general';
+import {General} from 'mattermost-redux/constants';
// Import the root of our routing tree
import rRoot from 'routes/route_root.jsx';
@@ -128,15 +130,19 @@ function renderRootComponent() {
let serverVersion = '';
-store.subscribe(() => {
- const newServerVersion = getState().entities.general.serverVersion;
+EventEmitter.on(General.CONFIG_CHANGED, setServerVersion);
+
+function setServerVersion(newServerVersion) {
if (serverVersion && serverVersion !== newServerVersion) {
console.log('Detected version update refreshing the page'); //eslint-disable-line no-console
window.location.reload(true);
}
- serverVersion = newServerVersion;
-});
+ if (serverVersion !== newServerVersion) {
+ serverVersion = newServerVersion;
+ setServerVersionRedux(newServerVersion)(dispatch, getState);
+ }
+}
global.window.setup_root = () => {
// Do the pre-render setup and call renderRootComponent when done
diff --git a/webapp/sass/base/_structure.scss b/webapp/sass/base/_structure.scss
index 60673f9a2c..df7d753295 100644
--- a/webapp/sass/base/_structure.scss
+++ b/webapp/sass/base/_structure.scss
@@ -10,6 +10,10 @@ body {
height: 100%;
position: relative;
width: 100%;
+
+ &.error-bar--fixed {
+ padding-top: 22px;
+ }
}
.sticky {
diff --git a/webapp/sass/components/_error-bar.scss b/webapp/sass/components/_error-bar.scss
index c2ad2402a1..765b61ba85 100644
--- a/webapp/sass/components/_error-bar.scss
+++ b/webapp/sass/components/_error-bar.scss
@@ -4,16 +4,33 @@
background-color: darken($primary-color, 5%);
color: $white;
padding: 5px 30px;
- position: absolute;
+ position: fixed;
text-align: center;
top: 0;
width: 100%;
z-index: 9999;
+ &.error-bar--fixed {
+ overflow: hidden;
+ padding: 1px 30px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
a {
- color: $white !important;
+ color: $white;
text-decoration: underline;
+ .app__body & {
+ color: $white;
+
+ &:hover,
+ &:active,
+ &:focus {
+ color: $white;
+ }
+ }
+
&.error-bar__close {
color: $white;
font-family: 'Open Sans', sans-serif;
diff --git a/webapp/sass/layout/_sidebar-left.scss b/webapp/sass/layout/_sidebar-left.scss
index d08a9ef454..abe49b9c6c 100644
--- a/webapp/sass/layout/_sidebar-left.scss
+++ b/webapp/sass/layout/_sidebar-left.scss
@@ -8,6 +8,10 @@
width: 220px;
z-index: 5;
+ .error-bar--fixed & {
+ height: calc(100% - 22px);
+ }
+
&.sidebar--padded {
padding-top: 44px;
}
diff --git a/webapp/sass/layout/_sidebar-right.scss b/webapp/sass/layout/_sidebar-right.scss
index a1698b3a18..ab73e075bd 100644
--- a/webapp/sass/layout/_sidebar-right.scss
+++ b/webapp/sass/layout/_sidebar-right.scss
@@ -10,6 +10,10 @@
width: 400px;
z-index: 8;
+ .error-bar--fixed & {
+ height: calc(100% - 22px);
+ }
+
&.webrtc {
z-index: 5;
}
@@ -85,8 +89,8 @@
@include opacity(.55);
position: absolute;
top: -25px;
- }
- }
+ }
+ }
}
.help__format-text {
diff --git a/webapp/sass/routes/_admin-console.scss b/webapp/sass/routes/_admin-console.scss
index aece76b281..26e93ec3db 100644
--- a/webapp/sass/routes/_admin-console.scss
+++ b/webapp/sass/routes/_admin-console.scss
@@ -12,6 +12,13 @@
overflow: auto;
padding: 0 20px;
+ .color-picker__popover {
+ position: absolute;
+ right: 0;
+ top: 40px;
+ z-index: 5;
+ }
+
.dropdown-menu {
.divider {
@include opacity(1);
diff --git a/webapp/tests/components/admin_console/__snapshots__/color_setting.test.jsx.snap b/webapp/tests/components/admin_console/__snapshots__/color_setting.test.jsx.snap
new file mode 100644
index 0000000000..7b8c934ce4
--- /dev/null
+++ b/webapp/tests/components/admin_console/__snapshots__/color_setting.test.jsx.snap
@@ -0,0 +1,95 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`components/ColorSetting should match snapshot, all 1`] = `
+
+
+
+
+
+
+
+
+`;
+
+exports[`components/ColorSetting should match snapshot, disabled 1`] = `
+
+
+
+
+
+
+
+
+`;
+
+exports[`components/ColorSetting should match snapshot, no help text 1`] = `
+
+
+
+
+
+
+
+
+`;
diff --git a/webapp/tests/components/admin_console/color_setting.test.jsx b/webapp/tests/components/admin_console/color_setting.test.jsx
new file mode 100644
index 0000000000..a1c44a0371
--- /dev/null
+++ b/webapp/tests/components/admin_console/color_setting.test.jsx
@@ -0,0 +1,55 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+import React from 'react';
+import {shallow} from 'enzyme';
+
+import ColorSetting from 'components/admin_console/color_setting.jsx';
+
+describe('components/ColorSetting', () => {
+ test('should match snapshot, all', () => {
+ function emptyFunction() {} //eslint-disable-line no-empty-function
+
+ const wrapper = shallow(
+
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('should match snapshot, no help text', () => {
+ function emptyFunction() {} //eslint-disable-line no-empty-function
+
+ const wrapper = shallow(
+
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ test('should match snapshot, disabled', () => {
+ function emptyFunction() {} //eslint-disable-line no-empty-function
+
+ const wrapper = shallow(
+
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx
index e4aa48a597..469f793c85 100644
--- a/webapp/utils/utils.jsx
+++ b/webapp/utils/utils.jsx
@@ -1348,3 +1348,16 @@ export function isEmptyObject(object) {
export function updateWindowDimensions(component) {
component.setState({width: window.innerWidth, height: window.innerHeight});
}
+
+export function removePrefixFromLocalStorage(prefix) {
+ const keys = [];
+ for (let i = 0; i < localStorage.length; i++) {
+ if (localStorage.key(i).startsWith(prefix)) {
+ keys.push(localStorage.key(i));
+ }
+ }
+
+ for (let i = 0; i < keys.length; i++) {
+ localStorage.removeItem(keys[i]);
+ }
+}
diff --git a/webapp/yarn.lock b/webapp/yarn.lock
index 7036224501..8660bed5e9 100644
--- a/webapp/yarn.lock
+++ b/webapp/yarn.lock
@@ -4792,7 +4792,7 @@ lodash.unset@^4.5.2:
version "4.5.2"
resolved "https://registry.yarnpkg.com/lodash.unset/-/lodash.unset-4.5.2.tgz#370d1d3e85b72a7e1b0cdf2d272121306f23e4ed"
-lodash@^4.0.0, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.8.0:
+lodash@^4.0.0, lodash@^4.0.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@^4.8.0:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@@ -4874,13 +4874,17 @@ match-at@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/match-at/-/match-at-0.1.0.tgz#f561e7709ff9a105b85cc62c6b8ee7c15bf24f31"
+material-colors@^1.2.1:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.5.tgz#5292593e6754cb1bcc2b98030e4e0d6a3afc9ea1"
+
math-expression-evaluator@^1.2.14:
version "1.2.16"
resolved "https://registry.yarnpkg.com/math-expression-evaluator/-/math-expression-evaluator-1.2.16.tgz#b357fa1ca9faefb8e48d10c14ef2bcb2d9f0a7c9"
mattermost-redux@mattermost/mattermost-redux#webapp-master:
version "0.0.1"
- resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/d1652dc7b636aae658d0d109919b6a74762a186d"
+ resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/dfa584b61ed9d04c167be53fe16ac6432892ece1"
dependencies:
deep-equal "1.0.1"
harmony-reflect "1.5.1"
@@ -6044,6 +6048,16 @@ react-bootstrap@0.31.0:
uncontrollable "^4.1.0"
warning "^3.0.0"
+react-color@^2.11.7:
+ version "2.11.7"
+ resolved "https://registry.yarnpkg.com/react-color/-/react-color-2.11.7.tgz#746465b75feda63c2567607dfbcb276fc954a5b7"
+ dependencies:
+ lodash "^4.0.1"
+ material-colors "^1.2.1"
+ prop-types "^15.5.4"
+ reactcss "^1.2.0"
+ tinycolor2 "^1.1.2"
+
react-custom-scrollbars@4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/react-custom-scrollbars/-/react-custom-scrollbars-4.1.2.tgz#0e60c4a46c4a61f9e4994a7663e2b9cbbc5187a3"
@@ -6137,6 +6151,12 @@ react@15.5.4:
object-assign "^4.1.0"
prop-types "^15.5.7"
+reactcss@^1.2.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/reactcss/-/reactcss-1.2.2.tgz#41b0ef43e01d54880357c34b11ac1531209350ef"
+ dependencies:
+ lodash "^4.0.1"
+
read-all-stream@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/read-all-stream/-/read-all-stream-3.1.0.tgz#35c3e177f2078ef789ee4bfafa4373074eaef4fa"
@@ -6280,7 +6300,7 @@ redux-persist-transform-filter@0.0.9:
lodash.set "^4.3.2"
lodash.unset "^4.5.2"
-redux-persist@4.6.0, redux-persist@^4.5.0:
+redux-persist@4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-4.6.0.tgz#3994793d5f2f38bf02591c9e693e16bf8eae2728"
dependencies:
@@ -6288,7 +6308,7 @@ redux-persist@4.6.0, redux-persist@^4.5.0:
lodash "^4.17.4"
lodash-es "^4.17.4"
-redux-persist@4.8.0:
+redux-persist@4.8.0, redux-persist@^4.5.0:
version "4.8.0"
resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-4.8.0.tgz#17fd998949bdeef9275e4cf60ad5bbe1c73675fc"
dependencies:
@@ -7257,6 +7277,10 @@ timers-browserify@^2.0.2:
dependencies:
setimmediate "^1.0.4"
+tinycolor2@^1.1.2:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8"
+
tmp@^0.0.29:
version "0.0.29"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.29.tgz#f25125ff0dd9da3ccb0c2dd371ee1288bb9128c0"