[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [websites/paste-kde-org/dev-1.0] /: Add AJAX and JS bits and admin dashboard
From:       Sayak Banerjee <sayakb () kde ! org>
Date:       2013-09-01 7:16:51
Message-ID: E1VG1tz-0004SC-CQ () scm ! kde ! org
[Download RAW message or body]

Git commit cc5c21a9324e9a4d0dd11d10b462f0401aad1a85 by Sayak Banerjee.
Committed on 01/09/2013 at 07:16.
Pushed by sayakb into branch 'dev-1.0'.

Add AJAX and JS bits and admin dashboard

M  +12   -0    app/config/app.php
A  +16   -0    app/config/googlesvc.php
M  +1    -1    app/config/menus.php
M  +43   -1    app/controllers/AjaxController.php
M  +16   -3    app/controllers/CreateController.php
A  +18   -0    app/lang/en/ajax.php
A  +102  -0    app/lib/GoogleSvc.php
M  +4    -4    app/views/admin/dashboard.blade.php
A  +4    -0    app/views/ajax/version/ok.blade.php
A  +4    -0    app/views/ajax/version/old.blade.php
M  +1    -1    app/views/site/create.blade.php
M  +6    -2    app/views/site/show.blade.php
M  +1    -0    public/assets/css/stickynotes.css
M  +114  -16   public/assets/js/stickynotes.js
M  +1    -1    vendor/autoload.php
M  +2    -0    vendor/composer/autoload_classmap.php
M  +3    -3    vendor/composer/autoload_real.php

http://commits.kde.org/websites/paste-kde-org/cc5c21a9324e9a4d0dd11d10b462f0401aad1a85

diff --git a/app/config/app.php b/app/config/app.php
index 34dae91..5fd8eb1 100755
--- a/app/config/app.php
+++ b/app/config/app.php
@@ -11,10 +11,22 @@ return array(
 	| this value to have the update checker keep working as expected.
 	|
 	*/
+
 	'version' => '1.0.0',
 
 	/*
 	|--------------------------------------------------------------------------
+	| Sticky Notes update URL
+	|--------------------------------------------------------------------------
+	|
+	| The update checker will use this URL to get the latest version.
+	|
+	*/
+
+	'updateUrl' => 'http://sayakb.github.io/sticky-notes/version/',
+
+	/*
+	|--------------------------------------------------------------------------
 	| Application Debug Mode
 	|--------------------------------------------------------------------------
 	|
diff --git a/app/config/googlesvc.php b/app/config/googlesvc.php
new file mode 100644
index 0000000..01f53a0
--- /dev/null
+++ b/app/config/googlesvc.php
@@ -0,0 +1,16 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| Google services configuration
+	|--------------------------------------------------------------------------
+	|
+	| This file holds URLs to interact with google services
+	|
+	*/
+
+	'urlshortener'  => 'https://www.googleapis.com/urlshortener/v1/url?key=%s',
+
+);
diff --git a/app/config/menus.php b/app/config/menus.php
index 12b611c..b38586d 100755
--- a/app/config/menus.php
+++ b/app/config/menus.php
@@ -98,7 +98,7 @@ return array(
 
 		'admin/dashboard'   => array(
 			'label'         => 'admin.dashboard',
-			'icon'          => 'dashboard',
+			'icon'          => 'home',
 			'role'          => 'admin'
 		),
 
diff --git a/app/controllers/AjaxController.php b/app/controllers/AjaxController.php
index cafea03..4a0f3ad 100755
--- a/app/controllers/AjaxController.php
+++ b/app/controllers/AjaxController.php
@@ -28,11 +28,23 @@ class AjaxController extends BaseController {
 	/**
 	 * Fetches the latest available sticky notes version
 	 *
-	 * @return string
+	 * @return \Illuminate\View\View
 	 */
 	public function getVersion()
 	{
+		// Get app configuration
+		$app = Config::get('app');
+
+		// Parse the version number to unified numeral format
+		$localVersion = str_replace('.', '', $app['version']);
+
+		// Get the remote version number
+		$remoteVersion = @file_get_contents($app['updateUrl']);
+
+		// Compare the versions and return the appropriate response
+		$view = intval($remoteVersion) > intval($localVersion) ? 'old' : 'ok';
 
+		return View::make("ajax/version/{$view}");
 	}
 
 	/**
@@ -45,4 +57,34 @@ class AjaxController extends BaseController {
 		return Site::getSystemLoad();
 	}
 
+	/**
+	 * Generates a short URL for a paste
+	 *
+	 * @param  string  $urlkey
+	 * @param  string  $hash = ''
+	 * @return \Illuminate\View\View|string
+	 */
+	public function getShorten($urlkey, $hash = '')
+	{
+		// We need to validate the paste first
+		$paste = Paste::where('urlkey', $urlkey)->first();
+
+		// Paste was not found
+		if (is_null($paste))
+		{
+			return Lang::get('ajax.error');
+		}
+
+		// If it is a private paste, we need the hash
+		if ($paste->private AND $paste->hash != $hash)
+		{
+			return Lang::get('ajax.error');
+		}
+
+		// Shorten and return the paste URL
+		$longUrl = url("{$urlkey}/{$hash}");
+
+		return GoogleSvc::urlshortener($longUrl);
+	}
+
 }
diff --git a/app/controllers/CreateController.php b/app/controllers/CreateController.php
index d6d1526..4e143e3 100755
--- a/app/controllers/CreateController.php
+++ b/app/controllers/CreateController.php
@@ -34,13 +34,21 @@ class CreateController extends BaseController {
 	 */
 	public function getCreate()
 	{
+		// Build the view data
 		$data = array(
 			'languages'  => Highlighter::make()->languages(),
+			'language'   => 'text',
 			'paste'      => new Paste,
 			'action'     => 'CreateController@postCreate',
 			'disabled'   => '',
 		);
 
+		// Get the default language from cookie
+		if (Cookie::has('language'))
+		{
+			$data['language'] = Cookie::get('language');
+		}
+
 		return View::make('site/create', $data, Site::defaults());
 	}
 
@@ -68,6 +76,10 @@ class CreateController extends BaseController {
 		// Execute antispam services
 		$resultAntispam = $antispam->passes();
 
+		// Save the language as a cookie so that it is auto
+		// selected next time
+		$cookie = Cookie::forever('language', Input::get('language'));
+
 		if ($resultValidation AND $resultAntispam)
 		{
 			// We inject the project into the input so that
@@ -89,11 +101,11 @@ class CreateController extends BaseController {
 			}
 			else if ($paste->private)
 			{
-				return Redirect::to("{$paste->urlkey}/{$paste->hash}");
+				return Redirect::to("{$paste->urlkey}/{$paste->hash}")->withCookie($cookie);
 			}
 			else
 			{
-				return Redirect::to($paste->urlkey);
+				return Redirect::to($paste->urlkey)->withCookie($cookie);
 			}
 		}
 		else
@@ -109,7 +121,7 @@ class CreateController extends BaseController {
 			}
 		}
 
-		return Redirect::to(URL::previous())->withInput();
+		return Redirect::to(URL::previous())->withInput()->withCookie($cookie);
 	}
 
 	/**
@@ -146,6 +158,7 @@ class CreateController extends BaseController {
 		// Output the view
 		$data = array(
 			'languages'  => Highlighter::make()->languages(),
+			'language'   => 'text',
 			'paste'      => $paste,
 			'action'     => 'CreateController@postRevision',
 			'disabled'   => 'disabled',
diff --git a/app/lang/en/ajax.php b/app/lang/en/ajax.php
new file mode 100755
index 0000000..c1aaca1
--- /dev/null
+++ b/app/lang/en/ajax.php
@@ -0,0 +1,18 @@
+<?php
+
+return array(
+
+	/*
+	|--------------------------------------------------------------------------
+	| AJAX module language lines
+	|--------------------------------------------------------------------------
+	|
+	| This file defines languages lines for the AJAX requests
+	|
+	*/
+
+	"version_ok"     => "You have the latest version of Sticky Notes",
+	"version_old"    => "A newer version of Sticky Notes is available",
+	"error"          => "Error",
+
+);
diff --git a/app/lib/GoogleSvc.php b/app/lib/GoogleSvc.php
new file mode 100755
index 0000000..24da373
--- /dev/null
+++ b/app/lib/GoogleSvc.php
@@ -0,0 +1,102 @@
+<?php
+
+/**
+ * Sticky Notes
+ *
+ * An open source lightweight pastebin application
+ *
+ * @package     StickyNotes
+ * @author      Sayak Banerjee
+ * @copyright   (c) 2013 Sayak Banerjee <mail@sayakbanerjee.com>
+ * @license     http://www.opensource.org/licenses/bsd-license.php
+ * @link        http://sayakbanerjee.com/sticky-notes
+ * @since       Version 1.0
+ * @filesource
+ */
+
+/**
+ * GoogleSvc class
+ *
+ * Layer for accessing Google APIs
+ *
+ * @package     StickyNotes
+ * @subpackage  Libraries
+ * @author      Sayak Banerjee
+ */
+class GoogleSvc {
+
+	/**
+	 * goo.gl URL shortener service
+	 *
+	 * @static
+	 * @param  string  $longUrl
+	 * @return string
+	 */
+	public static function urlshortener($longUrl)
+	{
+		$apiUrl = static::getServiceUrl('urlshortener');
+
+		if ( ! is_null($apiUrl))
+		{
+			$ch = curl_init();
+
+			// Set the API url to connect to
+			curl_setopt($ch, CURLOPT_URL, $apiUrl);
+
+			// We will be making a POST request
+			curl_setopt($ch, CURLOPT_POST, TRUE);
+
+			// Set the URL that we want to shorten
+			curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(array("longUrl" => $longUrl)));
+
+			// Indicate that we want the response in JSON format
+			curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
+
+			// Indicate that we want a text response back
+			curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+
+			// This is just in case the SSL certificate is not valid
+			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
+
+			// Execute the POST request
+			$result = curl_exec($ch);
+
+			curl_close($ch);
+
+			// Parse and return the response
+			$response = json_decode($result, TRUE);
+
+			if (isset($response['id']))
+			{
+				return $response['id'];
+			}
+		}
+
+		return Lang::get('ajax.error');
+	}
+
+	/**
+	 * Returns the service URL for a specific service
+	 *
+	 * @static
+	 * @param  string  $service
+	 * @return string
+	 */
+	private static function getServiceUrl($service)
+	{
+		// Get the service URL
+		$urls = Config::get('googlesvc');
+
+		// Get the site configuration
+		$site = Site::config('general');
+
+		// Get the google API key
+		$apiKey = $site->googleApi;
+
+		if ( ! empty($apiKey))
+		{
+			return sprintf($urls[$service], $apiKey);
+		}
+	}
+
+}
diff --git a/app/views/admin/dashboard.blade.php b/app/views/admin/dashboard.blade.php
index e24de9d..a49399e 100755
--- a/app/views/admin/dashboard.blade.php
+++ b/app/views/admin/dashboard.blade.php
@@ -22,8 +22,8 @@
 							<b>{{ Lang::get('admin.stickynotes_version') }}:</b>
 							{{ $sn_version }}
 
