integral 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +4 -3
  3. data/app/assets/javascripts/integral/backend.js +86 -2
  4. data/app/assets/javascripts/integral/support/character_counter.js +13 -8
  5. data/app/assets/javascripts/integral/support/list.coffee +1 -0
  6. data/app/assets/javascripts/integral/support/record_selector.coffee +2 -0
  7. data/app/assets/javascripts/integral/support/slug_generator.coffee +1 -0
  8. data/app/assets/stylesheets/integral/backend.sass +34 -23
  9. data/app/assets/stylesheets/integral/backend/_foundation_settings.scss +2 -2
  10. data/app/assets/stylesheets/integral/backend/dashboard-layout.scss +27 -63
  11. data/app/assets/stylesheets/integral/backend/devise.sass +2 -3
  12. data/app/assets/stylesheets/integral/backend/materialize-tags.sass +1 -0
  13. data/app/assets/stylesheets/integral/backend/modules/dropdown_pane_notifications.scss +150 -0
  14. data/app/assets/stylesheets/integral/backend/modules/dropdown_pane_profile.scss +59 -0
  15. data/app/assets/stylesheets/integral/backend/shared.sass +41 -2
  16. data/app/assets/stylesheets/integral/frontend/layout.sass +10 -0
  17. data/app/assets/stylesheets/integral/support/media-query-indicator.sass +4 -4
  18. data/app/controllers/integral/backend/activities_controller.rb +21 -27
  19. data/app/controllers/integral/backend/base_controller.rb +87 -37
  20. data/app/controllers/integral/backend/images_controller.rb +26 -8
  21. data/app/controllers/integral/backend/lists_controller.rb +2 -14
  22. data/app/controllers/integral/backend/notification_subscriptions_controller.rb +23 -0
  23. data/app/controllers/integral/backend/pages_controller.rb +0 -4
  24. data/app/controllers/integral/backend/posts_controller.rb +0 -4
  25. data/app/controllers/integral/backend/settings_controller.rb +4 -0
  26. data/app/controllers/integral/backend/static_pages_controller.rb +6 -0
  27. data/app/controllers/integral/backend/users_controller.rb +43 -24
  28. data/app/controllers/integral/blog_controller.rb +12 -0
  29. data/app/controllers/integral/categories_controller.rb +17 -3
  30. data/app/controllers/integral/tags_controller.rb +5 -2
  31. data/app/decorators/integral/base_decorator.rb +16 -0
  32. data/app/decorators/integral/image_decorator.rb +2 -2
  33. data/app/decorators/integral/list_decorator.rb +1 -13
  34. data/app/decorators/integral/notification/notification_decorator.rb +74 -0
  35. data/app/decorators/integral/page_decorator.rb +1 -13
  36. data/app/decorators/integral/post_decorator.rb +1 -2
  37. data/app/decorators/integral/user_decorator.rb +1 -13
  38. data/app/decorators/integral/version_decorator.rb +8 -4
  39. data/app/helpers/integral/backend/base_helper.rb +97 -31
  40. data/app/jobs/integral/application_job.rb +1 -0
  41. data/app/jobs/integral/newsletter_signup_job.rb +0 -2
  42. data/app/mailers/integral/devise_mailer.rb +6 -0
  43. data/app/models/concerns/integral/notification/subscribable.rb +67 -0
  44. data/app/models/integral/application_record.rb +9 -0
  45. data/app/models/integral/category.rb +9 -0
  46. data/app/models/integral/image.rb +40 -3
  47. data/app/models/integral/list.rb +10 -2
  48. data/app/models/integral/list_item.rb +14 -14
  49. data/app/models/integral/list_item_connection.rb +6 -0
  50. data/app/models/integral/notification/notification.rb +28 -0
  51. data/app/models/integral/notification/subscription.rb +14 -0
  52. data/app/models/integral/page.rb +15 -8
  53. data/app/models/integral/post.rb +11 -13
  54. data/app/models/integral/user.rb +45 -2
  55. data/app/policies/integral/base_policy.rb +7 -12
  56. data/app/policies/integral/page_policy.rb +1 -0
  57. data/app/policies/integral/version_policy.rb +0 -8
  58. data/app/views/devise/invitations/edit.haml +1 -4
  59. data/app/views/devise/mailer/invitation_instructions.inky-haml +20 -0
  60. data/app/views/integral/backend/activities/grid/_dropdown_actions.haml +1 -0
  61. data/app/views/integral/backend/activities/grid/_row_content.haml +13 -0
  62. data/app/views/integral/backend/activities/index.haml +7 -13
  63. data/app/views/integral/backend/activities/shared/_grid.haml +35 -20
  64. data/app/views/integral/backend/activities/shared/index.haml +12 -12
  65. data/app/views/integral/backend/activities/shared/show.haml +7 -7
  66. data/app/views/integral/backend/activities/show.haml +1 -1
  67. data/app/views/integral/backend/categories/_modal.haml +2 -3
  68. data/app/views/integral/backend/images/_form.haml +13 -25
  69. data/app/views/integral/backend/images/edit.haml +1 -9
  70. data/app/views/integral/backend/images/grid/_dropdown_actions.haml +5 -0
  71. data/app/views/integral/backend/images/grid/_row_content.haml +5 -0
  72. data/app/views/integral/backend/images/index.haml +11 -17
  73. data/app/views/integral/backend/images/list.haml +11 -0
  74. data/app/views/integral/backend/images/show.haml +26 -0
  75. data/app/views/integral/backend/lists/_form.haml +6 -19
  76. data/app/views/integral/backend/lists/_item_modal.haml +3 -3
  77. data/app/views/integral/backend/lists/_manager.haml +11 -13
  78. data/app/views/integral/backend/lists/edit.haml +6 -20
  79. data/app/views/integral/backend/lists/grid/_dropdown_actions.haml +9 -0
  80. data/app/views/integral/backend/lists/grid/_row_content.haml +3 -0
  81. data/app/views/integral/backend/lists/index.haml +11 -17
  82. data/app/views/integral/backend/lists/list.haml +11 -0
  83. data/app/views/integral/backend/lists/show.haml +30 -0
  84. data/app/views/integral/backend/notifications/_notification.haml +21 -0
  85. data/app/views/integral/backend/pages/_form.haml +19 -43
  86. data/app/views/integral/backend/pages/edit.haml +4 -12
  87. data/app/views/integral/backend/pages/grid/_dropdown_actions.haml +11 -0
  88. data/app/views/integral/backend/pages/grid/_row_content.haml +5 -0
  89. data/app/views/integral/backend/pages/index.haml +6 -6
  90. data/app/views/integral/backend/pages/list.haml +12 -19
  91. data/app/views/integral/backend/pages/show.haml +19 -35
  92. data/app/views/integral/backend/posts/_form.haml +18 -56
  93. data/app/views/integral/backend/posts/edit.haml +4 -14
  94. data/app/views/integral/backend/posts/grid/_dropdown_actions.haml +10 -0
  95. data/app/views/integral/backend/posts/grid/_row_content.haml +6 -0
  96. data/app/views/integral/backend/posts/index.haml +6 -6
  97. data/app/views/integral/backend/posts/list.haml +11 -18
  98. data/app/views/integral/backend/posts/new.haml +0 -1
  99. data/app/views/integral/backend/posts/show.haml +18 -41
  100. data/app/views/integral/backend/shared/_breadcrumbs.haml +7 -4
  101. data/app/views/integral/backend/shared/_image_preview.haml +10 -3
  102. data/app/views/integral/backend/shared/_image_selector.haml +1 -1
  103. data/app/views/integral/backend/shared/_notification_subscription_toggle.haml +22 -0
  104. data/app/views/integral/backend/shared/action_bar/_index.haml +9 -0
  105. data/app/views/integral/backend/shared/action_bar/_show.haml +3 -0
  106. data/app/views/integral/backend/shared/cards/_at_a_glance.haml +3 -3
  107. data/app/views/integral/backend/shared/cards/_categories.haml +27 -28
  108. data/app/views/integral/backend/shared/cards/_object.haml +1 -1
  109. data/app/views/integral/backend/shared/cards/_recent_activity.haml +12 -12
  110. data/app/views/integral/backend/shared/cards/_recent_resources.haml +17 -0
  111. data/app/views/integral/backend/shared/cards/_top_post_authors.haml +14 -15
  112. data/app/views/integral/backend/shared/cards/_welcome.haml +24 -25
  113. data/app/views/integral/backend/shared/{_empty_grid.haml → grid/_empty.haml} +0 -0
  114. data/app/views/integral/backend/shared/grid/_form.haml +9 -0
  115. data/app/views/integral/backend/shared/grid/_grid.haml +21 -0
  116. data/app/views/integral/backend/shared/{_pagination.haml → grid/_pagination.haml} +0 -0
  117. data/app/views/integral/backend/shared/grid/_row_layout.haml +8 -0
  118. data/app/views/integral/backend/shared/record_selector/_collection.haml +1 -0
  119. data/app/views/integral/backend/shared/record_selector/_modal.haml +9 -10
  120. data/app/views/integral/backend/static_pages/dashboard.haml +6 -7
  121. data/app/views/integral/backend/users/_form.haml +34 -46
  122. data/app/views/integral/backend/users/grid/_dropdown_actions.haml +17 -0
  123. data/app/views/integral/backend/users/grid/_row_content.haml +8 -0
  124. data/app/views/integral/backend/users/index.haml +6 -6
  125. data/app/views/integral/backend/users/list.haml +10 -16
  126. data/app/views/integral/backend/users/show.haml +10 -1
  127. data/app/views/integral/categories/show.haml +3 -3
  128. data/app/views/integral/posts/_article_footer.haml +1 -1
  129. data/app/views/integral/posts/_card.haml +1 -1
  130. data/app/views/integral/posts/_most_read_section.haml +1 -1
  131. data/app/views/integral/posts/_post.haml +1 -1
  132. data/app/views/integral/posts/templates/default.haml +1 -1
  133. data/app/views/integral/shared/sidebar/_item.haml +1 -1
  134. data/app/views/layouts/integral/backend.html.haml +24 -5
  135. data/app/views/layouts/integral/backend/_create_dropdown.haml +1 -30
  136. data/app/views/layouts/integral/backend/_main_menu_items.haml +1 -101
  137. data/config/initializers/devise.rb +1 -1
  138. data/config/locales/en.yml +60 -2
  139. data/config/routes.rb +2 -0
  140. data/db/migrate/20200407022636_create_integral_notifications.rb +25 -0
  141. data/db/migrate/20200421223602_add_status_to_integral_users.rb +5 -0
  142. data/db/seeds.rb +15 -11
  143. data/lib/integral.rb +1 -0
  144. data/lib/integral/acts_as_integral.rb +115 -0
  145. data/lib/integral/acts_as_listable.rb +1 -1
  146. data/lib/integral/engine.rb +9 -0
  147. data/lib/integral/grids/activities_grid.rb +0 -1
  148. data/lib/integral/grids/lists_grid.rb +1 -0
  149. data/lib/integral/grids/posts_grid.rb +5 -1
  150. data/lib/integral/grids/users_grid.rb +5 -0
  151. data/lib/integral/list_renderer.rb +5 -1
  152. data/lib/integral/router.rb +20 -4
  153. data/lib/integral/version.rb +1 -1
  154. data/spec/factories.rb +15 -1
  155. metadata +45 -39
  156. data/app/decorators/integral/category_version_decorator.rb +0 -7
  157. data/app/decorators/integral/image_version_decorator.rb +0 -7
  158. data/app/decorators/integral/list_version_decorator.rb +0 -7
  159. data/app/decorators/integral/page_version_decorator.rb +0 -7
  160. data/app/decorators/integral/post_version_decorator.rb +0 -7
  161. data/app/decorators/integral/user_version_decorator.rb +0 -7
  162. data/app/views/devise/mailer/invitation_instructions.html.erb +0 -13
  163. data/app/views/integral/backend/activities/_grid.haml +0 -22
  164. data/app/views/integral/backend/images/_grid.haml +0 -16
  165. data/app/views/integral/backend/lists/_grid.haml +0 -14
  166. data/app/views/integral/backend/pages/_grid.haml +0 -46
  167. data/app/views/integral/backend/posts/_grid.haml +0 -51
  168. data/app/views/integral/backend/shared/_grid.haml +0 -18
  169. data/app/views/integral/backend/shared/cards/_recent_pages.haml +0 -19
  170. data/app/views/integral/backend/shared/cards/_recent_posts.haml +0 -18
  171. data/app/views/integral/backend/shared/cards/_recent_users.haml +0 -19
  172. data/app/views/integral/backend/users/_grid.haml +0 -36
