diff --git a/.codecov.yml b/.codecov.yml index db247200..9c6a4c0d 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1 +1,6 @@ +coverage: + status: + project: + default: + threshold: 0.5% comment: off diff --git a/.travis.yml b/.travis.yml index a94c68ef..b35784c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,8 @@ -language: ruby -cache: bundler -rvm: - - 2.6.6 +os: linux dist: bionic -addons: - apt: - packages: - - chromium-browser -services: - - postgresql branches: except: - /^depfu/.*$/ -before_install: - - "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" - - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true - - gem install bundler -v $(tail -n 1 Gemfile.lock) notifications: email: on_success: change @@ -25,22 +12,9 @@ notifications: - "chat.freenode.net#osem" on_success: change on_failure: change -before_script: - # install CodeClimate test reporter and tell it we are starting a test run - # - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > $CCTR - # - chmod +x $CCTR - # - $CCTR before-build - - RAILS_ENV=test bundle exec rake db:bootstrap --trace - - RAILS_ENV=test bundle exec bin/rails webdrivers:chromedriver:update -script: - - "bin/travis_script.sh $TEST_SUITE" - # TODO Get this working. - # - $CCTR format-coverage -t simplecov --output coverage/codeclimate.$SUITE.json -# after_script: - # combine coverage from all suites, and upload3 to CodeClimate - # - $CCTR sum-coverage coverage/codeclimate.*.json | $CCTR upload-coverage - # - $CCTR after-build --exit-code $TRAVIS_TEST_RESULT - +stages: + - test + - finalize env: global: - OSEM_DB_ADAPTER=sqlite3 @@ -49,11 +23,90 @@ env: - OSEM_DB_NAME='osem_test' - CC_TEST_REPORTER_ID=$CC_TEST_REPORTER - CCTR=./cc-test-reporter - matrix: - - TEST_SUITE=ability - - TEST_SUITE=features - - TEST_SUITE=models - - TEST_SUITE=controllers - - TEST_SUITE=rest -matrix: - fast_finish: false + - TOTAL_TEST_SUITES=5 +jobs: + include: + - &tests + language: ruby + cache: bundler + rvm: + - 2.6.6 + addons: + apt: + packages: + - chromium-browser + services: + - postgresql + before_install: + - "echo 'gem: --no-ri --no-rdoc' > ~/.gemrc" + - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true + - gem install bundler -v $(tail -n 1 Gemfile.lock) + - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > $CCTR + - chmod +x $CCTR + before_script: + - RAILS_ENV=test bundle exec rake db:bootstrap --trace + - RAILS_ENV=test bundle exec bin/rails webdrivers:chromedriver:update + - $CCTR before-build + script: + - "bin/travis_script.sh $TEST_SUITE && $CCTR format-coverage -t cobertura -o ./coverage/codeclimate.1.json ./coverage/coverage.xml" + env: + - TEST_SUITE=ability + workspaces: + create: + name: ws1 + paths: + - coverage/codeclimate.1.json + - <<: *tests + env: + - TEST_SUITE=features + script: + - "bin/travis_script.sh $TEST_SUITE && $CCTR format-coverage -t cobertura -o ./coverage/codeclimate.2.json ./coverage/coverage.xml" + workspaces: + create: + name: ws2 + paths: + - coverage/codeclimate.2.json + - <<: *tests + env: + - TEST_SUITE=models + script: + - "bin/travis_script.sh $TEST_SUITE && $CCTR format-coverage -t cobertura -o ./coverage/codeclimate.3.json ./coverage/coverage.xml" + workspaces: + create: + name: ws3 + paths: + - coverage/codeclimate.3.json + - <<: *tests + env: + - TEST_SUITE=controllers + script: + - "bin/travis_script.sh $TEST_SUITE && $CCTR format-coverage -t cobertura -o ./coverage/codeclimate.4.json ./coverage/coverage.xml" + workspaces: + create: + name: ws4 + paths: + - coverage/codeclimate.4.json + - <<: *tests + env: + - TEST_SUITE=rest + script: + - "bin/travis_script.sh $TEST_SUITE && $CCTR format-coverage -t cobertura -o ./coverage/codeclimate.5.json ./coverage/coverage.xml" + workspaces: + create: + name: ws5 + paths: + - coverage/codeclimate.5.json + - stage: finalize + if: branch = master + language: minimal + before_install: + - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > $CCTR + - chmod +x $CCTR + workspaces: + use: + - ws1 + - ws2 + - ws3 + - ws4 + - ws5 + script: $CCTR sum-coverage --output - --parts $TOTAL_TEST_SUITES coverage/codeclimate.*.json | $CCTR upload-coverage --input - diff --git a/Gemfile b/Gemfile index 226932f5..87a01972 100644 --- a/Gemfile +++ b/Gemfile @@ -266,7 +266,7 @@ group :test do gem 'pdf-inspector', require: "pdf/inspector" end -group :development, :test do +group :development, :test, :linters do # as debugger gem 'byebug' gem 'pry' @@ -280,6 +280,9 @@ group :development, :test do gem 'rubocop-rspec', require: false gem 'haml-lint', require: false +end + +group :development, :test do # as development/test database gem 'sqlite3' end diff --git a/Gemfile.lock b/Gemfile.lock index c59eb26c..d5815b3f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -127,6 +127,8 @@ GEM aws_cf_signer rest-client cocoon (1.2.15) + codecov (0.5.0) + simplecov (>= 0.15, < 0.22) coderay (1.1.1) concurrent-ruby (1.1.8) countable-rails (0.0.1) diff --git a/README.md b/README.md index 71f3ac37..1a549b45 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ### Spring 2021 Student Project [![Build Status](https://travis-ci.com/CactusPuppy/snapcon.svg?branch=master)](https://travis-ci.com/CactusPuppy/snapcon) [![Maintainability](https://api.codeclimate.com/v1/badges/6c7fc446b3b10866ba71/maintainability)](https://codeclimate.com/github/CactusPuppy/snapcon/maintainability) -[![codecov](https://codecov.io/gh/CactusPuppy/snapcon/branch/master/graph/badge.svg?token=y4aEAtw6KJ)](https://codecov.io/gh/CactusPuppy/snapcon) +[![Test Coverage](https://api.codeclimate.com/v1/badges/6c7fc446b3b10866ba71/test_coverage)](https://codeclimate.com/github/CactusPuppy/snapcon/test_coverage) [![Security Status](https://hakiri.io/github/CactusPuppy/snapcon/master.svg)](https://hakiri.io/github/CactusPuppy/snapcon/master) [![Depfu](https://badges.depfu.com/badges/16eb1ffb3a9f1a36c4e595a5ae2a1dca/overview.svg)](https://depfu.com/github/CactusPuppy/snapcon?project_id=22682) [![Bluejay Dashboard](https://img.shields.io/badge/Bluejay-Dashboard_5-blue.svg)](http://dashboard.bluejay.governify.io/dashboard/script/dashboardLoader.js?dashboardURL=https://reporter.bluejay.governify.io/api/v4/dashboards/tpa-CS169L-GH-CactusPuppy_snapcon/main) diff --git a/app/assets/javascripts/osem.js b/app/assets/javascripts/osem.js index 0839f13b..636ed959 100644 --- a/app/assets/javascripts/osem.js +++ b/app/assets/javascripts/osem.js @@ -147,6 +147,15 @@ function word_count(text, divId, maxcount) { }); }; +function fill_if_empty(text_area, filler) { + let area = $('#' + text_area); + + if (!area.val()) { + area.val(filler); + area.trigger('change'); + } +} + /* Wait for the DOM to be ready before attaching events to the elements */ $( document ).ready(function() { /* Set the minimum and maximum proposal abstract and submission text word length */ @@ -155,15 +164,15 @@ $( document ).ready(function() { var max = $selected.data("max-words"); var min = $selected.data("min-words"); + // Set the filler text for the submission text + fill_if_empty('event_submission_text', $selected.data("help")); + $("#abstract-maximum-word-count").text(max); $("#submission-maximum-word-count").text(max); $("#abstract-minimum-word-count").text(min); $("#submission-minimum-word-count").text(min); word_count($('#event_abstract').get(0), 'abstract-count', max); word_count($('#event_submission_text').get(0), 'submission-count', max); - - // Set the placeholder text for the abstract - $('#event_submission_text').attr("placeholder", $selected.data("help")); }) .trigger('change'); @@ -180,6 +189,18 @@ $( document ).ready(function() { var max = $selected.data("max-words"); word_count(this, 'submission-count', max); }); + + /* Listen for reset template button, wait for confirm, and reset. */ + $('#sub_text_reset').click((e) => { + let $selected = $("#event_event_type_id option:selected"); + let $this = $(e.target); + let affirm = confirm($this.data('confirm')); + if (affirm) { + let sub_text = $('#event_submission_text'); + sub_text.val($selected.data('help')); + sub_text.trigger('change'); + } + }); }); /* Commodity function for modal windows */ diff --git a/app/assets/stylesheets/mailbot.css b/app/assets/stylesheets/mailbot.css new file mode 100644 index 00000000..870eb7ef --- /dev/null +++ b/app/assets/stylesheets/mailbot.css @@ -0,0 +1,40 @@ +html { + scroll-behavior: smooth; + } + + body { + background: #fff; + box-shadow: 0 0 2px rgba(0, 0, 0, 0.06); + color: #000; + font-family: 'Montserrat', sans-serif; + font-size: 16px; + line-height: 1.5; + margin: 0 auto; + } + + h1, + h3, + h4, + h5, + h6 { + font-weight: 400; + line-height: 1.3; + } + p { + color: #0B3559; + font-weight: 400; + line-height: 2; + } + + #border { + background-color: #0B3559; + padding: 25px; + color:#fff; + } + + #content { + background-color: #fff; + padding: 100px; + color: #0B3559; + } + \ No newline at end of file diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb index 5dae6d19..ffbfec15 100644 --- a/app/controllers/payments_controller.rb +++ b/app/controllers/payments_controller.rb @@ -16,6 +16,7 @@ class PaymentsController < ApplicationController raise CanCan::AccessDenied.new('Nothing to pay for!', :new, Payment) end + @has_registration_ticket = params[:has_registration_ticket] @unpaid_ticket_purchases = current_user.ticket_purchases.unpaid.by_conference(@conference) end @@ -24,8 +25,15 @@ class PaymentsController < ApplicationController if @payment.purchase && @payment.save update_purchased_ticket_purchases - redirect_to conference_physical_tickets_path, - notice: 'Thanks! Your ticket is booked successfully.' + + has_registration_ticket = params[:has_registration_ticket] + if has_registration_ticket == 'true' + redirect_to new_conference_conference_registration_path(@conference.short_title), + notice: 'Thanks! Your ticket is booked successfully. Please register for the conference.' + else + redirect_to conference_physical_tickets_path, + notice: 'Thanks! Your ticket is booked successfully.' + end else @total_amount_to_pay = Ticket.total_price(@conference, current_user, paid: false) @unpaid_ticket_purchases = current_user.ticket_purchases.unpaid.by_conference(@conference) diff --git a/app/controllers/ticket_purchases_controller.rb b/app/controllers/ticket_purchases_controller.rb index 1a1bc449..3034d742 100644 --- a/app/controllers/ticket_purchases_controller.rb +++ b/app/controllers/ticket_purchases_controller.rb @@ -8,23 +8,42 @@ class TicketPurchasesController < ApplicationController def create current_user.ticket_purchases.by_conference(@conference).unpaid.destroy_all + + # Create a ticket purchase which can be paid or unpaid + count_registration_tickets_before = current_user.count_registration_tickets(@conference) message = TicketPurchase.purchase(@conference, current_user, params[:tickets].try(:first)) - if message.blank? - if current_user.ticket_purchases.by_conference(@conference).unpaid.any? - redirect_to new_conference_payment_path, - notice: 'Please pay here to get tickets.' - elsif current_user.ticket_purchases.by_conference(@conference).paid.any? - redirect_to conference_physical_tickets_path, - notice: 'You already have tickets for the conference.' - elsif @conference.tickets.for_registration.any? - redirect_to conference_tickets_path(@conference.short_title), - error: 'Please get at least one ticket to continue.' - else - redirect_to conference_conference_registration_path(@conference.short_title) - end - else + # The new ticket_purchase has been added to the database. current_user.ticket_purchases contains the new one. + count_registration_tickets_after = current_user.count_registration_tickets(@conference) + + # Failed to create ticket purchase + unless message.blank? redirect_to conference_tickets_path(@conference.short_title), error: "Oops, something went wrong with your purchase! #{message}" + return + end + + # Current user already paid for a registration ticket and the current ticket purchase contains one + if count_registration_tickets_before == 1 && count_registration_tickets_after > 1 + redirect_to conference_physical_tickets_path, + error: 'You already have one registration ticket for the conference.' + return + end + + # User needs to pay for tickets if any of them is not free. + if current_user.ticket_purchases.by_conference(@conference).unpaid.any? + has_registration_ticket = count_registration_tickets_before.zero? && count_registration_tickets_after == 1 + redirect_to new_conference_payment_path(has_registration_ticket: has_registration_ticket), + notice: 'Please pay here to get tickets.' + return + end + + # Redirect to registration page for a user who didn't have a registration ticket and is purchasing one + if count_registration_tickets_before.zero? && count_registration_tickets_after == 1 + redirect_to new_conference_conference_registration_path(@conference.short_title), + notice: 'Thanks! Your ticket is booked successfully. Please register for the conference.' + else + redirect_to conference_physical_tickets_path, + notice: 'Thanks! Your ticket is booked successfully.' end end diff --git a/app/helpers/conference_helper.rb b/app/helpers/conference_helper.rb index 14253b23..417a8d55 100644 --- a/app/helpers/conference_helper.rb +++ b/app/helpers/conference_helper.rb @@ -1,5 +1,8 @@ # frozen_string_literal: true +DEFAULT_LOGO = 'snapcon_logo.png' +DEFAULT_COLOR = '#0B3559' + module ConferenceHelper # Return true if only call_for_papers or call_for_tracks or call_for_booths is open def one_call_open(*calls) @@ -28,6 +31,24 @@ module ConferenceHelper markdown(ticket.description.split("\n").first&.strip) end + def conference_logo_url(conference) + if conference.picture.present? + conference.picture.thumb.url + elsif conference.organization.picture.present? + conference.organization.picture.thumb.url + else + DEFAULT_LOGO + end + end + + def conference_color(conference) + if conference.color.present? + conference.color + else + DEFAULT_COLOR + end + end + # adds events to icalendar for proposals in a conference def icalendar_proposals(calendar, proposals, conference) proposals.each do |proposal| diff --git a/app/mailers/mailbot.rb b/app/mailers/mailbot.rb index c055ec84..07249862 100644 --- a/app/mailers/mailbot.rb +++ b/app/mailers/mailbot.rb @@ -5,21 +5,25 @@ EMAIL_TEMPLATE = 'email_template' YTLF_TICKET_ID = 50 class Mailbot < ActionMailer::Base - def registration_mail(conference, user) - @email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.registration_body) - @logo = conference.picture.thumb.url + helper ConferenceHelper - mail(to: user.email, - bcc: SNAPCON_BCC_ADDRESS, - from: conference.contact.email, - subject: conference.email_settings.registration_subject, - template_name: EMAIL_TEMPLATE) + default bcc: -> { SNAPCON_BCC_ADDRESS }, + template_name: -> { EMAIL_TEMPLATE }, + to: -> { @user.email }, + from: -> { @conference.contact.email } + + def registration_mail(conference, user) + @user = user + @conference = conference + @email_body = @conference.email_settings.generate_email_on_conf_updates(@conference, @user, @conference.email_settings.registration_body) + + mail(subject: @conference.email_settings.registration_subject) end def ticket_confirmation_mail(ticket_purchase) @ticket_purchase = ticket_purchase - @conference = ticket_purchase.conference @user = ticket_purchase.user + @conference = ticket_purchase.conference PhysicalTicket.last(ticket_purchase.quantity).each do |physical_ticket| pdf = TicketPdf.new(@conference, @user, physical_ticket, @conference.ticket_layout.to_sym, "ticket_for_#{@conference.short_title}_#{physical_ticket.id}") @@ -31,138 +35,100 @@ class Mailbot < ActionMailer::Base template_name = 'young_thinkers_ticket_confirmation_template' end - mail(to: @user.email, - bcc: SNAPCON_BCC_ADDRESS, - from: @conference.contact.email, - template_name: template_name, - subject: "#{@conference.title} | Ticket Confirmation and PDF!") + mail(subject: "#{@conference.title} | Ticket Confirmation and PDF!", + template_name: template_name) end def acceptance_mail(event) - conference = event.program.conference + @user = event.submitter + @conference = event.program.conference + @email_body = @conference.email_settings.generate_event_mail(event, @conference.email_settings.accepted_body) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_event_mail(event, conference.email_settings.accepted_body) - - mail(to: event.submitter.email, - bcc: SNAPCON_BCC_ADDRESS, - from: conference.contact.email, - subject: conference.email_settings.accepted_subject, - template_name: EMAIL_TEMPLATE) + mail(subject: @conference.email_settings.accepted_subject) end def submitted_proposal_mail(event) - conference = event.program.conference + @user = event.submitter + @conference = event.program.conference + @email_body = @conference.email_settings.generate_event_mail(event, @conference.email_settings.submitted_proposal_body) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_event_mail(event, conference.email_settings.submitted_proposal_body) - - mail(to: event.submitter.email, - bcc: SNAPCON_BCC_ADDRESS, - from: conference.contact.email, - subject: conference.email_settings.submitted_proposal_subject, - template_name: EMAIL_TEMPLATE) + mail(subject: @conference.email_settings.submitted_proposal_subject) end def rejection_mail(event) - conference = event.program.conference + @user = event.submitter + @conference = event.program.conference + @email_body = @conference.email_settings.generate_event_mail(event, @conference.email_settings.rejected_body) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_event_mail(event, conference.email_settings.rejected_body) - - mail(to: event.submitter.email, - bcc: SNAPCON_BCC_ADDRESS, - from: conference.contact.email, - subject: conference.email_settings.rejected_subject, - template_name: EMAIL_TEMPLATE) + mail(subject: @conference.email_settings.rejected_subject) end def confirm_reminder_mail(event) - conference = event.program.conference + @user = event.submitter + @conference = event.program.conference + @email_body = @conference.email_settings.generate_event_mail(event, @conference.email_settings.confirmed_without_registration_body) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_event_mail(event, conference.email_settings.confirmed_without_registration_body) - - mail(to: event.submitter.email, - bcc: SNAPCON_BCC_ADDRESS, - from: conference.contact.email, - subject: conference.email_settings.confirmed_without_registration_subject, - template_name: EMAIL_TEMPLATE) + mail(subject: @conference.email_settings.confirmed_without_registration_subject) end def conference_date_update_mail(conference, user) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.conference_dates_updated_body) + @user = user + @conference = conference + @email_body = @conference.email_settings.generate_email_on_conf_updates(@conference, @user, @conference.email_settings.conference_dates_updated_body) - mail(to: user.email, - bcc: SNAPCON_BCC_ADDRESS, - from: conference.contact.email, - subject: conference.email_settings.conference_dates_updated_subject, - template_name: EMAIL_TEMPLATE) + mail(subject: @conference.email_settings.conference_dates_updated_subject) end def conference_registration_date_update_mail(conference, user) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.conference_registration_dates_updated_body) + @user = user + @conference = conference + @email_body = @conference.email_settings.generate_email_on_conf_updates(@conference, @user, @conference.email_settings.conference_registration_dates_updated_body) - mail(to: user.email, - bcc: SNAPCON_BCC_ADDRESS, - from: conference.contact.email, - subject: conference.email_settings.conference_registration_dates_updated_subject, - template_name: EMAIL_TEMPLATE) + mail(subject: @conference.email_settings.conference_registration_dates_updated_subject) end def conference_venue_update_mail(conference, user) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.venue_updated_body) + @user = user + @conference = conference + @email_body = @conference.email_settings.generate_email_on_conf_updates(@conference, @user, @conference.email_settings.venue_updated_body) - mail(to: user.email, - bcc: SNAPCON_BCC_ADDRESS, - from: conference.contact.email, - subject: conference.email_settings.venue_updated_subject, - template_name: EMAIL_TEMPLATE) + mail(subject: @conference.email_settings.venue_updated_subject) end def conference_schedule_update_mail(conference, user) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.program_schedule_public_body) + @user = user + @conference = conference + @email_body = @conference.email_settings.generate_email_on_conf_updates(@conference, @user, @conference.email_settings.program_schedule_public_body) - mail(to: user.email, - from: conference.contact.email, - subject: conference.email_settings.program_schedule_public_subject, - template_name: EMAIL_TEMPLATE) + mail(bcc: nil, + subject: @conference.email_settings.program_schedule_public_subject) end def conference_cfp_update_mail(conference, user) - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.cfp_dates_updated_body) + @user = user + @conference = conference + @email_body = @conference.email_settings.generate_email_on_conf_updates(@conference, @user, @conference.email_settings.cfp_dates_updated_body) - mail(to: user.email, - from: conference.contact.email, - subject: conference.email_settings.cfp_dates_updated_subject, - template_name: EMAIL_TEMPLATE) + mail(bcc: nil, + subject: @conference.email_settings.cfp_dates_updated_subject) end def conference_booths_acceptance_mail(booth) - conference = booth.conference - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_booth_mail(booth, conference.email_settings.booths_acceptance_body) + @user = booth.submitter + @conference = booth.conference + @email_body = @conference.email_settings.generate_booth_mail(booth, @conference.email_settings.booths_acceptance_body) - mail(to: booth.submitter.email, - from: conference.contact.email, - subject: conference.email_settings.booths_acceptance_subject, - template_name: EMAIL_TEMPLATE) + mail(bcc: nil, + subject: @conference.email_settings.booths_acceptance_subject) end def conference_booths_rejection_mail(booth) - conference = booth.conference - @logo = conference.picture.thumb.url - @email_body = conference.email_settings.generate_booth_mail(booth, conference.email_settings.booths_rejection_body) + @user = booth.submitter + @conference = booth.conference + @email_body = @conference.email_settings.generate_booth_mail(booth, @conference.email_settings.booths_rejection_body) - mail(to: booth.submitter.email, - from: conference.contact.email, - subject: conference.email_settings.booths_rejection_subject, - template_name: EMAIL_TEMPLATE) + mail(bcc: nil, + subject: @conference.email_settings.booths_rejection_subject) end def event_comment_mail(comment, user) @@ -171,8 +137,7 @@ class Mailbot < ActionMailer::Base @conference = @event.program.conference @user = user - mail(to: @user.email, - from: @conference.contact.email, + mail(bcc: nil, template_name: 'comment_template', subject: "New comment has been posted for #{@event.title}") end diff --git a/app/models/event.rb b/app/models/event.rb index d10ae1a1..ba04ba20 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -7,7 +7,6 @@ # id :bigint not null, primary key # abstract :text # comments_count :integer default(0), not null -# committee_review :text # description :text # guid :string not null # is_highlight :boolean default(FALSE) diff --git a/app/models/user.rb b/app/models/user.rb index 9bd1bf80..955c76d1 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -346,6 +346,17 @@ class User < ApplicationRecord events.where(program_id: conference.program.id, 'event_users.event_role': 'volunteer') end + def count_registration_tickets(conference) + count = 0 + ticket_purchases.by_conference(conference).each do |ticket_purchase| + if ticket_purchase.ticket.registration_ticket + count += 1 + end + end + + count + end + def self.empty? User.count == 1 && User.first.email == 'deleted@localhost.osem' end diff --git a/app/serializers/event_serializer.rb b/app/serializers/event_serializer.rb index 9bf196f2..8c30b1a1 100644 --- a/app/serializers/event_serializer.rb +++ b/app/serializers/event_serializer.rb @@ -7,7 +7,6 @@ # id :bigint not null, primary key # abstract :text # comments_count :integer default(0), not null -# committee_review :text # description :text # guid :string not null # is_highlight :boolean default(FALSE) diff --git a/app/views/admin/conferences/show.html.haml b/app/views/admin/conferences/show.html.haml index eaf6a031..b1b07f2c 100644 --- a/app/views/admin/conferences/show.html.haml +++ b/app/views/admin/conferences/show.html.haml @@ -57,6 +57,33 @@ .col-md-4 = render 'donut_chart', title: 'Event types', combined_data: @event_type_distribution + .col-md-4 + -# + = render 'donut_chart', title: 'Difficulty levels', + combined_data: @difficulty_levels_distribution + .col-md-4 + -# + = render 'donut_chart', title: 'Tracks', + combined_data: @tracks_distribution + .tab-pane#distribution_confirmed + .row + .col-md-4 + -# + = render 'donut_chart', title: 'Event types', + combined_data: @event_type_distribution_confirmed + .col-md-4 + -# + = render 'donut_chart', title: 'Difficulty levels', + combined_data: @difficulty_levels_distribution_confirmed + .col-md-4 + -# + = render 'donut_chart', title: 'Tracks', + combined_data: @tracks_distribution_confirmed + .tab-pane#distribution_withdrawn + .row + .col-md-4 + = render 'donut_chart', title: 'Event types', + combined_data: @event_type_distribution_withdrawn .col-md-4 = render 'donut_chart', title: 'Difficulty levels', combined_data: @difficulty_levels_distribution diff --git a/app/views/conference_registrations/_event.html.haml b/app/views/conference_registrations/_event.html.haml index 1a8a3d96..dd389f66 100644 --- a/app/views/conference_registrations/_event.html.haml +++ b/app/views/conference_registrations/_event.html.haml @@ -1,9 +1,9 @@ -.panel.panel-default{c lass: ("panel-success" if event.registrations.include?(@registration)) } +.panel.panel-default{ class: ('panel-success' if event.registrations.include?(registration)) } .panel-heading %label{ for: "registration_event_ids_#{event.id}" } %h3{ style: 'margin: 0 auto;' } = hidden_field_tag 'registration[event_ids][]', nil - = check_box_tag 'registration[event_ids][]', event.id, event.registrations.include?(@registration), id: "registration_event_ids_#{event.id}" + = check_box_tag 'registration[event_ids][]', event.id, event.registrations.include?(registration), id: "registration_event_ids_#{event.id}" = event.title %small = event.subtitle @@ -13,9 +13,10 @@ (Scheduled on: #{event.time.to_date}) .panel-body - %p - = canceled_replacement_event_label(event, event_schedule) - = replacement_event_notice(event_schedule) + -# + %p + = canceled_replacement_event_label(event, event_schedule) + = replacement_event_notice(event_schedule) %p - if event.speakers.any? presented by #{event.speaker_names} @@ -29,10 +30,10 @@ %p = markdown(truncate(event.abstract, length: 250)) -# TODO: More informative text or aria-label. - = link_to 'more', conference_program_proposal_path(@conference.short_title, event.id), target: '_blank' + = link_to 'more', conference_program_proposal_path(conference.short_title, event.id), target: '_blank' - if event.track %span.track %span.fa.fa-road - %span.label{ style: "background-color: #{event.track.color}; color: #{ contrast_color(event.track.color) }" } + %span.label{ style: "background-color: #{event.track.color}; color: #{contrast_color(event.track.color)}" } = event.track.name diff --git a/app/views/conference_registrations/_registration_info.html.haml b/app/views/conference_registrations/_registration_info.html.haml index e8968298..45d6f9fe 100644 --- a/app/views/conference_registrations/_registration_info.html.haml +++ b/app/views/conference_registrations/_registration_info.html.haml @@ -18,6 +18,6 @@ You are registered for #{pluralize(@registration.events.count, 'event')}. They are at the end of this list. - @registration.events_ordered.each do |event| - = render 'conference_registrations/event', event: event, event_schedule: event.event_schedules.first + = render 'conference_registrations/event', event: event, event_schedule: event.event_schedules.first, conference: @conference, registration: @registration = render 'conferences/code_of_conduct', organization: @conference.organization diff --git a/app/views/conferences/_footer.haml b/app/views/conferences/_footer.haml index 6b66478a..0ef3fa56 100644 --- a/app/views/conferences/_footer.haml +++ b/app/views/conferences/_footer.haml @@ -1,14 +1,15 @@ --# .scroll-top-wrapper --# = link_to "#banner", class: "smoothscroll" do --# %i.fa.fa-2x.fa-arrow-circle-up +-# + scroll-top-wrapper + = link_to "#banner", class: "smoothscroll" do + %i.fa.fa-2x.fa-arrow-circle-up --# :javascript --# $(function(){ --# $(document).on( 'scroll', function(){ --# if ($(window).scrollTop() > 100) { --# $('.scroll-top-wrapper').addClass('show'); --# } else { --# $('.scroll-top-wrapper').removeClass('show'); --# } --# }); --# }); + :javascript + $(function(){ + $(document).on( 'scroll', function(){ + if ($(window).scrollTop() > 100) { + $('.scroll-top-wrapper').addClass('show'); + } else { + $('.scroll-top-wrapper').removeClass('show'); + } + }); + }); diff --git a/app/views/conferences/_header.haml b/app/views/conferences/_header.haml index fad8648c..f40fe600 100644 --- a/app/views/conferences/_header.haml +++ b/app/views/conferences/_header.haml @@ -2,13 +2,14 @@ #banner{ style: ("background-image: url(#{conference.picture_url})" if conference.picture_url) } .container .row - .col-md-6.col-md-offset-3{id: (conference.picture? ? "header-image" : "header-no-image")} + .col-md-6.col-md-offset-3{ id: (conference.picture? ? "header-image" : "header-no-image") } .row - -# - if conference.picture? - -# .col-md-4 - -# = image_tag(conference.picture_url, - -# class: 'img-responsive img-center', - -# id: 'splash-logo') + -# + - if conference.picture? + .col-md-4 + = image_tag(conference.picture_url, + class: 'img-responsive img-center', + id: 'splash-logo') .col-md-8 %h1 = conference.title.html_safe diff --git a/app/views/conferences/_program.haml b/app/views/conferences/_program.haml index 18d8a540..de07b475 100644 --- a/app/views/conferences/_program.haml +++ b/app/views/conferences/_program.haml @@ -2,7 +2,7 @@ %li %a.smoothscroll{ href: '#program' } Program %li - = link_to('Schedule', events_conference_schedule_path(@conference)) + = link_to('Schedule', events_conference_schedule_path(conference)) - cache [conference, highlights, tracks, booths, '#splash#program'] do %section#program diff --git a/app/views/conferences/_sponsors.haml b/app/views/conferences/_sponsors.haml index 0bd5edb0..ab9e3638 100644 --- a/app/views/conferences/_sponsors.haml +++ b/app/views/conferences/_sponsors.haml @@ -27,7 +27,7 @@ .row .col-md-12 %h3.text-center - = "Interested in sponsoring #{conference.title}?" + Interested in sponsoring #{conference.title}? = link_to(sponsorship_mailto(conference)) do Please, contact us! .trapezoid diff --git a/app/views/conferences/_tickets.haml b/app/views/conferences/_tickets.haml index b28f705e..940dc1ca 100644 --- a/app/views/conferences/_tickets.haml +++ b/app/views/conferences/_tickets.haml @@ -22,6 +22,6 @@ .word_break = short_ticket_description(ticket) %button.btn-block.btn.btn-lg.btn-success - %i.fa.fa-ticket.fa-fw{"aria-hidden": true} + %i.fa.fa-ticket.fa-fw{ "aria-hidden": true } = humanized_money_with_symbol(ticket.price) .trapezoid diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml index f498bf97..c34aa3c1 100644 --- a/app/views/conferences/show.html.haml +++ b/app/views/conferences/show.html.haml @@ -20,24 +20,22 @@ - if @unpaid_tickets .row .col-md-12 - .alert.alert-dismissable.alert-info.text-center#unpaid-tickets{role: 'alert'} - %button.button.close{"data-dismiss" => "alert", "aria-label"=>"close"} + .alert.alert-dismissable.alert-info.text-center#unpaid-tickets{ role: 'alert' } + %button.button.close{ "data-dismiss" => "alert", "aria-label"=>"close" } × %p You have unpaid tickets. Please complete your purchase. = link_to('Purchase Tickets', new_conference_payment_path(@conference), class: 'btn btn-success btn-lg') - - if @user_needs_to_register .row - .col-md-12 - .alert.alert-dismissable.alert-warning.text-center#flash{role: 'alert'} - %button.button.close{"data-dismiss" => "alert", 'aria-label': 'close'} - × - %p - You still need to complete your registration for #{@conference.title}. - = link_to('Complete Registration', new_conference_conference_registration_path(@conference), class: 'btn btn-success btn-lg') - + .col-md-12 + .alert.alert-dismissable.alert-warning.text-center#flash{ role: 'alert' } + %button.button.close{ "data-dismiss" => "alert", 'aria-label': 'close' } + × + %p + You still need to complete your registration for #{@conference.title}. + = link_to('Complete Registration', new_conference_conference_registration_path(@conference), class: 'btn btn-success btn-lg') #splash - if @conference.code_of_conduct.present? @@ -79,29 +77,8 @@ sponsorship_levels: @sponsorship_levels, sponsors: @sponsors - -# footer - if @conference.splashpage.include_social_media - if @conference.contact.has_social_media? = render 'social_media', contact: @conference.contact = render 'footer' - - --# - content_for :script_head do --# :javascript --# var triangle_tcs = tinycolor("#{h(@conference.color)}").monochromatic(); --# var triangle_colors = triangle_tcs.map(function(t) { --# return t.toHexString(); --# }); --# $(function () { --# $(document).ready(function() { --# var triangle_width = document.body.clientWidth; --# var triangle_height = ($( "#banner" ).height() + 200 ); --# var pattern = Trianglify({ width: triangle_width, --# height: triangle_height, --# cell_size: 100, --# x_colors: triangle_colors --# }); --# $('#banner').css('background-image', 'url(' + 0 + ')'); --# }); --# }); diff --git a/app/views/layouts/_mailbot_footer.html.erb b/app/views/layouts/_mailbot_footer.html.erb new file mode 100644 index 00000000..3cc8b3c3 --- /dev/null +++ b/app/views/layouts/_mailbot_footer.html.erb @@ -0,0 +1,12 @@ + + + + + + + <%= stylesheet_link_tag "mailbot" %> + + +
+ + \ No newline at end of file diff --git a/app/views/layouts/_mailbot_header.html.erb b/app/views/layouts/_mailbot_header.html.erb new file mode 100644 index 00000000..12f9d4a5 --- /dev/null +++ b/app/views/layouts/_mailbot_header.html.erb @@ -0,0 +1,25 @@ + + + + + + <%= 'Email' %> + + + + <%= stylesheet_link_tag "mailbot" %> + + +
+
+
+ <% if @conference.present? %> + <%= image_tag(conference_logo_url(@conference), style: "display:block;height:70px;width:auto;", alt: @conference.title + ' logo') %> + <% end %> +
+
+
+ + + + \ No newline at end of file diff --git a/app/views/layouts/_navigation.html.haml b/app/views/layouts/_navigation.html.haml index fb1ddeff..8215f5ce 100644 --- a/app/views/layouts/_navigation.html.haml +++ b/app/views/layouts/_navigation.html.haml @@ -51,37 +51,38 @@ = link_to(sign_in_path) do %span.fa.fa-user Sign In - -# %li.dropdown.visible-desktop - -# %a.dropdown-toggle{"data-toggle" => "dropdown", href: '#'} - -# %span.fa.fa-user - -# Sign In - -# %span.caret - -# .dropdown-menu - -# - if ENV['OSEM_ICHAIN_ENABLED'] == 'true' - -# = form_tag User.ichain_login_url do - -# = text_field_tag 'username', nil, id: 'user_ichain_email_dd', class: 'form-control', placeholder: 'Username' - -# = password_field_tag 'password', nil, id: 'user_ichain_password_dd', class: 'form-control', placeholder: 'Password' - -# %button.btn.btn-success.btn-block Sign in - -# - else - -# %div{style: "padding: 6px"} - -# = form_tag new_user_session_path, class: 'form-group' do - -# = text_field_tag 'user[login]', nil, id: 'user_login_dd', class: 'form-control', placeholder: 'Username / E-Mail' - -# = password_field_tag 'user[password]', nil, id: 'user_password_dd', class: 'form-control', placeholder: 'Password' - -# %p.text-right - -# %small - -# %label{for: 'user_remember_me'} Remember me - -# = check_box_tag 'user[remember_me]' - -# %br - -# %button.btn.btn-success.btn-block Sign in - -# - unless omniauth_configured.empty? - -# .divider - -# %h6.text-center - -# or - -# = render 'devise/shared/openid_links' - -# %p.text-right - -# %br - -# %a.small.btn.btn-xs.btn-default{"data-toggle" => "collapse", "data-target" => "#navbar-devise-help"} - -# Need Help? - -# #navbar-devise-help.collapse - -# = render 'devise/shared/links' + -# + %li.dropdown.visible-desktop + %a.dropdown-toggle{"data-toggle" => "dropdown", href: '#'} + %span.fa.fa-user + Sign In + %span.caret + .dropdown-menu + - if ENV['OSEM_ICHAIN_ENABLED'] == 'true' + = form_tag User.ichain_login_url do + = text_field_tag 'username', nil, id: 'user_ichain_email_dd', class: 'form-control', placeholder: 'Username' + = password_field_tag 'password', nil, id: 'user_ichain_password_dd', class: 'form-control', placeholder: 'Password' + %button.btn.btn-success.btn-block Sign in + - else + %div{style: "padding: 6px"} + = form_tag new_user_session_path, class: 'form-group' do + = text_field_tag 'user[login]', nil, id: 'user_login_dd', class: 'form-control', placeholder: 'Username / E-Mail' + = password_field_tag 'user[password]', nil, id: 'user_password_dd', class: 'form-control', placeholder: 'Password' + %p.text-right + %small + %label{for: 'user_remember_me'} Remember me + = check_box_tag 'user[remember_me]' + %br + %button.btn.btn-success.btn-block Sign in + - unless omniauth_configured.empty? + .divider + %h6.text-center + or + = render 'devise/shared/openid_links' + %p.text-right + %br + %a.small.btn.btn-xs.btn-default{"data-toggle" => "collapse", "data-target" => "#navbar-devise-help"} + Need Help? + #navbar-devise-help.collapse + = render 'devise/shared/links' .trapezoid diff --git a/app/views/mailbot/comment_template.html.erb b/app/views/mailbot/comment_template.html.erb new file mode 100644 index 00000000..b9e9cce0 --- /dev/null +++ b/app/views/mailbot/comment_template.html.erb @@ -0,0 +1,16 @@ +<%= render partial: "layouts/mailbot_header" %> +
+ + Dear <%= @user.name %>, + + User <%= @comment.user.name %> posted a new comment for event <%= @event.title %> of <%= @conference.short_title %> . + + "<%= @comment.body %>" + + To reply to this comment, please go to <%= h(admin_conference_program_event_url(@conference.short_title, @event, only_path: false)) %> + + Best wishes, + <%= @conference.title %> Team + +
+<%= render partial: "layouts/mailbot_footer" %> \ No newline at end of file diff --git a/app/views/mailbot/comment_template.text.erb b/app/views/mailbot/comment_template.text.erb deleted file mode 100644 index d162d710..00000000 --- a/app/views/mailbot/comment_template.text.erb +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - Email - - -
-
- -
-
-

-
-
-
- - Dear <%= @user.name %>, - - User <%= @comment.user.name %> posted a new comment for event <%= @event.title %> of <%= @conference.short_title %> . - - "<%= @comment.body %>" - - To reply to this comment, please go to <%= h(admin_conference_program_event_url(@conference.short_title, @event, only_path: false)) %> - - Best wishes, - <%= @conference.title %> Team - -
-
-

-
- - diff --git a/app/views/mailbot/email_template.erb b/app/views/mailbot/email_template.erb deleted file mode 100644 index 429553be..00000000 --- a/app/views/mailbot/email_template.erb +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - Email - - -
-
- -
- <% if !@logo.nil? %> - <%= image_tag(@logo, style: "display:block") %> - <% end %> -
-

-
-
-
- - <%= @email_body %> - -
-
-

-
- - diff --git a/app/views/mailbot/email_template.html.erb b/app/views/mailbot/email_template.html.erb new file mode 100644 index 00000000..6176cf08 --- /dev/null +++ b/app/views/mailbot/email_template.html.erb @@ -0,0 +1,7 @@ +<%= render partial: "layouts/mailbot_header" %> +
+ + <%= @email_body %> + +
+<%= render partial: "layouts/mailbot_footer" %> \ No newline at end of file diff --git a/app/views/mailbot/ticket_confirmation_template.html.erb b/app/views/mailbot/ticket_confirmation_template.html.erb new file mode 100644 index 00000000..f92284d7 --- /dev/null +++ b/app/views/mailbot/ticket_confirmation_template.html.erb @@ -0,0 +1,14 @@ +<%= render partial: "layouts/mailbot_header" %> +
+ + Dear <%= @user.name %>, + + Thanks! You have successfully booked <%= @ticket_purchase.quantity %> <%= @ticket_purchase.ticket.title %> ticket(s) for the event <%= @conference.title %>. Your transaction id is <%= @ticket_purchase.id %>. + + Please, find the ticket(s) pdf attached. + + Best wishes, + <%= @conference.title %> Team + +
+<%= render partial: "layouts/mailbot_footer" %> \ No newline at end of file diff --git a/app/views/mailbot/ticket_confirmation_template.text.erb b/app/views/mailbot/ticket_confirmation_template.text.erb deleted file mode 100644 index 0e4e54f8..00000000 --- a/app/views/mailbot/ticket_confirmation_template.text.erb +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - Email - - -
-
- -
-
-

