slash_admin 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +95 -0
  3. data/app/assets/config/relax_admin_manifest.js +2 -0
  4. data/app/assets/images/slash_admin/en.png +0 -0
  5. data/app/assets/images/slash_admin/favicon.png +0 -0
  6. data/app/assets/images/slash_admin/fr.png +0 -0
  7. data/app/assets/javascripts/slash_admin/application.js +344 -0
  8. data/app/assets/javascripts/slash_admin/custom.js +0 -0
  9. data/app/assets/stylesheets/slash_admin/alert.scss +29 -0
  10. data/app/assets/stylesheets/slash_admin/application.scss +1469 -0
  11. data/app/assets/stylesheets/slash_admin/colors.scss +17 -0
  12. data/app/assets/stylesheets/slash_admin/custom.scss +0 -0
  13. data/app/controllers/slash_admin/application_controller.rb +17 -0
  14. data/app/controllers/slash_admin/base_controller.rb +45 -0
  15. data/app/controllers/slash_admin/batch_actions_controller.rb +17 -0
  16. data/app/controllers/slash_admin/dashboard_controller.rb +11 -0
  17. data/app/controllers/slash_admin/models_controller.rb +325 -0
  18. data/app/controllers/slash_admin/security/sessions_controller.rb +29 -0
  19. data/app/controllers/slash_admin/selectize_controller.rb +49 -0
  20. data/app/helpers/slash_admin/application_helper.rb +212 -0
  21. data/app/helpers/slash_admin/menu_helper.rb +14 -0
  22. data/app/helpers/slash_admin/widgets_helper.rb +7 -0
  23. data/app/jobs/slash_admin/application_job.rb +4 -0
  24. data/app/mailers/slash_admin/application_mailer.rb +6 -0
  25. data/app/models/slash_admin/admin.rb +46 -0
  26. data/app/models/slash_admin/admin_ability.rb +11 -0
  27. data/app/models/slash_admin/application_record.rb +5 -0
  28. data/app/views/layouts/slash_admin/admin_user.html.erb +16 -0
  29. data/app/views/layouts/slash_admin/application.html.erb +40 -0
  30. data/app/views/slash_admin/base/_data_belongs_to.html.erb +37 -0
  31. data/app/views/slash_admin/base/_data_list.html.erb +276 -0
  32. data/app/views/slash_admin/base/_data_nestable.html.erb +33 -0
  33. data/app/views/slash_admin/base/_data_new.html.erb +16 -0
  34. data/app/views/slash_admin/base/_data_show.html.erb +72 -0
  35. data/app/views/slash_admin/base/_filters.html.erb +60 -0
  36. data/app/views/slash_admin/base/_translatable_fields.html.erb +23 -0
  37. data/app/views/slash_admin/base/edit.html.erb +26 -0
  38. data/app/views/slash_admin/base/index.html.erb +47 -0
  39. data/app/views/slash_admin/base/index.xls.erb +27 -0
  40. data/app/views/slash_admin/base/nestable.html.erb +28 -0
  41. data/app/views/slash_admin/base/new.html.erb +26 -0
  42. data/app/views/slash_admin/base/show.html.erb +22 -0
  43. data/app/views/slash_admin/custom_fields/_color.html.erb +2 -0
  44. data/app/views/slash_admin/custom_fields/_email.html.erb +2 -0
  45. data/app/views/slash_admin/custom_fields/_google_map.html.erb +72 -0
  46. data/app/views/slash_admin/custom_fields/_nested_belongs_to.html.erb +55 -0
  47. data/app/views/slash_admin/custom_fields/_password.html.erb +2 -0
  48. data/app/views/slash_admin/custom_fields/_select.html.erb +2 -0
  49. data/app/views/slash_admin/custom_fields/_tags.html.erb +2 -0
  50. data/app/views/slash_admin/custom_fields/_wysiwyg.html.erb +2 -0
  51. data/app/views/slash_admin/dashboard/home.html.erb +5 -0
  52. data/app/views/slash_admin/dashboard/widgets/_statistic_chart.html.erb +0 -0
  53. data/app/views/slash_admin/dashboard/widgets/_statistic_progress_tile.html.erb +29 -0
  54. data/app/views/slash_admin/fields/_belongs_to.html.erb +9 -0
  55. data/app/views/slash_admin/fields/_boolean.html.erb +2 -0
  56. data/app/views/slash_admin/fields/_carrierwave.html.erb +15 -0
  57. data/app/views/slash_admin/fields/_date.html.erb +2 -0
  58. data/app/views/slash_admin/fields/_decimal.html.erb +2 -0
  59. data/app/views/slash_admin/fields/_form_group.html.erb +12 -0
  60. data/app/views/slash_admin/fields/_has_many.html.erb +12 -0
  61. data/app/views/slash_admin/fields/_has_many_row.html.erb +18 -0
  62. data/app/views/slash_admin/fields/_has_one.html.erb +24 -0
  63. data/app/views/slash_admin/fields/_integer.html.erb +2 -0
  64. data/app/views/slash_admin/fields/_json.html.erb +14 -0
  65. data/app/views/slash_admin/fields/_nested_has_many.html.erb +14 -0
  66. data/app/views/slash_admin/fields/_number.html.erb +2 -0
  67. data/app/views/slash_admin/fields/_string.html.erb +2 -0
  68. data/app/views/slash_admin/fields/_text.html.erb +2 -0
  69. data/app/views/slash_admin/security/sessions/new.html.erb +30 -0
  70. data/app/views/slash_admin/shared/_batch_actions.html.erb +21 -0
  71. data/app/views/slash_admin/shared/_better_paginate.html.erb +30 -0
  72. data/app/views/slash_admin/shared/_breadcrumb.html.erb +30 -0
  73. data/app/views/slash_admin/shared/_debug.html.erb +24 -0
  74. data/app/views/slash_admin/shared/_errors_data_new.html.erb +12 -0
  75. data/app/views/slash_admin/shared/_header.html.erb +38 -0
  76. data/app/views/slash_admin/shared/_menu.html.erb +57 -0
  77. data/app/views/slash_admin/shared/_new_form_buttons.html.erb +9 -0
  78. data/app/views/slash_admin/shared/_sub_header.html.erb +11 -0
  79. data/config/initializers/validators.rb +13 -0
  80. data/config/locales/slash_admin.en.yml +67 -0
  81. data/config/locales/slash_admin.fr.yml +72 -0
  82. data/config/routes.rb +16 -0
  83. data/db/migrate/20170512104248_create_slash_admin_admins.rb +19 -0
  84. data/lib/batch_translation.rb +19 -0
  85. data/lib/generators/slash_admin/controllers/controllers_generator.rb +16 -0
  86. data/lib/generators/slash_admin/controllers/templates/controllers.erb +9 -0
  87. data/lib/generators/slash_admin/install/install_generator.rb +13 -0
  88. data/lib/generators/slash_admin/install/templates/install.erb +14 -0
  89. data/lib/generators/slash_admin/override_admin/override_admin_generator.rb +13 -0
  90. data/lib/generators/slash_admin/override_admin/templates/admin.erb +46 -0
  91. data/lib/generators/slash_admin/override_session/override_session_generator.rb +13 -0
  92. data/lib/generators/slash_admin/override_session/templates/session.erb +27 -0
  93. data/lib/generators/slash_admin/permissions/permissions_generator.rb +13 -0
  94. data/lib/generators/slash_admin/permissions/templates/permissions.erb +11 -0
  95. data/lib/slash_admin.rb +29 -0
  96. data/lib/slash_admin/engine.rb +8 -0
  97. data/lib/slash_admin/version.rb +3 -0
  98. data/lib/tasks/slash_admin_tasks.rake +4 -0
  99. data/vendor/assets/javascripts/bootstrap-material-datetimepicker.js +1295 -0
  100. data/vendor/assets/javascripts/codemirror/codemirror.js +9657 -0
  101. data/vendor/assets/javascripts/codemirror/lint/json-lint.js +37 -0
  102. data/vendor/assets/javascripts/codemirror/lint/jsonlint.js +432 -0
  103. data/vendor/assets/javascripts/codemirror/lint/lint.js +252 -0
  104. data/vendor/assets/javascripts/codemirror/mode/javascript.js +865 -0
  105. data/vendor/assets/javascripts/jquery.nestable.js +910 -0
  106. data/vendor/assets/javascripts/jquery.tagsinput-revisited.min.js +5 -0
  107. data/vendor/assets/javascripts/toastr.js +6 -0
  108. data/vendor/assets/stylesheets/animate.css +1579 -0
  109. data/vendor/assets/stylesheets/bootstrap-material-datetimepicker.css +82 -0
  110. data/vendor/assets/stylesheets/codemirror/codemirror.css +346 -0
  111. data/vendor/assets/stylesheets/codemirror/lint/lint.css +73 -0
  112. data/vendor/assets/stylesheets/codemirror/theme/relax-seti.css +41 -0
  113. data/vendor/assets/stylesheets/jquery.nestable.css +121 -0
  114. data/vendor/assets/stylesheets/jquery.tagsinput-revisited.min.css +1 -0
  115. data/vendor/assets/stylesheets/sweetalert.css +935 -0
  116. data/vendor/assets/stylesheets/toastr.css +1 -0
  117. metadata +509 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1f1eb8776c07ec77415ce20ceea1075b36554d5ddd7e3b8591206c0b562dbf2a
4
+ data.tar.gz: fd7d4b221829064885b86a0c2e96588faa006648b41855386da5d3efd706a988
5
+ SHA512:
6
+ metadata.gz: 55167cf3a304061acb8b693ea52717d7dda264ee09bc4f90dc8438bed7decc3a0abf75a1881340069539a58736d504b0c684afade373d9ecf3aaf8398bb659e7
7
+ data.tar.gz: 4db31680e5d862e6810eb46c0172e1e7d3b4b64f25c33911907524d71d44be751765fc82450e4a9551352d21da5f920e35117481c965a95e0bc35a0e03c2dda8
@@ -0,0 +1,95 @@
1
+ [![Code Climate](https://codeclimate.com/github/nicovak/slash_admin/badges/gpa.svg)](https://codeclimate.com/github/nicovak/slash_admin)
2
+ [![CircleCI](https://circleci.com/gh/nicovak/slash_admin/tree/master.svg?style=svg&circle-token=6e9ebd7fef3ebc881c75a769b0970808024a2ae9)](https://circleci.com/gh/nicovak/slash_admin/tree/master)
3
+
4
+ # [W.I.P] SlashAdmin
5
+
6
+ A modern and overridable admin, just the rails way.
7
+ Embeded admin user and authentication system, devise is not needed.
8
+
9
+ #### Motivation:
10
+ - Provide to rails the admin it deserves without DSL or obscure logic.
11
+ - Provide an easy to use and modern experience to final users.
12
+
13
+ I tried to take the best from two greats existing gem:
14
+ - [rails_admin](https://github.com/sferik/rails_admin)
15
+ - [administrate](https://github.com/thoughtbot/administrate)
16
+
17
+ Design inspired from the awesome metronic admin theme:
18
+ - [keenthemes](http://keenthemes.com/preview/metronic/)
19
+
20
+ #### Screenshots
21
+
22
+ ![Image of Login screen](http://i.imgur.com/HFQ9hfw.jpg)
23
+ ![Image of List](http://i.imgur.com/p34HUU5.png)
24
+ ![Image of Create / Edit](http://i.imgur.com/TzOx3i8.png)
25
+
26
+ ### Installation
27
+ Add this line to your application's Gemfile:
28
+
29
+ ```ruby
30
+ gem 'slash_admin'
31
+ ```
32
+
33
+ And then execute:
34
+ ```bash
35
+ $ bundle
36
+ ```
37
+
38
+ Or install it yourself as:
39
+ ```bash
40
+ $ gem install slash_admin
41
+ ```
42
+
43
+ Gemfile
44
+ ```
45
+ gem 'carrierwave'
46
+ ```
47
+
48
+ Then:
49
+ ```bash
50
+ rails g slash_admin:install
51
+ rails slash_admin:install:migrations
52
+ rails db:migrate
53
+ ```
54
+
55
+ `config/initializers/mime_types.rb`
56
+ ```ruby
57
+ Mime::Type.register "application/xls", :xls
58
+ ```
59
+
60
+ ```ruby
61
+ Rails.application.routes.draw do
62
+ mount SlashAdmin::Engine => "/"
63
+ end
64
+ ```
65
+
66
+ Mounted as '/' but prefixed in the gem and in routes definition of models admin. See above.
67
+
68
+ ### Important
69
+
70
+ If you are using [friendly_id](https://github.com/norman/friendly_id) gem, you have to add `routes: :default` like so:
71
+
72
+ ```ruby
73
+ friendly_id :title, use: :history, routes: :default
74
+ ```
75
+
76
+ Example of create admin in `seed.rb` in your app:
77
+
78
+ ```ruby
79
+ SlashAdmin::Admin.create!(
80
+ username: 'admin',
81
+ email: 'contact@mysite.com',
82
+ password: 'admin@admin',
83
+ password_confirmation: 'admin@admin'
84
+ )
85
+ ```
86
+
87
+ ### Documentation
88
+
89
+ [Read the docs](https://github.com/nicovak/slash_admin/tree/master/docs/index.md)
90
+
91
+ ## Contributing
92
+ Coming soon.
93
+
94
+ ## License
95
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/slash_admin .js
2
+ //= link_directory ../stylesheets/slash_admin .css
@@ -0,0 +1,344 @@
1
+ //= require js-routes
2
+ //= require i18n
3
+ //= require i18n/translations
4
+ //= require jquery3
5
+ //= require jquery_ujs
6
+ //= require popper
7
+ //= require bootstrap
8
+ //= require selectize
9
+ //= require moment
10
+ //= require moment/fr
11
+ //= require bootstrap-material-datetimepicker
12
+ //= require jquery.tagsinput-revisited.min
13
+ //= require Chart.min
14
+ //= require highcharts
15
+ //= require chartkick
16
+ //= require bootstrap-datepicker
17
+ //= require sweetalert
18
+ //= require cocoon
19
+ //= require toastr
20
+ //= require codemirror/codemirror
21
+ //= require codemirror/lint/lint
22
+ //= require codemirror/lint/jsonlint
23
+ //= require codemirror/lint/json-lint
24
+ //= require codemirror/mode/javascript
25
+ //= require jquery.nestable
26
+ //= require jquery.minicolors
27
+ //= require turbolinks
28
+ //= require slash_admin/custom
29
+ //= require_tree .
30
+
31
+ $(document).on("turbolinks:load", init);
32
+
33
+ function init() {
34
+ Turbolinks.clearCache();
35
+
36
+ $('.page-sidebar a[href$="#"]').on('click', function(e) {
37
+ e.preventDefault()
38
+ });
39
+
40
+ $(".tags").tagsInput({
41
+ placeholder: I18n.t('slash_admin.view.add_tag'),
42
+ delimiter: [",", ";", " "]
43
+ });
44
+
45
+ // Scroll to top
46
+ var offset = 250;
47
+ $(window).scroll(function() {
48
+ if ($(this).scrollTop() > offset) {
49
+ $(".scroll-to-top").fadeIn("slow");
50
+ } else {
51
+ $(".scroll-to-top").fadeOut("slow");
52
+ }
53
+ });
54
+
55
+ $(".scroll-to-top").click(function(event) {
56
+ $("html, body").animate({ scrollTop: 0 }, 300);
57
+ });
58
+
59
+ // Automatic hide alert
60
+ window.setTimeout(function() {
61
+ $(".alert").fadeTo(500, 0).slideUp(500, function() {
62
+ $(this).remove();
63
+ });
64
+ }, 1500);
65
+
66
+ // clearForm
67
+ $.fn.clearForm = function() {
68
+ return this.each(function() {
69
+ var type = this.type,
70
+ tag = this.tagName.toLowerCase();
71
+ if (tag === "form") return $(":input", this).clearForm();
72
+ if (type === "text" || type === "password" || tag === "textarea")
73
+ this.value = "";
74
+ else if (type === "checkbox" || type === "radio") this.checked = false;
75
+ else if (tag === "select") this.selectedIndex = -1;
76
+ });
77
+ };
78
+
79
+ // CounterUp plugin
80
+ $("[data-counter='counterup']").each(function() {
81
+ var $this = $(this),
82
+ countTo = $this.attr("data-value");
83
+ $({ countNum: $this.text() }).animate(
84
+ {
85
+ countNum: countTo
86
+ },
87
+ {
88
+ duration: 1500,
89
+ easing: "linear",
90
+ step: function() {
91
+ $this.text(Math.floor(this.countNum));
92
+ },
93
+ complete: function() {
94
+ $this.text(this.countNum);
95
+ }
96
+ }
97
+ );
98
+ });
99
+
100
+ // MENU
101
+ $(".sub-menu").has(".active").parent().addClass("active");
102
+
103
+ // BULK ACTIONS
104
+ $(".toggle-all").on("change", function() {
105
+ var checked = this.checked;
106
+ $('.table-data-list tbody input[type="checkbox"]').each(function(
107
+ index,
108
+ item
109
+ ) {
110
+ $(item).prop("checked", checked);
111
+ });
112
+ });
113
+
114
+ $('.table-data-list input[type="checkbox"]').on("change", function() {
115
+ var length = $('.table-data-list tbody input[type="checkbox"]:checked')
116
+ .length;
117
+ $(".batch-current-selected").html(length);
118
+ });
119
+
120
+ // Delete button protection sweetalert
121
+ $(".single-delete").on("click", function(e) {
122
+ e.preventDefault();
123
+ var target = $(this).attr("href");
124
+ var current = window.location.href;
125
+
126
+ swal(
127
+ {
128
+ title: I18n.t('slash_admin.view.confirm'),
129
+ text: I18n.t('slash_admin.view.no_back'),
130
+ type: "warning",
131
+ showCancelButton: true,
132
+ confirmButtonClass: "btn-danger",
133
+ cancelButtonClass: "btn-primary",
134
+ confirmButtonText: I18n.t('slash_admin.view.yes_delete'),
135
+ cancelButtonText: I18n.t('slash_admin.view.cancel'),
136
+ closeOnConfirm: false
137
+ },
138
+ function() {
139
+ $.ajax({
140
+ url: target,
141
+ method: "DELETE"
142
+ }).done(function() {
143
+ window.location.href = current;
144
+ });
145
+ }
146
+ );
147
+ });
148
+
149
+ // Batch action
150
+ $(".batch-action").on("click", function(e) {
151
+ e.preventDefault();
152
+ var target = $(this).data("action");
153
+ var message = $(this).data("message");
154
+ var current = window.location.href;
155
+ var ids = [];
156
+
157
+ $('.table-data-list tbody input[type="checkbox"]:checked').each(function(
158
+ index,
159
+ checkbox
160
+ ) {
161
+ ids.push($(this).val());
162
+ });
163
+
164
+ if (ids.length > 0) {
165
+ swal(
166
+ {
167
+ title: I18n.t('slash_admin.view.confirm'),
168
+ text: message,
169
+ type: "warning",
170
+ showCancelButton: true,
171
+ confirmButtonClass: "btn-danger",
172
+ cancelButtonClass: "btn-primary",
173
+ confirmButtonText: I18n.t('slash_admin.view.yes_delete'),
174
+ cancelButtonText: I18n.t('slash_admin.view.cancel'),
175
+ closeOnConfirm: false
176
+ },
177
+ function() {
178
+ $.ajax({
179
+ url: target,
180
+ method: "post",
181
+ data: {
182
+ ids: ids
183
+ }
184
+ }).done(function() {
185
+ window.location.href = current;
186
+ });
187
+ }
188
+ );
189
+ }
190
+ });
191
+
192
+ $(".selectize-single").selectize({
193
+ allowEmptyOption: true
194
+ });
195
+
196
+ $(".selectize-multiple").selectize({
197
+ allowEmptyOption: true,
198
+ persist: false,
199
+ plugins: {
200
+ remove_button: {}
201
+ }
202
+ });
203
+
204
+ $(".selectize-model-single").selectize({
205
+ allowEmptyOption: true,
206
+ valueField: "id",
207
+ labelField: "name",
208
+ searchField: "name",
209
+ create: false,
210
+ load: function(query, callback) {
211
+ if (!query.length) return callback();
212
+ var model = $(this)[0].$input[0].getAttribute("data-model");
213
+ var fields = $(this)[0].$input[0].getAttribute("data-fields");
214
+ $.ajax({
215
+ url: Routes.slash_admin_remote_selectize_path({
216
+ format: "json"
217
+ }),
218
+ dataType: "json",
219
+ data: {
220
+ model_class: model,
221
+ q: query,
222
+ fields: fields.split(" ")
223
+ },
224
+ error: function() {
225
+ callback();
226
+ },
227
+ success: function(res) {
228
+ callback(res);
229
+ }
230
+ });
231
+ },
232
+ render: {
233
+ option: function(item, escape) {
234
+ return "<div>" + escape(item.name) + "</div>";
235
+ }
236
+ }
237
+ });
238
+
239
+ $(".selectize-model-multiple").selectize({
240
+ allowEmptyOption: true,
241
+ persist: false,
242
+ plugins: {
243
+ remove_button: {}
244
+ },
245
+ valueField: "id",
246
+ labelField: "name",
247
+ searchField: "name",
248
+ create: false,
249
+ load: function(query, callback) {
250
+ if (!query.length) return callback();
251
+ var model = $(this)[0].$input[0].getAttribute("data-model");
252
+ var fields = $(this)[0].$input[0].getAttribute("data-fields");
253
+ $.ajax({
254
+ url: Routes.slash_admin_remote_selectize_path({
255
+ format: "json"
256
+ }),
257
+ dataType: "json",
258
+ data: {
259
+ model_class: model,
260
+ q: query,
261
+ fields: fields.split(" ")
262
+ },
263
+ error: function() {
264
+ callback();
265
+ },
266
+ success: function(res) {
267
+ callback(res);
268
+ }
269
+ });
270
+ },
271
+ render: {
272
+ option: function(item, escape) {
273
+ return "<div>" + escape(item.name) + "</div>";
274
+ }
275
+ }
276
+ });
277
+
278
+ $(".bootstrap-datepicker").datepicker({
279
+ language: I18n.currentLocale(),
280
+ format: "YYYY-MM-DD"
281
+ });
282
+
283
+ $(".bootstrap-material-date").bootstrapMaterialDatePicker({
284
+ lang: I18n.currentLocale(),
285
+ weekStart: 1,
286
+ cancelText: I18n.t("slash_admin.view.cancel"),
287
+ time: false,
288
+ clearButton: true,
289
+ clearText: I18n.t("slash_admin.view.erase"),
290
+ format: "YYYY-MM-DD"
291
+ });
292
+
293
+ $(".bootstrap-material-datetime").bootstrapMaterialDatePicker({
294
+ lang: I18n.currentLocale(),
295
+ weekStart: 1,
296
+ cancelText: I18n.t("slash_admin.view.cancel"),
297
+ clearButton: true,
298
+ clearText: I18n.t("slash_admin.view.erase"),
299
+ format: "YYYY-MM-DD HH:mm:ss"
300
+ });
301
+
302
+ $(".colorpicker").minicolors();
303
+
304
+ $("#reset-filters").on("click", function(e) {
305
+ e.preventDefault();
306
+
307
+ $("input[name*='filters']").val("");
308
+ $("select[name*='filters'] option:first").prop("selected", true);
309
+
310
+ $("#filters").trigger("submit");
311
+ });
312
+
313
+ // Handle Both form
314
+ function handleFiltersAndLocation() {
315
+ var url = window.location.href.split("?")[0];
316
+
317
+ var filtersParams = $("#filters").serialize();
318
+ var paginationParams = $(".admin-pagination").first().serialize();
319
+ var orderParams = $("#order").serialize();
320
+
321
+ parameters = "";
322
+ $.each([filtersParams, paginationParams, orderParams], function(
323
+ index,
324
+ params
325
+ ) {
326
+ if (index !== 0) {
327
+ parameters += "&" + params;
328
+ } else {
329
+ parameters += params;
330
+ }
331
+ });
332
+
333
+ window.location.href = url + "?" + parameters;
334
+ }
335
+
336
+ // Handle create belongs to
337
+ $("#create-belongs-to-form")
338
+ .on("ajax:success", function(e, data, status, xhr) {
339
+ $("#create-belongs-to-form").text("Done.");
340
+ })
341
+ .on("ajax:error", function(e, xhr, status, error) {
342
+ $("#create-belongs-to-form").text("Failed.");
343
+ });
344
+ }