Coding for Social Good: Building Refugee Finder Part 1

TL;DR

In this article I discuss the first day of building Refugee Finder. I will cover the following:

  • Cloning my Meteor skeleton
  • Converting LayoutIt HTML layouts to Meteor templates
  • Creating a quick event map for the buttons from above
  • Creating initial set of collections
  • Creating first set of routes (mostly static) using FlowRouter

Getting Started, the Clone Way

It’s been a few months since I’ve been able to work with Meteor. I wanted to get started quick and the thought of architecting the initial file hierarchy made me pause. A blank slate is always so daunting.

Fortunately, just before I took my break from coding I created a real nice skeleton for myself (as well as super-tuned my .vimrc [currently issues w/html & spacebars fighting] and other dotfiles).

git clone git@github.com/iDoMeteor/meteor-skeleton.git
mv meteor-skeleton refugeefinder
cd refugeefinder && mv myproject finder
vim finder/client/* finder/lib/* finder/server/* finder/lib/init/*

Boom, that’s done, son!

Converting LayoutIt layouts to Meteor Templates

I created 7 or 8 quick templates using LayoutIt. Since both of my content management systems are built using Bootstrap, I have learned it pretty well and I like things that are ubiquitous so we will be taking that route for now.

I am a function over fashion sort of guy, so I really just slapped in a few buttons on a bunch of screens without much concern. I just wanted to layout the basic feature elements so that my friend could click around and get the basic feature set in mind.

I could have written these from scratch straight into Meteor templates in about the same amount of time that it took me to make those layouts, but I felt pretty lazy and had not written any code in a while… so it seemed easier on the brain at the time.

Since I already had my main.html open, I threw in a quick , and then I copy/pasted that a bunch of times for each of the templates that I had made and a few extra. Then I searched for XXX and went through and named them all.

I used the download feature and grabbed each of those as a zip file. Then I went and unzipped them all, opened them in gedit and copied the main bootstrap row and content then pasted them one at a time into their Meteor containers.

For the time being, each template contains the full row and column declarations. Eventually they will be factored out, but I left them as is until we work through the UI design.

I threw in a quick wrapper template with a Spacebar tags for the header, footer and content. While I have not used dynamic templates yet, I am pretty sure I remembered the syntax correctly and moved on.

The first main.html file

Quick CSS & Event Outlines

Before I actually pasted in the template content, I copied all the named template tags and pasted them into the main.css and main.js files. Then I did some global substitions (:%s/<template name=”/Template./ and :%s/”>/.events({/ etc…). Easy peasy.

Thankfully, I had just skated through the blank slate dilemma in no time at all.

Navigational Events

Since I just read most of the Meteor Guide, I remembered that FlowRouter.go() does what I used to use Router.go for. I used my ,ei vim shortcut to put in a quick ID based event function block and put FlowRouter.go(‘XXX”) inside of it. I copied the whole block and pasted it into each Template.xxx.events containers that I envisioned as being navigational elements.

After I went through and named them all appropriately, the other event blocks looked sad all empty. Knowing that I will eventually create a universal RF API object, I went through and added a phantom RF.popModal(‘XXX’) to all of those. Repeat naming process.

I threw in one or two others, such as RF.sendContact() for good measure, and now none of my event blocks were empty.

The first main.js

The Global API

Looks like I did create a quick RF object in the first api.js file, just for posteriety. :smile:

Collections

Generally, this is where I would have started. I find that by giving each obvious feature / data set a collection and schema, it helps organize my mind for the project ahead. I spend a bit of time here, thinking about relationships, normalization, denormalization and all those other database goodies.

However, I really want to get RF to MVP status as quickly as possible so I just declared the most obvious collections and moved on.

The first collections file

Routes

It was getting late, so I took a bit of a break. I wished it I could just fire it up and click around now, but of course without any routes defined, all those FlowRouter.go()s were pretty useless.

Desire beat out laziness for the most part and I tossed in my first route.

FlowRouter.route(‘/alerts/new’, {
name: ‘alertProfileNew’,
action () {
BlazeLayout.render(‘wrapper’,
{main: ‘alertProfileNew’}
);
}
});

Pretty straight forward, as I took the block template straight from the Meteor Guide. I copy and pasted this, put XXX in all the places that would need to be changed for each route, then copied the whole block about 40 times (I counted the CSS tags from earlier).

I’m sure you can guess what I did at this point.

After I customized all the routes I realized that I still needed a few things before I could gleefully click around on my pretty useless buttons.

The first routes.js file

Packages

My skeleton does not include FlowRouter or BlazeLayout by default, so I needed to add those.

meteor add kadira:flow-router
meteor add kadira:blaze-layout

I’m pretty sure I could have done this in one command, but Meteor used to hate on me for trying that so habit won there.

The Big Test

Thinking about firing it up, I realized that I had not created the template for the main route / first dynamically loaded template. I just took a guess and threw this in real quick:

FlowRouter.route(‘/’, {
name: ‘main’,
action: function () {
BlazeLayout.render(‘wrapper’,
{main: ‘main’}
);
}
});

I went for it. Failure.

Seems there is a potential typo in the Meteor Guide, I needed to add a ‘: function’ after ‘action’ and before the ‘() {‘. It is possible, I realized at the time, that since I had not updated Meteor to 1.2 (scared to mess up my OPW & MP work, lol) that this may be ECMA 6 shorthand.

I did a quick global search and replace to fix it up.

Success

Meteor went ahead and recompiled it for me while I was in my vim screen buffer and it suddenly appeared in my browser window on the other monitor. One of those magic “Man, I LOVE Meteor” moments. :slight_smile:

I clicked around a bit, it worked pretty well. A couple missing routes, links and etc… but at least now my friend could see where I was going with the whole thing.

Next Steps

Well, I’ve already thrown in a back button but I didn’t make it too smart. My next steps will be to clean up the missing routes and interface buttons and make sure I can navigate around the entirety of the application. Then I will add a v1.0.0-alpha.1 tag to the repository and move along to alpha 2 and start getting some real work done.

Follow along on Twitter or Github or check back in a week or so for part 2 of ‘Coding for Social Good’, Refugee Finder edition.

Thanks for reading!

@iDoMeteor (those interested participating, contact me here)
@Refugee_Finder
http://RefugeeFinder.org (coming soon)
http://Demo.RefugeeFinder.org (alpha 1)
https://github.com/iDoMeteor/RefugeeFinder
http://iDoMeteor.com

The first article in this series can be found here: ‘Coding for Social Good: About Refugee Finder’.

6 Likes

Question: Why so many Mongo collections? Seems like information is related. What did you have in mind?

Having said that, I’d be interested in contributing as a “payback” for my mentoring, what do you need done?

2 Likes

Contributing

You are more than welcome to join in the effort! What are your particular strong points?

This is a good time to jump in, while it is small and simple. Tomorrow will be a full day of coding for me and I will probably work mostly on the back end and throwing in a few place holders on the front end. Hamza is going to do most of the design, mapping and data scraping.

Working on the front end would probably be a good place to start, while I flesh out the API and such. We could chat about it more directly via Hangouts or Twitter.

Collections

With regards to your query about the number of collections, collections are cheap.

Some of the information is indeed related. However, due to the way Mongo & Minimongo work, it is typical to denormalize data at times and this is what I am planning to do.

Basically, I like simple queries and so does Mongo for the most part, although they have recently added some more typical ANSI SQL type joining methods and such. So, while I could keep the data related to help centers and border crossings in the same collection with slightly different fields based on the type… I would then have to provide both of them with a type field.

And then I might think…maybe the type field should be an ID, in case something changes in the future. Then I need a new collection to give me various types of label and help for each ID field. UGH.

If I need data from both sets together, it would be easier to perform two separate queries for just the fields that I needed and join them via underscore (although with massive data sets this would be a total performance killer).

I will add comment blocks to each collection when I define their schemas.

I have created a Trello board to track issues and progress, it will get quite a bit more robust quickly. :smile: