short 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/.gitignore +4 -0
  2. data/README.md +9 -0
  3. data/Rakefile +3 -0
  4. data/bin/shortener +115 -0
  5. data/config.ru +2 -0
  6. data/lib/shortener/client.rb +69 -0
  7. data/lib/shortener/configuration.rb +76 -0
  8. data/lib/shortener/server/Gemfile +6 -0
  9. data/lib/shortener/server/Gemfile.lock +23 -0
  10. data/lib/shortener/server/config.ru.template +2 -0
  11. data/lib/shortener/server/public/delete-icon.png +0 -0
  12. data/lib/shortener/server/public/flash/Jplayer.swf +0 -0
  13. data/lib/shortener/server/public/flash/clippy.swf +0 -0
  14. data/lib/shortener/server/public/flash/swfupload.swf +0 -0
  15. data/lib/shortener/server/public/images/XPButtonUploadText_61x22.png +0 -0
  16. data/lib/shortener/server/public/jquery-swfupload-min.js +1 -0
  17. data/lib/shortener/server/public/jquery-swfupload.js +64 -0
  18. data/lib/shortener/server/public/jquery.jplayer.min.js +97 -0
  19. data/lib/shortener/server/public/jquery.min.js +18 -0
  20. data/lib/shortener/server/public/patched.bootstrap.min.css +370 -0
  21. data/lib/shortener/server/public/site.js +36 -0
  22. data/lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.css +623 -0
  23. data/lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.jpg +0 -0
  24. data/lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.seeking.gif +0 -0
  25. data/lib/shortener/server/public/skin/blue.monday/jplayer.blue.monday.video.play.png +0 -0
  26. data/lib/shortener/server/public/swfupload.js +980 -0
  27. data/lib/shortener/server/views/add.haml +22 -0
  28. data/lib/shortener/server/views/display.haml +5 -0
  29. data/lib/shortener/server/views/index.haml +25 -0
  30. data/lib/shortener/server/views/layout.haml +21 -0
  31. data/lib/shortener/server/views/s3/audio.haml +75 -0
  32. data/lib/shortener/server/views/s3/image.haml +27 -0
  33. data/lib/shortener/server/views/s3/layout.haml +23 -0
  34. data/lib/shortener/server/views/s3/video.haml +71 -0
  35. data/lib/shortener/server/views/upload.haml +130 -0
  36. data/lib/shortener/server.rb +346 -0
  37. data/lib/shortener/version.rb +6 -0
  38. data/lib/shortener.rb +9 -0
  39. data/tasks/heroku.rake +46 -0
  40. data/test/test_client.rb +26 -0
  41. data/test/test_configuration.rb +23 -0
  42. data/test/test_server.rb +0 -0
  43. metadata +102 -0
@@ -0,0 +1,22 @@
1
+ #shortener.row(style="margin-top: 40px;")
2
+ %form{:id => 'add-form',:name => "shortener", :action => "/add", :method => "post", :class => 'offset3 form'}
3
+ %label{:for => "shortener[url]"} Url to Shorten:
4
+ %input{:type => "text", :name => "shortener[url]", :class => "text"}
5
+ %input{:type => "submit", :value => "Shorten", :class => "btn primary"}
6
+ %a{:onClick => '$(".advanced").fadeIn();'} Show Advanced Options
7
+ %br
8
+ %label{:for => 'shortener[expire]', :class => 'advanced'} Time till Expired:
9
+ %input{:type => 'text', :name => 'shortener[expire]', :class => 'text advanced'}
10
+ %br
11
+ %label{:for => 'shortener[max-clicks]', :class => 'advanced'} Max Clicks:
12
+ %input{:type => 'text', :name => 'shortener[max-clicks]', :class => 'text advanced'}
13
+ %br
14
+ %label{:for => 'shortener[desired-short]', :class => 'advanced'} Desired Short:
15
+ %input{:type => 'text', :name => 'shortener[desired-short]', :class => 'text advanced'}
16
+ %br
17
+ %label{:for => 'shortener[allow-override]', :class => 'advanced'} Allow Random Override:
18
+ %input{:type => 'checkbox', :name => 'shortener[allow-override]', :class => 'text advanced', :value => 'true'}
19
+ :javascript
20
+ $(function(){
21
+ $('.advanced').hide();
22
+ })
@@ -0,0 +1,5 @@
1
+ #link_display.row
2
+ %div.offset5.span4
3
+ %h4= @url
4
+ %div.span2
5
+ = clippy(@url)
@@ -0,0 +1,25 @@
1
+ #shorterner-index
2
+ %table
3
+ %thead
4
+ %tr
5
+ %th Shortened
6
+ %th Full Url
7
+ %th Set Count
8
+ %th Click Count
9
+ %th TTL
10
+ %th Max Clicks
11
+ %tbody
12
+ - @shortens.each do |short|
13
+ %tr
14
+ %td= short['shortened']
15
+ %td
16
+ %a{href: short['url']}= short['url'][0..50] + ((short['url'].length > 50) ? '...' : '')
17
+ %td= short['set-count']
18
+ %td= short['click-count'] || 0
19
+ %td= ttl_display(short['expire'])
20
+ %td= short['max-clicks'] || "∞"
21
+ %td
22
+ %a{href: "/delete/#{short['shortened']}", class: 'delete-button'}
23
+ %img{src: 'delete-icon.png', alt: 'delete!', width: '16px', height: '16px'}
24
+ %td= clippy("#{base_url}/#{short['shortened']}")
25
+
@@ -0,0 +1,21 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title Shortener
5
+ %link{rel: 'stylesheet', type: 'text/css', href: '/patched.bootstrap.min.css'}
6
+ %script{src: '/jquery.min.js', type: 'text/javascript'}
7
+ %script{src: 'site.js', type: 'text/javascript'}
8
+ %body{:'padding-top' => '60px'}
9
+
10
+ %div.topbar
11
+ %div.topbar-inner
12
+ %div.container
13
+ %a{class: 'brand', href: "/"} Shortener
14
+ %ul.nav
15
+ %li
16
+ %a{href: '/index'} Index
17
+ %li
18
+ %a{href: '/add'} Add
19
+
20
+ #main.container(style="margin-top: 40px;")
21
+ = yield
@@ -0,0 +1,75 @@
1
+ %link{href: "skin/blue.monday/jplayer.blue.monday.css", rel: 'stylesheet', type: 'text/css'}
2
+ %script{src: 'jquery.jplayer.min.js', type: 'text/javascript'}
3
+
4
+ %br
5
+ %br
6
+ .row
7
+ #jquery_jplayer_1.jp-jplayer.center
8
+ #jp_container_1.jp-audio.center
9
+ .jp-type-single
10
+ .jp-gui.jp-interface
11
+ %ul.jp-controls
12
+ %li
13
+ %a.jp-play{:href => "javascript:;", :tabindex => "1"} play
14
+ %li
15
+ %a.jp-pause{:href => "javascript:;", :tabindex => "1"} pause
16
+ %li
17
+ %a.jp-stop{:href => "javascript:;", :tabindex => "1"} stop
18
+ %li
19
+ %a.jp-mute{:href => "javascript:;", :tabindex => "1", :title => "mute"} mute
20
+ %li
21
+ %a.jp-unmute{:href => "javascript:;", :tabindex => "1", :title => "unmute"} unmute
22
+ %li
23
+ %a.jp-volume-max{:href => "javascript:;", :tabindex => "1", :title => "max volume"} max volume
24
+ .jp-progress
25
+ .jp-seek-bar
26
+ .jp-play-bar
27
+ .jp-volume-bar
28
+ .jp-volume-bar-value
29
+ .jp-time-holder
30
+ .jp-current-time
31
+ .jp-duration
32
+ %ul.jp-toggles
33
+ %li
34
+ %a.jp-repeat{:href => "javascript:;", :tabindex => "1", :title => "repeat"} repeat
35
+ %li
36
+ %a.jp-repeat-off{:href => "javascript:;", :tabindex => "1", :title => "repeat off"} repeat off
37
+ .jp-title
38
+ %ul
39
+ %li= @short['name']
40
+ %li= @short['description']
41
+ .jp-no-solution
42
+ %span Update Required
43
+ To play the media you will need to either update your browser to a recent version or update your
44
+ = succeed "." do
45
+ %a{:href => "http://get.adobe.com/flashplayer/", :target => "_blank"} Flash plugin
46
+
47
+ :javascript
48
+
49
+ $("#jquery_jplayer_1").jPlayer({
50
+ ready: function () {
51
+ $(this).jPlayer("setMedia", {
52
+ #{@short['extension']}: "#{@short['url']}",
53
+ });
54
+ },
55
+ play: function() { // To avoid both jPlayers playing together.
56
+ $(this).jPlayer("pauseOthers");
57
+ },
58
+ repeat: function(event) { // Override the default jPlayer repeat event handler
59
+ if(event.jPlayer.options.loop) {
60
+ $(this).unbind(".jPlayerRepeat").unbind(".jPlayerNext");
61
+ $(this).bind($.jPlayer.event.ended + ".jPlayer.jPlayerRepeat", function() {
62
+ $(this).jPlayer("play");
63
+ });
64
+ } else {
65
+ $(this).unbind(".jPlayerRepeat").unbind(".jPlayerNext");
66
+ $(this).bind($.jPlayer.event.ended + ".jPlayer.jPlayerNext", function() {
67
+ $("#jquery_jplayer_2").jPlayer("play", 0);
68
+ });
69
+ }
70
+ },
71
+ swfPath: "js",
72
+ supplied: "#{@short['extension']}",
73
+ wmode: "window"
74
+ });
75
+
@@ -0,0 +1,27 @@
1
+ %br
2
+ %br
3
+ :css
4
+ img {
5
+ max-width: 100%;
6
+ }
7
+
8
+ .row
9
+ %a.center{href: @short['url']}
10
+ %img{src: @short['url']}
11
+
12
+ .row
13
+ %p
14
+ %b Name:
15
+ = @short['name']
16
+
17
+ .row
18
+ %p
19
+ %b Descrtiption:
20
+ %br
21
+ = @short['description']
22
+
23
+ :css
24
+ .center {
25
+ margin: 0 auto;
26
+ padding: 0;
27
+ }
@@ -0,0 +1,23 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title Shortener
5
+ %link{rel: 'stylesheet', type: 'text/css', href: '/patched.bootstrap.min.css'}
6
+ %script{src: 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js', type: 'text/javascript'}
7
+ %script{src: 'site.js', type: 'text/javascript'}
8
+ %body{:'padding-top' => '60px'}
9
+
10
+ #main.container(style="margin-top: 40px;")
11
+ = yield
12
+ .row
13
+ %a.center{href: "#{@short['url']}"} Download
14
+ :css
15
+ body {
16
+ background-color: #787171;
17
+ }
18
+
19
+ .center {
20
+ margin: 0 auto;
21
+ padding: 0;
22
+ }
23
+
@@ -0,0 +1,71 @@
1
+ %link{href: "skin/blue.monday/jplayer.blue.monday.css", rel: 'stylesheet', type: 'text/css'}
2
+ %script{src: 'jquery.jplayer.min.js', type: 'text/javascript'}
3
+
4
+ #jp_container_1.jp-video.jp-video-360p.center
5
+ .jp-type-single
6
+ #jquery_jplayer_1.jp-jplayer
7
+ .jp-gui
8
+ .jp-video-play
9
+ %a.jp-video-play-icon{:href => "javascript:;", :tabindex => "1"} play
10
+ .jp-interface
11
+ .jp-progress
12
+ .jp-seek-bar
13
+ .jp-play-bar
14
+ .jp-current-time
15
+ .jp-duration
16
+ .jp-controls-holder
17
+ %ul.jp-controls
18
+ %li
19
+ %a.jp-play{:href => "javascript:;", :tabindex => "1"} play
20
+ %li
21
+ %a.jp-pause{:href => "javascript:;", :tabindex => "1"} pause
22
+ %li
23
+ %a.jp-stop{:href => "javascript:;", :tabindex => "1"} stop
24
+ %li
25
+ %a.jp-mute{:href => "javascript:;", :tabindex => "1", :title => "mute"} mute
26
+ %li
27
+ %a.jp-unmute{:href => "javascript:;", :tabindex => "1", :title => "unmute"} unmute
28
+ %li
29
+ %a.jp-volume-max{:href => "javascript:;", :tabindex => "1", :title => "max volume"} max volume
30
+ .jp-volume-bar
31
+ .jp-volume-bar-value
32
+ %ul.jp-toggles
33
+ %li
34
+ %a.jp-full-screen{:href => "javascript:;", :tabindex => "1", :title => "full screen"} full screen
35
+ %li
36
+ %a.jp-restore-screen{:href => "javascript:;", :tabindex => "1", :title => "restore screen"} restore screen
37
+ %li
38
+ %a.jp-repeat{:href => "javascript:;", :tabindex => "1", :title => "repeat"} repeat
39
+ %li
40
+ %a.jp-repeat-off{:href => "javascript:;", :tabindex => "1", :title => "repeat off"} repeat off
41
+ .jp-title
42
+ %ul
43
+ %li= @short['name']
44
+ %li= @short['description']
45
+ .jp-no-solution
46
+ %span Update Required
47
+ To play the media you will need to either update your browser to a recent version or update your
48
+ = succeed "." do
49
+ %a{:href => "http://get.adobe.com/flashplayer/", :target => "_blank"} Flash plugin
50
+
51
+
52
+ :javascript
53
+
54
+ $("#jquery_jplayer_1").jPlayer({
55
+ ready: function () {
56
+ $(this).jPlayer("setMedia", { #{@short['extension']}: "#{@short['url']}" });
57
+ },
58
+ swfPath: "js",
59
+ supplied: "#{@short['extension']}",
60
+ size: {
61
+ width: "640px",
62
+ height: "360px",
63
+ cssClass: "jp-video-360p"
64
+ }
65
+ });
66
+
67
+ :css
68
+ .center {
69
+ margin: 0 auto;
70
+ padding: 0;
71
+ }
@@ -0,0 +1,130 @@
1
+ %script{src: "swfupload.js"}
2
+ %script{src: "jquery-swfupload-min.js"}
3
+ :erb
4
+ <script>
5
+ $(function(){
6
+ $('#swfupload-control').swfupload({
7
+ // Backend Settings
8
+ upload_url: "<%= @upload_url %>", // Relative to the SWF file (or you can use absolute paths)
9
+ http_success : [ 200, 201, 204 ], // FOR AWS
10
+
11
+ // File Upload Settings
12
+ file_size_limit : "102400", // 100MB
13
+ file_types : "*.*",
14
+ file_types_description : "All Files",
15
+ file_upload_limit : "10",
16
+ file_queue_limit : "0",
17
+ file_post_name : "file", // FOR AWS
18
+
19
+ // Button settings
20
+ button_image_url : "/images/XPButtonUploadText_61x22.png",
21
+ button_placeholder_id : "span-button-placeholder",
22
+ button_width: 61,
23
+ button_height: 22,
24
+
25
+ // Flash Settings
26
+ flash_url : "/flash/swfupload.swf",
27
+ //debug: true,
28
+ post_params: <%= @post.to_json %> // FOR AWS
29
+
30
+ })
31
+ .bind('fileQueued', function(event, file){
32
+ // start the upload since it's queued
33
+ //$(this).swfupload('startUpload');
34
+ $(this).swfupload('setButtonDisabled', true);
35
+ $('#file-name-placeholder').text(file.name);
36
+ })
37
+ .bind('fileQueueError', function(event, file, errorCode, message){
38
+ //$('#log').append('<li>File queue error - '+message+'</li>');
39
+ //$(this).show();
40
+ })
41
+ .bind('uploadStart', function(event, file){
42
+ $('#progressbar').show();
43
+ })
44
+ .bind('uploadProgress', function(event, file, bytesLoaded){
45
+ var avg = bytesLoaded / file.size * 100;
46
+ //$('#log').append('<li>Upload progress - '+bytesLoaded+ ' ' + avg + '</li>');
47
+ $('#progressbar .bar').css('width', avg + '%' );
48
+ })
49
+ .bind('uploadSuccess', function(event, file, serverData){
50
+ //$('#log').append('<li>Upload success - '+file.name+'</li>');
51
+ })
52
+ .bind('uploadComplete', function(event, file){
53
+ //$('#log').append('<li>Upload complete - '+file.name+'</li>');
54
+ $('#progressbar .active').removeClass('active');
55
+
56
+ var values = $('#upload-form').serialize();
57
+ values += '&shortener%5bfile_name%5d=' + file.name;
58
+ // Change this callback function to suite your needs
59
+ // $.ajax({
60
+ // type: "POST",
61
+ // url: '/upload',
62
+ // data: "name=" + file.name,
63
+ // async: false,
64
+ // });
65
+ $.post('/upload', values, function(data){
66
+ $('#shortener-display').text(data.url)
67
+ .removeClass('hide');
68
+ });
69
+
70
+ // upload has completed, lets try the next one in the queue
71
+ $(this).swfupload('startUpload');
72
+ })
73
+ .bind('uploadError', function(event, file, errorCode, message){
74
+ //$('#log').append('<li>Upload error - '+message+'</li>');
75
+ });
76
+
77
+ });
78
+ </script>
79
+
80
+ .row
81
+ #progressbar.span8{style: 'display:none;'}
82
+ .progress.danger.active.striped
83
+ .bar{style: "width: 0%"}
84
+
85
+ .row
86
+ %div.offset1{:id=> "swfupload-control"}
87
+ %ol{:id=> "log"}
88
+ %span{:id=> "span-button-placeholder"}
89
+ %span{id: 'file-name-placeholder'}
90
+ %br
91
+
92
+ .row
93
+ %form.form{id: 'upload-form', action: '/upload', method: 'post'}
94
+ .row
95
+ %ul.offset2
96
+ %li.radio
97
+ %input{name: 'shortener[type]', type: 'radio', value: 'video'} Video
98
+ %li.radio
99
+ %input{name: 'shortener[type]', type: 'radio', value: 'audio'} Audio
100
+ %li.radio
101
+ %input{name: 'shortener[type]', type: 'radio', value: 'image'} Image
102
+ %li.radio
103
+ %input{name: 'shortener[type]', type: 'radio', value: 'download'} Download
104
+ .row
105
+ %label.offset8.hide{id: 'shortener-display'}
106
+ .field
107
+ %label{for: 'shorterner[name]'} Name
108
+ %input{type: 'text', name: 'shortener[name]'}
109
+ .field
110
+ %label{for: 'shorterner[description]'} Description
111
+ %input{type: 'text', name: 'shortener[description]'}
112
+ .row
113
+ .actions
114
+ %input.btn.primary{type: 'submit', value: 'Shorten'}
115
+
116
+ .row
117
+
118
+ :css
119
+ .radio {
120
+ display: inline;
121
+ margin-right: 20px;
122
+ }
123
+
124
+ :javascript
125
+ $('#upload-form').submit(function(e){
126
+ e.preventDefault();
127
+ $('#swfupload-control').swfupload('startUpload');
128
+ });
129
+
130
+