cm-admin 1.3.0 → 1.3.2

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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/app/assets/stylesheets/cm_admin/base/cardView.scss +43 -0
  4. data/app/assets/stylesheets/cm_admin/base/form.scss +0 -19
  5. data/app/assets/stylesheets/cm_admin/base/scaffold.scss +1 -1
  6. data/app/assets/stylesheets/cm_admin/base/table.scss +117 -122
  7. data/app/assets/stylesheets/cm_admin/cm_admin.css.scss +2 -1
  8. data/app/controllers/cm_admin/resource_controller.rb +1 -1
  9. data/app/helpers/cm_admin/application_helper.rb +9 -7
  10. data/app/javascript/packs/cm_admin/scaffolds.js +1 -1
  11. data/app/views/cm_admin/main/_actions_dropdown.html.slim +3 -3
  12. data/app/views/cm_admin/main/_associated_table.html.slim +8 -10
  13. data/app/views/cm_admin/main/_card.html.slim +71 -0
  14. data/app/views/cm_admin/main/_member_custom_action_modal.html.slim +5 -2
  15. data/app/views/cm_admin/main/_nested_fields.html.slim +1 -1
  16. data/app/views/cm_admin/main/_nested_table_form.html.slim +1 -1
  17. data/app/views/cm_admin/main/_nested_table_section.html.slim +4 -4
  18. data/app/views/cm_admin/main/_table.html.slim +24 -21
  19. data/app/views/cm_admin/main/_top_navbar.html.slim +5 -5
  20. data/app/views/cm_admin/main/index.html.slim +2 -0
  21. data/app/views/cm_admin/main/new.html.slim +1 -1
  22. data/app/views/layouts/_custom_action_modals.html.slim +1 -1
  23. data/lib/cm_admin/models/action.rb +4 -3
  24. data/lib/cm_admin/models/column.rb +1 -0
  25. data/lib/cm_admin/models/dsl_method.rb +2 -2
  26. data/lib/cm_admin/models/field.rb +1 -0
  27. data/lib/cm_admin/version.rb +1 -1
  28. data/lib/cm_admin/view_helpers/action_dropdown_helper.rb +3 -3
  29. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f7e6efbcc18df89a3b37963b143cb81564c1ba2aa07df3972d452f7d79a5615e
4
- data.tar.gz: d779de03dae22b2c81c568205a29e3a785c62e4d14bb4a2633c7ee4e9a3c4944
3
+ metadata.gz: 653bbd73e1bb64cbc7a6a56624ffa50d55942e4b1fe42d3be44af91d7e31d14b
4
+ data.tar.gz: 71ebf18e94bca9bce2453688683aad2f35373ab346d7815b992d009aaeb4cfbb
5
5
  SHA512:
6
- metadata.gz: b878ed9eb649bb0838b2901d89f1dee2eab61c03bda22a05dd07d27929e0bfbf0c08aad3c0d6c02ebb652ce989330177d168bf4200707a65983ac1de9724a141
7
- data.tar.gz: 406bf4e9fe8311d52af3e0f733faf8136c19ef3e3f3bc0547e399afaf13d4cf591d555d031120c3fab1f6f0b7e93c7e6aac1e955eab6d22182c0b49356964874
6
+ metadata.gz: b0b8346923b752798b96faf677ef08fd71f6ed343a4baaa8333a49a1feb93b737e6d77f228851e7b63adf66f490ebf6c452cd9b13c8e75677497e2ff8247a89f
7
+ data.tar.gz: 90a247fd04d1b7fdf647c3ace27ba7e9b176e1af000fc5718551ab76dcd87198bdcb2c54cfed2aa3571f2fde0e32520142bca75c8f49a51f57f6400648838d8c
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cm-admin (1.3.0)
4
+ cm-admin (1.3.2)
5
5
  caxlsx_rails
6
6
  cocoon (~> 1.2.15)
7
7
  csv-importer (~> 0.8.2)
@@ -0,0 +1,43 @@
1
+ @import "../helpers/index.scss";
2
+ @import "../dependency/bootstrap/scss/bootstrap";
3
+
4
+ .card-list-container {
5
+ overflow: hidden;
6
+ padding-right: 24px;
7
+ .card-grid {
8
+ @extend .row, .row-cols-4, .g-3;
9
+ }
10
+ .item-card {
11
+ @extend .card, .position-relative;
12
+ border-radius: 4px;
13
+ .card-menu {
14
+ @extend .dropdown, .position-absolute;
15
+ top: 8px;
16
+ right: 8px;
17
+ }
18
+ .card-img-top {
19
+ height: 185px;
20
+ object-fit: cover;
21
+ border-top-left-radius: 4px;
22
+ border-top-right-radius: 4px;
23
+ }
24
+ .card-subtitle {
25
+ @extend .d-flex, .justify-content-between, .text-secondary, .fw-medium;
26
+ font-size: $t4-text;
27
+ .item-id {
28
+ margin: 0;
29
+ span {
30
+ border-left: 1px solid;
31
+ padding-left: 4px;
32
+ }
33
+ }
34
+ }
35
+ .card-footer {
36
+ @extend .d-flex, .justify-content-between, .bg-white;
37
+ .item-price {
38
+ font-size: $t4-text;
39
+ margin: 0;
40
+ }
41
+ }
42
+ }
43
+ }
@@ -72,22 +72,3 @@
72
72
  visibility: hidden;
