Skip to content

Instantly share code, notes, and snippets.

@tnightingale
Last active August 24, 2016 23:16
Show Gist options
  • Save tnightingale/c6c0d9e28544d32456dfdd5f2f439127 to your computer and use it in GitHub Desktop.
Save tnightingale/c6c0d9e28544d32456dfdd5f2f439127 to your computer and use it in GitHub Desktop.
import StateProxy from "./state-proxy";
const {params, dispatch, state} = this.props,
{organization, trip} = params;
// Proxy objects are light-weight & contain very little of own state. Just a mechanism for
// traversing a state tree.
// Only StateProxy instance holds reference to state tree.
// The idea is it would be created after memoized selectors are run in mapStateToProps() or render().
let stateProxy = new StateProxy(dispatch, state),
tripProxy = stateProxy.trip(organization, trip),
// Traversing relationship; returns a RecordProxy object.
recordProxy = tripProxy.tripDetail();
console.log(tripProxy.data(), recordProxy.data());
for (tripProxy of stateProxy.trips(organization)) {
console.log(tripProxy.data(), tripProxy.tripDetail().data());
}
import {saveRecord} from "./actions/r_record";
export default class RecordsProxy {
constructor(state, organization) {
this._state = state;
this._organization = organization;
}
dispatch(action) {
return this._state.dispatch(action);
}
record(id) {
return new RecordProxy(this, id);
}
data(id) {
const data = this._state.recordsData().getIn([this._organization, id]);
if (!data) {
throw new Error(`Missing record ${this._id} in ${this._organization} organization.`);
}
return data;
}
save(data) {
return this.dispatch(saveRecord(this._organization, data));
}
}
class RecordProxy {
constructor(records, id) {
this._records = records;
this._id = id;
}
data() {
return this._records.data(this._id);
}
save(data) {
return this._records.save(data);
}
}
import {idFromParam} from "./util";
import TripsProxy from "./trip-proxy";
import RecordsProxy from "./record-proxy";
export default class StateProxy {
constructor(dispatch, {records, trips, docsSyncStatus}) {
this._dispatch = dispatch;
this._records = records;
this._trips = trips;
this._docsSyncStatus = docsSyncStatus;
}
dispatch(action) {
return this._dispatch(action);
}
recordsData() {
return this._records;
}
tripsData() {
return this._trips;
}
records(organization) {
return new RecordsProxy(this, organization);
}
record(organization, id) {
return this.records(organization).record(id);
}
trips(organization) {
return new TripsProxy(this, organization);
}
trip(organization, id) {
return this.trips(organization).trip(id);
}
}
import {saveTrip} from "./actions/trips";
export default class TripsProxy {
constructor(state, organization) {
this._state = state;
this._organization = organization;
}
dispatch(action) {
return this._state.dispatch(action);
}
trip(id) {
return new TripProxy(this, id);
}
data(id) {
const data = this._state.tripsData().getIn([this._organization, id]);
if (!data) {
throw new Error(`Missing trip ${id} in ${this._organization} organization.`);
}
return data;
}
save(data) {
return this.dispatch(saveTrip(this._organization, data));
}
tripDetail(id) {
const data = this.data(id),
tripDetailId = data.get('tripDetailId');
return this._state.record(this._organization, tripDetailId);
}
[Symbol.iterator]() {
const data = this._state.tripsData(),
iterator = data.get(this._organization).values();
return {
next: () => {
const {done, value: trip} = iterator.next(),
next = {done, value: undefined};
if (trip) next.value = this.trip(trip.get('_id'));
return next;
}
};
}
}
class TripProxy {
constructor(trips, id) {
this._trips = trips;
this._id = id;
}
data() {
return this._trips.data(this._id);
}
tripDetail() {
return this._trips.tripDetail(this._id);
}
save(data) {
return this.save(data);
}
async startTrip() {
const data = this.data();
try {
await this.toggleTrackingEnabled(true);
this.save(data.merge({
start: (new Date()).toISOString(),
active: true
}));
} catch (error) {
console.warn("There was a problem enabling background location tracking. This should be handled in an action so that the error can be correctly routed.");
}
}
async completeTrip() {
const data = this.data();
try {
await this.toggleTrackingEnabled(false);
this.save(data.merge({
end: (new Date()).toISOString(),
active: false
}));
} catch (error) {
console.warn("There was a problem disabling background location tracking. This should be handled in an action so that the error can be correctly routed.");
}
}
async toggleTrip() {
const data = this.data(),
active = data.get('active', false);
try {
await this.toggleTrackingEnabled(!active);
this.save(data.set('active', !active));
} catch (error) {
console.warn("There was a problem toggling background location tracking. This should be handled in an action so that the error can be correctly routed.");
}
}
toggleTrackingEnabled(enable) {
return new Promise((resolve, reject) => {
const success = () => {
console.log(enable ? "Enabled!" : "Disabled");
resolve();
},
error = (errorMessage) => {
console.warn("Could not toggle tracking:", errorMessage);
reject(errorMessage);
};
if (!window.BackgroundGeolocation) {
console.warn("window.BackgroundGeolocation is undefined. Tracking enabled: ", enable);
return success();
}
if (enable) {
window.BackgroundGeolocation.start(success, error);
} else {
window.BackgroundGeolocation.stop(success, error);
}
});
}
submit() {
const data = this.data(),
tripDetail = this.tripDetail();
// TODO: This should be wrapped up in a submit() method on RecordProxy.
const record = tripDetail.data(),
submitted = (new Date()).toISOString();
tripDetail.save(record.set('submitted', submitted));
this.save(data.set('submitted', submitted));
}
delete() {
const data = this.data(),
tripDetail = this.tripDetail();
// tripId = trip.get('_id'),
// tripDetail = tripDetails.get(tripId);
// TODO: This should be wrapped up in a delete() method on RecordProxy.
const record = tripDetail.data();
if (record) {
tripDetail.save(record.set('_deleted', true));
} else {
console.warn(`Missing trip details record for trip: ${this._id}.`);
}
this.save(data.set('_deleted', true));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment