slight modifications to keyboards dialog and also fix error with non-Mac (#7367)

This commit is contained in:
Saturnino Abril
2017-09-06 04:34:53 +08:00
committed by GitHub
parent 8d680cf64e
commit 2977b31a39
6 changed files with 306 additions and 17 deletions

View File

@@ -234,7 +234,7 @@ export default class NeedsTeam extends React.Component {
<RemovedFromChannelModal/> <RemovedFromChannelModal/>
<ResetStatusModal/> <ResetStatusModal/>
<LeavePrivateChannelModal/> <LeavePrivateChannelModal/>
<ShortcutsModal/> <ShortcutsModal isMac={Utils.isMac()}/>
</div> </div>
</div> </div>
); );

View File

@@ -2,18 +2,24 @@
// See License.txt for license information. // See License.txt for license information.
import Constants from 'utils/constants.jsx'; import Constants from 'utils/constants.jsx';
import * as Utils from 'utils/utils.jsx';
import ModalStore from 'stores/modal_store.jsx'; import ModalStore from 'stores/modal_store.jsx';
import {intlShape, injectIntl, defineMessages} from 'react-intl'; import {intlShape, injectIntl, defineMessages} from 'react-intl';
import {Modal} from 'react-bootstrap'; import {Modal} from 'react-bootstrap';
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types';
const allShortcuts = defineMessages({ const allShortcuts = defineMessages({
mainHeader: { mainHeader: {
id: 'shortcuts.header', default: {
defaultMessage: 'Keyboard Shortcuts' id: 'shortcuts.header',
defaultMessage: 'Keyboard Shortcuts\tCtrl|/'
},
mac: {
id: 'shortcuts.header.mac',
defaultMessage: 'Keyboard Shortcuts\t⌘|/'
}
}, },
navHeader: { navHeader: {
id: 'shortcuts.nav.header', id: 'shortcuts.nav.header',
@@ -103,10 +109,6 @@ const allShortcuts = defineMessages({
id: 'shortcuts.msgs.header', id: 'shortcuts.msgs.header',
defaultMessage: 'Messages' defaultMessage: 'Messages'
}, },
msgMarkAsRead: {
id: 'shortcuts.msgs.mark_as_read',
defaultMessage: 'Mark current channel as read:\tEsc'
},
msgInputHeader: { msgInputHeader: {
id: 'shortcuts.msgs.input.header', id: 'shortcuts.msgs.input.header',
defaultMessage: 'Works inside an empty input field' defaultMessage: 'Works inside an empty input field'
@@ -237,7 +239,8 @@ const allShortcuts = defineMessages({
class ShortcutsModal extends React.PureComponent { class ShortcutsModal extends React.PureComponent {
static propTypes = { static propTypes = {
intl: intlShape.isRequired intl: intlShape.isRequired,
isMac: PropTypes.bool.isRequired
} }
constructor(props) { constructor(props) {
@@ -266,7 +269,8 @@ class ShortcutsModal extends React.PureComponent {
this.setState({show: false}); this.setState({show: false});
} }
getShortcuts(isMac) { getShortcuts() {
const {isMac} = this.props;
const shortcuts = {}; const shortcuts = {};
Object.keys(allShortcuts).forEach((s) => { Object.keys(allShortcuts).forEach((s) => {
if (isMac && allShortcuts[s].mac) { if (isMac && allShortcuts[s].mac) {
@@ -282,8 +286,7 @@ class ShortcutsModal extends React.PureComponent {
} }
render() { render() {
const shortcuts = this.getShortcuts(Utils.isMac()); const shortcuts = this.getShortcuts();
const {formatMessage} = this.props.intl; const {formatMessage} = this.props.intl;
return ( return (
@@ -296,7 +299,7 @@ class ShortcutsModal extends React.PureComponent {
<div className='shortcuts-content'> <div className='shortcuts-content'>
<Modal.Header closeButton={true}> <Modal.Header closeButton={true}>
<Modal.Title> <Modal.Title>
<strong>{formatMessage(shortcuts.mainHeader)}</strong> <strong>{renderShortcut(formatMessage(shortcuts.mainHeader))}</strong>
</Modal.Title> </Modal.Title>
</Modal.Header> </Modal.Header>
<Modal.Body ref='modalBody'> <Modal.Body ref='modalBody'>
@@ -320,7 +323,6 @@ class ShortcutsModal extends React.PureComponent {
<div className='section'> <div className='section'>
<div> <div>
<h4 className='section-title'><strong>{formatMessage(shortcuts.msgHeader)}</strong></h4> <h4 className='section-title'><strong>{formatMessage(shortcuts.msgHeader)}</strong></h4>
{renderShortcut(formatMessage(shortcuts.msgMarkAsRead))}
<span><strong>{formatMessage(shortcuts.msgInputHeader)}</strong></span> <span><strong>{formatMessage(shortcuts.msgInputHeader)}</strong></span>
<div className='subsection'> <div className='subsection'>
{renderShortcut(formatMessage(shortcuts.msgEdit))} {renderShortcut(formatMessage(shortcuts.msgEdit))}

View File

@@ -2156,7 +2156,8 @@
"shortcuts.files.header": "Files", "shortcuts.files.header": "Files",
"shortcuts.files.upload": "Upload files:\tCtrl|U", "shortcuts.files.upload": "Upload files:\tCtrl|U",
"shortcuts.files.upload.mac": "Upload files:\t⌘|U", "shortcuts.files.upload.mac": "Upload files:\t⌘|U",
"shortcuts.header": "Keyboard Shortcuts", "shortcuts.header": "Keyboard Shortcuts\tCtrl|/",
"shortcuts.header.mac": "Keyboard Shortcuts\t⌘|/",
"shortcuts.info": "Begin a message with / for a list of all the commands at your disposal.", "shortcuts.info": "Begin a message with / for a list of all the commands at your disposal.",
"shortcuts.msgs.comp.channel": "Channel:\t~|[a-z]|Tab", "shortcuts.msgs.comp.channel": "Channel:\t~|[a-z]|Tab",
"shortcuts.msgs.comp.emoji": "Emoji:\t:|[a-z]|Tab", "shortcuts.msgs.comp.emoji": "Emoji:\t:|[a-z]|Tab",
@@ -2165,7 +2166,6 @@
"shortcuts.msgs.edit": "Edit last message in channel:\tUp", "shortcuts.msgs.edit": "Edit last message in channel:\tUp",
"shortcuts.msgs.header": "Messages", "shortcuts.msgs.header": "Messages",
"shortcuts.msgs.input.header": "Works inside an empty input field", "shortcuts.msgs.input.header": "Works inside an empty input field",
"shortcuts.msgs.mark_as_read": "Mark current channel as read:\tEsc",
"shortcuts.msgs.reply": "Reply to last message in channel:\tShift|Up", "shortcuts.msgs.reply": "Reply to last message in channel:\tShift|Up",
"shortcuts.msgs.reprint_next": "Reprint next message:\tCtrl|Down", "shortcuts.msgs.reprint_next": "Reprint next message:\tCtrl|Down",
"shortcuts.msgs.reprint_next.mac": "Reprint next message:\t⌘|Down", "shortcuts.msgs.reprint_next.mac": "Reprint next message:\t⌘|Down",

View File

@@ -11,18 +11,43 @@
background: transparent; background: transparent;
border: none; border: none;
color: inherit; color: inherit;
padding: 40px 40px 20px; padding: 20px 40px 20px;
.close { .close {
color: inherit; color: inherit;
font-size: 28px; font-size: 28px;
font-weight: normal; font-weight: normal;
right: 35px; right: 35px;
top: 35px;
} }
.modal-title { .modal-title {
color: inherit; color: inherit;
font-size: 20px; font-size: 20px;
> div {
&:first-child {
margin-bottom: 2.5em;
}
}
.shortcut-line {
margin: 17px 0;
span {
&:first-child {
margin-right: 5px;
}
}
.shortcut-key {
border-radius: 3px;
font-size: .9em;
font-weight: 500;
margin: 5px 0 5px 5px;
padding: 1px 5px;
}
}
} }
} }
} }

View File

@@ -0,0 +1,237 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`components/ShortcutsModal should match snapshot modal for Mac 1`] = `
<InjectIntl(ShortcutsModal)
intl={
Object {
"defaultFormats": Object {},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"textComponent": "span",
}
}
isMac={true}
>
<ShortcutsModal
intl={
Object {
"defaultFormats": Object {},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"textComponent": "span",
}
}
isMac={true}
>
<Modal
animation={true}
autoFocus={true}
backdrop={true}
bsClass="modal"
dialogClassName="shortcuts-modal"
dialogComponentClass={[Function]}
enforceFocus={true}
keyboard={true}
manager={
ModalManager {
"add": [Function],
"containers": Array [],
"data": Array [],
"handleContainerOverflow": true,
"hideSiblingNodes": true,
"isTopModal": [Function],
"modals": Array [],
"remove": [Function],
}
}
onExited={[Function]}
onHide={[Function]}
renderBackdrop={[Function]}
restoreFocus={true}
show={false}
>
<Modal
autoFocus={true}
backdrop={true}
backdropClassName="modal-backdrop"
backdropTransitionTimeout={150}
containerClassName="modal-open"
dialogTransitionTimeout={300}
enforceFocus={true}
keyboard={true}
manager={
ModalManager {
"add": [Function],
"containers": Array [],
"data": Array [],
"handleContainerOverflow": true,
"hideSiblingNodes": true,
"isTopModal": [Function],
"modals": Array [],
"remove": [Function],
}
}
onEntering={[Function]}
onExited={[Function]}
onHide={[Function]}
renderBackdrop={[Function]}
restoreFocus={true}
show={false}
transition={[Function]}
/>
</Modal>
</ShortcutsModal>
</InjectIntl(ShortcutsModal)>
`;
exports[`components/ShortcutsModal should match snapshot modal for non-Mac like Windows/Linux 1`] = `
<InjectIntl(ShortcutsModal)
intl={
Object {
"defaultFormats": Object {},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"textComponent": "span",
}
}
isMac={false}
>
<ShortcutsModal
intl={
Object {
"defaultFormats": Object {},
"defaultLocale": "en",
"formatDate": [Function],
"formatHTMLMessage": [Function],
"formatMessage": [Function],
"formatNumber": [Function],
"formatPlural": [Function],
"formatRelative": [Function],
"formatTime": [Function],
"formats": Object {},
"formatters": Object {
"getDateTimeFormat": [Function],
"getMessageFormat": [Function],
"getNumberFormat": [Function],
"getPluralFormat": [Function],
"getRelativeFormat": [Function],
},
"locale": "en",
"messages": Object {},
"now": [Function],
"textComponent": "span",
}
}
isMac={false}
>
<Modal
animation={true}
autoFocus={true}
backdrop={true}
bsClass="modal"
dialogClassName="shortcuts-modal"
dialogComponentClass={[Function]}
enforceFocus={true}
keyboard={true}
manager={
ModalManager {
"add": [Function],
"containers": Array [],
"data": Array [],
"handleContainerOverflow": true,
"hideSiblingNodes": true,
"isTopModal": [Function],
"modals": Array [],
"remove": [Function],
}
}
onExited={[Function]}
onHide={[Function]}
renderBackdrop={[Function]}
restoreFocus={true}
show={false}
>
<Modal
autoFocus={true}
backdrop={true}
backdropClassName="modal-backdrop"
backdropTransitionTimeout={150}
containerClassName="modal-open"
dialogTransitionTimeout={300}
enforceFocus={true}
keyboard={true}
manager={
ModalManager {
"add": [Function],
"containers": Array [],
"data": Array [],
"handleContainerOverflow": true,
"hideSiblingNodes": true,
"isTopModal": [Function],
"modals": Array [],
"remove": [Function],
}
}
onEntering={[Function]}
onExited={[Function]}
onHide={[Function]}
renderBackdrop={[Function]}
restoreFocus={true}
show={false}
transition={[Function]}
/>
</Modal>
</ShortcutsModal>
</InjectIntl(ShortcutsModal)>
`;

View File

@@ -0,0 +1,25 @@
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
import {mountWithIntl} from 'tests/helpers/intl-test-helper.jsx';
import ShortcutsModal from 'components/shortcuts_modal.jsx';
describe('components/ShortcutsModal', () => {
test('should match snapshot modal for Mac', () => {
const wrapper = mountWithIntl(
<ShortcutsModal isMac={true}/>
);
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot modal for non-Mac like Windows/Linux', () => {
const wrapper = mountWithIntl(
<ShortcutsModal isMac={false}/>
);
expect(wrapper).toMatchSnapshot();
});
});