diff options
author | Aaron Parecki <aaron@parecki.com> | 2016-02-10 18:36:55 -0800 |
---|---|---|
committer | Aaron Parecki <aaron@parecki.com> | 2016-02-10 18:36:55 -0800 |
commit | d62b497b401a767c9a8db153726e0c7e1f2c474e (patch) | |
tree | 60f9890178795f0b0893b312bcdffd1d08bf2ac0 | |
parent | 75d075412f0bbba867772e9a05e00480090cc290 (diff) |
add interface for posting travel itinerary
-rw-r--r-- | controllers/controllers.php | 45 | ||||
-rw-r--r-- | lib/helpers.php | 51 | ||||
-rw-r--r-- | public/js/script.js | 32 | ||||
-rw-r--r-- | views/new-itinerary.php | 209 |
4 files changed, 306 insertions, 31 deletions
diff --git a/controllers/controllers.php b/controllers/controllers.php index 70e84cf..0b63699 100644 --- a/controllers/controllers.php +++ b/controllers/controllers.php @@ -130,6 +130,18 @@ $app->get('/favorite', function() use($app) { } }); +$app->get('/itinerary', function() use($app) { + if($user=require_login($app)) { + $params = $app->request()->params(); + + $html = render('new-itinerary', array( + 'title' => 'Itinerary', + 'authorizing' => false + )); + $app->response()->body($html); + } +}); + $app->get('/photo', function() use($app) { if($user=require_login($app)) { $params = $app->request()->params(); @@ -217,7 +229,7 @@ $app->get('/add-to-home', function() use($app) { if($user=require_login($app)) { if(array_key_exists('start', $params)) { $_SESSION['add-to-home-started'] = true; - + $token = JWT::encode(array( 'user_id' => $_SESSION['user_id'], 'me' => $_SESSION['me'], @@ -260,7 +272,7 @@ $app->get('/email', function() use($app) { 'test_response' => $test_response, 'user' => $user )); - $app->response()->body($html); + $app->response()->body($html); } }); @@ -294,7 +306,7 @@ $app->get('/favorite-popup', function() use($app) { $params = $app->request()->params(); $html = $app->render('favorite-popup.php', array( - 'url' => $params['url'], + 'url' => $params['url'], 'token' => $params['token'] )); $app->response()->body($html); @@ -339,7 +351,7 @@ function create_favorite(&$user, $url) { if($user->twitter_access_token && preg_match('/https?:\/\/(?:www\.)?twitter\.com\/[^\/]+\/status(?:es)?\/(\d+)/', $url, $match)) { $tweet_id = $match[1]; - $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, + $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, $user->twitter_access_token, $user->twitter_token_secret); $result = $twitter->post('favorites/create', array( 'id' => $tweet_id @@ -373,7 +385,7 @@ function create_repost(&$user, $url) { if($user->twitter_access_token && preg_match('/https?:\/\/(?:www\.)?twitter\.com\/[^\/]+\/status(?:es)?\/(\d+)/', $url, $match)) { $tweet_id = $match[1]; - $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, + $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, $user->twitter_access_token, $user->twitter_token_secret); $result = $twitter->post('statuses/retweet/'.$tweet_id); } @@ -390,8 +402,8 @@ $app->get('/favorite.js', function() use($app) { $r = create_favorite($user, $params['url']); $app->response()->body($app->render('favorite-js.php', array( - 'url' => $params['url'], - 'like_url' => $r['location'], + 'url' => $params['url'], + 'like_url' => $r['location'], 'error' => $r['error'], // 'facebook_id' => $facebook_id ))); @@ -464,6 +476,20 @@ $app->post('/repost', function() use($app) { } }); +$app->post('/itinerary', function() use($app) { + if($user=require_login($app)) { + $params = $app->request()->params(); + + $r = micropub_post_for_user($user, json_decode($params['data'], true), null, true); + + $app->response()->body(json_encode(array( + 'location' => $r['location'], + 'error' => $r['error'], + 'response' => $r['response'] + ))); + } +}); + $app->get('/micropub/syndications', function() use($app) { if($user=require_login($app)) { $data = get_syndication_targets($user); @@ -545,7 +571,7 @@ $app->get('/auth/twitter', function() use($app) { // If there is an existing Twitter token, check if it is valid // Otherwise, generate a Twitter login link $twitter_login_url = false; - $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, + $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, $user->twitter_access_token, $user->twitter_token_secret); if(array_key_exists('login', $params)) { @@ -582,7 +608,7 @@ $app->get('/auth/twitter/callback', function() use($app) { if($user=require_login($app)) { $params = $app->request()->params(); - $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, + $twitter = new \TwitterOAuth\Api(Config::$twitterClientID, Config::$twitterClientSecret, $_SESSION['twitter_auth']['oauth_token'], $_SESSION['twitter_auth']['oauth_token_secret']); $credentials = $twitter->getAccessToken($params['oauth_verifier']); @@ -634,4 +660,3 @@ $app->get('/auth/instagram/callback', function() use($app) { $app->redirect('/settings'); } }); - diff --git a/lib/helpers.php b/lib/helpers.php index 8f435f0..a2796e1 100644 --- a/lib/helpers.php +++ b/lib/helpers.php @@ -75,23 +75,23 @@ function get_timezone($lat, $lng) { } if(!function_exists('http_build_url')) { - function http_build_url($parsed_url) { - $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; - $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; - $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; - $user = isset($parsed_url['user']) ? $parsed_url['user'] : ''; - $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : ''; - $pass = ($user || $pass) ? "$pass@" : ''; - $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; - $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : ''; - $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : ''; - return "$scheme$user$pass$host$port$path$query$fragment"; - } + function http_build_url($parsed_url) { + $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : ''; + $host = isset($parsed_url['host']) ? $parsed_url['host'] : ''; + $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : ''; + $user = isset($parsed_url['user']) ? $parsed_url['user'] : ''; + $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : ''; + $pass = ($user || $pass) ? "$pass@" : ''; + $path = isset($parsed_url['path']) ? $parsed_url['path'] : ''; + $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : ''; + $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : ''; + return "$scheme$user$pass$host$port$path$query$fragment"; + } } -function micropub_post_for_user(&$user, $params, $file_path = NULL) { +function micropub_post_for_user(&$user, $params, $file_path = NULL, $json = false) { // Now send to the micropub endpoint - $r = micropub_post($user->micropub_endpoint, $params, $user->micropub_access_token, $file_path); + $r = micropub_post($user->micropub_endpoint, $params, $user->micropub_access_token, $file_path, $json); $user->last_micropub_response = substr(json_encode($r), 0, 1024); $user->last_micropub_response_date = date('Y-m-d H:i:s'); @@ -109,7 +109,7 @@ function micropub_post_for_user(&$user, $params, $file_path = NULL) { return $r; } -function micropub_post($endpoint, $params, $access_token, $file_path = NULL) { +function micropub_post($endpoint, $params, $access_token, $file_path = NULL, $json = false) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $endpoint); curl_setopt($ch, CURLOPT_POST, true); @@ -118,14 +118,23 @@ function micropub_post($endpoint, $params, $access_token, $file_path = NULL) { // https://github.com/aaronpk/Quill/issues/4 // http://indiewebcamp.com/irc/2015-02-14#t1423955287064 $httpheaders = array('Authorization: Bearer ' . $access_token); - $params = array_merge(array( - 'h' => 'entry', - 'access_token' => $access_token - ), $params); + + if(!$json) { + $params = array_merge(array( + 'h' => 'entry', + 'access_token' => $access_token + ), $params); + } if(!$file_path) { - $post = http_build_query($params); - $post = preg_replace('/%5B[0-9]+%5D/', '%5B%5D', $post); // change [0] to [] + if($json) { + $params['access_token'] = $access_token; + $httpheaders[] = 'Content-type: application/json'; + $post = json_encode($params); + } else { + $post = http_build_query($params); + $post = preg_replace('/%5B[0-9]+%5D/', '%5B%5D', $post); // change [0] to [] + } } else { $finfo = finfo_open(FILEINFO_MIME_TYPE); $mimetype = finfo_file($finfo, $file_path); diff --git a/public/js/script.js b/public/js/script.js new file mode 100644 index 0000000..399af05 --- /dev/null +++ b/public/js/script.js @@ -0,0 +1,32 @@ + + function tz_seconds_to_offset(seconds) { + var tz_offset = ''; + var hours = zero_pad(Math.abs(seconds / 60 / 60)); + var minutes = zero_pad(Math.floor(seconds / 60) % 60); + return (seconds < 0 ? '-' : '+') + hours + ":" + minutes; + } + function zero_pad(num) { + num = "" + num; + if(num.length == 1) { + num = "0" + num; + } + return num; + } + + +$(function(){ + + // Set the date from JS + var d = new Date(); + $("#note_date").val(d.getFullYear()+"-"+zero_pad(d.getMonth()+1)+"-"+zero_pad(d.getDate())); + $("#note_time").val(zero_pad(d.getHours())+":"+zero_pad(d.getMinutes())+":"+zero_pad(d.getSeconds())); + $("#note_tzoffset").val(tz_seconds_to_offset(d.getTimezoneOffset() * 60 * -1)); + + // ctrl-s to save + $(window).on('keydown', function(e){ + if(e.keyCode == 83 && e.ctrlKey){ + $("#btn_post").click(); + } + }); + +}) diff --git a/views/new-itinerary.php b/views/new-itinerary.php new file mode 100644 index 0000000..8d8811c --- /dev/null +++ b/views/new-itinerary.php @@ -0,0 +1,209 @@ +<div class="narrow"> + <?= partial('partials/header') ?> + + <div style="clear: both;"> + <div class="alert alert-success hidden" id="test_success"><strong>Success! We found a Location header in the response!</strong><br>Your post should be on your website now!<br><a href="" id="post_href">View your post</a></div> + <div class="alert alert-danger hidden" id="test_error"><strong>Your endpoint did not return a Location header.</strong><br>See <a href="/creating-a-micropub-endpoint">Creating a Micropub Endpoint</a> for more information.</div> + </div> + + <form role="form" style="margin-top: 20px;" id="note_form"> + + <h4>Legs</h4> + <div class="form-group" id="itinerary-legs-container"> + <div style="display:none;" id="leg-template"> + <div class="itinerary-leg"> + <input type="hidden" class="template" value="1"> + <div class="remove">×</div> + <div class="row"> + <div class="col-xs-3"> + <label>Transit Type</label> + <select class="leg-transit-type form-control"> + <option value="air">Air</option> + <option value="train">Train</option> + <option value="bus">Bus</option> + <option value="boat">Boat</option> + <option value="generic">Generic</option> + </select> + </div> + <div class="col-xs-3"> + <label>Operator</label> + <input type="text" class="form-control leg-operator" placeholder="Operator" value=""> + </div> + <div class="col-xs-3"> + <label>Number</label> + <input type="text" class="form-control leg-number" placeholder="Number" value=""> + </div> + </div> + <div class="row"> + <div class="col-xs-2"> + <label>Origin</label> + <input type="text" class="form-control leg-origin" placeholder="Origin" value=""> + </div> + <div class="col-xs-9"> + <label>Departure</label> + <div class="form-group leg-departure"> + <input type="text" class="form-control leg-departure-date date" style="max-width:160px; float:left; margin-right: 4px;" value=""> + <input type="text" class="form-control leg-departure-time time" style="max-width:85px; float:left; margin-right: 4px;" value=""> + <input type="text" class="form-control leg-departure-tz tz" style="max-width:75px;" value=""> + </div> + </div> + </div> + <div class="row"> + <div class="col-xs-2"> + <label>Destination</label> + <input type="text" class="form-control leg-destination" placeholder="Destination" value=""> + </div> + <div class="col-xs-9"> + <label>Arrival</label> + <div class="form-group leg-arrival"> + <input type="text" class="form-control leg-arrival-date date" style="max-width:160px; float:left; margin-right: 4px;" value=""> + <input type="text" class="form-control leg-arrival-time time" style="max-width:85px; float:left; margin-right: 4px;" value=""> + <input type="text" class="form-control leg-arrival-tz tz" style="max-width:75px;" value=""> + </div> + </div> + </div> + </div> + </div> + </div> + <button class="btn btn-default" id="btn_add_leg">Add Leg</button> + + <div class="form-group" style="margin-top: 18px;"> + <label for="note_category">Tags (comma-separated)</label> + <input type="text" id="note_category" value="" class="form-control"> + </div> + + <div style="float: right; margin-top: 6px;"> + <button class="btn btn-success" id="btn_post">Post</button> + </div> + + </form> + +</div> + + + +<style type="text/css"> +.itinerary-leg { + margin-bottom: 10px; + padding: 8px 8px; + border-left: 4px #5bc0de solid; + background-color: #f4f8fa; +} +.itinerary-leg .row { + margin-bottom: 10px; +} +.itinerary-leg .remove { + float: right; + margin-right: 10px; + margin-top: 0; + font-size: 20px; + cursor: pointer; + color: #40A9C7; +} +.itinerary-leg .remove:hover { + color: #7ECDE4; +} +</style> + +<script src="/js/script.js"></script> +<script> +$(function(){ + + $("#btn_add_leg").click(function(){ + add_leg(); + return false; + }); + + function bind_leg_x() { + $(".itinerary-leg .remove").unbind("click").click(function(){ + // Don't allow the only leg to be removed. (2 because there is an invisible one as the template) + if($(".itinerary-leg").length > 2) { + $(this).parent().remove(); + } + }); + } + + function add_leg() { + $("#itinerary-legs-container").append($("#leg-template").html()); + + $(".itinerary-leg:last .template").val(0); + var d = new Date(); + $(".itinerary-leg:last .date").val(d.getFullYear()+"-"+zero_pad(d.getMonth()+1)+"-"+zero_pad(d.getDate())); + $(".itinerary-leg:last .time").val(zero_pad(d.getHours())+":"+zero_pad(d.getMinutes())+":00"); + $(".itinerary-leg:last .tz").val(tz_seconds_to_offset(d.getTimezoneOffset() * 60 * -1)); + + /* + $('.itinerary-leg:last .date').datepicker({ + 'format': 'yyyy-mm-dd', + 'autoclose': true, + 'todayHighlight': true + }); + + $('.itinerary-leg:last .time').timepicker({ + 'showDuration': true, + 'timeFormat': 'g:ia' + }); + + $('.itinerary-leg:last').datepair(); + */ + + bind_leg_x(); + } + + add_leg(); + + $("#btn_post").click(function(){ + + var itinerary = []; + + $(".itinerary-leg").each(function(){ + if($(this).find(".template").val() == 1) { return; } + + var departure = $(this).find(".leg-departure-date").val()+"T"+$(this).find(".leg-departure-time").val()+$(this).find(".leg-departure-tz").val(); + var arrival = $(this).find(".leg-arrival-date").val()+"T"+$(this).find(".leg-arrival-time").val()+$(this).find(".leg-arrival-tz").val(); + + itinerary.push({ + "type": "h-leg", + "properties": { + "transit-type": $(this).find(".leg-transit-type").val(), + "operator": $(this).find(".leg-operator").val(), + "number": $(this).find(".leg-number").val(), + "origin": $(this).find(".leg-origin").val(), + "destination": $(this).find(".leg-destination").val(), + "departure": departure, + "arrival": arrival + } + }); + }); + + var category = $("#note_category").val().split(/[, ]+/) + + $.post("/itinerary", { + data: JSON.stringify({ + "type": "h-entry", + "properties": { + "itinerary": itinerary, + "category": category + } + }) + }, function(data){ + var response = JSON.parse(data); + + if(response.location != false) { + $("#test_success").removeClass('hidden'); + $("#test_error").addClass('hidden'); + $("#post_href").attr("href", response.location); + } else { + $("#test_success").addClass('hidden'); + $("#test_error").removeClass('hidden'); + } + + }); + return false; + }); + +}); + +<?= partial('partials/syndication-js') ?> + +</script> |