73
73
  }
74
74
  }
75
-
76
- //Nested form table styles
77
- .nested-form-table-wrapper {
78
- overflow-y: scroll;
79
- .nested-form-table {
80
- @extend .table, .table-light, .table-hover, .table-bordered, .m-0;
81
- width: max-content;
82
- .item-delete-cell {
83
- vertical-align: middle;
84
- text-align: center;
85
- }
86
- }
87
- }
88
-
89
- .nested-table-footer {
90
- padding: 8px;
91
- border: 1px solid var(--bs-border-color);
92
- border-top: 0;
93
- }
@@ -102,7 +102,7 @@ a {
102
102
  }
103
103
 
104
104
  .nested-fields .select2 {
105
- width: 320px !important;
105
+ width: 100% !important;
106
106
  }
107
107
 
108
108
  .datetime-wrapper {
@@ -37,143 +37,97 @@
37
37
  }
38
38
  }
39
39
 
40
- //Table UI styles
41
- .new-admin-table {
40
+ // Table UI v2
41
+ .table-wrapper {
42
42
  min-width: 720px;
43
43
  max-width: fit-content;
44
- // max-height: calc(100vh - 240px); Height is dynamic
44
+ max-height: calc(100vh - 240px);
45
45
  overflow: auto;
46
- .cm-table {
47
- table-layout: fixed;
46
+ .index-table {
47
+ @extend .table, .table-hover;
48
+ border: 1px solid $grey-lighter-clr;
48
49
  position: relative;
49
50
  min-width: 720px;
50
- border-collapse: collapse;
51
- border: 1px solid $grey-lighter-clr;
52
- border-top-width: 0;
53
- border-radius: $radius-8;
54
- &__header {
55
- .header-row {
56
- display: block;
57
- width: 100%;
58
- position: relative;
59
- box-shadow: inset 0px -1px 0px rgba(148, 151, 155, 0.15);
60
- border-top: 1px solid $grey-lighter-clr;
61
- th {
62
- @include font($size: $t6-text, $color: $ink-lighter-clr, $weight: bold);
63
- text-transform: uppercase;
64
- min-width: 200px;
65
- max-width: 200px;
66
- padding: 12px 16px 12px 16px;
67
- }
68
- th:nth-child(1) {
69
- position: sticky;
70
- left: 0;
71
- z-index: 2;
72
- background-color: $white;
73
- border-bottom: 1.21px solid rgb(240, 239, 239);
74
- }
75
- .check-box-space {
76
- position: sticky;
77
- left: 0;
78
- min-width: fit-content;
79
- max-width: fit-content;
80
- padding: 12px 8px 12px 16px;
81
- z-index: 2;
82
- background-color: $white;
83
- border-bottom: 1.21px solid rgb(240, 239, 239);
84
- span {
85
- vertical-align: text-top;
86
- }
87
- }
51
+ margin: 0;
52
+ thead {
53
+ position: sticky;
54
+ top: 0;
55
+ z-index: 4;
56
+ background-color: $white;
57
+ th {
58
+ font-size: 12px;
59
+ min-width: 120px;
60
+ max-width: 240px;
61
+ }
62
+ th:nth-child(1) {
63
+ position: sticky;
64
+ left: 0;
65
+ z-index: 2;
66
+ background-color: $white;
67
+ }
68
+ th:nth-child(2) {
69
+ position: sticky;
70
+ left: 32px;
71
+ z-index: 2;
72
+ background-color: $white;
88
73
  }
89
74
  }
90
- &__body {
91
- display: block;
92
- position: relative;
93
- width: 100%;
94
- background-color: $white;
95
- .body-row {
96
- display: flex;
97
- border-bottom: 1.21px solid rgb(240, 239, 239);
98
- td:nth-child(1) {
99
- position: sticky;
100
- left: 0;
101
- z-index: 2;
102
- background-color: $white;
103
- }
104
- &:nth-last-child(1) {
105
- box-shadow: none;
106
- }
75
+
76
+ tbody {
77
+ tr {
78
+ border-bottom: 1px solid var(--bs-border-color);
107
79
  &:hover {
108
- background-color: $grey-lighter-clr;
109
- td:nth-child(1) {
110
- background-color: $grey-lighter-clr;
111
- }
112
80
  .row-action-cell {
113
- display: inline-block;
114
- }
115
- }
116
- .check-box-space {
117
- position: sticky;
118
- left: 0;
119
- min-width: fit-content;
120
- max-width: fit-content;
121
- padding: 16px 8px 16px 16px;
122
- z-index: 2;
123
- background-color: $white;
124
- span {
125
- vertical-align: text-top;
81
+ visibility: visible;
126
82
  }
127
83
  }
128
- td {
129
- @include font($size: $t4-text, $color: $primary-text-clr);
130
- min-width: 200px;
131
- max-width: 200px;
132
- padding: 16px;
133
- }
134
- .row-action-cell {
135
- position: sticky;
136
- right: 0;
137
- width: 88px;
138
- max-width: inherit;
139
- min-width: inherit;
140
- height: 53px;
141
- padding: 0;
142
- background: $gradient-one;
143
- display: none;
144
- transition: all 0.1s linear;
145
- z-index: 3;
146
- .row-action-tool {
147
- display: flex;
148
- align-items: center;
149
- justify-content: center;
150
- height: 100%;
151
- .popup-card {
152
- .popup-option {
153
- a {
154
- @include font($size: $t4-text, $color: $ink-regular-clr, $weight: 500);
155
- line-height: 22px;
156
- }
157
- }
158
- button {
159
- background: none;
160
- border: none;
161
- width: 100%;
162
- text-align: left;
163
- padding: 0px;
164
- }
84
+ }
85
+ td {
86
+ font-size: $t4-text;
87
+ min-width: 120px;
88
+ max-width: 240px;
89
+ }
90
+ td:nth-child(1) {
91
+ position: sticky;
92
+ left: 0;
93
+ z-index: 2;
94
+ background-color: $white;
95
+ }
96
+ td:nth-child(2) {
97
+ position: sticky;
98
+ left: 32px;
99
+ z-index: 2;
100
+ background-color: $white;
101
+ }
102
+ }
103
+
104
+ .check-box-space {
105
+ min-width: 32px;
106
+ max-width: 32px;
107
+ font-size: $t4-text;
108
+ }
109
+
110
+ .row-action-cell {
111
+ position: sticky;
112
+ right: 0;
113
+ max-width: inherit;
114
+ min-width: inherit;
115
+ padding: 4px;
116
+ background: $gradient-one;
117
+ visibility: hidden;
118
+ z-index: 3;
119
+ .row-action-tool {
120
+ .popup-card {
121
+ .popup-option {
122
+ a {
123
+ @include font($size: $t4-text, $color: $ink-regular-clr, $weight: 500);
124
+ line-height: 22px;
165
125
  }
166
126
  }
167
127
  }
168
128
  }
169
129
  }
170
130
  }
171
- .cm-table > thead {
172
- position: sticky;
173
- top: 0;
174
- background-color: $white;
175
- z-index: 4;
176
- }
177
131
  }
178
132
 
179
133
  // table-column-modal
@@ -266,7 +220,7 @@
266
220
  bottom: 0;
267
221
  left: 0;
268
222
  border: 1px solid $grey-lighter-clr;
269
- box-shadow: inset 0px 1px 0px rgba(148, 151, 155, 0.3);
223
+ box-shadow: 0px 1px 0px 0px rgba(148, 151, 155, 0.3) inset;
270
224
  z-index: 2;
271
225
  .count-text {
272
226
  @include font($size: $t4-text, $color: var(--bs-body-color));
@@ -281,11 +235,52 @@
281
235
  }
282
236
  }
283
237
 
284
- //Nested table styles
238
+ [data-field-type="money"] {
239
+ text-align: right;
240
+ }
241
+
242
+ //Nested show table styles
285
243
  .nested-table-wrapper {
286
244
  overflow-y: scroll;
287
245
  .nested-table {
288
246
  @extend .table, .table-light, .table-hover, .table-bordered;
289
247
  width: max-content;
290
248
  }
249
+ th,
250
+ td {
251
+ min-width: 120px;
252
+ max-width: 240px;
253
+ }
254
+ }
255
+
256
+ //Nested form table styles
257
+ .nested-form-table-wrapper {
258
+ overflow-y: scroll;
259
+ .nested-form-table {
260
+ @extend .table, .table-light, .table-hover, .table-bordered, .m-0;
261
+ width: max-content;
262
+ .item-delete-cell {
263
+ vertical-align: middle;
264
+ text-align: center;
265
+ }
266
+ }
267
+ th:nth-child(1) {
268
+ min-width: 47px;
269
+ max-width: 47px;
270
+ }
271
+ td:nth-child(1) {
272
+ min-width: 47px;
273
+ max-width: 47px;
274
+ }
275
+ th,
276
+ td {
277
+ min-width: 120px;
278
+ max-width: 240px;
279
+ }
280
+ }
281
+
282
+ .nested-table-footer {
283
+ padding: 8px;
284
+ border: 1px solid var(--bs-border-color);
285
+ border-top: 0;
291
286
  }
@@ -22,6 +22,7 @@
22
22
  *= require 'cm_admin/base/auth'
23
23
  *= require 'cm_admin/base/filters'
24
24
  *= require 'cm_admin/base/common'
25
+ *= require 'cm_admin/base/cardView'
25
26
  *= require 'cm_admin/components/index'
26
27
  *= require 'cm_admin/dependency/bootstrap.min'
27
28
  *= require 'cm_admin/dependency/flatpickr.min'
@@ -29,4 +30,4 @@
29
30
  *= require 'cm_admin/dependency/jquery-jgrowl.min'
30
31
  *= require 'cm_admin/scaffold'
31
32
  *= require_self
32
- */
33
+ */
@@ -172,7 +172,7 @@ module CmAdmin
172
172
 
173
173
  def resource_identifier
174
174
  @ar_object, @associated_model, @associated_ar_object = custom_controller_action(action_name, params.permit!) if !@ar_object.present? && params[:id].present?
175
- authorize controller_name.classify.constantize, policy_class: "CmAdmin::#{controller_name.classify}Policy".constantize if defined? "CmAdmin::#{controller_name.classify}Policy".constantize
175
+ authorize @ar_object, policy_class: "CmAdmin::#{controller_name.classify}Policy".constantize if defined? "CmAdmin::#{controller_name.classify}Policy".constantize
176
176
  aar_model = request.url.split('/')[-2].classify.constantize if params[:aar_id]
177
177
  @associated_ar_object = aar_model.find(params[:aar_id]) if params[:aar_id]
178
178
  nested_fields = get_nested_table_fields(@model.available_fields[:new])
@@ -6,9 +6,11 @@ module CmAdmin
6
6
  end
7
7
 
8
8
  # Allow if policy is not defined.
9
- def has_valid_policy(model_name, action_name)
10
- return true unless policy([:cm_admin, model_name.classify.constantize]).methods.include?(:"#{action_name}?")
11
- policy([:cm_admin, model_name.classify.constantize]).send(:"#{action_name}?")
9
+ def has_valid_policy(ar_object, action_name)
10
+ policy_object = ar_object.instance_of?(OpenStruct) ? @model.name.classify.constantize : ar_object
11
+ return true unless policy([:cm_admin, policy_object]).methods.include?(:"#{action_name}?")
12
+
13
+ policy([:cm_admin, policy_object]).send(:"#{action_name}?")
12
14
  end
13
15
 
14
16
  def action(action_name)
@@ -63,14 +65,14 @@ module CmAdmin
63
65
  end
64
66
  end
65
67
 
66
- def is_show_action_available(model)
68
+ def is_show_action_available(model, ar_object)
67
69
  model &&
68
70
  model.available_actions.map(&:name).include?('show') &&
69
- has_valid_policy(model.name, 'show')
71
+ has_valid_policy(ar_object, 'show')
70
72
  end
71
73
 
72
- def actions_filter(model, action_type)
73
- model.available_actions.select { |action| action.action_type == action_type && has_valid_policy(model.name, action.name) }
74
+ def actions_filter(model, ar_object, action_type)
75
+ model.available_actions.select { |action| action.action_type == action_type && has_valid_policy(ar_object, action.name) }
74
76
  end
75
77
  end
76
78
  end
@@ -20,5 +20,5 @@ $(document).on('turbolinks:load', function () {
20
20
  }
21
21
  var headerElemHeight = $('.page-top-bar').height() + 64
22
22
  var calculatedHeight = "calc(100vh - " + headerElemHeight+"px"+")"
23
- $('.new-admin-table').css("maxHeight", calculatedHeight);
23
+ $('.table-wrapper').css("maxHeight", calculatedHeight);
24
24
  });
@@ -1,6 +1,6 @@
1
- - edit_action = available_actions(cm_model, 'edit')
2
- - destroy_action = available_actions(cm_model, 'destroy')
3
- - custom_actions = available_actions(cm_model, 'custom_actions')
1
+ - edit_action = available_actions(cm_model, ar_object, 'edit')
2
+ - destroy_action = available_actions(cm_model, ar_object, 'destroy')
3
+ - custom_actions = available_actions(cm_model, ar_object, 'custom_actions')
4
4
  - current_model = @associated_model || @model
5
5
  - if custom_actions.any? || edit_action.present? || destroy_action.present?
6
6
  td.row-action-cell
@@ -4,7 +4,7 @@
4
4
  == render partial: 'cm_admin/main/filters', locals: { filters: @associated_model.filters }
5
5
  p.table-top__total-count = "#{humanized_ar_collection_count(@associated_ar_object.pagy.count, @action.child_records.to_s)}"
6
6
  .table-top__column-action
7
- - if @associated_model && @associated_model.available_actions.map(&:name).include?('new') && has_valid_policy(@associated_model.name, 'new')
7
+ - if @associated_model && @associated_model.available_actions.map(&:name).include?('new') && has_valid_policy(@associated_ar_object, 'new')
8
8
  - association = @ar_object.class.reflect_on_all_associations.select{|x| x.name == @associated_model.name.tableize.to_sym }.first
9
9
  - polymorphic_name = (association && association.inverse_of && association.inverse_of.options[:polymorphic]) ? association.inverse_of.name : ''
10
10
  a href="#{CmAdmin::Engine.mount_path}/#{@associated_model.name.tableize}/new?associated_id=#{@ar_object.id}&associated_class=#{@ar_object.class.name.underscore}&polymorphic_name=#{polymorphic_name}&referrer=#{request.path}"
@@ -20,13 +20,13 @@
20
20
  - elsif flash[:notice].present?
21
21
  .alert.alert-success
22
22
  = flash[:notice].html_safe
23
- - bulk_actions = actions_filter(@associated_model, :bulk_action)
23
+ - bulk_actions = actions_filter(@associated_model, @associated_ar_object, :bulk_action)
24
24
  - if bulk_actions.present?
25
25
  .table-top.hidden data-section="bulk-action"
26
26
  - bulk_actions.each do |action|
27
27
  = custom_action_items(action, 'index')
28
- .new-admin-table.scrollable
29
- table.cm-table
28
+ .table-wrapper
29
+ table.index-table
30
30
  thead.cm-table__header
31
31
  tr.header-row
32
32
  - if bulk_actions.present?
@@ -47,7 +47,7 @@
47
47
  - if column.display_if.call(Current.user) && column.viewable
48
48
  td class="text-ellipsis"
49
49
  span class="#{column.field_type.to_s} #{column.cm_css_class} "
50
- - if index == 0 && is_show_action_available(@associated_model)
50
+ - if index == 0 && is_show_action_available(@associated_model, ar_object)
51
51
  a href="#{CmAdmin::Engine.mount_path}/#{@associated_model.name.tableize}/#{ar_object.id}" = show_field_value(ar_object, column)
52
52
  - else
53
53
  = show_field_value(ar_object, column)
@@ -57,9 +57,7 @@
57
57
  - if @associated_model
58
58
  == render partial: 'cm_admin/main/actions_dropdown', locals: { cm_model: @associated_model, ar_object: ar_object }
59
59
 
60
- .cm-pagination
61
- .cm-pagination__lhs Showing #{@associated_ar_object.pagy.from} to #{@associated_ar_object.pagy.to} out of #{@associated_ar_object.pagy.count}
62
- .cm-pagination__rhs
63
- == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @associated_ar_object.pagy }
64
-
60
+ .pagination-bar
61
+ p.count-text.m-0 Showing #{@associated_ar_object.pagy.from} to #{@associated_ar_object.pagy.to} out of #{@associated_ar_object.pagy.count}
62
+ == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @associated_ar_object.pagy }
65
63
  = render partial: 'cm_admin/main/member_custom_action_modal', locals: { cm_model: @associated_model, ar_collection: @associated_ar_object }
@@ -0,0 +1,71 @@
1
+ // Card view right now is application specific, so card partial will be overwritten in the application
2
+
3
+ .table-top
4
+ p.table-top__total-count = "#{humanized_ar_collection_count(@ar_object.pagy.count, @model.ar_model.table_name)}"
5
+ .table-top__column-action
6
+ .btn-group[role="group" aria-label="Basic example"]
7
+ a.btn.btn-ghost href="#{cm_admin.send("#{@model.name.underscore}_index_path")}?page=#{params[:page] || 1}"
8
+ i.fa.fa-table
9
+ a.btn.btn-ghost href="#{cm_admin.send("#{@model.name.underscore}_index_path")}?page=#{params[:page] || 1}&list_type=card"
10
+ i.fa.fa-table-cells
11
+ / button.secondary-btn.column-btn data-bs-target="#columnActionModal" data-bs-toggle="modal"
12
+ / span
13
+ / i.fa.fa-columns.bolder
14
+ / span
15
+ / i.fa.fa-angle-down
16
+ - if flash[:alert].present?
17
+ .alert.alert-danger role="alert"
18
+ = flash[:alert].html_safe
19
+ - elsif flash[:notice].present?
20
+ .alert.alert-success
21
+ = flash[:notice].html_safe
22
+
23
+ - bulk_actions = actions_filter(@model, @ar_object, :bulk_action)
24
+ - if bulk_actions.present?
25
+ .table-top.hidden data-section="bulk-action"
26
+ - bulk_actions.each do |action|
27
+ = custom_action_items(action, 'index')
28
+ .card-list-container
29
+ .card-grid
30
+ - @ar_object.data.each_slice(3) do |chunk|
31
+ - chunk.each do |ar_object|
32
+ .col
33
+ .item-card
34
+ .card-menu
35
+ .row-action-cell
36
+ == render partial: 'cm_admin/main/actions_dropdown', locals: { cm_model: @model, ar_object: ar_object }
37
+ img.card-img-top[src="https://images.unsplash.com/photo-1658211312038-4293c7bdd37e?auto=format&fit=crop&q=80&w=3280&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D" alt="..."]
38
+ .card-body
39
+ - @model.available_fields[:index].each_with_index do |column, index|
40
+ - if column.display_if.call(Current.user) && column.viewable
41
+ - if index == 0 && is_show_action_available(@model, ar_object) && !([:link, :custom, :attachment, :drawer, :image].include?(column.field_type))
42
+ h6.card-title
43
+ | Coffee table
44
+ .card-subtitle
45
+ p.item-id
46
+ | TB-6910
47
+ span
48
+ | Table
49
+ p.m-0
50
+ | Nadim
51
+ / h6.card-title
52
+ / = link_to ar_object.send(column.field_name), cm_admin.send("#{ar_object.model_name.singular}_show_path", ar_object.id)
53
+ - else
54
+ p.card-text
55
+ = show_field_value(ar_object, column)
56
+ - if column.field_type == :drawer
57
+ = render partial: column.drawer_partial, locals: { ar_object: ar_object }
58
+ .card-footer
59
+ p.item-price
60
+ | L.E 100,000
61
+ .item-status
62
+ span.status-tag.danger
63
+ | Out of stock
64
+ span.status-tag.active.ms-1
65
+ | Active
66
+
67
+ .pagination-bar
68
+ p.count-text.m-0 Showing #{@ar_object.pagy.from} to #{@ar_object.pagy.to} out of #{@ar_object.pagy.count}
69
+ == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @ar_object.pagy }
70
+
71
+ / = render partial: 'cm_admin/main/member_custom_action_modal', locals: { cm_model: @model, ar_collection: @ar_object }
@@ -1,4 +1,4 @@
1
- - custom_actions = available_actions(cm_model, 'custom_actions')
1
+ - custom_actions = available_actions(cm_model, ar_object, 'custom_actions')
2
2
  - custom_actions_modals = custom_actions.select{ |act| act if act.display_type.eql?(:modal) }
3
3
  - ar_collection.data.each do |ar_object|
4
4
  - if custom_actions_modals.any?
@@ -10,4 +10,7 @@
10
10
  h5.modal-title id="#{custom_action.name.classify}ModalLabel" = custom_action_title(custom_action)
11
11
  button.btn-close aria-label='Close' data-bs-dismiss='modal'
12
12
  .modal-body
13
- = render partial: custom_action.partial, locals: { ar_object: ar_object }
13
+ - if custom_action.partial
14
+ = render partial: custom_action.partial
15
+ - else
16
+ = render partial: 'cm_admin/main/custom_action_modal_form', locals: { custom_action: custom_action, ar_object: ar_object }
@@ -3,7 +3,7 @@
3
3
  td.item-delete-cell
4
4
  = link_to_remove_association "", f, class: 'fa-regular fa-trash-can btn-ghost'
5
5
  - nested_table_field.fields.each do |field|
6
- td
6
+ td data-field-type="#{field.input_type}"
7
7
  = input_field_for_column(f, field)
8
8
  - else
9
9
  .form-card.nested-fields
@@ -11,7 +11,7 @@
11
11
  th
12
12
  |
13
13
  - nested_table_field.fields.each do |field|
14
- th
14
+ th data-field-type="#{field.input_type}"
15
15
  = field.field_name.to_s.titleize
16
16
  tbody class="insert-cocoon-position-#{uniq_no}"
17
17
  = f.fields_for table_name do |record|
@@ -3,22 +3,22 @@
3
3
  div class="#{nested_field.label ? 'card-info' : ''}"
4
4
  - if nested_field.label
5
5
  p.card-info__label = nested_field.label.to_s.titleize
6
- .card-info__description.nested-table-wrapper
6
+ .card-info__description.nested-table-wrapper data-table-name="#{nested_field.field_name}"
7
7
  table.nested-table
8
8
  thead
9
9
  tr
10
10
  - nested_field.fields.each do |field|
11
- th scope="col"
11
+ th scope="col" data-field-type="#{field.field_type}"
12
12
  = field.label || field.field_name.to_s.titleize
13
13
  tbody
14
14
  - associated_records.each do |record|
15
15
  tr
16
16
  - nested_field.fields.each do |field|
17
- td
17
+ td data-field-type="#{field.field_type}"
18
18
  = record.send(field.field_name)
19
19
  - else
20
20
  - associated_records.each do |record|
21
- .card.mb-3
21
+ .card.mb-3 data-table-name="#{nested_field.field_name}"
22
22
  .card-body
23
23
  .card-info
24
24
  .card-info__title = nested_section_title(record, nested_field)
@@ -1,6 +1,12 @@
1
1
  .table-top
2
2
  p.table-top__total-count = "#{humanized_ar_collection_count(@ar_object.pagy.count, @model.ar_model.table_name)}"
3
- / .table-top__column-action
3
+ .table-top__column-action
4
+ - if @current_action.card_layout
5
+ .btn-group[role="group" aria-label="Card Toggle"]
6
+ a.btn.btn-ghost href="#{cm_admin.send("#{@model.name.underscore}_index_path")}?page=#{params[:page] || 1}"
7
+ i.fa.fa-table
8
+ a.btn.btn-ghost href="#{cm_admin.send("#{@model.name.underscore}_index_path")}?page=#{params[:page] || 1}&list_type=card"
9
+ i.fa.fa-table-cells
4
10
  / button.secondary-btn.column-btn data-bs-target="#columnActionModal" data-bs-toggle="modal"
5
11
  / span
6
12
  / i.fa.fa-columns.bolder
@@ -13,42 +19,39 @@
13
19
  .alert.alert-success
14
20
  = flash[:notice].html_safe
15
21
 
16
- - bulk_actions = actions_filter(@model, :bulk_action)
22
+ - bulk_actions = actions_filter(@model, @ar_object, :bulk_action)
17
23
  - if bulk_actions.present?
18
24
  .table-top.hidden data-section="bulk-action"
19
25
  - bulk_actions.each do |action|
20
26
  = custom_action_items(action, 'index')
21
- .new-admin-table
22
- table.cm-table
23
- thead.cm-table__header
24
- tr.header-row
27
+ .table-wrapper
28
+ table.index-table
29
+ thead
30
+ tr
25
31
  - if bulk_actions.present?
26
32
  th.check-box-space
27
- span
28
- input.cm-checkbox type="checkbox" data-behaviour="bulk-action-select-all"
33
+ input.form-check-input type="checkbox" data-behaviour="bulk-action-select-all"
29
34
  - @model.available_fields[:index].each do |column|
30
35
  - if column.display_if.call(Current.user) && column.viewable
31
- th = column.header
32
- tbody.cm-table__body
36
+ th data-field-type="#{column.field_type}" = column.header
37
+ th
38
+ tbody
33
39
  - @ar_object.data.each do |ar_object|
34
40
  tr.body-row
35
41
  - if bulk_actions.present?
36
42
  td.check-box-space
37
- span
38
- input.cm-checkbox type="checkbox" data-behaviour="bulk-action-checkbox" data-ar-object-id="#{ar_object.id}"
43
+ input.form-check-input type="checkbox" data-behaviour="bulk-action-checkbox" data-ar-object-id="#{ar_object.id}"
39
44
  - @model.available_fields[:index].each_with_index do |column, index|
40
45
  - if column.display_if.call(Current.user) && column.viewable
41
- td.text-ellipsis
42
- span class="#{column.field_type.to_s} #{column.cm_css_class} "
43
- - if index == 0 && is_show_action_available(@model) && !([:link, :custom, :attachment, :drawer, :image].include?(column.field_type))
44
- = link_to ar_object.send(column.field_name), cm_admin.send("#{ar_object.model_name.singular}_show_path", ar_object.id)
45
- - else
46
- = show_field_value(ar_object, column)
47
- - if column.field_type == :drawer
48
- = render partial: column.drawer_partial, locals: { ar_object: ar_object }
46
+ td.text-ellipsis data-field-type="#{column.field_type || 'string'}"
47
+ - if index == 0 && is_show_action_available(@model, ar_object) && !([:link, :custom, :attachment, :drawer, :image].include?(column.field_type))
48
+ = link_to ar_object.send(column.field_name), cm_admin.send("#{ar_object.model_name.singular}_show_path", ar_object.id)
49
+ - else
50
+ = show_field_value(ar_object, column)
51
+ - if column.field_type == :drawer
52
+ = render partial: column.drawer_partial, locals: { ar_object: ar_object }
49
53
  - if @model
50
54
  == render partial: 'cm_admin/main/actions_dropdown', locals: { cm_model: @model, ar_object: ar_object }
51
-
52
55
  .pagination-bar
53
56
  p.count-text.m-0 Showing #{@ar_object.pagy.from} to #{@ar_object.pagy.to} out of #{@ar_object.pagy.count}
54
57
  == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @ar_object.pagy }
@@ -8,7 +8,7 @@
8
8
  p.mb-0.text-body-secondary = @model.current_action.page_description
9
9
  .entity-header__actions
10
10
  - if @model.current_action.name == 'index'
11
- - if has_valid_policy(@model.name, :exportable)
11
+ - if has_valid_policy(@ar_object, :exportable)
12
12
  .export-container
13
13
  .dropdown
14
14
  button.btn-secondary.dropdown-toggle data-bs-toggle='dropdown'
@@ -18,10 +18,10 @@
18
18
  li
19
19
  .popup-option.pointer data-bs-toggle='modal' data-bs-target='#exportmodal'
20
20
  span Export
21
- - if @model.importer && has_valid_policy(@model.name, :importable)
21
+ - if @model.importer && has_valid_policy(@ar_object, :importable)
22
22
  = link_to 'Import', cm_admin.send(:"#{@model.name.underscore}_import_path"), class: 'btn-primary ms-2'
23
23
  - new_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('new')}
24
- - if new_action.any? && policy([:cm_admin, @model.name.classify.constantize]).new?
24
+ - if new_action.any? && has_valid_policy(@ar_object, 'new')
25
25
  = link_to 'Add', cm_admin.send(:"#{@model.name.underscore}_new_path"), class: 'btn-primary ms-2'
26
26
  - @model.available_actions.select{|act| act if act.route_type == 'collection'}.each do |custom_action|
27
27
  = custom_action_items(custom_action, 'index')
@@ -30,8 +30,8 @@
30
30
  = custom_action_items(custom_action, 'show')
31
31
 
32
32
  - edit_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('edit')}
33
- - destroy_action = available_actions(@model, 'destroy')
34
- - if edit_action.any? && policy([:cm_admin, @model.name.classify.constantize]).edit?
33
+ - destroy_action = available_actions(@model, @ar_object, 'destroy')
34
+ - if edit_action.any? && has_valid_policy(@ar_object, 'edit')
35
35
  = link_to cm_admin.send(:"#{@model.name.underscore}_edit_path", @ar_object), class: 'btn-primary ms-2' do
36
36
  span
37
37
  i.fa.fa-edit
@@ -8,6 +8,8 @@
8
8
  .cm-index-page__table-container
9
9
  - if @action.partial
10
10
  == render @action.partial
11
+ - elsif params[:list_type] == 'card'
12
+ == render 'cm_admin/main/card'
11
13
  - else
12
14
  == render 'cm_admin/main/table'
13
15
  = column_pop_up(@model)
@@ -10,7 +10,7 @@
10
10
  | Attention
11
11
  .alert-body
12
12
  p.body-title
13
- | Error saving #{@ar_object.class}
13
+ | Error: unable to save #{@ar_object.class.downcase}
14
14
  p.body-info
15
15
  ul
16
16
  - @ar_object.errors.full_messages.each do |error_message|
@@ -1,6 +1,6 @@
1
1
  - custom_action_with_modals = @model.available_actions.select{ |act| act if act.display_type == :modal && act.action_type == :custom }
2
2
  - bulk_action_with_modals = @model.available_actions.select{ |act| act if act.display_type == :modal && act.action_type == :bulk_action }
3
- - destroy_action = available_actions(@model, 'destroy')
3
+ - destroy_action = available_actions(@model, @ar_object, 'destroy')
4
4
  - if @associated_model
5
5
  - custom_action_with_modals += @associated_model.available_actions.select{ |act| act if act.display_type == :modal }
6
6
  - if @current_action&.name == 'index'
@@ -6,7 +6,7 @@ module CmAdmin
6
6
  include Actions::Blocks
7
7
  attr_accessor :name, :display_name, :verb, :layout_type, :layout, :partial, :path, :page_title, :page_description,
8
8
  :child_records, :is_nested_field, :nested_table_name, :parent, :display_if, :route_type, :code_block,
9
- :display_type, :action_type, :redirection_url, :sort_direction, :sort_column, :icon_name, :scopes
9
+ :display_type, :action_type, :redirection_url, :sort_direction, :sort_column, :icon_name, :scopes, :card_layout
10
10
 
11
11
  VALID_SORT_DIRECTION = Set[:asc, :desc].freeze
12
12
 
@@ -39,13 +39,14 @@ module CmAdmin
39
39
  self.verb = :get
40
40
  self.route_type = nil
41
41
  self.display_type = nil
42
-
42
+ self.card_layout = false
43
43
  end
44
44
 
45
- def set_values(page_title, page_description, partial)
45
+ def set_values(page_title, page_description, partial, card_layout=false)
46
46
  self.page_title = page_title
47
47
  self.page_description = page_description
48
48
  self.partial = partial
49
+ self.card_layout = card_layout
49
50
  end
50
51
 
51
52
  def controller_action_name
@@ -43,6 +43,7 @@ module CmAdmin
43
43
  self.lockable = false
44
44
  self.viewable = true
45
45
  self.tag_class = {}
46
+ self.field_type = :string
46
47
  end
47
48
 
48
49
  class << self
@@ -3,9 +3,9 @@ module CmAdmin
3
3
  module DslMethod
4
4
  extend ActiveSupport::Concern
5
5
 
6
- def cm_index(page_title: nil, page_description: nil, partial: nil, &block)
6
+ def cm_index(page_title: nil, page_description: nil, partial: nil, card_layout: false, &block)
7
7
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'index')
8
- @current_action.set_values(page_title, page_description, partial)
8
+ @current_action.set_values(page_title, page_description, partial, card_layout)
9
9
  yield
10
10
  end
11
11
 
@@ -25,6 +25,7 @@ module CmAdmin
25
25
  def set_default_values
26
26
  self.tag_class = {}
27
27
  self.col_size = nil
28
+ self.field_type = :string
28
29
  end
29
30
  end
30
31
  end
@@ -1,3 +1,3 @@
1
1
  module CmAdmin
2
- VERSION = '1.3.0'
2
+ VERSION = '1.3.2'
3
3
  end
@@ -1,19 +1,19 @@
1
1
  module CmAdmin
2
2
  module ViewHelpers
3
3
  module ActionDropdownHelper
4
- def available_actions(cm_model, action_type)
4
+ def available_actions(cm_model, ar_object, action_type)
5
5
  if action_type.eql?('custom_actions')
6
6
  cm_model.available_actions.select {
7
7
  |act| act if act.route_type.eql?('member') &&
8
8
  [:button, :modal].include?(act.display_type) &&
9
9
  act.name.present? &&
10
- has_valid_policy(cm_model.name, act.name)
10
+ has_valid_policy(ar_object, act.name)
11
11
  }
12
12
  else
13
13
  cm_model.available_actions.select {
14
14
  |act| act if act.action_type.eql?(:default) &&
15
15
  act.name.eql?(action_type)
16
- } if has_valid_policy(cm_model.name, action_type)
16
+ } if has_valid_policy(ar_object, action_type)
17
17
  end
