cm-admin 0.1.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +7 -1
  6. data/Gemfile.lock +121 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +20 -21
  9. data/app/assets/images/logo.png +0 -0
  10. data/app/assets/stylesheets/cm_admin/base/auth.scss +73 -0
  11. data/app/assets/stylesheets/cm_admin/base/common.scss +237 -0
  12. data/app/assets/stylesheets/cm_admin/base/filters.scss +200 -0
  13. data/app/assets/stylesheets/cm_admin/base/form.scss +197 -0
  14. data/app/assets/stylesheets/cm_admin/base/main-nav.scss +47 -0
  15. data/app/assets/stylesheets/cm_admin/base/navbar.scss +65 -0
  16. data/app/assets/stylesheets/cm_admin/base/quicksearch.scss +76 -0
  17. data/app/assets/stylesheets/cm_admin/base/scaffold.scss +96 -0
  18. data/app/assets/stylesheets/cm_admin/base/show.scss +76 -0
  19. data/app/assets/stylesheets/cm_admin/base/sidebar.scss +225 -0
  20. data/app/assets/stylesheets/cm_admin/base/table.scss +320 -0
  21. data/app/assets/stylesheets/cm_admin/base/tabs.scss +26 -0
  22. data/{lib/generators/cm_admin/templates/assets/stylesheets/application.css.scss → app/assets/stylesheets/cm_admin/cm_admin.css.scss} +12 -16
  23. data/app/assets/stylesheets/cm_admin/components/_alerts.scss +101 -0
  24. data/app/assets/stylesheets/cm_admin/components/_buttons.scss +135 -0
  25. data/app/assets/stylesheets/cm_admin/components/_dropdown-popup.scss +153 -0
  26. data/app/assets/stylesheets/cm_admin/components/_input.scss +274 -0
  27. data/app/assets/stylesheets/cm_admin/components/_modal.scss +34 -0
  28. data/app/assets/stylesheets/cm_admin/components/_range.scss +31 -0
  29. data/app/assets/stylesheets/cm_admin/components/_status-tag.scss +68 -0
  30. data/app/assets/stylesheets/cm_admin/components/index.scss +7 -0
  31. data/app/assets/stylesheets/cm_admin/dependency/bootstrap.min.css +7 -0
  32. data/app/assets/stylesheets/cm_admin/helpers/_mixins.scss +20 -0
  33. data/app/assets/stylesheets/cm_admin/helpers/_variable.scss +87 -0
  34. data/app/assets/stylesheets/cm_admin/helpers/index.scss +2 -0
  35. data/app/controllers/cm_admin/application_controller.rb +11 -0
  36. data/app/controllers/cm_admin/exports_controller.rb +16 -0
  37. data/app/controllers/cm_admin/static_controller.rb +12 -0
  38. data/app/helpers/cm_admin/application_helper.rb +11 -0
  39. data/app/helpers/cm_admin/custom_helper.rb +4 -0
  40. data/app/javascript/packs/cm_admin/application.js +22 -0
  41. data/app/javascript/packs/cm_admin/filters.js +347 -0
  42. data/app/javascript/packs/cm_admin/quick_search.js +67 -0
  43. data/app/javascript/packs/cm_admin/scaffolds.js +43 -0
  44. data/app/javascript/stylesheets/cm_admin/application.scss +3 -0
  45. data/app/views/cm_admin/main/_associated_table.html.slim +60 -0
  46. data/app/views/cm_admin/main/_cm_pagy_nav.html.slim +23 -0
  47. data/app/views/cm_admin/main/_filters.html.slim +1 -0
  48. data/app/views/cm_admin/main/_nested_fields.html.slim +7 -0
  49. data/app/views/cm_admin/main/_nested_table_form.html.slim +6 -0
  50. data/app/views/cm_admin/main/_table.html.slim +60 -0
  51. data/app/views/cm_admin/main/_tabs.html.slim +5 -0
  52. data/app/views/cm_admin/main/_top_navbar.html.slim +25 -0
  53. data/app/views/cm_admin/main/associated_index.html.slim +6 -0
  54. data/app/views/cm_admin/main/associated_show.html.slim +6 -0
  55. data/app/views/cm_admin/main/dashboard.html.slim +1 -0
  56. data/app/views/cm_admin/main/edit.html.slim +19 -0
  57. data/app/views/cm_admin/main/index.html.slim +12 -0
  58. data/app/views/cm_admin/main/new.html.slim +22 -0
  59. data/app/views/cm_admin/main/show.html.slim +12 -0
  60. data/app/views/cm_admin/static/error_401.html.slim +4 -0
  61. data/app/views/layouts/_left_sidebar_nav.html.slim +34 -0
  62. data/app/views/layouts/_quick_links.html.slim +25 -0
  63. data/app/views/layouts/cm_admin.html.slim +41 -0
  64. data/app/views/layouts/static.html.slim +18 -0
  65. data/bin/webpack +18 -0
  66. data/bin/webpack-dev-server +18 -0
  67. data/cm_admin.gemspec +21 -31
  68. data/config/.DS_Store +0 -0
  69. data/config/initializers/active_record_extension.rb +9 -0
  70. data/config/routes.rb +19 -0
  71. data/config/webpack/development.js +5 -0
  72. data/config/webpack/environment.js +13 -0
  73. data/config/webpack/production.js +5 -0
  74. data/config/webpack/test.js +5 -0
  75. data/config/webpacker.yml +92 -0
  76. data/lib/cm_admin/constants.rb +33 -0
  77. data/lib/cm_admin/engine.rb +38 -0
  78. data/lib/cm_admin/model.rb +152 -0
  79. data/lib/cm_admin/models/action.rb +36 -0
  80. data/lib/cm_admin/models/actions/blocks.rb +25 -0
  81. data/lib/cm_admin/models/blocks.rb +19 -0
  82. data/lib/cm_admin/models/cm_show_section.rb +20 -0
  83. data/lib/cm_admin/models/column.rb +61 -0
  84. data/lib/cm_admin/models/controller_method.rb +75 -0
  85. data/lib/cm_admin/models/dsl_method.rb +122 -0
  86. data/lib/cm_admin/models/export.rb +54 -0
  87. data/lib/cm_admin/models/field.rb +15 -0
  88. data/lib/cm_admin/models/filter.rb +95 -0
  89. data/lib/cm_admin/models/form_field.rb +21 -0
  90. data/lib/cm_admin/models/tab.rb +13 -0
  91. data/lib/cm_admin/utils.rb +67 -0
  92. data/lib/cm_admin/version.rb +1 -1
  93. data/lib/cm_admin/view_helpers/column_field_helper.rb +29 -0
  94. data/lib/cm_admin/view_helpers/field_display_helper.rb +65 -0
  95. data/lib/cm_admin/view_helpers/filter_helper.rb +190 -0
  96. data/lib/cm_admin/view_helpers/form_field_helper.rb +33 -0
  97. data/lib/cm_admin/view_helpers/form_helper.rb +65 -0
  98. data/lib/cm_admin/view_helpers/manage_column_popup_helper.rb +75 -0
  99. data/lib/cm_admin/view_helpers/navigation_helper.rb +34 -0
  100. data/lib/cm_admin/view_helpers/page_info_helper.rb +57 -0
  101. data/lib/cm_admin/view_helpers.rb +74 -0
  102. data/lib/cm_admin.rb +33 -2
  103. data/lib/generators/cm_admin/install_generator.rb +11 -13
  104. data/lib/tasks/webpack_install.rake +63 -0
  105. data/package.json +23 -0
  106. data/postcss.config.js +12 -0
  107. data/tmp/cache/webpacker/last-compilation-digest-development +1 -0
  108. data/yarn.lock +6933 -0
  109. metadata +155 -42
  110. data/lib/generators/cm_admin/USAGE +0 -8
  111. data/lib/generators/cm_admin/templates/assets/images/same-logo.png +0 -0
  112. data/lib/generators/cm_admin/templates/assets/stylesheets/_variable.scss +0 -11
  113. data/lib/generators/cm_admin/templates/assets/stylesheets/alignment.scss +0 -111
  114. data/lib/generators/cm_admin/templates/assets/stylesheets/devise.scss +0 -98
  115. data/lib/generators/cm_admin/templates/assets/stylesheets/form.scss +0 -131
  116. data/lib/generators/cm_admin/templates/assets/stylesheets/products.scss +0 -21
  117. data/lib/generators/cm_admin/templates/assets/stylesheets/scaffold.scss +0 -241
  118. data/lib/generators/cm_admin/templates/assets/stylesheets/table.scss +0 -90
  119. data/lib/generators/cm_admin/templates/assets/stylesheets/user.scss +0 -25
  120. data/lib/generators/cm_admin/templates/layouts/_navbar.html.slim +0 -9
  121. data/lib/generators/cm_admin/templates/layouts/_side_navbar.html.slim +0 -16
  122. data/lib/generators/cm_admin/templates/layouts/application.html.slim +0 -25
  123. data/lib/generators/cm_admin/templates/layouts/initializer.rb +0 -2
  124. data/lib/generators/cm_admin/templates/views/_filters.html.slim +0 -0
  125. data/lib/generators/cm_admin/templates/views/_form.erb +0 -38
  126. data/lib/generators/cm_admin/templates/views/_table.erb +0 -14
  127. data/lib/generators/cm_admin/templates/views/index.erb +0 -11
  128. data/lib/generators/cm_admin/templates/views/show.erb +0 -8
  129. data/lib/generators/cm_admin/view_generator.rb +0 -57
