From 0e801a4e70f3d9c8e3cf929aa2f7ac201ca87b52 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Wed, 28 Oct 2015 15:04:17 -0400 Subject: Add tutorial intro screens for new users. --- web/react/components/navbar_dropdown.jsx | 2 +- .../components/tutorial/tutorial_intro_screens.jsx | 150 +++++++++++++++++++++ 2 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 web/react/components/tutorial/tutorial_intro_screens.jsx (limited to 'web/react/components') diff --git a/web/react/components/navbar_dropdown.jsx b/web/react/components/navbar_dropdown.jsx index dc21fad21..f43bdffdf 100644 --- a/web/react/components/navbar_dropdown.jsx +++ b/web/react/components/navbar_dropdown.jsx @@ -104,7 +104,7 @@ export default class NavbarDropdown extends React.Component { ); - if (this.props.teamType === 'O') { + if (this.props.teamType === Constants.OPEN_TEAM) { teamLink = (
  • +

    {'Welcome to:'}

    +

    {'Mattermost'}

    +
    + {'Your team communications all in one place,'} +
    + {'instantly searchable and available anywhere.'} +

    + {'Keep your team connected to help them'} +
    + {'achieve what matters most.'} +

    + {'[ x ][ ][ ]'} + + ); + } + createScreenTwo() { + return ( +
    +

    {'How Mattermost works:'}

    +
    + {'Communication happens in public discussion channels,'} +
    + {'private groups and direct messages.'} +

    + {'Everything is archived and searchable from'} +
    + {'any web-enabled laptop, tablet or phone.'} +

    + {'[ ][ x ][ ]'} +
    + ); + } + createScreenThree() { + const team = TeamStore.getCurrent(); + let inviteModalLink; + if (team.type === Constants.INVITE_TEAM) { + inviteModalLink = ( +
    + {'Invite teammates'} + + ); + } else { + inviteModalLink = ( + + ); + } + + return ( +
    +

    {'You’re all set'}

    +
    + {inviteModalLink} + {' when you’re ready.'} +

    + {'Need anything, just email us at '} +
    + {'feedback@mattermost.com.'} + +

    + {'Click “Next” to enter Town Square. This is the first channel'} +
    + {'teammates see when they sign up - use it for posting updates'} +
    + {'everyone needs to know.'} +

    + {'[ ][ ][ x ]'} +
    + ); + } + render() { + const screen = this.createScreen(); + + return ( +
    + {screen} +

    + +
    + ); + } +} -- cgit v1.2.3-1-g7c22 From 97449a102e5592358a4f7f22d6720a9af21286a1 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Fri, 30 Oct 2015 11:35:16 -0400 Subject: Add tutorial popovers --- web/react/components/create_post.jsx | 62 +++++++++--- web/react/components/sidebar.jsx | 68 +++++++++++-- web/react/components/sidebar_header.jsx | 89 ++++++++++++++++- .../components/tutorial/tutorial_intro_screens.jsx | 14 ++- web/react/components/tutorial/tutorial_tip.jsx | 108 +++++++++++++++++++++ 5 files changed, 313 insertions(+), 28 deletions(-) create mode 100644 web/react/components/tutorial/tutorial_tip.jsx (limited to 'web/react/components') diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index 7c601af4b..1dc30e251 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -1,21 +1,26 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +const MsgTyping = require('./msg_typing.jsx'); +const Textbox = require('./textbox.jsx'); +const FileUpload = require('./file_upload.jsx'); +const FilePreview = require('./file_preview.jsx'); +const TutorialTip = require('./tutorial/tutorial_tip.jsx'); + const AppDispatcher = require('../dispatcher/app_dispatcher.jsx'); const Client = require('../utils/client.jsx'); const AsyncClient = require('../utils/async_client.jsx'); +const Utils = require('../utils/utils.jsx'); + const ChannelStore = require('../stores/channel_store.jsx'); const PostStore = require('../stores/post_store.jsx'); const UserStore = require('../stores/user_store.jsx'); -const SocketStore = require('../stores/socket_store.jsx'); const PreferenceStore = require('../stores/preference_store.jsx'); -const MsgTyping = require('./msg_typing.jsx'); -const Textbox = require('./textbox.jsx'); -const FileUpload = require('./file_upload.jsx'); -const FilePreview = require('./file_preview.jsx'); -const Utils = require('../utils/utils.jsx'); +const SocketStore = require('../stores/socket_store.jsx'); const Constants = require('../utils/constants.jsx'); +const Preferences = Constants.Preferences; +const TutorialSteps = Constants.TutorialSteps; const ActionTypes = Constants.ActionTypes; const KeyCodes = Constants.KeyCodes; @@ -36,15 +41,16 @@ export default class CreatePost extends React.Component { this.handleTextDrop = this.handleTextDrop.bind(this); this.removePreview = this.removePreview.bind(this); this.onChange = this.onChange.bind(this); + this.onPreferenceChange = this.onPreferenceChange.bind(this); this.getFileCount = this.getFileCount.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this); this.handleResize = this.handleResize.bind(this); this.sendMessage = this.sendMessage.bind(this); - this.onPreferenceChange = this.onPreferenceChange.bind(this); PostStore.clearDraftUploads(); const draft = this.getCurrentDraft(); + const tutorialPref = PreferenceStore.getPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), {value: '0'}); this.state = { channelId: ChannelStore.getCurrentId(), @@ -55,16 +61,12 @@ export default class CreatePost extends React.Component { initialText: draft.messageText, windowWidth: Utils.windowWidth(), windowHeight: Utils.windowHeight(), - ctrlSend: PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', {value: 'false'}).value + ctrlSend: PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', {value: 'false'}).value, + showTutorialTip: parseInt(tutorialPref.value, 10) === TutorialSteps.POST_POPOVER }; PreferenceStore.addChangeListener(this.onPreferenceChange); } - onPreferenceChange() { - this.setState({ - ctrlSend: PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', {value: 'false'}).value - }); - } handleResize() { this.setState({ windowWidth: Utils.windowWidth(), @@ -318,11 +320,13 @@ export default class CreatePost extends React.Component { } componentDidMount() { ChannelStore.addChangeListener(this.onChange); + PreferenceStore.addChangeListener(this.onPreferenceChange); this.resizePostHolder(); window.addEventListener('resize', this.handleResize); } componentWillUnmount() { ChannelStore.removeChangeListener(this.onChange); + PreferenceStore.removeChangeListener(this.onPreferenceChange); window.removeEventListener('resize', this.handleResize); } onChange() { @@ -333,6 +337,13 @@ export default class CreatePost extends React.Component { this.setState({channelId, messageText: draft.messageText, initialText: draft.messageText, submitting: false, serverError: null, postError: null, previews: draft.previews, uploadsInProgress: draft.uploadsInProgress}); } } + onPreferenceChange() { + const tutorialPref = PreferenceStore.getPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), {value: '0'}); + this.setState({ + showTutorialTip: parseInt(tutorialPref.value, 10) === TutorialSteps.POST_POPOVER, + ctrlSend: PreferenceStore.getPreference(Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, 'send_on_ctrl_enter', {value: 'false'}).value + }); + } getFileCount(channelId) { if (channelId === this.state.channelId) { return this.state.previews.length + this.state.uploadsInProgress.length; @@ -367,6 +378,25 @@ export default class CreatePost extends React.Component { }); } } + createTutorialTip() { + const screens = []; + + screens.push( +
    +

    {'Sending Messages'}

    + {'Type here to write a message.'} +

    + {'Click the attachment button to upload an image or a file.'} +
    + ); + + return ( + + ); + } render() { let serverError = null; if (this.state.serverError) { @@ -398,6 +428,11 @@ export default class CreatePost extends React.Component { postFooterClassName += ' has-error'; } + let tutorialTip = null; + if (this.state.showTutorialTip) { + tutorialTip = this.createTutorialTip(); + } + return (
    + {tutorialTip}
    {postError} diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 023955e97..c3f43ff69 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -1,19 +1,26 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -const AsyncClient = require('../utils/async_client.jsx'); -const ChannelStore = require('../stores/channel_store.jsx'); -const Client = require('../utils/client.jsx'); -const Constants = require('../utils/constants.jsx'); -const PreferenceStore = require('../stores/preference_store.jsx'); const NewChannelFlow = require('./new_channel_flow.jsx'); const MoreDirectChannels = require('./more_direct_channels.jsx'); const SearchBox = require('./search_bar.jsx'); const SidebarHeader = require('./sidebar_header.jsx'); -const TeamStore = require('../stores/team_store.jsx'); const UnreadChannelIndicator = require('./unread_channel_indicator.jsx'); +const TutorialTip = require('./tutorial/tutorial_tip.jsx'); + +const ChannelStore = require('../stores/channel_store.jsx'); const UserStore = require('../stores/user_store.jsx'); +const TeamStore = require('../stores/team_store.jsx'); +const PreferenceStore = require('../stores/preference_store.jsx'); + +const AsyncClient = require('../utils/async_client.jsx'); +const Client = require('../utils/client.jsx'); const Utils = require('../utils/utils.jsx'); + +const Constants = require('../utils/constants.jsx'); +const Preferences = Constants.Preferences; +const TutorialSteps = Constants.TutorialSteps; + const Tooltip = ReactBootstrap.Tooltip; const OverlayTrigger = ReactBootstrap.OverlayTrigger; @@ -155,12 +162,15 @@ export default class Sidebar extends React.Component { visibleDirectChannels.sort(this.sortChannelsByDisplayName); + const tutorialPref = PreferenceStore.getPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), {value: '0'}); + return { activeId: currentId, channels: ChannelStore.getAll(), members, visibleDirectChannels, - hiddenDirectChannelCount + hiddenDirectChannelCount, + showTutorialTip: parseInt(tutorialPref.value, 10) === TutorialSteps.CHANNEL_POPOVER }; } @@ -308,6 +318,44 @@ export default class Sidebar extends React.Component { this.setState({showDirectChannelsModal: false}); } + createTutorialTip() { + const screens = []; + + screens.push( +
    +

    {'Channels'}

    + {'Channels'}{' organize conversations across different topics. They’re open to everyone on your team. To send private communications use '}{'Direct Messages'}{' for a single person or '}{'Private Groups'}{' for multiple people.'} +
    + ); + + screens.push( +
    +

    {'"Town Square" and "Off-Topic" channels'}

    + {'Here are two public channels to start:'} +

    + {'Town Square'}{' is a place for team-wide communication. Everyone in your team is a member of this channel.'} +

    + {'Off-Topic'}{' is a place for fun and humor outside of work-related channels. You and your team can decide what other channels to create.'} +
    + ); + + screens.push( +
    +

    {'Creating and Joining Channels'}

    + {'Click '}{'"More..."'}{' to create a new channel or join an existing one.'} +

    + {'You can also create a new channel or private group by clicking the '}{'"+" symbol'}{' next to the channel or private group header.'} +
    + ); + + return ( + + ); + } + createChannelElement(channel, index, arr, handleClose) { var members = this.state.members; var activeId = this.state.activeId; @@ -444,6 +492,11 @@ export default class Sidebar extends React.Component { rowClass += ' has-close'; } + let tutorialTip = null; + if (this.state.showTutorialTip && channel.name === Constants.DEFAULT_CHANNEL) { + tutorialTip = this.createTutorialTip(); + } + return (
  • + {tutorialTip}
  • ); } diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 65e4c6d7e..96348f688 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -1,9 +1,16 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -var NavbarDropdown = require('./navbar_dropdown.jsx'); -var UserStore = require('../stores/user_store.jsx'); +const NavbarDropdown = require('./navbar_dropdown.jsx'); +const TutorialTip = require('./tutorial/tutorial_tip.jsx'); + +const UserStore = require('../stores/user_store.jsx'); +const PreferenceStore = require('../stores/preference_store.jsx'); + const Utils = require('../utils/utils.jsx'); +const Constants = require('../utils/constants.jsx'); +const Preferences = Constants.Preferences; +const TutorialSteps = Constants.TutorialSteps; const Tooltip = ReactBootstrap.Tooltip; const OverlayTrigger = ReactBootstrap.OverlayTrigger; @@ -13,8 +20,23 @@ export default class SidebarHeader extends React.Component { super(props); this.toggleDropdown = this.toggleDropdown.bind(this); + this.onPreferenceChange = this.onPreferenceChange.bind(this); - this.state = {}; + this.state = this.getStateFromStores(); + } + componentDidMount() { + PreferenceStore.addChangeListener(this.onPreferenceChange); + } + componentWillUnmount() { + PreferenceStore.removeChangeListener(this.onPreferenceChange); + } + getStateFromStores() { + const tutorialPref = PreferenceStore.getPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), {value: '0'}); + + return {showTutorialTip: parseInt(tutorialPref.value, 10) === TutorialSteps.MENU_POPOVER}; + } + onPreferenceChange() { + this.setState(this.getStateFromStores()); } toggleDropdown(e) { e.preventDefault(); @@ -22,8 +44,63 @@ export default class SidebarHeader extends React.Component { this.refs.dropdown.blockToggle = false; return; } + console.log(this.refs.tip); + this.refs.tip.toggle(); $('.team__header').find('.dropdown-toggle').dropdown('toggle'); } + createTutorialTip() { + const screens = []; + + let teamSettingsLink = {'Team Settings'}; + if (Utils.isAdmin(UserStore.getCurrentUser().roles)) { + teamSettingsLink = ( + + {'Team Settings'} + + ); + } + + screens.push( +
    +

    {'Sending Messages'}

    + {'The '}{'Main Menu'}{' is where you can '} + + {'Invite New Members'} + + {', access your '} + + {'Account Settings'} + + {', and set your '}{'Theme Color'}{'.'} +

    + {'Team administrators can also access their '}{teamSettingsLink}{' from this menu.'} +
    + ); + + return ( +
    + +
    + ); + } render() { var me = UserStore.getCurrentUser(); var profilePicture = null; @@ -41,8 +118,14 @@ export default class SidebarHeader extends React.Component { ); } + let tutorialTip = null; + if (this.state.showTutorialTip) { + tutorialTip = this.createTutorialTip(); + } + return (
    + {tutorialTip} = this.props.screens.length - 1) { + let preference = PreferenceStore.getPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), {value: '0'}); + + const newValue = (parseInt(preference.value, 10) + 1).toString(); + + preference = PreferenceStore.setPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), newValue); + AsyncClient.savePreferences([preference]); + } + } + handleNext() { + if (this.state.currentScreen < this.props.screens.length - 1) { + this.setState({currentScreen: this.state.currentScreen + 1}); + return; + } + + this.toggle(); + } + skipTutorial(e) { + e.preventDefault(); + const preference = PreferenceStore.setPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), '999'); + AsyncClient.savePreferences([preference]); + } + render() { + const buttonText = this.state.currentScreen === this.props.screens.length - 1 ? 'Okay' : 'Next'; + + const dots = []; + if (this.props.screens.length > 1) { + for (let i = 0; i < this.props.screens.length; i++) { + if (i === this.state.currentScreen) { + dots.push({'[ x ]'}); + } else { + dots.push({'[ ]'}); + } + } + } + + return ( + + ); + } +} + +TutorialTip.propTypes = { + screens: React.PropTypes.array.isRequired, + placement: React.PropTypes.string.isRequired +}; -- cgit v1.2.3-1-g7c22 From 393d253021e6b119ec35b92f9eeaa6f2d255008f Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Mon, 2 Nov 2015 11:40:53 +0500 Subject: Updating tutorial screens --- web/react/components/create_post.jsx | 7 +- web/react/components/sidebar.jsx | 30 +++--- .../components/tutorial/tutorial_intro_screens.jsx | 107 +++++++++++---------- web/react/components/tutorial/tutorial_tip.jsx | 51 ++++++---- 4 files changed, 106 insertions(+), 89 deletions(-) (limited to 'web/react/components') diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index 1dc30e251..cb3148b7b 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -383,10 +383,9 @@ export default class CreatePost extends React.Component { screens.push(
    -

    {'Sending Messages'}

    - {'Type here to write a message.'} -

    - {'Click the attachment button to upload an image or a file.'} +

    {'Sending Messages'}

    +

    {'Type here to write a message.'}

    +

    {'Click the attachment button to upload an image or a file.'}

    ); diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index c3f43ff69..39d9808e9 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -323,28 +323,34 @@ export default class Sidebar extends React.Component { screens.push(
    -

    {'Channels'}

    - {'Channels'}{' organize conversations across different topics. They’re open to everyone on your team. To send private communications use '}{'Direct Messages'}{' for a single person or '}{'Private Groups'}{' for multiple people.'} +

    {'Channels'}

    +

    {'Channels'}{' organize conversations across different topics. They’re open to everyone on your team. To send private communications use '}{'Direct Messages'}{' for a single person or '}{'Private Groups'}{' for multiple people.'} +

    ); screens.push(
    -

    {'"Town Square" and "Off-Topic" channels'}

    - {'Here are two public channels to start:'} -

    - {'Town Square'}{' is a place for team-wide communication. Everyone in your team is a member of this channel.'} -

    - {'Off-Topic'}{' is a place for fun and humor outside of work-related channels. You and your team can decide what other channels to create.'} +

    {'"Town Square" and "Off-Topic" channels'}

    +

    {'Here are two public channels to start:'}

    +

    + {'Town Square'}{' is a place for team-wide communication. Everyone in your team is a member of this channel.'} +

    +

    + {'Off-Topic'}{' is a place for fun and humor outside of work-related channels. You and your team can decide what other channels to create.'} +

    ); screens.push(
    -

    {'Creating and Joining Channels'}

    - {'Click '}{'"More..."'}{' to create a new channel or join an existing one.'} -

    - {'You can also create a new channel or private group by clicking the '}{'"+" symbol'}{' next to the channel or private group header.'} +

    {'Creating and Joining Channels'}

    +

    + {'Click '}{'"More..."'}{' to create a new channel or join an existing one.'} +

    +

    + {'You can also create a new channel or private group by clicking the '}{'"+" symbol'}{' next to the channel or private group header.'} +

    ); diff --git a/web/react/components/tutorial/tutorial_intro_screens.jsx b/web/react/components/tutorial/tutorial_intro_screens.jsx index d423b4f1b..b37aac27c 100644 --- a/web/react/components/tutorial/tutorial_intro_screens.jsx +++ b/web/react/components/tutorial/tutorial_intro_screens.jsx @@ -20,6 +20,10 @@ export default class TutorialIntroScreens extends React.Component { this.state = {currentScreen: 0}; } + componentDidMount() { + const height = $(window).outerHeight() - 120; + $('.tutorial-steps__container').css('height', `${height}px`); + } handleNext() { if (this.state.currentScreen < 2) { this.setState({currentScreen: this.state.currentScreen + 1}); @@ -48,35 +52,29 @@ export default class TutorialIntroScreens extends React.Component { createScreenOne() { return (
    -

    {'Welcome to:'}

    -

    {'Mattermost'}

    -
    - {'Your team communications all in one place,'} -
    - {'instantly searchable and available anywhere.'} -

    - {'Keep your team connected to help them'} -
    - {'achieve what matters most.'} -

    - {'[ x ][ ][ ]'} +

    {'Welcome to:'}

    +

    {'Mattermost'}

    +

    {'Your team communications all in one place, instantly searchable and available anywhere.'}

    +

    {'Keep your team connected to help them achieve what matters most.'}

    +
    +
    +
    +
    +
    ); } createScreenTwo() { return (
    -

    {'How Mattermost works:'}

    -
    - {'Communication happens in public discussion channels,'} -
    - {'private groups and direct messages.'} -

    - {'Everything is archived and searchable from'} -
    - {'any web-enabled laptop, tablet or phone.'} -

    - {'[ ][ x ][ ]'} +

    {'How Mattermost works:'}

    +

    {'Communication happens in public discussion channels, private groups and direct messages.'}

    +

    {'Everything is archived and searchable from any web-enabled laptop, tablet or phone.'}

    +
    +
    +
    +
    +
    ); } @@ -111,26 +109,26 @@ export default class TutorialIntroScreens extends React.Component { return (
    -

    {'You’re all set'}

    -
    - {inviteModalLink} - {' when you’re ready.'} -

    - {'Need anything, just email us at '} - - {'feedback@mattermost.com.'} - -

    - {'Click “Next” to enter Town Square. This is the first channel'} -
    - {'teammates see when they sign up - use it for posting updates'} -
    - {'everyone needs to know.'} -

    - {'[ ][ ][ x ]'} +

    {'You’re all set'}

    +

    + {inviteModalLink} + {' when you’re ready.'} +

    +

    + {'Need anything, just email us at '} + + {'feedback@mattermost.com.'} + +

    + {'Click “Next” to enter Town Square. This is the first channel teammates see when they sign up - use it for posting updates everyone needs to know.'} +
    +
    +
    +
    +
    ); } @@ -138,16 +136,19 @@ export default class TutorialIntroScreens extends React.Component { const screen = this.createScreen(); return ( -
    - {screen} -

    - +
    +
    +
    + {screen} + +
    +
    ); } diff --git a/web/react/components/tutorial/tutorial_tip.jsx b/web/react/components/tutorial/tutorial_tip.jsx index 166d10d8a..3482a7cfa 100644 --- a/web/react/components/tutorial/tutorial_tip.jsx +++ b/web/react/components/tutorial/tutorial_tip.jsx @@ -52,9 +52,19 @@ export default class TutorialTip extends React.Component { if (this.props.screens.length > 1) { for (let i = 0; i < this.props.screens.length; i++) { if (i === this.state.currentScreen) { - dots.push({'[ x ]'}); + dots.push( +
    + ); } else { - dots.push({'[ ]'}); + dots.push( +
    + ); } } } @@ -63,7 +73,8 @@ export default class TutorialTip extends React.Component {
    @@ -77,24 +88,24 @@ export default class TutorialTip extends React.Component { >
    {this.props.screens[this.state.currentScreen]} -
    - {dots} - -
    - - {'Seen this before? '} - {dots}
    +
    + +
    + {'Seen this before? '} + + {'Opt out of these tips.'} + +
    +
    -- cgit v1.2.3-1-g7c22 From dedbc122c666a68de4759be7b7c70e698e3e2c28 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Mon, 2 Nov 2015 09:21:08 -0500 Subject: Overlay fixes and added class prop for tips --- web/react/components/create_post.jsx | 1 + web/react/components/sidebar.jsx | 1 + web/react/components/sidebar_header.jsx | 3 +-- web/react/components/tutorial/tutorial_tip.jsx | 15 +++++++++++++-- 4 files changed, 16 insertions(+), 4 deletions(-) (limited to 'web/react/components') diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index cb3148b7b..1545cdfaa 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -393,6 +393,7 @@ export default class CreatePost extends React.Component { ); } diff --git a/web/react/components/sidebar.jsx b/web/react/components/sidebar.jsx index 39d9808e9..c47919885 100644 --- a/web/react/components/sidebar.jsx +++ b/web/react/components/sidebar.jsx @@ -358,6 +358,7 @@ export default class Sidebar extends React.Component { ); } diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 96348f688..0d48c6f88 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -44,8 +44,6 @@ export default class SidebarHeader extends React.Component { this.refs.dropdown.blockToggle = false; return; } - console.log(this.refs.tip); - this.refs.tip.toggle(); $('.team__header').find('.dropdown-toggle').dropdown('toggle'); } createTutorialTip() { @@ -97,6 +95,7 @@ export default class SidebarHeader extends React.Component { ref='tip' placement='right' screens={screens} + overlayClass='tip-overlay--sidebar' />
    ); diff --git a/web/react/components/tutorial/tutorial_tip.jsx b/web/react/components/tutorial/tutorial_tip.jsx index 3482a7cfa..118209599 100644 --- a/web/react/components/tutorial/tutorial_tip.jsx +++ b/web/react/components/tutorial/tutorial_tip.jsx @@ -79,6 +79,12 @@ export default class TutorialTip extends React.Component { ref='target' /> + +
    + + this.refs.target} > -
    +
    {this.props.screens[this.state.currentScreen]}
    {dots}
    @@ -113,7 +119,12 @@ export default class TutorialTip extends React.Component { } } +TutorialTip.defaultProps = { + overlayClass: '' +}; + TutorialTip.propTypes = { screens: React.PropTypes.array.isRequired, - placement: React.PropTypes.string.isRequired + placement: React.PropTypes.string.isRequired, + overlayClass: React.PropTypes.string }; -- cgit v1.2.3-1-g7c22 From 4c5c42e37415df75d398027b6c2a6ea39e138688 Mon Sep 17 00:00:00 2001 From: Asaad Mahmood Date: Mon, 2 Nov 2015 20:57:23 +0500 Subject: Updating tutorials UI --- web/react/components/sidebar_header.jsx | 9 ++++++--- web/react/components/tutorial/tutorial_tip.jsx | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'web/react/components') diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 0d48c6f88..1bf70ce76 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -64,7 +64,8 @@ export default class SidebarHeader extends React.Component { screens.push( ); @@ -95,7 +98,7 @@ export default class SidebarHeader extends React.Component { ref='tip' placement='right' screens={screens} - overlayClass='tip-overlay--sidebar' + overlayClass='tip-overlay--header' />
    ); diff --git a/web/react/components/tutorial/tutorial_tip.jsx b/web/react/components/tutorial/tutorial_tip.jsx index 118209599..c85acb346 100644 --- a/web/react/components/tutorial/tutorial_tip.jsx +++ b/web/react/components/tutorial/tutorial_tip.jsx @@ -70,7 +70,7 @@ export default class TutorialTip extends React.Component { } return ( -
    +
    this.refs.target} >
    +
    {this.props.screens[this.state.currentScreen]}
    {dots}
    -- cgit v1.2.3-1-g7c22 From 51617a03bc191b1a0931c916abca21366fd2aeaf Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Mon, 2 Nov 2015 11:10:32 -0500 Subject: Remove modal links from tip --- web/react/components/sidebar_header.jsx | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) (limited to 'web/react/components') diff --git a/web/react/components/sidebar_header.jsx b/web/react/components/sidebar_header.jsx index 1bf70ce76..949c82a3b 100644 --- a/web/react/components/sidebar_header.jsx +++ b/web/react/components/sidebar_header.jsx @@ -49,43 +49,18 @@ export default class SidebarHeader extends React.Component { createTutorialTip() { const screens = []; - let teamSettingsLink = {'Team Settings'}; - if (Utils.isAdmin(UserStore.getCurrentUser().roles)) { - teamSettingsLink = ( - - {'Team Settings'} - - ); - } - screens.push(

    {'Main Menu'}

    {'The '}{'Main Menu'}{' is where you can '} - - {'Invite New Members'} - + {'Invite New Members'} {', access your '} - - {'Account Settings'} - + {'Account Settings'} {', and set your '}{'Theme Color'}{'.'}

    - {'Team administrators can also access their '}{teamSettingsLink}{' from this menu.'} + {'Team administrators can also access their '}{'Team Settings'}{' from this menu.'}

    ); -- cgit v1.2.3-1-g7c22 From 95da41257155e4d1d8201471e7ae1f5d96450189 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Mon, 2 Nov 2015 11:13:21 -0500 Subject: Move period out of link --- web/react/components/tutorial/tutorial_intro_screens.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'web/react/components') diff --git a/web/react/components/tutorial/tutorial_intro_screens.jsx b/web/react/components/tutorial/tutorial_intro_screens.jsx index b37aac27c..0f3050156 100644 --- a/web/react/components/tutorial/tutorial_intro_screens.jsx +++ b/web/react/components/tutorial/tutorial_intro_screens.jsx @@ -120,8 +120,9 @@ export default class TutorialIntroScreens extends React.Component { href='mailto:feedback@mattermost.com' target='_blank' > - {'feedback@mattermost.com.'} + {'feedback@mattermost.com'} + {'.'}

    {'Click “Next” to enter Town Square. This is the first channel teammates see when they sign up - use it for posting updates everyone needs to know.'}
    -- cgit v1.2.3-1-g7c22 From 35b11e0e61fd3c7130c3f54601ba05dd0b52fba3 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Mon, 2 Nov 2015 15:10:46 -0500 Subject: Fix merge issues --- web/react/components/center_panel.jsx | 42 ++++++++++++++++++---- web/react/components/channel_view.jsx | 8 ++--- web/react/components/posts_view_container.jsx | 9 +++-- web/react/components/sidebar_header.jsx | 2 +- .../components/tutorial/tutorial_intro_screens.jsx | 4 --- 5 files changed, 47 insertions(+), 18 deletions(-) (limited to 'web/react/components') diff --git a/web/react/components/center_panel.jsx b/web/react/components/center_panel.jsx index b871fe81a..a471c8af1 100644 --- a/web/react/components/center_panel.jsx +++ b/web/react/components/center_panel.jsx @@ -1,17 +1,47 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -var CreatePost = require('../components/create_post.jsx'); -var PostsViewContainer = require('../components/posts_view_container.jsx'); -var ChannelHeader = require('../components/channel_header.jsx'); -var Navbar = require('../components/navbar.jsx'); -var FileUploadOverlay = require('../components/file_upload_overlay.jsx'); +const TutorialIntroScreens = require('./tutorial/tutorial_intro_screens.jsx'); +const CreatePost = require('./create_post.jsx'); +const PostsViewContainer = require('./posts_view_container.jsx'); +const ChannelHeader = require('./channel_header.jsx'); +const Navbar = require('./navbar.jsx'); +const FileUploadOverlay = require('./file_upload_overlay.jsx'); + +const PreferenceStore = require('../stores/preference_store.jsx'); +const UserStore = require('../stores/user_store.jsx'); + +const Constants = require('../utils/constants.jsx'); +const TutorialSteps = Constants.TutorialSteps; +const Preferences = Constants.Preferences; export default class CenterPanel extends React.Component { constructor(props) { super(props); + + this.onPreferenceChange = this.onPreferenceChange.bind(this); + + const tutorialPref = PreferenceStore.getPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), {value: '0'}); + this.state = {showTutorialScreens: parseInt(tutorialPref.value, 10) === TutorialSteps.INTRO_SCREENS}; + } + componentDidMount() { + PreferenceStore.addChangeListener(this.onPreferenceChange); + } + componentWillUnmount() { + PreferenceStore.removeChangeListener(this.onPreferenceChange); + } + onPreferenceChange() { + const tutorialPref = PreferenceStore.getPreference(Preferences.TUTORIAL_STEP, UserStore.getCurrentId(), {value: '0'}); + this.setState({showTutorialScreens: parseInt(tutorialPref.value, 10) <= TutorialSteps.INTRO_SCREENS}); } render() { + let postsContainer + if (this.state.showTutorialScreens) { + postsContainer = ; + } else { + postsContainer = ; + } + return (
    @@ -32,7 +62,7 @@ export default class CenterPanel extends React.Component {
    - + {postsContainer}
    {'Invite New Members'} {', access your '} {'Account Settings'} - {', and set your '}{'Theme Color'}{'.'} + {' and set your '}{'Theme Color'}{'.'}

    {'Team administrators can also access their '}{'Team Settings'}{' from this menu.'} diff --git a/web/react/components/tutorial/tutorial_intro_screens.jsx b/web/react/components/tutorial/tutorial_intro_screens.jsx index 0f3050156..c7abccae3 100644 --- a/web/react/components/tutorial/tutorial_intro_screens.jsx +++ b/web/react/components/tutorial/tutorial_intro_screens.jsx @@ -20,10 +20,6 @@ export default class TutorialIntroScreens extends React.Component { this.state = {currentScreen: 0}; } - componentDidMount() { - const height = $(window).outerHeight() - 120; - $('.tutorial-steps__container').css('height', `${height}px`); - } handleNext() { if (this.state.currentScreen < 2) { this.setState({currentScreen: this.state.currentScreen + 1}); -- cgit v1.2.3-1-g7c22 From 6b1e80d1d55783016d295f3f116891ce65ae6b06 Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Mon, 2 Nov 2015 15:24:21 -0500 Subject: Fix typo --- web/react/components/center_panel.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'web/react/components') diff --git a/web/react/components/center_panel.jsx b/web/react/components/center_panel.jsx index a471c8af1..242c2c637 100644 --- a/web/react/components/center_panel.jsx +++ b/web/react/components/center_panel.jsx @@ -35,7 +35,7 @@ export default class CenterPanel extends React.Component { this.setState({showTutorialScreens: parseInt(tutorialPref.value, 10) <= TutorialSteps.INTRO_SCREENS}); } render() { - let postsContainer + let postsContainer; if (this.state.showTutorialScreens) { postsContainer = ; } else { -- cgit v1.2.3-1-g7c22