Skip to content

Commit

Permalink
Merge pull request #174 from ReCodEx/new_sis_semestr
Browse files Browse the repository at this point in the history
Manage SIS terms from web-app
  • Loading branch information
SemaiCZE committed Jan 30, 2018
2 parents 89048eb + bbc8dca commit a25d180
Show file tree
Hide file tree
Showing 21 changed files with 707 additions and 40 deletions.
161 changes: 161 additions & 0 deletions src/components/SisIntegration/EditTerm/EditTerm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Modal, Button } from 'react-bootstrap';
import { CloseIcon } from '../../icons';
import { FormattedMessage } from 'react-intl';
import { Field, reduxForm } from 'redux-form';
import DatetimeField from '../../forms/Fields/DatetimeField';
import SubmitButton from '../../forms/SubmitButton';

const EditTerm = ({
isOpen,
onClose,
submitting,
handleSubmit,
anyTouched,
submitFailed = false,
submitSucceeded = false,
invalid,
reset
}) =>
<Modal show={isOpen} backdrop="static" onHide={onClose}>
<Modal.Header closeButton>
<Modal.Title>
<FormattedMessage
id="app.editSisTerm.title"
defaultMessage="Edit SIS Term"
/>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Field
name="beginning"
component={DatetimeField}
label={
<FormattedMessage
id="app.editSisTerm.beginning"
defaultMessage="Beginning of the term:"
/>
}
/>
<Field
name="end"
component={DatetimeField}
label={
<FormattedMessage
id="app.editSisTerm.end"
defaultMessage="End of the term:"
/>
}
/>
<Field
name="advertiseUntil"
component={DatetimeField}
label={
<FormattedMessage
id="app.editSisTerm.advertiseUntil"
defaultMessage="Advertise this term to students until:"
/>
}
/>
</Modal.Body>
<Modal.Footer>
<SubmitButton
id="edit-sis-term"
handleSubmit={data => handleSubmit(data).then(() => reset())}
submitting={submitting}
dirty={anyTouched}
hasSucceeded={submitSucceeded}
hasFailed={submitFailed}
invalid={invalid}
messages={{
submit: (
<FormattedMessage id="app.editSisTerm.save" defaultMessage="Save" />
),
submitting: (
<FormattedMessage
id="app.editSisTerm.saving"
defaultMessage="Saving ..."
/>
),
success: (
<FormattedMessage
id="app.editSisTerm.successs"
defaultMessage="Saved"
/>
)
}}
/>

<Button bsStyle="default" className="btn-flat" onClick={onClose}>
<CloseIcon />{' '}
<FormattedMessage id="app.editSisTerm.close" defaultMessage="Close" />
</Button>
</Modal.Footer>
</Modal>;

EditTerm.propTypes = {
handleSubmit: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
submitFailed: PropTypes.bool,
anyTouched: PropTypes.bool,
submitSucceeded: PropTypes.bool,
submitting: PropTypes.bool,
invalid: PropTypes.bool,
reset: PropTypes.func,
onClose: PropTypes.func.isRequired,
isOpen: PropTypes.bool.isRequired
};

const validate = ({ beginning, end, advertiseUntil }) => {
const errors = {};

if (!beginning) {
errors['beginning'] = (
<FormattedMessage
id="app.editSisTerm.validation.noBeginning"
defaultMessage="Start of the term is required."
/>
);
}

if (!end) {
errors['end'] = (
<FormattedMessage
id="app.editSisTerm.validation.noEnd"
defaultMessage="End of the term is required."
/>
);
}

if (!advertiseUntil) {
errors['advertiseUntil'] = (
<FormattedMessage
id="app.editSisTerm.validation.noAdvertiseUntil"
defaultMessage="End date of advertising the term is required."
/>
);
}

const bDate = new Date(beginning * 1000);
const eDate = new Date(end * 1000);
const aDate = new Date(advertiseUntil * 1000);

if (aDate < bDate || aDate > eDate) {
errors['advertiseUntil'] = (
<FormattedMessage
id="app.editSisTerm.validation.advertiseInLimits"
defaultMessage="The term can be advertised only in its period."
/>
);
}

return errors;
};

export default reduxForm({
form: 'edit-sis-term',
enableReinitialize: true,
keepDirtyOnReinitialize: false,
validate
})(EditTerm);
1 change: 1 addition & 0 deletions src/components/SisIntegration/EditTerm/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default from './EditTerm';
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';
57 changes: 57 additions & 0 deletions src/components/SisIntegration/TermsListItem/TermsListItem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedMessage, FormattedDate, FormattedTime } from 'react-intl';

const TermsListItem = ({ data, createActions }) =>
<tr>
<td>
{data.year}
</td>
<td>
{data.term === 1 &&
<FormattedMessage id="app.termsList.winter" defaultMessage="Winter" />}
{data.term === 2 &&
<FormattedMessage id="app.termsList.summer" defaultMessage="Summer" />}
{data.term !== 1 &&
data.term !== 2 &&
<span>
{data.term}
</span>}
</td>
<td>
{data.beginning
? <FormattedDate value={new Date(data.beginning * 1000)} />
: <span>&mdash;</span>}
</td>
<td>
{data.end
? <FormattedDate value={new Date(data.end * 1000)} />
: <span>&mdash;</span>}
</td>
<td>
{data.advertiseUntil
? <span>
<FormattedDate value={new Date(data.advertiseUntil * 1000)} />
{', '}
<FormattedTime value={new Date(data.advertiseUntil * 1000)} />
</span>
: <span>&mdash;</span>}
</td>
<td className="text-right">
{createActions && createActions(data.id, data)}
</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';
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ const FailuresListItem = ({ id, createActions, failure }) =>
}
>
<div>
{failure.type === 'broker_reject' && <Icon name="times-rectangle" />}
{failure.type === 'evaluation_failure' && <Icon name="tint" />}
{failure.type === 'loading_failure' && <Icon name="wrench" />}
{failure.type === 'broker_reject' && <Icon name="exchange" />}
{failure.type === 'evaluation_failure' &&
<Icon name="graduation-cap" />}
{failure.type === 'loading_failure' && <Icon name="download" />}
</div>
</OverlayTrigger>
</td>
Expand Down
Loading

0 comments on commit a25d180

Please sign in to comment.