Added subs management (wip)

This commit is contained in:
vjrj 2017-12-16 18:47:08 +01:00
parent 6123977974
commit 316e14f0ea
21 changed files with 427 additions and 39 deletions

View file

@ -0,0 +1,33 @@
import React from 'react';
import PropTypes from 'prop-types';
import { createContainer } from 'meteor/react-meteor-data';
import { Meteor } from 'meteor/meteor';
import Subscriptions from '../../../api/Subscriptions/Subscriptions';
import SubscriptionEditor from '../../components/SubscriptionEditor/SubscriptionEditor';
import NotFound from '../NotFound/NotFound';
const EditSubscription = ({ doc, history }) => (doc ? (
<div className="EditSubscription">
<h4 className="page-header">{`Editing "${doc.title}"`}</h4>
<SubscriptionEditor doc={doc} history={history} />
</div>
) : <NotFound />);
EditSubscription.defaultProps = {
doc: null
};
EditSubscription.propTypes = {
doc: PropTypes.object,
history: PropTypes.object.isRequired
};
export default createContainer(({ match }) => {
const subscriptionId = match.params._id;
const subscription = Meteor.subscribe('subscriptions.view', subscriptionId);
return {
loading: !subscription.ready(),
doc: Subscriptions.findOne(subscriptionId)
};
}, EditSubscription);

View file