@@ -23,15 +23,15 @@
23
23
  Override defaults
24
24
  = icon('chevron-down')
25
25
  .cell
26
- = f.input :title, wrapper_html: { class: 'alternative' }, input_html: { class: formatted_item.title_required? ? 'title-field required' : 'title-field' }
26
+ = f.input :title, wrapper_html: { class: 'alternative' }, input_html: { 'data-character-counter' => 'true', class: formatted_item.title_required? ? 'title-field required' : 'title-field' }
27
27
  .cell.medium-8.link-attribute{ class: f.object.basic? || !f.object.persisted? ? 'hide' : '' }
28
28
  = f.input :url, wrapper_html: { class: "alternative" }, input_html: { class: 'url-field' }
29
29
  .cell.medium-4.link-attribute.align-self-middle.flex-container{ class: f.object.basic? || !f.object.persisted? ? 'hide' : '' }
30
30
  = f.input :target, as: :boolean, checked_value: '_blank', unchecked_value: '_self', input_html: { class: 'target-field' }, wrapper_html: { class: 'alternative' }
31
31
  .cell
32
- = f.input :subtitle, wrapper_html: { class: 'alternative' }, as: :string
32
+ = f.input :subtitle, input_html: { 'data-character-counter' => 'true' }, wrapper_html: { class: 'alternative' }, as: :string
33
33
  .cell.medium-8
34
- = f.input :description, wrapper_html: { class: 'alternative' }, as: :string, hint: false
34
+ = f.input :description, input_html: { 'data-character-counter' => 'true' }, wrapper_html: { class: 'alternative' }, as: :string, hint: false
35
35
  .cell.medium-4
36
36
  = f.input :image_id, as: :hidden, input_html: { class: 'image-field', data: { image_present: formatted_item.non_object_image?, fallback_image: formatted_item.fallback_image } }
37
37
  .image-preview.center
@@ -1,14 +1,12 @@
1
1
  .card.list-management
2
- .card-section
3
- .top-bar
4
- .top-bar-left
5
- = f.input :children, wrapper_html: { class: 'alternative' }, disabled: locked
6
- .top-bar-right
7
- = f.input :list_item_limit, wrapper_html: { class: 'alternative' }, disabled: locked
8
- #list-items.sortable
9
- = link_to_add_association f, :list_items, 'data-association-insertion-method' => 'after', id: 'top-add-list-button', 'data-association-insertion-node' => '#top-add-list-button', force_non_association_create: true do
10
- .add-list-item
11
- = icon('plus')
12
- = f.simple_fields_for :list_items do |list_item|
13
- = render 'list_item_fields', f: list_item
14
-
2
+ .top-bar
3
+ .top-bar-left
4
+ = f.input :children, wrapper_html: { class: 'alternative' }, disabled: locked
5
+ .top-bar-right
6
+ = f.input :list_item_limit, wrapper_html: { class: 'alternative' }, disabled: locked
7
+ #list-items.sortable
8
+ = link_to_add_association f, :list_items, 'data-association-insertion-method' => 'after', id: 'top-add-list-button', 'data-association-insertion-node' => '#top-add-list-button', force_non_association_create: true do
9
+ .add-list-item
10
+ = icon('plus')
11
+ = f.simple_fields_for :list_items do |list_item|
12
+ = render 'list_item_fields', f: list_item
@@ -1,35 +1,21 @@
1
1
  = content_for :actionbar do
2
2
  %ul.menu.horizontal
3
3
  - if policy(Integral::List).duplicate?
4
- %li
5
- = link_to duplicate_backend_list_url(@resource.id), class: 'button white', method: :post, data: { confirm: t('integral.actions.confirmation.clone') } do
6
- = icon('history')
7
- = t('integral.actions.clone')
8
-
9
- -# - if policy(Integral::Version).manager?
10
- -# %li
11
- -# = link_to activities_backend_list_url(@resource.id), class: 'button white' do
12
- -# = icon('history')
13
- -# = t('integral.navigation.activity')
4
+ = link_to t('integral.actions.clone'), duplicate_backend_list_url(@resource.id), class: 'button white', method: :post, data: { confirm: t('integral.actions.confirmation.clone') }, icon: :history, wrapper: :li
14
5
 
15
6
  = simple_form_for [:backend, @resource], validate: true, html: { class: 'are-you-sure', 'data-confirm-dirty-form' => true, 'data-list-item-limit' => @resource.list_item_limit, id: :list_form } do |f|
16
7
  = f.input :lock_version, as: :hidden
17
- .grid-x.grid-padding-x
8
+ .grid-x
18
9
  .cell.medium-6.flex-container
19
- .card
20
- .card-section
21
- = f.input :title, hint: false, disabled: f.object.locked?
10
+ .card= f.input :title, hint: false, disabled: f.object.locked?
22
11
  .cell.medium-6.flex-container
23
- .card
24
- .card-section
25
- = f.input :description, hint: false, disabled: f.object.locked?
12
+ .card= f.input :description, hint: false, disabled: f.object.locked?
26
13
  .cell
27
14
  = render partial: 'integral/backend/lists/manager', locals: { f: f, locked: f.object.locked? }
28
- .cell
29
- = f.button :button
15
+ .cell= f.button :button
30
16
 
31
17
  -# Image Selector
32
- = render partial: 'integral/backend/shared/record_selector/modal', locals: { search_path: backend_img_index_path, title: t('integral.prompts.select_image'), name: 'Image', create_modal: '#new_image_modal', initialize: true }
18
+ = render partial: 'integral/backend/shared/record_selector/modal', locals: { search_path: list_backend_img_index_path, title: t('integral.prompts.select_image'), name: 'Image', create_modal: '#new_image_modal', initialize: true }
33
19
  = render partial: 'integral/backend/images/create_modal'
34
20
 
35
21
  - Integral::ActsAsListable.objects.each do |listable|
@@ -0,0 +1,9 @@
1
+ - if policy(resource_klass).update?
2
+ = link_to t('integral.actions.edit'), edit_backend_resource_url(resource.id), icon: :edit, wrapper: :li
3
+ = link_to t('integral.actions.open_in_new_tab'), backend_resource_url(resource.id), target: :blank, icon: 'external-link', wrapper: :li
4
+ - if policy(resource_klass).duplicate?
5
+ = link_to t('integral.actions.clone'), duplicate_backend_resource_url(resource.id), method: :post, data: { confirm: t('integral.actions.confirmation.clone') }, icon: :clone, wrapper: :li
6
+ -# - if policy(Integral::Version).manager?
7
+ -# = link_to t('integral.actions.view_history'), activities_backend_resource_url(resource.id), icon: :history, wrapper: :li
8
+ - if policy(resource_klass).destroy?
9
+ = link_to t('integral.actions.delete'), backend_resource_url(resource.id), method: :delete, data: { confirm: t('integral.actions.confirmation.deletion') }, icon: :remove, wrapper: :li
@@ -0,0 +1,3 @@
1
+ %td= resource.title
2
+ %td= resource.description
3
+ %td= l(resource.updated_at)
@@ -1,18 +1,12 @@
1
- .card.listing
2
- .card-section
3
- %h2.show-for-small-only= t('.title')
4
- = link_to t('integral.actions.create'), new_backend_list_url, class: 'button hollow show-for-small-only create'
5
- .top-bar
6
- .top-bar-left.hide-for-small-only
7
- = link_to t('integral.actions.create'), new_backend_list_url, class: 'button hollow'
8
- .top-bar-right
9
- = simple_form_for :grid, url: backend_lists_url, method: :get, remote: true, html: { id: :grid_form, 'data-type' => :json } do |f|
10
- = hidden_field_tag(:gridview, true)
11
- = f.hidden_field(:descending, value: @grid.descending, class: 'desc-field')
12
- = f.hidden_field(:order, value: @grid.order, class: 'order-field')
13
- = f.hidden_field(:page, value: grid_options[:page], class: 'page-field')
1
+ .grid-x
2
+ -# Left Column
3
+ .cell.large-6
4
+ .grid-y
5
+ .cell= render_card(:recent_resources)
6
+ .cell= render_card(:at_a_glance)
14
7
 
