Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
React Uniforms Field for a map configuration
import _ from 'lodash';
import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session';
import { Bert } from 'meteor/themeteorchef:bert';
import React from 'react';
import { BaseField } from 'uniforms';
import UIMapPoly from 'react-map-polygon-selector';
// ------------------------------------------
// this is the map getMatchData function
// must return to the callback the following pattern
// callback(null, { matches: 99 });
// @param object mapData { center, bounds, rectangles, polygons, etc. }
// @param function callback from UIMapPoly, so it can receive { matches: <val> }
// ------------------------------------------
// to ignore matches, replace this with: const getMatchData = _.noop;
// ------------------------------------------
const getMatchData = (mapData, callback) => {
console.log('getMatchData input', mapData);
console.log('getMatchData response handler/Callback', callback);
Meteor.call('Buckets.GetMapsMatchData', mapData, (err, res) => {
console.log('getMatchData response', err, res);
callback(null, res);
});
};
// we need to alert if we disallow an overlay
const handleOverlayRejected = (reason) => {
console.error('Map Overlay Rejected', reason);
Bert.error(reason);
};
// this is the "base" data for the map, if we don't have a conf.map yet...
const getDefaultMap = (bucketId = '') => {
const map = {
// setting the default bucketId - needed by GetMapsMatchData
bucketId,
// center: undefined,
markers: [],
polygons: [],
circles: [],
rectangles: [],
// currentArea: 0,
matchData: {},
};
if (!map.center) {
// eslint-disable-next-line
const defaultCenter = Session.get('defaultMapCenter');
if (defaultCenter) {
map.center = defaultCenter;
}
}
return map;
};
// sticky map center = faster map loading (less geocoding)
const setDefaultCenterFromMapData = mapData => {
if (!(mapData && mapData.center)) return;
// eslint-disable-next-line
Session.set('defaultMapCenter', mapData.center);
};
// um... sometimes we are getting some junk in our data from the map
// this cleans it for storage into conf.map
const cleanMapData = (dataIn) => {
const mapData = _.cloneDeep(dataIn);
// translate map data into conf
Object.keys(mapData).forEach(key => {
if (!_.isObject(mapData[key])) return;
if (typeof mapData[key].toJSON !== 'function') return;
mapData[key] = mapData[key].toJSON();
});
return mapData;
};
// Here's the actual Uniforms enabled field
// NOTE this is using direct context vs. connectField()
// could possibly be refactored...
const MapEditField = (props, { uniforms: { model, onChange } }) => {
const name = props.name || 'conf.map';
// save data from the map, back into the uniforms model
const handleSubmit = (mapData) => {
setDefaultCenterFromMapData(mapData);
onChange(name, cleanMapData(mapData));
};
let map = _.result(model, name);
if (!map) {
map = getDefaultMap();
}
const bucketId = model._id || 'newBucket';
return (
<UIMapPoly
editable={true}
getMatchData={(mapData, cb) => {
mapData.bucketId = bucketId;
getMatchData(mapData, cb);
}}
handleSubmit={handleSubmit}
handleOverlayRejected={handleOverlayRejected}
{...map}
/>
);
};
MapEditField.contextTypes = BaseField.contextTypes;
MapEditField.propTypes = {
name: React.PropTypes.string,
};
export default MapEditField;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment