diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index a4542c19..e4754e1e 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -300,7 +300,7 @@ Lint/UnusedBlockArgument:
# Offense count: 136
Metrics/AbcSize:
- Max: 86
+ Max: 98
# Offense count: 258
# Configuration parameters: CountComments, ExcludedMethods.
@@ -320,7 +320,7 @@ Metrics/LineLength:
# Offense count: 133
# Configuration parameters: CountComments.
Metrics/MethodLength:
- Max: 56
+ Max: 63
# Offense count: 4
# Configuration parameters: CountComments.
diff --git a/Gemfile b/Gemfile
index e624a1f7..9be883a3 100644
--- a/Gemfile
+++ b/Gemfile
@@ -209,6 +209,9 @@ gem 'sprockets-rails'
# for multiple speakers select on proposal/event forms
gem 'selectize-rails'
+# For collecting performance data
+gem 'skylight'
+
# Nokogiri < 1.8.1 is subject to:
# CVE-2017-0663, CVE-2017-7375, CVE-2017-7376, CVE-2017-9047, CVE-2017-9048,
# CVE-2017-9049, CVE-2017-9050
diff --git a/Gemfile.lock b/Gemfile.lock
index 0f64b0e8..9e07eb20 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -297,7 +297,7 @@ GEM
nenv (0.3.0)
netrc (0.11.0)
nio4r (2.1.0)
- nokogiri (1.8.1)
+ nokogiri (1.8.2)
mini_portile2 (~> 2.3.0)
notiffany (0.1.1)
nenv (~> 0.1)
@@ -505,6 +505,8 @@ GEM
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
sixarm_ruby_unaccent (1.1.1)
+ skylight (1.5.1)
+ activesupport (>= 3.0.0)
slop (3.6.0)
sort_alphabetical (1.0.2)
unicode_utils (>= 1.2.2)
@@ -668,6 +670,7 @@ DEPENDENCIES
sass-rails (>= 4.0.2)
selectize-rails
shoulda-matchers
+ skylight
spring-commands-rspec
sprockets-rails
sqlite3
diff --git a/INSTALL.md b/INSTALL.md
index ea47fd93..f07b198f 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -78,35 +78,6 @@ You should not directly expose the web server port unless you have a good reason
## Configure
There are a couple of environment variables you can set to configure OSEM. Check out the *dotenv.example* file.
-| Variable | Content | Purpose |
-|---------- |--------- |--------- |
-| OSEM_NAME | openSUSE Events | The name of your page |
-| OSEM_HOSTNAME | events.opensuse.org | The host this OSEM instance runs on |
-| OSEM_EMAIL_ADDRESS | events@opensuse.org | The address OSEM uses for sending mails |
-| OSEM_ICHAIN_ENABLED | true/false | Enable the usage of [devise_ichain_authenticatable](https://github.com/openSUSE/devise_ichain_authenticatable) |
-| OSEM_TRANSIFEX_APIKEY | *string* | Use this api key for [transifex](https://www.transifex.com/). See TRANSLATION.md for details. |
-| OSEM_ERRBIT_HOST | errbit.opensuse.org | The [errbit](https://github.com/errbit/errbit) host to post exceptions to |
-| OSEM_ERRBIT_APIKEY | *string* | The api key for the errbit host |
-| OSEM_FACTORY_LINT | *boolean* (true/false) | Setting this to false will disable linting of factories before running spec
-| OSEM_GOOGLE_KEY | *string* | OMNIAUTH Developer Key for GOOGLE
-| OSEM_GOOGLE_SECRET | *string* | OMNIAUTH Developer Secret for GOOGLE
-| OSEM_FACEBOOK_KEY | *string* | OMNIAUTH Developer Key for Facebook
-| OSEM_FACEBOOK_SECRET | *string* | OMNIAUTH Developer Secret for Facebook
-| OSEM_GITHUB_KEY | *string* | OMNIAUTH Developer Key for GitHub
-| OSEM_GITHUB_SECRET | *string* | OMNIAUTH Developer Secret for GitHub
-| OSEM_SUSE_KEY | *string* | OMNIAUTH Developer Key for openSUSE
-| OSEM_SUSE_SECRET | *string* | OMNIAUTH Developer Secret for openSUSE
-| OSEM_SMTP_ADDRESS | smtp.opensuse.org | The smtp server to use
-| OSEM_SMTP_PORT | *int* | The port on the smtp server
-| OSEM_SMTP_USERNAME | *string* | The user for the smtp server
-| OSEM_SMTP_PASSWORD | *string* | The password for the smtp server
-| OSEM_SMTP_AUTHENTICATION | plain, login or cram_md5 | The auth method for the smtp server
-| OSEM_SMTP_DOMAIN | opensuse.org | The HELO domain for the smtp server
-| CLOUDINARY_URL | *string* | Configure your cloudinary.com cloud name and api key/secret
-| STRIPE_PUBLISHABLE_KEY | *string* | Publishable Key for Stripe Gateway
-| STRIPE_SECRET_KEY | *string* | Secret Key for Stripe Gateway
-| OSEM_REDIS_URL | *string* | Redis server URL e.g. redis://localhost:6379/1
-
### Online Ticket Payments
We use [Stripe](https://stripe.com) for accepting your ticket payments securely over the web.
Our application uses iFrame for accepting your user's payment details without storing them, making the application PCI SAQ-A Compliant.
@@ -121,8 +92,10 @@ If you would like to resize exisiting logos in your OSEM installation you can do
```shell
$ bundle exec rake logo:reprocess
```
+### Ruby
+OSEM is using Ruby version 2.4
-### openID
+## openID
In order to use [openID](http://openid.net/) logins for your OSEM installation you need to register your application with the providers ([Google](https://code.google.com/apis/console#:access), [GitHub](https://github.com/settings/applications/new) or [Facebook](https://developers.facebook.com/)) and enter their API keys in the environment variables found in your *.env* file(s).
## Recurring Jobs
@@ -130,3 +103,8 @@ Open a separate terminal and go into the directory where the rails app is presen
```
bundle exec rake jobs:work
```
+
+## Performance
+If you are experiencing performance issues (or just curious), you may be able to [apply a free Skylight account](https://www.skylight.io/oss).
+Once you have your account setup, simply set `SKYLIGHT_AUTHENTICATION` and `SKYLIGHT_PUBLIC_DASHBOARD_URL` in your `.env` file.
+If you are reporting a performance issue or submiting a performance patch, it would be helpful (but not required) to link to the relevant Skylight data.
diff --git a/app/assets/stylesheets/breakpoints.css.scss b/app/assets/stylesheets/breakpoints.scss
similarity index 100%
rename from app/assets/stylesheets/breakpoints.css.scss
rename to app/assets/stylesheets/breakpoints.scss
diff --git a/app/assets/stylesheets/mastodon.css.scss b/app/assets/stylesheets/mastodon.scss
similarity index 100%
rename from app/assets/stylesheets/mastodon.css.scss
rename to app/assets/stylesheets/mastodon.scss
diff --git a/app/assets/stylesheets/osem-dashboard.css.scss b/app/assets/stylesheets/osem-dashboard.scss
similarity index 96%
rename from app/assets/stylesheets/osem-dashboard.css.scss
rename to app/assets/stylesheets/osem-dashboard.scss
index 5dc69879..b2d0d125 100644
--- a/app/assets/stylesheets/osem-dashboard.css.scss
+++ b/app/assets/stylesheets/osem-dashboard.scss
@@ -1,4 +1,4 @@
-@import "breakpoints.css.scss";
+@import "breakpoints.scss";
.dashbox span.fa {
line-height: 1.1em;
diff --git a/app/assets/stylesheets/osem-fonts.css.scss b/app/assets/stylesheets/osem-fonts.scss
similarity index 100%
rename from app/assets/stylesheets/osem-fonts.css.scss
rename to app/assets/stylesheets/osem-fonts.scss
diff --git a/app/assets/stylesheets/osem-navbar.css.scss b/app/assets/stylesheets/osem-navbar.scss
similarity index 96%
rename from app/assets/stylesheets/osem-navbar.css.scss
rename to app/assets/stylesheets/osem-navbar.scss
index bfaac9ac..011ebc89 100644
--- a/app/assets/stylesheets/osem-navbar.css.scss
+++ b/app/assets/stylesheets/osem-navbar.scss
@@ -1,4 +1,4 @@
-@import "breakpoints.css.scss";
+@import "breakpoints.scss";
.nav-osem {
border: none;
@include breakpoint(xs) {
diff --git a/app/assets/stylesheets/osem-payments.css.scss b/app/assets/stylesheets/osem-payments.scss
similarity index 100%
rename from app/assets/stylesheets/osem-payments.css.scss
rename to app/assets/stylesheets/osem-payments.scss
diff --git a/app/assets/stylesheets/osem-rating.css.scss b/app/assets/stylesheets/osem-rating.scss
similarity index 100%
rename from app/assets/stylesheets/osem-rating.css.scss
rename to app/assets/stylesheets/osem-rating.scss
diff --git a/app/assets/stylesheets/osem-schedule.css.scss b/app/assets/stylesheets/osem-schedule.scss
similarity index 100%
rename from app/assets/stylesheets/osem-schedule.css.scss
rename to app/assets/stylesheets/osem-schedule.scss
diff --git a/app/assets/stylesheets/osem-splash.css.scss b/app/assets/stylesheets/osem-splash.scss
similarity index 99%
rename from app/assets/stylesheets/osem-splash.css.scss
rename to app/assets/stylesheets/osem-splash.scss
index 387dfc00..32cbb822 100644
--- a/app/assets/stylesheets/osem-splash.css.scss
+++ b/app/assets/stylesheets/osem-splash.scss
@@ -1,4 +1,4 @@
-@import "breakpoints.css.scss";
+@import "breakpoints.scss";
#splash {
// Counter the general padding for #content
diff --git a/app/assets/stylesheets/osem.css.scss b/app/assets/stylesheets/osem.scss
similarity index 94%
rename from app/assets/stylesheets/osem.css.scss
rename to app/assets/stylesheets/osem.scss
index bbcabc44..7d0d0519 100644
--- a/app/assets/stylesheets/osem.css.scss
+++ b/app/assets/stylesheets/osem.scss
@@ -115,3 +115,9 @@ p.comment-body {
float: right;
}
}
+
+/* omniauth btn grp */
+#openid-btn-grp{
+ display: flex;
+ justify-content: center;
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/strap-on.css.scss b/app/assets/stylesheets/strap-on.scss
similarity index 100%
rename from app/assets/stylesheets/strap-on.css.scss
rename to app/assets/stylesheets/strap-on.scss
diff --git a/app/controllers/admin/commercials_controller.rb b/app/controllers/admin/commercials_controller.rb
index 3c694246..1bc587ce 100644
--- a/app/controllers/admin/commercials_controller.rb
+++ b/app/controllers/admin/commercials_controller.rb
@@ -57,7 +57,9 @@ module Admin
def mass_upload
errors = Commercial.read_file(params[:file]) if params[:file]
- if errors.all? { |_k, v| v.blank? }
+ if !params[:file]
+ flash[:error] = 'Empty file detected while adding commercials to Event'
+ elsif errors.all? { |_k, v| v.blank? }
flash[:notice] = 'Successfully added commercials.'
else
errors_text = ''
diff --git a/app/controllers/admin/conferences_controller.rb b/app/controllers/admin/conferences_controller.rb
index 921a23d1..6342f09f 100644
--- a/app/controllers/admin/conferences_controller.rb
+++ b/app/controllers/admin/conferences_controller.rb
@@ -20,6 +20,10 @@ module Admin
@total_submissions = Event.count
@new_submissions = Event.where('created_at > ?', current_user.last_sign_in_at).count
+ @total_withdrawn = Event.where(state: :withdrawn).count
+ @new_withdrawn = Event
+ .where('state = ? and created_at > ?', 'withdrawn', current_user.last_sign_in_at).count
+
@active_conferences = Conference.get_active_conferences_for_dashboard # pending or the last two
@deactive_conferences = Conference
.get_conferences_without_active_for_dashboard(@active_conferences) # conferences without active
@@ -116,13 +120,19 @@ module Admin
@total_reg = @conference.registrations.count
@new_reg = @conference.registrations.where('created_at > ?', current_user.last_sign_in_at).count
- @total_submissions = @program.events.count
- @new_submissions = @program.events
+ @all_events = @program.events
+
+ @total_submissions = @all_events.count
+ @new_submissions = @all_events
.where('created_at > ?', current_user.last_sign_in_at).count
@program_length = @conference.current_program_hours
@new_program_length = @conference.new_program_hours(current_user.last_sign_in_at)
+ @total_withdrawn = @all_events.where(state: :withdrawn).count
+ @new_withdrawn = @all_events
+ .where('state = "withdrawn" and created_at > ?', current_user.last_sign_in_at).count
+
# Step by step list
@conference_progress = @conference.get_status
@@ -162,13 +172,17 @@ module Admin
# Doughnut charts
@event_type_distribution = @conference.event_type_distribution
@event_type_distribution_confirmed = @conference.event_type_distribution(:confirmed)
+ @event_type_distribution_withdrawn = @conference.event_type_distribution(:withdrawn)
@difficulty_levels_distribution = @conference.difficulty_levels_distribution
@difficulty_levels_distribution_confirmed = @conference
.difficulty_levels_distribution(:confirmed)
+ @difficulty_levels_distribution_withdrawn = @conference
+ .difficulty_levels_distribution(:withdrawn)
@tracks_distribution = @conference.tracks_distribution
@tracks_distribution_confirmed = @conference.tracks_distribution(:confirmed)
+ @tracks_distribution_withdrawn = @conference.tracks_distribution(:withdrawn)
# Recent actions information
@recent_events = @conference.program.events.limit(5).order(created_at: :desc)
diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb
index 4b01ca29..1c9b37b3 100644
--- a/app/controllers/conferences_controller.rb
+++ b/app/controllers/conferences_controller.rb
@@ -20,6 +20,11 @@ class ConferencesController < ApplicationController
authorize! :show, @conference # TODO: reduce the 10 queries performed here
splashpage = @conference.splashpage
+
+ unless splashpage.present?
+ redirect_to admin_conference_splashpage_path(@conference.short_title) && return
+ end
+
if splashpage.include_cfp
cfps = @conference.program.cfps
@call_for_events = cfps.find { |call| call.cfp_type == 'events' }
@@ -50,6 +55,7 @@ class ConferencesController < ApplicationController
@sponsorship_levels = @conference.sponsorship_levels.eager_load(
:sponsors
).order('sponsorship_levels.position ASC', 'sponsors.name')
+ @sponsors = @conference.sponsors
end
end
diff --git a/app/controllers/physical_tickets_controller.rb b/app/controllers/physical_tickets_controller.rb
index 2f6f18ec..c3cc40cb 100644
--- a/app/controllers/physical_tickets_controller.rb
+++ b/app/controllers/physical_tickets_controller.rb
@@ -10,7 +10,7 @@ class PhysicalTicketsController < ApplicationController
end
def show
- @file_name = "ticket_for_#{@conference.short_title}"
+ @file_name = "ticket_for_#{@conference.short_title}.pdf"
@user = @physical_ticket.user
@ticket_layout = @conference.ticket_layout.to_sym
@qrcode_image = RQRCode::QRCode.new(@physical_ticket.token).as_png(size: 180, border_modules: 0)
diff --git a/app/models/ability.rb b/app/models/ability.rb
index b833b6f4..d6b3ef21 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -66,7 +66,13 @@ class Ability
can [:new, :create], Registration do |registration|
conference = registration.conference
- conference.registration_open? && !conference.registration_limit_exceeded? || conference.program.speakers.confirmed.include?(user)
+ if conference.user_registered? user
+ false
+ elsif conference.program.speakers.confirmed.include?(user) && conference.registration_period
+ true
+ else
+ conference.registration_open? && !conference.registration_limit_exceeded?
+ end
end
can :index, Organization
diff --git a/app/models/conference.rb b/app/models/conference.rb
index 9adac888..81e9ec32 100644
--- a/app/models/conference.rb
+++ b/app/models/conference.rb
@@ -595,11 +595,11 @@ class Conference < ApplicationRecord
# * +ActiveRecord+
def self.get_active_conferences_for_dashboard
result = Conference.where('start_date > ?', Time.now)
- .select('id, short_title, color, start_date')
+ .select('id, short_title, color, start_date, organization_id')
if result.empty?
result = Conference
- .select('id, short_title, color, start_date').limit(2)
+ .select('id, short_title, color, start_date, organization_id').limit(2)
.order(start_date: :desc)
end
result
@@ -611,7 +611,7 @@ class Conference < ApplicationRecord
# ====Returns
# * +ActiveRecord+
def self.get_conferences_without_active_for_dashboard(active_conferences)
- result = Conference.select('id, short_title, color, start_date').order(start_date: :desc)
+ result = Conference.select('id, short_title, color, start_date, organization_id').order(start_date: :desc)
result - active_conferences
end
@@ -1029,7 +1029,7 @@ class Conference < ApplicationRecord
# * +hash+ -> object_type => {color, value}
def calculate_event_distribution(group_by_id, association_symbol, state = nil)
grouped = if state
- program.events.select(group_by_id).where('state = ?', 'confirmed').group(group_by_id)
+ program.events.select(group_by_id).where('state = ?', state).group(group_by_id)
else
program.events.select(group_by_id).group(group_by_id)
end
diff --git a/app/models/organization.rb b/app/models/organization.rb
index 21d0989b..1e3974de 100644
--- a/app/models/organization.rb
+++ b/app/models/organization.rb
@@ -7,7 +7,11 @@ class Organization < ApplicationRecord
after_create :create_roles
- validates :name, presence: true
+ validates :name,
+ uniqueness: {
+ case_sensitive: false
+ },
+ presence: true
mount_uploader :picture, PictureUploader, mount_on: :picture
diff --git a/app/models/registration.rb b/app/models/registration.rb
index 1198324e..45d2d55b 100644
--- a/app/models/registration.rb
+++ b/app/models/registration.rb
@@ -1,4 +1,5 @@
class Registration < ApplicationRecord
+ require 'csv'
belongs_to :user
belongs_to :conference
diff --git a/app/models/ticket.rb b/app/models/ticket.rb
index b49cf1b9..80e7f3e0 100644
--- a/app/models/ticket.rb
+++ b/app/models/ticket.rb
@@ -62,7 +62,11 @@ class Ticket < ApplicationRecord
def tickets_turnover_total(id)
tickets = TicketPurchase.where(ticket_id: id).paid
- tickets.inject(0){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) }
+ if tickets.blank?
+ Money.new(0, Ticket.find(id).price_currency)
+ else
+ tickets.inject(Money.new(0, tickets.first.price_currency)){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) }
+ end
end
def tickets_sold
diff --git a/app/views/admin/conferences/index.html.haml b/app/views/admin/conferences/index.html.haml
index 02208aeb..2fde1575 100644
--- a/app/views/admin/conferences/index.html.haml
+++ b/app/views/admin/conferences/index.html.haml
@@ -1,5 +1,5 @@
.row
- .col-sm-4.col-xs-4
+ .col-sm-3.col-xs-3
.dashbox.text-center
%span.fa.fa-user.fa-lg
%span.fa.fa-lg
@@ -11,7 +11,7 @@
%span.label.label-success{ title: "+ #{@new_user} since you last logged in!" }
+
= @new_user
- .col-sm-4.col-xs-4
+ .col-sm-3.col-xs-3
.dashbox.text-center
%span.fa.fa-check-square.fa-lg
%span.fa.fa-lg
@@ -23,7 +23,7 @@
%span.label.label-success{ title: "+#{@new_reg} since you last logged in!" }
+
= @new_reg
- .col-sm-4.col-xs-4
+ .col-sm-3.col-xs-3
.dashbox.text-center
%span.fa.fa-file-text.fa-lg
%span.fa.fa-lg
@@ -35,6 +35,18 @@
%span.label.label-success{ title: "+#{@new_submissions} since you last logged in!" }
+
= @new_submissions
+ .col-sm-3.col-xs-3
+ .dashbox.text-center
+ %span.fa.fa-archive.fa-lg
+ %span.fa.fa-lg
+ = @total_withdrawn
+ %p
+ %small
+ #{'Withdrawn'.pluralize(@total_withdrawn)}
+ - if @new_withdrawn
+ %span.label.label-success{ title: "+#{@new_withdrawn} since you last logged in!" }
+ +
+ = @new_withdrawn
.row#registrations
.col-md-8
diff --git a/app/views/admin/conferences/show.html.haml b/app/views/admin/conferences/show.html.haml
index cddae4c2..ca59d8d9 100644
--- a/app/views/admin/conferences/show.html.haml
+++ b/app/views/admin/conferences/show.html.haml
@@ -3,7 +3,7 @@
Dashboard for #{@conference.title}
%hr
.row
- .col-sm-4.col-xs-4
+ .col-sm-3.col-xs-3
.dashbox.text-center
%span.fa.fa-user.fa-lg
%span.fa.fa-lg
@@ -16,7 +16,7 @@
+
= @new_reg
- .col-sm-4.col-xs-4
+ .col-sm-3.col-xs-3
.dashbox.text-center
%span.fa.fa-check-square.fa-lg
%span.fa.fa-lg
@@ -29,7 +29,7 @@
+
= @new_submissions
- .col-sm-4.col-xs-4
+ .col-sm-3.col-xs-3
.dashbox.text-center
%span.fa.fa-file-text.fa-lg
%span.fa.fa-lg
@@ -42,6 +42,19 @@
+
= @new_program_length
+ .col-sm-3.col-xs-3
+ .dashbox.text-center
+ %span.fa.fa-archive.fa-lg
+ %span.fa.fa-lg
+ = @total_withdrawn
+ %p
+ %small
+ #{'Withdrawn'.pluralize(@total_withdrawn)}
+ - if @new_withdrawn
+ %span.label.label-success{ title: "+#{@new_withdrawn} since you last logged in!" }
+ +
+ = @new_withdrawn
+
.row
.col-md-12
.row
@@ -91,6 +104,10 @@
%a{ href: '#distribution_confirmed', 'data-toggle' => 'tab' }
%span.fa.fa-comment
Confirmed
+ %li
+ %a{ href: '#distribution_withdrawn', 'data-toggle' => 'tab' }
+ %span.fa.fa-archive
+ Withdrawn
.tab-content
.tab-pane.active#distribution_all
.row
@@ -108,6 +125,14 @@
= render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution_confirmed}
.col-md-4
= render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution_confirmed}
+ .tab-pane#distribution_withdrawn
+ .row
+ .col-md-4
+ = render partial: 'doughnut_chart', locals: {title: 'Event types', data: @event_type_distribution_withdrawn}
+ .col-md-4
+ = render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution_withdrawn}
+ .col-md-4
+ = render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution_withdrawn}
.row
.col-md-8
diff --git a/app/views/admin/organizations/index.html.haml b/app/views/admin/organizations/index.html.haml
index baf9bc80..7226d2a6 100644
--- a/app/views/admin/organizations/index.html.haml
+++ b/app/views/admin/organizations/index.html.haml
@@ -2,8 +2,9 @@
.col-md-12
.page-header
%h1 Organizations
- .btn-group.pull-right
- = link_to 'Create Organization', new_admin_organization_path, class: 'btn btn-success pull-right'
+ - if can? :manage, :all
+ .btn-group.pull-right
+ = link_to 'Create Organization', new_admin_organization_path, class: 'btn btn-success pull-right'
%p.text-muted
Manage organizations in OSEM
.row
diff --git a/app/views/admin/venues/show.html.haml b/app/views/admin/venues/show.html.haml
index b50c10da..36906e05 100644
--- a/app/views/admin/venues/show.html.haml
+++ b/app/views/admin/venues/show.html.haml
@@ -8,7 +8,7 @@
.row
.col-md-6
- if @conference.venue.location?
- = render '/conferences/venue_map'
+ = render '/conferences/venue_map', venue: @conference.venue
-else
- if @venue.commercial.nil?
.row
diff --git a/app/views/booths/show.html.haml b/app/views/booths/show.html.haml
index 6b12229d..f1790504 100644
--- a/app/views/booths/show.html.haml
+++ b/app/views/booths/show.html.haml
@@ -6,7 +6,7 @@
= image_tag(@booth.picture.thumb.url, size: '20%', alt: '')
= @booth.title
.btn-group.pull-right
- = link_to 'Edit', edit_admin_conference_booth_path(@conference.short_title, @booth), class: 'btn btn-mini btn-primary'
+ = link_to 'Edit', edit_conference_booth_path(@conference.short_title, @booth), class: 'btn btn-mini btn-primary'
.row
.col-md-12
diff --git a/app/views/conferences/_call_for_papers.haml b/app/views/conferences/_call_for_papers.haml
index 3bf0f295..b47d7118 100644
--- a/app/views/conferences/_call_for_papers.haml
+++ b/app/views/conferences/_call_for_papers.haml
@@ -23,5 +23,5 @@
left!
%p.cta-button
= link_to "Submit your proposal now",
- conference_program_proposals_path(conference_id),
+ new_conference_program_proposal_path(conference_id),
class: 'btn btn-success btn-lg text-center'
diff --git a/app/views/conferences/_call_for_tracks.haml b/app/views/conferences/_call_for_tracks.haml
index 7eb80fa6..6d78bd05 100644
--- a/app/views/conferences/_call_for_tracks.haml
+++ b/app/views/conferences/_call_for_tracks.haml
@@ -15,5 +15,5 @@
left!
%p.cta-button
= link_to("Submit your request for track",
- conference_program_tracks_path(conference_id),
+ new_conference_program_track_path(conference_id),
class: 'btn btn-success btn-lg text-center')
diff --git a/app/views/conferences/_social_media.haml b/app/views/conferences/_social_media.haml
index 32cf1b16..28a87dbc 100644
--- a/app/views/conferences/_social_media.haml
+++ b/app/views/conferences/_social_media.haml
@@ -15,6 +15,9 @@
- unless contact.googleplus.blank?
= link_to "#{ contact.googleplus }" do
%i.fa.fa-google-plus-square.fa-4x
+ - unless contact.mastodon.blank?
+ = link_to "#{ contact.mastodon }" do
+ %i.fa.icon-mastodon.fa-4x
- unless contact.email.blank?
= mail_to "#{ contact.email }" do
%i.fa.fa-envelope-o.fa-4x
diff --git a/app/views/conferences/_social_media.html.haml b/app/views/conferences/_social_media.html.haml
deleted file mode 100644
index 49216b6c..00000000
--- a/app/views/conferences/_social_media.html.haml
+++ /dev/null
@@ -1,21 +0,0 @@
-.container
- .row
- .col-md-12.text-center
- - unless @conference.contact.facebook.blank?
- = link_to "#{ @conference.contact.facebook }" do
- %i.fa.fa-facebook-square.fa-4x
- - unless @conference.contact.twitter.blank?
- = link_to "#{ @conference.contact.twitter }" do
- %i.fa.fa-twitter.fa-4x
- - unless @conference.contact.instagram.blank?
- = link_to "#{ @conference.contact.instagram }" do
- %i.fa.fa-instagram.fa-4x
- - unless @conference.contact.googleplus.blank?
- = link_to "#{ @conference.contact.googleplus }" do
- %i.fa.fa-google-plus-square.fa-4x
- - unless @conference.contact.mastodon.blank?
- = link_to "#{ @conference.contact.mastodon }" do
- %i.fa.icon-mastodon.fa-4x
- - unless @conference.contact.email.blank?
- = mail_to "#{ @conference.contact.email }" do
- %i.fa.fa-envelope-o.fa-4x
diff --git a/app/views/conferences/_sponsors.haml b/app/views/conferences/_sponsors.haml
index 8f4d55c6..5d7bbaa9 100644
--- a/app/views/conferences/_sponsors.haml
+++ b/app/views/conferences/_sponsors.haml
@@ -2,7 +2,7 @@
%li
%a.smoothscroll{ href: '#sponsors' } Sponsors
-- cache [conference, sponsorship_levels, '#splash#sponsors'] do
+- cache [conference, sponsors, sponsorship_levels, '#splash#sponsors'] do
%section#sponsors
.container
- sponsorship_levels.each do |sponsorship_level|
@@ -31,6 +31,6 @@
= link_to(sponsorship_mailto(conference)) do
Contact us!
-- sponsorship_levels.collect(&:sponsors).flatten.each do |sponsor|
+- sponsors.each do |sponsor|
- content_for :modals do
= render 'modal_description', object: sponsor
diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml
index ea99b419..246ccc35 100644
--- a/app/views/conferences/show.html.haml
+++ b/app/views/conferences/show.html.haml
@@ -43,7 +43,8 @@
-# sponsorship
- if @conference.splashpage.include_sponsors
= render 'sponsors', conference: @conference,
- sponsorship_levels: @sponsorship_levels
+ sponsorship_levels: @sponsorship_levels,
+ sponsors: @sponsors
-# footer
- if @conference.splashpage.include_social_media
diff --git a/app/views/devise/shared/_openid_links.html.haml b/app/views/devise/shared/_openid_links.html.haml
index 8bcc96da..09c7a7ea 100644
--- a/app/views/devise/shared/_openid_links.html.haml
+++ b/app/views/devise/shared/_openid_links.html.haml
@@ -1,5 +1,5 @@
.text-center
- .btn-group.btn-group-lg
+ .btn-group.btn-group-lg#openid-btn-grp
- omniauth_configured.each do |provider|
= link_to "user_#{provider}_omniauth_authorize".to_sym, class: "btn btn-success btn-lg",
id: "omniauth-#{provider}",
diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml
index aa155bcb..128f491a 100644
--- a/app/views/layouts/application.html.haml
+++ b/app/views/layouts/application.html.haml
@@ -37,11 +37,14 @@
%p.muted.text-center
%small
This tool is
- =link_to "free software,", "http://www.gnu.org/philosophy/free-sw.html"
+ #{link_to "free software", "http://www.gnu.org/philosophy/free-sw.html"},
released under the
- =link_to "MIT license.", "http://opensource.org/licenses/MIT"
+ #{link_to "MIT license", "http://opensource.org/licenses/MIT"}.
You can run, copy, distribute, study, change and improve it.
The source code and the developers are on
- =link_to "github.", "https://github.com/openSUSE/osem"
+ #{link_to "GitHub", "https://github.com/openSUSE/osem"}.
+ - if ENV["SKYLIGHT_PUBLIC_DASHBOARD_URL"].present?
+ Performance data is available on
+ #{link_to "Skylight", ENV["SKYLIGHT_PUBLIC_DASHBOARD_URL"]}.
= yield :script_body
= piwik_tracking_tag
diff --git a/config.ru b/config.ru
index 988dac89..a0123600 100644
--- a/config.ru
+++ b/config.ru
@@ -1,4 +1,5 @@
# This file is used by Rack-based servers to start the application.
require ::File.expand_path('../config/environment', __FILE__)
+use Rack::Deflater
run Osem::Application
diff --git a/config/application.rb b/config/application.rb
index 4e3844ad..7e5e3a5d 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -60,6 +60,9 @@ module Osem
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
+ # Set cache headers
+ config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=31536000' }
+
config.active_job.queue_adapter = :delayed_job
end
end
diff --git a/config/environments/production.rb b/config/environments/production.rb
index 11a8c06b..2a9bf1f8 100644
--- a/config/environments/production.rb
+++ b/config/environments/production.rb
@@ -25,6 +25,10 @@ Osem::Application.configure do
# Generate digests for assets URLs
config.assets.digest = true
+ config.assets.css_compressor = :sass
+ config.assets.js_compressor = :uglifier
+ config.assets.gzip = true
+
# Defaults to nil and saved in location specified by config.assets.prefix
# config.assets.manifest = YOUR_PATH
diff --git a/db/schema.rb b/db/schema.rb
index ed33d5a3..48815a8a 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -496,7 +496,7 @@ ActiveRecord::Schema.define(version: 20171201163628) do
t.integer "user_id"
t.integer "payment_id"
t.integer "week"
- t.float "amount_paid"
+ t.float "amount_paid", default: 0.0
end
create_table "ticket_scannings", force: :cascade do |t|
diff --git a/docker-compose.env.example b/docker-compose.env.example
index 905ff612..7bda181b 100644
--- a/docker-compose.env.example
+++ b/docker-compose.env.example
@@ -34,7 +34,7 @@ SECRET_KEY_BASE=changemechangemechangeme"
OSEM_EMAIL_ADDRESS="osem@mailhog"
OSEM_SMTP_AUTHENTICATION="login"
OSEM_SMTP_ADDRESS="mailhog"
-OSEM_SMTP_PORT="1025"
+OSEM_SMTP_PORT=1025
OSEM_SMTP_USERNAME="mailhog"
OSEM_SMTP_PASSWORD="mailhog"
diff --git a/dotenv.example b/dotenv.example
index e0e3f519..6d8dd025 100644
--- a/dotenv.example
+++ b/dotenv.example
@@ -46,6 +46,10 @@ OSEM_SUSE_SECRET=''
STRIPE_PUBLISHABLE_KEY=''
STRIPE_SECRET_KEY=''
+# (OPTIONAL) Skylight keys. See https://www.skylight.io/oss.
+# SKYLIGHT_AUTHENTICATION=''
+# SKYLIGHT_PUBLIC_DASHBOARD_URL='https://oss.skylight.io/app/applications/xxxxxxxxxxxx'
+
# Disable linting of factories in the test suite.
# Speeds up turn around times of tests
OSEM_FACTORY_LINT="false"
diff --git a/spec/controllers/admin/conferences_controller_spec.rb b/spec/controllers/admin/conferences_controller_spec.rb
index ff9d676b..984ef137 100644
--- a/spec/controllers/admin/conferences_controller_spec.rb
+++ b/spec/controllers/admin/conferences_controller_spec.rb
@@ -95,6 +95,75 @@ describe Admin::ConferencesController do
get :show, id: conference.short_title
expect(response).to render_template :show
end
+
+ it 'assigns conference withdrawn events distribution to event_type_distribution_withdrawn' do
+ conference
+ create(:event, program: conference.program)
+ workshop = create(:event_type, title: 'Workshop', color: '#000000', program: conference.program)
+ lecture = create(:event_type, title: 'Lecture', color: '#ffffff', program: conference.program)
+ get :show, id: conference.short_title
+ expect(assigns(:event_type_distribution_withdrawn)).to be_empty
+ create(:event, program: conference.program, state: 'withdrawn', event_type: lecture)
+ create(:event, program: conference.program, state: 'withdrawn', event_type: workshop)
+ get :show, id: conference.short_title
+ expect(assigns(:event_type_distribution_withdrawn)).not_to be_empty
+ result = {}
+ result['Workshop'] = {
+ 'value' => 1,
+ 'color' => '#000000'
+ }
+ result['Lecture'] = {
+ 'value' => 1,
+ 'color' => '#FFFFFF'
+ }
+ expect(assigns(:event_type_distribution_withdrawn)).to eq(result)
+ end
+
+ it 'assigns conference withdrawn difficulty level distribution to difficulty_levels_distribution_withdrawn' do
+ conference
+ create(:event, program: conference.program)
+ get :show, id: conference.short_title
+ expect(assigns(:difficulty_levels_distribution_withdrawn)).to be_empty
+ easy = create(:difficulty_level, title: 'Easy', color: '#000000')
+ hard = create(:difficulty_level, title: 'Hard', color: '#ffffff')
+ create(:event, program: conference.program, state: 'withdrawn', difficulty_level: easy)
+ create(:event, program: conference.program, state: 'withdrawn', difficulty_level: hard)
+ get :show, id: conference.short_title
+ expect(assigns(:difficulty_levels_distribution_withdrawn)).not_to be_empty
+ result = {}
+ result['Easy'] = {
+ 'value' => 1,
+ 'color' => '#000000'
+ }
+ result['Hard'] = {
+ 'value' => 1,
+ 'color' => '#FFFFFF'
+ }
+ expect(assigns(:difficulty_levels_distribution_withdrawn)).to eq(result)
+ end
+
+ it 'assigns conference withdrawn track distribution to tracks_distribution_withdrawn' do
+ conference
+ create(:event, program: conference.program)
+ get :show, id: conference.short_title
+ expect(assigns(:tracks_distribution_withdrawn)).to be_empty
+ track_one = create(:track, name: 'Track One', color: '#000000', program: conference.program)
+ track_two = create(:track, name: 'Track Two', color: '#FFFFFF', program: conference.program)
+ create(:event, program: conference.program, state: 'withdrawn', track: track_one)
+ create(:event, program: conference.program, state: 'withdrawn', track: track_two)
+ get :show, id: conference.short_title
+ expect(assigns(:tracks_distribution_withdrawn)).not_to be_empty
+ result = {}
+ result['Track One'] = {
+ 'value' => 1,
+ 'color' => '#000000'
+ }
+ result['Track Two'] = {
+ 'value' => 1,
+ 'color' => '#FFFFFF'
+ }
+ expect(assigns(:tracks_distribution_withdrawn)).to eq(result)
+ end
end
describe 'GET #index' do
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 214e522a..4d1c2eab 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -30,7 +30,45 @@ describe ApplicationController, type: :controller do
expect(controller.after_sign_in_path_for(user)).to eq conferences_path
end
end
-
+ end
+
+ end
+
+end
+
+describe ApplicationController, type: :request do
+ let(:conference) { create(:conference) }
+
+ describe 'Skylight link' do
+
+ around do |example|
+ original_value = ENV['SKYLIGHT_PUBLIC_DASHBOARD_URL']
+ example.run
+ ENV['SKYLIGHT_PUBLIC_DASHBOARD_URL'] = original_value
+ end
+
+ context 'when SKYLIGHT_PUBLIC_DASHBOARD_URL is set' do
+ before do
+ ENV['SKYLIGHT_PUBLIC_DASHBOARD_URL'] = 'https://oss.skylight.io/app/applications/my-osem'
+ end
+
+ it 'should include a link to view performance data' do
+ get '/'
+ expect(response.body).to match(/Performance data/i)
+ expect(response.body).to include('https://oss.skylight.io/app/applications/my-osem')
+ end
+ end
+
+ context 'when SKYLIGHT_PUBLIC_DASHBOARD_URL is not set' do
+ before do
+ ENV['SKYLIGHT_PUBLIC_DASHBOARD_URL'] = nil
+ end
+
+ it 'should not include a link to view performance data' do
+ get '/'
+ expect(response.body).to_not match(/performance data/i)
+ expect(response.body).to_not match(/skylight/i)
+ end
end
end
diff --git a/spec/factories/organizations.rb b/spec/factories/organizations.rb
index 0ee76554..f6331873 100644
--- a/spec/factories/organizations.rb
+++ b/spec/factories/organizations.rb
@@ -1,6 +1,6 @@
FactoryGirl.define do
factory :organization do
- name { Faker::Company.name }
+ sequence(:name) { |n| "#{Faker::Company.name} #{n}" }
description { Faker::Lorem.paragraph }
# after(:create) do |organization|
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index 7936ddbb..26522913 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -89,11 +89,131 @@ describe 'User' do
let(:other_self_organized_track) { create(:track, :self_organized) }
it{ should be_able_to(:manage, user) }
-
it{ should be_able_to(:manage, registration_public) }
it{ should be_able_to(:manage, registration_not_public) }
- it{ should_not be_able_to(:new, Registration.new(conference_id: conference_with_closed_registration.id))}
- it{ should_not be_able_to(:create, Registration.new(conference_id: conference_with_closed_registration.id))}
+
+ # Test for user can register or not
+ context 'when user is not a speaker with event confirmed' do
+ let(:conference) { create(:conference) }
+
+ context 'when the registration is closed' do
+ before :each do
+ create(:registration_period, conference: conference, start_date: Date.current - 6.days, end_date: Date.current - 6.days)
+ end
+
+ it{ should_not be_able_to(:new, Registration.new(conference: conference)) }
+ it{ should_not be_able_to(:create, Registration.new(conference: conference)) }
+ end
+
+ context 'when the registration period is not set' do
+ it{ should_not be_able_to(:new, Registration.new(conference: conference)) }
+ it{ should_not be_able_to(:create, Registration.new(conference: conference)) }
+ end
+
+ context 'when user has already registered' do
+ before :each do
+ create(:registration, conference: conference, user: user)
+ end
+
+ it{ should_not be_able_to(:new, Registration.new(conference: conference)) }
+ it{ should_not be_able_to(:create, Registration.new(conference: conference)) }
+ end
+
+ context 'when registrations are open' do
+ before :each do
+ create(:registration_period, conference: conference)
+ end
+
+ it{ should be_able_to(:new, Registration.new(conference: conference)) }
+ it{ should be_able_to(:create, Registration.new(conference: conference)) }
+
+ context 'when user has not registered with no registration_limit_exceeded' do
+ before :each do
+ conference.registration_limit = 1
+ end
+
+ it{ should be_able_to(:new, Registration.new(conference: conference)) }
+ it{ should be_able_to(:create, Registration.new(conference: conference)) }
+ end
+
+ context 'when user has not registered with registration_limit_exceeded' do
+ before :each do
+ conference.registration_limit = 1
+ create(:registration, conference: conference, user: user2)
+ end
+
+ it{ should_not be_able_to(:new, Registration.new(conference: conference)) }
+ it{ should_not be_able_to(:create, Registration.new(conference: conference)) }
+ end
+ end
+ end
+
+ context 'when user is a speaker with event confirmed' do
+ let(:conference_with_speaker_confirmed) { create(:conference) }
+ let(:event_with_speaker_confirmed) { create(:event, state: 'confirmed', program: conference_with_speaker_confirmed.program) }
+
+ before :each do
+ event_with_speaker_confirmed.speakers << user
+ end
+
+ context 'when registration period is not set' do
+ it{ should_not be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) }
+ it{ should_not be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) }
+ end
+
+ context 'when speaker has already registered' do
+ before :each do
+ create(:registration, conference: conference_with_speaker_confirmed, user: user)
+ end
+
+ it{ should_not be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) }
+ it{ should_not be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) }
+ end
+
+ context 'when registration period is set' do
+ before :each do
+ create(:registration_period, conference: conference_with_speaker_confirmed)
+ end
+
+ context 'when registrations are open' do
+ context 'when speaker has not registered' do
+ it{ should be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) }
+ it{ should be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) }
+ end
+
+ context 'when registration_limit_exceeded' do
+ before :each do
+ conference_with_speaker_confirmed.registration_limit = 1
+ create(:registration, conference: conference_with_speaker_confirmed, user: user2)
+ end
+
+ it{ should be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) }
+ it{ should be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) }
+ end
+ end
+
+ context 'when registrations are closed' do
+ before :each do
+ create(:registration_period, conference: conference_with_speaker_confirmed, start_date: Date.current - 6.days, end_date: Date.current - 6.days)
+ end
+
+ context 'when speaker has not registered' do
+ it{ should be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) }
+ it{ should be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) }
+ end
+
+ context 'with registration_limit_exceeded' do
+ before :each do
+ conference_with_speaker_confirmed.registration_limit = 1
+ create(:registration, conference: conference_with_speaker_confirmed, user: user2)
+ end
+
+ it{ should be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) }
+ it{ should be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) }
+ end
+ end
+ end
+ end
it{ should be_able_to(:index, Ticket) }
it{ should be_able_to(:manage, TicketPurchase.new(user_id: user.id)) }
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 704b8e08..60e07602 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -63,7 +63,12 @@ RSpec.configure do |config|
Capybara.javascript_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
- Capybara::Poltergeist::Driver.new(app, phantomjs: Phantomjs.path, js_errors: false, window_size: [1920, 1080])
+ Capybara::Poltergeist::Driver.new(
+ app,
+ phantomjs: Phantomjs.path,
+ js_errors: false,
+ window_size: [1920, 1080]
+ )
end
# Includes helpers and connect them to specific types of tests
diff --git a/spec/support/external_request.rb b/spec/support/external_request.rb
index d09ebc0a..ed7da3d3 100644
--- a/spec/support/external_request.rb
+++ b/spec/support/external_request.rb
@@ -11,9 +11,9 @@ end
def mock_commercial_request
response = {
author_name: 'Confreaks',
- html: '',
+ html: '',
thumbnail_width: 480,
- thumbnail_url: 'https://i.ytimg.com/vi/BTTygyxuGj8/hqdefault.jpg',
+ thumbnail_url: '/images/rails.png',
provider_name: 'YouTube',
width: 459,
type: 'video',