@@ -0,0 +1,4 @@
1
+ module CmAdmin
2
+ module CustomHelper
3
+ end
4
+ end
@@ -0,0 +1,22 @@
1
+ require("@rails/ujs").start()
2
+ require("turbolinks").start()
3
+ require("@rails/activestorage").start()
4
+ require("stylesheets/cm_admin/application")
5
+ require("jquery")
6
+ require("moment")
7
+ require("bootstrap")
8
+ require('flatpickr')
9
+ require('./scaffolds.js')
10
+ require('./quick_search.js')
11
+ require('./filters.js')
12
+
13
+ import jQuery from 'jquery'
14
+ window.$ = jQuery
15
+ window.jQuery = jQuery
16
+
17
+ require("@nathanvda/cocoon")
18
+ import "@fortawesome/fontawesome-free/css/all"
19
+ import "daterangepicker"
20
+
21
+
22
+
@@ -0,0 +1,347 @@
1
+ var currentRequest = null;
2
+
3
+ // Main method which will structure the existing filter values with the newly
4
+ // applied filter. Send and receive the value from the backend.
5
+ var getFilteredData = function(filterType, filterValue, filterColumn=null) {
6
+ var url = window.location.pathname
7
+
8
+ // Based on the value changed for recent filter generate the filterParams hash
9
+ var filterParams = {};
10
+ if (filterColumn) {
11
+ filterParams[filterType] = {};
12
+ filterParams[filterType][filterColumn] = filterValue
13
+ } else {
14
+ filterParams[filterType] = filterValue
15
+ }
16
+
17
+ // TODO add sort params in the queryString
18
+ // page params is reinitialized to 1 when any new filter value is applied so
19
+ // that it won't throw the error when the user doesn't have sufficent data
20
+ // to display on the table.
21
+ var queryString = {
22
+ filters: filterParams,
23
+ page: 1
24
+ };
25
+
26
+ // Generate the queryString by concatenating the filterParams and
27
+ // searchParams that are already applied, if searchParams are present.
28
+ var searchParams = window.location.search
29
+ if (searchParams.length > 0) {
30
+ // Delete the previous applied value for multi_select filter from the
31
+ // searchParams as altering the array with new and old value will create
32
+ // more complicated logic. The new value is passed and structured in
33
+ // filterParams and will be concadinated with the searchParams post deletion
34
+ if (filterType == 'multi_select') {
35
+ searchParams = getParamsAsObject(searchParams)
36
+ if (searchParams['filters'][filterType] != undefined) {
37
+ delete(searchParams['filters'][filterType][filterColumn])
38
+ }
39
+ searchParams = jQuery.param(searchParams)
40
+ }
41
+ filterParams = jQuery.param(queryString)
42
+ var availableParams = searchParams + '&' + filterParams
43
+ queryString = getParamsAsObject(availableParams)
44
+ }
45
+
46
+ return currentRequest = $.ajax(url, {
47
+ type: 'GET',
48
+ data: queryString,
49
+ beforeSend: function() {
50
+ if (currentRequest !== null) {
51
+ currentRequest.abort();
52
+ }
53
+ },
54
+ success: function(data) {
55
+ var queryParam = jQuery.param(queryString)
56
+ window.history.pushState("", "", url + '?' + queryParam);
57
+ $('.index-page__table-container').html(data);
58
+ },
59
+ error: function(jqxhr, textStatus, errorThrown) {
60
+ console.log(errorThrown, textStatus);
61
+ }
62
+ });
63
+ }
64
+
65
+ $(document).on('change', '[data-behaviour="filter"]', function(e) {
66
+ var filterType = $(this).data('filter-type')
67
+ var filterColumn = $(this).data('db-column')
68
+
69
+ if (filterType == 'range') {
70
+ var rangeElements = $(this).parent().children()
71
+ var filterValue = $(rangeElements[0]).val() + ' to ' + $(rangeElements[1]).val()
72
+ } else {
73
+ var filterValue = $(this).val()
74
+ }
75
+
76
+ $(this).parents(':nth(1)').children(':first').children(':nth(1)').text(filterValue)
77
+ $(this).parents(':nth(1)').children(':first').children(':last').removeClass('hidden')
78
+
79
+ unhideClearFilterBtn(filterValue)
80
+ getFilteredData(filterType, filterValue, filterColumn)
81
+ });
82
+
83
+ $(document).on('keyup', '[data-behaviour="input-search"]', function(e) {
84
+ e.stopPropagation();
85
+
86
+ var searchValue = $(this).val();
87
+ unhideClearFilterBtn(searchValue)
88
+ getFilteredData('search', searchValue)
89
+ });
90
+
91
+ $(document).on('click', '[data-behaviour="filter-option"]', function(e) {
92
+ var filterType = $(this).data('filter-type')
93
+ var filterColumn = $(this).data('db-column')
94
+
95
+ // Clear the search value post selection and regenerate the dropdown elements.
96
+ var searchInputElement = $(this).parents(':nth(1)').children(':first').children()
97
+ searchInputElement.val('')
98
+ CmFilter.dropdown_search(searchInputElement)
99
+
100
+ unhideFilter(filterType, filterColumn)
101
+ });
102
+
103
+ var unhideFilter = function(filterType, filterColumn) {
104
+ var filterInputElement = $('[data-behaviour="filter-input"][data-filter-type=' + filterType + '][data-db-column='+ filterColumn + ']')
105
+
106
+ filterInputElement.parent().removeClass('hidden');
107
+ filterInputElement.click()
108
+ };
109
+
110
+ // Search inside the dropdowns
111
+ $(document).on('keyup', '[data-behaviour="dropdown-filter-search"]', function(e) {
112
+ CmFilter.dropdown_search($(this))
113
+ });
114
+
115
+ // Method to decode the encoded nested and/or complex hash and convert it to
116
+ // object that is used for filters while sending the data to the backend.
117
+ var getParamsAsObject = function (query) {
118
+ query = query.substring(query.indexOf('?') + 1);
119
+
120
+ var re = /([^&=]+)=?([^&]*)/g;
121
+ var decodeRE = /\+/g;
122
+
123
+ var decode = function (str) {
124
+ return decodeURIComponent(str.replace(decodeRE, " "));
125
+ };
126
+
127
+ var params = {}, e;
128
+ while (e = re.exec(query)) {
129
+ var k = decode(e[1]), v = decode(e[2]);
130
+ if (k.substring(k.length - 2) === '[]') {
131
+ k = k.substring(0, k.length - 2);
132
+ (params[k] || (params[k] = [])).push(v);
133
+ }
134
+ else params[k] = v;
135
+ }
136
+
137
+ var assign = function (obj, keyPath, value) {
138
+ var lastKeyIndex = keyPath.length - 1;
139
+ for (var i = 0; i < lastKeyIndex; ++i) {
140
+ var key = keyPath[i];
141
+ if (!(key in obj))
142
+ obj[key] = {}
143
+ obj = obj[key];
144
+ }
145
+ obj[keyPath[lastKeyIndex]] = value;
146
+ }
147
+
148
+ for (var prop in params) {
149
+ var structure = prop.split('[');
150
+ if (structure.length > 1) {
151
+ var levels = [];
152
+ structure.forEach(function (item, i) {
153
+ var key = item.replace(/[?[\]\\ ]/g, '');
154
+ levels.push(key);
155
+ });
156
+ assign(params, levels, params[prop]);
157
+ delete(params[prop]);
158
+ }
159
+ }
160
+ return params;
161
+ };
162
+
163
+ $(document).on('click', '[data-behaviour="filter-input"]', function(e) {
164
+ var filterType = $(this).data('filter-type')
165
+ var filterColumn = $(this).data('db-column')
166
+
167
+ var filterElement = $('[data-behaviour="filter"][data-filter-type=' + filterType + '][data-db-column=' + filterColumn +']')
168
+
169
+ if (filterType == 'range') {
170
+ filterElement.parent().toggleClass('hidden')
171
+ } else if (filterType == 'multi_select') {
172
+ $(this).parent().children(':last').toggleClass('hidden')
173
+ } else if (filterType == 'date') {
174
+ filterElement.click()
175
+ }
176
+ })
177
+
178
+ // Remove all the applied filters and reload the page
179
+ $(document).on('click', '.clear-btn', function(e) {
180
+ window.location.href = window.location.href.split("?")[0]
181
+ })
182
+
183
+ var unhideClearFilterBtn = function(filterValue) {
184
+ if (filterValue) {
185
+ $('.clear-btn').removeClass('hidden')
186
+ }
187
+ }
188
+
189
+ // Selecting options for single and multi select filters
190
+ $(document).on('click', '[data-behaviour="select-option"]', function(e) {
191
+ var filterType = $(this).data('filter-type')
192
+ var filterColumn = $(this).data('db-column')
193
+
194
+ if (filterType == 'single_select') {
195
+ var filterValue = $(this).data('value')
196
+ if (!this.classList.contains('selected')) {
197
+ if (this.parentNode.querySelector('.list-item.selected') != null) {
198
+ this.parentNode.querySelector('.list-item.selected').classList.remove('selected');
199
+ }
200
+ $(this).addClass('selected')
201
+ }
202
+
203
+ $(this).parents(':nth(4)').children(':first').children(':nth(1)').text(filterValue)
204
+ $(this).parents(':nth(4)').children(':first').children(':last').removeClass('hidden')
205
+
206
+ // Clear the search value post selection and regenerate the dropdown elements.
207
+ var searchInputElement = $(this).parents(':nth(1)').children(':first').children()
208
+ searchInputElement.val('')
209
+ CmFilter.dropdown_search(searchInputElement)
210
+
211
+ unhideClearFilterBtn(filterValue)
212
+ getFilteredData(filterType, filterValue, filterColumn)
213
+ }
214
+ else if (filterType == 'multi_select') {
215
+ var parentChip = $(this).parent().siblings(':first')
216
+ var checkboxElement = $(this).find('.cm-checkbox')
217
+ checkboxElement.prop('checked', !checkboxElement.prop('checked'))
218
+ var checkedCount = $(this).parent().find('.cm-checkbox').filter(':checked').length
219
+
220
+ if (checkboxElement.prop('checked')) {
221
+ var chip = $('<div class="chip"></div>')
222
+ var firstSpan = $('<span></span>').text($(this).data('value'))
223
+ var secondSpan = $('<span data-behaviour="selected-chip"><i class="fa fa-times"></i></span>')
224
+ parentChip.prepend(chip.append(firstSpan).append(secondSpan))
225
+ } else {
226
+ var chipElement = parentChip.find('.chip')
227
+ for(var i = 0; i < chipElement.length; i++) {
228
+ if ($(chipElement[i]).text() == $(this).data('value')) {
229
+ $(chipElement[i]).remove()
230
+ break
231
+ }
232
+ }
233
+ }
234
+
235
+ if (checkedCount > 0) {
236
+ parentChip.addClass('search-with-chips').removeClass('search-area')
237
+ $(this).parents(':nth(1)').children(':last').addClass('active')
238
+ } else {
239
+ parentChip.addClass('search-area').removeClass('search-with-chips')
240
+ $(this).parents(':nth(1)').children(':last').removeClass('active')
241
+ }
242
+ }
243
+ });
244
+
245
+ // Apply button for multi select filters
246
+ $(document).on('click', '.apply-area', function(e) {
247
+ var filterInputElement = $(this).parents(':nth(3)').children(':first')
248
+ var filterType = filterInputElement.data('filter-type')
249
+ var filterColumn = filterInputElement.data('db-column')
250
+ var filterValue = []
251
+
252
+ var selectFilterElement = $('[data-behaviour="select-option"][data-filter-type=' + filterType + '][data-db-column=' + filterColumn + ']')
253
+ var checkedElements = selectFilterElement.find('.cm-checkbox').filter(':checked')
254
+
255
+ if (checkedElements.length > 0) {
256
+ for(var i = 0; i < checkedElements.length; i++) {
257
+ filterValue.push($(checkedElements[i]).parent().data('value'))
258
+ }
259
+
260
+ truncatedFilterValue = filterValue[0]
261
+ if (filterValue.length > 1) {
262
+ truncatedFilterValue += ' + ' + (filterValue.length - 1) + ' more'
263
+ }
264
+
265
+ filterInputElement.children(':nth(1)').text(truncatedFilterValue)
266
+ filterInputElement.children(':last').removeClass('hidden')
267
+ selectFilterElement.parents(':nth(3)').addClass('hidden')
268
+
269
+ // Clear the search value post selection and regenerate the dropdown elements.
270
+ var searchInputElement = $(this).parent().children(':first').children(':last')
271
+ searchInputElement.val('')
272
+ CmFilter.dropdown_search(searchInputElement)
273
+
274
+ unhideClearFilterBtn(filterValue)
275
+ getFilteredData(filterType, filterValue, filterColumn)
276
+ }
277
+ });
278
+
279
+ // Remove single applied filter.
280
+ $(document).on('click', '.filter-chip-remove', function(e) {
281
+ var url = window.location.pathname
282
+ var filterType = $(this).parent().data('filter-type')
283
+ var filterColumn = $(this).parent().data('db-column')
284
+
285
+ var searchParams = window.location.search
286
+ if (searchParams.length > 0) {
287
+ queryString = getParamsAsObject(searchParams)
288
+ if (queryString['filters'][filterType] != undefined) {
289
+ delete(queryString['filters'][filterType][filterColumn])
290
+ var queryParam = jQuery.param(queryString)
291
+ window.history.pushState("", "", url + '?' + queryParam);
292
+ window.location.reload()
293
+ }
294
+ }
295
+ });
296
+
297
+ $(document).on('click', '[data-behaviour="selected-chip"]', function(e) {
298
+ var filterType = $(this).parents(':nth(5)').find('.filter-chip').data('filter-type')
299
+ var filterColumn = $(this).parents(':nth(5)').find('.filter-chip').data('db-column')
300
+ var filterValue = $(this).siblings().text()
301
+
302
+ var selectElement = $('[data-behaviour="select-option"][data-filter-type=' + filterType + '][data-db-column=' + filterColumn + ']')
303
+ $(this).parent().remove()
304
+
305
+ for(var i = 0; i < selectElement.length; i++) {
306
+ if ($(selectElement[i]).data('value') == filterValue) {
307
+ var checkboxElement = $(selectElement[i]).find('.cm-checkbox')
308
+ checkboxElement.prop('checked', !checkboxElement.prop('checked'))
309
+ break
310
+ }
311
+ }
312
+
313
+ var checkedCount = $(selectElement).find('.cm-checkbox').filter(':checked').length
314
+ if (checkedCount < 1) {
315
+ $(selectElement).parent().siblings(':first').addClass('search-area').removeClass('search-with-chips')
316
+ $(selectElement).parent().siblings(':last').removeClass('active')
317
+ }
318
+ })
319
+
320
+ CmFilter = {
321
+ // Generate or remove elements of the dropdown based on the search value.
322
+ dropdown_search: function(element) {
323
+ var filter = element.val().toUpperCase();
324
+ var dropdownElements = element.parents(':nth(1)').find('.list-area').children();
325
+ for (var i = 0; i < dropdownElements.length; i++) {
326
+ txtValue = $(dropdownElements[i]).children().text();
327
+ if (txtValue.toUpperCase().indexOf(filter) > -1) {
328
+ $(dropdownElements[i]).css('display', 'flex');
329
+ } else {
330
+ $(dropdownElements[i]).css('display', 'none');
331
+ }
332
+ }
333
+ },
334
+ quick_input_search: function(element) {
335
+ var filter = element.val().toUpperCase();
336
+ var searchElements = element.parents(':nth(3)').find('.list-area').children();
337
+ searchElements.removeClass('visible').addClass('hidden')
338
+ console.log("Filter is ", filter)
339
+ console.log("Search elements are ", searchElements)
340
+ for (var i = 0; i < searchElements.length; i++) {
341
+ txtValue = $(searchElements[i]).children().text();
342
+ if (txtValue.toUpperCase().indexOf(filter) > -1) {
343
+ $(searchElements[i]).removeClass('hidden').addClass('visible');
344
+ }
345
+ }
346
+ }
347
+ }
@@ -0,0 +1,67 @@
1
+ $(document).on("keydown", function(e) {
2
+ if (e.keyCode == 75 && e.metaKey) {
3
+ $('#quickSearchModal').modal('show')
4
+ }
5
+ });
6
+
7
+ var liSelected;
8
+ $(document).on('keydown', function(e){
9
+ var sel_item = $('.search-results-container > a.visible');
10
+ if ($('#quickSearchModal').hasClass('show')) {
11
+ var selected;
12
+ if(e.which === 40){
13
+ if(liSelected){
14
+ liSelected.removeClass('active-item');
15
+ next = liSelected.next();
16
+ if(next.length > 0){
17
+ liSelected = next.addClass('active-item');
18
+ selected = next.text();
19
+
20
+ }else{
21
+ liSelected = sel_item.eq(0).addClass('active-item');
22
+ selected = sel_item.eq(0).text();
23
+ }
24
+ }else{
25
+ liSelected = sel_item.eq(0).addClass('active-item');
26
+ selected = sel_item.eq(0).text();
27
+ }
28
+ }else if(e.which === 38){
29
+ if(liSelected){
30
+ liSelected.removeClass('active-item');
31
+ next = liSelected.prev();
32
+ if(next.length > 0){
33
+ liSelected = next.addClass('active-item');
34
+ selected = next.text();
35
+
36
+ }else{
37
+
38
+ liSelected = sel_item.last().addClass('active-item');
39
+ selected = sel_item.last().text()
40
+ }
41
+ }else{
42
+ liSelected = sel_item.last().addClass('active-item');
43
+ selected = sel_item.last().text()
44
+ }
45
+ }
46
+ if(liSelected && e.which === 13) {
47
+ console.log("Selected item id ", liSelected)
48
+ href = liSelected.attr('href')
49
+ window.location = href
50
+ }
51
+ }
52
+ });
53
+
54
+ $(document).on('keyup', '[data-behaviour="quick-input-search"]', function(e) {
55
+ if ($(this).val().length > 0) {
56
+ $('.clear-search').removeClass('hidden')
57
+ } else {
58
+ $('.clear-search').addClass('hidden')
59
+ }
60
+ CmFilter.quick_input_search($(this))
61
+ });
62
+
63
+ $(document).on('click', '.clear-search', function(){
64
+ $('#quick-search-input').val('')
65
+ $('.clear-search').addClass('hidden')
66
+ CmFilter.quick_input_search($('#quick-search-input'))
67
+ });
@@ -0,0 +1,43 @@
1
+ $(document).ready(function(e) {
2
+ $('.select-2').select2();
3
+ flatpickr("[data-behaviour='date-only']", {})
4
+ flatpickr("[data-behaviour='date-time']", {
5
+ enableTime: true
6
+ })
7
+ flatpickr("[data-behaviour='filter'][data-filter-type='date']", {
8
+ mode: 'range'
9
+ })
10
+ Sortable.create($('.columns-list')[0],{
11
+ handle: '.dragger',
12
+ animation: 150
13
+ });
14
+ });
15
+
16
+ $(document).on("keypress keyup blur", "[data-behaviour='decimal-only'], [data-behaviour='filter'][data-filter-type='range']", function (e) {
17
+ var charCode = (e.which) ? e.which : e.keyCode
18
+ if (charCode > 31 && (charCode != 46 &&(charCode < 48 || charCode > 57)))
19
+ return false;
20
+ return true;
21
+ });
22
+
23
+ $(document).on("keypress keyup blur", "[data-behaviour='integer-only']", function (event) {
24
+ $(this).val($(this).val().replace(/[^\d].+/, ""));
25
+ if ((event.which < 48 || event.which > 57)) {
26
+ event.preventDefault();
27
+ }
28
+ });
29
+
30
+ $(document).on('click', '.row-action-cell', function(e) {
31
+ e.stopPropagation();
32
+ if ($(this).hasClass('opacity-1')) {
33
+ $('.row-action-cell').removeClass('opacity-1')
34
+ } else {
35
+ $('.row-action-cell').removeClass('opacity-1')
36
+ $(this).addClass('opacity-1');
37
+ }
38
+ if ($(this).find('.table-export-popup').hasClass('hidden')) {
39
+ return $(this).find('.table-export-popup').removeClass('hidden');
40
+ } else {
41
+ return $(this).find('.table-export-popup').addClass('hidden');
42
+ }
43
+ });
@@ -0,0 +1,3 @@
1
+ @import "bootstrap/scss/bootstrap";
2
+ @import "flatpickr/dist/flatpickr";
3
+ @import "../../../../node_modules/daterangepicker/daterangepicker.css";
@@ -0,0 +1,60 @@
1
+ .admin-table-index
2
+ .table-top
3
+ p.table-top__total-count = "#{@associated_ar_object.pagy.count} #{@associated_model.ar_model.table_name} found"
4
+ .table-top__column-action
5
+ button.secondary-btn.column-btn data-target="#columnActionModal" data-toggle="modal" type="button"
6
+ span
7
+ i.fa.fa-columns.bolder
8
+ span
9
+ i.fa.fa-angle-down
10
+
11
+ .new-admin-table.scrollable
12
+ table.cm-table
13
+ thead.cm-table__header
14
+ tr.header-row
15
+ th.check-box-space
16
+ span
17
+ input.cm-checkbox type="checkbox"
18
+ - @model.available_fields[@action.name.to_sym].each do |column|
19
+ th = column.header
20
+ tbody.cm-table__body
21
+ - @associated_ar_object.data.each do |ar_object|
22
+ tr.body-row
23
+ td.check-box-space
24
+ span
25
+ input.cm-checkbox type="checkbox"
26
+ - @model.available_fields[@action.name.to_sym].each do |column|
27
+ td
28
+ span class="#{column.cm_css_class}" = show_field_value(ar_object, column)
29
+ td.row-action-cell
30
+ .row-action-tool
31
+ button.secondary-btn.tool-btn type="button"
32
+ span
33
+ i.fa.fa-bars.bolder
34
+ span
35
+ i.fa.fa-angle-down
36
+ .popup-card.table-export-popup.hidden
37
+ .popup-option
38
+ a href="#{page_url('edit', ar_object)}"
39
+ | Edit
40
+ / .cm-pagination
41
+ / .cm-pagination__lhs Showing 1 to 15 out of 104
42
+ / .cm-pagination__rhs
43
+ / span.page-move-btn.disabled
44
+ / i.fa.fa-angle-double-left.bolder.f14
45
+ / span.page-move-btn.disabled
46
+ / i.fa.fa-chevron-left.bolder
47
+ / span.page-num-btn.active 1
48
+ / span.page-num-btn 2
49
+ / span.page-num-btn 3
50
+ / span.page-num-btn 4
51
+ / span.page-num-btn 5
52
+ / span.page-move-btn
53
+ / i.fa.fa-chevron-right.bolder
54
+ / span.page-move-btn
55
+ / i.fa.fa-angle-double-right.bolder.f14
56
+
57
+ .cm-pagination
58
+ .cm-pagination__lhs Showing #{@associated_ar_object.pagy.from} to #{@associated_ar_object.pagy.to} out of #{@associated_ar_object.pagy.count}
59
+ .cm-pagination__rhs
60
+ == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @associated_ar_object.pagy }
@@ -0,0 +1,23 @@
1
+ - link = pagy_link_proc(pagy)
2
+
3
+ nav.pagy_nav.pagination role="navigation" aria-label="pager"
4
+
5
+ - if pagy.prev
6
+ span ==> link.call(pagy.prev, '<', 'aria-label="previous" class="page-move-btn"')
7
+ - else
8
+ span ==> link.call('#', '<', 'class="page-move-btn disabled"')
9
+
10
+ - pagy.series.each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
11
+ - if item.is_a?(Integer) # page link
12
+ span ==> link.call(item, item, 'class="page-num-btn"')
13
+
14
+ - elsif item.is_a?(String) # current page
15
+ span ==> link.call(item, item, 'class="page-num-btn active"')
16
+
17
+ - elsif item == :gap # page gap
18
+ span.page.gap ==> pagy_t('pagy.nav.gap')
19
+
20
+ - if pagy.next
21
+ span == link.call(pagy.next, '>', 'aria-label="next" class="page-move-btn"')
22
+ - else
23
+ span ==> link.call('#', '>', 'class="page-move-btn disabled"')
@@ -0,0 +1 @@
1
+ = generate_filters(filters)
@@ -0,0 +1,7 @@
1
+ .nested-fields
2
+ - @model.available_fields[action_name.to_sym][assoc_name].each do |field|
3
+ = f.label field.field_name, class: 'field-label'
4
+ br
5
+ = input_field_for_column(f, field)
6
+ - if @reflections.select {|x| x if x.name == assoc_name}.first.macro == :has_many
7
+ = link_to_remove_association "remove #{assoc_name}", f
@@ -0,0 +1,6 @@
1
+ #tasks
2
+ = f.fields_for table_name do |record|
3
+ = render partial: '/cm_admin/main/nested_fields', locals: { f: record, assoc_name: table_name }
4
+ - if @reflections.select {|x| x if x.name == table_name}.first.macro == :has_many
5
+ .links
6
+ = link_to_add_association "add #{table_name}", f, table_name, partial: '/cm_admin/main/nested_fields', render_options: {locals: { assoc_name: table_name }}
@@ -0,0 +1,60 @@
1
+ .admin-table-index
2
+ .table-top
3
+ p.table-top__total-count = "#{@ar_object.pagy.count} #{@model.ar_model.table_name} found"
4
+ .table-top__column-action
5
+ button.secondary-btn.column-btn data-bs-target="#columnActionModal" data-bs-toggle="modal"
6
+ span
7
+ i.fa.fa-columns.bolder
8
+ span
9
+ i.fa.fa-angle-down
10
+
11
+ .new-admin-table.scrollable
12
+ table.cm-table
13
+ thead.cm-table__header
14
+ tr.header-row
15
+ th.check-box-space
16
+ span
17
+ input.cm-checkbox type="checkbox"
18
+ - @model.available_fields[:index].each do |column|
19
+ th = column.header
20
+ tbody.cm-table__body
21
+ - @ar_object.data.each do |ar_object|
22
+ tr.body-row
23
+ td.check-box-space
24
+ span
25
+ input.cm-checkbox type="checkbox"
26
+ - @model.available_fields[:index].each do |column|
27
+ td
28
+ span class="#{column.cm_css_class}" = show_field_value(ar_object, column)
29
+ td.row-action-cell
30
+ .row-action-tool
31
+ button.secondary-btn.tool-btn type="button"
32
+ span
33
+ i.fa.fa-bars.bolder
34
+ span
35
+ i.fa.fa-angle-down
36
+ .popup-card.table-export-popup.hidden
37
+ .popup-option
38
+ a href="#{page_url('edit', ar_object)}"
39
+ | Edit
40
+ / .cm-pagination
41
+ / .cm-pagination__lhs Showing 1 to 15 out of 104
42
+ / .cm-pagination__rhs
43
+ / span.page-move-btn.disabled
44
+ / i.fa.fa-angle-double-left.bolder.f14
45
+ / span.page-move-btn.disabled
46
+ / i.fa.fa-chevron-left.bolder
47
+ / span.page-num-btn.active 1
48
+ / span.page-num-btn 2
49
+ / span.page-num-btn 3
50
+ / span.page-num-btn 4
51
+ / span.page-num-btn 5
52
+ / span.page-move-btn
53
+ / i.fa.fa-chevron-right.bolder
54
+ / span.page-move-btn
55
+ / i.fa.fa-angle-double-right.bolder.f14
56
+
57
+ .cm-pagination
58
+ .cm-pagination__lhs Showing #{@ar_object.pagy.from} to #{@ar_object.pagy.to} out of #{@ar_object.pagy.count}
59
+ .cm-pagination__rhs
60
+ == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @ar_object.pagy }
@@ -0,0 +1,5 @@
1
+ ul.nav.nav-pills
2
+ - @model.available_tabs.each do |nav_item|
3
+ li.nav-item
4
+ - nav_item_action_name = nav_item.custom_action.present? ? nav_item.custom_action : 'show'
5
+ = link_to nav_item.nav_item_name.to_s.titleize, "/cm_admin/#{@model.name.underscore.pluralize}/#{@ar_object.id}/#{nav_item.custom_action}", class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"