From abd0466a42d6b9897ba9e3bcb373b41974e9c46f Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Mon, 5 Jun 2017 12:49:38 -0400 Subject: PLT-3466 E10: Add announcement bar feature (#6509) * E10 - Add announcement bar feature * Updates per feedback * Add component tests and snapshots * Update snapshots * Updating color picker UI (#6543) * Add class to body tag when banner is not dismissable and clean up localstorage items when banner changes * Fixing links (#6544) * Updating UI for fixed error bar (#6552) * Truncating text on fixed banner (#6561) * Plt 3466 - Error bar link states (#6577) * Updating error bar hover state * Updating error bar link states --- webapp/components/admin_console/admin_console.jsx | 9 +- webapp/components/admin_console/color_setting.jsx | 119 ++++++++ .../components/admin_console/policy_settings.jsx | 92 +++++- .../announcement_bar/announcement_bar.jsx | 308 +++++++++++++++++++++ webapp/components/announcement_bar/index.js | 16 ++ .../components/backstage/backstage_controller.jsx | 4 +- .../create_team/create_team_controller.jsx | 4 +- webapp/components/error_bar.jsx | 232 ---------------- webapp/components/login/login_controller.jsx | 4 +- webapp/components/needs_team/needs_team.jsx | 4 +- webapp/components/select_team/select_team.jsx | 4 +- webapp/components/signup/signup_controller.jsx | 4 +- 12 files changed, 550 insertions(+), 250 deletions(-) create mode 100644 webapp/components/admin_console/color_setting.jsx create mode 100644 webapp/components/announcement_bar/announcement_bar.jsx create mode 100644 webapp/components/announcement_bar/index.js delete mode 100644 webapp/components/error_bar.jsx (limited to 'webapp/components') diff --git a/webapp/components/admin_console/admin_console.jsx b/webapp/components/admin_console/admin_console.jsx index 80d9bfed9..b8250bab2 100644 --- a/webapp/components/admin_console/admin_console.jsx +++ b/webapp/components/admin_console/admin_console.jsx @@ -1,12 +1,11 @@ -import PropTypes from 'prop-types'; - // Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import React from 'react'; +import PropTypes from 'prop-types'; import 'bootstrap'; -import ErrorBar from 'components/error_bar.jsx'; +import AnnouncementBar from 'components/announcement_bar'; import AdminStore from 'stores/admin_store.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; @@ -52,7 +51,7 @@ export default class AdminConsole extends React.Component { if (config && Object.keys(config).length === 0 && config.constructor === 'Object') { return (
- +
); @@ -64,7 +63,7 @@ export default class AdminConsole extends React.Component { }); return (
- +
{children} diff --git a/webapp/components/admin_console/color_setting.jsx b/webapp/components/admin_console/color_setting.jsx new file mode 100644 index 000000000..483b585ee --- /dev/null +++ b/webapp/components/admin_console/color_setting.jsx @@ -0,0 +1,119 @@ +// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import Setting from './setting.jsx'; + +import React from 'react'; +import PropTypes from 'prop-types'; +import {ChromePicker} from 'react-color'; + +export default class ColorSetting extends React.PureComponent { + static propTypes = { + + /* + * The unique identifer for the admin console setting + */ + id: PropTypes.string.isRequired, + + /* + * The text/jsx display name for the setting + */ + label: PropTypes.node.isRequired, + + /* + * The text/jsx help text to display underneath the setting + */ + helpText: PropTypes.node, + + /* + * The hex color value + */ + value: PropTypes.string.isRequired, + + /* + * Function called when the input changes + */ + onChange: PropTypes.func, + + /* + * Set to disable the setting + */ + disabled: PropTypes.bool + } + + constructor(props) { + super(props); + + this.state = { + showPicker: false + }; + } + + componentDidMount() { + document.addEventListener('click', this.closePicker); + } + + componentWillUnmount() { + document.removeEventListener('click', this.closePicker); + } + + handleChange = (color) => { + this.props.onChange(this.props.id, color.hex); + } + + togglePicker = () => { + if (this.props.disabled) { + this.setState({showPicker: false}); + } + this.setState({showPicker: !this.state.showPicker}); + } + + closePicker = (e) => { + if (!e.target.closest('.picker-' + this.props.id)) { + this.setState({showPicker: false}); + } + } + + onTextInput = (e) => { + this.props.onChange(this.props.id, e.target.value); + } + + render() { + let picker; + if (this.state.showPicker) { + picker = ( +
+ +
+ ); + } + + return ( + +
+ + + + + {picker} +
+
+ ); + } +} diff --git a/webapp/components/admin_console/policy_settings.jsx b/webapp/components/admin_console/policy_settings.jsx index 7d2985001..f689efd82 100644 --- a/webapp/components/admin_console/policy_settings.jsx +++ b/webapp/components/admin_console/policy_settings.jsx @@ -8,6 +8,9 @@ import SettingsGroup from './settings_group.jsx'; import DropdownSetting from './dropdown_setting.jsx'; import RadioSetting from './radio_setting.jsx'; import PostEditSetting from './post_edit_setting.jsx'; +import BooleanSetting from './boolean_setting.jsx'; +import TextSetting from './text_setting.jsx'; +import ColorSetting from './color_setting.jsx'; import Constants from 'utils/constants.jsx'; import * as Utils from 'utils/utils.jsx'; @@ -35,6 +38,11 @@ export default class PolicySettings extends AdminSettings { config.TeamSettings.RestrictPublicChannelDeletion = this.state.restrictPublicChannelDeletion; config.TeamSettings.RestrictPrivateChannelDeletion = this.state.restrictPrivateChannelDeletion; config.TeamSettings.RestrictPrivateChannelManageMembers = this.state.restrictPrivateChannelManageMembers; + config.AnnouncementSettings.EnableBanner = this.state.enableBanner; + config.AnnouncementSettings.BannerText = this.state.bannerText; + config.AnnouncementSettings.BannerColor = this.state.bannerColor; + config.AnnouncementSettings.BannerTextColor = this.state.bannerTextColor; + config.AnnouncementSettings.AllowBannerDismissal = this.state.allowBannerDismissal; return config; } @@ -51,7 +59,12 @@ export default class PolicySettings extends AdminSettings { restrictPrivateChannelManagement: config.TeamSettings.RestrictPrivateChannelManagement, restrictPublicChannelDeletion: config.TeamSettings.RestrictPublicChannelDeletion, restrictPrivateChannelDeletion: config.TeamSettings.RestrictPrivateChannelDeletion, - restrictPrivateChannelManageMembers: config.TeamSettings.RestrictPrivateChannelManageMembers + restrictPrivateChannelManageMembers: config.TeamSettings.RestrictPrivateChannelManageMembers, + enableBanner: config.AnnouncementSettings.EnableBanner, + bannerText: config.AnnouncementSettings.BannerText, + bannerColor: config.AnnouncementSettings.BannerColor, + bannerTextColor: config.AnnouncementSettings.BannerTextColor, + allowBannerDismissal: config.AnnouncementSettings.AllowBannerDismissal }; } @@ -317,6 +330,83 @@ export default class PolicySettings extends AdminSettings { /> } /> + + } + helpText={ + + } + value={this.state.enableBanner} + onChange={this.handleChange} + /> + + } + helpText={ + + } + value={this.state.bannerText} + onChange={this.handleChange} + disabled={!this.state.enableBanner} + /> + + } + value={this.state.bannerColor} + onChange={this.handleChange} + disabled={!this.state.enableBanner} + /> + + } + value={this.state.bannerTextColor} + onChange={this.handleChange} + disabled={!this.state.enableBanner} + /> + + } + helpText={ + + } + value={this.state.allowBannerDismissal} + onChange={this.handleChange} + disabled={!this.state.enableBanner} + /> ); } diff --git a/webapp/components/announcement_bar/announcement_bar.jsx b/webapp/components/announcement_bar/announcement_bar.jsx new file mode 100644 index 000000000..ed097c436 --- /dev/null +++ b/webapp/components/announcement_bar/announcement_bar.jsx @@ -0,0 +1,308 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React from 'react'; +import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; +import {Link} from 'react-router'; + +import AnalyticsStore from 'stores/analytics_store.jsx'; +import ErrorStore from 'stores/error_store.jsx'; +import UserStore from 'stores/user_store.jsx'; + +import * as AsyncClient from 'utils/async_client.jsx'; +import {ErrorBarTypes, StatTypes} from 'utils/constants.jsx'; +import {isLicenseExpiring, isLicenseExpired, isLicensePastGracePeriod, displayExpiryDate} from 'utils/license_utils.jsx'; +import * as Utils from 'utils/utils.jsx'; + +const RENEWAL_LINK = 'https://licensing.mattermost.com/renew'; + +const BAR_DEVELOPER_TYPE = 'developer'; +const BAR_CRITICAL_TYPE = 'critical'; +const BAR_ANNOUNCEMENT_TYPE = 'announcement'; + +const ANNOUNCEMENT_KEY = 'announcement--'; + +export default class AnnouncementBar extends React.PureComponent { + static propTypes = { + + /* + * Set if the user is logged in + */ + isLoggedIn: React.PropTypes.bool.isRequired + } + + constructor() { + super(); + + this.onErrorChange = this.onErrorChange.bind(this); + this.onAnalyticsChange = this.onAnalyticsChange.bind(this); + this.handleClose = this.handleClose.bind(this); + + ErrorStore.clearLastError(); + + this.setInitialError(); + + this.state = this.getState(); + } + + setInitialError() { + let isSystemAdmin = false; + const user = UserStore.getCurrentUser(); + if (user) { + isSystemAdmin = Utils.isSystemAdmin(user.roles); + } + + const errorIgnored = ErrorStore.getIgnoreNotification(); + + if (!errorIgnored) { + if (isSystemAdmin && global.mm_config.SiteURL === '') { + ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.SITE_URL}); + return; + } else if (global.mm_config.SendEmailNotifications === 'false') { + ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.PREVIEW_MODE}); + return; + } + } + + if (isLicensePastGracePeriod()) { + if (isSystemAdmin) { + ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.LICENSE_EXPIRED, type: BAR_CRITICAL_TYPE}); + } else { + ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.LICENSE_PAST_GRACE, type: BAR_CRITICAL_TYPE}); + } + } else if (isLicenseExpired() && isSystemAdmin) { + ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.LICENSE_EXPIRED, type: BAR_CRITICAL_TYPE}); + } else if (isLicenseExpiring() && isSystemAdmin) { + ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.LICENSE_EXPIRING, type: BAR_CRITICAL_TYPE}); + } + } + + getState() { + const error = ErrorStore.getLastError(); + if (error) { + return {message: error.message, color: null, textColor: null, type: error.type, allowDismissal: true}; + } + + const bannerText = global.window.mm_config.BannerText || ''; + const allowDismissal = global.window.mm_config.AllowBannerDismissal === 'true'; + const bannerDismissed = localStorage.getItem(ANNOUNCEMENT_KEY + global.window.mm_config.BannerText); + + if (global.window.mm_config.EnableBanner === 'true' && + bannerText.length > 0 && + (!bannerDismissed || !allowDismissal)) { + // Remove old local storage items + Utils.removePrefixFromLocalStorage(ANNOUNCEMENT_KEY); + return { + message: bannerText, + color: global.window.mm_config.BannerColor, + textColor: global.window.mm_config.BannerTextColor, + type: BAR_ANNOUNCEMENT_TYPE, + allowDismissal + }; + } + + return {message: null, color: null, colorText: null, textColor: null, type: null, allowDismissal: true}; + } + + isValidState(s) { + if (!s) { + return false; + } + + if (!s.message) { + return false; + } + + if (s.message === ErrorBarTypes.LICENSE_EXPIRING && !this.state.totalUsers) { + return false; + } + + return true; + } + + componentDidMount() { + if (this.props.isLoggedIn && !this.state.allowDismissal) { + document.body.classList.add('error-bar--fixed'); + } + + ErrorStore.addChangeListener(this.onErrorChange); + AnalyticsStore.addChangeListener(this.onAnalyticsChange); + } + + componentWillUnmount() { + document.body.classList.remove('error-bar--fixed'); + ErrorStore.removeChangeListener(this.onErrorChange); + AnalyticsStore.removeChangeListener(this.onAnalyticsChange); + } + + componentDidUpdate(prevProps, prevState) { + if (!this.props.isLoggedIn) { + return; + } + + if (!prevState.allowDismissal && this.state.allowDismissal) { + document.body.classList.remove('error-bar--fixed'); + } else if (prevState.allowDismissal && !this.state.allowDismissal) { + document.body.classList.add('error-bar--fixed'); + } + } + + onErrorChange() { + const newState = this.getState(); + if (newState.message === ErrorBarTypes.LICENSE_EXPIRING && !this.state.totalUsers) { + AsyncClient.getStandardAnalytics(); + } + this.setState(newState); + } + + onAnalyticsChange() { + const stats = AnalyticsStore.getAllSystem(); + this.setState({totalUsers: stats[StatTypes.TOTAL_USERS]}); + } + + handleClose(e) { + if (e) { + e.preventDefault(); + } + + if (this.state.type === BAR_ANNOUNCEMENT_TYPE) { + localStorage.setItem(ANNOUNCEMENT_KEY + this.state.message, true); + } + + if (ErrorStore.getLastError() && ErrorStore.getLastError().notification) { + ErrorStore.clearNotificationError(); + } else { + ErrorStore.clearLastError(); + } + + this.setState(this.getState()); + } + + render() { + if (!this.isValidState(this.state)) { + return
; + } + + if (!this.props.isLoggedIn && this.state.type === BAR_ANNOUNCEMENT_TYPE) { + return
; + } + + let errClass = 'error-bar'; + let dismissClass = ' error-bar--fixed'; + const barStyle = {}; + const linkStyle = {}; + if (this.state.color && this.state.textColor) { + barStyle.backgroundColor = this.state.color; + barStyle.color = this.state.textColor; + linkStyle.color = this.state.textColor; + } else if (this.state.type === BAR_DEVELOPER_TYPE) { + errClass = 'error-bar-developer'; + } else if (this.state.type === BAR_CRITICAL_TYPE) { + errClass = 'error-bar-critical'; + } + + let closeButton; + if (this.state.allowDismissal) { + dismissClass = ''; + closeButton = ( + + {'×'} + + ); + } + + const renewalLink = RENEWAL_LINK + '?id=' + global.window.mm_license.Id + '&user_count=' + this.state.totalUsers; + + let message = this.state.message; + if (message === ErrorBarTypes.PREVIEW_MODE) { + message = ( + + ); + } else if (message === ErrorBarTypes.LICENSE_EXPIRING) { + message = ( + + ); + } else if (message === ErrorBarTypes.LICENSE_EXPIRED) { + message = ( + + ); + } else if (message === ErrorBarTypes.LICENSE_PAST_GRACE) { + message = ( + + ); + } else if (message === ErrorBarTypes.SITE_URL) { + let id; + let defaultMessage; + if (global.mm_config.EnableSignUpWithGitLab === 'true') { + id = 'error_bar.site_url_gitlab'; + defaultMessage = 'Please configure your {docsLink} in the System Console or in gitlab.rb if you\'re using GitLab Mattermost.'; + } else { + id = 'error_bar.site_url'; + defaultMessage = 'Please configure your {docsLink} in the System Console.'; + } + + message = ( + + + + ), + link: ( + + + + ) + }} + /> + ); + } + + return ( +
+ {message} + {closeButton} +
+ ); + } +} diff --git a/webapp/components/announcement_bar/index.js b/webapp/components/announcement_bar/index.js new file mode 100644 index 000000000..8fe4f56b4 --- /dev/null +++ b/webapp/components/announcement_bar/index.js @@ -0,0 +1,16 @@ +// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import {connect} from 'react-redux'; +import {getCurrentUserId} from 'mattermost-redux/selectors/entities/users'; + +import AnnouncementBar from './announcement_bar.jsx'; + +function mapStateToProps(state, ownProps) { + return { + ...ownProps, + isLoggedIn: Boolean(getCurrentUserId(state)) + }; +} + +export default connect(mapStateToProps)(AnnouncementBar); diff --git a/webapp/components/backstage/backstage_controller.jsx b/webapp/components/backstage/backstage_controller.jsx index 4619641b1..795fb0e95 100644 --- a/webapp/components/backstage/backstage_controller.jsx +++ b/webapp/components/backstage/backstage_controller.jsx @@ -10,7 +10,7 @@ import UserStore from 'stores/user_store.jsx'; import BackstageSidebar from './components/backstage_sidebar.jsx'; import BackstageNavbar from './components/backstage_navbar.jsx'; -import ErrorBar from 'components/error_bar.jsx'; +import AnnouncementBar from 'components/announcement_bar'; export default class BackstageController extends React.Component { static get propTypes() { @@ -55,7 +55,7 @@ export default class BackstageController extends React.Component { render() { return (
- +
- +
diff --git a/webapp/components/error_bar.jsx b/webapp/components/error_bar.jsx deleted file mode 100644 index 97fbbdca0..000000000 --- a/webapp/components/error_bar.jsx +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; -import {FormattedMessage, FormattedHTMLMessage} from 'react-intl'; -import {Link} from 'react-router'; - -import AnalyticsStore from 'stores/analytics_store.jsx'; -import ErrorStore from 'stores/error_store.jsx'; -import UserStore from 'stores/user_store.jsx'; - -import * as AsyncClient from 'utils/async_client.jsx'; -import {ErrorBarTypes, StatTypes} from 'utils/constants.jsx'; -import {isLicenseExpiring, isLicenseExpired, isLicensePastGracePeriod, displayExpiryDate} from 'utils/license_utils.jsx'; -import * as Utils from 'utils/utils.jsx'; - -const RENEWAL_LINK = 'https://licensing.mattermost.com/renew'; - -const BAR_DEVELOPER_TYPE = 'developer'; -const BAR_CRITICAL_TYPE = 'critical'; - -export default class ErrorBar extends React.Component { - constructor() { - super(); - - this.onErrorChange = this.onErrorChange.bind(this); - this.onAnalyticsChange = this.onAnalyticsChange.bind(this); - this.handleClose = this.handleClose.bind(this); - - ErrorStore.clearLastError(); - - this.setInitialError(); - - this.state = ErrorStore.getLastError() || {}; - } - - setInitialError() { - let isSystemAdmin = false; - const user = UserStore.getCurrentUser(); - if (user) { - isSystemAdmin = Utils.isSystemAdmin(user.roles); - } - - const errorIgnored = ErrorStore.getIgnoreNotification(); - - if (!errorIgnored) { - if (isSystemAdmin && global.mm_config.SiteURL === '') { - ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.SITE_URL}); - return; - } else if (global.mm_config.SendEmailNotifications === 'false') { - ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.PREVIEW_MODE}); - return; - } - } - - if (isLicensePastGracePeriod()) { - if (isSystemAdmin) { - ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.LICENSE_EXPIRED, type: BAR_CRITICAL_TYPE}); - } else { - ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.LICENSE_PAST_GRACE, type: BAR_CRITICAL_TYPE}); - } - } else if (isLicenseExpired() && isSystemAdmin) { - ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.LICENSE_EXPIRED, type: BAR_CRITICAL_TYPE}); - } else if (isLicenseExpiring() && isSystemAdmin) { - ErrorStore.storeLastError({notification: true, message: ErrorBarTypes.LICENSE_EXPIRING}); - } - } - - isValidError(s) { - if (!s) { - return false; - } - - if (!s.message) { - return false; - } - - if (s.message === ErrorBarTypes.LICENSE_EXPIRING && !this.state.totalUsers) { - return false; - } - - return true; - } - - componentDidMount() { - ErrorStore.addChangeListener(this.onErrorChange); - AnalyticsStore.addChangeListener(this.onAnalyticsChange); - } - - componentWillUnmount() { - ErrorStore.removeChangeListener(this.onErrorChange); - AnalyticsStore.removeChangeListener(this.onAnalyticsChange); - } - - onErrorChange() { - var newState = ErrorStore.getLastError(); - - if (newState) { - if (newState.message === ErrorBarTypes.LICENSE_EXPIRING && !this.state.totalUsers) { - AsyncClient.getStandardAnalytics(); - } - this.setState(newState); - } else { - this.setState({message: null}); - } - } - - onAnalyticsChange() { - const stats = AnalyticsStore.getAllSystem(); - this.setState({totalUsers: stats[StatTypes.TOTAL_USERS]}); - } - - handleClose(e) { - if (e) { - e.preventDefault(); - } - - if (ErrorStore.getLastError() && ErrorStore.getLastError().notification) { - ErrorStore.clearNotificationError(); - } else { - ErrorStore.clearLastError(); - } - - this.setState({message: null}); - } - - render() { - if (!this.isValidError(this.state)) { - return
; - } - - var errClass = 'error-bar'; - - if (this.state.type === BAR_DEVELOPER_TYPE) { - errClass = 'error-bar-developer'; - } else if (this.state.type === BAR_CRITICAL_TYPE) { - errClass = 'error-bar-critical'; - } - - const renewalLink = RENEWAL_LINK + '?id=' + global.window.mm_license.Id + '&user_count=' + this.state.totalUsers; - - let message = this.state.message; - if (message === ErrorBarTypes.PREVIEW_MODE) { - message = ( - - ); - } else if (message === ErrorBarTypes.LICENSE_EXPIRING) { - message = ( - - ); - } else if (message === ErrorBarTypes.LICENSE_EXPIRED) { - message = ( - - ); - } else if (message === ErrorBarTypes.LICENSE_PAST_GRACE) { - message = ( - - ); - } else if (message === ErrorBarTypes.SITE_URL) { - let id; - let defaultMessage; - if (global.mm_config.EnableSignUpWithGitLab === 'true') { - id = 'error_bar.site_url_gitlab'; - defaultMessage = 'Please configure your {docsLink} in the System Console or in gitlab.rb if you\'re using GitLab Mattermost.'; - } else { - id = 'error_bar.site_url'; - defaultMessage = 'Please configure your {docsLink} in the System Console.'; - } - - message = ( - - - - ), - link: ( - - - - ) - }} - /> - ); - } - - return ( -
- {message} - - {'×'} - -
- ); - } -} diff --git a/webapp/components/login/login_controller.jsx b/webapp/components/login/login_controller.jsx index cef7fe435..212a09bf2 100644 --- a/webapp/components/login/login_controller.jsx +++ b/webapp/components/login/login_controller.jsx @@ -2,7 +2,7 @@ // See License.txt for license information. import LoginMfa from './components/login_mfa.jsx'; -import ErrorBar from 'components/error_bar.jsx'; +import AnnouncementBar from 'components/announcement_bar'; import FormError from 'components/form_error.jsx'; import * as GlobalActions from 'actions/global_actions.jsx'; @@ -621,7 +621,7 @@ export default class LoginController extends React.Component { return (
- +
diff --git a/webapp/components/needs_team/needs_team.jsx b/webapp/components/needs_team/needs_team.jsx index aa3ea46e8..75ec40653 100644 --- a/webapp/components/needs_team/needs_team.jsx +++ b/webapp/components/needs_team/needs_team.jsx @@ -23,7 +23,7 @@ import Constants from 'utils/constants.jsx'; const TutorialSteps = Constants.TutorialSteps; const Preferences = Constants.Preferences; -import ErrorBar from 'components/error_bar.jsx'; +import AnnouncementBar from 'components/announcement_bar'; import SidebarRight from 'components/sidebar_right.jsx'; import SidebarRightMenu from 'components/sidebar_right_menu.jsx'; import Navbar from 'components/navbar.jsx'; @@ -211,7 +211,7 @@ export default class NeedsTeam extends React.Component { return (
- +
diff --git a/webapp/components/select_team/select_team.jsx b/webapp/components/select_team/select_team.jsx index 858329bd0..fe706af0f 100644 --- a/webapp/components/select_team/select_team.jsx +++ b/webapp/components/select_team/select_team.jsx @@ -5,7 +5,7 @@ import UserStore from 'stores/user_store.jsx'; import TeamStore from 'stores/team_store.jsx'; import * as UserAgent from 'utils/user_agent.jsx'; import * as Utils from 'utils/utils.jsx'; -import ErrorBar from 'components/error_bar.jsx'; +import AnnouncementBar from 'components/announcement_bar'; import LoadingScreen from 'components/loading_screen.jsx'; import * as GlobalActions from 'actions/global_actions.jsx'; import SelectTeamItem from './components/select_team_item.jsx'; @@ -218,7 +218,7 @@ export default class SelectTeam extends React.Component { } return (
- +
{headerButton}
diff --git a/webapp/components/signup/signup_controller.jsx b/webapp/components/signup/signup_controller.jsx index 5a9e535a8..e9024a389 100644 --- a/webapp/components/signup/signup_controller.jsx +++ b/webapp/components/signup/signup_controller.jsx @@ -18,7 +18,7 @@ import {addUserToTeamFromInvite, getInviteInfo} from 'actions/team_actions.jsx'; import {loadMe} from 'actions/user_actions.jsx'; import logoImage from 'images/logo.png'; -import ErrorBar from 'components/error_bar.jsx'; +import AnnouncementBar from 'components/announcement_bar'; import {FormattedMessage} from 'react-intl'; import {browserHistory, Link} from 'react-router/es6'; @@ -319,7 +319,7 @@ export default class SignupController extends React.Component { return (
- +
-- cgit v1.2.3-1-g7c22