biola_wcms_components 0.18.1 → 0.19.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1bdbcd07d32850d019054bc9cd87a61382666834
4
- data.tar.gz: abfe1ee56c0b317ad0b38d9ab972c30c898545e9
3
+ metadata.gz: 64707a51133721274a2d1442ff6c3bedcaa1cbc5
4
+ data.tar.gz: 595b3c6481b8b71436e1abd48406543a6e0bec26
5
5
  SHA512:
6
- metadata.gz: 15c789d5a03dc04223015c2bf62d3961d2c804b9cc444668b107ced5d0f6714ac5173a80dd27e1ae1bc99a4fed785c87604b130056799039361f2eed58edcea3
7
- data.tar.gz: eba8635a02a359d07a6e8d01f509c11ae207e770ad458e0d6e277356e231d1bceeeee32028e3d701fcf99014a78771aac592fad601d9ea9092f371f18276cd98
6
+ metadata.gz: 51605effdefc964f3070b01ee305995b7af9eb392cb6e0c8c4498deb73181a6b68ae8b287ab34f1f72812815b82f3a63a0e3a7352cb44e48d82e97cea7c5f2ab
7
+ data.tar.gz: 2ce7582ef2f4a1930c3963b611e4497753573c82e67bbda611077fdf3bec681287e2e924d05e7d64b9f189e2162a3f9118a63adf55b34197ad2eae964bc73c34
@@ -2,6 +2,10 @@
2
2
 
3
3
  ### Master (unreleased)
4
4
 
5
+ ### 0.19.0
6
+
7
+ * Added Changes class for history tracking
8
+
5
9
  ### 0.18.1
6
10
 
7
11
  * Updating site nav to let you set the text for the menu dropdown.
@@ -0,0 +1,33 @@
1
+ $(document).ready ->
2
+ # Each bullet point that has more than 100 chars is initially shortened
3
+ # and can be expanded.
4
+ showChar = 100
5
+ ellipsestext = '...'
6
+ moretext = 'more'
7
+ lesstext = 'less'
8
+
9
+ onClickMoreLink = (event) ->
10
+ link = $(event.target)
11
+
12
+ if link.hasClass('less')
13
+ link.removeClass 'less'
14
+ link.html moretext
15
+ else
16
+ link.addClass 'less'
17
+ link.html lesstext
18
+
19
+ link.parent().prev().toggle()
20
+ link.prev().toggle()
21
+ # Prevent the page from scrolling to the top.
22
+ false
23
+
24
+
25
+ $('.expandable_item').each ->
26
+ content = $(this).html()
27
+ if content.length > showChar
28
+ c = content.substr(0, showChar)
29
+ h = content.substr(showChar)
30
+ html = c + '<span class="moreellipses">' + ellipsestext + '&nbsp;</span><span class="morecontent"><span>' + h + '</span>&nbsp;&nbsp;<a href="" class="morelink">' + moretext + '</a></span>'
31
+ $(this).html html
32
+
33
+ $('.expandable_item .morelink').click onClickMoreLink
@@ -0,0 +1,27 @@
1
+
2
+ $(document).ready ->
3
+ # Used in Changes. For each recorded change if there is more than two changed fields
4
+ # hide all but the first two and provide a link to show the rest.
5
+ onClickMoreLink = (event) ->
6
+ link = $(event.target)
7
+ # Show all the list items
8
+ link.siblings('li').show()
9
+ # Hide the show more link
10
+ link.hide()
11
+ # Prevent the page from scrolling to the top
12
+ false
13
+
14
+ $('ul.expandable_list').each ->
15
+ ul = $(this)
16
+ lis = ul.children('li')
17
+ # If there are more than two list items
18
+ if lis.length > 2
19
+ # Show only the first two initially
20
+ lis.slice(2).hide()
21
+
22
+ # Create a link
23
+ show_more_link = $('<a class="show_more_link" href="#">Expand</a>')
24
+ # Add a click event to the link
25
+ show_more_link.click(onClickMoreLink)
26
+ # Add the link to the DOM
27
+ ul.append(show_more_link)
@@ -13,4 +13,5 @@
13
13
  @import "./components/alerts/*";
14
14
  @import "./components/buttons/*";
15
15
  @import "./components/forms/*";
16
+ @import "./components/list/*";
16
17
  @import "./components/navigation/*";
@@ -0,0 +1,9 @@
1
+ .expandable_item {
2
+ a.morelink {
3
+ text-decoration:none;
4
+ outline: none;
5
+ }
6
+ .morecontent span {
7
+ display: none;
8
+ }
9
+ }
@@ -0,0 +1,118 @@
1
+ class WcmsComponents::ChangesController < ApplicationController
2
+
3
+ before_filter :set_change, only: [:undo, :undo_destroy]
4
+ before_filter :pundit_authorize
5
+
6
+ def index
7
+ @changes = policy_scope(Change)
8
+ @changes = @changes.where(association_chain: {'$elemMatch' => {name: params[:klass].classify}})
9
+
10
+ # Filter Values
11
+ @available_users = User.find(@changes.distinct(:modifier_id))
12
+
13
+ @changes = @changes.where(modifier_id: params[:user_id]) if params[:user_id].present?
14
+ @changes = @changes.where(action: params[:action_taken]) if params[:action_taken].present?
15
+ @changes = @changes.by_last_change(params[:last_change]) if params[:last_change].present?
16
+
17
+ @changes = @changes.desc(:updated_at)
18
+ @changes = @changes.page(params[:page]).per(25)
19
+ end
20
+
21
+ def object_index
22
+ # Retrieve object of who's history you are desiring after.
23
+ @object = params[:klass].safe_constantize.find(params[:id])
24
+ @changes = []
25
+ @available_users = []
26
+ object_history = @object.history_tracks # TODO: this seems to not be pulling the embedded document history
27
+ @available_users += User.find(object_history.distinct(:modifier_id)) if object_history
28
+
29
+ # Apply the filters -- if there are no results then it will be as an empty array
30
+ @changes += set_filters(object_history)
31
+
32
+ # Retrieve applicable nested object histories defined in the respective publishers settings
33
+ fetch_nested_histories(@object) do |histories|
34
+ if histories.present?
35
+ @available_users += User.find(histories.distinct(:modifier_id))
36
+ @changes += set_filters(histories)
37
+ end
38
+ end
39
+
40
+ @available_users.uniq!
41
+
42
+ @changes.sort!{ |a,b| b.created_at <=> a.created_at }
43
+ end
44
+
45
+ def undo
46
+ set_modifier
47
+
48
+ if @change.undo! current_user
49
+ if @change.action == 'create'
50
+ flash[:info] = "Change was successfully reversed. <a href=wcms_components/changes/#{Change.last.id}/undo_destroy>Undo</a>"
51
+ else
52
+ flash[:info] = "Change was successfully reversed."
53
+ end
54
+ else
55
+ flash[:error] = "Something went wrong. Please try again."
56
+ end
57
+
58
+ # Ensure that the object wasn't just undone into nonexistence.
59
+ # For the time being referenced documents will not be able to be undone as
60
+ # we have no way to redirect back to the owning object.
61
+ @parent = params[:owning_class].safe_constantize
62
+ if @parent.where(id: params[:owning_id]).present?
63
+ redirect_to @parent.find(params[:owning_id])
64
+ else
65
+ redirect_to @parent
66
+ end
67
+ end
68
+
69
+ def undo_destroy
70
+ # Undo destory at the moment is only available in flash notices after destroy is completed.
71
+ # Because of this the modifier for the change will be set as the last known object modifier.
72
+ # This could cause issues so we may want to find a way to set it since mongoid history wont.
73
+ if @change.undo!
74
+ flash[:info] = "#{@change.original[:title]} has been successfully recreated."
75
+ else
76
+ flash[:error] = "Something went wrong. Please try again."
77
+ end
78
+ redirect_to :back
79
+ end
80
+
81
+ private
82
+ # Mongoid history for some reason is refraining from setting modifier on undo! so this will set it manually
83
+ # if the parent object is present.
84
+ def set_modifier
85
+ if @change.trackable_root.present?
86
+ @change.trackable_root.modifier = current_user
87
+ end
88
+ end
89
+
90
+ def set_filters(changes)
91
+ changes = changes.where(modifier_id: params[:user_id]) if params[:user_id].present?
92
+ changes = changes.where(action: params[:action_taken]) if params[:action_taken].present?
93
+ changes = changes.by_last_change(params[:last_change]) if params[:last_change].present?
94
+ changes
95
+ end
96
+
97
+ def fetch_nested_histories(object, &block)
98
+ # Trackable relations is an array of nested (e.g. has_many/belongs_to) relationships (e.g. ["attachments", "concentrations"])
99
+ # for a given class. Embedded documents are handled by Mongoid History.
100
+ if relations = Settings.trackable_relations[params[:klass]]
101
+
102
+ # Getting all the related objects for each relationship.
103
+ all_related_objects = relations.map{ |rels| object.send(rels) }.flatten.compact
104
+
105
+ # Passing the histories as a parameter to the block defined in object_index
106
+ all_related_objects.each { |related_object| block.call(related_object.history_tracks) }
107
+ end
108
+ end
109
+
110
+ def set_change
111
+ @change = Change.find(params[:id])
112
+ end
113
+
114
+ def pundit_authorize
115
+ authorize (@change || Change)
116
+ end
117
+
118
+ end
@@ -0,0 +1,22 @@
1
+ class ChangePolicy < ApplicationPolicy
2
+ class Scope < ApplicationPolicy
3
+ attr_reader :user, :scope
4
+ def initialize(user, scope)
5
+ @user = user
6
+ @scope = scope
7
+ end
8
+ def resolve
9
+ scope.all
10
+ end
11
+ end
12
+
13
+ def undo?
14
+ user.admin?
15
+ end
16
+ alias :undo_destroy? :undo?
17
+
18
+ def index?
19
+ true
20
+ end
21
+ alias :object_index? :index?
22
+ end
@@ -5,4 +5,4 @@
5
5
  .alert class=alert_class(msg[:type]) data-type=msg[:type]
