Merge pull request #1019 from nishanthvijayan/changelog

Changelog/Revision History page
This commit is contained in:
Stella Rouzi
2016-08-15 14:16:12 +03:00
committed by GitHub
51 changed files with 1154 additions and 26 deletions

View File

@@ -41,6 +41,7 @@
//= require osem-schedule
//= require osem-switch
//= require osem-bootstrap
//= require osem-revisionhistory
//= require osem-commercials
//= require unobtrusive_flash
//= require unobtrusive_flash_bootstrap

View File

@@ -7,6 +7,11 @@ $(function () {
pagingType: 'full_numbers',
"lengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]]
});
$('#versionstable').DataTable({
pagingType: 'full_numbers',
order: [[ 0, 'desc' ]]
});
});
});

View File

@@ -0,0 +1,10 @@
$(document).ready(function() {
$('.show-changeset').click(function(){
if ($(this).text() == 'View Changes'){
$(this).text('Hide Changes');
}else {
$(this).text('View Changes');
}
$('#changeset-' + this.id).toggle();
});
});

View File

@@ -86,3 +86,7 @@ p.comment-body {
#proposal-info div dt, #proposal-info div dd {
display: inline-block;
}
.changeset{
display: none;
}

View File

@@ -0,0 +1,58 @@
module Admin
class VersionsController < Admin::BaseController
skip_authorization_check
def index
authorize! :index, PaperTrail::Version.new(item_type: 'User')
conf_ids_for_organizer = current_user.is_admin? ? Conference.pluck(:id) : Conference.with_role(:organizer, current_user).pluck(:id)
@versions = PaperTrail::Version.where(["conference_id IN (?) OR item_type = 'User'", conf_ids_for_organizer])
end
def revert_attribute
@version = PaperTrail::Version.find(params[:id])
authorize! :revert_attribute, @version
if params[:attribute] && @version.changeset.reject{ |_, values| values[0].blank? && values[1].blank? }.keys.include?(params[:attribute])
if @version.item[params[:attribute]] == @version.changeset[params[:attribute]][0]
flash[:error] = 'The item is already in the state that you are trying to revert it back to'
else
@version.item[params[:attribute]] = @version.changeset[params[:attribute]][0]
if @version.item.save
flash[:notice] = 'The selected change was successfully reverted'
else
flash[:error] = "An error prohibited this change from being reverted: #{@version.item.errors.full_messages.join('. ')}."
end
end
else
flash[:error] = 'Revert failed. Attribute missing or invalid'
end
redirect_to admin_revision_history_path
end
def revert_object
@version = PaperTrail::Version.find(params[:id])
authorize! :revert_object, @version
if @version.event != 'create'
if @version.reify.save
flash[:notice] = 'The selected change was successfully reverted'
else
flash[:error] = "An error prohibited this change from being reverted: #{@version.reify.errors.full_messages.join('. ')}."
end
elsif @version.event == 'create' && @version.item
# if @version represets a create event and is not currently deleted
@version.item.destroy
flash[:notice] = 'The selected change was successfully reverted'
else
flash[:error] = 'The item is already in the state that you are trying to revert it back to'
end
redirect_to admin_revision_history_path
end
end
end

View File

@@ -370,4 +370,125 @@ module ApplicationHelper
def selected_scheduled?(schedule)
(schedule == @selected_schedule) ? 'Yes' : 'No'
end
# Recieves a PaperTrail::Version object
# Outputs the list of attributes that were changed in the version (ignoring changes from one blank value to another)
# Eg: If version.changeset = '{"title"=>[nil, "Premium"], "description"=>[nil, "Premium = Super cool"], "conference_id"=>[nil, 3]}'
# Output will be 'title, description and conference'
def updated_attributes(version)
version.changeset.
reject{ |_, values| values[0].blank? && values[1].blank? }.
keys.map{ |key| key.gsub('_id', '').tr('_', ' ')}.join(', ').
reverse.sub(',', ' dna ').reverse
end
def change_creator_link(user_id)
user = User.find_by(id: user_id)
if user
link_to user.name, admin_user_path(id: user_id)
else
'Someone (probably via the console)'
end
end
# Recieves a PaperTrail::Version object
# Returns object in its current state if its alive
# Returns object as it was before version's change(unless its a create event's version)
# Else Returns object as it was after version's change
def get_version_object(version)
version.item || version.reify || version.next.reify
end
def event_change_description(version)
case
when version.event == 'create' then 'submitted new'
when version.changeset['state']
case version.changeset['state'][1]
when 'unconfirmed' then 'accepted'
when 'withdrawn' then 'withdrew'
when 'canceled', 'rejected', 'confirmed' then version.changeset['state'][1]
when 'new' then 'resubmitted'
end
when version.changeset['start_time'] && version.changeset['start_time'][0].nil?
'scheduled'
when version.changeset['start_time'] && version.changeset['start_time'][1].nil?
'unscheduled'
else
"updated #{updated_attributes(version)} of"
end
end
def users_role_change_description(version)
version.event == 'create' ? 'added' : 'removed'
end
def subscription_change_description(version)
user = get_version_object(version).user
user_name = user.name unless user.id.to_s == version.whodunnit
version.event == 'create' ? "subscribed #{user_name} to" : "unsubscribed #{user_name} from"
end
def registration_change_description(version)
if version.item_type == 'Registration'
user = get_version_object(version).user
else
registration_id = get_version_object(version).registration_id
registration_last_version = PaperTrail::Version.where(item_type: 'Registration', item_id: registration_id).last
user = get_version_object(registration_last_version).user
end
if user.id.to_s == version.whodunnit
case version.event
when 'create' then 'registered to'
when 'update' then "updated #{updated_attributes(version)} of the registration for"
when 'destroy' then 'unregistered from'
end
else
case version.event
when 'create' then "registered #{user.name} to"
when 'update' then "updated #{updated_attributes(version)} of #{user.name}'s registration for"
when 'destroy' then "unregistered #{user.name} from"
end
end
end
def comment_change_description(version)
user = get_version_object(version).user
if version.event == 'create'
version.previous.nil? ? 'commented on' : "re-added #{user.name}'s comment on"
else
"deleted #{user.name}'s comment on"
end
end
def vote_change_description(version)
user = get_version_object(version).user
if version.event == 'create'
version.previous.nil? ? 'voted on' : "re-added #{user.name}'s vote on"
elsif version.event == 'update'
"updated #{user.name}'s vote on"
else
"deleted #{user.name}'s vote on"
end
end
def user_change_description(version)
if version.event == 'create'
change_creator_link(version.item_id) + ' signed up'
elsif version.event == 'update'
if version.changeset.keys.include?('reset_password_sent_at')
'Someone requested password reset of'
elsif version.changeset.keys.include?('confirmed_at') && version.changeset['confirmed_at'][0].nil?
(version.whodunnit.nil? ? change_creator_link(version.item_id) : change_creator_link(version.whodunnit)) + ' confirmed account of'
elsif version.changeset.keys.include?('confirmed_at') && version.changeset['confirmed_at'][1].nil?
change_creator_link(version.whodunnit) + ' unconfirmed account of'
else
change_creator_link(version.whodunnit) + " updated #{updated_attributes(version)} of"
end
end
end
end

View File

@@ -114,6 +114,14 @@ class Ability
# for admins
can :manage, :all if user.is_admin
cannot :revert_object, PaperTrail::Version do |version|
(version.event == 'create' && %w(Conference User Event).include?(version.item_type))
end
cannot :revert_attribute, PaperTrail::Version do |version|
version.event != 'update' || version.item.nil?
end
cannot :destroy, Program
# Do not delete venue, when there are rooms being used
cannot :destroy, Venue do |venue|
@@ -168,6 +176,10 @@ class Ability
can [:edit, :update, :toggle_user], Role do |role|
role.resource_type == 'Conference' && (conf_ids_for_organizer.include? role.resource_id)
end
can [:index, :revert_object, :revert_attribute], PaperTrail::Version do |version|
version.item_type == 'User' || (conf_ids_for_organizer.include? version.conference_id)
end
end
def signed_in_with_cfp_role(user)

View File

@@ -4,6 +4,8 @@ class Campaign < ActiveRecord::Base
has_many :targets, dependent: :nullify
belongs_to :conference
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
##
# Returns the utm parameters formatted as url.
#

View File

@@ -1,6 +1,7 @@
# cannot delete program if there are events submitted
class Cfp < ActiveRecord::Base
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
belongs_to :program
validates :program_id, presence: true
@@ -68,4 +69,8 @@ class Cfp < ActiveRecord::Base
errors.
add(:start_date, "can't be after the end date") if start_date && end_date && start_date > end_date
end
def conference_id
program.conference_id
end
end

View File

@@ -13,6 +13,8 @@ class Comment < ActiveRecord::Base
# NOTE: Comments belong to a user
belongs_to :user
has_paper_trail on: [:create, :destroy], meta: { conference_id: :conference_id }
# Helper class method that allows you to build a comment
# by passing a commentable object, a user_id, and comment text
# example in readme
@@ -58,4 +60,8 @@ class Comment < ActiveRecord::Base
def send_notification
EventCommentMailJob.perform_later(self)
end
def conference_id
commentable.program.conference_id
end
end

View File

@@ -3,6 +3,8 @@ class Commercial < ActiveRecord::Base
belongs_to :commercialable, polymorphic: true
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
validates :url, presence: true
validates :url, format: URI::regexp(%w(http https))
@@ -41,4 +43,12 @@ class Commercial < ActiveRecord::Base
speakerdeck
)
end
def conference_id
case commercialable_type
when 'Conference' then commercialable_id
when 'Event' then Event.find(commercialable_id).program.conference_id
when 'Venue' then Venue.find(commercialable_id).conference_id
end
end
end

View File

@@ -9,7 +9,7 @@ class Conference < ActiveRecord::Base
default_scope { order('start_date DESC') }
has_paper_trail
has_paper_trail ignore: [:updated_at, :guid, :revision, :events_per_week], meta: { conference_id: :id }
has_and_belongs_to_many :questions

View File

@@ -1,4 +1,6 @@
class Contact < ActiveRecord::Base
has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id }
belongs_to :conference
validates :conference, presence: true

View File

@@ -2,7 +2,10 @@ class DifficultyLevel < ActiveRecord::Base
belongs_to :program
has_many :events, dependent: :nullify
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
validates :title, presence: true
validates :color, format: /\A#[0-9A-F]{6}\z/
before_validation :capitalize_color
@@ -12,4 +15,8 @@ class DifficultyLevel < ActiveRecord::Base
def capitalize_color
self.color = color.upcase if color.present?
end
def conference_id
program.conference_id
end
end

View File

@@ -1,6 +1,8 @@
class EmailSettings < ActiveRecord::Base
belongs_to :conference
has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id }
def get_values(conference, user, event = nil)
h = {
'email' => user.email,

View File

@@ -1,6 +1,6 @@
class Event < ActiveRecord::Base
include ActiveRecord::Transitions
has_paper_trail
has_paper_trail on: [:create, :update], ignore: [:updated_at, :guid, :week], meta: { conference_id: :conference_id }
acts_as_commentable
@@ -280,7 +280,9 @@ class Event < ActiveRecord::Base
def set_week
self.week = created_at.strftime('%W')
save!
self.without_versioning do
self.save!
end
end
def before_end_of_conference
@@ -288,4 +290,8 @@ class Event < ActiveRecord::Base
add(:created_at, "can't be after the conference end date!") if program.conference && program.conference.end_date &&
(Date.today > program.conference.end_date)
end
def conference_id
program.conference_id
end
end

View File

@@ -2,6 +2,8 @@ class EventType < ActiveRecord::Base
belongs_to :program
has_many :events, dependent: :restrict_with_error
has_paper_trail meta: { conference_id: :conference_id }
validates :title, presence: true
validates :length, numericality: {greater_than: 0}
validates :minimum_abstract_length, presence: true
@@ -28,4 +30,8 @@ class EventType < ActiveRecord::Base
def capitalize_color
self.color = color.upcase if color.present?
end
def conference_id
program.conference_id
end
end

View File

@@ -4,9 +4,17 @@ class EventsRegistration < ActiveRecord::Base
has_one :user, through: :registration
has_paper_trail meta: { conference_id: :conference_id }
delegate :name, to: :registration
delegate :email, to: :registration
validates :event, :registration, presence: true
validates :event, uniqueness: { scope: :registration }
private
def conference_id
registration.conference_id
end
end

View File

@@ -1,6 +1,8 @@
class Lodging < ActiveRecord::Base
belongs_to :conference
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
validates :name, presence: true
mount_uploader :picture, PictureUploader, mount_on: :photo_file_name

View File

@@ -1,6 +1,8 @@
# cannot delete program if there are events submitted
class Program < ActiveRecord::Base
has_paper_trail on: [:update], ignore: [:updated_at], meta: { conference_id: :conference_id }
belongs_to :conference
has_one :cfp, dependent: :destroy
@@ -53,8 +55,8 @@ class Program < ActiveRecord::Base
validate :voting_start_date_before_end_date
validate :voting_dates_exist
before_create :create_event_types
before_create :create_difficulty_levels
after_create :create_event_types
after_create :create_difficulty_levels
validate :check_languages_format
# Returns all event_schedules for the selected schedule ordered by start_time
@@ -157,12 +159,12 @@ class Program < ActiveRecord::Base
# Creates default EventTypes for this Conference. Used as before_create.
#
def create_event_types
event_types << EventType.create(title: 'Talk', length: 30, color: '#FF0000', description: 'Presentation in lecture format',
minimum_abstract_length: 0,
maximum_abstract_length: 500)
event_types << EventType.create(title: 'Workshop', length: 60, color: '#0000FF', description: 'Interactive hands-on practice',
minimum_abstract_length: 0,
maximum_abstract_length: 500)
EventType.create(title: 'Talk', length: 30, color: '#FF0000', description: 'Presentation in lecture format',
minimum_abstract_length: 0,
maximum_abstract_length: 500, program_id: self.id)
EventType.create(title: 'Workshop', length: 60, color: '#0000FF', description: 'Interactive hands-on practice',
minimum_abstract_length: 0,
maximum_abstract_length: 500, program_id: self.id)
true
end
@@ -170,15 +172,15 @@ class Program < ActiveRecord::Base
# Creates default DifficultyLevels for this Conference. Used as before_create.
#
def create_difficulty_levels
difficulty_levels << DifficultyLevel.create(title: 'Easy',
description: 'Events are understandable for everyone without knowledge of the topic.',
color: '#70EF69')
difficulty_levels << DifficultyLevel.create(title: 'Medium',
description: 'Events require a basic understanding of the topic.',
color: '#EEEF69')
difficulty_levels << DifficultyLevel.create(title: 'Hard',
description: 'Events require expert knowledge of the topic.',
color: '#EF6E69')
DifficultyLevel.create(title: 'Easy',
description: 'Events are understandable for everyone without knowledge of the topic.',
color: '#70EF69', program_id: self.id)
DifficultyLevel.create(title: 'Medium',
description: 'Events require a basic understanding of the topic.',
color: '#EEEF69', program_id: self.id)
DifficultyLevel.create(title: 'Hard',
description: 'Events require expert knowledge of the topic.',
color: '#EF6E69', program_id: self.id)
true
end

View File

@@ -7,7 +7,9 @@ class Registration < ActiveRecord::Base
has_and_belongs_to_many :vchoices
has_many :events_registrations
has_many :events, through: :events_registrations
has_many :events, through: :events_registrations, dependent: :destroy
has_paper_trail ignore: [:updated_at, :week], meta: { conference_id: :conference_id }
accepts_nested_attributes_for :user
accepts_nested_attributes_for :qanswers
@@ -75,7 +77,9 @@ class Registration < ActiveRecord::Base
def set_week
self.week = created_at.strftime('%W')
save!
without_versioning do
save!
end
end
def registration_limit_not_exceed

View File

@@ -1,6 +1,8 @@
class RegistrationPeriod < ActiveRecord::Base
belongs_to :conference
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
validates :start_date, :end_date, presence: true
validate :before_end_of_conference
validate :start_date_before_end_date

View File

@@ -1,6 +1,10 @@
class Role < ActiveRecord::Base
belongs_to :resource, polymorphic: true
has_and_belongs_to_many :users, join_table: :users_roles
has_many :users_roles
has_many :users, through: :users_roles
has_paper_trail on: [:update], only: [:name, :description], meta: { conference_id: :resource_id }
before_destroy :cancel
scopify

View File

@@ -2,6 +2,8 @@ class Room < ActiveRecord::Base
belongs_to :venue
has_many :event_schedules, dependent: :nullify
has_paper_trail ignore: [:guid], meta: { conference_id: :conference_id }
before_create :generate_guid
validates :name, :venue_id, presence: true
@@ -14,4 +16,8 @@ class Room < ActiveRecord::Base
guid = SecureRandom.urlsafe_base64
self.guid = guid
end
def conference_id
venue.conference_id
end
end

View File

@@ -1,3 +1,5 @@
class Splashpage < ActiveRecord::Base
belongs_to :conference
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
end

View File

@@ -2,6 +2,8 @@ class Sponsor < ActiveRecord::Base
belongs_to :sponsorship_level
belongs_to :conference
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
mount_uploader :picture, PictureUploader, mount_on: :logo_file_name
validates_presence_of :name, :website_url, :sponsorship_level

View File

@@ -3,4 +3,6 @@ class SponsorshipLevel < ActiveRecord::Base
belongs_to :conference
acts_as_list scope: :conference
has_many :sponsors
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
end

View File

@@ -3,5 +3,7 @@ class Subscription < ActiveRecord::Base
belongs_to :conference
belongs_to :user
has_paper_trail on: [:create, :destroy], ignore: [:updated_at], meta: { conference_id: :conference_id }
validates_uniqueness_of :user_id, scope: :conference_id, message: 'already subscribed!'
end

View File

@@ -3,6 +3,8 @@ class Target < ActiveRecord::Base
default_scope { order('due_date ASC') }
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
def self.units
{
registrations: 'Registration',

View File

@@ -3,6 +3,8 @@ class Ticket < ActiveRecord::Base
has_many :ticket_purchases, dependent: :destroy
has_many :buyers, -> { distinct }, through: :ticket_purchases, source: :user
has_paper_trail meta: { conference_id: :conference_id }
monetize :price_cents, with_model_currency: :price_currency
# This validation is for the sake of simplicity.

View File

@@ -2,6 +2,8 @@ class Track < ActiveRecord::Base
belongs_to :program
has_many :events, dependent: :nullify
has_paper_trail only: [:name, :description, :color], meta: { conference_id: :conference_id }
before_create :generate_guid
validates :name, presence: true
validates :color, format: /\A#[0-9A-F]{6}\z/
@@ -21,4 +23,8 @@ class Track < ActiveRecord::Base
def capitalize_color
self.color = color.upcase if color.present?
end
def conference_id
program.conference_id
end
end

View File

@@ -6,6 +6,12 @@ end
class User < ActiveRecord::Base
rolify
has_many :users_roles
has_many :roles, through: :users_roles, dependent: :destroy
has_paper_trail on: [:create, :update], ignore: [:sign_in_count, :remember_created_at, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip, :unconfirmed_email,
:avatar_content_type, :avatar_file_size, :avatar_updated_at, :updated_at, :confirmation_sent_at, :confirmation_token, :reset_password_token]
include Gravtastic
gravtastic size: 32
@@ -72,7 +78,7 @@ class User < ActiveRecord::Base
end
def name
self[:name] || username
self[:name].blank? ? username : self[:name]
end
##

12
app/models/users_role.rb Normal file
View File

@@ -0,0 +1,12 @@
class UsersRole < ActiveRecord::Base
belongs_to :role
belongs_to :user
has_paper_trail on: [:create, :destroy], meta: { conference_id: :conference_id }
private
def conference_id
role.resource_id
end
end

View File

@@ -4,6 +4,8 @@ class Venue < ActiveRecord::Base
has_many :rooms, dependent: :destroy
before_create :generate_guid
has_paper_trail ignore: [:updated_at, :guid], meta: { conference_id: :conference_id }
accepts_nested_attributes_for :commercial, allow_destroy: true
validates :name, :street, :city, :country, presence: true

View File

@@ -1,5 +1,14 @@
class Vote < ActiveRecord::Base
belongs_to :user
belongs_to :event
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
delegate :name, to: :user
private
def conference_id
event.program.conference_id
end
end

View File

@@ -0,0 +1,28 @@
.col-md-10.col-md-offset-1.changeset{id: "changeset-#{version.id}"}
%br
%br
%table.table.table-bordered.table-hover
%thead
%tr
%th Updated Attribute
- if version.event != 'create'
%th Previous Value
- if version.event != 'destroy'
%th New Value
- if can? :revert_attribute, version
%th Action
%tbody
- if version.event!= 'destroy'
- version.changeset.reject{ |_, values| values[0].blank? && values[1].blank? }.each do |attribute, values|
%tr
%td= attribute
- if version.event != 'create'
%td= values[0].blank? ? '-' : values[0]
%td= values[1].blank? ? '-' : values[1]
- if can? :revert_attribute, version
%td= link_to 'Revert', admin_revision_history_revert_attribute_path(id: version.id, attribute: attribute), class: 'btn btn-sm btn-primary', data: { confirm: "Are you sure you want to revert #{attribute}?" }
- else
- version.reify.attributes.each do |attribute, value|
%tr
%td= attribute
%td= value.blank? ? '-' : value

View File

@@ -0,0 +1,158 @@
- if version.item_type == 'UsersRole'
- users_role = get_version_object(version)
= 'role'
= link_to users_role.role.name, admin_conference_role_path(conference_id: Conference.find(version.conference_id).short_title, id: users_role.role.name)
= version.event == 'create' ? 'to' : 'from'
= 'user'
= link_to users_role.user.name, admin_user_path(id: users_role.user.id)
- elsif version.item_type == 'Subscription' || version.item_type == 'Registration'
= 'conference'
= link_to Conference.find(version.conference_id).title,
admin_conference_registrations_path(conference_id: Conference.find(version.conference_id).short_title)
- elsif version.item_type == 'Commercial'
- commercial_last_version = get_version_object(PaperTrail::Version.where(item_type: version.item_type, item_id: version.item_id).last)
- commercialable_last_version = get_version_object(PaperTrail::Version.where(item_type: commercial_last_version.commercialable_type,
item_id: commercial_last_version.commercialable_id).last)
- case commercial_last_version.commercialable_type
- when 'Event'
= link_to 'commercial',
edit_admin_conference_program_event_path(conference_id: Conference.find(version.conference_id).short_title,
id: commercialable_last_version.id, anchor: 'commercials-content')
= "in event #{commercialable_last_version.title}"
- when 'Venue'
- if Venue.find_by(id: commercialable_last_version.id)
= link_to 'commercial',
edit_admin_conference_program_event_path(conference_id: Conference.find(version.conference_id).short_title,
id: commercialable_last_version.id, anchor: 'commercials-content')
- else
= 'commercial'
= "in venue #{commercialable_last_version.name}"
- when 'Conference'
= link_to 'commercial',
admin_conference_commercials_path(conference_id: Conference.find(version.conference_id).short_title)
- elsif %w(EventsRegistration Comment Vote).include?(version.item_type)
= 'event'
- event_id = get_version_object(version).try(:event_id) || get_version_object(version).try(:commentable_id)
= link_to Event.find(event_id).title,
admin_conference_program_event_path(conference_id: Conference.find(version.conference_id).short_title, id: event_id)
- elsif version.item_type =='Target'
= 'target'
- if version.item
= link_to Target.find(version.item_id).to_s,
admin_conference_targets_path(conference_id: Conference.find(version.conference_id).short_title)
- else
= PaperTrail::Version.where(item_type: 'Target', item_id: version.item_id).last.reify.to_s
- elsif version.item
- case version.item_type
- when 'Conference'
= 'conference'
= link_to Conference.find(version.conference_id).title,
edit_admin_conference_path(id: Conference.find(version.conference_id).short_title)
- when 'RegistrationPeriod'
= link_to 'registration period',
admin_conference_registration_period_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Contact'
= link_to 'contact details',
edit_admin_conference_contact_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Program'
= link_to 'program',
admin_conference_program_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Cfp'
= link_to 'cfp',
admin_conference_program_cfp_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Track'
= 'track'
= link_to Track.find(version.item_id).name,
admin_conference_program_track_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item_id)
- when 'Event'
= 'event'
= link_to Event.find(version.item_id).title,
admin_conference_program_event_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item_id)
- when 'EventType'
= 'event type'
= link_to EventType.find(version.item_id).title,
admin_conference_program_event_types_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Role'
= 'role'
= link_to Role.find(version.item_id).name,
admin_conference_role_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item.name)
- when 'Venue'
= 'venue'
= link_to Venue.find(version.item_id).name,
admin_conference_venue_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Lodging'
= 'lodging'
= link_to Lodging.find(version.item_id).name,
admin_conference_lodgings_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Room'
= 'room'
= link_to Room.find(version.item_id).name,
admin_conference_venue_rooms_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Sponsor'
= 'sponsor'
= link_to Sponsor.find(version.item_id).name,
admin_conference_sponsors_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'SponsorshipLevel'
= 'sponsorship level'
= link_to SponsorshipLevel.find(version.item_id).title,
admin_conference_sponsorship_levels_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'Ticket'
= 'ticket'
= link_to Ticket.find(version.item_id).title,
admin_conference_ticket_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item_id)
- when 'Campaign'
= 'campaign'
= link_to Campaign.find(version.item_id).name,
admin_conference_campaigns_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'DifficultyLevel'
= 'difficulty level'
= link_to DifficultyLevel.find(version.item_id).title,
admin_conference_program_difficulty_level_path(conference_id: Conference.find(version.conference_id).short_title, id: version.item_id)
- when 'Splashpage'
= link_to 'splashpage',
admin_conference_splashpage_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'EmailSettings'
= link_to 'email settings',
admin_conference_emails_path(conference_id: Conference.find(version.conference_id).short_title)
- when 'User'
- if version.event == 'update'
= 'user'
= link_to User.find(version.item_id).name, admin_user_path(id: version.item_id)
- else
= version.item_type.underscore.tr('_', ' ')
/ The last deleted version's name/title is used to describe all the changes in object
- last_deleted_version = PaperTrail::Version.where(item_type: version.item_type, item_id: version.item_id).last.reify
= last_deleted_version.try(:title) || last_deleted_version.try(:name)
- unless %w(Conference Subscription Registration User).include?(version.item_type)
= "in conference"
= link_to Conference.find(version.conference_id).short_title,
edit_admin_conference_path(id: Conference.find(version.conference_id).short_title)

View File

@@ -0,0 +1,77 @@
.row
.col-md-12
.page-header
%h1 Revision History
%p.text-muted
Log of changes made to conferences and associated resources
%table.table.table-striped.table-bordered.table-hover#versionstable
%thead
%td ID
%td Description
%td Actions
%tbody
- @versions.each do |version|
%tr
%td.col-md-1
= version.id
%td.col-md-9
%p
= change_creator_link(version.whodunnit) unless version.item_type == 'User'
- case version.item_type
- when 'Event'
= event_change_description(version)
-when 'UsersRole'
= users_role_change_description(version)
- when 'Subscription'
= subscription_change_description(version)
- when 'Registration', 'EventsRegistration'
= registration_change_description(version)
- when 'Comment'
= comment_change_description(version)
- when 'Vote'
= vote_change_description(version)
- when 'User'
= user_change_description(version)
- else
- if version.event == 'create'
= 'created new'
- elsif version.event == 'update'
= "updated #{updated_attributes(version)} of"
- else
= 'deleted'
= render partial: 'object_desc_and_link', locals: { version: version }
%small.text-muted
= distance_of_time_in_words(Time.now,version.created_at) + ' ago'
%br
= "(#{version.created_at.strftime('%B %-d, %Y %H:%M')})"
%br
= render partial: 'object_changes', locals: { version: version }
%td.col-md-2
.btn-group{role: 'group'}
%a.btn.btn-success.btn-sm.show-changeset{id: version.id} View Changes
- if can? :revert_object, version
%button.btn.btn-default.dropdown-toggle.btn-sm.btn-primary{'data-toggle' => 'dropdown', type: 'button'}
Revert
%span.caret
%ul.dropdown-menu
%li= link_to 'All Changes', admin_revision_history_revert_object_path(id: version.id), data: { confirm: 'Are you sure you want to revert this change?' }
- if can? :revert_attribute, version
%li.divider{role: 'separator'}
- version.changeset.reject{ |_, values| values[0].blank? && values[1].blank? }.each do |attribute, values|
%li= link_to attribute, admin_revision_history_revert_attribute_path(id: version.id, attribute: attribute), data: { confirm: "Are you sure you want to revert #{attribute}?" }
- else
%button.btn.btn-sm.btn-primary.disabled Revert

View File

@@ -27,3 +27,8 @@
= link_to(admin_users_path) do
%span.fa.fa-user
Users
- if can? :index, PaperTrail::Version.new(item_type: 'User')
%li
= link_to(admin_revision_history_path) do
%span.fa.fa-history
Revision History

View File

@@ -44,3 +44,8 @@
= link_to(admin_users_path) do
%span.fa.fa-user
Users
- if can? :index, PaperTrail::Version.new(item_type: 'User')
%li
= link_to(admin_revision_history_path) do
%span.fa.fa-history
Revision History

View File

@@ -91,6 +91,10 @@ Osem::Application.routes.draw do
end
end
end
get '/revision_history' => 'versions#index'
get '/revision_history/:id/revert_object' => 'versions#revert_object', as: 'revision_history_revert_object'
get '/revision_history/:id/revert_attribute' => 'versions#revert_attribute', as: 'revision_history_revert_attribute'
end
resources :conference, only: [:index, :show] do

View File

@@ -0,0 +1,5 @@
class AddConferenceIdToVersions < ActiveRecord::Migration
def change
add_column :versions, :conference_id, :integer
end
end

View File

@@ -0,0 +1,5 @@
class AddIdToUsersRoles < ActiveRecord::Migration
def change
add_column :users_roles, :id, :primary_key
end
end

View File

@@ -483,7 +483,7 @@ ActiveRecord::Schema.define(version: 20160704092023) do
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
add_index "users", ["username"], name: "index_users_on_username", unique: true
create_table "users_roles", id: false, force: :cascade do |t|
create_table "users_roles", force: :cascade do |t|
t.integer "role_id"
t.integer "user_id"
end
@@ -529,6 +529,7 @@ ActiveRecord::Schema.define(version: 20160704092023) do
t.text "object"
t.text "object_changes"
t.datetime "created_at"
t.integer "conference_id"
end
add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"

21
lib/tasks/version.rake Normal file
View File

@@ -0,0 +1,21 @@
namespace :data do
desc 'Sets conference_id in all pre-existing PaperTrail::Version objects'
task set_conference_in_versions: :environment do
PaperTrail::Version.where(conference_id: nil, item_type: ['Conference', 'Event']).each do |version|
# All pre-existing versions are either of Conference or Event
if version.item_type == 'Conference'
version.update_attributes(conference_id: version.item_id)
elsif version.item_type == 'Event'
event = (version.item || version.reify || version.next.reify)
if event.try(:program)
version.update_attributes(conference_id: event.program.conference_id)
else
puts "Setting conference_id value failed for PaperTrail::Version object with ID=#{version.id}"
end
end
end
puts 'All done!'
end
end

View File

@@ -0,0 +1,101 @@
require 'spec_helper'
describe Admin::VersionsController do
let!(:conference) { create(:conference, short_title: 'exampletitle', description: 'Example Description') }
let(:admin) { create(:admin) }
with_versioning do
describe 'GET #revert' do
before :each do
sign_in admin
end
it 'reverts all changes for update actions' do
conference.update_attributes(short_title: 'testtitle', description: 'Some random text')
get :revert_object, id: PaperTrail::Version.last.id
conference.reload
expect(conference.short_title).to eq 'exampletitle'
expect(conference.description).to eq 'Example Description'
end
it 'shows correct flash on trying to revert create event of a deleted object' do
creation_version_id = conference.program.event_types.first.versions.first.id
conference.program.event_types.first.destroy
get :revert_object, id: creation_version_id
expect(flash[:error]).to match('The item is already in the state that you are trying to revert it back to')
end
it 'reverting deletion of object creates it again' do
conference.program.event_types.first.destroy
event_types_count = conference.program.event_types.count
get :revert_object, id: PaperTrail::Version.last.id
conference.reload
expect(PaperTrail::Version.last.event).to eq 'create'
expect(conference.program.event_types.count).to eq(event_types_count + 1)
end
it 'reverting creation of object deletes it ' do
create(:lodging, conference: conference)
get :revert_object, id: PaperTrail::Version.last.id
expect(PaperTrail::Version.last.event).to eq 'destroy'
expect(Lodging.count).to eq 0
end
it 'reverting creation of conference is not permitted' do
conference_count_before = Conference.count
get :revert_object, id: conference.versions.first.id
expect(flash[:alert]).to eq 'You are not authorized to access this page.'
expect(Conference.count).to eq(conference_count_before)
end
end
describe 'GET #revert_attribute' do
before :each do
sign_in admin
end
it 'reverts specified change for update actions' do
conference.update_attributes(short_title: 'testtitle', description: 'Some random text')
get :revert_attribute, id: PaperTrail::Version.last.id, attribute: 'short_title'
conference.reload
expect(conference.short_title).to eq 'exampletitle'
expect(conference.description).to eq 'Some random text'
end
it 'shows correct flash on trying to revert to the current state' do
conference.update_attributes(short_title: 'testtitle', description: 'Some random text')
conference.update_attributes(short_title: 'exampletitle')
get :revert_attribute, id: PaperTrail::Version.all[-2].id, attribute: 'short_title'
expect(flash[:error]).to match('The item is already in the state that you are trying to revert it back to')
expect(conference.short_title).to eq 'exampletitle'
end
it 'fails on trying to revert deleted object' do
conference.program.event_types.first.update_attributes(title: 'New Event Title')
conference.program.event_types.first.destroy
get :revert_attribute, id: PaperTrail::Version.all[-2].id, attribute: 'title'
conference.reload
expect(flash[:alert]).to eq 'You are not authorized to access this page.'
end
it 'fails on trying to revert creation event' do
create(:lodging, conference: conference)
get :revert_attribute, id: PaperTrail::Version.last.id, attribute: 'name'
expect(flash[:alert]).to eq 'You are not authorized to access this page.'
end
it 'revert fails when attribute is invalid' do
conference.update_attributes(short_title: 'testtitle', description: 'Some random text')
before_conference_title = conference.title
# Note: even though title is a valid attribute of conference, it was not updated in the change we are trying to revert
get :revert_attribute, id: PaperTrail::Version.last.id, attribute: 'title'
conference.reload
expect(conference.short_title).to eq 'testtitle'
expect(conference.description).to eq 'Some random text'
expect(conference.title).to eq(before_conference_title)
expect(flash[:error]).to match('Revert failed. Attribute missing or invalid')
end
end
end
end

View File

@@ -17,7 +17,6 @@ FactoryGirl.define do
factory :event_full do
difficulty_level
track
after(:build) do |event|
event.commercials << build(:event_commercial, commercialable: event)
event.difficulty_level = build(:difficulty_level, program: event.program)

View File

@@ -3,5 +3,6 @@ FactoryGirl.define do
name { Faker::Commerce.department(2, true) }
description { Faker::Lorem.sentence }
color { Faker::Color.hex_color }
program
end
end

View File

@@ -102,6 +102,9 @@ feature 'Has correct abilities' do
visit admin_conference_commercials_path(conference1.short_title)
expect(current_path).to eq(admin_conference_commercials_path(conference1.short_title))
visit admin_revision_history_path
expect(current_path).to eq(admin_revision_history_path)
end
scenario 'when user is cfp' do
@@ -176,6 +179,9 @@ feature 'Has correct abilities' do
visit admin_conference_commercials_path(conference2.short_title)
expect(current_path).to eq(root_path)
visit admin_revision_history_path
expect(current_path).to eq(root_path)
end
scenario 'when user is info desk' do
@@ -250,5 +256,8 @@ feature 'Has correct abilities' do
visit admin_conference_commercials_path(conference3.short_title)
expect(current_path).to eq(root_path)
visit admin_revision_history_path
expect(current_path).to eq(root_path)
end
end

View File

@@ -0,0 +1,373 @@
require 'spec_helper'
feature 'Version' do
let!(:conference) { create(:conference) }
let!(:organizer_role) { Role.find_by(name: 'organizer', resource: conference) }
let!(:organizer) { create(:user, role_ids: [organizer_role.id]) }
before(:each) do
sign_in organizer
end
scenario 'display changes in contact', feature: true, versioning: true, js: true do
visit edit_admin_conference_contact_path(conference.short_title)
fill_in 'contact_email', with: 'example@example.com'
fill_in 'contact_sponsor_email', with: 'sponsor@example.com'
fill_in 'contact_social_tag', with: 'example'
fill_in 'contact_googleplus', with: 'http:\\www.google.com'
click_button 'Update Contact'
visit admin_revision_history_path
expect(page).to have_text("#{organizer.name} updated social tag, email, googleplus and sponsor email of contact details in conference #{conference.short_title}")
end
scenario 'display changes in program', feature: true, versioning: true, js: true do
visit edit_admin_conference_program_path(conference.short_title)
fill_in 'program_rating', with: '4'
click_button 'Update Program'
visit admin_revision_history_path
expect(page).to have_text("#{organizer.name} updated rating of program in conference #{conference.short_title}")
end
scenario 'display changes in cfp', feature: true, versioning: true, js: true do
cfp = create(:cfp, program: conference.program)
cfp.update_attributes(start_date: (Date.today + 1).strftime('%d/%m/%Y'), end_date: (Date.today + 3).strftime('%d/%m/%Y'))
cfp.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new cfp in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated start date and end date of cfp in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted cfp in conference #{conference.short_title}")
end
scenario 'display changes in registration_period', feature: true, versioning: true, js: true do
registration_period = create(:registration_period, conference: conference)
registration_period.update_attributes(start_date: (Date.today + 1).strftime('%d/%m/%Y'), end_date: (Date.today + 3).strftime('%d/%m/%Y'))
registration_period.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new registration period in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated start date and end date of registration period in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted registration period in conference #{conference.short_title}")
end
scenario 'display changes in conference', feature: true, versioning: true, js: true do
new_conference = create(:conference, title: 'Test Conference')
organizer.add_role :organizer, new_conference
new_conference.update_attributes(title: 'New Con', short_title: 'NewCon')
visit admin_revision_history_path
expect(page).to have_text('Someone (probably via the console) created new conference New Con')
expect(page).to have_text('Someone (probably via the console) created new event type Talk in conference NewCon')
expect(page).to have_text('Someone (probably via the console) created new event type Workshop in conference NewCon')
expect(page).to have_text('Someone (probably via the console) updated title and short title of conference New Con')
end
scenario 'display changes in event_type', feature: true, versioning: true, js: true do
event_type = create(:event_type, program: conference.program, name: 'Discussion')
event_type.update_attributes(length: 90, maximum_abstract_length: 10000)
event_type.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new event type Discussion in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated length and maximum abstract length of event type Discussion in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted event type Discussion in conference #{conference.short_title}")
end
scenario 'display changes in lodging', feature: true, versioning: true, js: true do
lodging = create(:lodging, conference: conference, name: 'Hotel XYZ')
lodging.update_attributes(description: 'Nice view,close to venue', website_link: 'http://www.example.com')
lodging.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new lodging Hotel XYZ in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated description and website link of lodging Hotel XYZ in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted lodging Hotel XYZ in conference #{conference.short_title}")
end
scenario 'display changes in role', feature: true, versioning: true, js: true do
visit edit_admin_conference_role_path(conference.short_title, 'cfp')
fill_in 'role_description', with: 'For the members of the call for papers team'
click_button 'Update Role'
visit admin_revision_history_path(conference_id: conference.short_title)
expect(page).to have_text("#{organizer.name} updated description of role cfp in conference #{conference.short_title}")
end
scenario 'display changes in room', feature: true, versioning: true, js: true do
venue = create(:venue, conference: conference)
room = create(:room, venue: venue, name: 'Auditorium')
room.update_attributes(size: 120)
room.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new room Auditorium in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated size of room Auditorium in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted room Auditorium in conference #{conference.short_title}")
end
scenario 'display changes in sponsor', feature: true, versioning: true, js: true do
conference.sponsorship_levels << create_list(:sponsorship_level, 2, conference: conference)
sponsor = create(:sponsor, conference: conference, name: 'SUSE', sponsorship_level: conference.sponsorship_levels.first)
sponsor.update_attributes(website_url: 'https://www.suse.com/company/history', sponsorship_level: conference.sponsorship_levels.second)
sponsor.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new sponsor SUSE in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated website url and sponsorship level of sponsor SUSE in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted sponsor SUSE in conference #{conference.short_title}")
end
scenario 'display changes in sponsorship_level', feature: true, versioning: true, js: true do
sponsorship_level = create(:sponsorship_level, conference: conference)
sponsorship_level.update_attributes(title: 'Gold')
sponsorship_level.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new sponsorship level Gold in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated title of sponsorship level Gold in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted sponsorship level Gold in conference #{conference.short_title}")
end
scenario 'display changes in ticket', feature: true, versioning: true, js: true do
ticket = create(:ticket, conference: conference, title: 'Gold')
ticket.update_attributes(price: 50, description: 'Premium Ticket')
ticket.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new ticket Gold in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated price cents and description of ticket Gold in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted ticket Gold in conference #{conference.short_title}")
end
scenario 'display changes in track', feature: true, versioning: true, js: true do
track = create(:track, program: conference.program, name: 'Distribution')
track.update_attributes(description: 'Events about Linux distributions')
track.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new track Distribution in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated description of track Distribution in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted track Distribution in conference #{conference.short_title}")
end
scenario 'display changes in venue', feature: true, versioning: true, js: true do
venue = create(:venue, conference: conference, name: 'Example University')
venue.update_attributes(website: 'www.example.com new', description: 'Just another beautiful venue')
venue.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new venue Example University in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated website and description of venue Example University in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted venue Example University in conference #{conference.short_title}")
end
scenario 'display changes in event', feature: true, versioning: true, js: true do
visit new_conference_program_proposal_path(conference_id: conference.short_title)
fill_in 'event_title', with: 'ABC'
fill_in 'event_abstract', with: 'Lorem ipsum abstract'
select('Talk - 30 min', from: 'event[event_type_id]')
click_button 'Create Proposal'
click_link 'Edit'
fill_in 'event_subtitle', with: 'My event subtitle'
select('Easy', from: 'event[difficulty_level_id]')
click_button 'Update Proposal'
visit admin_conference_program_events_path(conference.short_title)
click_button 'New'
click_link 'Reject event'
visit conference_program_proposal_index_path(conference_id: conference.short_title)
click_link 'Re-Submit'
visit admin_conference_program_events_path(conference.short_title)
click_button 'New'
click_link 'Accept event'
visit conference_program_proposal_index_path(conference_id: conference.short_title)
click_link 'Confirm'
visit admin_conference_program_events_path(conference.short_title)
click_button 'Confirmed'
click_link 'Cancel event'
visit admin_revision_history_path
expect(page).to have_text("#{organizer.name} submitted new event ABC in conference #{conference.short_title}")
expect(page).to have_text("#{organizer.name} updated difficulty level and subtitle of event ABC in conference #{conference.short_title}")
expect(page).to have_text("#{organizer.name} rejected event ABC in conference #{conference.short_title}")
expect(page).to have_text("#{organizer.name} resubmitted event ABC in conference #{conference.short_title}")
expect(page).to have_text("#{organizer.name} accepted event ABC in conference #{conference.short_title}")
expect(page).to have_text("#{organizer.name} confirmed event ABC in conference #{conference.short_title}")
expect(page).to have_text("#{organizer.name} canceled event ABC in conference #{conference.short_title}")
end
scenario 'display changes in difficulty levels', feature: true, versioning: true, js: true do
difficulty_level = create(:difficulty_level, program: conference.program, title: 'Expert')
difficulty_level.update_attributes(description: 'Only for Experts')
difficulty_level.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new difficulty level Expert in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated description of difficulty level Expert in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted difficulty level Expert in conference #{conference.short_title}")
end
scenario 'display changes in splashpages', feature: true, versioning: true, js: true do
visit admin_conference_splashpage_path(conference.short_title)
click_link 'Create Splashpage'
click_button 'Save Splashpage'
click_link 'Edit'
check('Make splash page public')
check('Display tracks on the splashpage?')
check('Display the registration period on the splashpage?')
click_button 'Save Splashpage'
click_link 'Delete'
visit admin_revision_history_path
expect(page).to have_text("#{organizer.name} created new splashpage in conference #{conference.short_title}")
expect(page).to have_text("#{organizer.name} updated public, include tracks and include registrations of splashpage in conference #{conference.short_title}")
expect(page).to have_text("#{organizer.name} deleted splashpage in conference #{conference.short_title}")
end
scenario 'displays users subscribe/unsubscribe to conferences', feature: true, versioning: true, js: true do
visit root_path
click_link 'Subscribe'
click_link 'Unsubscribe'
PaperTrail::Version.last.reify.save!
PaperTrail::Version.last.item.destroy!
visit admin_revision_history_path
expect(page).to have_text("#{organizer.name} subscribed to conference #{conference.title}")
expect(page).to have_text("#{organizer.name} unsubscribed from conference #{conference.title}")
expect(page).to have_text("Someone (probably via the console) subscribed #{organizer.name} to conference #{conference.title}")
expect(page).to have_text("Someone (probably via the console) unsubscribed #{organizer.name} from conference #{conference.title}")
end
scenario 'display changes in conference commercials', feature: true, versioning: true, js: true do
conference_commercial = create(:conference_commercial, commercialable: conference)
conference_commercial.update_attributes(url: 'https://www.youtube.com/watch?v=VNkDJk5_9eU')
conference_commercial.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new commercial in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated url of commercial in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted commercial in conference #{conference.short_title}")
end
scenario 'display changes in event commercials', feature: true, versioning: true, js: true do
event = create(:event, program: conference.program)
event_commercial = create(:event_commercial, commercialable: event, url: 'https://www.youtube.com/watch?v=M9bq_alk-sw')
event_commercial.update_attributes(url: 'https://www.youtube.com/watch?v=VNkDJk5_9eU')
event_commercial.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new commercial in event #{event.title} in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated url of commercial in event #{event.title} in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted commercial in event #{event.title} in conference #{conference.short_title}")
end
scenario 'display changes in users_role', feature: true, versioning: true, js: true do
user = create(:user)
user.add_role :cfp, conference
user.remove_role :cfp, conference
visit admin_revision_history_path
expect(page).to have_text("added role cfp to user #{user.name} in conference #{conference.short_title}")
expect(page).to have_text("removed role cfp from user #{user.name} in conference #{conference.short_title}")
end
scenario 'display changes in email settings', feature: true, versioning: true, js: true do
conference.email_settings.update_attributes(registration_subject: 'xxxxx', registration_body: 'yyyyy', accepted_subject: 'zzzzz')
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) updated registration subject, registration body and accepted subject
of email settings in conference #{conference.short_title}")
end
scenario 'display changes in conference registrations', feature: true, versioning: true, js: true do
Registration.create(user: organizer, conference: conference)
Registration.last.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) registered #{organizer.name} to conference #{conference.title}")
expect(page).to have_text("Someone (probably via the console) unregistered #{organizer.name} from conference #{conference.title}")
end
scenario 'display changes in event registration', feature: true, versioning: true, js: true do
registration = Registration.create(user: organizer, conference: conference)
event = create(:event, program: conference.program)
EventsRegistration.create(registration: registration, event: event)
EventsRegistration.first.update_attributes(attended: true)
EventsRegistration.last.destroy
# Here registration is deleted to ensure the event registration related change still displays the asociated user's name
registration.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) registered #{organizer.name} to event #{event.title} in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated attended of #{organizer.name}'s registration for event #{event.title} in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) unregistered #{organizer.name} from event #{event.title} in conference #{conference.short_title}")
end
scenario 'display changes in target', feature: true, versioning: true, js: true do
target = create(:target, conference: conference)
target.update_attributes(due_date: Date.today, target_count: 1000)
target.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new target 1000 Submissions by #{Date.today} in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated due date and target count of target 1000 Submissions by #{Date.today} in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted target 1000 Submissions by #{Date.today} in conference #{conference.short_title}")
end
scenario 'display changes in comment', feature: true, versioning: true, js: true do
event = create(:event, program: conference.program)
visit admin_conference_program_event_path(conference_id: conference.short_title, id: event.id)
click_link 'Comments (0)'
fill_in 'comment_body', with: 'Sample comment'
click_button 'Add Comment'
Comment.last.destroy
PaperTrail::Version.last.reify.save
visit admin_revision_history_path
expect(page).to have_text("#{organizer.name} commented on event #{event.title} in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted #{organizer.name}'s comment on event #{event.title} in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) re-added #{organizer.name}'s comment on event #{event.title} in conference #{conference.short_title}")
end
scenario 'display changes in campaign', feature: true, versioning: true, js: true do
campaign = create(:campaign, conference: conference, name: 'Test Campaign', utm_campaign: 'campaign')
campaign.update_attributes(utm_source: 'source', utm_medium: 'medium', utm_term: 'term', utm_content: 'content')
campaign.destroy
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) created new campaign Test Campaign in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) updated utm source, utm medium, utm term and utm content of campaign Test Campaign in conference #{conference.short_title}")
expect(page).to have_text("Someone (probably via the console) deleted campaign Test Campaign in conference #{conference.short_title}")
end
scenario 'display password reset requests', feature: true, versioning: true, js: true do
user = create(:user)
user.send_reset_password_instructions
visit admin_revision_history_path
expect(page).to have_text("Someone requested password reset of user #{user.name}")
end
scenario 'display user signups', feature: true, versioning: true, js: true do
create(:user, name: 'testname')
visit admin_revision_history_path
expect(page).to have_text('testname signed up')
end
scenario 'display updates to user', feature: true, versioning: true, js: true do
user = create(:user)
user.update_attributes(nickname: 'testnick', affiliation: 'openSUSE')
visit admin_revision_history_path
expect(page).to have_text("Someone (probably via the console) updated nickname and affiliation of user #{user.name}")
end
end

View File

@@ -22,6 +22,10 @@ ActiveRecord::Migration.maintain_test_schema!
require 'capybara/poltergeist'
require 'phantomjs'
# Adds rspec helper provided by paper_trail
# makes it easier to control when PaperTrail is enabled during testing.
require 'paper_trail/frameworks/rspec'
# Requires supporting ruby files with custom matchers and macros, etc, in
# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are
# run as spec files by default. This means that files in spec/support that end