15
- %ul.align-right.menu.filters
16
- %li= f.input :title, placeholder: t('integral.actions.search'), wrapper_html: { class: 'filter search' }, hint: false, label: false
17
-
18
- = render partial: 'grid'
8
+ -# Right Column
9
+ .cell.large-6
10
+ .grid-y
11
+ .cell= render_card(:recent_activity)
12
+ .cell.xlarge-6= render_card(:recent_user_activity)
@@ -0,0 +1,11 @@
1
+ .card.listing
2
+ %h2.show-for-small-only= page_title
3
+ = link_to t('integral.actions.create'), new_backend_resource_url, class: 'button hollow show-for-small-only create'
4
+ .top-bar
5
+ .top-bar-left.hide-for-small-only
6
+ = link_to t('integral.actions.create'), new_backend_resource_url, class: 'button hollow'
7
+ .top-bar-right
8
+ = render_resource_grid_form do |f|
9
+ %li= f.input :title, placeholder: t('integral.actions.search'), wrapper_html: { class: 'filter search' }, hint: false, label: false
10
+
11
+ = render_resource_grid
@@ -0,0 +1,30 @@
1
+ = content_for :title, @resource.title
2
+
3
+ .grid-x
4
+ .cell.large-6
5
+ -# Left Column
6
+ .grid-x
7
+ .cell
8
+ .card
9
+ %h2= @resource.title
10
+ %p.subtitle= @resource.description
11
+ %hr
12
+
13
+ .grid-x.actions
14
+ .cell.xlarge-8.xxlarge-6
15
+ .grid-x.small-up-2
16
+ - if policy(resource_klass).manager?
17
+ = link_to t('integral.actions.edit'), edit_backend_resource_url(@resource.id), icon: :edit, wrapper: :cell
18
+ - if policy(resource_klass).duplicate?
19
+ = link_to t('integral.actions.clone'), duplicate_backend_resource_url(@resource.id), method: :post, data: { confirm: t('integral.actions.confirmation.clone') }, icon: :clone, wrapper: :cell
20
+ - if policy(resource_klass).manager?
21
+ = link_to t('integral.actions.delete'), backend_resource_url(@resource.id), method: :delete, data: { confirm: t('integral.actions.confirmation.deletion') }, icon: :remove, wrapper: :cell
22
+ -# - if policy(Integral::Version).manager?
23
+ -# = link_to t('integral.actions.view_history'), activities_backend_resource_url(@resource.id), icon: :history, wrapper: :cell
24
+
25
+ -# .cell.medium-6.flex-container= render_card(:object, { title: 'Essentials', record: @resource })
26
+ .cell.xlarge-6.flex-container= render_card(:recent_user_activity)
27
+ .cell.large-6
28
+ -# Right Column
29
+ .grid-x
30
+ .cell= render_card(:recent_activity)
@@ -0,0 +1,21 @@
1
+ %li.notification{ class: notification.unread? ? 'unread' : '', data: { notification_read_url: notification.unread? ? read_notification_backend_user_url(current_user, notification_id: notification.id) : nil, notification_id: notification.id }}
2
+ .notification-icon
3
+ -#= icon('home')
4
+ .notification-content
5
+ .align-justify.flex-container
6
+ %span.notification-action
7
+ = notification.model_name
8
+ = notification.action_verb
9
+ %span.notification-whodunnit
10
+ - if notification.whodunnit.present?
11
+ = link_to notification.whodunnit_url do
12
+ = image_tag notification.whodunnit_avatar_url, class: :avatar
13
+ %span= notification.whodunnit_name.truncate(30)
14
+ - else
15
+ = image_tag notification.whodunnit_avatar_url, class: :avatar
16
+ %span= notification.whodunnit_name.truncate(30)
17
+ .align-justify.flex-container
18
+ = link_to notification.item_url, class: 'notification-title' do
19
+ = notification.item_title.truncate(40)
20
+ %span.notification-created-at= time_ago_in_words(notification.created_at, scope: 'datetime.distance_in_words.short')
21
+
@@ -1,49 +1,25 @@
1
1
  = simple_form_for [:backend, @resource], validate: true, html: { id: 'resource_form', class: 'are-you-sure', 'data-confirm-dirty-form' => true } do |f|
2
2
  = f.input :lock_version, as: :hidden
3
- .grid-x.grid-padding-x
4
- .cell.small-12.medium-8.large-9
3
+ .grid-x
4
+ .cell.medium-8.large-9
5
+ -# Left Column
5
6
  .grid-y
6
- .cell
7
- .card
8
- .card-section
9
- = f.input :title
10
- .cell
11
- .card
12
- .card-section
13
- = f.input :description
14
- .cell
15
- .card
16
- .card-section
17
- = f.input :path, disabled: current_policy.unpermitted_attribute?(:path)
18
- .cell
19
- .card
20
- .card-section
21
- = f.input :body, as: :ckeditor, input_html: { value: @resource.editor_body, id: 'resource_body_editor', ckeditor: { language: current_user.locale }, data: { 'ckeditor-class' => @resource.template } }
7
+ = f.input :title
8
+ = f.input :description
9
+ = f.input :path
10
+ = f.input :body, as: :ckeditor, input_html: { id: 'resource_body_editor', value: @resource.editor_body, data: { 'ckeditor-class' => @resource.template } }
22
11
 
23
- .cell.small-12.medium-4.large-3
12
+ .cell.medium-4.large-3
13
+ -# Right Column
24
14
  .grid-y
25
- .cell
26
- .card
27
- .card-section
28
- %h2= t('integral.records.attributes.status')
29
- %hr.dark
30
- .radios
31
- = f.collection_radio_buttons :status, Integral::Page.statuses.map{ |status| [status.first, I18n.t("integral.records.status.#{status.first}")] }, :first, :last, disabled: current_policy.permitted_attribute?(:status) ? '' : Integral::Post.statuses.keys, include_hidden: false
32
- %hr.dark
33
- = f.button :button if f.object.persisted?
34
- .cell
35
- .card
36
- .card-section
37
- = f.input :template, collection: Integral::Page.available_templates, prompt: t('integral.backend.pages.prompts.choose_template'), include_blank: false
38
- .cell
39
- .card
40
- .card-section
41
- = f.association :parent, collection: @resource.available_parents.map {|p| [p.title, p.id]}, include_blank: true
42
- .cell
43
- .card.initial-overflow
44
- .card-section
45
- %h2= t('integral.records.attributes.image')
46
- = render partial: 'integral/backend/shared/image_preview', locals: { f:f, image_attr: :image }
15
+ .input
16
+ %h2= t('integral.records.attributes.status')
17
+ %hr.dark
18
+ .radios= f.collection_radio_buttons :status, Integral::Page.available_statuses, :last, :first, include_hidden: false
19
+ %hr.dark
20
+ = f.button :button if f.object.persisted?
21
+ = f.input :template, collection: Integral::Page.available_templates, prompt: t('integral.backend.pages.prompts.choose_template'), include_blank: false
22
+ = f.association :parent, collection: @resource.available_parents.map {|p| [p.title, p.id]}, include_blank: true
23
+ = render partial: 'integral/backend/shared/image_preview', locals: { f:f }
47
24
 
48
- .cell.small-12
49
- = f.button :button
25
+ .cell= f.button :button
@@ -8,19 +8,11 @@
8
8
  = icon('eye')
9
9
  = t('integral.actions.view_on_site')
10
10
  - else
11
- = link_to @resource.path, class: 'button white' do
12
- = icon('eye')
13
- = t('integral.actions.view_on_site')
11
+ = link_to t('integral.actions.view_on_site'), @resource.path, class: 'button white', icon: :eye
14
12
 
15
- - if policy(Integral::Page).duplicate?
16
- %li
17
- = link_to duplicate_backend_page_url(@resource.id), class: 'button white', method: :post, data: { confirm: t('integral.actions.confirmation.clone') } do
18
- = icon('history')
19
- = t('integral.actions.clone')
13
+ - if policy(resource_klass).duplicate?
14
+ = link_to t('integral.actions.clone'), duplicate_backend_resource_url(@resource.id), class: 'button white', method: :post, data: { confirm: t('integral.actions.confirmation.clone') }, icon: :history, wrapper: :li
20
15
  - if policy(Integral::Version).manager?
21
- %li
22
- = link_to activities_backend_page_url(@resource.id), class: 'button white' do
23
- = icon('history')
24
- = t('integral.navigation.activity')
16
+ = link_to t('integral.navigation.activity'), activities_backend_resource_url(@resource.id), class: 'button white', icon: :history, wrapper: :li
25
17
 
26
18
  = render 'form'
@@ -0,0 +1,11 @@
1
+ - if policy(resource_klass).update?
2
+ = link_to t('integral.actions.edit'), edit_backend_resource_url(resource.id), icon: :edit, wrapper: :li
3
+ - unless resource.archived?
4
+ = link_to t('integral.actions.view_on_site'), resource.path, icon: :eye, wrapper: :li
5
+ = link_to t('integral.actions.open_in_new_tab'), backend_resource_url(resource.id), target: :blank, icon: 'external-link', wrapper: :li
6
+ - if policy(resource_klass).duplicate?
7
+ = link_to t('integral.actions.clone'), duplicate_backend_resource_url(resource.id), method: :post, data: { confirm: t('integral.actions.confirmation.clone') }, icon: :clone, wrapper: :li
8
+ - if policy(Integral::Version).manager?
9
+ = link_to t('integral.actions.view_history'), activities_backend_resource_url(resource.id), icon: :history, wrapper: :li
10
+ - if policy(resource_klass).destroy?
11
+ = link_to t('integral.actions.delete'), backend_resource_url(resource.id), method: :delete, data: { confirm: t('integral.actions.confirmation.deletion') }, icon: :remove, wrapper: :li
@@ -0,0 +1,5 @@
1
+ %td= resource.title.truncate(30)
2
+ %td= resource.path
3
+ %td
4
+ %span.label= t("integral.records.status.#{resource.status}")
5
+ %td= l(resource.updated_at, format: :long)
@@ -1,12 +1,12 @@
1
- .grid-x.grid-padding-x
1
+ .grid-x
2
2
  -# Left Column
3
3
  .cell.large-6
4
- .grid-x.grid-padding-x
5
- .cell= render_card(:recent_pages)
6
- .cell= render_card(:at_a_glance, { dataset: dataset_at_a_glance_pages })
4
+ .grid-y
5
+ .cell= render_card(:recent_resources)
6
+ .cell= render_card(:at_a_glance)
7
7
 
8
8
  -# Right Column
9
9
  .cell.large-6
10
- .grid-x.grid-padding-x
10
+ .grid-y
11
11
  .cell= render_card(:recent_activity)
12
- .cell.large-6= render_card(:recent_user_activity)
12
+ .cell.xlarge-6= render_card(:recent_user_activity)
@@ -1,22 +1,15 @@
1
1
  .card.listing
2
- .card-section
3
- %h2.show-for-small-only= page_title
4
- - if policy(Integral::Page).create?
5
- = link_to t('integral.actions.create'), new_backend_page_url, class: 'button hollow show-for-small-only create'
2
+ %h2.show-for-small-only= page_title
3
+ - if policy(resource_klass).create?
4
+ = link_to t('integral.actions.create'), new_backend_resource_url, class: 'button hollow show-for-small-only create'
6
5
 
7
- .top-bar
8
- - if policy(Integral::Page).create?
9
- .top-bar-left.hide-for-small-only
10
- = link_to t('integral.actions.create'), new_backend_page_url, class: 'button hollow'
11
- .top-bar-right
12
- = simple_form_for :grid, url: list_backend_pages_url, method: :get, remote: true, html: { id: :grid_form, 'data-type' => :json } do |f|
13
- = hidden_field_tag(:gridview, true)
14
- = f.hidden_field(:descending, value: @grid.descending, class: 'desc-field')
15
- = f.hidden_field(:order, value: @grid.order, class: 'order-field')
16
- = f.hidden_field(:page, value: grid_options[:page], class: 'page-field')
6
+ .top-bar
7
+ - if policy(resource_klass).create?
8
+ .top-bar-left.hide-for-small-only
9
+ = link_to t('integral.actions.create'), new_backend_resource_url, class: 'button hollow'
10
+ .top-bar-right
11
+ = render_resource_grid_form do |f|
12
+ %li= f.input :status, collection: resource_klass.available_statuses, label: t('integral.records.attributes.status'), wrapper_html: { class: 'filter' }, input_html: { 'data-filter' => true }, required: false
13
+ %li= f.input :title, placeholder: t('integral.actions.search'), wrapper_html: { class: 'filter search' }, hint: false, label: false
17
14
 
18
- %ul.align-right.menu.filters
19
- %li= f.input :status, collection: Integral::Page.available_statuses, label: t('integral.records.attributes.status'), wrapper_html: { class: 'filter' }, input_html: { 'data-filter' => true }, required: false
20
- %li= f.input :title, placeholder: t('integral.actions.search'), wrapper_html: { class: 'filter search' }, hint: false, label: false
21
-
22
- = render partial: 'grid'
15
+ = render_resource_grid
@@ -3,46 +3,30 @@
3
3
  .grid-x
4
4
  .cell.large-6
5
5
  -# Left Column
6
- .grid-x.grid-padding-x
6
+ .grid-x
7
7
  .cell
8
8
  .card
9
- .card-section
10
- %h2= @resource.title
11
- %p.subtitle= @resource.description
12
- %hr
9
+ %h2= @resource.title
10
+ %p.subtitle= @resource.description
11
+ %hr
13
12
 
14
- .grid-x.actions
15
- .cell.xlarge-8.xxlarge-6
16
- .grid-x.small-up-2
17
- - unless @resource.archived?
18
- .cell
19
- = link_to @resource.path do
20
- = icon('eye')
21
- = t('integral.actions.view_on_site')
22
- - if policy(Integral::Page).manager?
23
- .cell
24
- = link_to edit_backend_page_url(@resource.id) do
25
- = icon('edit')
26
- = t('integral.actions.edit')
27
- - if policy(Integral::Page).duplicate?
28
- .cell
29
- = link_to duplicate_backend_page_url(@resource.id), method: :post, data: { confirm: t('integral.actions.confirmation.clone') } do
30
- = icon('clone')
31
- = t('integral.actions.clone')
32
- - if policy(Integral::Page).manager?
33
- .cell
34
- = link_to backend_page_url(@resource.id), method: :delete, data: { confirm: t('integral.actions.confirmation.deletion') } do
35
- = icon('remove')
36
- = t('integral.actions.delete')
37
- - if policy(Integral::Version).manager?
38
- .cell
39
- = link_to activities_backend_page_url(@resource.id) do
40
- = icon('history')
41
- = t('integral.actions.view_history')
13
+ .grid-x.actions
14
+ .cell.xlarge-8.xxlarge-6
15
+ .grid-x.small-up-2
16
+ - unless @resource.archived?
17
+ = link_to t('integral.actions.view_on_site'), @resource.path, icon: :eye, wrapper: :cell
18
+ - if policy(resource_klass).manager?
19
+ = link_to t('integral.actions.edit'), edit_backend_resource_url(@resource.id), icon: :edit, wrapper: :cell
20
+ - if policy(resource_klass).duplicate?
21
+ = link_to t('integral.actions.clone'), duplicate_backend_resource_url(@resource.id), method: :post, data: { confirm: t('integral.actions.confirmation.clone') }, icon: :clone, wrapper: :cell
22
+ - if policy(resource_klass).manager?
23
+ = link_to t('integral.actions.delete'), backend_resource_url(@resource.id), method: :delete, data: { confirm: t('integral.actions.confirmation.deletion') }, icon: :remove, wrapper: :cell
24
+ - if policy(Integral::Version).manager?
25
+ = link_to t('integral.actions.view_history'), activities_backend_resource_url(@resource.id), icon: :history, wrapper: :cell
42
26
 
43
27
  .cell.medium-6.flex-container= render_card(:object, { title: 'Essentials', record: @resource })
44
- .cell.medium-6.flex-container= render_card(:recent_user_activity)
28
+ .cell.xlarge-6.flex-container= render_card(:recent_user_activity)
45
29
  .cell.large-6
46
30
  -# Right Column
47
- .grid-x.grid-padding-x
31
+ .grid-x
48
32
  .cell= render_card(:recent_activity)
@@ -1,63 +1,25 @@
1
1
  = simple_form_for [:backend, @resource], validate: true, html: { id: 'resource_form', class: 'are-you-sure', 'data-confirm-dirty-form' => true } do |f|
2
2
  = f.input :lock_version, as: :hidden
3
- .grid-x.grid-padding-x
4
- .cell.small-12.medium-9
3
+ .grid-x
4
+ .cell.medium-9
5
5
  .grid-y
6
- .cell
7
- .card
8
- .card-section
9
- = f.input :title, input_html: { id: 'resource_title' }
10
- .cell
11
- .card
12
- .card-section
13
- = f.input :description
14
- .cell
15
- .card
16
- .card-section
17
- = f.input :slug, input_html: { data: { slugify: '#resource_title' }}
18
- .cell
19
- .card
20
- .card-section
21
- = f.input :body, as: :ckeditor, input_html: { value: @resource.editor_body, id: 'resource_body_editor', ckeditor: { language: current_user.locale }, data: { 'ckeditor-class' => 'integral-post' } }
6
+ = f.input :title, input_html: { id: 'resource_title' }
7
+ = f.input :description
8
+ = f.input :slug, input_html: { data: { slugify: '#resource_title' }}
9
+ = f.input :body, as: :ckeditor, input_html: { value: @resource.editor_body, id: 'resource_body_editor', ckeditor: { language: current_user.locale }, data: { 'ckeditor-class' => 'integral-post' } }
22
10
 
23
- .cell.small-12.medium-3
11
+ .cell.medium-3
24
12
  .grid-y
25
13
  .cell
26
14
  .card
27
- .card-section
28
- %h2= t('integral.records.attributes.status')
29
- %hr.dark
30
- .radios
31
- = f.collection_radio_buttons :status, Integral::Post.statuses.map{ |status| [status.first, I18n.t("integral.records.status.#{status.first}")] }, :first, :last
32
- %hr.dark
33
- = f.button :button if f.object.persisted?
34
- .cell
35
- .card
36
- .card-section
37
- %h2= t('integral.records.attributes.category')
38
- %hr.dark
39
- = f.input :category_id, collection: Integral::Category.all.map{ |category| [category.title, category.id] }, label: false
40
- .cell
41
- .card.initial-overflow
42
- .card-section
43
- %h2= t('integral.records.attributes.tags')
44
- %hr.dark
45
- = f.input :tag_list, label: false, input_html: { value: @resource.tag_list_on(@resource.tag_context).join(','), data: { suggest_tags: true, suggest_tags_typeahead: Integral::Post.tag_counts.collect(&:name).join(' ') } }
46
- .cell
47
- .card
48
- .card-section
49
- = f.association :user
50
- .cell
51
- .card.initial-overflow
52
- .card-section
53
- %h2= t('integral.records.attributes.featured_image')
54
- = render partial: 'integral/backend/shared/image_preview', locals: { f:f, image_attr: :image }
55
- .cell
56
- .card.initial-overflow
57
- .card-section
58
- %h2= t('integral.records.attributes.preview_image')
59
- = render partial: 'integral/backend/shared/image_preview', locals: { f:f, image_attr: :preview_image }
60
- %br
61
- %p.help-text This is displayed when sharing socially, leave blank to fallback to the featured image.
62
- .cell.small-12
63
- = f.button :button
15
+ = f.label(:status)
16
+ %hr.dark
17
+ .radios= f.collection_radio_buttons :status, resource_klass.available_statuses, :last, :first
18
+ %hr.dark
19
+ = f.button :button if f.object.persisted?
20
+ = f.input :category_id, collection: Integral::Category.all.map{ |category| [category.title, category.id] }, include_blank: false
21
+ = f.input :tag_list, input_html: { value: @resource.tag_list_on(@resource.tag_context).join(','), data: { suggest_tags: true, suggest_tags_typeahead: resource_klass.tags_on('published').map(&:name).join(' ') } }
22
+ = f.association :user
23
+ = render partial: 'integral/backend/shared/image_preview', locals: { f:f }
24
+ = render partial: 'integral/backend/shared/image_preview', locals: { f:f, attribute: :preview_image, help_text: 'This is displayed when sharing socially, leave blank to fallback to the featured image.' }
25
+ .cell= f.button :button