-							<span class="ajax" data-realtime="false" data-onload="false" data-component="version">
-								<span class="glyphicon glyphicon-refresh text-muted"></span>
+							<span data-toggle="ajax" data-onload="true" data-component="version">
+								<span class="glyphicon glyphicon-refresh"></span>
 							</span>
 						</div>
 					</div>
@@ -67,8 +67,8 @@
 						<div class="well well-sm well-white">
 							<b>{{ Lang::get('admin.system_load') }}:</b>
 
-							<span class="ajax" data-realtime="true" data-onload="true" data-component="sysload">
-								<span class="glyphicon glyphicon-refresh text-muted"></span>
+							<span data-toggle="ajax" data-realtime="true" data-onload="true" data-component="sysload">
+								<span class="glyphicon glyphicon-refresh"></span>
 							</span>
 						</div>
 					</div>
diff --git a/app/views/ajax/version/ok.blade.php b/app/views/ajax/version/ok.blade.php
new file mode 100644
index 0000000..a394282
--- /dev/null
+++ b/app/views/ajax/version/ok.blade.php
@@ -0,0 +1,4 @@
+<span class="glyphicon glyphicon-ok-sign text-success"
+      title="{{ Lang::get('ajax.version_ok') }}"
+      data-toggle="tooltip">
+</span>
diff --git a/app/views/ajax/version/old.blade.php b/app/views/ajax/version/old.blade.php
new file mode 100644
index 0000000..b6f19ee
--- /dev/null
+++ b/app/views/ajax/version/old.blade.php
@@ -0,0 +1,4 @@
+<span class="glyphicon glyphicon-exclamation-sign text-danger"
+      title="{{ Lang::get('ajax.version_old') }}"
+      data-toggle="tooltip">
+</span>
diff --git a/app/views/site/create.blade.php b/app/views/site/create.blade.php
index 3d574f3..04b3f1a 100755
--- a/app/views/site/create.blade.php
+++ b/app/views/site/create.blade.php
@@ -31,7 +31,7 @@
 			<div class="col-sm-4">
 				<div class="form-group">
 					{{
-						Form::select('language', $languages, $paste->language ?: 'text', array(
+						Form::select('language', $languages, $paste->language ?: $language, array(
 							'class'    => 'form-control',
 							$disabled  => $disabled
 						))
diff --git a/app/views/site/show.blade.php b/app/views/site/show.blade.php
index 4b25221..9faca91 100755
--- a/app/views/site/show.blade.php
+++ b/app/views/site/show.blade.php
@@ -22,13 +22,17 @@
 						<div class="col-sm-7 text-right">
 							{{
 								link_to("#", Lang::get('show.short_url'), array(
-									'class' => 'btn btn-success'
+									'class'          => 'btn btn-success',
+									'data-toggle'    => 'ajax',
+									'data-component' => 'shorten',
+									'data-extra'     => $paste->urlkey.($paste->private ? '/'.$paste->hash : ''),
 								))
 							}}
 
 							{{
 								link_to("#", Lang::get('show.wrap'), array(
-									'class' => 'btn btn-success'
+									'class'        => 'btn btn-success',
+									'data-toggle'  => 'wrap',
 								))
 							}}
 
diff --git a/public/assets/css/stickynotes.css b/public/assets/css/stickynotes.css
index dee3df3..b7f8e10 100755
--- a/public/assets/css/stickynotes.css
+++ b/public/assets/css/stickynotes.css
@@ -24,6 +24,7 @@ pre {
   border-radius: 4px 4px 0 0;
   margin: 0 0 -1px 0;
   border-color: #e7e7e7;
+  overflow-x: auto;
 }
 pre ol {
   margin: 0;
diff --git a/public/assets/js/stickynotes.js b/public/assets/js/stickynotes.js
index 905bfa7..b20c6bb 100644
--- a/public/assets/js/stickynotes.js
+++ b/public/assets/js/stickynotes.js
@@ -21,6 +21,12 @@ function stickyNotes()
 {
 	// Initialize AJAX events
 	initAjax();
+
+	// Initialize code wrapping
+	initWrapToggle();
+
+	// Initialize the code editor
+	initEditor();
 }
 
 /**
@@ -38,44 +44,136 @@ function initAjax()
 {
 	var count = 1;
 
-	$('.ajax').each(function()
+	// Setup AJAX requests
+	$('[data-toggle="ajax"]').each(function()
 	{
-		var id = 'ajax-' + count++;
-
-		var realtime = $(this).attr('data-realtime') === 'true';
-
+		var id = 'stickynotes-' + count++;
 		var onload = $(this).attr('data-onload') === 'true';
-
+		var realtime = $(this).attr('data-realtime') === 'true';
 		var component = $(this).attr('data-component');
-
 		var extra = $(this).attr('data-extra');
 
 		// Set the id of this element
-		$(this).attr('id', id);
+		$(this).attr('data-id', id);
 
-		// ajaxUrl must be defined in your page template somewhere
-		if (ajaxUrl !== undefined)
+		// ajaxUrl and component must be defined
+		if (ajaxUrl !== undefined && component !== undefined)
 		{
 			var getUrl = ajaxUrl + '/' + component + (extra !== undefined ? '/' + extra : '');
 
-			var loop = setInterval(function()
+			var callback = function(e)
 			{
+				// Add the loading icon
+				$(this).html('<span class="glyphicon glyphicon-refresh"></span>');
+
+				// Send the AJAX request
 				$.ajax({
-					url: getUrl,
-					context: $('#' + id),
+					url: getUrl + '?key=' + Math.random(),
+					context: $('[data-id="' + id + '"]'),
 					success: function(response)
 					{
+						// Dump the HTML in the element
 						$(this).html(response);
+
+						// If response is link, set it as href as well
+						if (response.indexOf('http') === 0)
+						{
+							$(this).attr('href', response);
+						}
+
+						// Activate bootstrap components again
+						initBootstrap();
 					}
 				});
 
-				if ( ! realtime || true)
+				if (e !== undefined)
+				{
+					e.preventDefault();
+				}
+			};
+
+			// For onload requests, execute the callback right away
+			// For the rest, bind it to the click event of the element
+			if (onload)
+			{
+				if (realtime)
+				{
+					setInterval(callback, 1000);
+				}
+				else
 				{
-					clearInterval(loop);
+					setTimeout(callback);
 				}
-			}, 1000);
+			}
+			else
+			{
+				$(this).click(callback);
+			}
+		}
+	});
+}
+
+/**
+ * Activates the code wrapping toggle function
+ *
+ * @return void
+ */
+function initWrapToggle()
+{
+	$('[data-toggle="wrap"]').click(function(e)
+	{
+		var isWrapped = $('pre div').css('white-space') != 'nowrap';
+		var newValue = isWrapped ? 'nowrap' : 'inherit';
+
+		$('pre div').css('white-space', newValue);
+
+		e.preventDefault();
+	});
+}
+
+/**
+ * Activates the paste editor
+ *
+ * @return void
+ */
+function initEditor()
+{
+	// Insert tab in the code box
+	$('[name="data"]').keydown(function (e)
+	{
+		if (e.keyCode == 9)
+		{
+			var myValue = "\t";
+			var startPos = this.selectionStart;
+			var endPos = this.selectionEnd;
+			var scrollTop = this.scrollTop;
+
+			this.value = this.value.substring(0, startPos) + myValue + \
this.value.substring(endPos,this.value.length); +			this.focus();
+			this.selectionStart = startPos + myValue.length;
+			this.selectionEnd = startPos + myValue.length;
+			this.scrollTop = scrollTop;
+
+			e.preventDefault();
 		}
 	});
+
+	// Tick the private checkbox if password is entered
+	$('[name="password"]').keyup(function()
+	{
+		$('[name="private"]').attr('checked', $(this).val().length > 0);
+	});
+}
+
+/**
+ * Activates some bootstrap components
+ *
+ * @return void
+ */
+function initBootstrap()
+{
+	// Activate tooltips
+	$('[data-toggle="tooltip"]').tooltip();
 }
 
 /**
diff --git a/vendor/autoload.php b/vendor/autoload.php
index 421250e..ffeb911 100755
--- a/vendor/autoload.php
+++ b/vendor/autoload.php
@@ -4,4 +4,4 @@
 
 require_once __DIR__ . '/composer' . '/autoload_real.php';
 
-return ComposerAutoloaderInitb4b70d7e6d995d7d7e5bb75e0884baaf::getLoader();
+return ComposerAutoloaderInitf1da2c49ffbe98583eb87187211c5db2::getLoader();
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 9be6147..d04647f 100755
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -8,11 +8,13 @@ $baseDir = dirname($vendorDir);
 return array(
     'API' => $baseDir . '/app/lib/API.php',
     'AdminController' => $baseDir . '/app/controllers/AdminController.php',
+    'AjaxController' => $baseDir . '/app/controllers/AjaxController.php',
     'Antispam' => $baseDir . '/app/lib/Antispam.php',
     'ApiController' => $baseDir . '/app/controllers/ApiController.php',
     'BaseController' => $baseDir . '/app/controllers/BaseController.php',
     'CreateController' => $baseDir . '/app/controllers/CreateController.php',
     'DatabaseSeeder' => $baseDir . '/app/database/seeds/DatabaseSeeder.php',
+    'GoogleSvc' => $baseDir . '/app/lib/GoogleSvc.php',
     'Highlighter' => $baseDir . '/app/lib/Highlighter.php',
     'IPBan' => $baseDir . '/app/models/IPBan.php',
     'IlluminateQueueClosure' => $vendorDir . \
                '/laravel/framework/src/Illuminate/Queue/IlluminateQueueClosure.php',
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index 9800099..1d955e0 100755
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
 
 // autoload_real.php generated by Composer
 
-class ComposerAutoloaderInitb4b70d7e6d995d7d7e5bb75e0884baaf
+class ComposerAutoloaderInitf1da2c49ffbe98583eb87187211c5db2
 {
     private static $loader;
 
@@ -19,9 +19,9 @@ class ComposerAutoloaderInitb4b70d7e6d995d7d7e5bb75e0884baaf
             return self::$loader;
         }
 
-        spl_autoload_register(array('ComposerAutoloaderInitb4b70d7e6d995d7d7e5bb75e0884baaf', \
'loadClassLoader'), true, true); +        \
spl_autoload_register(array('ComposerAutoloaderInitf1da2c49ffbe98583eb87187211c5db2', 'loadClassLoader'), \
true, true);  self::$loader = $loader = new \Composer\Autoload\ClassLoader();
-        spl_autoload_unregister(array('ComposerAutoloaderInitb4b70d7e6d995d7d7e5bb75e0884baaf', \
'loadClassLoader')); +        \
spl_autoload_unregister(array('ComposerAutoloaderInitf1da2c49ffbe98583eb87187211c5db2', \
'loadClassLoader'));  
         $vendorDir = dirname(__DIR__);
         $baseDir = dirname($vendorDir);


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic