Skip to content

Commit

Permalink
Listing, adding and deleting SIS terms
Browse files Browse the repository at this point in the history
  • Loading branch information
SemaiCZE committed Jan 28, 2018
1 parent a117255 commit 360b9dd
Show file tree
Hide file tree
Showing 10 changed files with 391 additions and 11 deletions.
55 changes: 55 additions & 0 deletions src/components/SisIntegration/TermsList/TermsList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Table } from 'react-bootstrap';
import { injectIntl, FormattedMessage } from 'react-intl';
import TermsListItem from '../TermsListItem';

const TermsList = ({ terms = [], createActions, intl, ...rest }) =>
<Table hover striped>
<thead>
<tr>
<th>
<FormattedMessage id="app.termsList.year" defaultMessage="Year" />
</th>
<th>
<FormattedMessage id="app.termsList.term" defaultMessage="Term" />
</th>
<th>
<FormattedMessage id="app.termsList.start" defaultMessage="Start" />
</th>
<th>
<FormattedMessage id="app.termsList.end" defaultMessage="End" />
</th>
<th>
<FormattedMessage
id="app.termsList.advertiseUntil"
defaultMessage="Advertise Until"
/>
</th>
<th />
</tr>
</thead>
<tbody>
{terms.map((term, i) =>
<TermsListItem key={i} data={term} createActions={createActions} />
)}

{terms.length === 0 &&
<tr>
<td className="text-center">
<FormattedMessage
id="app.termsList.noTerms"
defaultMessage="There are no SIS terms in this list."
/>
</td>
</tr>}
</tbody>
</Table>;

TermsList.propTypes = {
terms: PropTypes.array,
createActions: PropTypes.func,
intl: PropTypes.shape({ locale: PropTypes.string.isRequired }).isRequired
};

export default injectIntl(TermsList);
1 change: 1 addition & 0 deletions src/components/SisIntegration/TermsList/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default from './TermsList';
60 changes: 60 additions & 0 deletions src/components/SisIntegration/TermsListItem/TermsListItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, FormattedDate, FormattedTime } from 'react-intl';

const TermsListItem = ({
data: { id, year, term, beginning, end, advertiseUntil },
createActions
}) =>
<tr>
<td>
{year}
</td>
<td>
{term === 1 &&
<FormattedMessage id="app.termsList.winter" defaultMessage="Winter" />}
{term === 2 &&
<FormattedMessage id="app.termsList.summer" defaultMessage="Summer" />}
{term !== 1 &&
term !== 2 &&
<span>
{term}
</span>}
</td>
<td>
{beginning
? <FormattedDate value={new Date(beginning * 1000)} />
: <span>&mdash;</span>}
</td>
<td>
{end
? <FormattedDate value={new Date(end * 1000)} />
: <span>&mdash;</span>}
</td>
<td>
{advertiseUntil
? <span>
<FormattedDate value={new Date(advertiseUntil * 1000)} />
{', '}
<FormattedTime value={new Date(advertiseUntil * 1000)} />
</span>
: <span>&mdash;</span>}
</td>
<td className="text-right">
{createActions && createActions(id)}
</td>
</tr>;

TermsListItem.propTypes = {
data: PropTypes.shape({
id: PropTypes.string.isRequired,
year: PropTypes.number.isRequired,
term: PropTypes.number.isRequired,
beginning: PropTypes.number,
end: PropTypes.number,
advertiseUntil: PropTypes.number
}),
createActions: PropTypes.func
};

export default TermsListItem;
1 change: 1 addition & 0 deletions src/components/SisIntegration/TermsListItem/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default from './TermsListItem';
139 changes: 139 additions & 0 deletions src/components/forms/AddSisTermForm/AddSisTermForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
FormattedMessage,
defineMessages,
intlShape,
injectIntl
} from 'react-intl';
import { reduxForm, Field } from 'redux-form';
import { Alert } from 'react-bootstrap';
import isInt from 'validator/lib/isInt';
import FormBox from '../../widgets/FormBox';
import SubmitButton from '../SubmitButton';
import { TextField, SelectField } from '../Fields';

const messages = defineMessages({
summerTerm: {
id: 'app.addSisTermForm.summer',
defaultMessage: 'Summer term'
},
winterTerm: {
id: 'app.addSisTermForm.winter',
defaultMessage: 'Winter term'
}
});

const AddSisTermForm = ({
submitting,
handleSubmit,
anyTouched,
submitFailed = false,
submitSucceeded = false,
invalid,
intl: { formatMessage }
}) =>
<FormBox
title={
<FormattedMessage
id="app.addSisTermForm.title"
defaultMessage="Add new term"
/>
}
type={submitSucceeded ? 'success' : undefined}
isOpen={true}
collapsable={false}
footer={
<div className="text-center">
<SubmitButton
id="add-sis-term"
handleSubmit={handleSubmit}
submitting={submitting}
dirty={anyTouched}
hasSucceeded={submitSucceeded}
hasFailed={submitFailed}
invalid={invalid}
messages={{
submit: (
<FormattedMessage
id="app.addSisTermForm.submit"
defaultMessage="Save new term"
/>
),
submitting: (
<FormattedMessage
id="app.addSisTermForm.processing"
defaultMessage="Saving ..."
/>
),
success: (
<FormattedMessage
id="app.addSisTermForm.success"
defaultMessage="The term is saved."
/>
)
}}
/>
</div>
}
>
{submitFailed &&
<Alert bsStyle="danger">
<FormattedMessage
id="app.addSisTermForm.failed"
defaultMessage="Cannot save the new SIS term."
/>
</Alert>}

<Field
name="year"
component={TextField}
label={
<FormattedMessage id="app.addSisTermForm.year" defaultMessage="Year:" />
}
/>
<Field
name="term"
component={SelectField}
label={
<FormattedMessage id="app.addSisTermForm.term" defaultMessage="Term:" />
}
options={[
{ name: formatMessage(messages.winterTerm), key: 1 },
{ name: formatMessage(messages.summerTerm), key: 2 }
]}
addEmptyOption
/>
</FormBox>;

AddSisTermForm.propTypes = {
handleSubmit: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
submitFailed: PropTypes.bool,
anyTouched: PropTypes.bool,
submitSucceeded: PropTypes.bool,
submitting: PropTypes.bool,
invalid: PropTypes.bool,
intl: intlShape.isRequired
};

const validate = ({ year, term }) => {
const errors = {};
if (year && !isInt(String(year))) {
errors['year'] = (
<FormattedMessage
id="app.addSisTermForm.validation.year"
defaultMessage="The year must be an integer."
/>
);
}

return errors;
};

export default injectIntl(
reduxForm({
form: 'add-sis-term',
validate
})(AddSisTermForm)
);
1 change: 1 addition & 0 deletions src/components/forms/AddSisTermForm/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default from './AddSisTermForm';
90 changes: 79 additions & 11 deletions src/pages/SisIntegration/SisIntegration.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,38 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';
import { Row, Col, Button } from 'react-bootstrap';

import PageContent from '../../components/layout/PageContent';
import { isLoggedAsSuperAdmin } from '../../redux/selectors/users';
import { loggedInUserIdSelector } from '../../redux/selectors/auth';
import {
fetchAllTerms,
create,
deleteTerm
} from '../../redux/modules/sisTerms';
import FetchManyResourceRenderer from '../../components/helpers/FetchManyResourceRenderer';
import {
fetchManyStatus,
readySisTermsSelector
} from '../../redux/selectors/sisTerms';
import AddSisTermForm from '../../components/forms/AddSisTermForm/AddSisTermForm';
import TermsList from '../../components/SisIntegration/TermsList/TermsList';
import Box from '../../components/widgets/Box/Box';
import Confirm from '../../components/forms/Confirm';
import { DeleteIcon } from '../../components/icons';

class SisIntegration extends Component {
static loadAsync = ({ groupId }, dispatch, userId, isSuperAdmin) =>
Promise.all([]);
static loadAsync = (params, dispatch, userId, isSuperAdmin) =>
Promise.all([dispatch(fetchAllTerms)]);

componentWillMount() {
const { loadAsync, userId, isSuperAdmin } = this.props;
loadAsync(userId, isSuperAdmin);
}

componentWillReceiveProps(newProps) {}

render() {
// const {} = this.props;
const { fetchStatus, createNewTerm, deleteTerm, sisTerms } = this.props;

return (
<PageContent
Expand Down Expand Up @@ -47,9 +61,55 @@ class SisIntegration extends Component {
}
]}
>
<div>
<div />
</div>
<Row>
<Col lg={8}>
<FetchManyResourceRenderer fetchManyStatus={fetchStatus}>
{() =>
<Box
title={
<FormattedMessage
id="app.sisIntegration.list"
defaultMessage="SIS Terms"
/>
}
noPadding
unlimitedHeight
>
<TermsList
terms={sisTerms}
createActions={id =>
<div>
<Confirm
id={id}
onConfirmed={() => deleteTerm(id)}
question={
<FormattedMessage
id="app.sisIntegration.deleteConfirm"
defaultMessage="Are you sure you want to delete the SIS term?"
/>
}
>
<Button
bsSize="xs"
className="btn-flat"
bsStyle="danger"
>
<DeleteIcon />{' '}
<FormattedMessage
id="app.sisIntegration.deleteButton"
defaultMessage="Delete"
/>
</Button>
</Confirm>
</div>}
/>
</Box>}
</FetchManyResourceRenderer>
</Col>
<Col lg={4}>
<AddSisTermForm onSubmit={createNewTerm} />
</Col>
</Row>
</PageContent>
);
}
Expand All @@ -58,19 +118,27 @@ class SisIntegration extends Component {
SisIntegration.propTypes = {
userId: PropTypes.string.isRequired,
isSuperAdmin: PropTypes.bool.isRequired,
loadAsync: PropTypes.func.isRequired
loadAsync: PropTypes.func.isRequired,
fetchStatus: PropTypes.string,
createNewTerm: PropTypes.func,
deleteTerm: PropTypes.func,
sisTerms: PropTypes.array.isRequired
};

const mapStateToProps = state => {
return {
userId: loggedInUserIdSelector(state),
isSuperAdmin: isLoggedAsSuperAdmin(state)
isSuperAdmin: isLoggedAsSuperAdmin(state),
fetchStatus: fetchManyStatus(state),
sisTerms: readySisTermsSelector(state)
};
};

const mapDispatchToProps = (dispatch, { params }) => ({
loadAsync: (userId, isSuperAdmin) =>
SisIntegration.loadAsync(params, dispatch, userId, isSuperAdmin)
SisIntegration.loadAsync(params, dispatch, userId, isSuperAdmin),
createNewTerm: data => dispatch(create(data)),
deleteTerm: id => dispatch(deleteTerm(id))
});

export default connect(mapStateToProps, mapDispatchToProps)(SisIntegration);
Loading

0 comments on commit 360b9dd

Please sign in to comment.