cm-admin 1.3.0 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
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