18
18
  end
19
19
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cm-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - sajinmp
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2023-10-20 00:00:00.000000000 Z
13
+ date: 2023-11-02 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -201,6 +201,7 @@ files:
201
201
  - app/assets/javascripts/cm_admin/scaffolds.js
202
202
  - app/assets/javascripts/cm_admin/shared_scaffolds.js
203
203
  - app/assets/stylesheets/cm_admin/base/auth.scss
204
+ - app/assets/stylesheets/cm_admin/base/cardView.scss
204
205
  - app/assets/stylesheets/cm_admin/base/common.scss
205
206
  - app/assets/stylesheets/cm_admin/base/filters.scss
206
207
  - app/assets/stylesheets/cm_admin/base/form.scss
@@ -348,6 +349,7 @@ files:
348
349
  - app/policies/cm_admin/file_import_policy.rb
349
350
  - app/views/cm_admin/main/_actions_dropdown.html.slim
350
351
  - app/views/cm_admin/main/_associated_table.html.slim
352
+ - app/views/cm_admin/main/_card.html.slim
351
353
  - app/views/cm_admin/main/_cm_pagy_nav.html.slim
352
354
  - app/views/cm_admin/main/_custom_action_modal_form.html.slim
353
355
  - app/views/cm_admin/main/_drawer.html.slim