diff options
Diffstat (limited to 'web')
28 files changed, 326 insertions, 237 deletions
diff --git a/web/react/components/admin_console/image_settings.jsx b/web/react/components/admin_console/image_settings.jsx index 12bf554ea..86f78e093 100644 --- a/web/react/components/admin_console/image_settings.jsx +++ b/web/react/components/admin_console/image_settings.jsx @@ -8,10 +8,6 @@ import crypto from 'crypto'; import {injectIntl, intlShape, defineMessages, FormattedMessage} from 'mm-intl'; const holders = defineMessages({ - storeDisabled: { - id: 'admin.image.storeDisabled', - defaultMessage: 'Disable File Storage' - }, storeLocal: { id: 'admin.image.storeLocal', defaultMessage: 'Local File System' @@ -242,7 +238,6 @@ class FileSettings extends React.Component { defaultValue={this.props.config.FileSettings.DriverName} onChange={this.handleChange.bind(this, 'DriverName')} > - <option value=''>{formatMessage(holders.storeDisabled)}</option> <option value='local'>{formatMessage(holders.storeLocal)}</option> <option value='amazons3'>{formatMessage(holders.storeAmazonS3)}</option> </select> diff --git a/web/react/components/admin_console/user_item.jsx b/web/react/components/admin_console/user_item.jsx index 02b01b090..0c1a55cc1 100644 --- a/web/react/components/admin_console/user_item.jsx +++ b/web/react/components/admin_console/user_item.jsx @@ -360,8 +360,8 @@ export default class UserItem extends React.Component { height='36' width='36' /> - <span className='member-name'>{Utils.getDisplayName(user)}</span> - <span className='member-email'>{email}</span> + <span className='more-name'>{Utils.getDisplayName(user)}</span> + <span className='more-description'>{email}</span> <div className='dropdown member-drop'> <a href='#' diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx index 65ffa96a1..95b2e58a8 100644 --- a/web/react/components/delete_post_modal.jsx +++ b/web/react/components/delete_post_modal.jsx @@ -173,7 +173,7 @@ export default class DeletePostModal extends React.Component { <Modal.Body> <FormattedMessage id='delete_post.question' - defaultMessage='Are you sure you want to delete this ${term}?' + defaultMessage='Are you sure you want to delete this {term}?' values={{ term: (postTerm) }} diff --git a/web/react/components/member_list_item.jsx b/web/react/components/member_list_item.jsx index c50ee5c96..41ea58eeb 100644 --- a/web/react/components/member_list_item.jsx +++ b/web/react/components/member_list_item.jsx @@ -124,8 +124,8 @@ export default class MemberListItem extends React.Component { height='36' width='36' /> - <div className='member-name'>{Utils.displayUsername(member.id)}</div> - <div className='member-description'>{member.email}</div> + <div className='more-name'>{Utils.displayUsername(member.id)}</div> + <div className='more-description'>{member.email}</div> </td> <td className='td--action lg'>{invite}</td> </tr> diff --git a/web/react/components/member_list_team_item.jsx b/web/react/components/member_list_team_item.jsx index 6e1006911..30086d1b2 100644 --- a/web/react/components/member_list_team_item.jsx +++ b/web/react/components/member_list_team_item.jsx @@ -208,8 +208,8 @@ export default class MemberListTeamItem extends React.Component { height='36' width='36' /> - <span className='member-name'>{Utils.displayUsername(user.id)}</span> - <span className='member-email'>{email}</span> + <span className='more-name'>{Utils.displayUsername(user.id)}</span> + <span className='more-description'>{email}</span> <div className='dropdown member-drop'> <a href='#' diff --git a/web/react/components/more_channels.jsx b/web/react/components/more_channels.jsx index d12ea4703..d800f93d8 100644 --- a/web/react/components/more_channels.jsx +++ b/web/react/components/more_channels.jsx @@ -114,7 +114,7 @@ export default class MoreChannels extends React.Component { <tr key={channel.id}> <td> <p className='more-name'>{channel.display_name}</p> - <p className='more-purpose'>{channel.purpose}</p> + <p className='more-description'>{channel.purpose}</p> </td> <td className='td--action'> {joinButton} diff --git a/web/react/components/posts_view.jsx b/web/react/components/posts_view.jsx index f108ace2e..ebe19abad 100644 --- a/web/react/components/posts_view.jsx +++ b/web/react/components/posts_view.jsx @@ -94,7 +94,7 @@ export default class PostsView extends React.Component { }); } - this.scrollStopAction.fireAfter(1000); + this.scrollStopAction.fireAfter(2000); } handleScrollStop() { this.setState({ @@ -564,6 +564,8 @@ function ScrollToBottomArrows({isScrolling, atBottom, onClick}) { <div className={className} onClick={onClick} - /> + > + <span dangerouslySetInnerHTML={{__html: Constants.SCROLL_BOTTOM_ICON}} /> + </div> ); } diff --git a/web/react/components/search_results.jsx b/web/react/components/search_results.jsx index 9dcc99061..4adc3afe0 100644 --- a/web/react/components/search_results.jsx +++ b/web/react/components/search_results.jsx @@ -1,6 +1,7 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +import ChannelStore from '../stores/channel_store.jsx'; import SearchStore from '../stores/search_store.jsx'; import UserStore from '../stores/user_store.jsx'; import SearchBox from './search_bar.jsx'; @@ -11,7 +12,22 @@ import SearchResultsItem from './search_results_item.jsx'; import {FormattedMessage, FormattedHTMLMessage} from 'mm-intl'; function getStateFromStores() { - return {results: SearchStore.getSearchResults()}; + const results = SearchStore.getSearchResults(); + + const channels = new Map(); + const channelIds = results.order.map((postId) => results.posts[postId].channel_id); + for (const id of channelIds) { + if (channels.has(id)) { + continue; + } + + channels.set(id, ChannelStore.get(id)); + } + + return { + results, + channels + }; } export default class SearchResults extends React.Component { @@ -33,16 +49,22 @@ export default class SearchResults extends React.Component { componentDidMount() { this.mounted = true; SearchStore.addSearchChangeListener(this.onChange); + ChannelStore.addChangeListener(this.onChange); this.resize(); window.addEventListener('resize', this.handleResize); } + shouldComponentUpdate(nextProps, nextState) { + return !Utils.areObjectsEqual(this.props, nextProps) || !Utils.areObjectsEqual(this.state, nextState); + } + componentDidUpdate() { this.resize(); } componentWillUnmount() { SearchStore.removeSearchChangeListener(this.onChange); + ChannelStore.removeChangeListener(this.onChange); this.mounted = false; window.removeEventListener('resize', this.handleResize); } @@ -56,10 +78,7 @@ export default class SearchResults extends React.Component { onChange() { if (this.mounted) { - var newState = getStateFromStores(); - if (!Utils.areObjectsEqual(newState, this.state)) { - this.setState(newState); - } + this.setState(getStateFromStores()); } } @@ -116,6 +135,7 @@ export default class SearchResults extends React.Component { return ( <SearchResultsItem key={post.id} + channel={this.state.channels.get(post.channel_id)} post={post} term={searchTerm} isMentionSearch={this.props.isMentionSearch} diff --git a/web/react/components/search_results_item.jsx b/web/react/components/search_results_item.jsx index 544ba920a..d3533037f 100644 --- a/web/react/components/search_results_item.jsx +++ b/web/react/components/search_results_item.jsx @@ -1,7 +1,6 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import ChannelStore from '../stores/channel_store.jsx'; import UserStore from '../stores/user_store.jsx'; import UserProfile from './user_profile.jsx'; import * as EventHelpers from '../dispatcher/event_helpers.jsx'; @@ -37,8 +36,8 @@ export default class SearchResultsItem extends React.Component { } render() { - var channelName = ''; - var channel = ChannelStore.get(this.props.post.channel_id); + var channelName = null; + const channel = this.props.channel; var timestamp = UserStore.getCurrentUser().update_at; if (channel) { @@ -136,6 +135,7 @@ export default class SearchResultsItem extends React.Component { SearchResultsItem.propTypes = { post: React.PropTypes.object, + channel: React.PropTypes.object, isMentionSearch: React.PropTypes.bool, term: React.PropTypes.string }; diff --git a/web/react/components/signup_user_complete.jsx b/web/react/components/signup_user_complete.jsx index 672213d1a..b770a2a2c 100644 --- a/web/react/components/signup_user_complete.jsx +++ b/web/react/components/signup_user_complete.jsx @@ -362,6 +362,17 @@ class SignupUserComplete extends React.Component { ); } + if (signupMessage.length === 0 && !emailSignup) { + emailSignup = ( + <div> + <FormattedMessage + id='signup_user_completed.none' + defaultMessage='No user creation method has been enabled. Please contact an administrator for access.' + /> + </div> + ); + } + return ( <div> <form> diff --git a/web/react/components/user_settings/manage_command_hooks.jsx b/web/react/components/user_settings/manage_command_hooks.jsx index d23d2957e..f4009aeaa 100644 --- a/web/react/components/user_settings/manage_command_hooks.jsx +++ b/web/react/components/user_settings/manage_command_hooks.jsx @@ -18,7 +18,7 @@ const holders = defineMessages({ }, addDisplayNamePlaceholder: { id: 'user.settings.cmds.add_display_name.placeholder', - defaultMessage: 'Display Name' + defaultMessage: 'Example: "Search patient records"' }, addUsernamePlaceholder: { id: 'user.settings.cmds.add_username.placeholder', @@ -30,11 +30,11 @@ const holders = defineMessages({ }, addAutoCompleteDescPlaceholder: { id: 'user.settings.cmds.auto_complete_desc.placeholder', - defaultMessage: 'A short description of what this commands does.' + defaultMessage: 'Example: "Returns search results for patient records"' }, addAutoCompleteHintPlaceholder: { id: 'user.settings.cmds.auto_complete_hint.placeholder', - defaultMessage: '[zipcode]' + defaultMessage: 'Example: [Patient Name]' }, adUrlPlaceholder: { id: 'user.settings.cmds.url.placeholder', @@ -261,7 +261,7 @@ export default class ManageCommandCmds extends React.Component { <strong> <FormattedMessage id='user.settings.cmds.trigger' - defaultMessage='Trigger: ' + defaultMessage='Command Trigger Word: ' /> </strong>{cmd.trigger} </div> @@ -271,21 +271,43 @@ export default class ManageCommandCmds extends React.Component { cmds.push( <div key={cmd.id} - className='webcmd__item' + className='webhook__item webcmd__item' > + {triggerDiv} + <div className='padding-top x2 webcmd__url'> + <strong> + <FormattedMessage + id='user.settings.cmds.url' + defaultMessage='Request URL: ' + /> + </strong><span className='word-break--all'>{cmd.url}</span> + </div> <div className='padding-top x2'> <strong> <FormattedMessage - id='user.settings.cmds.display_name' - defaultMessage='Display Name: ' + id='user.settings.cmds.request_type' + defaultMessage='Request Method: ' /> - </strong><span className='word-break--all'>{cmd.display_name}</span> + </strong> + <span className='word-break--all'> + { + cmd.method === 'P' ? + <FormattedMessage + id='user.settings.cmds.request_type_post' + defaultMessage='POST' + /> : + <FormattedMessage + id='user.settings.cmds.request_type_get' + defaultMessage='GET' + /> + } + </span> </div> <div className='padding-top x2'> <strong> <FormattedMessage id='user.settings.cmds.username' - defaultMessage='Username: ' + defaultMessage='Response Username: ' /> </strong><span className='word-break--all'>{cmd.username}</span> </div> @@ -293,7 +315,7 @@ export default class ManageCommandCmds extends React.Component { <strong> <FormattedMessage id='user.settings.cmds.icon_url' - defaultMessage='Icon URL: ' + defaultMessage='Response Icon: ' /> </strong><span className='word-break--all'>{cmd.icon_url}</span> </div> @@ -301,56 +323,34 @@ export default class ManageCommandCmds extends React.Component { <strong> <FormattedMessage id='user.settings.cmds.auto_complete' - defaultMessage='Auto Complete: ' + defaultMessage='Autocomplete: ' /> </strong><span className='word-break--all'>{cmd.auto_complete ? this.props.intl.formatMessage(holders.autocompleteYes) : this.props.intl.formatMessage(holders.autocompleteNo)}</span> </div> <div className='padding-top x2'> <strong> <FormattedMessage - id='user.settings.cmds.auto_complete_desc' - defaultMessage='Auto Complete Description: ' - /> - </strong><span className='word-break--all'>{cmd.auto_complete_desc}</span> - </div> - <div className='padding-top x2'> - <strong> - <FormattedMessage id='user.settings.cmds.auto_complete_hint' - defaultMessage='Auto Complete Hint: ' + defaultMessage='Autocomplete Hint: ' /> </strong><span className='word-break--all'>{cmd.auto_complete_hint}</span> </div> <div className='padding-top x2'> <strong> <FormattedMessage - id='user.settings.cmds.request_type' - defaultMessage='Request Type: ' + id='user.settings.cmds.auto_complete_desc' + defaultMessage='Autocomplete Description: ' /> - </strong> - <span className='word-break--all'> - { - cmd.method === 'P' ? - <FormattedMessage - id='user.settings.cmds.request_type_post' - defaultMessage='POST' - /> : - <FormattedMessage - id='user.settings.cmds.request_type_get' - defaultMessage='GET' - /> - } - </span> + </strong><span className='word-break--all'>{cmd.auto_complete_desc}</span> </div> - <div className='padding-top x2 webcmd__url'> + <div className='padding-top x2'> <strong> <FormattedMessage - id='user.settings.cmds.url' - defaultMessage='URL: ' + id='user.settings.cmds.display_name' + defaultMessage='Descriptive Label: ' /> - </strong><span className='word-break--all'>{cmd.url}</span> + </strong><span className='word-break--all'>{cmd.display_name}</span> </div> - {triggerDiv} <div className='padding-top'> <strong> <FormattedMessage @@ -400,7 +400,7 @@ export default class ManageCommandCmds extends React.Component { } const existingCmds = ( - <div className='webcmds__container'> + <div className='webhooks__container webcmds__container'> <label className='control-label padding-top x2'> <FormattedMessage id='user.settings.cmds.existing' @@ -408,7 +408,7 @@ export default class ManageCommandCmds extends React.Component { /> </label> <div className='padding-top divider-light'></div> - <div className='webcmds__list'> + <div className='webhooks__list webcmds__list'> {displayCmds} </div> </div> @@ -420,7 +420,7 @@ export default class ManageCommandCmds extends React.Component { <div key='addCommandCmd'> <FormattedHTMLMessage id='user.settings.cmds.add_desc' - defaultMessage='Create commands to send message events to an external integration. Please see <a href="http://mattermost.org/commands">http://mattermost.org/commands</a> to learn more.' + defaultMessage='Create slash commands to send events to external integrations and receive a response. For example typing `/patient Joe Smith` could bring back search results from your internal health records management system for the name “Joe Smith”. Please see <a href="http://docs.mattermost.com/developer/slash-commands.html">Slash commands documentation</a> for detailed instructions.' /> <div><label className='control-label padding-top x2'> <FormattedMessage @@ -430,103 +430,139 @@ export default class ManageCommandCmds extends React.Component { </label></div> <div className='padding-top divider-light'></div> <div className='padding-top'> + <div className='padding-top x2'> <label className='control-label'> <FormattedMessage - id='user.settings.cmds.display_name' - defaultMessage='Display Name: ' + id='user.settings.cmds.trigger' + defaultMessage='Command Trigger Word: ' /> </label> <div className='padding-top'> <input - ref='displayName' + ref='trigger' className='form-control' - value={this.state.cmd.display_name} - onChange={this.updateDisplayName} - placeholder={this.props.intl.formatMessage(holders.addDisplayNamePlaceholder)} + value={this.state.cmd.trigger} + onChange={this.updateTrigger} + placeholder={this.props.intl.formatMessage(holders.addTriggerPlaceholder)} /> </div> <div className='padding-top'> <FormattedMessage - id='user.settings.cmds.cmd_display_name' - defaultMessage='Command display name.' + id='user.settings.cmds.trigger_desc' + defaultMessage='Examples: /patient, /client, /employee Reserved: /echo, /join, /logout, /me, /shrug' /> </div> </div> + <div className='padding-top x2'> <label className='control-label'> <FormattedMessage - id='user.settings.cmds.username' - defaultMessage='Username: ' + id='user.settings.cmds.url' + defaultMessage='Request URL: ' /> </label> <div className='padding-top'> - <input - ref='username' - className='form-control' - value={this.state.cmd.username} - onChange={this.updateUsername} - placeholder={this.props.intl.formatMessage(holders.addUsernamePlaceholder)} + <input + ref='URL' + className='form-control' + value={this.state.cmd.url} + rows={1} + onChange={this.updateURL} + placeholder={this.props.intl.formatMessage(holders.adUrlPlaceholder)} + /> + </div> + <div className='padding-top'> + <FormattedMessage + id='user.settings.cmds.url_desc' + defaultMessage='The callback URL to receive the HTTP POST or GET event request when the slash command is run.' /> </div> + </div> + + <div className='padding-top x2'> + <label className='control-label'> + <FormattedMessage + id='user.settings.cmds.request_type' + defaultMessage='Request Method: ' + /> + </label> + <div className='padding-top'> + <select + ref='method' + className='form-control' + value={this.state.cmd.method} + onChange={this.updateMethod} + > + <option value='P'> + {this.props.intl.formatMessage(holders.requestTypePost)} + </option> + <option value='G'> + {this.props.intl.formatMessage(holders.requestTypeGet)} + </option> + </select> + </div> <div className='padding-top'> <FormattedMessage - id='user.settings.cmds.username_desc' - defaultMessage='The username to use when overriding the post.' + id='user.settings.cmds.request_type_desc' + defaultMessage='The type of command request issued to the Request URL.' /> </div> </div> + <div className='padding-top x2'> <label className='control-label'> <FormattedMessage - id='user.settings.cmds.icon_url' - defaultMessage='Icon URL: ' + id='user.settings.cmds.username' + defaultMessage='Response Username: ' /> </label> <div className='padding-top'> <input - ref='iconURL' + ref='username' className='form-control' - value={this.state.cmd.icon_url} - onChange={this.updateIconURL} - placeholder='https://www.example.com/myicon.png' + value={this.state.cmd.username} + onChange={this.updateUsername} + placeholder={this.props.intl.formatMessage(holders.addUsernamePlaceholder)} /> </div> <div className='padding-top'> <FormattedMessage - id='user.settings.cmds.icon_url_desc' - defaultMessage='URL to an icon' + id='user.settings.cmds.username_desc' + defaultMessage='Choose a username override for responses for this slash command. Usernames can consist of up to 22 characters consisting of lowercase letters, numbers and they symbols "-", "_", and "." .' /> </div> </div> + <div className='padding-top x2'> <label className='control-label'> <FormattedMessage - id='user.settings.cmds.trigger' - defaultMessage='Trigger: ' + id='user.settings.cmds.icon_url' + defaultMessage='Response Icon: ' /> </label> <div className='padding-top'> <input - ref='trigger' + ref='iconURL' className='form-control' - value={this.state.cmd.trigger} - onChange={this.updateTrigger} - placeholder={this.props.intl.formatMessage(holders.addTriggerPlaceholder)} + value={this.state.cmd.icon_url} + onChange={this.updateIconURL} + placeholder='https://www.example.com/myicon.png' /> </div> <div className='padding-top'> <FormattedMessage - id='user.settings.cmds.trigger_desc' - defaultMessage='Word to trigger on' + id='user.settings.cmds.icon_url_desc' + defaultMessage='Choose a profile picture override for the post responses to this slash command. Enter the URL of a .png or .jpg file at least 128 pixels by 128 pixels.' /> - {''}</div> + </div> </div> + <div className='padding-top x2'> <label className='control-label'> <FormattedMessage id='user.settings.cmds.auto_complete' - defaultMessage='Auto Complete: ' + defaultMessage='Autocomplete: ' /> </label> <div className='padding-top'> @@ -539,34 +575,18 @@ export default class ManageCommandCmds extends React.Component { /> <FormattedMessage id='user.settings.cmds.auto_complete_help' - defaultMessage=' Show this command in autocomplete list' + defaultMessage=' Show this command in the autocomplete list.' /> </label> </div> </div> </div> - <div className='padding-top x2'> - <label className='control-label'> - <FormattedMessage - id='user.settings.cmds.auto_complete_desc' - defaultMessage='Auto Complete Description: ' - /> - </label> - <div className='padding-top'> - <input - ref='autoCompleteDesc' - className='form-control' - value={this.state.cmd.auto_complete_desc} - onChange={this.updateAutoCompleteDesc} - placeholder={this.props.intl.formatMessage(holders.addAutoCompleteDescPlaceholder)} - /> - </div> - </div> + <div className='padding-top x2'> <label className='control-label'> <FormattedMessage id='user.settings.cmds.auto_complete_hint' - defaultMessage='Auto Complete Hint: ' + defaultMessage='Autocomplete Hint: ' /> </label> <div className='padding-top'> @@ -581,64 +601,60 @@ export default class ManageCommandCmds extends React.Component { <div className='padding-top'> <FormattedMessage id='user.settings.cmds.auto_complete_hint_desc' - defaultMessage='List parameters to be passed to the command.' + defaultMessage='Optional hint in the autocomplete list about parameters needed for command.' /> </div> </div> + <div className='padding-top x2'> <label className='control-label'> <FormattedMessage - id='user.settings.cmds.request_type' - defaultMessage='Request Type: ' + id='user.settings.cmds.auto_complete_desc' + defaultMessage='Autocomplete Description: ' /> </label> <div className='padding-top'> - <select - ref='method' + <input + ref='autoCompleteDesc' className='form-control' - value={this.state.cmd.method} - onChange={this.updateMethod} - > - <option value='P'> - {this.props.intl.formatMessage(holders.requestTypePost)} - </option> - <option value='G'> - {this.props.intl.formatMessage(holders.requestTypeGet)} - </option> - </select> + value={this.state.cmd.auto_complete_desc} + onChange={this.updateAutoCompleteDesc} + placeholder={this.props.intl.formatMessage(holders.addAutoCompleteDescPlaceholder)} + /> </div> <div className='padding-top'> <FormattedMessage - id='user.settings.cmds.request_type_desc' - defaultMessage='Command request type issued to the callback URL.' + id='user.settings.cmds.auto_complete_desc_desc' + defaultMessage='Optional short description of slash command for the autocomplete list.' /> </div> </div> + <div className='padding-top x2'> <label className='control-label'> <FormattedMessage - id='user.settings.cmds.url' - defaultMessage='URL: ' + id='user.settings.cmds.display_name' + defaultMessage='Descriptive Label: ' /> </label> <div className='padding-top'> - <input - ref='URL' - className='form-control' - value={this.state.cmd.url} - rows={1} - onChange={this.updateURL} - placeholder={this.props.intl.formatMessage(holders.adUrlPlaceholder)} - /> + <input + ref='displayName' + className='form-control' + value={this.state.cmd.display_name} + onChange={this.updateDisplayName} + placeholder={this.props.intl.formatMessage(holders.addDisplayNamePlaceholder)} + /> </div> <div className='padding-top'> <FormattedMessage - id='user.settings.cmds.url_desc' - defaultMessage='URL that will receive the HTTP POST or GET event' + id='user.settings.cmds.cmd_display_name' + defaultMessage='Brief description of slash command to show in listings.' /> </div> {addError} </div> + <div className='padding-top x2 padding-bottom'> <a className={'btn btn-sm btn-primary'} diff --git a/web/react/components/user_settings/user_settings_integrations.jsx b/web/react/components/user_settings/user_settings_integrations.jsx index 1a9edab03..07d5230d1 100644 --- a/web/react/components/user_settings/user_settings_integrations.jsx +++ b/web/react/components/user_settings/user_settings_integrations.jsx @@ -28,11 +28,11 @@ const holders = defineMessages({ }, cmdName: { id: 'user.settings.integrations.commands', - defaultMessage: 'Commands' + defaultMessage: 'Slash Commands' }, cmdDesc: { id: 'user.settings.integrations.commandsDescription', - defaultMessage: 'Manage your commands' + defaultMessage: 'Manage your slash commands' } }); diff --git a/web/react/components/user_settings/user_settings_modal.jsx b/web/react/components/user_settings/user_settings_modal.jsx index e0b72157b..a7541073e 100644 --- a/web/react/components/user_settings/user_settings_modal.jsx +++ b/web/react/components/user_settings/user_settings_modal.jsx @@ -113,6 +113,7 @@ class UserSettingsModal extends React.Component { return false; } + this.resetTheme(); this.deactivateTab(); this.props.onModalDismissed(); } @@ -215,15 +216,19 @@ class UserSettingsModal extends React.Component { this.showConfirmModal(() => this.updateSection(section, true)); } else { if (this.state.active_section === 'theme' && section !== 'theme') { - const user = UserStore.getCurrentUser(); - if (user.theme_props != null) { - Utils.applyTheme(user.theme_props); - } + this.resetTheme(); } this.setState({active_section: section}); } } + resetTheme() { + const user = UserStore.getCurrentUser(); + if (user.theme_props != null) { + Utils.applyTheme(user.theme_props); + } + } + render() { const {formatMessage} = this.props.intl; var tabs = []; @@ -234,7 +239,7 @@ class UserSettingsModal extends React.Component { tabs.push({name: 'developer', uiName: formatMessage(holders.developer), icon: 'glyphicon glyphicon-th'}); } - if (global.window.mm_config.EnableIncomingWebhooks === 'true' || global.window.mm_config.EnableOutgoingWebhooks === 'true') { + if (global.window.mm_config.EnableIncomingWebhooks === 'true' || global.window.mm_config.EnableOutgoingWebhooks === 'true' || global.window.mm_config.EnableCommands === 'true') { tabs.push({name: 'integrations', uiName: formatMessage(holders.integrations), icon: 'glyphicon glyphicon-transfer'}); } tabs.push({name: 'display', uiName: formatMessage(holders.display), icon: 'glyphicon glyphicon-eye-open'}); diff --git a/web/react/stores/channel_store.jsx b/web/react/stores/channel_store.jsx index d650b23c2..ac800a988 100644 --- a/web/react/stores/channel_store.jsx +++ b/web/react/stores/channel_store.jsx @@ -308,7 +308,7 @@ ChannelStore.dispatchToken = AppDispatcher.register((payload) => { ChannelStore.storeChannels(action.channels); ChannelStore.storeChannelMembers(action.members); currentId = ChannelStore.getCurrentId(); - if (currentId) { + if (currentId && !document.hidden) { ChannelStore.resetCounts(currentId); } ChannelStore.setUnreadCounts(); @@ -321,7 +321,7 @@ ChannelStore.dispatchToken = AppDispatcher.register((payload) => { ChannelStore.pStoreChannelMember(action.member); } currentId = ChannelStore.getCurrentId(); - if (currentId) { + if (currentId && !document.hidden) { ChannelStore.resetCounts(currentId); } ChannelStore.setUnreadCount(action.channel.id); diff --git a/web/react/stores/socket_store.jsx b/web/react/stores/socket_store.jsx index bc2bdbe64..e1b65fe14 100644 --- a/web/react/stores/socket_store.jsx +++ b/web/react/stores/socket_store.jsx @@ -188,7 +188,9 @@ function handleNewPostEvent(msg, translations) { // Update channel state if (ChannelStore.getCurrentId() === msg.channel_id) { - if (window.isActive) { + if (document.hidden) { + AsyncClient.getChannel(msg.channel_id); + } else { AsyncClient.updateLastViewedAt(); } } else if (UserStore.getCurrentId() !== msg.user_id || post.type !== Constants.POST_TYPE_JOIN_LEAVE) { diff --git a/web/react/utils/async_client.jsx b/web/react/utils/async_client.jsx index d5fc10b8f..c8676f45d 100644 --- a/web/react/utils/async_client.jsx +++ b/web/react/utils/async_client.jsx @@ -779,13 +779,19 @@ export function getSuggestedCommands(command, suggestionId, component) { var matches = []; data.forEach((cmd) => { if (('/' + cmd.trigger).indexOf(command) === 0) { + let s = '/' + cmd.trigger; + if (cmd.auto_complete_hint && cmd.auto_complete_hint.length !== 0) { + s += ' ' + cmd.auto_complete_hint; + } matches.push({ - suggestion: '/' + cmd.trigger + ' ' + cmd.auto_complete_hint, + suggestion: s, description: cmd.auto_complete_desc }); } }); + matches = matches.sort((a, b) => a.suggestion.localeCompare(b.suggestion)); + // pull out the suggested commands from the returned data const terms = matches.map((suggestion) => suggestion.suggestion); diff --git a/web/react/utils/constants.jsx b/web/react/utils/constants.jsx index 0a055d55c..428549d57 100644 --- a/web/react/utils/constants.jsx +++ b/web/react/utils/constants.jsx @@ -174,6 +174,7 @@ export default { MENU_ICON: "<svg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px'width='4px' height='16px' viewBox='0 0 8 32' enable-background='new 0 0 8 32' xml:space='preserve'> <g> <circle cx='4' cy='4.062' r='4'/> <circle cx='4' cy='16' r='4'/> <circle cx='4' cy='28' r='4'/> </g> </svg>", COMMENT_ICON: "<svg version='1.1' id='Layer_2' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px'width='15px' height='15px' viewBox='1 1.5 15 15' enable-background='new 1 1.5 15 15' xml:space='preserve'> <g> <g> <path fill='#211B1B' d='M14,1.5H3c-1.104,0-2,0.896-2,2v8c0,1.104,0.896,2,2,2h1.628l1.884,3l1.866-3H14c1.104,0,2-0.896,2-2v-8 C16,2.396,15.104,1.5,14,1.5z M15,11.5c0,0.553-0.447,1-1,1H8l-1.493,2l-1.504-1.991L5,12.5H3c-0.552,0-1-0.447-1-1v-8 c0-0.552,0.448-1,1-1h11c0.553,0,1,0.448,1,1V11.5z'/> </g> </g> </svg>", REPLY_ICON: "<svg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px'viewBox='-158 242 18 18' style='enable-background:new -158 242 18 18;' xml:space='preserve'> <path d='M-142.2,252.6c-2-3-4.8-4.7-8.3-4.8v-3.3c0-0.2-0.1-0.3-0.2-0.3s-0.3,0-0.4,0.1l-6.9,6.2c-0.1,0.1-0.1,0.2-0.1,0.3 c0,0.1,0,0.2,0.1,0.3l6.9,6.4c0.1,0.1,0.3,0.1,0.4,0.1c0.1-0.1,0.2-0.2,0.2-0.4v-3.8c4.2,0,7.4,0.4,9.6,4.4c0.1,0.1,0.2,0.2,0.3,0.2 c0,0,0.1,0,0.1,0c0.2-0.1,0.3-0.3,0.2-0.4C-140.2,257.3-140.6,255-142.2,252.6z M-150.8,252.5c-0.2,0-0.4,0.2-0.4,0.4v3.3l-6-5.5 l6-5.3v2.8c0,0.2,0.2,0.4,0.4,0.4c3.3,0,6,1.5,8,4.5c0.5,0.8,0.9,1.6,1.2,2.3C-144,252.8-147.1,252.5-150.8,252.5z'/> </svg>", + SCROLL_BOTTOM_ICON: "<svg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px'viewBox='-239 239 21 23' style='enable-background:new -239 239 21 23;' xml:space='preserve'> <path d='M-239,241.4l2.4-2.4l8.1,8.2l8.1-8.2l2.4,2.4l-10.5,10.6L-239,241.4z M-228.5,257.2l8.1-8.2l2.4,2.4l-10.5,10.6l-10.5-10.6 l2.4-2.4L-228.5,257.2z'/> </svg>", UPDATE_TYPING_MS: 5000, THEMES: { default: { diff --git a/web/react/utils/markdown.jsx b/web/react/utils/markdown.jsx index 47b3a9a66..8b3602a89 100644 --- a/web/react/utils/markdown.jsx +++ b/web/react/utils/markdown.jsx @@ -151,6 +151,10 @@ class MattermostMarkdownRenderer extends marked.Renderer { ); } + codespan(text) { + return '<pre class="text-nowrap">' + super.codespan(text) + '</pre>'; + } + br() { if (this.formattingOptions.singleline) { return ' '; diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index 896a94ac5..e2a5b9620 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -392,6 +392,10 @@ export function areObjectsEqual(x, y) { return x.toString() === y.toString(); } + if (x instanceof Map && y instanceof Map) { + return areMapsEqual(x, y); + } + // At last checking prototypes as good a we can if (!(x instanceof Object && y instanceof Object)) { return false; @@ -456,6 +460,24 @@ export function areObjectsEqual(x, y) { return true; } +export function areMapsEqual(a, b) { + if (a.size !== b.size) { + return false; + } + + for (const [key, value] of a) { + if (!b.has(key)) { + return false; + } + + if (!areObjectsEqual(value, b.get(key))) { + return false; + } + } + + return true; +} + export function replaceHtmlEntities(text) { var tagsToReplace = { '&': '&', @@ -680,6 +702,7 @@ export function applyTheme(theme) { } if (theme.centerChannelColor) { + changeCss('.post-list__arrows', 'fill:' + changeOpacity(theme.centerChannelColor, 0.3), 1); changeCss('.sidebar--left, .sidebar--right .sidebar--right__header', 'border-color:' + changeOpacity(theme.centerChannelColor, 0.2), 1); changeCss('.app__content, .post-create__container .post-create-body .btn-file, .post-create__container .post-create-footer .msg-typing, .command-name, .modal .modal-content, .dropdown-menu, .popover, .mentions-name, .tip-overlay', 'color:' + theme.centerChannelColor, 1); changeCss('#archive-link-home', 'background:' + changeOpacity(theme.centerChannelColor, 0.15), 1); diff --git a/web/sass-files/sass/partials/_markdown.scss b/web/sass-files/sass/partials/_markdown.scss index 14e12ecd2..a08379ae1 100644 --- a/web/sass-files/sass/partials/_markdown.scss +++ b/web/sass-files/sass/partials/_markdown.scss @@ -39,6 +39,7 @@ padding: 4px 10px 5px 10px; font-size: 13px; opacity: 0.7; + z-index: 5; } .post__body { @@ -53,6 +54,13 @@ code { white-space: pre; } + pre { + &.text-nowrap { + code { + white-space: nowrap; + } + } + } } .markdown__table { background: #fff; diff --git a/web/sass-files/sass/partials/_mentions.scss b/web/sass-files/sass/partials/_mentions.scss index df6dd40a2..aa654e9e8 100644 --- a/web/sass-files/sass/partials/_mentions.scss +++ b/web/sass-files/sass/partials/_mentions.scss @@ -18,6 +18,13 @@ line-height: 36px; font-size: 13px; cursor: pointer; + white-space: nowrap; + + .mention-align { + @include clearfix; + text-overflow: ellipsis; + width: calc(100% - 50px); + } } .mentions-text { @@ -33,6 +40,15 @@ font-size: 20px; text-align: center; @include border-radius(32px); + + .mention-align { + max-width: 80%; + overflow: hidden; + display: inline-block; + white-space: nowrap; + text-overflow: ellipsis; + } + } .mention-fullname { diff --git a/web/sass-files/sass/partials/_modal.scss b/web/sass-files/sass/partials/_modal.scss index b451adb75..db99e840b 100644 --- a/web/sass-files/sass/partials/_modal.scss +++ b/web/sass-files/sass/partials/_modal.scss @@ -103,7 +103,7 @@ background: rgba(0, 0, 0, 0.1); } span { - font-family: 'Open Sans', sans-serif; + font-family: 'Open Sans', sans-serif; line-height: 10px; } } @@ -170,6 +170,12 @@ overflow: hidden; text-overflow: ellipsis; } + .more-description { + @include opacity(0.7); + display: block; + overflow: hidden; + text-overflow: ellipsis; + } tbody { > tr { &:hover td { @@ -425,9 +431,9 @@ } .modal-body.edit-modal-body { - overflow: visible; + overflow: visible; - .suggestion-content { - max-height: 150px; - } + .suggestion-content { + max-height: 150px; + } } diff --git a/web/sass-files/sass/partials/_popover.scss b/web/sass-files/sass/partials/_popover.scss index 8a61758f1..bf762d2c9 100644 --- a/web/sass-files/sass/partials/_popover.scss +++ b/web/sass-files/sass/partials/_popover.scss @@ -150,6 +150,9 @@ } .more-name { margin-left: 6px; + max-width: 140px; + overflow: hidden; + text-overflow: ellipsis; } } } diff --git a/web/sass-files/sass/partials/_post.scss b/web/sass-files/sass/partials/_post.scss index cc22cc913..323691d89 100644 --- a/web/sass-files/sass/partials/_post.scss +++ b/web/sass-files/sass/partials/_post.scss @@ -264,32 +264,37 @@ body.ios { line-height: 25px; margin-left: -60px; -webkit-font-smoothing: initial; - @include single-transition(all, 0.3s, ease); + @include single-transition(all, 0.6s, ease); @include translateY(-45px); @include opacity(0); display: none; &.scrolling { - @include single-transition(all, 0.3s, ease); @include translateY(0); @include opacity(0.8); } } .post-list__arrows { - background: url('../images/postArrows.png') center; - @include background-size(28px 28px); background-repeat: no-repeat; width: 40px; height: 40px; + text-align: center; + fill: #444; position: absolute; bottom: 0; - left: 10px; + left: 9px; z-index: 50; @include opacity(0); - @include single-transition(all, 0.3s); + @include single-transition(all, 0.6s); display: none; + svg { + color: inherit; + width: 28px; + height: 28px; + } + &.scrolling { display: block; @include opacity(1); @@ -487,7 +492,7 @@ body.ios { position: absolute; top: -2px; left: -7px; - font-size: 11px; + font-size: 11px; line-height: 37px; @include opacity(0); } diff --git a/web/sass-files/sass/partials/_settings.scss b/web/sass-files/sass/partials/_settings.scss index bf296e913..1bbec566c 100644 --- a/web/sass-files/sass/partials/_settings.scss +++ b/web/sass-files/sass/partials/_settings.scss @@ -223,6 +223,8 @@ .section-describe { @include opacity(0.7); white-space:pre; + @include clearfix; + text-overflow: ellipsis; } .divider-dark { @@ -341,21 +343,6 @@ h3 { @include border-radius(50px); margin-right: 8px; } - .member-name { - font-weight:500; - display: block; - max-width: 80%; - overflow: hidden; - text-overflow: ellipsis; - } - - .member-email { - color:darkgrey; - display: block; - max-width: 80%; - overflow: hidden; - text-overflow: ellipsis; - } } .member-role, .member-drop { diff --git a/web/static/i18n/en.json b/web/static/i18n/en.json index b4a68425e..ade6462e9 100644 --- a/web/static/i18n/en.json +++ b/web/static/i18n/en.json @@ -148,7 +148,6 @@ "admin.gitlab.userTitle": "User API Endpoint:", "admin.gitlab.userDescription": "Enter https://<your-gitlab-url>/api/v3/user. Make sure you use HTTP or HTTPS in your URL depending on your server configuration.", "admin.gitlab.save": "Save", - "admin.image.storeDisabled": "Disable File Storage", "admin.image.storeLocal": "Local File System", "admin.image.storeAmazonS3": "Amazon S3", "admin.image.localExample": "Ex \"./data/\"", @@ -580,7 +579,7 @@ "delete_post.comment": "Comment", "delete_post.post": "Post", "delete_post.confirm": "Confirm {term} Delete", - "delete_post.question": "Are you sure you want to delete this ${term}?", + "delete_post.question": "Are you sure you want to delete this {term}?", "delete_post.cancel": "Cancel", "delete_post.del": "Delete", "edit_channel_header_modal.error": "This channel header is too long, please enter a shorter one", @@ -902,6 +901,7 @@ "signup_user_completed.choosePwd": "Choose your password", "signup_user_completed.create": "Create Account", "signup_user_completed.or": "or", + "signup_user_completed.none": "No user creation method has been enabled. Please contact an administrator for access.", "signup_user_completed.welcome": "Welcome to:", "signup_user_completed.onSite": "on {siteName}", "signup_user_completed.lets": "Let's create your account", @@ -1063,37 +1063,38 @@ "user.settings.import_theme.submit": "Submit", "user.settings.cmds.request_type_post": "POST", "user.settings.cmds.request_type_get": "GET", - "user.settings.cmds.add_display_name.placeholder": "Display Name", + "user.settings.cmds.add_display_name.placeholder": "Example: \"Search patient records\"", "user.settings.cmds.add_username.placeholder": "Username", "user.settings.cmds.add_trigger.placeholder": "Command trigger e.g. \"hello\" not including the slash", - "user.settings.cmds.auto_complete_desc.placeholder": "A short description of what this commands does.", - "user.settings.cmds.auto_complete_hint.placeholder": "[zipcode]", + "user.settings.cmds.auto_complete_desc.placeholder": "Example: \"Returns search results for patient records\"", + "user.settings.cmds.auto_complete_hint.placeholder": "Example: [Patient Name]", + "user.settings.cmds.auto_complete_desc_desc": "Optional short description of slash command for the autocomplete list.", "user.settings.cmds.url.placeholder": "Must start with http:// or https://", "user.settings.cmds.auto_complete.yes": "yes", "user.settings.cmds.auto_complete.no": "no", - "user.settings.cmds.trigger": "Trigger: ", - "user.settings.cmds.display_name": "Display Name: ", - "user.settings.cmds.username": "Username: ", - "user.settings.cmds.icon_url": "Icon URL: ", - "user.settings.cmds.auto_complete": "Auto Complete: ", - "user.settings.cmds.auto_complete_desc": "Auto Complete Description: ", - "user.settings.cmds.auto_complete_hint": "Auto Complete Hint: ", - "user.settings.cmds.request_type": "Request Type: ", - "user.settings.cmds.url": "URL: ", + "user.settings.cmds.trigger": "Command Trigger Word: ", + "user.settings.cmds.display_name": "Descriptive Label: ", + "user.settings.cmds.username": "Response Username: ", + "user.settings.cmds.icon_url": "Response Icon: ", + "user.settings.cmds.auto_complete": "Autocomplete: ", + "user.settings.cmds.auto_complete_desc": "Autocomplete Description: ", + "user.settings.cmds.auto_complete_hint": "Autocomplete Hint: ", + "user.settings.cmds.request_type": "Request Method: ", + "user.settings.cmds.url": "Request URL: ", "user.settings.cmds.token": "Token: ", "user.settings.cmds.regen": "Regen Token", "user.settings.cmds.none": "None", "user.settings.cmds.existing": "Existing commands", - "user.settings.cmds.add_desc": "Create commands to send message events to an external integration. Please see <a href=\"http://mattermost.org/commands\">http://mattermost.org/commands</a> to learn more.", + "user.settings.cmds.add_desc": "Create slash commands to send events to external integrations and receive a response. For example typing `/patient Joe Smith` could bring back search results from your internal health records management system for the name 'Joe Smith'. Please see <a href=\"http://docs.mattermost.com/developer/slash-commands.html\">Slash commands documentation</a> for detailed instructions.", "user.settings.cmds.add_new": "Add a new command", - "user.settings.cmds.cmd_display_name": "Command display name.", - "user.settings.cmds.username_desc": "The username to use when overriding the post.", - "user.settings.cmds.icon_url_desc": "URL to an icon", - "user.settings.cmds.trigger_desc": "Word to trigger on", - "user.settings.cmds.auto_complete_help": "Show this command in autocomplete list", - "user.settings.cmds.auto_complete_hint_desc": "List parameters to be passed to the command.", - "user.settings.cmds.request_type_desc": "Command request type issued to the callback URL.", - "user.settings.cmds.url_desc": "URL that will receive the HTTP POST or GET event", + "user.settings.cmds.cmd_display_name": "Brief description of slash command to show in listings.", + "user.settings.cmds.username_desc": "Choose a username override for responses for this slash command. Usernames can consist of up to 22 characters consisting of lowercase letters, numbers and they symbols \"-\", \"_\", and \".\" .", + "user.settings.cmds.icon_url_desc": "Choose a profile picture override for the post responses to this slash command. Enter the URL of a .png or .jpg file at least 128 pixels by 128 pixels.", + "user.settings.cmds.trigger_desc": "Examples: /patient, /client, /employee Reserved: /echo, /join, /logout, /me, /shrug", + "user.settings.cmds.auto_complete_help": " Show this command in the autocomplete list.", + "user.settings.cmds.auto_complete_hint_desc": "Optional hint in the autocomplete list about parameters needed for command.", + "user.settings.cmds.request_type_desc": "The type of command request issued to the Request URL.", + "user.settings.cmds.url_desc": "The callback URL to receive the HTTP POST or GET event request when the slash command is run.", "user.settings.cmds.add": "Add", "user.settings.hooks_in.channel": "Channel: ", "user.settings.hooks_in.none": "None", @@ -1183,8 +1184,8 @@ "user.settings.integrations.incomingWebhooksDescription": "Manage your incoming webhooks", "user.settings.integrations.outWebhooks": "Outgoing Webhooks", "user.settings.integrations.outWebhooksDescription": "Manage your outgoing webhooks", - "user.settings.integrations.commands": "Commands", - "user.settings.integrations.commandsDescription": "Manage your commands", + "user.settings.integrations.commands": "Slash Commands", + "user.settings.integrations.commandsDescription": "Manage your slash commands", "user.settings.integrations.title": "Integration Settings", "user.settings.modal.general": "General", "user.settings.modal.security": "Security", diff --git a/web/static/i18n/es.json b/web/static/i18n/es.json index a3c7e13a7..e4ddd76ce 100644 --- a/web/static/i18n/es.json +++ b/web/static/i18n/es.json @@ -157,7 +157,6 @@ "admin.image.shareDescription": "Permitir a los usuarios compartir enlaces públicos para archivos e imágenes.", "admin.image.shareTitle": "Compartir publicamente enlaces de archivos: ", "admin.image.storeAmazonS3": "Amazon S3", - "admin.image.storeDisabled": "Deshabilitar almacenamiento de archivos", "admin.image.storeLocal": "Sistema local de archivos", "admin.image.storeTitle": "Almacenar archivos en:", "admin.image.thumbHeightDescription": "Alto de imágen miniatura subida. Actualizando este valor la imagen miniatura cambia en el futuro, pero no cambia para imagenes creadas en el pasado.", @@ -933,6 +932,7 @@ "signup_user_completed.gitlab": "con GitLab", "signup_user_completed.google": "con Google", "signup_user_completed.lets": "Vamos a crear tu cuenta", + "signup_user_completed.none": "No está habilitado ningún método para crear usuarios. Por favor contacta a un administrador para obtener acceso.", "signup_user_completed.onSite": "en {siteName}", "signup_user_completed.or": "o", "signup_user_completed.passwordLength": "Por favor ingresa al menos {min} caracteres", @@ -1058,39 +1058,19 @@ "user.settings.advance.sendTitle": "Enviar mensajes con Ctrl + Retorno", "user.settings.advance.title": "Configuración Avanzada", "user.settings.cmds.add": "Agregar", - "user.settings.cmds.add_desc": "Crea comandos que permitan enviar eventos a integraciones externas. Por favor revisa <a href=\"http://mattermost.org/commands\">http://mattermost.org/commands</a> para aprender más.", - "user.settings.cmds.add_display_name.placeholder": "Nombre a mostrar", "user.settings.cmds.add_new": "Agregar un nuevo comando", "user.settings.cmds.add_trigger.placeholder": "Gatillador del Comando ej. \"hola\" no se debe incluir la barra", "user.settings.cmds.add_username.placeholder": "Nombre de usuario", - "user.settings.cmds.auto_complete": "Auto completado: ", "user.settings.cmds.auto_complete.no": "no", "user.settings.cmds.auto_complete.yes": "sí", - "user.settings.cmds.auto_complete_desc": "Descripción del Auto Completado: ", - "user.settings.cmds.auto_complete_desc.placeholder": "Una pequeña descripción de que hace el comando.", "user.settings.cmds.auto_complete_help": "Mostrar este comando en la lista de auto completado.", - "user.settings.cmds.auto_complete_hint": "Pista de auto completado: ", - "user.settings.cmds.auto_complete_hint.placeholder": "[código postal]", - "user.settings.cmds.auto_complete_hint_desc": "Lista de parámetros que recibe el comando.", - "user.settings.cmds.cmd_display_name": "Nombre a mostrar del Comando.", - "user.settings.cmds.display_name": "Nombre a mostrar: ", "user.settings.cmds.existing": "Comandos existentes", - "user.settings.cmds.icon_url": "URL del icono: ", - "user.settings.cmds.icon_url_desc": "URL para un icono", "user.settings.cmds.none": "Ninguno", "user.settings.cmds.regen": "Regenerar Token", - "user.settings.cmds.request_type": "Tipo de Solicitud: ", - "user.settings.cmds.request_type_desc": "Tipo de solicitud emitido al callback URL por el Comando.", "user.settings.cmds.request_type_get": "GET", "user.settings.cmds.request_type_post": "POST", "user.settings.cmds.token": "Token: ", - "user.settings.cmds.trigger": "Gatillador: ", - "user.settings.cmds.trigger_desc": "Palabra que gatilla la acción", - "user.settings.cmds.url": "URL: ", "user.settings.cmds.url.placeholder": "Debe comenzar con http:// o https://", - "user.settings.cmds.url_desc": "URL que va a recibir el evento HTTP POST o GET", - "user.settings.cmds.username": "Nombre de usuario: ", - "user.settings.cmds.username_desc": "El nombre de usuario a utilizar cuando se genere el mensaje.", "user.settings.custom_theme.awayIndicator": "Indicador Ausente", "user.settings.custom_theme.buttonBg": "Fondo Botón", "user.settings.custom_theme.buttonColor": "Texto Botón", @@ -1193,8 +1173,6 @@ "user.settings.import_theme.importHeader": "Importar Tema de Slack", "user.settings.import_theme.submit": "Enviar", "user.settings.import_theme.submitError": "Formato inválido, por favor intenta copiando y pegando nuevamente.", - "user.settings.integrations.commands": "Comandos", - "user.settings.integrations.commandsDescription": "Administra tus comandos", "user.settings.integrations.incomingWebhooks": "Webhooks de entrada", "user.settings.integrations.incomingWebhooksDescription": "Administra tus webhooks de entrada", "user.settings.integrations.outWebhooks": "Webhooks de salida", diff --git a/web/static/images/postArrows.png b/web/static/images/postArrows.png Binary files differdeleted file mode 100644 index 7b5919fc3..000000000 --- a/web/static/images/postArrows.png +++ /dev/null |