6
6
  a.close data-dismiss="alert" href="#" &times;
7
7
  i> class=alert_icon(msg[:type])
8
- = msg[:message]
8
+ = msg[:message].html_safe
@@ -0,0 +1,28 @@
1
+ .container.page
2
+ h3 = "#{params[:klass].titleize} changes"
3
+ .page-header
4
+ ul.nav.nav-pills.pull-left
5
+ = nav_pill_header 'Options'
6
+ - if @available_users.present?
7
+ = nav_pill_dropdown 'User', :user do
8
+ - @available_users.each do |user|
9
+ = nav_list_link user, :user_id, user.id
10
+ = nav_pill_dropdown 'Action', :action_taken do
11
+ = nav_list_link 'Create', :action_taken, 'create'
12
+ = nav_list_link 'Update', :action_taken, 'update'
13
+ = nav_list_link 'Destroy', :action_taken, 'destroy'
14
+ = nav_pill_dropdown 'Last Changed', :last_change do
15
+ = nav_list_link 'Today', :last_change, Date.today
16
+ = nav_list_link 'Yesterday', :last_change, 1.day.ago.to_date
17
+ = nav_list_link "Last #{1.week.ago.strftime('%A')}", :last_change, 1.week.ago.to_date
18
+ = nav_list_link 1.month.ago.strftime('%B %e'), :last_change, 1.month.ago.to_date
19
+ .clearfix
20
+
21
+ - if @changes.empty?
22
+ .alert.alert-warning
23
+ = fa_icon 'warning', text: "No changes were found"
24
+ - else
25
+ = render 'changes'
26
+
27
+ - unless params[:action] == 'object_index'
28
+ .text-center = paginate @changes
@@ -0,0 +1,51 @@
1
+ .change_history
2
+ .table-responsive style="overflow: scroll;"
3
+ table.table.table-striped
4
+ thead
5
+ tr
6
+ th
7
+ th.col-xs-2 Action
8
+ th.col-xs-2 User
9
+ th.col-xs-2 Created
10
+ th.col-xs-6 Changes
11
+
12
+ tbody
13
+ - @changes.each do |change|
14
+ tr
15
+ td
16
+ - if change.action == 'destroy' && (change.trackable_root.present? || change.trackable.present?)
17
+ = link_to fa_icon('undo'), '#', data: { confirm: "This change has already been reversed and the object currently exists" }
18
+ - else
19
+ = link_to fa_icon('undo'), undo_wcms_components_change_path(change, owning_class: params[:klass], owning_id: params[:id]), data: { confirm: "Are you sure that you want to undo this change?" }
20
+ td
21
+ - if change.action.present?
22
+ = "#{change.action == 'destroy' ? 'Destroyed' : change.action.try(:humanize).to_s + 'd'} #{change.association_chain.last[:name].titleize}"
23
+ td = change.modifier.try(:to_s)
24
+ td = change.created_at.to_s(:long_ordinal)
25
+ td
26
+
27
+ ul.changes.expandable_list
28
+ / if the change belongs to a tracked child object display the title of the child object so that we know which it is
29
+ - if (change.association_chain.last[:name] != params[:klass]) && change.trackable.present?
30
+ strong = "#{change.association_chain.last[:name].titleize} Title: #{change.trackable.to_s}"
31
+ - elsif params[:action] != 'object_index'
32
+ strong = "Title: #{change.trackable.to_s}"
33
+
34
+ - (change.tracked_edits[:add]||[]).each do |k,v|
35
+ li.remove.expandable_item = "Added field #{k} value #{v}"
36
+
37
+ - (change.tracked_edits[:modify]||[]).each do |k,v|
38
+ li.modify.expandable_item = "Changed field #{k} from #{v[:from]} to #{v[:to]}"
39
+
40
+ - (change.tracked_edits[:array]||[]).each do |k,v|
41
+ li.modify.expandable_item
42
+ - if v[:remove].nil?
43
+ = "Changed field #{k} by adding #{v[:add]}"
44
+ - elsif v[:add].nil?
45
+ = "Changed field #{k} by removing #{v[:remove]}"
46
+ - else
47
+ = "Changed field #{k} by adding #{v[:add]} and removing #{v[:remove]}"
48
+
49
+ - (change.tracked_edits[:remove]||[]).each do |k,v|
50
+ li.remove.expandable_item = "Removed field #{k} (was previously #{v})"
51
+
@@ -0,0 +1,3 @@
1
+ = render 'change_index'
2
+ - content_for :site_nav_right do
3
+ = link_to 'Back', [params[:klass].underscore.pluralize], class: "top-nav-link"
@@ -0,0 +1,3 @@
1
+ = render 'change_index'
2
+ - content_for :site_nav_right do
3
+ = link_to 'Back', [@object], class: "top-nav-link"
@@ -45,4 +45,14 @@ ruby:
45
45
 
46
46
  - crumbs.each do |crumb|
47
47
  i class='fa fa-angle-right'
48
- = link_to crumb[:body], crumb[:url], class: 'top-nav-link'
48
+ - if crumb[:body] == "Changes"
49
+ = link_to crumb[:body], '#', class: 'top-nav-link'
50
+ - else
51
+ = link_to crumb[:body], crumb[:url], class: 'top-nav-link'
52
+
53
+ / Example:
54
+ / - content_for :site_nav_right do
55
+ / = link_to 'History', wcms_components_changes_path(klass: 'page_editions'), class: "top-nav-link"
56
+ - if content_for?(:site_nav_right)
57
+ #site_nav_right.pull-right
58
+ = yield(:site_nav_right)
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "ace-rails-ap", "~> 3.0"
22
- spec.add_dependency "buweb_content_models", ">= 0.82"
22
+ spec.add_dependency "buweb_content_models", ">= 1.7"
23
23
  spec.add_dependency "coffee-rails", ">= 4.0"
24
24
  spec.add_dependency "chronic_ping", "~> 0.4"
25
25
  spec.add_dependency "jquery-ui-rails"
@@ -4,8 +4,14 @@ Rails.application.routes.draw do
4
4
  resources :embedded_images, only: [:create], defaults: { format: 'json' }
5
5
  resources :people, only: [:index], defaults: { format: 'json' }
6
6
  resources :tags, only: [:index], defaults: { format: 'json' }
7
+ resources :changes, only: :index do
8
+ get :object_index, on: :collection
9
+ get :undo, on: :member
10
+ get :undo_destroy, on: :member
11
+ end
7
12
  end
8
13
 
14
+
9
15
  # this is just a convenience to create a named route to rack-cas' logout
10
16
  get '/logout' => -> env { [200, { 'Content-Type' => 'text/html' }, ['Rack::CAS should have caught this']] }, as: :logout
11
17
 
@@ -1,3 +1,3 @@
1
1
  module BiolaWcmsComponents
2
- VERSION = "0.18.1"
2
+ VERSION = "0.19.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: biola_wcms_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.1
4
+ version: 0.19.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Hall
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-16 00:00:00.000000000 Z
11
+ date: 2015-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ace-rails-ap
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0.82'
33
+ version: '1.7'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0.82'
40
+ version: '1.7'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: coffee-rails
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -172,9 +172,10 @@ files:
172
172
  - app/assets/javascripts/components/forms/presentation_data_editor.js.coffee
173
173
  - app/assets/javascripts/components/forms/tag_input.js.coffee
174
174
  - app/assets/javascripts/components/forms/yaml_editor.js.coffee
175
+ - app/assets/javascripts/components/list/expandable_item.js.coffee
176
+ - app/assets/javascripts/components/list/expandable_list.js.coffee
175
177
  - app/assets/javascripts/configuration/file_uploader.js.coffee
176
178
  - app/assets/javascripts/configuration/setup_redactor.js.coffee
177
- - app/assets/stylesheets/_mixins.scss
178
179
  - app/assets/stylesheets/_settings.scss
179
180
  - app/assets/stylesheets/_utilities.scss
180
181
  - app/assets/stylesheets/biola-wcms-components.css.scss
@@ -183,18 +184,26 @@ files:
183
184
  - app/assets/stylesheets/components/forms/_person_lookup.scss
184
185
  - app/assets/stylesheets/components/forms/_presentation_data_editor.scss
185
186
  - app/assets/stylesheets/components/forms/_tag_input.scss
187
+ - app/assets/stylesheets/components/list/_expandable_item.scss
186
188
  - app/assets/stylesheets/components/navigation/_footer.scss
189
+ - app/assets/stylesheets/components/navigation/_mixins.scss
187
190
  - app/assets/stylesheets/components/navigation/_page_nav.scss
188
191
  - app/assets/stylesheets/components/navigation/_site_nav.scss
189
192
  - app/controllers/wcms_application_controller.rb
193
+ - app/controllers/wcms_components/changes_controller.rb
190
194
  - app/controllers/wcms_components/embedded_images_controller.rb
191
195
  - app/controllers/wcms_components/people_controller.rb
192
196
  - app/controllers/wcms_components/tags_controller.rb
193
197
  - app/helpers/wcms_components/alerts_helper.rb
194
198
  - app/helpers/wcms_components/component_helper.rb
195
199
  - app/helpers/wcms_components/navigation_helper.rb
200
+ - app/policies/change_policy.rb
196
201
  - app/views/wcms_components/alerts/_impersonation.html.slim
197
202
  - app/views/wcms_components/alerts/_message_list.html.slim
203
+ - app/views/wcms_components/changes/_change_index.html.slim
204
+ - app/views/wcms_components/changes/_changes.html.slim
205
+ - app/views/wcms_components/changes/index.html.slim
206
+ - app/views/wcms_components/changes/object_index.html.slim
198
207
  - app/views/wcms_components/forms/_data_template_picker.html.slim
199
208
  - app/views/wcms_components/forms/_date.html.slim
200
209
  - app/views/wcms_components/forms/_datetime.html.slim
@@ -254,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
254
263
  version: '0'
255
264
  requirements: []
256
265
  rubyforge_project:
257
- rubygems_version: 2.4.6
266
+ rubygems_version: 2.2.2
258
267
  signing_key:
259
268
  specification_version: 4
260
269
  summary: Reusable UX components for use in or WCMS projects