acts_as_status_bar 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +20 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +141 -0
- data/Rakefile +32 -0
- data/app/controllers/acts_as_status_bar/status_bar_controller.rb +29 -0
- data/app/helpers/acts_as_status_bar_helper.rb +105 -0
- data/app/models/acts_as_status_bar/status_bar.rb +260 -0
- data/app/views/acts_as_status_bar/status_bar/index.html.erb +18 -0
- data/app/views/acts_as_status_bar/status_bar/show.html.erb +5 -0
- data/config/initializers/acts_as_status_bar.rb +4 -0
- data/config/locales/custom_errors.it.yml +4 -0
- data/config/locales/links.it.yml +7 -0
- data/config/routes.rb +7 -0
- data/lib/acts_as_status_bar.rb +7 -0
- data/lib/acts_as_status_bar/engine.rb +19 -0
- data/lib/acts_as_status_bar/exceptions.rb +18 -0
- data/lib/acts_as_status_bar/status_bar_base.rb +62 -0
- data/lib/acts_as_status_bar/version.rb +4 -0
- data/lib/generators/acts_as_status_bar/install/install_generator.rb +17 -0
- data/lib/generators/acts_as_status_bar/install/templates/public/images/acts_as_status_bar_background.gif +0 -0
- data/lib/generators/acts_as_status_bar/install/templates/public/images/acts_as_status_bar_foreground.gif +0 -0
- data/lib/generators/acts_as_status_bar/install/templates/public/javascripts/acts_as_status_bar_javascript.js +66 -0
- data/lib/generators/acts_as_status_bar/install/templates/public/stylesheets/acts_as_status_bar.css +33 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA512:
|
3
|
+
data.tar.gz: e014a866d94cae0d40e0213e112f422d9a8f92704d3d86058aff626af8a4a47cc423d454e9ebe9fd0a2757947b73f19551210ede0e5b40d3fe253cda43d4cdb7
|
4
|
+
metadata.gz: 0cc5d160cd7c16ba3a8eb27d10a42dd7016e09f935a3fd1af1bb5901c83a0c64f72f0b7d7bac10b3fd87748eab2743a7936cd3f254aad0c525f483f60edb7952
|
5
|
+
SHA1:
|
6
|
+
data.tar.gz: b75fea836e04252a07fc4452c03d305a98f60770
|
7
|
+
metadata.gz: e7d40def19450dca0731002d4740182cf735c71a
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#You can add lacal gems with
|
2
|
+
# gem "my_gem", :path => "/home/www/gems/my_gem"
|
3
|
+
#you must remove the path in production or if you change server and replace with:
|
4
|
+
# git "git@10.2.252.240:my_gem.git"
|
5
|
+
|
6
|
+
source "http://rubygems.org"
|
7
|
+
|
8
|
+
gem 'rails', '~>3.0.15'
|
9
|
+
gem 'mysql2', '< 0.3'
|
10
|
+
|
11
|
+
group :development, :test do
|
12
|
+
gem "ruby-debug"
|
13
|
+
gem "capybara", ">= 0.4.0"
|
14
|
+
gem "sqlite3"
|
15
|
+
gem "single_test"
|
16
|
+
gem "rspec-rails", "~> 2.0"
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec
|
20
|
+
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
=ActsAsStatusBar
|
2
|
+
ActsAsStatusBar adds status bar functionality to your ActiveRecord Models.
|
3
|
+
I tried to keep it very simple, but powerful enough to be very useful.
|
4
|
+
|
5
|
+
You will need Prototype to run your gem.
|
6
|
+
|
7
|
+
==Setup
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
gem 'acts_as_status_bar'
|
10
|
+
|
11
|
+
then execute:
|
12
|
+
$ bundle install
|
13
|
+
|
14
|
+
or install it yourself as:
|
15
|
+
$ sudo gem install acts_as_status_bar
|
16
|
+
|
17
|
+
install addon:
|
18
|
+
$ rails g acts_as_status_bar:install
|
19
|
+
|
20
|
+
==Usage
|
21
|
+
Let's imagine you have a Home model, with a controller and a view...
|
22
|
+
|
23
|
+
In your model:
|
24
|
+
#app/models/home.rb
|
25
|
+
class Home < ActiveRecord::Base
|
26
|
+
acts_as_status_bar
|
27
|
+
|
28
|
+
def my_very_long_task_needing_a_status_bar
|
29
|
+
status_bar_init
|
30
|
+
status_bar.max=10000
|
31
|
+
status_bar.message="My very long task..."
|
32
|
+
10000.times do
|
33
|
+
status_bar.inc
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
In your controller:
|
39
|
+
#app/controllers/homes_controller.erb
|
40
|
+
def create
|
41
|
+
@home = Home.new(params[:home])
|
42
|
+
status_bar_init(@home) do
|
43
|
+
@home.save!
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
In your view:
|
48
|
+
#app/views/home/index.html.erb
|
49
|
+
<%= status_bar_for(@home) %>
|
50
|
+
|
51
|
+
<%= form_for(@home) do |f| %>
|
52
|
+
...
|
53
|
+
<%= f.hidden_field :status_bar_id %>
|
54
|
+
<%= f.submit :onclick => 'status_bar_init()' %>
|
55
|
+
<% end %>
|
56
|
+
|
57
|
+
Please note that the status_bar_for helper MUST be before the form_for with the hidden field.
|
58
|
+
(The helper creates the bar id, but form_for copies the object so it is not possibile to update by reference...)
|
59
|
+
|
60
|
+
Or, if you don't have an object,
|
61
|
+
|
62
|
+
<%= status_bar_tag %>
|
63
|
+
<%=link_tag "MyLink", my_url, :onclick => 'status_bar_init()' %>
|
64
|
+
|
65
|
+
==Functions
|
66
|
+
StatusBar uses an external store (PStore) to archive progress data, so all you need to use it
|
67
|
+
is the id of the status bar you are using.
|
68
|
+
|
69
|
+
This id is stored in your model status_bar_id attribute.
|
70
|
+
|
71
|
+
You need to pass it back to your controller's "create" actions using an hidden field.
|
72
|
+
|
73
|
+
When you call status_bar_init from your model the status_bar_id is valorized, so your status_bar
|
74
|
+
is created, with the same id of your js.
|
75
|
+
|
76
|
+
Only one id is passed and the magic is done!
|
77
|
+
|
78
|
+
There are some functions you can use in your model to customize the behavior of the bar.
|
79
|
+
===Basic
|
80
|
+
* status_bar_init
|
81
|
+
Initializes the bar using the id in status_bar_id, or creates a new one if not defined.
|
82
|
+
* status_bar.inc(value=1)
|
83
|
+
Increments counter by 1 or by value.
|
84
|
+
* status_bar.dec(value=1)
|
85
|
+
Decrements counter by 1 or by value.
|
86
|
+
* status_bar.max=(value)
|
87
|
+
Sets the max value, that, once reached, stops the bar.
|
88
|
+
* status_bar.message=(value)
|
89
|
+
Set the message in the first line of the bar: you can use it to display dynamic messages
|
90
|
+
during the process.
|
91
|
+
* status_bar.delete
|
92
|
+
Deletes the current status bar.
|
93
|
+
Do not forget it or you will be submerged of useless inactive status bars...
|
94
|
+
|
95
|
+
===Advanced
|
96
|
+
* status_bar.progress=(value)
|
97
|
+
Default value is : %q<["#{current}/#{max} (#{percent}%) tempo stimato #{finish_in}", "#{percent}", "#{message}"]>
|
98
|
+
The string is evaluated and passed to the js as xml.
|
99
|
+
You can customize the first and the last fields, while the second (percentage) is used for the visual bar and to
|
100
|
+
stop the bar when 100 is reached.
|
101
|
+
You can see the code to get the usable fields.
|
102
|
+
* status_bar.add_field(:field)
|
103
|
+
Adds a new field to the status bar, you can use to store data or to customize the output.
|
104
|
+
New methods are created dinamically to access your new field:
|
105
|
+
* inc_field
|
106
|
+
* dec_field
|
107
|
+
* field=(value)
|
108
|
+
* field
|
109
|
+
* ActsAsStatusBar::StatusBar.delete_all
|
110
|
+
Deletes all bars stored.
|
111
|
+
* ActsAsStatusBar::StatusBar.all
|
112
|
+
Return all active status bars.
|
113
|
+
* ActsAsStatusBar::StatusBar.valid?(id)
|
114
|
+
Checks if the id passed corresponds to a valid status bar.
|
115
|
+
==Administration
|
116
|
+
Some times you will need to maintain the status bar storage.
|
117
|
+
|
118
|
+
You can link to acts_as_status_bar_status_bar_index_path .
|
119
|
+
|
120
|
+
The controller lets you check and delete stored status bars.
|
121
|
+
|
122
|
+
You can access the bar info pointing to acts_as_status_bar_status_bar_path(id) or,
|
123
|
+
if you need a more structured info, to acts_as_status_bar_status_bar(id, :format => :xml)
|
124
|
+
|
125
|
+
==Styling
|
126
|
+
You can change the bar style in the acts_as_status_bar.css .
|
127
|
+
|
128
|
+
==Whislist
|
129
|
+
* finding time to create tests...
|
130
|
+
|
131
|
+
==Contributing
|
132
|
+
|
133
|
+
1. Fork it
|
134
|
+
2. Create your feature branch (git checkout -b my-new-feature)
|
135
|
+
3. Commit your changes (git commit -am 'Added some feature')
|
136
|
+
4. Push to the branch (git push origin my-new-feature)
|
137
|
+
5. Create new Pull Request
|
138
|
+
|
139
|
+
==Thanks
|
140
|
+
|
141
|
+
* Michele Ferretti, who created the original AjaxProgressBar (http://www.blackbirdblog.it/blog/archivio/2006/03/09/ajax-progress-bar/)
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'rubygems'
|
3
|
+
begin
|
4
|
+
require 'bundler/setup'
|
5
|
+
require "bundler/gem_tasks"
|
6
|
+
rescue LoadError
|
7
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
8
|
+
end
|
9
|
+
|
10
|
+
require 'rake'
|
11
|
+
require 'rake/testtask'
|
12
|
+
require 'rdoc/task'
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
Rake::TestTask.new(:test) do |t|
|
17
|
+
t.libs << 'lib'
|
18
|
+
t.libs << 'test'
|
19
|
+
t.pattern = 'test/**/*_test.rb'
|
20
|
+
t.verbose = false
|
21
|
+
end
|
22
|
+
|
23
|
+
task :default => :test
|
24
|
+
|
25
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
26
|
+
rdoc.rdoc_dir = 'rdoc'
|
27
|
+
rdoc.title = 'acts_as_status_bar'
|
28
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
29
|
+
rdoc.rdoc_files.include('README.rdoc')
|
30
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module ActsAsStatusBar
|
2
|
+
class StatusBarController < ::ApplicationController
|
3
|
+
def index
|
4
|
+
@status_bars=ActsAsStatusBar::StatusBar.all
|
5
|
+
end
|
6
|
+
|
7
|
+
def show
|
8
|
+
@status_bar = ActsAsStatusBar::StatusBar.new(:id => params[:id], :create => false)
|
9
|
+
respond_to do |format|
|
10
|
+
format.html
|
11
|
+
format.xml {render :inline => @status_bar.to_xml}
|
12
|
+
end
|
13
|
+
# rescue => e
|
14
|
+
# flash[:alert] = e.message
|
15
|
+
# redirect_to :action => 'show', :controller => 'status_bar'
|
16
|
+
end
|
17
|
+
|
18
|
+
def destroy
|
19
|
+
@status_bar = ActsAsStatusBar::StatusBar.new(:id => params[:id], :create => false)
|
20
|
+
@status_bar.delete
|
21
|
+
redirect_to :action => "index"
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy_all
|
25
|
+
ActsAsStatusBar::StatusBar.delete_all
|
26
|
+
redirect_to :action => "index"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module ActsAsStatusBarHelper
|
2
|
+
#Use it in your views to activate status bars.
|
3
|
+
#You can put it everywhere in your view, you only need to pass it your object.
|
4
|
+
#
|
5
|
+
#The only other thing you need to do is to add an :onclick => 'status_bar_init()'
|
6
|
+
#to the button/link that activates the bar:
|
7
|
+
#
|
8
|
+
# => <%= f.submit :onclick => 'status_bar_init()' %>
|
9
|
+
#
|
10
|
+
#You can access to the admin page via the helper:
|
11
|
+
# => acts_as_status_bar_status_bar_index_path
|
12
|
+
|
13
|
+
#Use it if you don't have an object.
|
14
|
+
#Id is passed to the controller via session[:acts_as_status_bar][:id]
|
15
|
+
#and can be retrieved using status_bar_id(params) in your controller
|
16
|
+
# => #app/views/home/index.html.erb
|
17
|
+
# => <%= status_bar_tag %>
|
18
|
+
# => <%= link_to 'my_link', my_link_action_path, :onclick => 'status_bar_init()' %>
|
19
|
+
#
|
20
|
+
# => #app/controllers/homes_controller.erb
|
21
|
+
# => def action
|
22
|
+
# => @home = Home.new
|
23
|
+
# => @home.status_bar_id = status_bar_id(params)
|
24
|
+
# => @home.do_what_I_need
|
25
|
+
# => @home.status_bar.delete
|
26
|
+
# => end
|
27
|
+
def status_bar_tag(frequency = nil)
|
28
|
+
status_bar = ActsAsStatusBar::StatusBar.new
|
29
|
+
frequency = frequency || status_bar.frequency
|
30
|
+
url = acts_as_status_bar_status_bar_path(status_bar.id, :format => :xml)
|
31
|
+
session[:acts_as_status_bar]={:id => status_bar.id}
|
32
|
+
_status_bar_init(frequency, url)
|
33
|
+
end
|
34
|
+
|
35
|
+
#Use it with status_bar or status_bar_tag in the controller to initialize and then destroy the bar.
|
36
|
+
# => @home = Home.find(params[:id])
|
37
|
+
# => status_bar_init(@home) do
|
38
|
+
# @home.destroy
|
39
|
+
# => end
|
40
|
+
#
|
41
|
+
#It returns the value of status_bar.delete, a hash with parameters of the last update.
|
42
|
+
#You can use it to display info like process duration, object updated, ...
|
43
|
+
#
|
44
|
+
def status_bar_init(object, &block)
|
45
|
+
object.status_bar_id ||= status_bar_id(params)
|
46
|
+
object.status_bar_init
|
47
|
+
bar = object.status_bar
|
48
|
+
yield block
|
49
|
+
bar.delete
|
50
|
+
end
|
51
|
+
|
52
|
+
#Use it if you have an object and a form to pass parameters to the controller.
|
53
|
+
#The helper populates object.status_bar_id, and you need an hidden field in your form
|
54
|
+
#to pass the id to your object in the controller:
|
55
|
+
# => #app/views/home/index.html.erb
|
56
|
+
# => <%= status_bar_for(@home) %>
|
57
|
+
# => <%= form_for(@home) do |f| %>
|
58
|
+
# => ...
|
59
|
+
# => <%= f.hidden_field :status_bar_id %>
|
60
|
+
# => <%= f.submit :onclick => 'status_bar_init()' %>
|
61
|
+
# => <% end %>
|
62
|
+
def status_bar_for(object,frequnecy = nil)
|
63
|
+
object.status_bar_init
|
64
|
+
url = acts_as_status_bar_status_bar_path(object.status_bar_id, :format => :xml)
|
65
|
+
frequency = frequency || object.status_bar.frequency
|
66
|
+
_status_bar_init(frequency, url)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
#Used to retrieve id from params in controller
|
72
|
+
def status_bar_id(params)
|
73
|
+
session[:acts_as_status_bar].try(:fetch, :id)
|
74
|
+
end
|
75
|
+
|
76
|
+
#Initialize the status bar
|
77
|
+
def _status_bar_init(frequency, url)
|
78
|
+
stylesheet_link_tag('acts_as_status_bar')+
|
79
|
+
content_tag(:div, :id => "acts-as-status-bar-container", :align => 'center') do
|
80
|
+
content_tag(:p, '...', :id => 'acts-as-status-bar-message') +
|
81
|
+
content_tag(:p, '...', :id => 'acts-as-status-bar-value') +
|
82
|
+
content_tag(:div,
|
83
|
+
content_tag(:div,'', :id => "acts-as-status-bar"),
|
84
|
+
:id => "acts-as-status-bar-progress-bar", :align => 'left'
|
85
|
+
)
|
86
|
+
end +
|
87
|
+
javascript_include_tag("acts_as_status_bar_javascript") +
|
88
|
+
javascript_tag(%Q[
|
89
|
+
function status_bar_init(){
|
90
|
+
var progress = new ActsAsStatusBar(
|
91
|
+
'acts-as-status-bar-container',
|
92
|
+
'acts-as-status-bar-message',
|
93
|
+
'acts-as-status-bar-value',
|
94
|
+
'acts-as-status-bar-progress-bar',
|
95
|
+
'acts-as-status-bar', {
|
96
|
+
frequency: #{frequency},
|
97
|
+
total: 100,
|
98
|
+
url: "#{url}"
|
99
|
+
});
|
100
|
+
progress.start();
|
101
|
+
}
|
102
|
+
])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -0,0 +1,260 @@
|
|
1
|
+
require 'pstore'
|
2
|
+
|
3
|
+
module ActsAsStatusBar
|
4
|
+
#StatusBar is used to support a dynamic status bar, with values, percentage, timing and messages.
|
5
|
+
#==Usage
|
6
|
+
#
|
7
|
+
#It is possible to instantiate the bar with additional fields, passed as a list of arguments and their relative default values.
|
8
|
+
#new(:id => nil, )
|
9
|
+
class StatusBar
|
10
|
+
include ActionView::Helpers::DateHelper
|
11
|
+
|
12
|
+
#Update frequency in seconds
|
13
|
+
FREQUENCY = 10
|
14
|
+
#Default End value
|
15
|
+
MAX = 100
|
16
|
+
#Default storage path
|
17
|
+
FILE = "db/acts_as_status_bar.store"
|
18
|
+
#Default status bar output when progress is finished
|
19
|
+
XML = %q<["Completato", 100, ""]>
|
20
|
+
|
21
|
+
# ==CLASS Methods
|
22
|
+
class<<self
|
23
|
+
#Start Public Class Methods
|
24
|
+
#NO BAR is created using Class Methods
|
25
|
+
|
26
|
+
#Delete all bars
|
27
|
+
def delete_all
|
28
|
+
store = new
|
29
|
+
store.send :_delete_all
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
#Check if the bar is valid
|
34
|
+
def valid?(id)
|
35
|
+
store = new
|
36
|
+
store.send(:ids).include?(id.to_i)
|
37
|
+
end
|
38
|
+
|
39
|
+
#It returns all active bars
|
40
|
+
#===Format
|
41
|
+
# {id1 => {:max, :current, ...}
|
42
|
+
# id2 => {:max, :current, ...}
|
43
|
+
# }
|
44
|
+
def all
|
45
|
+
store = new
|
46
|
+
store.send :_all
|
47
|
+
end
|
48
|
+
|
49
|
+
#to_s
|
50
|
+
def to_s
|
51
|
+
store = new
|
52
|
+
opt = []
|
53
|
+
store.send(:_options).each_key.map{|k| opt << ":#{k}" }
|
54
|
+
"#{store.class.name}(#{opt.join(', ')})"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Start Private Class Methods
|
58
|
+
private
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
# ==INSTANCE Methods
|
63
|
+
|
64
|
+
#Initialize the bar
|
65
|
+
#===Options
|
66
|
+
#* no_options #Initialize the bar with a new id and don't store defaults
|
67
|
+
#* :id => id #Initialize the bar with a specific id and store defaults if new_record?
|
68
|
+
#* :create => false #Initialize the bar with a specific id (if present), without storing defaults
|
69
|
+
def initialize(*args)
|
70
|
+
@options = { :max => MAX,
|
71
|
+
:current => 0,
|
72
|
+
:start_at => nil,
|
73
|
+
:current_at => 0.0,
|
74
|
+
:message => "",
|
75
|
+
:progress => %q<["#{current}/#{max} (#{percent}%) tempo stimato #{finish_in}", "#{percent}", "#{message}"]> }
|
76
|
+
@options.merge!(args.extract_options!)
|
77
|
+
@id = @options.delete(:id)
|
78
|
+
#id usually comes from params, so it must be sure it is converted to int
|
79
|
+
@id = @id.to_i if @id
|
80
|
+
@store = PStore.new(FILE)
|
81
|
+
_init_bar if @id
|
82
|
+
end
|
83
|
+
|
84
|
+
#Add a new field to the bar and store default value
|
85
|
+
#(Store Data)
|
86
|
+
def add_field(field, default=nil)
|
87
|
+
_define_method(field.to_sym) unless @options[field.to_sym]
|
88
|
+
send("#{field.to_sym}=", default)
|
89
|
+
end
|
90
|
+
|
91
|
+
#Get or create an id
|
92
|
+
def id
|
93
|
+
@id ||= Time.now.utc.to_i
|
94
|
+
end
|
95
|
+
|
96
|
+
#Check if the bar is new or already existent
|
97
|
+
def valid?
|
98
|
+
ids.include?(@id)
|
99
|
+
end
|
100
|
+
|
101
|
+
#Destroy the bar and return its last values
|
102
|
+
def delete
|
103
|
+
out = _delete(id) if @store
|
104
|
+
@id = nil
|
105
|
+
@store = nil
|
106
|
+
out
|
107
|
+
end
|
108
|
+
|
109
|
+
def percent
|
110
|
+
#mylog("percent = #{max.inspect}")
|
111
|
+
unless !valid? || max == 0
|
112
|
+
#raise CustomError::InvalidBar if !valid? || max == 0
|
113
|
+
(current.to_i * 100 / max.to_i).to_i
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
#Decrement current value
|
118
|
+
def dec(value=1)
|
119
|
+
inc(value*-1)
|
120
|
+
end
|
121
|
+
|
122
|
+
#Increment current value and set start_at at current time (if not set yet)
|
123
|
+
def inc(value=1)
|
124
|
+
if valid?
|
125
|
+
#raise CustomError::InvalidBar unless valid?
|
126
|
+
_set(:start_at, Time.now.to_f) unless _get(:start_at)
|
127
|
+
_set(:current_at, Time.now.to_f)
|
128
|
+
inc_value = _inc(:current,value)
|
129
|
+
mylog("inc inc_value: #{inc_value}")
|
130
|
+
inc_value
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
#Return default frequency value, if not passed in the helper
|
135
|
+
def frequency
|
136
|
+
FREQUENCY
|
137
|
+
end
|
138
|
+
|
139
|
+
#Return estimated completion time
|
140
|
+
def finish_in
|
141
|
+
if valid?
|
142
|
+
#raise CustomError::InvalidBar unless valid?
|
143
|
+
remaining_time = (current_at.to_f - start_at.to_f)*(max.to_f/current.to_f - 1.0) if current.to_i > 0
|
144
|
+
remaining_time ? distance_of_time_in_words(remaining_time) : "non disponibile"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
#Return current value in xml in a format compatible with the status bar
|
150
|
+
def to_xml
|
151
|
+
val = valid? ? eval(progress) : eval(XML)
|
152
|
+
Hash['value', val[0], 'percent', val[1], 'message', val[2]].to_xml
|
153
|
+
end
|
154
|
+
|
155
|
+
private
|
156
|
+
|
157
|
+
#Initialize the bar, store defaults and dinamycally create methods
|
158
|
+
def _init_bar
|
159
|
+
unless @options.delete(:create)
|
160
|
+
_store_defaults
|
161
|
+
_define_methods
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
#Return all ids
|
166
|
+
def ids
|
167
|
+
@store.transaction {@store.roots}
|
168
|
+
end
|
169
|
+
|
170
|
+
#Delete the bar marked with a specific id
|
171
|
+
def _delete(i)
|
172
|
+
out ={}
|
173
|
+
@store.transaction {out = @store.delete(i)}
|
174
|
+
out
|
175
|
+
end
|
176
|
+
|
177
|
+
#Delete all bars
|
178
|
+
def _delete_all
|
179
|
+
ids.each {|i| _delete(i)}
|
180
|
+
end
|
181
|
+
|
182
|
+
#Return all status bars
|
183
|
+
def _all
|
184
|
+
out = {}
|
185
|
+
ids.each {|i| @store.transaction(true) {out[i] = @store[i]}}
|
186
|
+
out
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
#Increment a value
|
191
|
+
#It also works with strings
|
192
|
+
def _inc(key,value)
|
193
|
+
_set(key, (_get(key) || 0) + value)
|
194
|
+
end
|
195
|
+
|
196
|
+
#Decrement a value
|
197
|
+
#inc_ key, value*-1 was not used so that it can also work with strings
|
198
|
+
#[Not implemented yet... It would be a nice thing to add in the future...]
|
199
|
+
def _dec(key,value)
|
200
|
+
_set(key, (_get(key) || 0) - value)
|
201
|
+
end
|
202
|
+
|
203
|
+
#Save a value
|
204
|
+
def _set(key,value)
|
205
|
+
@store.transaction {@store[@id][key] = value}
|
206
|
+
end
|
207
|
+
|
208
|
+
#Retrieve a value
|
209
|
+
def _get(key)
|
210
|
+
@store.transaction(true) {@store[@id][key]}
|
211
|
+
end
|
212
|
+
|
213
|
+
#Return options
|
214
|
+
def _options
|
215
|
+
@options
|
216
|
+
end
|
217
|
+
|
218
|
+
#Store default values if the bar is not created yet
|
219
|
+
def _store_defaults
|
220
|
+
@store.transaction {@store[@id]= @options} unless valid?
|
221
|
+
end
|
222
|
+
|
223
|
+
#Build accessor methods for every bar's attribute
|
224
|
+
def _define_methods
|
225
|
+
@store.transaction(true){@store[@id]}.each_key do |method|
|
226
|
+
_define_method(method)
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
#Build acessors for a specific attribute
|
231
|
+
#===Accessors
|
232
|
+
#* inc_attribute(value=1)
|
233
|
+
#* dec_attribute(value=1)
|
234
|
+
#* attribute
|
235
|
+
#* attribute=(value)
|
236
|
+
def _define_method(method)
|
237
|
+
#Getters
|
238
|
+
self.class.send(:define_method, method) do
|
239
|
+
_get method.to_sym
|
240
|
+
end
|
241
|
+
|
242
|
+
#Setters
|
243
|
+
self.class.send(:define_method, "#{method.to_s}=") do |value|
|
244
|
+
_set method, value
|
245
|
+
end
|
246
|
+
|
247
|
+
#Incrementer
|
248
|
+
self.class.send(:define_method, "inc_#{method.to_s}") do |*args|
|
249
|
+
value = args.first || 1
|
250
|
+
_inc method, value
|
251
|
+
end
|
252
|
+
|
253
|
+
#Decrementer
|
254
|
+
self.class.send(:define_method, "dec_#{method.to_s}") do |*args|
|
255
|
+
value = args.first || 1
|
256
|
+
_dec method, value
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<html>
|
2
|
+
<body>
|
3
|
+
<h1>Active Status Bars</h1>
|
4
|
+
<% @status_bars.each do |k,v|%>
|
5
|
+
<li><%=link_to 'Delete',
|
6
|
+
acts_as_status_bar_status_bar_path(k),
|
7
|
+
:method => :delete
|
8
|
+
%>
|
9
|
+
<%= k %>:
|
10
|
+
<%= v.inspect %>
|
11
|
+
</li>
|
12
|
+
<% end %>
|
13
|
+
<%=link_to 'Delete All',
|
14
|
+
destroy_all_acts_as_status_bar_status_bar_index_path,
|
15
|
+
:method => :delete
|
16
|
+
%>
|
17
|
+
</body>
|
18
|
+
</html>
|
@@ -0,0 +1,4 @@
|
|
1
|
+
#Il caricamento dellce costanti, poich� dipende dalla classe Enumeration, definita dall'applicazione Rails
|
2
|
+
#non pu� essere fatto nell'engine in quanto Rails.root non � definito....
|
3
|
+
require "acts_as_status_bar/constant" if File.exists?("acts_as_status_bar/constant.rb")
|
4
|
+
require "acts_as_status_bar/exceptions" if File.exists?("acts_as_status_bar/exceptions.rb")
|
data/config/routes.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActsAsStatusBar
|
2
|
+
class Engine < Rails::Engine
|
3
|
+
|
4
|
+
config.autoload_paths += Dir["#{config.root}/lib/**/"]
|
5
|
+
|
6
|
+
initializer 'acts_as_status_bar.helper' do |app|
|
7
|
+
ActiveSupport.on_load(:action_controller) do
|
8
|
+
include ActsAsStatusBarHelper
|
9
|
+
end
|
10
|
+
ActiveSupport.on_load(:action_view) do
|
11
|
+
include ActsAsStatusBarHelper
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
#Add ere require to specific file or gem used
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#Localize messages in it.CustomError.MyError
|
2
|
+
module ActsAsStatusBar
|
3
|
+
class CustomError < StandardError
|
4
|
+
def initialize(*args)
|
5
|
+
@options = args.extract_options!
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def message
|
10
|
+
@options.merge!({:default => "Error : #{@options.inspect}"})
|
11
|
+
I18n.t("#{self.class.name.gsub(/::/,'.')}", @options )
|
12
|
+
end
|
13
|
+
|
14
|
+
class InvalidBar < CustomError; end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ActsAsStatusBar
|
2
|
+
module StatusBarBase
|
3
|
+
def self.included(base) # :nodoc:
|
4
|
+
base.send :extend, ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
# Class methods for the mixin
|
8
|
+
module ClassMethods
|
9
|
+
# Defines the class method to inject monitor methods
|
10
|
+
#
|
11
|
+
#==Example
|
12
|
+
# class MyModel < ActiveRecord::Base
|
13
|
+
# acts_as_status_bar
|
14
|
+
# ...
|
15
|
+
# private
|
16
|
+
#
|
17
|
+
# def warn_test?
|
18
|
+
# whatever you want that returns true in a warning condition
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def error_test?
|
22
|
+
# whatever you want that returns true in an error condition
|
23
|
+
# end
|
24
|
+
def acts_as_status_bar(options={})
|
25
|
+
attr_accessor :status_bar_id
|
26
|
+
attr_accessor :status_bar
|
27
|
+
extend ActsAsStatusBar::StatusBarBase::SingletonMethods
|
28
|
+
include ActsAsStatusBar::StatusBarBase::InstanceMethods
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
# Singleton methods for the mixin
|
35
|
+
module SingletonMethods
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
#Instance methods for the mixin
|
40
|
+
module InstanceMethods
|
41
|
+
|
42
|
+
def status_bar_init
|
43
|
+
self.status_bar = ActsAsStatusBar::StatusBar.new(:id => self.status_bar_id)
|
44
|
+
self.status_bar_id = self.status_bar.id
|
45
|
+
end
|
46
|
+
|
47
|
+
def status_bar=(sb)
|
48
|
+
@status_bar = sb
|
49
|
+
@status_bar_id = sb.id
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
require 'active_record'
|
62
|
+
ActiveRecord::Base.send :include, ActsAsStatusBar::StatusBarBase
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
module ActsAsStatusBar
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
desc "Install generator for ActsAsStatusBar gem"
|
5
|
+
source_root File.expand_path("../templates", __FILE__)
|
6
|
+
|
7
|
+
def copy_config
|
8
|
+
directory "."
|
9
|
+
end
|
10
|
+
|
11
|
+
#def copy_public
|
12
|
+
# directory "public"
|
13
|
+
#end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1,66 @@
|
|
1
|
+
//ActsAsStatusBar
|
2
|
+
|
3
|
+
var instanceNo = 0;
|
4
|
+
var ActsAsStatusBar = Class.create();
|
5
|
+
ActsAsStatusBar.prototype = {
|
6
|
+
initialize: function(progressBarContainerElementId,progressBarMessageId,progressBarValueId,progressBarElementId, barElementId, initProperties){
|
7
|
+
this.progressBarContainerElement = document.getElementById(progressBarContainerElementId);
|
8
|
+
this.progressMessage = document.getElementById(progressBarMessageId);
|
9
|
+
this.progressValue = document.getElementById(progressBarValueId);
|
10
|
+
this.progressBarElement = document.getElementById(progressBarElementId);
|
11
|
+
this.barElement = document.getElementById(barElementId);
|
12
|
+
if( initProperties != null ){
|
13
|
+
this.frequency = initProperties["frequency"];
|
14
|
+
this.url = initProperties["url"];
|
15
|
+
this.total = initProperties["total"];
|
16
|
+
}else{ this.frequency = 2; }
|
17
|
+
this.value = 1;
|
18
|
+
this.display_value = "";
|
19
|
+
this.display_message = "";
|
20
|
+
this.isFinish = false;
|
21
|
+
this.repaint();
|
22
|
+
this.id = "AjaxProgressBar"+ instanceNo++;
|
23
|
+
window[this.id] = this;
|
24
|
+
},
|
25
|
+
setValue: function(value){ this.value = value; this.repaint(); },
|
26
|
+
|
27
|
+
setDisplayValue: function(display_value, display_message){
|
28
|
+
this.display_value = display_value;
|
29
|
+
this.display_message = display_message;
|
30
|
+
this.repaint();
|
31
|
+
},
|
32
|
+
|
33
|
+
//Update div content on the page
|
34
|
+
repaint: function(){
|
35
|
+
if( this.value >= 0 && this.value <= 100 ){
|
36
|
+
this.barElement.style.width = this.value +"%";
|
37
|
+
this.progressValue.innerHTML = this.display_value;
|
38
|
+
this.progressMessage.innerHTML = this.display_message;
|
39
|
+
}
|
40
|
+
},
|
41
|
+
start: function(){ this.progressBarContainerElement.style.visibility = 'visible'; this.update(); },
|
42
|
+
update: function(){
|
43
|
+
var upThis = this;
|
44
|
+
var ajax = new Ajax.Request(this.url, {
|
45
|
+
method: "get",
|
46
|
+
onSuccess: function(res){ upThis.updateSuccess(res); },
|
47
|
+
onFailure: function(res){ alert("Error: "+ res.status +" "+ res.statusText);}
|
48
|
+
});
|
49
|
+
if(!this.isFinish )
|
50
|
+
{
|
51
|
+
setTimeout("window."+ this.id +".update()", this.frequency*1000);
|
52
|
+
}
|
53
|
+
else
|
54
|
+
{
|
55
|
+
this.progressBarContainerElement.style.visibility = 'hidden';
|
56
|
+
}
|
57
|
+
},
|
58
|
+
updateSuccess: function(res){
|
59
|
+
var value = res.responseXML.getElementsByTagName("value")[0].firstChild.nodeValue;
|
60
|
+
var message = res.responseXML.getElementsByTagName("message")[0].firstChild.nodeValue;
|
61
|
+
var percent = parseInt(res.responseXML.getElementsByTagName("percent")[0].firstChild.nodeValue);
|
62
|
+
this.setValue(percent);
|
63
|
+
this.setDisplayValue(value,message);
|
64
|
+
this.isFinish = percent == 100;
|
65
|
+
}
|
66
|
+
}
|
data/lib/generators/acts_as_status_bar/install/templates/public/stylesheets/acts_as_status_bar.css
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
/* Progress_bar ============================================================== */
|
2
|
+
#acts-as-status-bar-container {
|
3
|
+
width: 500px;
|
4
|
+
height: 70px;
|
5
|
+
background-position: right center;
|
6
|
+
position:absolute;
|
7
|
+
left:30%;
|
8
|
+
top:45%;
|
9
|
+
z-index:10;
|
10
|
+
visibility:hidden;
|
11
|
+
margin:0;
|
12
|
+
padding:10px;
|
13
|
+
background:#EAEBD8;
|
14
|
+
border:3px solid #5970B2;
|
15
|
+
}
|
16
|
+
#acts-as-status-bar-message {
|
17
|
+
|
18
|
+
}
|
19
|
+
#acts-as-status-bar-value {
|
20
|
+
|
21
|
+
}
|
22
|
+
#acts-as-status-bar-progress-bar {
|
23
|
+
width: 400px;
|
24
|
+
height: 19px;
|
25
|
+
background: url(../images/acts_as_status_bar_background.gif);
|
26
|
+
background-position: right center;
|
27
|
+
}
|
28
|
+
#acts-as-status-bar {
|
29
|
+
background: url(../images/acts_as_status_bar_foreground.gif);
|
30
|
+
background-position: right center;
|
31
|
+
width: 0%;
|
32
|
+
height: 100%;
|
33
|
+
}
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: acts_as_status_bar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrea Bignozzi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2013-10-24 00:00:00 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
type: :runtime
|
16
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ~>
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 3.0.15
|
21
|
+
name: rails
|
22
|
+
prerelease: false
|
23
|
+
requirement: *id001
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
type: :runtime
|
26
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
27
|
+
requirements:
|
28
|
+
- &id003
|
29
|
+
- ">="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: "0"
|
32
|
+
name: mysql2
|
33
|
+
prerelease: false
|
34
|
+
requirement: *id002
|
35
|
+
description: Rails StatusBar with ActiveRecord integration, permits dynamic custom output from your model
|
36
|
+
email:
|
37
|
+
- skylord73@gmail.com
|
38
|
+
executables: []
|
39
|
+
|
40
|
+
extensions: []
|
41
|
+
|
42
|
+
extra_rdoc_files: []
|
43
|
+
|
44
|
+
files:
|
45
|
+
- app/controllers/acts_as_status_bar/status_bar_controller.rb
|
46
|
+
- app/helpers/acts_as_status_bar_helper.rb
|
47
|
+
- app/models/acts_as_status_bar/status_bar.rb
|
48
|
+
- app/views/acts_as_status_bar/status_bar/index.html.erb
|
49
|
+
- app/views/acts_as_status_bar/status_bar/show.html.erb
|
50
|
+
- lib/acts_as_status_bar/engine.rb
|
51
|
+
- lib/acts_as_status_bar/exceptions.rb
|
52
|
+
- lib/acts_as_status_bar/status_bar_base.rb
|
53
|
+
- lib/acts_as_status_bar/version.rb
|
54
|
+
- lib/acts_as_status_bar.rb
|
55
|
+
- lib/generators/acts_as_status_bar/install/install_generator.rb
|
56
|
+
- lib/generators/acts_as_status_bar/install/templates/public/images/acts_as_status_bar_background.gif
|
57
|
+
- lib/generators/acts_as_status_bar/install/templates/public/images/acts_as_status_bar_foreground.gif
|
58
|
+
- lib/generators/acts_as_status_bar/install/templates/public/javascripts/acts_as_status_bar_javascript.js
|
59
|
+
- lib/generators/acts_as_status_bar/install/templates/public/stylesheets/acts_as_status_bar.css
|
60
|
+
- config/initializers/acts_as_status_bar.rb
|
61
|
+
- config/locales/custom_errors.it.yml
|
62
|
+
- config/locales/links.it.yml
|
63
|
+
- config/routes.rb
|
64
|
+
- MIT-LICENSE
|
65
|
+
- Rakefile
|
66
|
+
- Gemfile
|
67
|
+
- README.rdoc
|
68
|
+
- CHANGELOG.md
|
69
|
+
homepage:
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
metadata: {}
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- *id003
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- *id003
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.0.10
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Rails StatusBar with ActiveRecord integration
|
92
|
+
test_files: []
|
93
|
+
|