beet 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +1 -1
- data/VERSION +1 -1
- data/beet.gemspec +8 -2
- data/lib/beet/files/swfupload/images/cancelbutton.gif +0 -0
- data/lib/beet/files/swfupload/images/header-bg.jpg +0 -0
- data/lib/beet/files/swfupload/images/logo.gif +0 -0
- data/lib/beet/files/swfupload/js/handlers.js +290 -0
- data/lib/beet/recipes/rails/auth/devise.rb +3 -4
- data/lib/beet/recipes/rails/db/mongo.rb +57 -0
- data/lib/beet/recipes/rails/swfupload.rb +305 -0
- metadata +8 -2
data/README.rdoc
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.3
|
data/beet.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{beet}
|
8
|
-
s.version = "0.4.
|
8
|
+
s.version = "0.4.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jack Dempsey"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-01-09}
|
13
13
|
s.default_executable = %q{beet}
|
14
14
|
s.email = %q{jack.dempsey@gmail.com}
|
15
15
|
s.executables = ["beet"]
|
@@ -37,6 +37,10 @@ Gem::Specification.new do |s|
|
|
37
37
|
"lib/beet/execution.rb",
|
38
38
|
"lib/beet/executor.rb",
|
39
39
|
"lib/beet/file_system.rb",
|
40
|
+
"lib/beet/files/swfupload/images/cancelbutton.gif",
|
41
|
+
"lib/beet/files/swfupload/images/header-bg.jpg",
|
42
|
+
"lib/beet/files/swfupload/images/logo.gif",
|
43
|
+
"lib/beet/files/swfupload/js/handlers.js",
|
40
44
|
"lib/beet/gem_location_map.rb",
|
41
45
|
"lib/beet/interaction.rb",
|
42
46
|
"lib/beet/logger.rb",
|
@@ -52,10 +56,12 @@ Gem::Specification.new do |s|
|
|
52
56
|
"lib/beet/recipes/rails/css/blueprint.rb",
|
53
57
|
"lib/beet/recipes/rails/css/nifty_layout.rb",
|
54
58
|
"lib/beet/recipes/rails/css/reset.rb",
|
59
|
+
"lib/beet/recipes/rails/db/mongo.rb",
|
55
60
|
"lib/beet/recipes/rails/db/mysql.rb",
|
56
61
|
"lib/beet/recipes/rails/db/postgres.rb",
|
57
62
|
"lib/beet/recipes/rails/git.rb",
|
58
63
|
"lib/beet/recipes/rails/jquery.rb",
|
64
|
+
"lib/beet/recipes/rails/swfupload.rb",
|
59
65
|
"lib/beet/recipes/rails/testing/rspec.rb",
|
60
66
|
"lib/beet/recipes/rails/testing/shoulda.rb",
|
61
67
|
"lib/beet/scm.rb",
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,290 @@
|
|
1
|
+
function fileQueueError(file, errorCode, message) {
|
2
|
+
try {
|
3
|
+
var imageName = "error.gif";
|
4
|
+
var errorName = "";
|
5
|
+
if (errorCode === SWFUpload.errorCode_QUEUE_LIMIT_EXCEEDED) {
|
6
|
+
errorName = "You have attempted to queue too many files.";
|
7
|
+
}
|
8
|
+
|
9
|
+
if (errorName !== "") {
|
10
|
+
alert(errorName);
|
11
|
+
return;
|
12
|
+
}
|
13
|
+
|
14
|
+
switch (errorCode) {
|
15
|
+
case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
|
16
|
+
imageName = "zerobyte.gif";
|
17
|
+
break;
|
18
|
+
case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
|
19
|
+
imageName = "toobig.gif";
|
20
|
+
break;
|
21
|
+
case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
|
22
|
+
case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
|
23
|
+
default:
|
24
|
+
alert(message);
|
25
|
+
break;
|
26
|
+
}
|
27
|
+
|
28
|
+
addImage("images/swfupload/" + imageName);
|
29
|
+
|
30
|
+
} catch (ex) {
|
31
|
+
this.debug(ex);
|
32
|
+
}
|
33
|
+
|
34
|
+
}
|
35
|
+
|
36
|
+
function fileDialogComplete(numFilesSelected, numFilesQueued) {
|
37
|
+
try {
|
38
|
+
if (numFilesQueued > 0) {
|
39
|
+
this.startUpload();
|
40
|
+
}
|
41
|
+
} catch (ex) {
|
42
|
+
this.debug(ex);
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
function uploadProgress(file, bytesLoaded) {
|
47
|
+
|
48
|
+
try {
|
49
|
+
var percent = Math.ceil((bytesLoaded / file.size) * 100);
|
50
|
+
|
51
|
+
var progress = new FileProgress(file, this.customSettings.upload_target);
|
52
|
+
progress.setProgress(percent);
|
53
|
+
if (percent === 100) {
|
54
|
+
progress.setStatus("Processing file...");
|
55
|
+
progress.toggleCancel(false, this);
|
56
|
+
} else {
|
57
|
+
progress.setStatus("Uploading...");
|
58
|
+
progress.toggleCancel(true, this);
|
59
|
+
}
|
60
|
+
} catch (ex) {
|
61
|
+
this.debug(ex);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
function uploadSuccess(file, serverData) {
|
66
|
+
try {
|
67
|
+
$('#mp3info').append("<p>"+serverData+"</p>");
|
68
|
+
var progress = new FileProgress(file, this.customSettings.upload_target);
|
69
|
+
|
70
|
+
if (serverData.substring(0, 2) === "OK") {
|
71
|
+
//addImage("thumbnail.php?id=" + serverData.substring(7));
|
72
|
+
|
73
|
+
progress.setStatus("Upload Successfull.");
|
74
|
+
progress.toggleCancel(false);
|
75
|
+
} else {
|
76
|
+
addImage("/images/swfupload/error.gif");
|
77
|
+
progress.setStatus("Error.");
|
78
|
+
progress.toggleCancel(false);
|
79
|
+
alert(serverData);
|
80
|
+
|
81
|
+
}
|
82
|
+
|
83
|
+
|
84
|
+
} catch (ex) {
|
85
|
+
this.debug(ex);
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
function uploadComplete(file) {
|
90
|
+
try {
|
91
|
+
/* I want the next upload to continue automatically so I'll call startUpload here */
|
92
|
+
if (this.getStats().files_queued > 0) {
|
93
|
+
this.startUpload();
|
94
|
+
} else {
|
95
|
+
var progress = new FileProgress(file, this.customSettings.upload_target);
|
96
|
+
progress.setComplete();
|
97
|
+
progress.setStatus("All files received.");
|
98
|
+
progress.toggleCancel(false);
|
99
|
+
}
|
100
|
+
} catch (ex) {
|
101
|
+
this.debug(ex);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
function uploadError(file, errorCode, message) {
|
106
|
+
var imageName = "error.gif";
|
107
|
+
var progress;
|
108
|
+
try {
|
109
|
+
switch (errorCode) {
|
110
|
+
case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
|
111
|
+
try {
|
112
|
+
progress = new FileProgress(file, this.customSettings.upload_target);
|
113
|
+
progress.setCancelled();
|
114
|
+
progress.setStatus("Cancelled");
|
115
|
+
progress.toggleCancel(false);
|
116
|
+
}
|
117
|
+
catch (ex1) {
|
118
|
+
this.debug(ex1);
|
119
|
+
}
|
120
|
+
break;
|
121
|
+
case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
|
122
|
+
try {
|
123
|
+
progress = new FileProgress(file, this.customSettings.upload_target);
|
124
|
+
progress.setCancelled();
|
125
|
+
progress.setStatus("Stopped");
|
126
|
+
progress.toggleCancel(true);
|
127
|
+
}
|
128
|
+
catch (ex2) {
|
129
|
+
this.debug(ex2);
|
130
|
+
}
|
131
|
+
case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
|
132
|
+
imageName = "uploadlimit.gif";
|
133
|
+
break;
|
134
|
+
default:
|
135
|
+
alert(message);
|
136
|
+
break;
|
137
|
+
}
|
138
|
+
|
139
|
+
addImage("/images/swfupload/" + imageName);
|
140
|
+
|
141
|
+
} catch (ex3) {
|
142
|
+
this.debug(ex3);
|
143
|
+
}
|
144
|
+
|
145
|
+
}
|
146
|
+
|
147
|
+
|
148
|
+
function addImage(src) {
|
149
|
+
var newImg = document.createElement("img");
|
150
|
+
newImg.style.margin = "5px";
|
151
|
+
|
152
|
+
document.getElementById("thumbnails").appendChild(newImg);
|
153
|
+
if (newImg.filters) {
|
154
|
+
try {
|
155
|
+
newImg.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 0;
|
156
|
+
} catch (e) {
|
157
|
+
// If it is not set initially, the browser will throw an error. This will set it if it is not set yet.
|
158
|
+
newImg.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + 0 + ')';
|
159
|
+
}
|
160
|
+
} else {
|
161
|
+
newImg.style.opacity = 0;
|
162
|
+
}
|
163
|
+
|
164
|
+
newImg.onload = function () {
|
165
|
+
fadeIn(newImg, 0);
|
166
|
+
};
|
167
|
+
newImg.src = src;
|
168
|
+
}
|
169
|
+
|
170
|
+
function fadeIn(element, opacity) {
|
171
|
+
var reduceOpacityBy = 5;
|
172
|
+
var rate = 30; // 15 fps
|
173
|
+
|
174
|
+
|
175
|
+
if (opacity < 100) {
|
176
|
+
opacity += reduceOpacityBy;
|
177
|
+
if (opacity > 100) {
|
178
|
+
opacity = 100;
|
179
|
+
}
|
180
|
+
|
181
|
+
if (element.filters) {
|
182
|
+
try {
|
183
|
+
element.filters.item("DXImageTransform.Microsoft.Alpha").opacity = opacity;
|
184
|
+
} catch (e) {
|
185
|
+
// If it is not set initially, the browser will throw an error. This will set it if it is not set yet.
|
186
|
+
element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + opacity + ')';
|
187
|
+
}
|
188
|
+
} else {
|
189
|
+
element.style.opacity = opacity / 100;
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
if (opacity < 100) {
|
194
|
+
setTimeout(function () {
|
195
|
+
fadeIn(element, opacity);
|
196
|
+
}, rate);
|
197
|
+
}
|
198
|
+
}
|
199
|
+
|
200
|
+
|
201
|
+
|
202
|
+
/* ******************************************
|
203
|
+
* FileProgress Object
|
204
|
+
* Control object for displaying file info
|
205
|
+
* ****************************************** */
|
206
|
+
|
207
|
+
function FileProgress(file, targetID) {
|
208
|
+
this.fileProgressID = "divFileProgress";
|
209
|
+
|
210
|
+
this.fileProgressWrapper = document.getElementById(this.fileProgressID);
|
211
|
+
if (!this.fileProgressWrapper) {
|
212
|
+
this.fileProgressWrapper = document.createElement("div");
|
213
|
+
this.fileProgressWrapper.className = "progressWrapper";
|
214
|
+
this.fileProgressWrapper.id = this.fileProgressID;
|
215
|
+
|
216
|
+
this.fileProgressElement = document.createElement("div");
|
217
|
+
this.fileProgressElement.className = "progressContainer";
|
218
|
+
|
219
|
+
var progressCancel = document.createElement("a");
|
220
|
+
progressCancel.className = "progressCancel";
|
221
|
+
progressCancel.href = "#";
|
222
|
+
progressCancel.style.visibility = "hidden";
|
223
|
+
progressCancel.appendChild(document.createTextNode(" "));
|
224
|
+
|
225
|
+
var progressText = document.createElement("div");
|
226
|
+
progressText.className = "progressName";
|
227
|
+
progressText.appendChild(document.createTextNode(file.name));
|
228
|
+
|
229
|
+
var progressBar = document.createElement("div");
|
230
|
+
progressBar.className = "progressBarInProgress";
|
231
|
+
|
232
|
+
var progressStatus = document.createElement("div");
|
233
|
+
progressStatus.className = "progressBarStatus";
|
234
|
+
progressStatus.innerHTML = " ";
|
235
|
+
|
236
|
+
this.fileProgressElement.appendChild(progressCancel);
|
237
|
+
this.fileProgressElement.appendChild(progressText);
|
238
|
+
this.fileProgressElement.appendChild(progressStatus);
|
239
|
+
this.fileProgressElement.appendChild(progressBar);
|
240
|
+
|
241
|
+
this.fileProgressWrapper.appendChild(this.fileProgressElement);
|
242
|
+
|
243
|
+
document.getElementById(targetID).appendChild(this.fileProgressWrapper);
|
244
|
+
fadeIn(this.fileProgressWrapper, 0);
|
245
|
+
|
246
|
+
} else {
|
247
|
+
this.fileProgressElement = this.fileProgressWrapper.firstChild;
|
248
|
+
this.fileProgressElement.childNodes[1].firstChild.nodeValue = file.name;
|
249
|
+
}
|
250
|
+
|
251
|
+
this.height = this.fileProgressWrapper.offsetHeight;
|
252
|
+
|
253
|
+
}
|
254
|
+
FileProgress.prototype.setProgress = function (percentage) {
|
255
|
+
this.fileProgressElement.className = "progressContainer green";
|
256
|
+
this.fileProgressElement.childNodes[3].className = "progressBarInProgress";
|
257
|
+
this.fileProgressElement.childNodes[3].style.width = percentage + "%";
|
258
|
+
};
|
259
|
+
FileProgress.prototype.setComplete = function () {
|
260
|
+
this.fileProgressElement.className = "progressContainer blue";
|
261
|
+
this.fileProgressElement.childNodes[3].className = "progressBarComplete";
|
262
|
+
this.fileProgressElement.childNodes[3].style.width = "";
|
263
|
+
|
264
|
+
};
|
265
|
+
FileProgress.prototype.setError = function () {
|
266
|
+
this.fileProgressElement.className = "progressContainer red";
|
267
|
+
this.fileProgressElement.childNodes[3].className = "progressBarError";
|
268
|
+
this.fileProgressElement.childNodes[3].style.width = "";
|
269
|
+
|
270
|
+
};
|
271
|
+
FileProgress.prototype.setCancelled = function () {
|
272
|
+
this.fileProgressElement.className = "progressContainer";
|
273
|
+
this.fileProgressElement.childNodes[3].className = "progressBarError";
|
274
|
+
this.fileProgressElement.childNodes[3].style.width = "";
|
275
|
+
|
276
|
+
};
|
277
|
+
FileProgress.prototype.setStatus = function (status) {
|
278
|
+
this.fileProgressElement.childNodes[2].innerHTML = status;
|
279
|
+
};
|
280
|
+
|
281
|
+
FileProgress.prototype.toggleCancel = function (show, swfuploadInstance) {
|
282
|
+
this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden";
|
283
|
+
if (swfuploadInstance) {
|
284
|
+
var fileID = this.fileProgressID;
|
285
|
+
this.fileProgressElement.childNodes[0].onclick = function () {
|
286
|
+
swfuploadInstance.cancelUpload(fileID);
|
287
|
+
return false;
|
288
|
+
};
|
289
|
+
}
|
290
|
+
};
|
@@ -1,5 +1,5 @@
|
|
1
|
-
gem 'warden', :version => '~> 0.5
|
2
|
-
gem 'devise', :version => '~> 0.
|
1
|
+
gem 'warden', :version => '~> 0.6.5'
|
2
|
+
gem 'devise', :version => '~> 0.7.1'
|
3
3
|
|
4
4
|
rake 'gems:install'
|
5
5
|
generate "devise_install"
|
@@ -13,8 +13,7 @@ add_after 'config/routes.rb', '# map.root :controller => "welcome"', "\n map.ro
|
|
13
13
|
rake "db:migrate"
|
14
14
|
|
15
15
|
file 'app/controllers/home_controller.rb' do
|
16
|
-
%{
|
17
|
-
class HomeController < ApplicationController
|
16
|
+
%{class HomeController < ApplicationController
|
18
17
|
def index
|
19
18
|
render :text => "Welcome!"
|
20
19
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# based on jnunemaker's gist at http://gist.github.com/232953
|
2
|
+
file 'config/database.yml' do
|
3
|
+
%{
|
4
|
+
development: &global_settings
|
5
|
+
database: #{project_name}_development
|
6
|
+
host: 127.0.0.1
|
7
|
+
port: 27017
|
8
|
+
|
9
|
+
test:
|
10
|
+
database: #{project_name}_test
|
11
|
+
<<: *global_settings
|
12
|
+
|
13
|
+
production:
|
14
|
+
host: hostname
|
15
|
+
database: databasename
|
16
|
+
username: username
|
17
|
+
password: password
|
18
|
+
<<: *global_settings
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
file 'config/initializers/mongo.rb' do
|
23
|
+
%{
|
24
|
+
config = YAML.load_file(Rails.root + 'config' + 'database.yml')[Rails.env]
|
25
|
+
|
26
|
+
MongoMapper.connection = Mongo::Connection.new(config['host'], config['port'], {
|
27
|
+
:logger => Rails.logger
|
28
|
+
})
|
29
|
+
|
30
|
+
MongoMapper.database = config['database']
|
31
|
+
if config['username'].present?
|
32
|
+
MongoMapper.database.authenticate(config['username'], config['password'])
|
33
|
+
end
|
34
|
+
|
35
|
+
Dir[Rails.root + 'app/models/**/*.rb'].each do |model_path|
|
36
|
+
File.basename(model_path, '.rb').classify.constantize
|
37
|
+
end
|
38
|
+
MongoMapper.ensure_indexes!
|
39
|
+
|
40
|
+
if defined?(PhusionPassenger)
|
41
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
42
|
+
# if using older than 0.6.5 of MM then you want database instead of connection
|
43
|
+
# MongoMapper.database.connect_to_master if forked
|
44
|
+
MongoMapper.connection.connect_to_master if forked
|
45
|
+
end
|
46
|
+
end
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
# for those who don't like keeping database.yml in version control
|
51
|
+
# we slot in an example file to serve as reference
|
52
|
+
|
53
|
+
FileUtils.copy "config/database.yml", "config/database.yml.example"
|
54
|
+
|
55
|
+
environment 'config.frameworks -= [:active_record]'
|
56
|
+
|
57
|
+
gem 'mongo_mapper'
|
@@ -0,0 +1,305 @@
|
|
1
|
+
# lots of code and ideas borrowed from http://jetpackweb.com/blog/2009/10/21/rails-2-3-4-and-swfupload-rack-middleware-for-flash-uploads-that-degrade-gracefully/
|
2
|
+
# setup directories to hold files
|
3
|
+
FileUtils.mkdir_p 'public/javascripts/swfupload'
|
4
|
+
FileUtils.mkdir_p 'public/flash/swfupload'
|
5
|
+
FileUtils.mkdir_p 'public/images/swfupload'
|
6
|
+
FileUtils.mkdir_p 'app/views/swfupload'
|
7
|
+
FileUtils.mkdir_p 'app/stylesheets'
|
8
|
+
|
9
|
+
# download plugin files
|
10
|
+
base_url = 'http://swfupload.googlecode.com/svn/swfupload/trunk/core/plugins'
|
11
|
+
|
12
|
+
js_files = %w(swfupload.cookies swfupload.queue swfupload.speed swfupload.swfobject handlers swfupload)
|
13
|
+
|
14
|
+
js_files.each do |js_file|
|
15
|
+
run "curl -L #{base_url}/#{js_file}.js > public/javascripts/swfupload/#{js_file}.js"
|
16
|
+
end
|
17
|
+
|
18
|
+
run "curl -L http://github.com/jackdempsey/beet/raw/master/lib/beet/files/swfupload/js/handlers.js > public/javascripts/swfupload/handlers.js"
|
19
|
+
run "curl -L http://swfupload.googlecode.com/svn/swfupload/trunk/core/swfupload.js > public/javascripts/swfupload/swfupload.js"
|
20
|
+
run "curl -L http://swfupload.googlecode.com/svn/swfupload/trunk/core/Flash/swfupload.swf > public/flash/swfupload/swfupload.swf"
|
21
|
+
run "chmod +x public/flash/swfupload/swfupload.swf"
|
22
|
+
run "curl -L http://github.com/jackdempsey/beet/raw/master/lib/beet/files/swfupload/images/cancelbutton.gif > public/images/swfupload/cancelbutton.gif"
|
23
|
+
|
24
|
+
file 'app/stylesheets/swfupload.sass', <<-FILE
|
25
|
+
divFileProgressContainer
|
26
|
+
height: 75px
|
27
|
+
|
28
|
+
#divFileProgress
|
29
|
+
|
30
|
+
.progressWrapper
|
31
|
+
width: 100%
|
32
|
+
overflow: hidden
|
33
|
+
|
34
|
+
.progressContainer
|
35
|
+
margin: 5px
|
36
|
+
padding: 4px
|
37
|
+
border: solid 1px #E8E8E8
|
38
|
+
background-color: #F7F7F7
|
39
|
+
overflow: hidden
|
40
|
+
|
41
|
+
.progressName
|
42
|
+
font-size: 8pt
|
43
|
+
font-weight: 700
|
44
|
+
color: #555
|
45
|
+
width: 100%
|
46
|
+
height: 14px
|
47
|
+
text-align: left
|
48
|
+
white-space: nowrap
|
49
|
+
overflow: hidden
|
50
|
+
|
51
|
+
.progressBarInProgress, .progressBarComplete, .progressBarError
|
52
|
+
font-size: 0
|
53
|
+
width: 0%
|
54
|
+
height: 2px
|
55
|
+
background-color: blue
|
56
|
+
margin-top: 2px
|
57
|
+
|
58
|
+
.progressBarComplete
|
59
|
+
width: 100%
|
60
|
+
background-color: green
|
61
|
+
visibility: hidden
|
62
|
+
|
63
|
+
.progressBarError
|
64
|
+
width: 100%
|
65
|
+
background-color: red
|
66
|
+
visibility: hidden
|
67
|
+
|
68
|
+
.progressBarStatus
|
69
|
+
margin-top: 2px
|
70
|
+
width: 337px
|
71
|
+
font-size: 7pt
|
72
|
+
font-family: Arial
|
73
|
+
text-align: left
|
74
|
+
white-space: nowrap
|
75
|
+
|
76
|
+
a.progressCancel
|
77
|
+
font-size: 0
|
78
|
+
display: block
|
79
|
+
height: 14px
|
80
|
+
width: 14px
|
81
|
+
background-image: url(/images/swfupload/cancelbutton.gif)
|
82
|
+
background-repeat: no-repeat
|
83
|
+
background-position: -14px 0px
|
84
|
+
float: right
|
85
|
+
|
86
|
+
a.progressCancel:hover
|
87
|
+
background-position: 0px 0px
|
88
|
+
FILE
|
89
|
+
|
90
|
+
# create upload partial
|
91
|
+
file 'app/views/swfupload/_upload.html.haml', %q{
|
92
|
+
- content_for :head do
|
93
|
+
= javascript_include_tag 'swfupload/swfupload', 'swfupload/swfupload.swfobject', 'swfupload/handlers'
|
94
|
+
= stylesheet_link_tag %w(compiled/swfupload)
|
95
|
+
- session_key_name = ActionController::Base.session_options[:key]
|
96
|
+
|
97
|
+
- upload_url = songs_path
|
98
|
+
- form_tag upload_url, :multipart => true do
|
99
|
+
#swfupload_degraded_container
|
100
|
+
%noscript= "You should have Javascript enabled for a nicer upload experience"
|
101
|
+
= file_field_tag :Filedata
|
102
|
+
= submit_tag "Add a File"
|
103
|
+
#swfupload_container{ :style => "display: none" }
|
104
|
+
%span#spanButtonPlaceholder
|
105
|
+
#divFileProgressContainer
|
106
|
+
|
107
|
+
|
108
|
+
:javascript
|
109
|
+
SWFUpload.onload = function() {
|
110
|
+
var swf_settings = {
|
111
|
+
|
112
|
+
// SWFObject settings
|
113
|
+
minimum_flash_version: "9.0.28",
|
114
|
+
swfupload_pre_load_handler: function() {
|
115
|
+
$('#swfupload_degraded_container').hide();
|
116
|
+
$('#swfupload_container').show();
|
117
|
+
},
|
118
|
+
swfupload_load_failed_handler: function() {
|
119
|
+
},
|
120
|
+
|
121
|
+
post_params: {
|
122
|
+
"#{session_key_name}": "#{cookies[session_key_name]}",
|
123
|
+
"authenticity_token": "#{form_authenticity_token}",
|
124
|
+
},
|
125
|
+
|
126
|
+
//upload_url: "#{upload_url}?#{session_key_name}="+encodeURIComponent("#{cookies[session_key_name]}")+"&authenticity_token="+encodeURIComponent("#{form_authenticity_token}"),
|
127
|
+
upload_url: "#{upload_url}",
|
128
|
+
flash_url: '/flash/swfupload/swfupload.swf',
|
129
|
+
|
130
|
+
//example below lets you scope to only allowing image uploads
|
131
|
+
//file_types: "*.jpg;*.jpeg;*.gif;*.png;",
|
132
|
+
file_types: "*",
|
133
|
+
file_types_description: "pictures",
|
134
|
+
file_size_limit: "20 MB",
|
135
|
+
|
136
|
+
button_placeholder_id: "spanButtonPlaceholder",
|
137
|
+
button_width: 380,
|
138
|
+
button_height: 32,
|
139
|
+
button_text : '<span class="button">Select Files <span class="buttonSmall">(10 MB Max)</span></span>',
|
140
|
+
button_text_style : '.button { font-family: Helvetica, Arial, sans-serif; font-size: 24pt; } .buttonSmall { font-size: 18pt; }',
|
141
|
+
button_text_top_padding: 0,
|
142
|
+
button_text_left_padding: 18,
|
143
|
+
button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
|
144
|
+
button_cursor: SWFUpload.CURSOR.HAND,
|
145
|
+
file_queue_error_handler : fileQueueError,
|
146
|
+
file_dialog_complete_handler : fileDialogComplete,
|
147
|
+
upload_progress_handler : uploadProgress,
|
148
|
+
upload_error_handler : uploadError,
|
149
|
+
upload_success_handler : uploadSuccess,
|
150
|
+
upload_complete_handler : uploadComplete,
|
151
|
+
|
152
|
+
custom_settings : {
|
153
|
+
upload_target: "divFileProgressContainer"
|
154
|
+
}
|
155
|
+
}
|
156
|
+
var swf_upload = new SWFUpload(swf_settings);
|
157
|
+
};
|
158
|
+
}
|
159
|
+
|
160
|
+
append_file 'config/initializers/session_store.rb', <<-FILE
|
161
|
+
require 'rack/utils'
|
162
|
+
|
163
|
+
class FlashSessionCookieMiddleware
|
164
|
+
def initialize(app, session_key = '_session_id')
|
165
|
+
@app = app
|
166
|
+
@session_key = session_key
|
167
|
+
end
|
168
|
+
|
169
|
+
def call(env)
|
170
|
+
if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
|
171
|
+
params = ::Rack::Request.new(env).params
|
172
|
+
env['HTTP_COOKIE'] = [ @session_key, params[@session_key] ].join('=').freeze unless params[@session_key].nil?
|
173
|
+
end
|
174
|
+
@app.call(env)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
ActionController::Dispatcher.middleware.insert_before(ActionController::Base.session_store, FlashSessionCookieMiddleware, ActionController::Base.session_options[:key])
|
179
|
+
FILE
|
180
|
+
|
181
|
+
# example Song resource for those who want it
|
182
|
+
controller_file = <<-FILE
|
183
|
+
class SongsController < ApplicationController
|
184
|
+
layout 'swfupload'
|
185
|
+
|
186
|
+
def index
|
187
|
+
@songs = Song.all
|
188
|
+
end
|
189
|
+
|
190
|
+
def create
|
191
|
+
require 'mime/types'
|
192
|
+
mp3_info = Mp3Info.new(params[:Filedata].path)
|
193
|
+
|
194
|
+
song = Song.new
|
195
|
+
song.artist = mp3_info.tag.artist
|
196
|
+
song.title = mp3_info.tag.title
|
197
|
+
song.length_in_seconds = mp3_info.length.to_i
|
198
|
+
|
199
|
+
params[:Filedata].content_type = MIME::Types.type_for(params[:Filedata].original_filename).to_s
|
200
|
+
song.track = params[:Filedata]
|
201
|
+
song.save
|
202
|
+
|
203
|
+
render :text => [song.artist, song.title, song.convert_seconds_to_time].join(" - ")
|
204
|
+
rescue Mp3InfoError => e
|
205
|
+
render :text => "File error"
|
206
|
+
rescue Exception => e
|
207
|
+
render :text => e.message
|
208
|
+
end
|
209
|
+
end
|
210
|
+
FILE
|
211
|
+
|
212
|
+
|
213
|
+
model_file = <<-FILE
|
214
|
+
class Song < ActiveRecord::Base
|
215
|
+
|
216
|
+
has_attached_file :track
|
217
|
+
|
218
|
+
# validates_presence_of :title, :artist, :length_in_seconds
|
219
|
+
validates_attachment_presence :track
|
220
|
+
validates_attachment_content_type :track, :content_type => [ 'application/mp3', 'application/x-mp3', 'audio/mpeg', 'audio/mp3' ]
|
221
|
+
validates_attachment_size :track, :less_than => 20.megabytes
|
222
|
+
|
223
|
+
attr_accessible :title, :artist, :length_in_seconds
|
224
|
+
|
225
|
+
def convert_seconds_to_time
|
226
|
+
total_minutes = length_in_seconds / 1.minutes
|
227
|
+
seconds_in_last_minute = length_in_seconds - total_minutes.minutes.seconds
|
228
|
+
"\#{total_minutes}m \#{seconds_in_last_minute}s"
|
229
|
+
end
|
230
|
+
|
231
|
+
|
232
|
+
end
|
233
|
+
FILE
|
234
|
+
|
235
|
+
view_file = <<-FILE
|
236
|
+
%h1 Songs
|
237
|
+
|
238
|
+
- @songs.each do |song|
|
239
|
+
%p= song.title
|
240
|
+
|
241
|
+
= render 'swfupload/upload'
|
242
|
+
FILE
|
243
|
+
|
244
|
+
migration_file = <<-FILE
|
245
|
+
class CreateSongs < ActiveRecord::Migration
|
246
|
+
def self.up
|
247
|
+
create_table :songs do |t|
|
248
|
+
t.string :artist
|
249
|
+
t.string :title
|
250
|
+
t.integer :length_in_seconds
|
251
|
+
t.string :track_file_name
|
252
|
+
t.string :track_content_type
|
253
|
+
t.integer :track_file_size
|
254
|
+
t.timestamps
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def self.down
|
259
|
+
drop_table :songs
|
260
|
+
end
|
261
|
+
end
|
262
|
+
FILE
|
263
|
+
|
264
|
+
layout_file = <<-FILE
|
265
|
+
!!! Strict
|
266
|
+
%html
|
267
|
+
%head
|
268
|
+
%title
|
269
|
+
= h(yield(:title) || "Untitled")
|
270
|
+
= '<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"></script>'
|
271
|
+
= '<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery-ui.min.js"></script>'
|
272
|
+
= yield(:head)
|
273
|
+
%body
|
274
|
+
#container
|
275
|
+
= yield
|
276
|
+
FILE
|
277
|
+
|
278
|
+
puts '=' * 80
|
279
|
+
if yes? "Create an example resource using Paperclip? (y/n)"
|
280
|
+
FileUtils.mkdir_p 'app/views/songs'
|
281
|
+
FileUtils.mkdir_p 'public/stylesheets/compiled'
|
282
|
+
|
283
|
+
file 'app/views/layouts/swfupload.html.haml', layout_file
|
284
|
+
file 'app/controllers/songs_controller.rb', controller_file
|
285
|
+
file 'app/models/song.rb', model_file
|
286
|
+
file 'app/views/songs/index.html.haml', view_file
|
287
|
+
|
288
|
+
generate "migration", "create_songs"
|
289
|
+
filename = Dir['db/migrate/*create_songs.rb'].first
|
290
|
+
file filename, migration_file
|
291
|
+
rake "db:migrate"
|
292
|
+
|
293
|
+
gem 'paperclip'
|
294
|
+
gem 'haml'
|
295
|
+
gem 'ruby-mp3info', :lib => 'mp3info'
|
296
|
+
|
297
|
+
run "sass app/stylesheets/swfupload.sass > public/stylesheets/compiled/swfupload.css"
|
298
|
+
|
299
|
+
route 'map.resources :songs'
|
300
|
+
|
301
|
+
puts "Now fire up the app and go to /songs to test it out!"
|
302
|
+
else
|
303
|
+
puts "\nYour controller should have a create action that looks something like this:\n#{controller_file}"
|
304
|
+
puts "\nYou can create a model that looks like this:\n#{model_file}"
|
305
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: beet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jack Dempsey
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-01-09 00:00:00 -05:00
|
13
13
|
default_executable: beet
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -51,6 +51,10 @@ files:
|
|
51
51
|
- lib/beet/execution.rb
|
52
52
|
- lib/beet/executor.rb
|
53
53
|
- lib/beet/file_system.rb
|
54
|
+
- lib/beet/files/swfupload/images/cancelbutton.gif
|
55
|
+
- lib/beet/files/swfupload/images/header-bg.jpg
|
56
|
+
- lib/beet/files/swfupload/images/logo.gif
|
57
|
+
- lib/beet/files/swfupload/js/handlers.js
|
54
58
|
- lib/beet/gem_location_map.rb
|
55
59
|
- lib/beet/interaction.rb
|
56
60
|
- lib/beet/logger.rb
|
@@ -66,10 +70,12 @@ files:
|
|
66
70
|
- lib/beet/recipes/rails/css/blueprint.rb
|
67
71
|
- lib/beet/recipes/rails/css/nifty_layout.rb
|
68
72
|
- lib/beet/recipes/rails/css/reset.rb
|
73
|
+
- lib/beet/recipes/rails/db/mongo.rb
|
69
74
|
- lib/beet/recipes/rails/db/mysql.rb
|
70
75
|
- lib/beet/recipes/rails/db/postgres.rb
|
71
76
|
- lib/beet/recipes/rails/git.rb
|
72
77
|
- lib/beet/recipes/rails/jquery.rb
|
78
|
+
- lib/beet/recipes/rails/swfupload.rb
|
73
79
|
- lib/beet/recipes/rails/testing/rspec.rb
|
74
80
|
- lib/beet/recipes/rails/testing/shoulda.rb
|
75
81
|
- lib/beet/scm.rb
|