@ -3,7 +3,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Row, Col } from 'react-bootstrap';
import { Trans, translate } from 'react-i18next';
import { translate } from 'react-i18next';
import DistanceSlider from '/imports/ui/components/DistanceSlider/DistanceSlider';
import SelectionMap from '/imports/ui/components/SelectionMap/SelectionMap';
import Gkeys from '/imports/startup/client/Gkeys';
@ -14,7 +14,9 @@ class FireSubscription extends React.Component {
constructor(props) {
super(props);
this.state = {
init: false
init: false,
center: this.props.center,
distance: this.props.distance
};
// console.log(this.props.location.state);
}
@ -27,7 +29,7 @@ class FireSubscription extends React.Component {
}
onAutocompleteChange(value) {
this.setState({ lat: value.lat, lng: value.lng });
this.setState({ center: [value.lat, value.lng] });
}
onSliderChange(value) {
@ -35,11 +37,15 @@ class FireSubscription extends React.Component {
}
onSelection(value) {
this.setState({ lat: value.lat, lng: value.lng, distance: value.distance });
this.setState({ center: [value.lat, value.lng], distance: value.distance });
}
onSubs(value) {
this.props.onSubs(value);
}
centerOnUserLocation(value) {
this.setState({ lat: value.center[0], lng: value.center[1] });
this.setState({ center: value.center });
}
render() {
@ -54,7 +60,6 @@ class FireSubscription extends React.Component {
<Row>
<Col xs={12} sm={12} md={6} lg={6} >
<div>
<h4 className="page-header"><Trans parent="span">Suscríbete a alertas de fuegos</Trans></h4>
<SubsAutocomplete
focusInput={this.props.focusInput}
onChange={value => this.onAutocompleteChange(value)}
@ -70,10 +75,11 @@ class FireSubscription extends React.Component {
</Row>
<Row className="align-items-center justify-content-center">
<SelectionMap
center={[this.state.lat, this.state.lng]}
center={this.state.center}
distance={this.state.distance}
history={this.props.history}
subsBtn={this.props.subsBtn}
onSelection={state => this.onSelection(state)}
onSubs={state => this.onSubs(state)}
/>
</Row>
</div>
@ -82,8 +88,12 @@ class FireSubscription extends React.Component {
}
FireSubscription.propTypes = {
history: PropTypes.object.isRequired,
focusInput: PropTypes.bool.isRequired
t: PropTypes.func.isRequired,
center: PropTypes.arrayOf(PropTypes.number),
distance: PropTypes.number,
focusInput: PropTypes.bool.isRequired,
subsBtn: PropTypes.string.isRequired,
onSubs: PropTypes.func.isRequired
};
export default translate([], { wait: true })(FireSubscription);

View file

@ -12,7 +12,7 @@ import ReactResizeDetector from 'react-resize-detector';
import _ from 'lodash';
import { ScrollToTopOnMount, SectionsContainer, Section } from 'react-fullpage';
import 'html5-device-mockups/dist/device-mockups.min.css';
import FireSubscription from '/imports/ui/pages/FireSubscription/FireSubscription';
import SubscriptionEditor from '/imports/ui/components/SubscriptionEditor/SubscriptionEditor';
import FiresMap from '../FiresMap/FiresMap';
import './Index.scss';
@ -218,7 +218,8 @@ class Index extends Component {
<Section className="">
<div className="container">
<FireSubscription history={this.props.history} focusInput={false} />
<h4 className="page-header"><Trans parent="span">Suscríbete a alertas de fuegos</Trans></h4>
<SubscriptionEditor history={this.props.history} />
</div>
<div className="overlay" />
</Section>

View file

@ -0,0 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Trans, translate } from 'react-i18next';
import SubscriptionEditor from '../../components/SubscriptionEditor/SubscriptionEditor';
const NewSubscription = ({ history }) => (
<div className="NewSubscription">
<h4 className="page-header"><Trans>Nueva suscripción</Trans></h4>
<SubscriptionEditor history={history} />
</div>
);
NewSubscription.propTypes = {
history: PropTypes.object.isRequired
};
export default translate([], { wait: true })(NewSubscription);

View file

@ -0,0 +1,105 @@
/* eslint-disable react/jsx-indent-props */
/* eslint-disable import/no-absolute-path */
/* eslint-disable react/jsx-indent */
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import { Table, Alert, Button, Row } from 'react-bootstrap';
import { timeago, monthDayYearAtTime } from '@cleverbeagle/dates';
import { Meteor } from 'meteor/meteor';
import { withTracker } from 'meteor/react-meteor-data';
import { Trans, translate } from 'react-i18next';
import { Bert } from 'meteor/themeteorchef:bert';
import UserSubsToFiresCollection from '/imports/api/Subscriptions/Subscriptions';
import Loading from '../../components/Loading/Loading';
import './Subscriptions.scss';
const handleRemove = (subscriptionId) => {
if (confirm('Are you sure? This is permanent!')) {
Meteor.call('subscriptions.remove', subscriptionId, (error) => {
if (error) {
Bert.alert(error.reason, 'danger');
} else {
Bert.alert('Subscription deleted!', 'success');
}
});
}
};
const Subscriptions = ({
loading,
subscriptions,
match,
history
}) => (!loading ? (
<div className="Subscriptions">
<div className="page-header clearfix">
<h4 className="pull-left"><Trans>Suscripciones a fuegos en áreas de mi interés</Trans></h4>
<Link className="btn btn-success pull-right" to={`${match.url}/new`}><Trans>Añadir suscripción</Trans></Link>
</div>
<br />
{subscriptions.length ?
<Table responsive>
<thead>
<tr>
<th>Location</th>
<th>Last Updated</th>
<th>Created</th>
<th />
<th />
</tr>
</thead>
<tbody>
{subscriptions.map(({
_id,
location,
createdAt,
updatedAt
}) => (
<tr key={_id}>
<td>{location.lat},{location.lon}</td>
<td>{timeago(updatedAt)}</td>
<td>{monthDayYearAtTime(createdAt)}</td>
<td>
<Button
bsStyle="primary"
onClick={() => history.push(`${match.url}/${_id}`)}
block
>View
</Button>
</td>
<td>
<Button
bsStyle="danger"
onClick={() => handleRemove(_id)}
block
>Delete
</Button>
</td>
</tr>
))}
</tbody>
</Table> :
<Alert bsStyle="warning"><Trans>Todavía sin suscriptiones</Trans></Alert>
}
</div>
) : <Loading />);
Subscriptions.propTypes = {
loading: PropTypes.bool.isRequired,
subscriptions: PropTypes.arrayOf(PropTypes.object).isRequired,
match: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
};
export default translate([], { wait: true })(withTracker(() => {
const subscription = Meteor.subscribe('subscriptions');
// console.log(UserSubsToFiresCollection.find().fetch());
return {
loading: !subscription.ready(),
subscriptions: UserSubsToFiresCollection.find().fetch()
};
})(Subscriptions));

View file

@ -0,0 +1,3 @@
.Subscriptions table tbody tr td {
vertical-align: middle;
}

View file

@ -0,0 +1,65 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ButtonToolbar, ButtonGroup, Button } from 'react-bootstrap';
import { createContainer } from 'meteor/react-meteor-data';
import { Meteor } from 'meteor/meteor';
import { Bert } from 'meteor/themeteorchef:bert';
import Subscriptions from '../../../api/Subscriptions/Subscriptions';
import NotFound from '../NotFound/NotFound';
import Loading from '../../components/Loading/Loading';
const handleRemove = (subscriptionId, history) => {
if (confirm('Are you sure? This is permanent!')) {
Meteor.call('subscriptions.remove', subscriptionId, (error) => {
if (error) {
Bert.alert(error.reason, 'danger');
} else {
Bert.alert('Subscription deleted!', 'success');
history.push('/subscriptions');
}
});
}
};
const renderSubscription = (doc, match, history) => (doc ? (
<div className="ViewSubscription">
<div className="page-header clearfix">
<h4 className="pull-left">{ doc && doc.title }</h4>
<ButtonToolbar className="pull-right">
<ButtonGroup bsSize="small">
<Button onClick={() => history.push(`${match.url}/edit`)}>Edit</Button>
<Button onClick={() => handleRemove(doc._id, history)} className="text-danger">
Delete
</Button>
</ButtonGroup>
</ButtonToolbar>
</div>
{ doc && doc.body }
</div>
) : <NotFound />);
const ViewSubscription = ({
loading,
doc,
match,
history
}) => (
!loading ? renderSubscription(doc, match, history) : <Loading />
);
ViewSubscription.propTypes = {
loading: PropTypes.bool.isRequired,
doc: PropTypes.object,
match: PropTypes.object.isRequired,
history: PropTypes.object.isRequired
};
export default createContainer(({ match }) => {
const subscriptionId = match.params._id;
const subscription = Meteor.subscribe('subscriptions.view', subscriptionId);
return {
loading: !subscription.ready(),
doc: Subscriptions.findOne(subscriptionId)
};
}, ViewSubscription);