dashboard-rails 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/MIT-LICENSE +20 -0
- data/README.md +198 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/dashboard-rails.js +119 -0
- data/app/assets/stylesheets/dashboard-rails.css +40 -0
- data/app/controllers/application_widget.rb +56 -0
- data/app/controllers/dashboard-rails/application_controller.rb +5 -0
- data/app/controllers/dashboard-rails/widgets_controller.rb +46 -0
- data/app/helpers/dashboard-rails/application_helper.rb +20 -0
- data/app/models/dashboard-rails/user.rb +9 -0
- data/app/views/dashboard-rails/widgets/_widgets_list.html.erb +24 -0
- data/app/views/dashboard-rails/widgets/index.html.erb +25 -0
- data/config/initializers/assets.rb +1 -0
- data/config/routes.rb +19 -0
- data/lib/dashboard-rails.rb +8 -0
- data/lib/dashboard-rails/engine.rb +6 -0
- data/lib/dashboard-rails/singleton_helper.rb +19 -0
- data/lib/dashboard-rails/version.rb +3 -0
- data/lib/dashboard-rails/widget.rb +23 -0
- data/lib/generators/dashboard-rails/install_generator.rb +26 -0
- data/lib/generators/dashboard-rails/view_generator.rb +11 -0
- data/lib/generators/dashboard-rails/widget_generator.rb +25 -0
- data/lib/generators/templates/create_taxweb_widgets_users.rb +18 -0
- data/lib/generators/templates/generic_widget.erb +12 -0
- data/lib/generators/templates/generic_widget.html.erb +2 -0
- metadata +89 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 3a86427f3df1221fe3e57a76b2018089abc3264a47ab1f8ca71619cf547ae7cd
|
4
|
+
data.tar.gz: 56714713af95f13099f3721281b037a59c42a4e68dd2b55ae3c28adbc04a80d8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5c5c522b76dfa3d830dec7da01b35a7f67cd3331596fe34460a59c5f981fba735a5f077a9bf345cfef977f0058791ef21a2a8ac85b50f6edb5653060709797f2
|
7
|
+
data.tar.gz: 3129075c90183adc2ed987134bd164d87c2fb049878bfea9b7b9eef79d5074b32cd98a4cf76fd161e86e01a54bd1185e89016c47791cf273135df19b8cc6d613
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 Daniel de Carvalho Passarini
|
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.md
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
# Dashboard Rails
|
2
|
+
|
3
|
+
This Gem was designed to help create a dashboard page where the user can configure the diplayed widgets.
|
4
|
+
|
5
|
+
The user selects the widgets that he would like to display and save this information to the database so next time he
|
6
|
+
loads the application the desired widgets will be displayed.
|
7
|
+
|
8
|
+
For the moment we require a model *User* and the method *current_user*
|
9
|
+
|
10
|
+
## TODO
|
11
|
+
|
12
|
+
- Configure page layout (number and size of columns)
|
13
|
+
- Define widgets position in the page using drag & drop
|
14
|
+
- Define the auto refrsesh interval (today fixed in 60 seconds)
|
15
|
+
|
16
|
+
### Installation
|
17
|
+
|
18
|
+
Add the gem to the Gemfile
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
gem 'dashboard-rails'
|
22
|
+
```
|
23
|
+
run bundle install
|
24
|
+
|
25
|
+
```sh
|
26
|
+
$ bundle install
|
27
|
+
```
|
28
|
+
|
29
|
+
Generate some required files using the provided install generator
|
30
|
+
```sh
|
31
|
+
$ rails g dashboard-rails:install
|
32
|
+
```
|
33
|
+
|
34
|
+
A migration will be created the table to keep the dashboard settings per user
|
35
|
+
|
36
|
+
```sh
|
37
|
+
$ rake db:migrate
|
38
|
+
```
|
39
|
+
|
40
|
+
Add the provide css to **application.css**
|
41
|
+
```js
|
42
|
+
*= require dashboard-rails
|
43
|
+
```
|
44
|
+
|
45
|
+
Add the provide js to **application.js**
|
46
|
+
```js
|
47
|
+
//= require dashboard-rails
|
48
|
+
```
|
49
|
+
|
50
|
+
### Dashboard Page
|
51
|
+
|
52
|
+
Create you dashboard page, just add the following helper to your page
|
53
|
+
|
54
|
+
```html
|
55
|
+
<%= dashboard_view %>
|
56
|
+
```
|
57
|
+
|
58
|
+
Or, you can generate the dashboard viwes in your project to customize it
|
59
|
+
|
60
|
+
```sh
|
61
|
+
rails g dashboard-rails:view
|
62
|
+
```
|
63
|
+
|
64
|
+
### the Dashboard Configuration Page
|
65
|
+
|
66
|
+
Create you confi dashboard page, just add the following helper to your page
|
67
|
+
|
68
|
+
```html
|
69
|
+
<%= config_dashboard_view %>
|
70
|
+
```
|
71
|
+
|
72
|
+
|
73
|
+
<%= config_dashboard_path %>
|
74
|
+
|
75
|
+
|
76
|
+
Or, you can generate the dashboard viwes in your project to customize it
|
77
|
+
|
78
|
+
```sh
|
79
|
+
rails g dashboard-rails:view
|
80
|
+
```
|
81
|
+
|
82
|
+
|
83
|
+
### Widget Generators
|
84
|
+
|
85
|
+
To create the widget skeleton use:
|
86
|
+
```sh
|
87
|
+
rails generate dashboard-rails:widget #{widget_name}
|
88
|
+
```
|
89
|
+
|
90
|
+
|
91
|
+
All widgets are create under the `app/widgets` folder
|
92
|
+
|
93
|
+
|
94
|
+
## How to create a Widget
|
95
|
+
|
96
|
+
For example:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
class ExemploWidget < ApplicationWidget
|
100
|
+
|
101
|
+
name! 'Widget Exemplo'
|
102
|
+
description! 'Esse Widget é apenas um exemplo'
|
103
|
+
|
104
|
+
description! :executar, 'Essa ação é um outro exemplo'
|
105
|
+
def executar
|
106
|
+
@ano = params[:ano] || Date.today.year
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
**Cada ação será uma visão diferente do widget. Exemplo: Calendário Mensal, Calendário Semanal, você terá o widget Calendários e as ações mensal e semanal.**
|
113
|
+
|
114
|
+
Parametros utilizados como documentação para exibir na lista de configuração de Widgets x Usuários.
|
115
|
+
|
116
|
+
- **name!** identifica o nome (título) do Widget.
|
117
|
+
- **description!** é a descrição (função) do Widget.
|
118
|
+
- **description! :acao** é a descrição (função) da ação daquele Widget.
|
119
|
+
|
120
|
+
O conteúdo visual do Widget (VIEW) seguirá o padrão do rails estando na pasta `app/views/widgets/nome_do_widget/nome_da_acao.html.erb`:
|
121
|
+
|
122
|
+
*app/widgets/exemplo/executar.html.erb*
|
123
|
+
```html
|
124
|
+
<div>
|
125
|
+
Meu widget de exemplo retornou o ano: <%= @ano %>
|
126
|
+
<%= link_to 'Próximo Ano e recarregar Widget', widget_path(ano: (@ano +1), widget_ajax: true %>
|
127
|
+
<%= link_to 'Ir para página externa normalmente', 'http://www.google.com.br/' %>
|
128
|
+
</div>
|
129
|
+
```
|
130
|
+
|
131
|
+
Para direcionar o usuário para configurar seus widgets, faça um link para `dashboard-rails_path`
|
132
|
+
```html
|
133
|
+
<%= link_to 'Gerenciar Widgets', dashboard-rails_path %>
|
134
|
+
|
135
|
+
<%= link_to 'Gerenciar Widgets', dashboard_settings_path %>
|
136
|
+
|
137
|
+
|
138
|
+
```
|
139
|
+
|
140
|
+
### Helpers
|
141
|
+
|
142
|
+
Para verificar a permissão de acesso ao Widget pelo usuário atual (current_user), utilize o helper `user_can_widget?(nome_widget, ação)`:
|
143
|
+
```html
|
144
|
+
<% if show_widget?(:calendarios, :mensal) %>
|
145
|
+
|
146
|
+
<% end %>
|
147
|
+
```
|
148
|
+
|
149
|
+
Para adicionar um widget use o helper `add_widget(nome_widget, ação)`:
|
150
|
+
```html
|
151
|
+
<%= add_widget(:calendarios, :mensal) %>
|
152
|
+
```
|
153
|
+
|
154
|
+
Para referenciar um path do widget de forma automática utilize `widget_path`. Esse helper espera que haja definido em params *widget_name* e *widget_name* :
|
155
|
+
```html
|
156
|
+
<!-- ESPERA QUE EXISTA params[:widget_name] e params[:widget_action] definidos -->
|
157
|
+
<%= widget_path(novo_atributo: 'novo valor') %>
|
158
|
+
```
|
159
|
+
|
160
|
+
Para criar um link que faça uma chamada ajax e retorne o resultado HTML no próprio widget (como mudar de página por exemplo):
|
161
|
+
```html
|
162
|
+
<%= link_to 'Link Remoto', widget_path({ano: @ano}), widget_ajax: true %>
|
163
|
+
```
|
164
|
+
|
165
|
+
Formulário para reescrever o plugin baseado em algum parametro:
|
166
|
+
```html
|
167
|
+
<%= form_tag widget_path, method: :get, widget_ajax: true do %>
|
168
|
+
|
169
|
+
<% end %>
|
170
|
+
```
|
171
|
+
|
172
|
+
### Atualização Manual do Widget
|
173
|
+
|
174
|
+
Para atualizar um widget de forma manual você precisa recuperar o elemento do widget com a classe `widget` e chamar o método `widget_load_from_ajax`:
|
175
|
+
```javascript
|
176
|
+
var elemento = $('.widget:first')
|
177
|
+
//Esse elemento precisa ser um elemento jQuery
|
178
|
+
widget_load_from_ajax(elemento);
|
179
|
+
```
|
180
|
+
|
181
|
+
### Recursos AJAX (automáticos)
|
182
|
+
|
183
|
+
Toda vez que um elemento com classe `widget-user-control` for alterado será disparado um evento AJAX que irá localizar as configuraçẽos do usuário na view de configuração e retornará um HTML com o conteúdo no elemento `.widgets_list .list`. Caso não seja informado esse item, o primeiro formulário com a classe `widget_config` será passado como elemento destino.
|
184
|
+
|
185
|
+
Todo formulário em widget que tenha a atributo `widget_ajax` terá seu evento "submit" enviado por AJAX, retornando o resultado no próprio container do widget, portanto é esperado um retorno HTML.
|
186
|
+
|
187
|
+
Todo elemento com atributo `data-url` tentará criar um contador com tempo igual ao atributo `data-tick` para atualização automática do widget.
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
# Developers
|
192
|
+
|
193
|
+
To publish this gem use:
|
194
|
+
|
195
|
+
```sh
|
196
|
+
gem push dashboard-rails-0.1.0.gem
|
197
|
+
|
198
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
# require 'rdoc/task'
|
8
|
+
# RDoc::Task.new(:rdoc) do |rdoc|
|
9
|
+
# rdoc.rdoc_dir = 'rdoc'
|
10
|
+
# rdoc.title = 'DashboardRails'
|
11
|
+
# rdoc.options << '--line-numbers'
|
12
|
+
# rdoc.rdoc_files.include('README.rdoc')
|
13
|
+
# rdoc.rdoc_files.include('lib/**/*.rb')
|
14
|
+
# end
|
15
|
+
|
16
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
17
|
+
load 'rails/tasks/engine.rake'
|
18
|
+
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
# require 'rake/testtask'
|
25
|
+
#
|
26
|
+
# Rake::TestTask.new(:test) do |t|
|
27
|
+
# t.libs << 'lib'
|
28
|
+
# t.libs << 'test'
|
29
|
+
# t.pattern = 'test/**/*_test.rb'
|
30
|
+
# t.verbose = false
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
#
|
34
|
+
# task default: :test
|
@@ -0,0 +1,119 @@
|
|
1
|
+
function hasParams(url) {
|
2
|
+
var regex = new RegExp(/\?\w+\=/);
|
3
|
+
regex.test(url);
|
4
|
+
}
|
5
|
+
|
6
|
+
function widget_load_from_ajax($el, new_url) {
|
7
|
+
if ($el!=undefined && $el!=null && $el instanceof jQuery) {
|
8
|
+
var dest_url = (new_url != undefined ? new_url : $el.attr('data-url'));
|
9
|
+
// var query_string = window.location.search.substring(1);
|
10
|
+
// if (query_string!=undefined && query_string!=null) {
|
11
|
+
// dest_url = dest_url + (hasParams(dest_url) ? '&' : '?') + query_string;
|
12
|
+
// }
|
13
|
+
$.ajax({
|
14
|
+
url: dest_url,
|
15
|
+
method: 'get',
|
16
|
+
dataType: 'html',
|
17
|
+
beforeSend: function (jqXHR, settings) {
|
18
|
+
widget_loading($el);
|
19
|
+
},
|
20
|
+
success: function (data, textStatus, jqXHR) {
|
21
|
+
//console.log('sucesso');
|
22
|
+
$el.html(data);
|
23
|
+
if (new_url != undefined) {
|
24
|
+
$el.attr('data-url', new_url);
|
25
|
+
}
|
26
|
+
},
|
27
|
+
error: function (jqXHR, textStatus, errorThrown) {
|
28
|
+
console.log('erro',jqXHR);
|
29
|
+
},
|
30
|
+
complete: function (jqXHR, textStatus) {
|
31
|
+
widget_loading($el, false);
|
32
|
+
}
|
33
|
+
});
|
34
|
+
} else {
|
35
|
+
alert('Erro! Objeto Widget Não encontrado!');
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
function widget_load_user_config(user_id, elDestBlock) {
|
40
|
+
var $elDestBlock = $('.widget_config');
|
41
|
+
var $elDestList = $elDestBlock.find('.widgets_list .list');
|
42
|
+
$.ajax({
|
43
|
+
url: '/dashboard-rails/widgets/user/'+user_id,
|
44
|
+
method: 'get',
|
45
|
+
dataType: 'html',
|
46
|
+
beforeSend: function (jqXHR, settings) {
|
47
|
+
widget_loading($elDestBlock);
|
48
|
+
},
|
49
|
+
success: function (data, textStatus, jqXHR) {
|
50
|
+
// console.log(data);
|
51
|
+
$elDestList.html(data);
|
52
|
+
},
|
53
|
+
error: function (jqXHR, textStatus, errorThrown) {
|
54
|
+
console.log('erro',jqXHR);
|
55
|
+
},
|
56
|
+
complete: function (jqXHR, textStatus) {
|
57
|
+
widget_loading($elDestBlock, false);
|
58
|
+
}
|
59
|
+
});
|
60
|
+
}
|
61
|
+
|
62
|
+
function widget_loading(element, state) {
|
63
|
+
var $el = $(element);
|
64
|
+
if (state==undefined) state=true;
|
65
|
+
|
66
|
+
if (state==true) {
|
67
|
+
$("<div class='widget_loading'><span>Carregando...</span></div>").appendTo($el);
|
68
|
+
} else {
|
69
|
+
$el.find('.widget_loading').fadeOut('fast', function(){
|
70
|
+
$(this).remove();
|
71
|
+
});
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
//FORMS
|
76
|
+
$(document).on('submit','form[widget_ajax]', function(ev) {
|
77
|
+
ev.preventDefault();
|
78
|
+
var widget_element = $(this).closest('.widget'),
|
79
|
+
atributos = $(this).serialize(),
|
80
|
+
form_url = $(this).attr('action');
|
81
|
+
if (atributos!=undefined && atributos!=null) {
|
82
|
+
form_url = form_url + (hasParams(form_url) ? '&' : '?') + atributos;
|
83
|
+
}
|
84
|
+
widget_load_from_ajax(widget_element, form_url);
|
85
|
+
});
|
86
|
+
|
87
|
+
//LINKS
|
88
|
+
$(document).on('click','a[widget_ajax]', function(ev) {
|
89
|
+
ev.preventDefault();
|
90
|
+
var widget_element = $(this).closest('.widget');
|
91
|
+
var new_url = $(this).attr('href');
|
92
|
+
widget_load_from_ajax(widget_element, new_url);
|
93
|
+
});
|
94
|
+
|
95
|
+
//USER CONTORL
|
96
|
+
$(document).on('change','.widget-user-control', function(ev) {
|
97
|
+
var $el = $(this);
|
98
|
+
widget_load_user_config($el.val());
|
99
|
+
});
|
100
|
+
|
101
|
+
$(document).on('ready',function(){
|
102
|
+
|
103
|
+
$('.widget[data-url]').each(function(i,el) {
|
104
|
+
var $el = $(el);
|
105
|
+
var delay_in_ms = $el.attr('data-tick') || 0;
|
106
|
+
widget_load_from_ajax($el);
|
107
|
+
if (delay_in_ms > 0) {
|
108
|
+
window.setInterval(function(){ widget_load_from_ajax($el); }, delay_in_ms);
|
109
|
+
}
|
110
|
+
});
|
111
|
+
|
112
|
+
//INIT
|
113
|
+
if ($('.widget-user-control').length > 0) {
|
114
|
+
$('.widget-user-control').trigger('change');
|
115
|
+
} else {
|
116
|
+
widget_load_user_config('');
|
117
|
+
}
|
118
|
+
|
119
|
+
});
|
@@ -0,0 +1,40 @@
|
|
1
|
+
.widget {
|
2
|
+
position: relative;
|
3
|
+
min-height: 50px;
|
4
|
+
}
|
5
|
+
|
6
|
+
.widgets_list ul {
|
7
|
+
padding-left: 0px;
|
8
|
+
}
|
9
|
+
|
10
|
+
.widgets_list ul li {
|
11
|
+
list-style: none;
|
12
|
+
}
|
13
|
+
|
14
|
+
.widget_loading {
|
15
|
+
position: absolute;
|
16
|
+
width: 100%;
|
17
|
+
height: 100%;
|
18
|
+
min-height: 50px;
|
19
|
+
top: 0;
|
20
|
+
left: 0;
|
21
|
+
background-color: #ccc;
|
22
|
+
opacity: 0.5;
|
23
|
+
border-radius: 5px;
|
24
|
+
cursor: not-allowed;
|
25
|
+
}
|
26
|
+
|
27
|
+
.widget_loading span {
|
28
|
+
background-color: #FFF;
|
29
|
+
font-size: 18px;
|
30
|
+
color: #000;
|
31
|
+
padding: 5px;
|
32
|
+
font-weight: bold;
|
33
|
+
margin: 0;
|
34
|
+
border-radius: 5px;
|
35
|
+
position: absolute;
|
36
|
+
top: 50%;
|
37
|
+
left: 50%;
|
38
|
+
margin-right: -50%;
|
39
|
+
transform: translate(-50%, -50%);
|
40
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
class ApplicationWidget < ::ApplicationController
|
2
|
+
include SingletonHelper
|
3
|
+
|
4
|
+
attr_singleton :refresh_interval, 0
|
5
|
+
|
6
|
+
def initialize(request)
|
7
|
+
self.request = request
|
8
|
+
end
|
9
|
+
|
10
|
+
def render_template(view_file=nil, *args)
|
11
|
+
args << {template: view_file}
|
12
|
+
render_to_string *args
|
13
|
+
end
|
14
|
+
|
15
|
+
def view(view_file=nil, klass=nil)
|
16
|
+
class_caller = klass || (caller[0].match(/(\b\w+)\.rb/)[1] rescue '')
|
17
|
+
action_caller = view_file || (caller[0].match(/`(.*)'/)[1] rescue '')
|
18
|
+
view_file = "widgets/#{class_caller.to_s.sub('_widget','')}/#{action_caller}" unless lookup_context.find_all(view_file).any?
|
19
|
+
instance_variable_set(:@view_file, view_file)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.name?
|
23
|
+
instance_variable_defined?(:@widget_name) ? instance_variable_get(:@widget_name) : ''
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.name!(value)
|
27
|
+
# define_singleton_method(:widget_name) {value}
|
28
|
+
instance_variable_set(:@widget_name, value)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.description?(attr=nil)
|
32
|
+
attr='widget' if attr.nil?
|
33
|
+
instance_variable_defined?("@description_#{attr}") ? instance_variable_get("@description_#{attr}") : ''
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.description!(*args)
|
37
|
+
if args.size == 1
|
38
|
+
instance_variable_set(:@description_widget, args[0])
|
39
|
+
elsif args.size == 2
|
40
|
+
instance_variable_set("@description_#{args[0]}", args[1])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.widgets
|
45
|
+
# ApplicationWidget.descendants.map do |klass| #Não estava carregando no primeiro load...
|
46
|
+
Dir["#{Rails.root}/app/widgets/*.rb"].map do |file_path|
|
47
|
+
file_name = File.basename(file_path, ".rb")
|
48
|
+
klass = Object.const_get file_name.classify
|
49
|
+
actions = klass.instance_methods(false).map do |action|
|
50
|
+
{name: action, description: klass.description?(action)}
|
51
|
+
end
|
52
|
+
{code: klass.to_s.tableize.sub('_widgets',''), name: klass.name?, description: klass.description?, actions: actions}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_dependency "dashboard-rails/application_controller"
|
2
|
+
|
3
|
+
module DashboardRails
|
4
|
+
class WidgetsController < ApplicationController
|
5
|
+
|
6
|
+
def load
|
7
|
+
widget = DashboardRails::Widget.new(params[:widget_name], self.request)
|
8
|
+
content = widget.html(params[:widget_action])
|
9
|
+
rescue Exception => e
|
10
|
+
content = e.message
|
11
|
+
ensure
|
12
|
+
render html: content, layout: false
|
13
|
+
end
|
14
|
+
|
15
|
+
def user
|
16
|
+
user_id = params[:id]
|
17
|
+
@widgets_code = DashboardRails::User.where(user_id: user_id).pluck(:widget, :action).map{|r| "#{r[0]}_#{r[1]}"}
|
18
|
+
render partial: 'widgets_list'
|
19
|
+
end
|
20
|
+
|
21
|
+
def index
|
22
|
+
@user_id = params[:user_id] || current_user.id
|
23
|
+
end
|
24
|
+
|
25
|
+
def save
|
26
|
+
user_id = params[:user_id]
|
27
|
+
widgets = params[:widgets]
|
28
|
+
widget_name_user = []
|
29
|
+
action_user = []
|
30
|
+
if user_id.present? && widgets.present?
|
31
|
+
widgets.each do |widget|
|
32
|
+
widget_name, action = widget.split('|')
|
33
|
+
if widget_name && action
|
34
|
+
widget_name_user << widget_name
|
35
|
+
action_user << action
|
36
|
+
DashboardRails::User.find_or_create_by(widget: widget_name, action: action, user_id: user_id)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
DashboardRails::User.where(user_id: user_id).where.not(widget: widget_name_user, action: action_user).destroy_all
|
41
|
+
flash[:success] = 'Alterações foram salvas com sucesso!'
|
42
|
+
redirect_to dashboard-rails_path(user_id: user_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DashboardRails
|
2
|
+
module ApplicationHelper
|
3
|
+
|
4
|
+
def add_widget(widget_name, widget_action)
|
5
|
+
widget = DashboardRails::Widget.new(widget_name, self.request)
|
6
|
+
content_tag(:div, '', id: "widget_#{widget_name}_#{widget_action}", class: 'widget', data: {tick: widget.param(:refresh_interval), url: dashboard-rails_load_path(widget_name: widget_name, widget_action: widget_action)})
|
7
|
+
end
|
8
|
+
|
9
|
+
def widget_path(args=nil)
|
10
|
+
my_params = {widget_name: params[:widget_name], widget_action: params[:widget_action]}
|
11
|
+
my_params.merge!(args) if args.present?
|
12
|
+
dashboard-rails_load_path(my_params)
|
13
|
+
end
|
14
|
+
|
15
|
+
def user_can_widget?(widget_name, widget_action)
|
16
|
+
DashboardRails::User.where(user_id: current_user.id, widget: widget_name, action: widget_action).count > 0
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<% ApplicationWidget.widgets.each do |widget| %>
|
2
|
+
<ul>
|
3
|
+
<li>
|
4
|
+
<b><%= widget[:name] %></b>
|
5
|
+
<br><span class="help-block"><%= widget[:description] %></span>
|
6
|
+
<ul>
|
7
|
+
<% widget[:actions].each do |action| %>
|
8
|
+
<% widget_code = "#{widget[:code]}_#{action[:name]}" %>
|
9
|
+
<li>
|
10
|
+
<div class="checkbox">
|
11
|
+
<%= label_tag widget_code do %>
|
12
|
+
<%= check_box_tag 'widgets[]', "#{widget[:code]}|#{action[:name]}", @widgets_code.include?(widget_code), {id: widget_code} %>
|
13
|
+
<b><%= action[:name].to_s.humanize %></b>
|
14
|
+
<% if action[:description].present? %>
|
15
|
+
<br><span class="help-block"><%= action[:description] %></span>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</li>
|
20
|
+
<% end %>
|
21
|
+
</ul>
|
22
|
+
</li>
|
23
|
+
</ul>
|
24
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col-md-12">
|
3
|
+
<div class="panel panel-default">
|
4
|
+
<div class="panel-heading">
|
5
|
+
<div class="panel-title">Selecione os Widgets que deseja utilizar:</div>
|
6
|
+
</div>
|
7
|
+
<div class="panel-body">
|
8
|
+
<%= form_tag(dashboard-rails_save_path, method: :put, class: 'widget_config') do %>
|
9
|
+
|
10
|
+
<div class="form-group">
|
11
|
+
<label class="control-label">Usuário:</label>
|
12
|
+
<%= select_tag :user_id, options_from_collection_for_select(User.all, :id, :email, current_user.id), include_blank: false, class: 'form-control widget-user-control' %>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<fieldset class="widgets_list">
|
16
|
+
<legend>Widgets</legend>
|
17
|
+
<div class="list"></div>
|
18
|
+
</fieldset>
|
19
|
+
|
20
|
+
<%= submit_tag "Salvar", class: 'btn btn-success' %>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
Rails.application.config.assets.precompile += %w( dashboard-rails.js dashboard-rails.css )
|
data/config/routes.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
|
3
|
+
|
4
|
+
namespace :dashboard-rails do
|
5
|
+
|
6
|
+
get 'widgets/load/:widget_name/:widget_action', to: 'widgets#load', as: 'load'
|
7
|
+
get 'widgets/user(/:id)', to: 'widgets#user', as: 'user'
|
8
|
+
get 'widgets', to: 'widgets#index', as: ''
|
9
|
+
put 'widgets/save', to: 'widgets#save', as: 'save'
|
10
|
+
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SingletonHelper
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
base.extend ClassMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
def attr_singleton(attr, default=nil)
|
9
|
+
define_singleton_method attr do |value=nil|
|
10
|
+
if value.present?
|
11
|
+
instance_variable_set("@#{attr}", value)
|
12
|
+
else
|
13
|
+
instance_variable_get("@#{attr}") || default
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DashboardRails
|
2
|
+
class Widget
|
3
|
+
|
4
|
+
attr_accessor :widget, :klass
|
5
|
+
|
6
|
+
def initialize(widget_name, request)
|
7
|
+
@klass_name = widget_name
|
8
|
+
@klass = Object.const_get "#{@klass_name}_widget".classify
|
9
|
+
@widget = @klass.new(request)
|
10
|
+
end
|
11
|
+
|
12
|
+
def param(param)
|
13
|
+
@klass.send(param)
|
14
|
+
end
|
15
|
+
|
16
|
+
def html(action)
|
17
|
+
content = @widget.send(action)
|
18
|
+
view_file = (@widget.instance_variables.include?(:@view_file) ? @widget.instance_variable_get(:@view_file) : @widget.view(action, @klass_name))
|
19
|
+
@widget.render_template(view_file) # rescue content
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
module DashboardRails
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../../templates", __FILE__)
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
|
9
|
+
class_option :orm
|
10
|
+
desc 'Instalando Taxweb Widgets'
|
11
|
+
|
12
|
+
desc 'Criando Migrations'
|
13
|
+
def self.next_migration_number(path)
|
14
|
+
unless @prev_migration_nr
|
15
|
+
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
16
|
+
else
|
17
|
+
@prev_migration_nr += 1
|
18
|
+
end
|
19
|
+
@prev_migration_nr.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_migration_file
|
23
|
+
migration_template 'create_dashboard-rails_users.rb', 'db/migrate/create_dashboard-rails_users.rb'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module DashboardRails
|
4
|
+
class ViewGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path("../../../../app/views/dashboard-rails", __FILE__)
|
6
|
+
|
7
|
+
def copy_views
|
8
|
+
directory 'widgets', 'app/views/dashboard-rails/widgets'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module DashboardRails
|
4
|
+
class WidgetGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path("../../templates", __FILE__)
|
6
|
+
|
7
|
+
def generate_widget
|
8
|
+
@widget_name = file_name.classify
|
9
|
+
view_dir = "app/views/widgets/#{widget_name_file}"
|
10
|
+
|
11
|
+
template "generic_widget.erb", File.join('app/widgets', "#{widget_name_file}_widget.rb")
|
12
|
+
|
13
|
+
if self.behavior == :revoke && Dir.exists?(view_dir)
|
14
|
+
require 'fileutils'
|
15
|
+
FileUtils.rm_rf(view_dir)
|
16
|
+
elsif self.behavior == :invoke
|
17
|
+
copy_file "generic_widget.html.erb", File.join(view_dir, 'exemplo.html.erb')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def widget_name_file
|
22
|
+
file_name.underscore
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateDashboardSettings < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def up
|
4
|
+
unless table_exists?(:dashboard_settings)
|
5
|
+
create_table :dashboard_settings do |t|
|
6
|
+
t.references :user, index: true, foreign_key: false
|
7
|
+
t.string :widget
|
8
|
+
t.string :action
|
9
|
+
t.index [:widget, :action]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def down
|
15
|
+
drop_table :dashboard_settings if table_exists? :dashboard_settings
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class <%= @widget_name %>Widget < ApplicationWidget
|
2
|
+
|
3
|
+
name! "<%= @widget_name %>"
|
4
|
+
description! "O Widget <%= @widget_name %> tem como função..."
|
5
|
+
#refresh_interval 60000 #60 segundos para refresh automático
|
6
|
+
|
7
|
+
description! :exemplo, 'Essa ação é um exemplo'
|
8
|
+
def exemplo
|
9
|
+
@data = Date.today
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dashboard-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- TaxWeb
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-03-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5'
|
33
|
+
description: Gerenciamento de Widgets para Dashboard
|
34
|
+
email:
|
35
|
+
- produto@taxweb.com.br
|
36
|
+
executables: []
|
37
|
+
extensions: []
|
38
|
+
extra_rdoc_files: []
|
39
|
+
files:
|
40
|
+
- MIT-LICENSE
|
41
|
+
- README.md
|
42
|
+
- Rakefile
|
43
|
+
- app/assets/javascripts/dashboard-rails.js
|
44
|
+
- app/assets/stylesheets/dashboard-rails.css
|
45
|
+
- app/controllers/application_widget.rb
|
46
|
+
- app/controllers/dashboard-rails/application_controller.rb
|
47
|
+
- app/controllers/dashboard-rails/widgets_controller.rb
|
48
|
+
- app/helpers/dashboard-rails/application_helper.rb
|
49
|
+
- app/models/dashboard-rails/user.rb
|
50
|
+
- app/views/dashboard-rails/widgets/_widgets_list.html.erb
|
51
|
+
- app/views/dashboard-rails/widgets/index.html.erb
|
52
|
+
- config/initializers/assets.rb
|
53
|
+
- config/routes.rb
|
54
|
+
- lib/dashboard-rails.rb
|
55
|
+
- lib/dashboard-rails/engine.rb
|
56
|
+
- lib/dashboard-rails/singleton_helper.rb
|
57
|
+
- lib/dashboard-rails/version.rb
|
58
|
+
- lib/dashboard-rails/widget.rb
|
59
|
+
- lib/generators/dashboard-rails/install_generator.rb
|
60
|
+
- lib/generators/dashboard-rails/view_generator.rb
|
61
|
+
- lib/generators/dashboard-rails/widget_generator.rb
|
62
|
+
- lib/generators/templates/create_taxweb_widgets_users.rb
|
63
|
+
- lib/generators/templates/generic_widget.erb
|
64
|
+
- lib/generators/templates/generic_widget.html.erb
|
65
|
+
homepage: http://www.taxweb.com.br
|
66
|
+
licenses:
|
67
|
+
- MIT
|
68
|
+
metadata: {}
|
69
|
+
post_install_message:
|
70
|
+
rdoc_options: []
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
requirements: []
|
84
|
+
rubyforge_project:
|
85
|
+
rubygems_version: 2.7.8
|
86
|
+
signing_key:
|
87
|
+
specification_version: 4
|
88
|
+
summary: Gerenciamento de Widgets para Dashboard
|
89
|
+
test_files: []
|