slash_admin 0.1.0 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +38 -12
- data/app/assets/images/slash_admin/favicon.png +0 -0
- data/app/assets/images/slash_admin/logo.png +0 -0
- data/app/assets/javascripts/slash_admin/application.js +33 -25
- data/app/assets/stylesheets/slash_admin/application.scss +271 -146
- data/app/assets/stylesheets/slash_admin/colors.scss +16 -13
- data/app/controllers/slash_admin/models_controller.rb +166 -32
- data/app/controllers/slash_admin/security/sessions_controller.rb +1 -1
- data/app/controllers/slash_admin/selectize_controller.rb +21 -1
- data/app/helpers/slash_admin/application_helper.rb +45 -4
- data/app/helpers/slash_admin/widgets_helper.rb +1 -0
- data/app/views/layouts/slash_admin/application.html.erb +1 -1
- data/app/views/slash_admin/base/_data_belongs_to.html.erb +14 -16
- data/app/views/slash_admin/base/_data_list.html.erb +118 -121
- data/app/views/slash_admin/base/_data_nestable.html.erb +2 -2
- data/app/views/slash_admin/base/_data_new.html.erb +4 -1
- data/app/views/slash_admin/base/_filters.html.erb +63 -55
- data/app/views/slash_admin/base/index.html.erb +3 -3
- data/app/views/slash_admin/custom_fields/_google_map.html.erb +14 -11
- data/app/views/slash_admin/custom_fields/_select.html.erb +5 -1
- data/app/views/slash_admin/custom_fields/_timezone.html.erb +2 -0
- data/app/views/slash_admin/dashboard/widgets/_statistic_progress_tile.html.erb +1 -1
- data/app/views/slash_admin/fields/_belongs_to.html.erb +2 -2
- data/app/views/slash_admin/fields/_carrierwave.html.erb +107 -10
- data/app/views/slash_admin/fields/_has_many.html.erb +2 -2
- data/app/views/slash_admin/fields/_has_one.html.erb +9 -24
- data/app/views/slash_admin/fields/_json.html.erb +1 -1
- data/app/views/slash_admin/fields/_jsonb.html.erb +14 -0
- data/app/views/slash_admin/{custom_fields → fields}/_nested_belongs_to.html.erb +11 -10
- data/app/views/slash_admin/fields/_nested_has_one.html.erb +23 -0
- data/app/views/slash_admin/security/sessions/new.html.erb +6 -3
- data/app/views/slash_admin/shared/_batch_actions.html.erb +1 -1
- data/app/views/slash_admin/shared/_header.html.erb +2 -3
- data/app/views/slash_admin/shared/_menu.html.erb +33 -30
- data/app/views/slash_admin/shared/_new_form_buttons.html.erb +2 -2
- data/config/initializers/validators.rb +4 -0
- data/config/locales/{slash_admin.en.yml → en.yml} +3 -0
- data/config/locales/{slash_admin.fr.yml → fr.yml} +4 -1
- data/lib/batch_translation.rb +1 -1
- data/lib/generators/slash_admin/override_admin/override_admin_generator.rb +1 -0
- data/lib/generators/slash_admin/override_session/templates/session.erb +2 -2
- data/lib/slash_admin.rb +1 -3
- data/lib/slash_admin/version.rb +1 -1
- data/vendor/assets/javascripts/bootstrap-datepicker.fr.min.js +1 -0
- data/vendor/assets/javascripts/bootstrap-datepicker.min.js +8 -0
- data/vendor/assets/stylesheets/bootstrap-datepicker.min.css +7 -0
- metadata +19 -69
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
<div class="row">
|
5
5
|
<div class="col-sm-12">
|
6
|
-
<div class="portlet">
|
6
|
+
<div class="portlet" id="portlet-<%= @model_class.model_name.human(count: 2).parameterize.underscore.downcase %>">
|
7
7
|
<div class="portlet-title">
|
8
8
|
<div class="caption">
|
9
9
|
<% if @is_nestable %>
|
@@ -27,8 +27,8 @@
|
|
27
27
|
<i class="fa fa-angle-down fix-dropdown"></i>
|
28
28
|
</a>
|
29
29
|
<div class="dropdown-menu">
|
30
|
-
<a class="dropdown-item" href="<%= polymorphic_url([:slash_admin, @model_class], format: 'csv') %>"><%= t('slash_admin.view.export_csv') %></a>
|
31
|
-
<a class="dropdown-item" href="<%= polymorphic_url([:slash_admin, @model_class], format: 'xls') %>"><%= t('slash_admin.view.export_xls') %></a>
|
30
|
+
<a class="dropdown-item" href="<%= polymorphic_url([:slash_admin, @model_class], filters: params[:filters].present? ? params[:filters].permit! : [], format: 'csv') %>"><%= t('slash_admin.view.export_csv') %></a>
|
31
|
+
<!-- <a class="dropdown-item" href="<%= polymorphic_url([:slash_admin, @model_class], format: 'xls') %>"><%= t('slash_admin.view.export_xls') %></a> -->
|
32
32
|
</div>
|
33
33
|
</div>
|
34
34
|
</div>
|
@@ -1,24 +1,27 @@
|
|
1
1
|
<%= f.label a.keys.first, class: "form-control-label #{required?(f.object, a).present? ? 'required' : ''}" %>
|
2
2
|
<input type="text" class="form-control" id="<%= f.options[:html][:id] %>_search" />
|
3
3
|
<script async defer
|
4
|
-
src="https://maps.googleapis.com/maps/api/js?key=<%= a[a.keys.first.to_sym][:google_api_key] %>&libraries=places&callback=initMap">
|
4
|
+
src="https://maps.googleapis.com/maps/api/js?key=<%= a[a.keys.first.to_sym][:google_api_key] %>&libraries=places&callback=initMap&language=<%= I18n.locale %>">
|
5
5
|
</script>
|
6
6
|
<div class="google-map-container" id="<%= f.options[:html][:id] %>_map" style="width:100%; min-height:350px"></div>
|
7
|
-
<%= f.hidden_field a.keys.first, class: 'form-control', id: f.options[:html][:id] + '_' + a.keys.first.to_s, required: required?(f.object, a) %>
|
8
|
-
|
7
|
+
<%= f.hidden_field a.keys.first, class: 'form-control', id: f.options[:html][:id] + '_' + a.keys.first.to_s, required: required?(f.object, a), value: f.object.send(a.keys.first.to_s).to_json %>
|
9
8
|
<script type="text/javascript">
|
10
9
|
var map = {};
|
11
10
|
var markers;
|
12
11
|
function initMap() {
|
13
12
|
markers = [];
|
14
13
|
var myOptions = {
|
15
|
-
zoom: <%= a[a.keys.first.to_sym][:
|
14
|
+
zoom: <%= a[a.keys.first.to_sym][:default_zoom] %>,
|
16
15
|
center: new google.maps.LatLng(<%= a[a.keys.first.to_sym][:default_latitude] %>, <%= a[a.keys.first.to_sym][:default_longitude] %>),
|
17
16
|
mapTypeId: google.maps.MapTypeId.ROADMAP,
|
18
17
|
scrollwheel: false
|
19
18
|
};
|
20
19
|
map = new google.maps.Map(document.getElementById("<%= f.options[:html][:id] %>_map"), myOptions);
|
21
|
-
|
20
|
+
<% if f.object.send(a.keys.first.to_s).present? %>
|
21
|
+
document.getElementById("<%= f.options[:html][:id] %>_search").value = "<%= f.object.send(a.keys.first.to_s)['formatted_address'] %>";
|
22
|
+
<% else %>
|
23
|
+
document.getElementById("<%= f.options[:html][:id] %>_search").value = '';
|
24
|
+
<% end %>
|
22
25
|
initializeAutocomplete('<%= f.options[:html][:id] %>_search');
|
23
26
|
function initializeAutocomplete(id) {
|
24
27
|
var element = document.getElementById(id);
|
@@ -31,15 +34,15 @@
|
|
31
34
|
}
|
32
35
|
function onPlaceChanged() {
|
33
36
|
cleanAllMarkers();
|
34
|
-
var final_datas = {}
|
37
|
+
var final_datas = {};
|
35
38
|
var place = this.getPlace();
|
36
|
-
if (place.length
|
39
|
+
if (place.length === 0) {
|
37
40
|
return;
|
38
41
|
}
|
39
42
|
var location = place.geometry.location;
|
40
43
|
final_datas.location = {
|
41
|
-
|
42
|
-
|
44
|
+
lat: location.lat(),
|
45
|
+
lng: location.lng()
|
43
46
|
};
|
44
47
|
final_datas.formatted_address = place.formatted_address;
|
45
48
|
for (var i in place.address_components) {
|
@@ -56,11 +59,11 @@
|
|
56
59
|
var json = JSON.parse(document.getElementById("<%= f.options[:html][:id] + '_' + a.keys.first.to_s %>").value);
|
57
60
|
if (json.location) {
|
58
61
|
var marker = new google.maps.Marker({
|
59
|
-
position: new google.maps.LatLng(json.location.
|
62
|
+
position: new google.maps.LatLng(json.location.lat, json.location.lng),
|
60
63
|
map: map
|
61
64
|
});
|
62
65
|
markers.push(marker);
|
63
|
-
map.setCenter(new google.maps.LatLng(json.location.
|
66
|
+
map.setCenter(new google.maps.LatLng(json.location.lat, json.location.lng));
|
64
67
|
}
|
65
68
|
}
|
66
69
|
}
|
@@ -1,2 +1,6 @@
|
|
1
1
|
<%= f.label a.keys.first, class: "form-control-label #{required?(f.object, a) ? 'required' : ''}" %>
|
2
|
-
|
2
|
+
<% if a[a.keys.first][:multiple].present? && a[a.keys.first][:multiple] == true %>
|
3
|
+
<%= f.select(a.keys.first, a[a.keys.first][:choices], { include_blank: a[a.keys.first][:include_blank], required: required?(f.object, a) }, class: 'selectize-multiple', multiple: true) %>
|
4
|
+
<% else %>
|
5
|
+
<%= f.select(a.keys.first, a[a.keys.first][:choices], { include_blank: a[a.keys.first][:include_blank], required: required?(f.object, a) }, class: 'selectize-single') %>
|
6
|
+
<% end %>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<div class="display">
|
3
3
|
<div class="number">
|
4
4
|
<h3 class="font-green-sharp">
|
5
|
-
<span
|
5
|
+
<span><%= options[:number] %></span><!--
|
6
6
|
--><% if options[:currency].present? %><small><%= options[:currency] %></small><% end %>
|
7
7
|
</h3>
|
8
8
|
<small><%= options[:title] %></small>
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<%= f.label a, class: "form-control-label #{required?(f.object, a).present? ? 'required' : ''}" %>
|
2
2
|
<%= f.collection_select a.to_s + '_id',
|
3
|
-
class_name_from_association(f.object, a).constantize.all.limit(20), :id, object_label(class_name_from_association(f.object, a)),
|
3
|
+
class_name_from_association(f.object, a).constantize.all.order(f.object.send(a).present? ? "CASE WHEN id = #{f.object.send(a).try(:id)} THEN 1 ELSE 0 END DESC" : "id DESC").limit(20), :id, object_label(class_name_from_association(f.object, a)),
|
4
4
|
{
|
5
5
|
prompt: t('slash_admin.view.select_model', model_name: class_name_from_association(f.object, a).constantize.model_name.human.downcase),
|
6
6
|
},
|
7
7
|
'data-model': class_name_from_association(f.object, a).constantize.model_name.to_s.underscore,
|
8
8
|
'data-fields': "SlashAdmin::Models::#{class_name_from_association(f.object, a).classify.pluralize}Controller".constantize.new.autocomplete_params.join(' '),
|
9
|
-
class: 'selectize-model-single', required: required?(f.object, a).present? %>
|
9
|
+
class: 'selectize-model-single', required: required?(f.object, a).present? %>
|
@@ -1,15 +1,112 @@
|
|
1
1
|
<%= f.label a.to_sym, class: "form-control-label #{required?(f.object, a).present? ? 'required' : ''}" %>
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
3
|
+
<% if f.object.send(a).is_a? Array %>
|
4
|
+
<% multiple_files = true %>
|
5
|
+
<% else %>
|
6
|
+
<% multiple_files = false %>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<div class="row row-end">
|
10
|
+
<div class="col-3">
|
11
|
+
<% if multiple_files %>
|
12
|
+
<% f.object.send(a).each_with_index do |file, i| %>
|
13
|
+
<% extension = file.try(:extension).try(:downcase) || file.try(:format).try(:downcase) || file.try(:file).try(:extension) %>
|
14
|
+
<% if extension.present? %>
|
15
|
+
<% if %w{jpg png jpeg gif bmp}.include?(extension) %>
|
16
|
+
<% if file.try(:url).present? %>
|
17
|
+
<a href="#" class="image-link-modal" data-toggle="modal" data-target="#imageModal_<%= f.object.class.name + '_' + a + '_' + i.to_s %>" data-src="<%= file.url %>">
|
18
|
+
<div class="block cover-image" style="background: url(<%= file.url %>) no-repeat center center;">
|
19
|
+
<div class="image-overlay">
|
20
|
+
<i class="fa-2x icon-magnifier icon-zoom-image"></i>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
</a>
|
24
|
+
<div id="imageModal_<%= f.object.class.name + '_' + a + '_' + i.to_s %>" class="modal">
|
25
|
+
<div class="modal-dialog modal-xl">
|
26
|
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
27
|
+
<span aria-hidden="true">×</span>
|
28
|
+
</button>
|
29
|
+
<img class="modal-content img-fluid" id="image_container_<%= f.object.class.name + '_' + a + '_' + i.to_s %>"/>
|
30
|
+
</div>
|
31
|
+
</div>
|
32
|
+
<script type="text/javascript">
|
33
|
+
var excluder_<%= f.object.class.name + '_' + a + '_' + i.to_s %> = "<%= f.object.class.name + '_' + a + '_' + i.to_s %>";
|
34
|
+
var target_<%= f.object.class.name + '_' + a + '_' + i.to_s %> = "imageModal_" + excluder_<%= f.object.class.name + '_' + a + '_' + i.to_s %>;
|
35
|
+
$('a[data-target="#'+ target_<%= f.object.class.name + '_' + a + '_' + i.to_s %> +'"]').on('click', function(e) {
|
36
|
+
e.preventDefault();
|
37
|
+
|
38
|
+
var container = $('#image_container_' + excluder_<%= f.object.class.name + '_' + a + '_' + i.to_s %>);
|
39
|
+
container.attr('src', '');
|
40
|
+
|
41
|
+
var src = $(this).attr('data-src');
|
42
|
+
|
43
|
+
container.attr('src', src);
|
44
|
+
});
|
45
|
+
</script>
|
46
|
+
<% else %>
|
47
|
+
<a href="<%= file %>" target="_blank" class="remote-asset-link"><%= file.url %></a>
|
48
|
+
<% end %>
|
49
|
+
<% end %>
|
50
|
+
<% else %>
|
51
|
+
<%= t('slash_admin.view.no_image') %>
|
52
|
+
<% end %>
|
53
|
+
<% end %>
|
54
|
+
<% else %>
|
55
|
+
<% extension = f.object.send(a).file.try(:extension).try(:downcase) || f.object.send(a).file.try(:format).try(:downcase) || f.object.send(a).file.try(:file).try(:extension) %>
|
56
|
+
<% if extension.present? %>
|
57
|
+
<% if %w{jpg png jpeg gif bmp}.include?(extension) %>
|
58
|
+
<% if f.object.send(a).try(:url).present? %>
|
59
|
+
<a href="#" class="image-link-modal" data-toggle="modal" data-target="#imageModal_<%= f.object.class.name + '_' + a.to_s %>" data-src="<%= f.object.send(a) %>">
|
60
|
+
<div class="block cover-image" style="background: url(<%= f.object.send(a) %>) no-repeat center center;">
|
61
|
+
<div class="image-overlay">
|
62
|
+
<i class="fa-2x icon-magnifier icon-zoom-image"></i>
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
</a>
|
66
|
+
<div id="imageModal_<%= f.object.class.name + '_' + a.to_s %>" class="modal">
|
67
|
+
<div class="modal-dialog modal-xl">
|
68
|
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
69
|
+
<span aria-hidden="true">×</span>
|
70
|
+
</button>
|
71
|
+
<img class="modal-content img-fluid" id="image_container_<%= f.object.class.name + '_' + a.to_s %>"/>
|
72
|
+
</div>
|
73
|
+
</div>
|
74
|
+
<script type="text/javascript">
|
75
|
+
var excluder_<%= f.object.class.name + '_' + a.to_s %> = "<%= f.object.class.name + '_' + a.to_s %>";
|
76
|
+
var target_<%= f.object.class.name + '_' + a.to_s %> = "imageModal_" + excluder_<%= f.object.class.name + '_' + a.to_s %>;
|
77
|
+
$('a[data-target="#'+ target_<%= f.object.class.name + '_' + a.to_s %> +'"]').on('click', function(e) {
|
78
|
+
e.preventDefault();
|
79
|
+
|
80
|
+
var container = $('#image_container_' + excluder_<%= f.object.class.name + '_' + a.to_s %>);
|
81
|
+
container.attr('src', '');
|
82
|
+
|
83
|
+
var src = $(this).attr('data-src');
|
84
|
+
|
85
|
+
container.attr('src', src);
|
86
|
+
});
|
87
|
+
</script>
|
88
|
+
<% end %>
|
89
|
+
<% else %>
|
90
|
+
<a href="<%= f.object.send(a) %>" target="_blank" class="remote-asset-link"><%= f.object.send(a) %></a>
|
91
|
+
<% end %>
|
92
|
+
<% else %>
|
93
|
+
<%= t('slash_admin.view.no_image') %>
|
94
|
+
<% end %>
|
95
|
+
<% end %>
|
96
|
+
</div>
|
97
|
+
<div class="col-9">
|
98
|
+
<%= f.hidden_field (a.to_s + '_cache').to_sym %>
|
99
|
+
<%= f.file_field a, multiple: multiple_files %>
|
100
|
+
</div>
|
10
101
|
</div>
|
11
102
|
|
12
|
-
<%
|
13
|
-
|
14
|
-
|
103
|
+
<% unless multiple_files %>
|
104
|
+
<% if f.object.send(a).try(:url).present? && required?(f.object, a).blank? %>
|
105
|
+
<div class="form-check image-delete">
|
106
|
+
<%= f.check_box ('remove_' + a.to_s).to_sym, class: 'form-check-input' %>
|
107
|
+
<label class="form-check-label" for="<%= f.object.model_name.param_key + '_remove_' + a.to_s %>">
|
108
|
+
<%= t('slash_admin.view.delete_image') %>
|
109
|
+
</label>
|
110
|
+
</div>
|
111
|
+
<% end %>
|
15
112
|
<% end %>
|
@@ -1,11 +1,11 @@
|
|
1
1
|
<%= f.label a, class: "form-control-label #{required?(f.object, a) ? 'required' : ''}" %>
|
2
2
|
<%= f.collection_select "#{a.to_s.singularize}_ids",
|
3
|
-
class_name_from_association(f.object, a).
|
3
|
+
class_name_from_association(f.object, a).constantize.all.order(f.object.send(a).present? ? "CASE WHEN id IN(#{f.object.send(a).pluck(:id).join(',')}) THEN 1 ELSE 0 END DESC" : "id DESC").limit(20), :id,
|
4
4
|
object_label(class_name_from_association(f.object, a)),
|
5
5
|
{include_blank: true},
|
6
6
|
{
|
7
7
|
class: 'selectize-model-multiple',
|
8
|
-
multiple:
|
8
|
+
multiple: true,
|
9
9
|
'data-model': class_name_from_association(f.object, a).constantize.model_name.to_s.underscore,
|
10
10
|
'data-fields': "SlashAdmin::Models::#{class_name_from_association(f.object, a).classify.pluralize}Controller".constantize.new.autocomplete_params.join(' '),
|
11
11
|
required: required?(f.object, a)
|
@@ -1,24 +1,9 @@
|
|
1
|
-
<%= f.label a, class:
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
<% params_assoc = "SlashAdmin::Models::#{class_name_from_association(f.object, a).pluralize}Controller".constantize.new.create_params(from: @model_class).each %>
|
11
|
-
<% else %>
|
12
|
-
<% params_assoc = "SlashAdmin::Models::#{a.to_s.classify.pluralize}Controller".constantize.new.create_params(from: @model_class).each %>
|
13
|
-
<% end %>
|
14
|
-
<% else %>
|
15
|
-
<% if a.is_a?(Hash) %>
|
16
|
-
<% params_assoc = "SlashAdmin::Models::#{class_name_from_association(f.object, a).pluralize}Controller".constantize.new.update_params(from: @model_class).each %>
|
17
|
-
<% else %>
|
18
|
-
<% params_assoc = "SlashAdmin::Models::#{a.to_s.classify.pluralize}Controller".constantize.new.update_params(from: @model_class).each %>
|
19
|
-
<% end %>
|
20
|
-
<% end %>
|
21
|
-
<% params_assoc.each do |attribute| %>
|
22
|
-
<%= render 'slash_admin/fields/form_group', f: association_form, a: attribute %>
|
23
|
-
<% end %>
|
24
|
-
<% end %>
|
1
|
+
<%= f.label a, class: "form-control-label #{required?(f.object, a).present? ? 'required' : ''}" %>
|
2
|
+
<%= f.select a.to_s,
|
3
|
+
class_name_from_association(f.object, a).constantize.all.order(f.object.send(a).present? ? "CASE WHEN id = #{f.object.send(a).try(:id)} THEN 1 ELSE 0 END DESC" : "id DESC").limit(20).collect { |assoc| [assoc.send(object_label(class_name_from_association(f.object, a))), assoc.id] },
|
4
|
+
{
|
5
|
+
prompt: t('slash_admin.view.select_model', model_name: class_name_from_association(f.object, a).constantize.model_name.human.downcase),
|
6
|
+
},
|
7
|
+
'data-model': class_name_from_association(f.object, a).constantize.model_name.to_s.underscore,
|
8
|
+
'data-fields': "SlashAdmin::Models::#{class_name_from_association(f.object, a).classify.pluralize}Controller".constantize.new.autocomplete_params.join(' '),
|
9
|
+
class: 'selectize-model-single', required: required?(f.object, a).present? %>
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<%= f.label a, class: "form-control-label #{required?(f.object, a) ? 'required' : ''}"%>
|
2
|
-
<%= f.text_area a, class: "form-control #{'jsonarea_' + f.object.class.to_s + '_' + a.to_s}", required: required?(f.object, a) %>
|
2
|
+
<%= f.text_area a, class: "form-control #{'jsonarea_' + f.object.class.to_s + '_' + a.to_s}", required: required?(f.object, a), value: f.object.send(a).to_json %>
|
3
3
|
|
4
4
|
<script src="https://rawgithub.com/zaach/jsonlint/79b553fb65c192add9066da64043458981b3972b/lib/jsonlint.js"></script>
|
5
5
|
<script type="text/javascript">
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<%= f.label a, class: "form-control-label #{required?(f.object, a) ? 'required' : ''}"%>
|
2
|
+
<%= f.text_area a, class: "form-control #{'jsonarea_' + f.object.class.to_s + '_' + a.to_s}", required: required?(f.object, a) %>
|
3
|
+
|
4
|
+
<script src="https://rawgithub.com/zaach/jsonlint/79b553fb65c192add9066da64043458981b3972b/lib/jsonlint.js"></script>
|
5
|
+
<script type="text/javascript">
|
6
|
+
var jsonarea_<%= f.object.class.to_s + '_' + a.to_s %> = document.getElementsByClassName("jsonarea_<%= f.object.class.to_s + '_' + a.to_s %>")[0];
|
7
|
+
var editor_jsonarea_<%= f.object.class.to_s + '_' + a.to_s %> = CodeMirror.fromTextArea(jsonarea_<%= f.object.class.to_s + '_' + a.to_s %>, {
|
8
|
+
lineNumbers: true,
|
9
|
+
theme: 'relax-seti',
|
10
|
+
mode: "application/json",
|
11
|
+
gutters: ["CodeMirror-lint-markers"],
|
12
|
+
lint: true
|
13
|
+
});
|
14
|
+
</script>
|
@@ -1,24 +1,24 @@
|
|
1
|
-
<%= f.label a
|
2
|
-
<%= f.collection_select a.
|
3
|
-
class_name_from_association(f.object, a).constantize.all.limit(20), :id, object_label(a),
|
1
|
+
<%= f.label a, class: "form-control-label #{required?(f.object, a).present? ? 'required' : ''}" %>
|
2
|
+
<%= f.collection_select a.to_s + '_id',
|
3
|
+
class_name_from_association(f.object, a).constantize.all.order(f.object.send(a).present? ? "CASE WHEN id = #{f.object.send(a).try(:id)} THEN 1 ELSE 0 END DESC" : "id DESC").limit(20), :id, object_label(a),
|
4
4
|
{
|
5
5
|
prompt: t('slash_admin.view.select_model', model_name: class_name_from_association(f.object, a).constantize.model_name.human.downcase),
|
6
6
|
},
|
7
7
|
'data-model': class_name_from_association(f.object, a).constantize.model_name.to_s.underscore,
|
8
|
-
'data-fields': "SlashAdmin::Models::#{a.
|
9
|
-
class: "selectize-model-single #{a.
|
8
|
+
'data-fields': "SlashAdmin::Models::#{a.to_s.classify.pluralize}Controller".constantize.new.autocomplete_params.join(' '),
|
9
|
+
class: "selectize-model-single #{a.to_s}_id", required: required?(f.object, a).present? %>
|
10
10
|
|
11
|
-
<a href="#" class="add-belongs-to" style="font-size: .9em;"><%= t('slash_admin.view.add', class_name_from_association(f.object, a).constantize.model_name.human.downcase) %></a>
|
11
|
+
<a href="#" class="add-belongs-to" style="font-size: .9em;"><%= t('slash_admin.view.add', model_name: class_name_from_association(f.object, a).constantize.model_name.human.downcase) %></a>
|
12
12
|
|
13
13
|
<script type="text/javascript">
|
14
14
|
$(function() {
|
15
15
|
$('.add-belongs-to').on('click', function(e) {
|
16
16
|
e.preventDefault();
|
17
17
|
$('.modal-belongs-to').html();
|
18
|
-
$('.modal-belongs-to').html("<%= escape_javascript(render 'slash_admin/base/data_belongs_to', a: a) %>");
|
18
|
+
$('.modal-belongs-to').html("<%= escape_javascript(render 'slash_admin/base/data_belongs_to', f: f, a: a) %>");
|
19
19
|
$('.modal-belongs-to').modal('show');
|
20
20
|
|
21
|
-
var id = "form#new_<%= a.
|
21
|
+
var id = "form#new_<%= a.to_s.singularize %>";
|
22
22
|
|
23
23
|
function closeModals() {
|
24
24
|
$(".modal").modal("hide");
|
@@ -45,8 +45,9 @@ class: "selectize-model-single #{a.keys.first.to_s}_id", required: required?(f.o
|
|
45
45
|
toastr.success("<%= t('slash_admin.view.create_success', model_name: class_name_from_association(f.object, a).constantize.model_name.human) %>");
|
46
46
|
$(id).trigger("reset");
|
47
47
|
closeModals();
|
48
|
-
var select = $('.<%= a.
|
49
|
-
select.addOption({value: data.id, text: data.
|
48
|
+
var select = $('.<%= a.to_s + '_id' %>')[0].selectize;
|
49
|
+
select.addOption({value: data.id, text: data.name});
|
50
|
+
select.refreshOption();
|
50
51
|
select.addItem(data.id);
|
51
52
|
}
|
52
53
|
});
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<%= f.label a, class: 'form-control-label label-has-one' %>
|
2
|
+
|
3
|
+
<% if f.object.send(a).blank? %>
|
4
|
+
<% f.object.send("#{a.to_s}=", a.to_s.classify.constantize.new) %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<%= f.fields_for a do |association_form| %>
|
8
|
+
<% if f.object.id.blank? %>
|
9
|
+
<% method = 'create_params' %>
|
10
|
+
<% else %>
|
11
|
+
<% method = 'update_params' %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<% if a.is_a?(Hash) %>
|
15
|
+
<% params_assoc = "SlashAdmin::Models::#{class_name_from_association(f.object, a).pluralize}Controller".constantize.new.send(method, from: @model_class) %>
|
16
|
+
<% else %>
|
17
|
+
<% params_assoc = "SlashAdmin::Models::#{a.to_s.classify.pluralize}Controller".constantize.new.send(method, from: @model_class) %>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<% params_assoc.each do |attribute| %>
|
21
|
+
<%= render 'slash_admin/fields/form_group', f: association_form, a: attribute %>
|
22
|
+
<% end %>
|
23
|
+
<% end %>
|
@@ -1,20 +1,23 @@
|
|
1
1
|
<div class="container-fluid container-fluid-admin bckg-dark">
|
2
|
-
<div class="login-form
|
2
|
+
<div class="login-form">
|
3
3
|
<div class="row">
|
4
4
|
<div class="col-sm-12 content bckg-dark-light">
|
5
5
|
<h2 class="text-center title-login"><%= t('slash_admin.view.administration') %></h2>
|
6
|
+
<div align="center">
|
7
|
+
<img src="<%= asset_path('slash_admin/logo.png') %>" class="img-fluid" style="max-width: 250px;"/>
|
8
|
+
</div>
|
6
9
|
<%= form_for(:admin, url: '') do |f| %>
|
7
10
|
<span class="failed-login">
|
8
11
|
<%= @error_messages %>
|
9
12
|
</span>
|
10
13
|
<div class="input-group">
|
11
|
-
<span class="input-group-
|
14
|
+
<span class="input-group-prepend">
|
12
15
|
<i class="fa fa-user"></i>
|
13
16
|
</span>
|
14
17
|
<%= f.text_field :login, required: false, autofocus: true, label: false, placeholder: t('slash_admin.view.username'), class: 'form-control' %>
|
15
18
|
</div>
|
16
19
|
<div class="input-group">
|
17
|
-
<span class="input-group-
|
20
|
+
<span class="input-group-prepend">
|
18
21
|
<i class="fa fa-lock"></i>
|
19
22
|
</span>
|
20
23
|
<%= f.password_field :password, required: false, label: false, placeholder: t('slash_admin.view.password'), class: 'form-control' %>
|
@@ -18,18 +18,17 @@
|
|
18
18
|
<img src="data:image/png;base64,<%= current_admin.identicon %>" class="rounded-circle"/>
|
19
19
|
<% end %>
|
20
20
|
<span class=""><%= current_admin.login %></span>
|
21
|
-
<!--<i class="fa fa-angle-down"></i>-->
|
22
21
|
</a>
|
23
22
|
</li>
|
24
23
|
|
25
24
|
<li class="nav-item">
|
26
|
-
<a class="nav-link" href="/" title="
|
25
|
+
<a class="nav-link" href="/" title="<%= t('slash_admin.view.website_homepage') %>" target="_blank">
|
27
26
|
<i class="icon-screen-desktop"></i>
|
28
27
|
</a>
|
29
28
|
</li>
|
30
29
|
|
31
30
|
<li class="nav-item">
|
32
|
-
<a class="nav-link" href="<%= slash_admin.logout_url %>" title="
|
31
|
+
<a class="nav-link" href="<%= slash_admin.logout_url %>" title="<%= t('slash_admin.view.sign_out') %>">
|
33
32
|
<i class="icon-logout"></i>
|
34
33
|
</a>
|
35
34
|
</li>
|