bootbox_crud 0.1.1
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/.gitignore +31 -0
- data/MIT.license +20 -0
- data/README.md +301 -0
- data/app/views/layouts/_bb_alert.html.haml +2 -0
- data/app/views/layouts/_show_link_to.html.haml +5 -0
- data/app/views/layouts/_show_link_to_array.html.haml +6 -0
- data/app/views/layouts/_show_value.html.haml +4 -0
- data/app/views/modals/_alert.js.erb +5 -0
- data/app/views/modals/_create.js.erb +1 -0
- data/app/views/modals/_destroy.js.erb +1 -0
- data/app/views/modals/_form.js.erb +16 -0
- data/app/views/modals/_update.js.erb +1 -0
- data/bootbox_crud.gemspec +28 -0
- data/lib/bootbox_crud.rb +7 -0
- data/lib/bootbox_crud/action_view/helpers.rb +37 -0
- data/lib/bootbox_crud/engine.rb +23 -0
- data/lib/bootbox_crud/version.rb +5 -0
- data/lib/generators/bootbox_crud/install_generator.rb +16 -0
- data/lib/generators/bootbox_crud/templates/README +6 -0
- data/lib/generators/bootbox_crud/templates/app/assets/javascripts/models.js +7 -0
- data/lib/generators/bootbox_crud/templates/config/initializers/simple_form.rb +142 -0
- data/lib/generators/bootbox_crud/templates/config/initializers/simple_form_bootstrap.rb +163 -0
- data/lib/generators/rails/haml_modal_crud/USAGE +15 -0
- data/lib/generators/rails/haml_modal_crud/haml_modal_crud_generator.rb +30 -0
- data/lib/generators/rails/haml_modal_crud/templates/create.js.erb +2 -0
- data/lib/generators/rails/haml_modal_crud/templates/destroy.js.erb +1 -0
- data/lib/generators/rails/haml_modal_crud/templates/update.js.erb +1 -0
- data/lib/generators/rails/modal_crud_route/USAGE +9 -0
- data/lib/generators/rails/modal_crud_route/modal_crud_route_generator.rb +21 -0
- data/lib/generators/rails/modal_crud_route/templates/models.js +7 -0
- data/lib/templates/haml/scaffold/_form.html.haml +12 -0
- data/lib/templates/haml/scaffold/edit.html.haml +2 -0
- data/lib/templates/haml/scaffold/index.html.haml +51 -0
- data/lib/templates/haml/scaffold/new.html.haml +2 -0
- data/lib/templates/haml/scaffold/show.html.haml +7 -0
- data/lib/templates/rails/scaffold_controller/controller.rb +102 -0
- data/vendor/assets/javascripts/bootbox_crud_main.js +6 -0
- data/vendor/assets/javascripts/bootbox_crud_modals.js +206 -0
- data/vendor/assets/javascripts/sortable.js +177 -0
- data/vendor/assets/stylesheets/bootbox_crud.css.scss +25 -0
- data/vendor/assets/stylesheets/bootbox_crud_main.css.scss +2 -0
- data/vendor/assets/stylesheets/sortable-theme-minimal.css +47 -0
- metadata +255 -0
@@ -0,0 +1 @@
|
|
1
|
+
<%%= render partial: 'modals/destroy', locals: { model: @<%= singular_table_name %>, form_path: '<%= plural_table_name %>/form' } %>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%%= render partial: 'modals/update', locals: { model: @<%= singular_table_name %>, form_path: '<%= plural_table_name %>/form' } %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Description:
|
2
|
+
Adds model definition to app/assets/javascripts/models.js for CRUD modals and invokes resource_route generator to add route to routes.rb
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate modal_crud_route Thing name size:integer
|
6
|
+
|
7
|
+
This will create:
|
8
|
+
insert app/assets/javascripts/models.js
|
9
|
+
generate resource_route
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Rails::ModalCrudRouteGenerator < Rails::Generators::NamedBase
|
2
|
+
include Rails::Generators::ResourceHelpers
|
3
|
+
source_root File.expand_path('../templates', __FILE__)
|
4
|
+
|
5
|
+
def add_resource_route
|
6
|
+
if Rails.application.assets.find_asset('models.js').blank?
|
7
|
+
copy_file "models.js", "app/assets/javascripts/models.js"
|
8
|
+
end
|
9
|
+
inject_into_file 'app/assets/javascripts/models.js', after: "//!!! Generator adds after this line, do not delete it !!!\n" do
|
10
|
+
"BBCrud.Models.add('#{name}', '/#{controller_name.underscore}/', '#{name.underscore}');\n"
|
11
|
+
end
|
12
|
+
run_resource_route
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def run_resource_route
|
18
|
+
generate 'resource_route', name
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
.container-fluid
|
2
|
+
= simple_form_for(@<%= singular_table_name %>, remote_form_options) do |f|
|
3
|
+
= f.error_notification
|
4
|
+
= f.error :base, :error_method => :to_sentence
|
5
|
+
|
6
|
+
.form-inputs
|
7
|
+
<%- attributes.each do |attribute| -%>
|
8
|
+
= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %>
|
9
|
+
<%- end -%>
|
10
|
+
|
11
|
+
.form-actions.col-sm-7.col-sm-offset-5
|
12
|
+
= f.button :submit
|
@@ -0,0 +1,51 @@
|
|
1
|
+
.container-fluid
|
2
|
+
%h1 Listing <%= plural_table_name %>
|
3
|
+
|
4
|
+
<% has_name = attributes.find {|a| a.name == 'name'}.present? -%>
|
5
|
+
|
6
|
+
.table_responsive
|
7
|
+
%table.table.table-hover.table-striped.sortable-theme-minimal{data: {sortable: ''}}
|
8
|
+
%thead
|
9
|
+
%tr
|
10
|
+
<% if has_name -%>
|
11
|
+
%th
|
12
|
+
ID
|
13
|
+
%th{data:{sorted: 'true', sorted_direction: 'ascending' }}
|
14
|
+
Name
|
15
|
+
<% else -%>
|
16
|
+
%th{data:{sorted: 'true', sorted_direction: 'ascending' }}
|
17
|
+
ID
|
18
|
+
<% end -%>
|
19
|
+
<% for attribute in attributes -%>
|
20
|
+
<% next if %w{name id}.include? attribute.name -%>
|
21
|
+
%th <%= attribute.human_name %>
|
22
|
+
<% end -%>
|
23
|
+
%th{data:{sortable: 'false'}}
|
24
|
+
|
25
|
+
%tbody
|
26
|
+
- @<%= plural_table_name %>.each do |<%= singular_table_name %>|
|
27
|
+
%tr
|
28
|
+
<% if has_name -%>
|
29
|
+
%td
|
30
|
+
= <%= singular_table_name %>.id
|
31
|
+
%td{data:{value: <%= singular_table_name %>.name.gsub(' ', '').downcase, entity: '<%= singular_table_name.capitalize %>', action: 'show', id: (<%= singular_table_name %>.id) }}
|
32
|
+
= link_to <%= singular_table_name %>.name, '#'
|
33
|
+
<% else -%>
|
34
|
+
%td{data:{ entity: '<%= singular_table_name.capitalize %>', action: 'show', id: (<%= singular_table_name %>.id) }}
|
35
|
+
= link_to <%= singular_table_name %>.id, '#'
|
36
|
+
<% end -%>
|
37
|
+
|
38
|
+
<% for attribute in attributes -%>
|
39
|
+
<% next if %w{name id}.include? attribute.name -%>
|
40
|
+
%td= <%= singular_table_name %>.<%= attribute.name %>
|
41
|
+
<% end -%>
|
42
|
+
%td
|
43
|
+
= link_to '#', :class => 'btn-sm btn-primary', data: { entity: '<%= singular_table_name.capitalize %>', action: 'update', id: (<%= singular_table_name %>.id) } do
|
44
|
+
%i.fa.fa-edit
|
45
|
+
EDIT
|
46
|
+
|
47
|
+
%hr
|
48
|
+
%p
|
49
|
+
= link_to '#', :class => 'btn btn-success', data: { entity: '<%= singular_table_name.capitalize %>', action: 'create' } do
|
50
|
+
%i.fa.fa-plus
|
51
|
+
= 'New <%= human_name %>'
|
@@ -0,0 +1,102 @@
|
|
1
|
+
<% if namespaced? -%>
|
2
|
+
require_dependency "<%= namespaced_file_path %>/application_controller"
|
3
|
+
|
4
|
+
<% end -%>
|
5
|
+
<% module_namespacing do -%>
|
6
|
+
class <%= controller_class_name %>Controller < ApplicationController
|
7
|
+
before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
|
8
|
+
|
9
|
+
# GET <%= route_url %>
|
10
|
+
def index
|
11
|
+
@<%= plural_table_name %> = <%= attributes_names.select { |attr| attr == 'name' }.present? ? "#{class_name}.order('lower(name)').all" : orm_class.all(class_name) %>
|
12
|
+
respond_to do |format|
|
13
|
+
format.html
|
14
|
+
format.json { render json: @<%= plural_table_name %> }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# GET <%= route_url %>/1
|
19
|
+
def show
|
20
|
+
respond_to do |format|
|
21
|
+
format.html { render layout: false }
|
22
|
+
format.json { render json: @<%= singular_table_name %> }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# GET <%= route_url %>/new
|
27
|
+
def new
|
28
|
+
@<%= singular_table_name %> = <%= orm_class.build(class_name) %>
|
29
|
+
respond_to do |format|
|
30
|
+
format.html { render layout: false }
|
31
|
+
format.json { render json: @<%= singular_table_name %> }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# GET <%= route_url %>/1/edit
|
36
|
+
def edit
|
37
|
+
render layout: false
|
38
|
+
end
|
39
|
+
|
40
|
+
# POST <%= route_url %>
|
41
|
+
def create
|
42
|
+
@<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
|
43
|
+
|
44
|
+
respond_to do |format|
|
45
|
+
if @<%= orm_instance.save %>
|
46
|
+
format.html { redirect_to @<%= singular_table_name %> }
|
47
|
+
format.json { render json: @<%= singular_table_name %>, status: :created }
|
48
|
+
format.js
|
49
|
+
else
|
50
|
+
format.html { render :new }
|
51
|
+
format.json { render json: @<%= singular_table_name %>.errors, status: :unprocessable_entity }
|
52
|
+
format.js
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# PATCH/PUT <%= route_url %>/1
|
58
|
+
def update
|
59
|
+
respond_to do |format|
|
60
|
+
if @<%= orm_instance.update("#{singular_table_name}_params") %>
|
61
|
+
format.html { redirect_to @<%= singular_table_name %> }
|
62
|
+
format.json { head :no_content }
|
63
|
+
format.js
|
64
|
+
else
|
65
|
+
format.html { render :edit }
|
66
|
+
format.json { render json: @<%= singular_table_name %>.errors, status: :unprocessable_entity }
|
67
|
+
format.js
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# DELETE <%= route_url %>/1
|
73
|
+
def destroy
|
74
|
+
respond_to do |format|
|
75
|
+
if @<%= orm_instance.destroy %>
|
76
|
+
format.html { redirect_to <%= index_helper %>_url }
|
77
|
+
format.json { head :no_content }
|
78
|
+
format.js
|
79
|
+
else
|
80
|
+
format.html { redirect_to <%= index_helper %>_url }
|
81
|
+
format.json { render json: @<%= singular_table_name %>.errors, status: :forbidden }
|
82
|
+
format.js { render status: :forbidden }
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
# Use callbacks to share common setup or constraints between actions.
|
89
|
+
def set_<%= singular_table_name %>
|
90
|
+
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
|
91
|
+
end
|
92
|
+
|
93
|
+
# Only allow a trusted parameter "white list" through.
|
94
|
+
def <%= "#{singular_table_name}_params" %>
|
95
|
+
<%- if attributes_names.empty? -%>
|
96
|
+
params[:<%= singular_table_name %>]
|
97
|
+
<%- else -%>
|
98
|
+
params.require(:<%= singular_table_name %>).permit(<%= attributes_names.map { |name| ":#{name}" }.join(', ') %>)
|
99
|
+
<%- end -%>
|
100
|
+
end
|
101
|
+
end
|
102
|
+
<% end -%>
|
@@ -0,0 +1,206 @@
|
|
1
|
+
var BBCrud = BBCrud || {};
|
2
|
+
|
3
|
+
BBCrud.Modals = function () {
|
4
|
+
|
5
|
+
var modals = {
|
6
|
+
form: function(id, title, btnLabel, url, exec, timeout, timeoutExec, options) {
|
7
|
+
var buttons = {
|
8
|
+
close: {
|
9
|
+
"label" : "Close"
|
10
|
+
},
|
11
|
+
submit: {
|
12
|
+
"label" : btnLabel,
|
13
|
+
"className" : "btn-success",
|
14
|
+
"callback": function() {
|
15
|
+
if (options.dontSubmit !== true) {
|
16
|
+
$('.bootbox.modal').find('input[type="submit"]').closest('form').submit();
|
17
|
+
}
|
18
|
+
if (timeoutExec !== null && typeof timeoutExec != 'undefined') { setTimeout(timeoutExec, timeout); }
|
19
|
+
return false;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
};
|
23
|
+
if (id !== -1 && options.showDeleteBtn !== false) {
|
24
|
+
$.extend(buttons, {
|
25
|
+
delete: {
|
26
|
+
"label" : "Delete",
|
27
|
+
"className" : "btn-danger",
|
28
|
+
"callback" : function() {
|
29
|
+
modals.delete(id, options.baseUrl);
|
30
|
+
return false;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
})
|
34
|
+
}
|
35
|
+
|
36
|
+
var modal = bootbox.dialog({
|
37
|
+
message : "Loading form...",
|
38
|
+
title : title,
|
39
|
+
backdrop : "static",
|
40
|
+
keyboard : false,
|
41
|
+
show : true,
|
42
|
+
header : title,
|
43
|
+
buttons: buttons
|
44
|
+
});
|
45
|
+
$.get(url, options.data, function(data) {
|
46
|
+
var result = $(data);
|
47
|
+
var content = result.attr('id') === 'content' ? result : result.find('#content');
|
48
|
+
modal.find('.modal-body').html(content);
|
49
|
+
modal.find('.form-actions').hide();
|
50
|
+
if (exec !== null && typeof exec != 'undefined') { exec(); }
|
51
|
+
});
|
52
|
+
},
|
53
|
+
create: function (title, baseUrl, exec, data) {
|
54
|
+
modals.update(-1, title, baseUrl, exec, true, undefined, undefined, data);
|
55
|
+
},
|
56
|
+
update: function (id, title, baseUrl, exec, createMode, timeout, timeoutExec, data) {
|
57
|
+
if (typeof id === 'object') id = id.id;
|
58
|
+
var primaryBtnLabel = createMode ? 'Create' : 'Update';
|
59
|
+
var url = createMode ? baseUrl + 'new' : baseUrl + id + '/edit';
|
60
|
+
modals.form(id, title, primaryBtnLabel, url, exec, timeout, timeoutExec, { baseUrl: baseUrl, data: data });
|
61
|
+
},
|
62
|
+
other: function (id, title, baseUrl, actionName, exec, timeout, timeoutExec, data) {
|
63
|
+
if (typeof id === 'object') id = id.id;
|
64
|
+
var url = baseUrl + id + '/' + actionName;
|
65
|
+
modals.form(id, title, actionName.charAt(0).toUpperCase() + actionName.slice(1), url, exec, timeout, timeoutExec, { baseUrl: baseUrl, data: data, showDeleteBtn: false });
|
66
|
+
},
|
67
|
+
delete: function (id, baseUrl, exec) {
|
68
|
+
bootbox.confirm('Are you sure?', function(result) {
|
69
|
+
if (result === true) {
|
70
|
+
$.ajax({
|
71
|
+
url: baseUrl + id,
|
72
|
+
contentType: "application/javascript",
|
73
|
+
dataType: 'script',
|
74
|
+
type: 'DELETE'
|
75
|
+
}).success(function () {
|
76
|
+
if (typeof exec != 'undefined') { exec(); }
|
77
|
+
VM.Alert.show('Deleted');
|
78
|
+
}).error(function () {
|
79
|
+
VM.Alert.show('Something went wrong!');
|
80
|
+
});
|
81
|
+
}
|
82
|
+
});
|
83
|
+
},
|
84
|
+
show: function(id, title, baseUrl) {
|
85
|
+
var modal = bootbox.dialog({
|
86
|
+
message : "Loading form...",
|
87
|
+
title : title,
|
88
|
+
backdrop : "static",
|
89
|
+
keyboard : false,
|
90
|
+
show : true,
|
91
|
+
header : title,
|
92
|
+
buttons: {
|
93
|
+
close: {
|
94
|
+
"label" : "Close"
|
95
|
+
}
|
96
|
+
}
|
97
|
+
});
|
98
|
+
$.get(baseUrl + id, function(data) {
|
99
|
+
handleResponse(data);
|
100
|
+
}).error(function (response) {
|
101
|
+
if (response.status === 200) {
|
102
|
+
handleResponse(response.responseText);
|
103
|
+
}
|
104
|
+
console.log(response);
|
105
|
+
});
|
106
|
+
function handleResponse(data) {
|
107
|
+
var result = $(data);
|
108
|
+
var content = result.attr('id') === 'content' ? result : result.find('#content');
|
109
|
+
modal.find('.modal-body').html(content);
|
110
|
+
}
|
111
|
+
},
|
112
|
+
// general click handler displaying create or update form in modal
|
113
|
+
initBtnHandler: function() {
|
114
|
+
$(document).on('click', '[data-entity]', function() {
|
115
|
+
var link = $(this);
|
116
|
+
var args = $.extend({}, link.data());
|
117
|
+
delete args['entity'];
|
118
|
+
delete args['action'];
|
119
|
+
BBCrud[link.data('entity')][link.data('action')].call(link, args);
|
120
|
+
return false;
|
121
|
+
});
|
122
|
+
}
|
123
|
+
};
|
124
|
+
return modals;
|
125
|
+
}();
|
126
|
+
|
127
|
+
BBCrud.Modals.initBtnHandler();
|
128
|
+
|
129
|
+
BBCrud.Models = function () {
|
130
|
+
function defineModelActions(modelName, actions) {
|
131
|
+
if (typeof BBCrud[modelName] === 'undefined') {
|
132
|
+
BBCrud[modelName] = actions;
|
133
|
+
} else {
|
134
|
+
$.extend(BBCrud[modelName], actions);
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
var models = {
|
139
|
+
add: function(modelName, url, titleName) {
|
140
|
+
var modelCRUD = function () {
|
141
|
+
var baseUrl = url;
|
142
|
+
|
143
|
+
var methods = {
|
144
|
+
create: function (data) {
|
145
|
+
BBCrud.Modals.create('Create ' + titleName, baseUrl, null, data);
|
146
|
+
},
|
147
|
+
update: function (data) {
|
148
|
+
BBCrud.Modals.update(data.id, 'Edit ' + titleName, baseUrl);
|
149
|
+
},
|
150
|
+
show: function (data) {
|
151
|
+
BBCrud.Modals.show(data.id, titleName.charAt(0).toUpperCase() + titleName.slice(1) + ' detail', baseUrl);
|
152
|
+
}
|
153
|
+
};
|
154
|
+
return methods;
|
155
|
+
}();
|
156
|
+
|
157
|
+
defineModelActions(modelName, modelCRUD);
|
158
|
+
},
|
159
|
+
addAction: function(modelName, url, titleName, actionName) {
|
160
|
+
var action = function () {
|
161
|
+
var baseUrl = url;
|
162
|
+
var modelAction = {};
|
163
|
+
modelAction[actionName] = function (data) {
|
164
|
+
BBCrud.Modals.other(data.id, actionName.charAt(0).toUpperCase() + actionName.slice(1) + ' ' + titleName,
|
165
|
+
baseUrl, actionName, null, 0, null, data);
|
166
|
+
};
|
167
|
+
return modelAction;
|
168
|
+
}();
|
169
|
+
defineModelActions(modelName, action);
|
170
|
+
}
|
171
|
+
|
172
|
+
};
|
173
|
+
return models;
|
174
|
+
}();
|
175
|
+
|
176
|
+
|
177
|
+
BBCrud.Alert = function() {
|
178
|
+
var elem,
|
179
|
+
hideHandler,
|
180
|
+
alert = {};
|
181
|
+
|
182
|
+
alert.init = function(options) {
|
183
|
+
elem = $(options.selector);
|
184
|
+
};
|
185
|
+
|
186
|
+
alert.show = function(text) {
|
187
|
+
clearTimeout(hideHandler);
|
188
|
+
|
189
|
+
elem.find("span").html(text);
|
190
|
+
elem.fadeIn();
|
191
|
+
|
192
|
+
hideHandler = setTimeout(function() {
|
193
|
+
alert.hide();
|
194
|
+
}, 4000);
|
195
|
+
};
|
196
|
+
|
197
|
+
alert.hide = function() {
|
198
|
+
elem.fadeOut();
|
199
|
+
};
|
200
|
+
|
201
|
+
return alert;
|
202
|
+
}();
|
203
|
+
|
204
|
+
$(function() {
|
205
|
+
BBCrud.Alert.init({selector: '.bb-alert'});
|
206
|
+
});
|