-
-
-
- - Dear <%= @user.name %>, - - Thanks! You have successfully booked <%= @ticket_purchase.quantity %> <%= @ticket_purchase.ticket.title %> ticket(s) for the event <%= @conference.title %>. Your transaction id is <%= @ticket_purchase.id %>. - - Please, find the ticket(s) pdf attached. - - Best wishes, - <%= @conference.title %> Team - -
-
-

-
- - diff --git a/app/views/mailbot/young_thinkers_ticket_confirmation_template.html.erb b/app/views/mailbot/young_thinkers_ticket_confirmation_template.html.erb new file mode 100644 index 00000000..d35d8a1f --- /dev/null +++ b/app/views/mailbot/young_thinkers_ticket_confirmation_template.html.erb @@ -0,0 +1,16 @@ +<%= render partial: "layouts/mailbot_header" %> +
+ + Dear <%= @user.name %>, + + Thanks! You have successfully booked <%= @ticket_purchase.quantity %> <%= @ticket_purchase.ticket.title %> ticket(s) for the event <%= @conference.title %>. Your transaction id is <%= @ticket_purchase.id %>. + + Please, find the ticket(s) pdf attached. + + The SAP Young Thinkers team will reach out to you with information on how to participate in the event soon. In the meantime, you can check the event page (https://events.sap.com/yt-learning-festival-at-snapcon-2020/en/home) or send an email with your questions to youngthinkers@sap.com. + + Best wishes, + <%= @conference.title %> Team + +
+<%= render partial: "layouts/mailbot_footer" %> \ No newline at end of file diff --git a/app/views/mailbot/young_thinkers_ticket_confirmation_template.text.erb b/app/views/mailbot/young_thinkers_ticket_confirmation_template.text.erb deleted file mode 100644 index 6a4c7fb5..00000000 --- a/app/views/mailbot/young_thinkers_ticket_confirmation_template.text.erb +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - Email - - -
-
- -
-
-

-
-
-
- - Dear <%= @user.name %>, - - Thanks! You have successfully booked <%= @ticket_purchase.quantity %> <%= @ticket_purchase.ticket.title %> ticket(s) for the event <%= @conference.title %>. Your transaction id is <%= @ticket_purchase.id %>. - - Please, find the ticket(s) pdf attached. - - The SAP Young Thinkers team will reach out to you with information on how to participate in the event soon. In the meantime, you can check the event page (https://events.sap.com/yt-learning-festival-at-snapcon-2020/en/home) or send an email with your questions to youngthinkers@sap.com. - - Best wishes, - <%= @conference.title %> Team - -
-
-

-
- - diff --git a/app/views/payments/_payment.html.haml b/app/views/payments/_payment.html.haml index 440f9985..bd70d8e8 100644 --- a/app/views/payments/_payment.html.haml +++ b/app/views/payments/_payment.html.haml @@ -19,7 +19,7 @@ %td = humanized_money_with_symbol ticket.quantity * ticket.price -= form_tag conference_payments_path do += form_tag conference_payments_path(@conference.short_title, :has_registration_ticket => @has_registration_ticket) do %script.stripe-button{'src': "https://checkout.stripe.com/checkout.js", 'data': {amount: @total_amount_to_pay.cents, label: "Pay #{humanized_money_with_symbol @total_amount_to_pay}", diff --git a/app/views/physical_tickets/index.html.haml b/app/views/physical_tickets/index.html.haml index f05215d7..e89ceeab 100644 --- a/app/views/physical_tickets/index.html.haml +++ b/app/views/physical_tickets/index.html.haml @@ -12,7 +12,7 @@ -# TODO: And if they have a registration ticket? - if !@conference.user_registered?(@user) && @has_registration_ticket .col-md-12 - .alert.alert-success{role: 'alert'} + .alert.alert-success{ role: 'alert' } = link_to 'Complete Registration', new_conference_conference_registration_path(@conference), class: 'btn btn-info pull-right btn-lg' diff --git a/app/views/proposals/_encouragement_text.html.haml b/app/views/proposals/_encouragement_text.html.haml index 5c4ccb73..9b28088c 100644 --- a/app/views/proposals/_encouragement_text.html.haml +++ b/app/views/proposals/_encouragement_text.html.haml @@ -16,7 +16,7 @@ That means you have %b.notranslate= pluralize(@program.cfp.remaining_days, 'day') left! - %span.notranslate #{@conference.title} + %span.notranslate= @conference.title will only be as good as the content you present. Submit early, submit often! - else The submission period is closed now. diff --git a/app/views/proposals/_proposal_form.html.haml b/app/views/proposals/_proposal_form.html.haml index 423a7fba..5f907d6a 100644 --- a/app/views/proposals/_proposal_form.html.haml +++ b/app/views/proposals/_proposal_form.html.haml @@ -56,6 +56,7 @@ = f.input :submission_text, input_html: { rows: 5, data: { provide: 'markdown' }, placeholder: '' }, hint: markdown_hint('Only conference organizers will read this.') + %button.btn.btn-primary.primary-button{ type: 'button', id: 'sub_text_reset', data: { confirm: 'Do you really want to reset your submission text to the provided template?' } } Reset to Template %p You have used diff --git a/app/views/proposals/_speaker_info.haml b/app/views/proposals/_speaker_info.haml index d757d9b4..552ff6ed 100644 --- a/app/views/proposals/_speaker_info.haml +++ b/app/views/proposals/_speaker_info.haml @@ -1,13 +1,13 @@ .speakerinfo .row .col-md-4 - = image_tag speaker.profile_picture(:size => 120), class: 'img-responsive img-rounded' + = image_tag speaker.profile_picture(size: 120), class: 'img-responsive img-rounded' .col-md-8 %h4 = link_to speaker.name, user_path(speaker.id) %br - if speaker.email_public? - = mail_to "#{ speaker.email }" do + = mail_to speaker.email.to_s do %i.fa.fa-envelope-o.fa-2x - if speaker.affiliation? .text-muted diff --git a/app/views/proposals/_volunteer_info.haml b/app/views/proposals/_volunteer_info.haml index f5e3e21b..ae63c327 100644 --- a/app/views/proposals/_volunteer_info.haml +++ b/app/views/proposals/_volunteer_info.haml @@ -1,7 +1,7 @@ .speakerinfo .row .col-md-4 - = image_tag speaker.profile_picture(:size => 120), class: 'img-responsive img-rounded' + = image_tag speaker.profile_picture(size: 120), class: 'img-responsive img-rounded' .col-md-8 %h4 = link_to speaker.name, user_path(speaker.id) diff --git a/app/views/proposals/_volunteers_table.haml b/app/views/proposals/_volunteers_table.haml index df99ce53..c842c1de 100644 --- a/app/views/proposals/_volunteers_table.haml +++ b/app/views/proposals/_volunteers_table.haml @@ -1,8 +1,8 @@ %table.table.table-striped#events - events.each do |event| %tr - %td.col-md-7{style: "padding:20px 8px 20px 8px;"} - = link_to event.title, conference_program_proposal_path(@conference.short_title, event.id) + %td.col-md-7{ style: 'padding:20px 8px 20px 8px;' } + = link_to event.title, conference_program_proposal_path(conference.short_title, event.id) %br %small.text-muted = event.event_type.title @@ -10,10 +10,11 @@ = "in #{event.track.name}" if event.track - if event.require_registration %br - = link_to registered_text(event), registrations_conference_program_proposal_path(@conference.short_title, event), class: 'btn btn-xs btn-danger' + = link_to registered_text(event), registrations_conference_program_proposal_path(conference.short_title, event), + class: 'btn btn-xs btn-danger' - %td.col-md-2{style: "padding:20px 8px 20px 8px;"} - - event_schedule = event.event_schedules.find_by(schedule_id: @program.selected_schedule_id) + %td.col-md-2{ style: 'padding:20px 8px 20px 8px;' } + - event_schedule = event.event_schedules.find_by(schedule_id: program.selected_schedule_id) - if event_schedule.present? - = inyourtz(event_schedule.start_time, @conference.timezone) do - = event_schedule.start_time.strftime("%Y %B %e - %H:%M") + = inyourtz(event_schedule.start_time, conference.timezone) do + = event_schedule.start_time.strftime('%Y %B %e - %H:%M') diff --git a/app/views/proposals/index.html.haml b/app/views/proposals/index.html.haml index 6785af29..2cc41860 100644 --- a/app/views/proposals/index.html.haml +++ b/app/views/proposals/index.html.haml @@ -121,7 +121,7 @@ Volunteer Duties %small Thanks for being a host at #{@conference.title} - = render 'volunteers_table', events: @volunteer_events + = render 'volunteers_table', events: @volunteer_events, conference: @conference, program: @program .row .col-md-12 diff --git a/app/views/proposals/new.html.haml b/app/views/proposals/new.html.haml index 5c581e5b..9c9a7004 100644 --- a/app/views/proposals/new.html.haml +++ b/app/views/proposals/new.html.haml @@ -33,7 +33,7 @@ = f.input :title, as: :string, required: true, input_html: { required: true } = f.input :event_type_id, as: :select, collection: @program.event_types.map {|type| ["#{type.title} - #{show_time(type.length)}", type.id, - data: { min_words: type.minimum_abstract_length, max_words: type.maximum_abstract_length }]}, + data: { min_words: type.minimum_abstract_length, max_words: type.maximum_abstract_length, help: type.description }]}, include_blank: false, label: 'Type', input_html: { class: 'select-help-toggle' } - if @program.languages.present? @@ -76,6 +76,8 @@ = f.input :submission_text, input_html: { rows: 5, data: { provide: 'markdown' } }, hint: markdown_hint + %button.btn.btn-primary.primary-button{ type: 'button', id: 'sub_text_reset', data: { confirm: 'Do you really want to reset your submission text to the provided template?' } } Reset to Template + - if @program.cfp.enable_registrations? = f.input :require_registration, label: 'Require participants to register to your event' diff --git a/app/views/schedules/_event.html.haml b/app/views/schedules/_event.html.haml index 25257c0d..dbd16b10 100644 --- a/app/views/schedules/_event.html.haml +++ b/app/views/schedules/_event.html.haml @@ -1,20 +1,20 @@ -.panel.panel-default.event-panel{ onClick: 'eventClicked(event, this);', "data-url" => "#{url_for(conference_program_proposal_path(@conference.short_title, event.id))}" } +.panel.panel-default.event-panel{ onClick: 'eventClicked(event, this);', 'data-url' => "#{url_for(conference_program_proposal_path(@conference.short_title, event.id))}" } - header_color = event.event_type&.color || '#f5f5f5' - .trapezoid{style: "color: white; top: 12px; z-index: 100;"} + .trapezoid{ style: 'color: white; top: 12px; z-index: 100;' } .panel-heading{ style: "background-color: #{header_color}; color: #{ contrast_color(header_color) }; border-radius: 4px" } - event.speakers_ordered.each do |speaker| - = image_tag speaker.profile_picture, class: "img-circle pull-right", alt: speaker.name, style: "padding: 2px;" + = image_tag speaker.profile_picture, class: 'img-circle pull-right', alt: speaker.name, style: 'padding: 2px;' %p = canceled_replacement_event_label(event, event_schedule) = replacement_event_notice(event_schedule) - %span.h3{style: "margin-bottom: 14px"} + %span.h3{ style: 'margin-bottom: 14px' } = event.title %br - %small{style: "color: #{contrast_color(header_color)}"} + %small{ style: "color: #{contrast_color(header_color)}" } = event.subtitle - .trapezoid{style: "color: #{header_color}; top: 12px;"} + .trapezoid{ style: "color: #{header_color}; top: 12px;" } .panel-body %h4 @@ -30,13 +30,13 @@ = inyourtz(event_schedule.start_time) do %span.track %span.fa.fa-clock-o - %span.label{ style: "background-color: grey" } + %span.label{ style: 'background-color: grey' } = event_schedule.start_time.strftime('%l:%M %P') \- = event_schedule.end_time.strftime('%l:%M %P') %span.track %span.fa.fa-map-marker - %span.label{ style: "background-color: grey" } + %span.label{ style: 'background-color: grey' } = event_schedule.room.name - if event.track %span.track diff --git a/app/views/schedules/happening_now.haml b/app/views/schedules/happening_now.haml index 0c64470d..6649529a 100644 --- a/app/views/schedules/happening_now.haml +++ b/app/views/schedules/happening_now.haml @@ -22,12 +22,15 @@ - unless event_schedule.start_time.strftime('%Y-%m-%d').eql?(date) .col-xs-12.col-md-12 .date-content - %span{ class: 'date-title', id: event_schedule.start_time.strftime('%Y-%m-%d') } + %span.date-title{ id: event_schedule.start_time.strftime('%Y-%m-%d').to_s } = inyourtz(event_schedule.start_time, @conference.timezone) do = date = event_schedule.start_time.strftime('%Y-%m-%d') - %a{ title: 'Go up', class: 'pull-right', href: '#program' } + %a.pull-right{ title: 'Go up', href: '#program' } %i.fa.fa-angle-double-up.fa-lg{ 'aria-hidden': true } - - if !event_schedule.start_time.strftime('%H:%M').eql?(time) + - if event_schedule.start_time.strftime('%H:%M').eql?(time) + .col-xs-12.col-md-11.col-md-offset-1 + = render 'event', event: event_schedule.event, event_schedule: event_schedule + - else .col-xs-12.col-md-1 .start-time = inyourtz(event_schedule.start_time, @conference.timezone) do @@ -35,10 +38,6 @@ .col-xs-12.col-md-11 .new-time-event = render 'event', event: event_schedule.event, event_schedule: event_schedule - - else - -# TODO: Add comment describing this condition. - .col-xs-12.col-md-11.col-md-offset-1 - = render 'event', event: event_schedule.event, event_schedule: event_schedule :javascript // Refresh the page every 5 minutes. diff --git a/bin/travis_script.sh b/bin/travis_script.sh index 3f4f52cf..dfcbfcac 100755 --- a/bin/travis_script.sh +++ b/bin/travis_script.sh @@ -12,23 +12,23 @@ else fi case $TEST_SUITE in - linters) + linters|all) bundle exec rubocop -Dc .rubocop.yml bundle exec haml-lint app/views - ;; - models) + ;;& + models|all) bundle exec rspec --format documentation spec/models - ;; - features) + ;;& + features|all) bundle exec rspec --format documentation spec/features - ;; - controllers) + ;;& + controllers|all) bundle exec rspec --format documentation spec/controllers - ;; - ability) + ;;& + ability|all) bundle exec rspec --format documentation spec/ability - ;; - rest) + ;;& + rest|all) bundle exec rspec --format documentation --exclude-pattern "spec/{models,features,controllers,ability}/**/*_spec.rb" ;; esac diff --git a/config/environments/development.rb b/config/environments/development.rb index d99d92f0..5b6263e3 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -113,5 +113,7 @@ Osem::Application.configure do devise_config.ichain_test_mode = true end end + + config.assets.precompile += ['mailbot.css'] config.active_record.verbose_query_logs = true end diff --git a/config/environments/production.rb b/config/environments/production.rb index 536a8aef..d41774af 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -26,7 +26,7 @@ Osem::Application.configure do config.assets.digest = true config.assets.css_compressor = :sass - config.assets.js_compressor = :uglifier + config.assets.js_compressor = Uglifier.new(harmony: true) config.assets.gzip = true # Defaults to nil and saved in location specified by config.assets.prefix diff --git a/config/environments/test.rb b/config/environments/test.rb index 225ae26f..1a9d4d7b 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -52,4 +52,5 @@ Osem::Application.configure do ActiveSupport::Deprecation.silenced = true end + config.assets.precompile += ['mailbot.css'] end diff --git a/spec/factories/conferences.rb b/spec/factories/conferences.rb index d1ac5032..1968e54e 100644 --- a/spec/factories/conferences.rb +++ b/spec/factories/conferences.rb @@ -49,6 +49,7 @@ FactoryBot.define do ticket_layout { 'portrait' } description { Faker::Hipster.paragraph } organization + color { '#FFFFFF' } after(:create) do |conference| Role.where(name: 'organizer', resource: conference).first_or_create(description: 'For the organizers of the conference (who shall have full access)') Role.where(name: 'cfp', resource: conference).first_or_create(description: 'For the members of the CfP team') diff --git a/spec/factories/events.rb b/spec/factories/events.rb index 2f68c311..c8360449 100644 --- a/spec/factories/events.rb +++ b/spec/factories/events.rb @@ -7,7 +7,6 @@ # id :bigint not null, primary key # abstract :text # comments_count :integer default(0), not null -# committee_review :text # description :text # guid :string not null # is_highlight :boolean default(FALSE) diff --git a/spec/features/proposals_spec.rb b/spec/features/proposals_spec.rb index 482282a2..18297d2d 100644 --- a/spec/features/proposals_spec.rb +++ b/spec/features/proposals_spec.rb @@ -191,5 +191,24 @@ feature Event do @event.reload expect(@event.state).to eq('withdrawn') end + + scenario 'can reset to text template', feature: true, js: true do + event_type = conference.program.event_types[-1] + event_type.description = 'Example event description' + event_type.save! + + sign_in participant + visit new_conference_program_proposal_path(conference.short_title) + + fill_in 'event_title', with: 'Example Proposal' + select(event_type.title, from: 'event[event_type_id]') + fill_in 'event_submission_text', with: 'Lorem ipsum example submission text' + + accept_confirm do + click_button 'Reset to Template' + end + + expect(page.find('#event_submission_text').value).to eq(event_type.description) + end end end diff --git a/spec/features/ticket_purchases_spec.rb b/spec/features/ticket_purchases_spec.rb index 0a4e4ff8..cc6b66b5 100644 --- a/spec/features/ticket_purchases_spec.rb +++ b/spec/features/ticket_purchases_spec.rb @@ -7,16 +7,17 @@ feature Registration, feature: true, js: true do let!(:free_ticket) { create(:ticket, price_cents: 0) } let!(:first_registration_ticket) { create(:registration_ticket, price_cents: 0) } let!(:second_registration_ticket) { create(:registration_ticket, price_cents: 0) } - let!(:conference) { create(:conference, title: 'ExampleCon', tickets: [ticket, free_ticket, first_registration_ticket, second_registration_ticket], registration_period: create(:registration_period, start_date: 3.days.ago)) } + let!(:third_registration_ticket) { create(:registration_ticket, price_cents: 2000) } + let!(:conference) { create(:conference, title: 'ExampleCon', tickets: [ticket, free_ticket, first_registration_ticket, second_registration_ticket, third_registration_ticket], registration_period: create(:registration_period, start_date: 3.days.ago)) } let!(:participant) { create(:user) } - def make_stripe_purchase(card_number='4242424242424242') + def make_stripe_purchase(card_number = '4242424242424242') find('.stripe-button-el').click stripe_iframe = all('iframe[name=stripe_checkout_app]').last sleep(5) Capybara.within_frame stripe_iframe do - expect(page).to have_content("#{ENV['OSEM_NAME']} tickets") + expect(page).to have_content(:all, "#{ENV['OSEM_NAME']} tickets") fill_in 'Card number', with: card_number fill_in 'Expiry', with: '08/22' fill_in 'CVC', with: '123' @@ -108,6 +109,49 @@ feature Registration, feature: true, js: true do expect(purchase.paid).to be true end + scenario 'purchases a free registartion ticket' do + visit root_path + click_link 'Register' + + expect(current_path).to eq(new_conference_conference_registration_path(conference.short_title)) + click_button 'Register' + + fill_in "tickets__#{first_registration_ticket.id}", with: '1' + expect(current_path).to eq(conference_tickets_path(conference.short_title)) + + click_button 'Continue' + expect(current_path).to eq(new_conference_conference_registration_path(conference.short_title)) + expect(flash).to eq('Thanks! Your ticket is booked successfully. Please register for the conference.') + + purchase = TicketPurchase.where(user_id: participant.id, ticket_id: first_registration_ticket.id).first + expect(purchase.quantity).to eq(1) + expect(purchase.paid).to be true + end + + scenario 'purchases a non-free registartion ticket' do + visit root_path + click_link 'Register' + + expect(current_path).to eq(new_conference_conference_registration_path(conference.short_title)) + click_button 'Register' + + fill_in "tickets__#{third_registration_ticket.id}", with: '1' + expect(current_path).to eq(conference_tickets_path(conference.short_title)) + + click_button 'Continue' + page.find('#flash') + expect(current_path).to eq(new_conference_payment_path(conference.short_title)) + expect(flash).to eq('Please pay here to get tickets.') + purchase = TicketPurchase.where(user_id: participant.id, ticket_id: third_registration_ticket.id).first + expect(purchase.quantity).to eq(1) + + if ENV['STRIPE_PUBLISHABLE_KEY'] || Rails.application.secrets.stripe_publishable_key + make_stripe_purchase + expect(current_path).to eq(new_conference_conference_registration_path(conference.short_title)) + expect(page).to have_content 'Your ticket is booked successfully.' + end + end + scenario 'purchases more than one registration tickets of a single type' do visit root_path click_link 'Register' @@ -144,7 +188,7 @@ feature Registration, feature: true, js: true do context 'who is registered' do scenario 'unregisters from conference, but ticket purchases dont delete' do - pending('SNAPCON: Investigate failure on the unregister button') + skip('SNAPCON: Investigate failure on the unregister button') visit root_path click_link 'Register' diff --git a/spec/helpers/conference_helper_spec.rb b/spec/helpers/conference_helper_spec.rb index 101d083a..4ea48496 100644 --- a/spec/helpers/conference_helper_spec.rb +++ b/spec/helpers/conference_helper_spec.rb @@ -67,4 +67,36 @@ describe ConferenceHelper, type: :helper do expect(sponsorship_mailto(conference)).to match conference.short_title end end + + describe '#conference_logo_url' do + let(:organization) { create(:organization) } + let(:conference2) { create(:conference, organization: organization) } + + it 'gives the correct logo url' do + expect(conference_logo_url(conference2)).to eq('snapcon_logo.png') + + File.open('spec/support/logos/1.png') do |file| + organization.picture = file + end + + expect(conference_logo_url(conference2)).to include('1.png') + + File.open('spec/support/logos/2.png') do |file| + conference2.picture = file + end + + expect(conference_logo_url(conference2)).to include('2.png') + end + end + + describe '#conference_color' do + let(:conference2) { create(:conference, color: '#000000') } + + it 'gives the correct conference color' do + expect(conference_color(conference2)).to eq('#000000') + + conference2.color = '' + expect(conference_color(conference2)).to eq('#0B3559') + end + end end diff --git a/spec/mailers/mailbot_spec.rb b/spec/mailers/mailbot_spec.rb index 1f739997..4c4bd699 100644 --- a/spec/mailers/mailbot_spec.rb +++ b/spec/mailers/mailbot_spec.rb @@ -26,6 +26,14 @@ describe Mailbot do expect(mail.body).to include 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit' end + it 'assigns the email body with the correct color' do + expect(mail.body).to include('background-color: ' + conference.color) + end + + it 'assigns the email body with the correct logo' do + expect(mail.body).to include 'snapcon_logo' + end + it 'delivers the email' do expect(ActionMailer::Base.deliveries).to include(mail) end diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb index 030ad382..2beb3a20 100644 --- a/spec/models/event_spec.rb +++ b/spec/models/event_spec.rb @@ -7,7 +7,6 @@ # id :bigint not null, primary key # abstract :text # comments_count :integer default(0), not null -# committee_review :text # description :text # guid :string not null # is_highlight :boolean default(FALSE) diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index eac86bfe..2e890949 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -441,6 +441,19 @@ describe User do end end end + + describe '#count_registration_tickets' do + let(:registration_ticket) { create(:registration_ticket, price_cents: 0) } + let(:conference3) { create(:conference, short_title: 'oSC17', title: 'openSUSE Conference 2017', tickets: [registration_ticket]) } + let(:ticket_purchase) { create(:ticket_purchase, user: user, conference: conference3, ticket: registration_ticket, quantity: 1) } + + it 'counts the number of registration tickets of a conference held by user' do + user.ticket_purchases << ticket_purchase + + expect(user.count_registration_tickets(conference3)).to eq(1) + expect(user.count_registration_tickets(conference2)).to eq(0) + end + end end describe 'rolify' do diff --git a/spec/serializers/event_serializer_spec.rb b/spec/serializers/event_serializer_spec.rb index 3ad68cad..506134cf 100644 --- a/spec/serializers/event_serializer_spec.rb +++ b/spec/serializers/event_serializer_spec.rb @@ -7,7 +7,6 @@ # id :bigint not null, primary key # abstract :text # comments_count :integer default(0), not null -# committee_review :text # description :text # guid :string not null # is_highlight :boolean default(FALSE) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d3e17427..2d680fb2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,7 +3,7 @@ # This file is copied to spec/ when you run 'rails generate rspec:install' require 'simplecov' -if ENV['GITHUB_ACTIONS'] +if ENV['GITHUB_ACTIONS'] || ENV['TRAVIS'] require 'simplecov-cobertura' SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter end