Skip to content

Commit

Permalink
Fixing bugs, minor ux issues, refactoring, cleanups, and removing ugl…
Browse files Browse the repository at this point in the history
…y hacks.
  • Loading branch information
Martin Krulis committed May 17, 2019
1 parent b8ae00c commit c6b8c77
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 187 deletions.
52 changes: 21 additions & 31 deletions src/components/SystemMessages/MessagesList/MessagesList.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,25 @@ import { defaultMemoize } from 'reselect';
import SortableTable, { SortableTableColumnDescriptor } from '../../widgets/SortableTable';
import { getLocalizedText } from '../../../helpers/localizedData';
import DateTime from '../../widgets/DateTime';
import { roleLabels } from '../../helpers/usersRoles';
import { roleLabels, rolePriorities } from '../../helpers/usersRoles';
import UsersNameContainer from '../../../containers/UsersNameContainer';
import FilterSystemMessagesForm from '../../forms/FilterSystemMessagesForm/FilterSystemMessagesForm';

import styles from './MessagesList.less';

const getVisibleMessages = (systemMessages, showAll) =>
showAll ? systemMessages : systemMessages.filter(msg => msg.visibleTo * 1000 >= Date.now());
const prepareData = defaultMemoize((systemMessages, showAll, renderActions) => {
const filteredMessages = showAll ? systemMessages : systemMessages.filter(msg => msg.visibleTo * 1000 >= Date.now());

return filteredMessages.map(message => ({
...message,
text: { localizedTexts: message.localizedTexts },
buttons: renderActions && renderActions(message),
}));
});

class MessagesList extends Component {
state = { showAll: false, visibleMessages: [] };

componentDidMount() {
this.setState({
visibleMessages: getVisibleMessages(this.props.systemMessages, this.state.showAll),
});
}

prepareColumnDescriptors = defaultMemoize(locale => {
const columns = [
new SortableTableColumnDescriptor(
Expand All @@ -44,6 +45,7 @@ class MessagesList extends Component {
{
comparator: ({ visibleFrom: f1 }, { visibleFrom: f2 }) => f2 - f1,
cellRenderer: visibleFrom => visibleFrom && <DateTime unixts={visibleFrom} />,
className: 'valign-middle',
}
),

Expand All @@ -53,19 +55,22 @@ class MessagesList extends Component {
{
comparator: ({ visibleTo: t1 }, { visibleTo: t2 }) => t2 - t1,
cellRenderer: visibleTo => visibleTo && <DateTime unixts={visibleTo} />,
className: 'valign-middle',
}
),

new SortableTableColumnDescriptor('authorId', <FormattedMessage id="generic.author" defaultMessage="Author" />, {
cellRenderer: authorId => authorId && <UsersNameContainer userId={authorId} />,
cellRenderer: authorId => authorId && <UsersNameContainer userId={authorId} size={8} />,
className: 'valign-middle',
}),

new SortableTableColumnDescriptor(
'role',
<FormattedMessage id="app.systemMessagesList.role" defaultMessage="Role" />,
{
comparator: ({ role: r1 }, { role: r2 }) => r1.localeCompare(r2, locale),
comparator: ({ role: r1 }, { role: r2 }) => Number(rolePriorities[r2]) - Number(rolePriorities[r1]),
cellRenderer: role => role && roleLabels[role],
className: 'valign-middle',
}
),

Expand All @@ -75,37 +80,22 @@ class MessagesList extends Component {
{
comparator: ({ type: t1 }, { type: t2 }) => t1.localeCompare(t2, locale),
cellRenderer: type => type && <Alert bsStyle={type} className={styles.alertType} />,
className: 'text-center valign-middle',
}
),

new SortableTableColumnDescriptor('buttons', '', {
className: 'text-right',
className: 'text-right valign-middle',
}),
];

return columns;
});

prepareData = defaultMemoize(systemMessages => {
const { renderActions } = this.props;

return systemMessages.map(message => {
const data = {
text: { localizedTexts: message.localizedTexts },
visibleFrom: message.visibleFrom,
visibleTo: message.visibleTo,
authorId: message.authorId,
role: message.role,
type: message.type,
buttons: renderActions && renderActions(message),
};
return data;
});
});

render() {
const {
systemMessages,
renderActions,
intl: { locale },
} = this.props;

Expand All @@ -115,17 +105,17 @@ class MessagesList extends Component {
onSubmit={({ showAll }) => {
this.setState({
showAll: showAll,
visibleMessages: getVisibleMessages(systemMessages, showAll),
});
return Promise.resolve();
}}
initialValues={{ showAll: this.state.showAll }}
/>
<hr className="no-margin" />
<SortableTable
hover
columns={this.prepareColumnDescriptors(locale)}
defaultOrder="visibleTo"
data={this.prepareData(this.state.visibleMessages)}
data={prepareData(systemMessages, this.state.showAll, renderActions)}
empty={
<div className="text-center text-muted">
<FormattedMessage
Expand Down
12 changes: 7 additions & 5 deletions src/components/SystemMessages/MessagesList/MessagesList.less
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
.alertType {
margin-bottom: 0px;
padding: 10px;
height: 10px;
width: 10px;
margin: 0px;
padding: 0px;
height: 16px;
width: 16px;
display: inline-block;
}

.textPreview {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 20vw;
max-width: 20vw;
vertical-align: middle !important;
}
51 changes: 22 additions & 29 deletions src/components/forms/EditSystemMessageForm/EditSystemMessageForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { reduxForm, Field, FieldArray } from 'redux-form';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { Alert, Modal } from 'react-bootstrap';
import moment from 'moment';
import { defaultMemoize } from 'reselect';

import { SelectField, DatetimeField } from '../Fields';
import SubmitButton from '../SubmitButton';
Expand All @@ -21,24 +21,34 @@ const typeOptions = [
{ key: 'danger', name: 'Danger' },
];

const getRoleOptions = defaultMemoize(formatMessage =>
Object.keys(roleLabelsSimpleMessages).map(role => ({
key: role,
name: formatMessage(roleLabelsSimpleMessages[role]),
}))
);

const EditSystemMessageForm = ({
initialValues,
error,
dirty,
submitting,
handleSubmit,
submitFailed,
submitSucceeded,
invalid,
asyncValidating,
isOpen,
onClose,
intl: { formatMessage },
createNew = false,
intl: { locale, formatMessage },
}) => (
<Modal show={isOpen} backdrop="static" size="lg" onHide={onClose}>
<Modal.Header closeButton>
<Modal.Title>
<FormattedMessage id="app.editSystemMessageForm.title" defaultMessage="Edit System Message" />
{createNew ? (
<FormattedMessage id="app.editSystemMessageForm.title" defaultMessage="Edit System Message" />
) : (
<FormattedMessage id="app.editSystemMessageForm.title" defaultMessage="Edit System Message" />
)}
</Modal.Title>
</Modal.Header>
<Modal.Body>
Expand All @@ -54,18 +64,13 @@ const EditSystemMessageForm = ({
name="type"
component={SelectField}
options={typeOptions}
addEmptyOption
label={<FormattedMessage id="app.editSystemMessageForm.type" defaultMessage="Type of the notification." />}
/>

<Field
name="role"
component={SelectField}
options={Object.keys(roleLabelsSimpleMessages).map(role => ({
key: role,
name: formatMessage(roleLabelsSimpleMessages[role]),
}))}
addEmptyOption
options={getRoleOptions(formatMessage)}
label={
<FormattedMessage
id="app.editSystemMessageForm.role"
Expand Down Expand Up @@ -108,7 +113,6 @@ const EditSystemMessageForm = ({
hasSucceeded={submitSucceeded}
hasFailed={submitFailed}
handleSubmit={handleSubmit}
asyncValidating={asyncValidating}
messages={{
submit: <FormattedMessage id="generic.save" defaultMessage="Save" />,
submitting: <FormattedMessage id="generic.saving" defaultMessage="Saving..." />,
Expand All @@ -128,18 +132,16 @@ const EditSystemMessageForm = ({

EditSystemMessageForm.propTypes = {
error: PropTypes.any,
initialValues: PropTypes.object.isRequired,
values: PropTypes.object,
handleSubmit: PropTypes.func.isRequired,
dirty: PropTypes.bool,
submitting: PropTypes.bool,
submitFailed: PropTypes.bool,
submitSucceeded: PropTypes.bool,
invalid: PropTypes.bool,
asyncValidating: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
links: PropTypes.object,
isOpen: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
createNew: PropTypes.bool,
intl: intlShape.isRequired,
};

Expand All @@ -160,7 +162,7 @@ const validate = ({ localizedTexts, type, role, visibleFrom, visibleTo }) => {
});

if (!visibleFrom) {
errors['visibleFrom'] = (
errors.visibleFrom = (
<FormattedMessage
id="app.editSystemMessageForm.validation.visibleFromEmpty"
defaultMessage="The visible from date must be set."
Expand All @@ -169,25 +171,16 @@ const validate = ({ localizedTexts, type, role, visibleFrom, visibleTo }) => {
}

if (!visibleTo) {
errors['visibleTo'] = (
errors.visibleTo = (
<FormattedMessage
id="app.editSystemMessageForm.validation.visibleToEmpty"
defaultMessage="The visible to date must be set."
/>
);
}

if (visibleTo.isBefore(moment.unix(Date.now() / 1000))) {
errors['visibleTo'] = (
<FormattedMessage
id="app.editSystemMessageForm.validation.visibleToInHistory"
defaultMessage="The visible to date cannot be in the past."
/>
);
}

if (visibleTo.isBefore(visibleFrom)) {
errors['visibleFrom'] = (
errors.visibleFrom = (
<FormattedMessage
id="app.editSystemMessageForm.validation.visibleFromBeforeTo"
defaultMessage="The visible from date cannot be after visible to date."
Expand All @@ -196,7 +189,7 @@ const validate = ({ localizedTexts, type, role, visibleFrom, visibleTo }) => {
}

if (!type) {
errors['type'] = (
errors.type = (
<FormattedMessage
id="app.editSystemMessageForm.validation.typeEmpty"
defaultMessage="Type of the notification must be set."
Expand All @@ -205,7 +198,7 @@ const validate = ({ localizedTexts, type, role, visibleFrom, visibleTo }) => {
}

if (!role) {
errors['role'] = (
errors.role = (
<FormattedMessage
id="app.editSystemMessageForm.validation.roleEmpty"
defaultMessage="Base user role of the notification muset be set."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, injectIntl, intlShape } from 'react-intl';
import { reduxForm, Field } from 'redux-form';
import { Alert, Well, Grid, Row, Col, Form } from 'react-bootstrap';
import { Grid, Row, Col, Form } from 'react-bootstrap';

import SubmitButton from '../SubmitButton';
import { CheckboxField } from '../Fields';
Expand All @@ -17,50 +17,40 @@ const FilterSystemMessagesForm = ({
intl: { locale },
}) => (
<Form method="POST" onSubmit={onSubmit}>
<Well bsSize="sm">
{submitFailed && (
<Alert bsStyle="danger">
<FormattedMessage id="generic.operationFailed" defaultMessage="Operation failed. Please try again later." />
</Alert>
)}

<Grid fluid>
<Row>
<Col sm={9} md={10}>
<span className="text-nowrap pull-left em-padding-right">
<Field
name="showAll"
component={CheckboxField}
onOff
label={
<FormattedMessage
id="app.systemMessagesList.showAll"
defaultMessage="Show all messages (including expired)"
/>
}
<Grid fluid>
<Row>
<Col sm={9} md={10}>
<Field
name="showAll"
component={CheckboxField}
onOff
label={
<FormattedMessage
id="app.systemMessagesList.showAll"
defaultMessage="Show all messages (including expired)"
/>
</span>
</Col>
}
/>
</Col>

<Col sm={3} md={2}>
<div className="text-right">
<SubmitButton
id="setFilters"
handleSubmit={handleSubmit}
hasSucceeded={submitSucceeded}
hasFailed={submitFailed}
invalid={invalid}
disabled={onSubmit === null}
messages={{
submit: <FormattedMessage id="generic.setFilters" defaultMessage="Set Filters" />,
success: <FormattedMessage id="generic.filtersSet" defaultMessage="Filters Set" />,
}}
/>
</div>
</Col>
</Row>
</Grid>
</Well>
<Col sm={3} md={2}>
<div className="text-right">
<SubmitButton
id="setFilters"
handleSubmit={handleSubmit}
hasSucceeded={submitSucceeded}
hasFailed={submitFailed}
invalid={invalid}
disabled={onSubmit === null}
messages={{
submit: <FormattedMessage id="generic.setFilters" defaultMessage="Set Filters" />,
success: <FormattedMessage id="generic.filtersSet" defaultMessage="Filters Set" />,
}}
/>
</div>
</Col>
</Row>
</Grid>
</Form>
);

Expand Down
Loading

0 comments on commit c6b8c77

Please sign in to comment.