What I Learned from My First Dev Competition – A story about discovery and having fun! – Quick Intro



What I Learned from My First Dev Competition – A story about discovery and having fun! – Quick Intro

0 0


whatilearned

A presentation about discovery, trial and error, and having fun!

On Github fmitchell / whatilearned

What I Learned from My First Dev Competition

A story about discovery and having fun!

Created by Fredric Mitchell / @fredricmitchell

What are we talking about?

The Why The Competition The Idea The Plan The Architecture The Code The Product The Lesson

Quick Intro

Paid Gig

Web Development Manager at Orbit Media Studios

Quick Intro

Passions

Drupal, DRY / KISS, Strat. Comm., Graphic Novels

Quick Intro

Learning

Javascript, Patience, Spanish

The Why

I've always enjoyed discovery through blogs, Hacker News, Sitepoint, PHP Weekly, etc.

I seem to never have the time.

Is there a way to force myself to make time?

After all...

“Tell me and I forget. Teach me and I remember. Involve me and I learn.” - Benjamin Franklin

The Perfect Impetus

A developer competition engaged my ego, within timed parameters, to build something while allowing me to reach outside my comfort zone.

The Competition

by JotForm

http://developers.jotform.com/competition/

Reconaissance

JotForm Facts

JotForm is a simple web application to build forms. JotForm users are requesting desired apps. JotForm experts were available for help. JotForm is providing hosting, if desired.

Reconaissance

Integration

JotForm has a RESTful API. JotForm provides best practice examples. JotForm has published a PHP library.

Let's do this.

Time to build!

The Idea

KISS

Something that doesn't require a lot of explanation.

Something that incorporates libraries I've read about.

The Idea

JotMap

Make a map.

Play with Leaflet.js.

The Plan

Reality

Four weeks +wife, kids (life) +learning something new = 5 hours / week

Keep technical debt small.

The Plan

KISS. Iterate.

  • Week 1: Establish and install libraries locally.
  • Week 2: Create JotForm sample. Build workflow for each page.
  • Week 3: Refine presentation. Optimize and cache.
  • Week 4: Test. Test.

The Architecture

Try All the Things!

  • Slim - Quick callbacks
  • Bootstrap - Not a designer
  • Mustache - Simple templates
  • JotForm Wrapper - Quickstart
  • Geocoder PHP - Maps like lat/long
  • Mongo - Cache?

The Architecture

Composer

                            {
    "require": {
        "jotform/jotform-api-php": "dev-master",
        "mustache/mustache": "~2.1",
        "willdurand/geocoder": "~2.3",
        "ext-mongo": "*",
        "slim/slim": "2.*"
    },
    "autoload": {
        "classmap": ["src/"]
    }
}
                        

Slim

PHP Micro Framework

Simple way to map urls to callbacks.

http://www.slimframework.com/

Initialize Slim

index.php

                            // Load composer libraries.
require 'vendor/autoload.php';

$app = new \Slim\Slim(array(
    'debug' => FALSE
));

$app->get('/', function() use ($app) {
    $app->render('step1.php');
});

// more steps...

$app->run();
                        

Bootstrap

Make it pretty.

http://getbootstrap.com/

Initialize Bootstrap

Use a CDN.

                            <!-- head -->
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
<!-- /head -->

<!-- body -->
<!-- some stuff -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<!-- /body -->
                        

Mustache Templates

Easily reuse HTML.

http://mustache.github.io/

Initialize Mustache

src/mustache.php

                            class JotMapMustache extends Mustache_Engine {

    public function __construct() {
        // Mustache setup.
        $mustache_options = array(
            'loader' => new Mustache_Loader_FilesystemLoader(dirname(dirname(__FILE__)).'/views'),
            'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(dirname(__FILE__)).'/views/partials'),
        );

        parent::__construct($mustache_options);
    }
}
                        

Alternative to relying on Slim Views

JotForm Library

PHP & JS to interact.

Follow docs and examples of how to work with Jotform services.

http://developers.jotform.com/libraries

https://github.com/jotform/jotform-api-php

http://developers.jotform.com/integrations/

Initialize JotForm data

step2.php, step3.php, etc.

                            try {
    $jotformAPI = new JotForm($key);
} catch (Exception $e) {
}

// Check if any forms return.
if ($forms = $jotformAPI->getForms()) {
    // do some stuff
}
                        

Geocode

Take addresses and make lat/long.

http://geocoder-php.org/

Initialize Geocoder Library

map.php

                            // Setup geocoder.
$adapter = new \Geocoder\HttpAdapter\CurlHttpAdapter();
$geocoder = new \Geocoder\Geocoder();
$chain = new \Geocoder\Provider\ChainProvider(
    array(
        new \Geocoder\Provider\GoogleMapsProvider($adapter),
    )
);
$geocoder->registerProvider($chain);

// Try to geocode.
try {
    $geocode = $geocoder->geocode($address);
    $longitude = $geocode->getLongitude();
    $latitude = $geocode->getLatitude();
    // do more stuff...
}
                        

Mongo

Cache geocoded addresses?

http://www.mongodb.org/

