acts_as_status_bar 1.0.0
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.
- 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
|
+
|