https://mongolab.com/

Initialize Mongo connection

map.php

                            // Mongo URI.
$mongo_uri = "mongodb://foo:bar@ds00000.mongolab.com:43338/jotmap";

// Setup Mongo for storing already geocoded submissions.
$uriParts = explode("/", $mongo_uri);
$dbName = $uriParts[3];

// Attempt to connect to mongo database.
try {
    $client = new MongoClient($mongo_uri);
    $db = $client->$dbName;
    $mongo_submissions = $db->submissions;
    } catch (Exception $e) {
}
                        

Other Decisions

  • Explore Mixpanel analytics
  • Keep it GET
  • Nice error page
  • Provide example link
  • Provide help link
  • Allow embed via iframe :-P

The Code

Deeper dive.

Let's review, in greater detail, some of the parts to make it work.

Mustache Partials

views/partials/step1.mustache

                            {{> pagetitle }}
<div id="loginresults"></div>
<button id="jotformlogin" class="btn btn-success btn-lg">Authorize JotMap</button>

<h3>OR</h3>

<form id="step1form" role="form" action="/step2" method="get">
    <div class="input-group">
        <input type="text" class="form-control input-lg" id="jotformAPIKey" placeholder="Enter API Key" name="jotformapi">
        <span class="input-group-btn">
            <button type="submit" id="jotmapstep1" class="btn btn-success btn-lg">Next ››</button>
        </span>
    </div>
</form>
<script>
mixpanel.track('Step1 viewed', {'page name' : document.title, 'url' : window.location.pathname, 'parameters' : window.location.search.replace( "?", "" )});
mixpanel.track_forms("#step1form", "Step1 form submission");
$("#jotmapstep1").click(function() {
    mixpanel.track("Step1 clicked");
});
</script>
                        

Mustache Rendering

step1.php

                            // Mustache template loading.
$m = new JotMapMustache;
$page = $m->loadTemplate('page');

// Hash
$hash = array(
    'pagetitle' => 'Enter JotForm API Key',
    'step' => 1,
    'jotformauth' => TRUE,
    'sidebar-hidden' => TRUE,
);
echo $page->render($hash);
                        

Getting Submissions

My Big Assumption

                            // Go through each submission to geocode.
// Based on quick testing, usage of JotForm.
foreach ($submissions as $submission) {

    // Setup variables.
    $id = $submission['id'];
    $form_id = $submission['form_id'];

    $address_answer = $submission['answers'][$jotaddress]['answer'];
    $label_answer = $submission['answers'][$jotlabel]['answer'];

    $address = (is_array($address_answer))
        ? implode(', ', $submission['answers'][$jotaddress]['answer'])
        : $address_answer;
    $name = (is_array($label_answer))
        ? implode(' ', $submission['answers'][$jotlabel]['answer'])
        : $label_answer;

    // Build Mongo query parameters.
    $query = array(
        'id' => $submission['id'],
        'form_id' => $submission['form_id']
    );

    // See if record is already in db.
    $existing = (isset($mongo_submissions) && is_object($mongo_submissions))
        ? $mongo_submissions->findOne($query)
        : null;

    // More stuff.
}
                        

Mapping

Leaflet is dead simple.

                            // mapdata.mustache
<script>
    {{> mapjs }}
    {{# markerdata }}
    {{> markerjs }}
    {{/ markerdata }}
    var group = new L.featureGroup([{{marker_ids}}]);
    map.fitBounds(group.getBounds());
</script>

// mapjs.mustache
var map = L.map('map');

L.tileLayer('//{s}.tile.cloudmade.com/{{cloudmade_api_key}}/998/256/{z}/{x}/{y}.png', {
attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="http://cloudmade.com">CloudMade</a>',
maxZoom: 18
}).addTo(map);

// markerjs.mustache
var {{marker_id}} = L.marker([{{lat}}, {{long}}]).addTo(map);
{{marker_id}}.bindPopup("{{label}}");
                        

The Product

http://jotmap.jotform.io

Yay!

But tired.

The Lesson

Have fun. Stay positive.

There will be critics, late nights, and not perfect implementations in your first implementation.

The point is to learn, not hate.

The Lesson

Analyze ALL THE THINGS.

The Lesson

Analyze your analytics.

The Lesson

Embrace failure.

The Lesson

HTTP Request-type GET is OK.

The Lesson

Your assumptions will be wrong.

The trade off of KISS is that user needs are complex.

Must decide, within the budget (time, cost) that you have, what will be Phase 2, 3, etc.

The Lesson

Roll with the punches.

The Lesson

Share your experience.

Allows for alternative opinions and approaches.

Possibly gives you uses for soft launch.

Inspires others to keep trying.

Contribute to the community (patches, pull requests).

The Lesson

Better learning by doing.

Learning on your own time, by doing, is magical.

JotMap

Patches welcome.

jotmap.jotform.io

github.com/fmitchell/jotmap

Questions?

By Fredric Mitchell / @fredricmitchell

Slides: brightplumbox.com/whatilearned

Slides Repo: github.com/fmitchell/whatilearned

Feedback: joind.in/talk/view/10066