resolve conflicts with master

This commit is contained in:
Michael Ball 2021-03-21 12:59:43 -07:00
commit f22ad296af
59 changed files with 669 additions and 629 deletions

View file

@ -1 +1,6 @@
coverage:
status:
project:
default:
threshold: 0.5%
comment: off comment: off

View file

@ -1,21 +1,8 @@
language: ruby os: linux
cache: bundler
rvm:
- 2.6.6
dist: bionic dist: bionic
addons:
apt:
packages:
- chromium-browser
services:
- postgresql
branches: branches:
except: except:
- /^depfu/.*$/ - /^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: notifications:
email: email:
on_success: change on_success: change
@ -25,22 +12,9 @@ notifications:
- "chat.freenode.net#osem" - "chat.freenode.net#osem"
on_success: change on_success: change
on_failure: change on_failure: change
before_script: stages:
# install CodeClimate test reporter and tell it we are starting a test run - test
# - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > $CCTR - finalize
# - 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
env: env:
global: global:
- OSEM_DB_ADAPTER=sqlite3 - OSEM_DB_ADAPTER=sqlite3
@ -49,11 +23,90 @@ env:
- OSEM_DB_NAME='osem_test' - OSEM_DB_NAME='osem_test'
- CC_TEST_REPORTER_ID=$CC_TEST_REPORTER - CC_TEST_REPORTER_ID=$CC_TEST_REPORTER
- CCTR=./cc-test-reporter - CCTR=./cc-test-reporter
matrix: - 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 - TEST_SUITE=ability
workspaces:
create:
name: ws1
paths:
- coverage/codeclimate.1.json
- <<: *tests
env:
- TEST_SUITE=features - 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 - 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 - 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 - TEST_SUITE=rest
matrix: script:
fast_finish: false - "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 -

View file

@ -266,7 +266,7 @@ group :test do
gem 'pdf-inspector', require: "pdf/inspector" gem 'pdf-inspector', require: "pdf/inspector"
end end
group :development, :test do group :development, :test, :linters do
# as debugger # as debugger
gem 'byebug' gem 'byebug'
gem 'pry' gem 'pry'
@ -280,6 +280,9 @@ group :development, :test do
gem 'rubocop-rspec', require: false gem 'rubocop-rspec', require: false
gem 'haml-lint', require: false gem 'haml-lint', require: false
end
group :development, :test do
# as development/test database # as development/test database
gem 'sqlite3' gem 'sqlite3'
end end

View file

@ -127,6 +127,8 @@ GEM
aws_cf_signer aws_cf_signer
rest-client rest-client
cocoon (1.2.15) cocoon (1.2.15)
codecov (0.5.0)
simplecov (>= 0.15, < 0.22)
coderay (1.1.1) coderay (1.1.1)
concurrent-ruby (1.1.8) concurrent-ruby (1.1.8)
countable-rails (0.0.1) countable-rails (0.0.1)

View file

@ -1,7 +1,7 @@
### Spring 2021 Student Project ### Spring 2021 Student Project
[![Build Status](https://travis-ci.com/CactusPuppy/snapcon.svg?branch=master)](https://travis-ci.com/CactusPuppy/snapcon) [![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) [![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) [![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) [![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) [![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)

View file

@ -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 */ /* Wait for the DOM to be ready before attaching events to the elements */
$( document ).ready(function() { $( document ).ready(function() {
/* Set the minimum and maximum proposal abstract and submission text word length */ /* 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 max = $selected.data("max-words");
var min = $selected.data("min-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); $("#abstract-maximum-word-count").text(max);
$("#submission-maximum-word-count").text(max); $("#submission-maximum-word-count").text(max);
$("#abstract-minimum-word-count").text(min); $("#abstract-minimum-word-count").text(min);
$("#submission-minimum-word-count").text(min); $("#submission-minimum-word-count").text(min);
word_count($('#event_abstract').get(0), 'abstract-count', max); word_count($('#event_abstract').get(0), 'abstract-count', max);
word_count($('#event_submission_text').get(0), 'submission-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'); .trigger('change');
@ -180,6 +189,18 @@ $( document ).ready(function() {
var max = $selected.data("max-words"); var max = $selected.data("max-words");
word_count(this, 'submission-count', max); 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 */ /* Commodity function for modal windows */

View file

@ -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;
}

View file

@ -16,6 +16,7 @@ class PaymentsController < ApplicationController
raise CanCan::AccessDenied.new('Nothing to pay for!', :new, Payment) raise CanCan::AccessDenied.new('Nothing to pay for!', :new, Payment)
end end
@has_registration_ticket = params[:has_registration_ticket]
@unpaid_ticket_purchases = current_user.ticket_purchases.unpaid.by_conference(@conference) @unpaid_ticket_purchases = current_user.ticket_purchases.unpaid.by_conference(@conference)
end end
@ -24,8 +25,15 @@ class PaymentsController < ApplicationController
if @payment.purchase && @payment.save if @payment.purchase && @payment.save
update_purchased_ticket_purchases update_purchased_ticket_purchases
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, redirect_to conference_physical_tickets_path,
notice: 'Thanks! Your ticket is booked successfully.' notice: 'Thanks! Your ticket is booked successfully.'
end
else else
@total_amount_to_pay = Ticket.total_price(@conference, current_user, paid: false) @total_amount_to_pay = Ticket.total_price(@conference, current_user, paid: false)
@unpaid_ticket_purchases = current_user.ticket_purchases.unpaid.by_conference(@conference) @unpaid_ticket_purchases = current_user.ticket_purchases.unpaid.by_conference(@conference)

View file

@ -8,23 +8,42 @@ class TicketPurchasesController < ApplicationController
def create def create
current_user.ticket_purchases.by_conference(@conference).unpaid.destroy_all 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)) message = TicketPurchase.purchase(@conference, current_user, params[:tickets].try(:first))
if message.blank? # The new ticket_purchase has been added to the database. current_user.ticket_purchases contains the new one.
if current_user.ticket_purchases.by_conference(@conference).unpaid.any? count_registration_tickets_after = current_user.count_registration_tickets(@conference)
redirect_to new_conference_payment_path,
notice: 'Please pay here to get tickets.' # Failed to create ticket purchase
elsif current_user.ticket_purchases.by_conference(@conference).paid.any? unless message.blank?
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
redirect_to conference_tickets_path(@conference.short_title), redirect_to conference_tickets_path(@conference.short_title),
error: "Oops, something went wrong with your purchase! #{message}" 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
end end

View file

@ -1,5 +1,8 @@
# frozen_string_literal: true # frozen_string_literal: true
DEFAULT_LOGO = 'snapcon_logo.png'
DEFAULT_COLOR = '#0B3559'
module ConferenceHelper module ConferenceHelper
# Return true if only call_for_papers or call_for_tracks or call_for_booths is open # Return true if only call_for_papers or call_for_tracks or call_for_booths is open
def one_call_open(*calls) def one_call_open(*calls)
@ -28,6 +31,24 @@ module ConferenceHelper
markdown(ticket.description.split("\n").first&.strip) markdown(ticket.description.split("\n").first&.strip)
end 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 # adds events to icalendar for proposals in a conference
def icalendar_proposals(calendar, proposals, conference) def icalendar_proposals(calendar, proposals, conference)
proposals.each do |proposal| proposals.each do |proposal|

View file

@ -5,21 +5,25 @@ EMAIL_TEMPLATE = 'email_template'
YTLF_TICKET_ID = 50 YTLF_TICKET_ID = 50
class Mailbot < ActionMailer::Base class Mailbot < ActionMailer::Base
def registration_mail(conference, user) helper ConferenceHelper
@email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.registration_body)
@logo = conference.picture.thumb.url
mail(to: user.email, default bcc: -> { SNAPCON_BCC_ADDRESS },
bcc: SNAPCON_BCC_ADDRESS, template_name: -> { EMAIL_TEMPLATE },
from: conference.contact.email, to: -> { @user.email },
subject: conference.email_settings.registration_subject, from: -> { @conference.contact.email }
template_name: EMAIL_TEMPLATE)
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 end
def ticket_confirmation_mail(ticket_purchase) def ticket_confirmation_mail(ticket_purchase)
@ticket_purchase = ticket_purchase @ticket_purchase = ticket_purchase
@conference = ticket_purchase.conference
@user = ticket_purchase.user @user = ticket_purchase.user
@conference = ticket_purchase.conference
PhysicalTicket.last(ticket_purchase.quantity).each do |physical_ticket| 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}") 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' template_name = 'young_thinkers_ticket_confirmation_template'
end end
mail(to: @user.email, mail(subject: "#{@conference.title} | Ticket Confirmation and PDF!",
bcc: SNAPCON_BCC_ADDRESS, template_name: template_name)
from: @conference.contact.email,
template_name: template_name,
subject: "#{@conference.title} | Ticket Confirmation and PDF!")
end end
def acceptance_mail(event) 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 mail(subject: @conference.email_settings.accepted_subject)
@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)
end end
def submitted_proposal_mail(event) 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 mail(subject: @conference.email_settings.submitted_proposal_subject)
@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)
end end
def rejection_mail(event) 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 mail(subject: @conference.email_settings.rejected_subject)
@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)
end end
def confirm_reminder_mail(event) 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 mail(subject: @conference.email_settings.confirmed_without_registration_subject)
@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)
end end
def conference_date_update_mail(conference, user) def conference_date_update_mail(conference, user)
@logo = conference.picture.thumb.url @user = user
@email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.conference_dates_updated_body) @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, mail(subject: @conference.email_settings.conference_dates_updated_subject)
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.conference_dates_updated_subject,
template_name: EMAIL_TEMPLATE)
end end
def conference_registration_date_update_mail(conference, user) def conference_registration_date_update_mail(conference, user)
@logo = conference.picture.thumb.url @user = user
@email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.conference_registration_dates_updated_body) @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, mail(subject: @conference.email_settings.conference_registration_dates_updated_subject)
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.conference_registration_dates_updated_subject,
template_name: EMAIL_TEMPLATE)
end end
def conference_venue_update_mail(conference, user) def conference_venue_update_mail(conference, user)
@logo = conference.picture.thumb.url @user = user
@email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.venue_updated_body) @conference = conference
@email_body = @conference.email_settings.generate_email_on_conf_updates(@conference, @user, @conference.email_settings.venue_updated_body)
mail(to: user.email, mail(subject: @conference.email_settings.venue_updated_subject)
bcc: SNAPCON_BCC_ADDRESS,
from: conference.contact.email,
subject: conference.email_settings.venue_updated_subject,
template_name: EMAIL_TEMPLATE)
end end
def conference_schedule_update_mail(conference, user) def conference_schedule_update_mail(conference, user)
@logo = conference.picture.thumb.url @user = user
@email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.program_schedule_public_body) @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, mail(bcc: nil,
from: conference.contact.email, subject: @conference.email_settings.program_schedule_public_subject)
subject: conference.email_settings.program_schedule_public_subject,
template_name: EMAIL_TEMPLATE)
end end
def conference_cfp_update_mail(conference, user) def conference_cfp_update_mail(conference, user)
@logo = conference.picture.thumb.url @user = user
@email_body = conference.email_settings.generate_email_on_conf_updates(conference, user, conference.email_settings.cfp_dates_updated_body) @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, mail(bcc: nil,
from: conference.contact.email, subject: @conference.email_settings.cfp_dates_updated_subject)
subject: conference.email_settings.cfp_dates_updated_subject,
template_name: EMAIL_TEMPLATE)
end end
def conference_booths_acceptance_mail(booth) def conference_booths_acceptance_mail(booth)
conference = booth.conference @user = booth.submitter
@logo = conference.picture.thumb.url @conference = booth.conference
@email_body = conference.email_settings.generate_booth_mail(booth, conference.email_settings.booths_acceptance_body) @email_body = @conference.email_settings.generate_booth_mail(booth, @conference.email_settings.booths_acceptance_body)
mail(to: booth.submitter.email, mail(bcc: nil,
from: conference.contact.email, subject: @conference.email_settings.booths_acceptance_subject)
subject: conference.email_settings.booths_acceptance_subject,
template_name: EMAIL_TEMPLATE)
end end
def conference_booths_rejection_mail(booth) def conference_booths_rejection_mail(booth)
conference = booth.conference @user = booth.submitter
@logo = conference.picture.thumb.url @conference = booth.conference
@email_body = conference.email_settings.generate_booth_mail(booth, conference.email_settings.booths_rejection_body) @email_body = @conference.email_settings.generate_booth_mail(booth, @conference.email_settings.booths_rejection_body)
mail(to: booth.submitter.email, mail(bcc: nil,
from: conference.contact.email, subject: @conference.email_settings.booths_rejection_subject)
subject: conference.email_settings.booths_rejection_subject,
template_name: EMAIL_TEMPLATE)
end end
def event_comment_mail(comment, user) def event_comment_mail(comment, user)
@ -171,8 +137,7 @@ class Mailbot < ActionMailer::Base
@conference = @event.program.conference @conference = @event.program.conference
@user = user @user = user
mail(to: @user.email, mail(bcc: nil,
from: @conference.contact.email,
template_name: 'comment_template', template_name: 'comment_template',
subject: "New comment has been posted for #{@event.title}") subject: "New comment has been posted for #{@event.title}")
end end

View file

@ -7,7 +7,6 @@
# id :bigint not null, primary key # id :bigint not null, primary key
# abstract :text # abstract :text
# comments_count :integer default(0), not null # comments_count :integer default(0), not null
# committee_review :text
# description :text # description :text
# guid :string not null # guid :string not null
# is_highlight :boolean default(FALSE) # is_highlight :boolean default(FALSE)

View file

@ -346,6 +346,17 @@ class User < ApplicationRecord
events.where(program_id: conference.program.id, 'event_users.event_role': 'volunteer') events.where(program_id: conference.program.id, 'event_users.event_role': 'volunteer')
end 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? def self.empty?
User.count == 1 && User.first.email == 'deleted@localhost.osem' User.count == 1 && User.first.email == 'deleted@localhost.osem'
end end

View file

@ -7,7 +7,6 @@
# id :bigint not null, primary key # id :bigint not null, primary key
# abstract :text # abstract :text
# comments_count :integer default(0), not null # comments_count :integer default(0), not null
# committee_review :text
# description :text # description :text
# guid :string not null # guid :string not null
# is_highlight :boolean default(FALSE) # is_highlight :boolean default(FALSE)

View file

@ -57,6 +57,33 @@
.col-md-4 .col-md-4
= render 'donut_chart', title: 'Event types', = render 'donut_chart', title: 'Event types',
combined_data: @event_type_distribution 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 .col-md-4
= render 'donut_chart', title: 'Difficulty levels', = render 'donut_chart', title: 'Difficulty levels',
combined_data: @difficulty_levels_distribution combined_data: @difficulty_levels_distribution

View file

@ -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 .panel-heading
%label{ for: "registration_event_ids_#{event.id}" } %label{ for: "registration_event_ids_#{event.id}" }
%h3{ style: 'margin: 0 auto;' } %h3{ style: 'margin: 0 auto;' }
= hidden_field_tag 'registration[event_ids][]', nil = 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 = event.title
%small %small
= event.subtitle = event.subtitle
@ -13,6 +13,7 @@
(Scheduled on: #{event.time.to_date}) (Scheduled on: #{event.time.to_date})
.panel-body .panel-body
-#
%p %p
= canceled_replacement_event_label(event, event_schedule) = canceled_replacement_event_label(event, event_schedule)
= replacement_event_notice(event_schedule) = replacement_event_notice(event_schedule)
@ -29,7 +30,7 @@
%p %p
= markdown(truncate(event.abstract, length: 250)) = markdown(truncate(event.abstract, length: 250))
-# TODO: More informative text or aria-label. -# 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 - if event.track
%span.track %span.track

View file

@ -18,6 +18,6 @@
You are registered for #{pluralize(@registration.events.count, 'event')}. You are registered for #{pluralize(@registration.events.count, 'event')}.
They are at the end of this list. They are at the end of this list.
- @registration.events_ordered.each do |event| - @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 = render 'conferences/code_of_conduct', organization: @conference.organization

View file

@ -1,14 +1,15 @@
-# .scroll-top-wrapper -#
-# = link_to "#banner", class: "smoothscroll" do scroll-top-wrapper
-# %i.fa.fa-2x.fa-arrow-circle-up = link_to "#banner", class: "smoothscroll" do
%i.fa.fa-2x.fa-arrow-circle-up
-# :javascript :javascript
-# $(function(){ $(function(){
-# $(document).on( 'scroll', function(){ $(document).on( 'scroll', function(){
-# if ($(window).scrollTop() > 100) { if ($(window).scrollTop() > 100) {
-# $('.scroll-top-wrapper').addClass('show'); $('.scroll-top-wrapper').addClass('show');
-# } else { } else {
-# $('.scroll-top-wrapper').removeClass('show'); $('.scroll-top-wrapper').removeClass('show');
-# } }
-# }); });
-# }); });

View file

@ -4,11 +4,12 @@
.row .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 .row
-# - if conference.picture? -#
-# .col-md-4 - if conference.picture?
-# = image_tag(conference.picture_url, .col-md-4
-# class: 'img-responsive img-center', = image_tag(conference.picture_url,
-# id: 'splash-logo') class: 'img-responsive img-center',
id: 'splash-logo')
.col-md-8 .col-md-8
%h1 %h1
= conference.title.html_safe = conference.title.html_safe

View file

@ -2,7 +2,7 @@
%li %li
%a.smoothscroll{ href: '#program' } Program %a.smoothscroll{ href: '#program' } Program
%li %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 - cache [conference, highlights, tracks, booths, '#splash#program'] do
%section#program %section#program

View file

@ -27,7 +27,7 @@
.row .row
.col-md-12 .col-md-12
%h3.text-center %h3.text-center
= "Interested in sponsoring #{conference.title}?" Interested in sponsoring #{conference.title}?
= link_to(sponsorship_mailto(conference)) do = link_to(sponsorship_mailto(conference)) do
Please, contact us! Please, contact us!
.trapezoid .trapezoid

View file

@ -27,7 +27,6 @@
You have unpaid tickets. Please complete your purchase. You have unpaid tickets. Please complete your purchase.
= link_to('Purchase Tickets', new_conference_payment_path(@conference), class: 'btn btn-success btn-lg') = link_to('Purchase Tickets', new_conference_payment_path(@conference), class: 'btn btn-success btn-lg')
- if @user_needs_to_register - if @user_needs_to_register
.row .row
.col-md-12 .col-md-12
@ -38,7 +37,6 @@
You still need to complete your registration for #{@conference.title}. 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') = link_to('Complete Registration', new_conference_conference_registration_path(@conference), class: 'btn btn-success btn-lg')
#splash #splash
- if @conference.code_of_conduct.present? - if @conference.code_of_conduct.present?
= render 'code_of_conduct', organization: @conference.organization = render 'code_of_conduct', organization: @conference.organization
@ -79,29 +77,8 @@
sponsorship_levels: @sponsorship_levels, sponsorship_levels: @sponsorship_levels,
sponsors: @sponsors sponsors: @sponsors
-# footer -# footer
- if @conference.splashpage.include_social_media - if @conference.splashpage.include_social_media
- if @conference.contact.has_social_media? - if @conference.contact.has_social_media?
= render 'social_media', contact: @conference.contact = render 'social_media', contact: @conference.contact
= render 'footer' = 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 + ')');
-# });
-# });

View file

@ -0,0 +1,12 @@
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<meta content="Snap!Con -- A conference all about Snap!, a programing language from UC Berkeley." name="description"/>
<meta content="Michael Ball, Brian Harvey, Jens Moenig, Bernat Romagosa, Dan Garcia, Lauren Mock" name="author"/>
<%= stylesheet_link_tag "mailbot" %>
</head>
<body>
<div id="border" style="background-color: <%= conference_color(@conference) %>"></div>
</body>
</html>

View file

@ -0,0 +1,25 @@
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<title>
<%= 'Email' %>
</title>
<meta content="Snap!Con -- A conference all about Snap!, a programing language from UC Berkeley." name="description"/>
<meta content="Michael Ball, Brian Harvey, Jens Moenig, Bernat Romagosa, Dan Garcia, Lauren Mock" name="author"/>
<%= stylesheet_link_tag "mailbot" %>
</head>
<body>
<div id="border" style="background-color: <%= conference_color(@conference) %>">
<div class="row">
<div class="col-md-2">
<% if @conference.present? %>
<%= image_tag(conference_logo_url(@conference), style: "display:block;height:70px;width:auto;", alt: @conference.title + ' logo') %>
<% end %>
</div>
</div>
</div>
</body>

View file

@ -51,37 +51,38 @@
= link_to(sign_in_path) do = link_to(sign_in_path) do
%span.fa.fa-user %span.fa.fa-user
Sign In Sign In
-# %li.dropdown.visible-desktop -#
-# %a.dropdown-toggle{"data-toggle" => "dropdown", href: '#'} %li.dropdown.visible-desktop
-# %span.fa.fa-user %a.dropdown-toggle{"data-toggle" => "dropdown", href: '#'}
-# Sign In %span.fa.fa-user
-# %span.caret Sign In
-# .dropdown-menu %span.caret
-# - if ENV['OSEM_ICHAIN_ENABLED'] == 'true' .dropdown-menu
-# = form_tag User.ichain_login_url do - if ENV['OSEM_ICHAIN_ENABLED'] == 'true'
-# = text_field_tag 'username', nil, id: 'user_ichain_email_dd', class: 'form-control', placeholder: 'Username' = form_tag User.ichain_login_url do
-# = password_field_tag 'password', nil, id: 'user_ichain_password_dd', class: 'form-control', placeholder: 'Password' = text_field_tag 'username', nil, id: 'user_ichain_email_dd', class: 'form-control', placeholder: 'Username'
-# %button.btn.btn-success.btn-block Sign in = password_field_tag 'password', nil, id: 'user_ichain_password_dd', class: 'form-control', placeholder: 'Password'
-# - else %button.btn.btn-success.btn-block Sign in
-# %div{style: "padding: 6px"} - else
-# = form_tag new_user_session_path, class: 'form-group' do %div{style: "padding: 6px"}
-# = text_field_tag 'user[login]', nil, id: 'user_login_dd', class: 'form-control', placeholder: 'Username / E-Mail' = form_tag new_user_session_path, class: 'form-group' do
-# = password_field_tag 'user[password]', nil, id: 'user_password_dd', class: 'form-control', placeholder: 'Password' = text_field_tag 'user[login]', nil, id: 'user_login_dd', class: 'form-control', placeholder: 'Username / E-Mail'
-# %p.text-right = password_field_tag 'user[password]', nil, id: 'user_password_dd', class: 'form-control', placeholder: 'Password'
-# %small %p.text-right
-# %label{for: 'user_remember_me'} Remember me %small
-# = check_box_tag 'user[remember_me]' %label{for: 'user_remember_me'} Remember me
-# %br = check_box_tag 'user[remember_me]'
-# %button.btn.btn-success.btn-block Sign in %br
-# - unless omniauth_configured.empty? %button.btn.btn-success.btn-block Sign in
-# .divider - unless omniauth_configured.empty?
-# %h6.text-center .divider
-# or %h6.text-center
-# = render 'devise/shared/openid_links' or
-# %p.text-right = render 'devise/shared/openid_links'
-# %br %p.text-right
-# %a.small.btn.btn-xs.btn-default{"data-toggle" => "collapse", "data-target" => "#navbar-devise-help"} %br
-# Need Help? %a.small.btn.btn-xs.btn-default{"data-toggle" => "collapse", "data-target" => "#navbar-devise-help"}
-# #navbar-devise-help.collapse Need Help?
-# = render 'devise/shared/links' #navbar-devise-help.collapse
= render 'devise/shared/links'
.trapezoid .trapezoid

View file

@ -0,0 +1,16 @@
<%= render partial: "layouts/mailbot_header" %>
<div id="content">
<span style="white-space: pre-line">
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
</span>
</div>
<%= render partial: "layouts/mailbot_footer" %>

View file

@ -1,83 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- CSS -->
<link rel="stylesheet" href="main.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Montserrat:100,200,300,400,500,600,700,800" rel="stylesheet">
<style>
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;
}
</style>
<!-- Page Title -->
<title>Email</title>
</head>
<body>
<div id="border">
<div class="row">
<!-- Uncomment below to get logo -->
<div class="col-md-2">
</div>
<div class="col-md-10"><h1></h1></div>
</div>
</div>
<div id="content">
<span style="white-space: pre-line">
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
</span>
</div>
<div id="border">
<h1></h1>
</div>
</body>
</html>

View file

@ -1,77 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- CSS -->
<link rel="stylesheet" href="main.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Montserrat:100,200,300,400,500,600,700,800" rel="stylesheet">
<style>
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;
}
</style>
<!-- Page Title -->
<title>Email</title>
</head>
<body>
<div id="border">
<div class="row">
<!-- Uncomment below to get logo -->
<div class="col-md-2">
<% if !@logo.nil? %>
<%= image_tag(@logo, style: "display:block") %>
<% end %>
</div>
<div class="col-md-10"><h1></h1></div>
</div>
</div>
<div id="content">
<span style="white-space: pre-line">
<%= @email_body %>
</span>
</div>
<div id="border">
<h1></h1>
</div>
</body>
</html>

View file

@ -0,0 +1,7 @@
<%= render partial: "layouts/mailbot_header" %>
<div id="content">
<span style="white-space: pre-line">
<%= @email_body %>
</span>
</div>
<%= render partial: "layouts/mailbot_footer" %>

View file

@ -0,0 +1,14 @@
<%= render partial: "layouts/mailbot_header" %>
<div id="content">
<span style="white-space: pre-line">
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
</span>
</div>
<%= render partial: "layouts/mailbot_footer" %>

View file

@ -1,81 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- CSS -->
<link rel="stylesheet" href="main.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Montserrat:100,200,300,400,500,600,700,800" rel="stylesheet">
<style>
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;
}
</style>
<!-- Page Title -->
<title>Email</title>
</head>
<body>
<div id="border">
<div class="row">
<!-- Uncomment below to get logo -->
<div class="col-md-2">
</div>
<div class="col-md-10"><h1></h1></div>
</div>
</div>
<div id="content">
<span style="white-space: pre-line">
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
</span>
</div>
<div id="border">
<h1></h1>
</div>
</body>
</html>

View file

@ -0,0 +1,16 @@
<%= render partial: "layouts/mailbot_header" %>
<div id="content">
<span style="white-space: pre-line">
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
</span>
</div>
<%= render partial: "layouts/mailbot_footer" %>

View file

@ -1,83 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- CSS -->
<link rel="stylesheet" href="main.css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Montserrat:100,200,300,400,500,600,700,800" rel="stylesheet">
<style>
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;
}
</style>
<!-- Page Title -->
<title>Email</title>
</head>
<body>
<div id="border">
<div class="row">
<!-- Uncomment below to get logo -->
<div class="col-md-2">
</div>
<div class="col-md-10"><h1></h1></div>
</div>
</div>
<div id="content">
<span style="white-space: pre-line">
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
</span>
</div>
<div id="border">
<h1></h1>
</div>
</body>
</html>

View file

@ -19,7 +19,7 @@
%td %td
= humanized_money_with_symbol ticket.quantity * ticket.price = 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", %script.stripe-button{'src': "https://checkout.stripe.com/checkout.js",
'data': {amount: @total_amount_to_pay.cents, 'data': {amount: @total_amount_to_pay.cents,
label: "Pay #{humanized_money_with_symbol @total_amount_to_pay}", label: "Pay #{humanized_money_with_symbol @total_amount_to_pay}",

View file

@ -16,7 +16,7 @@
That means you have That means you have
%b.notranslate= pluralize(@program.cfp.remaining_days, 'day') %b.notranslate= pluralize(@program.cfp.remaining_days, 'day')
left! left!
%span.notranslate #{@conference.title} %span.notranslate= @conference.title
will only be as good as the content you present. Submit early, submit often! will only be as good as the content you present. Submit early, submit often!
- else - else
The submission period is closed now. The submission period is closed now.

View file

@ -56,6 +56,7 @@
= f.input :submission_text, input_html: { rows: 5, data: { provide: 'markdown' }, placeholder: '' }, = f.input :submission_text, input_html: { rows: 5, data: { provide: 'markdown' }, placeholder: '' },
hint: markdown_hint('Only conference organizers will read this.') 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 %p
You have used You have used

View file

@ -1,13 +1,13 @@
.speakerinfo .speakerinfo
.row .row
.col-md-4 .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 .col-md-8
%h4 %h4
= link_to speaker.name, user_path(speaker.id) = link_to speaker.name, user_path(speaker.id)
%br %br
- if speaker.email_public? - if speaker.email_public?
= mail_to "#{ speaker.email }" do = mail_to speaker.email.to_s do
%i.fa.fa-envelope-o.fa-2x %i.fa.fa-envelope-o.fa-2x
- if speaker.affiliation? - if speaker.affiliation?
.text-muted .text-muted

View file

@ -1,7 +1,7 @@
.speakerinfo .speakerinfo
.row .row
.col-md-4 .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 .col-md-8
%h4 %h4
= link_to speaker.name, user_path(speaker.id) = link_to speaker.name, user_path(speaker.id)

View file

@ -1,8 +1,8 @@
%table.table.table-striped#events %table.table.table-striped#events
- events.each do |event| - events.each do |event|
%tr %tr
%td.col-md-7{style: "padding:20px 8px 20px 8px;"} %td.col-md-7{ style: 'padding:20px 8px 20px 8px;' }
= link_to event.title, conference_program_proposal_path(@conference.short_title, event.id) = link_to event.title, conference_program_proposal_path(conference.short_title, event.id)
%br %br
%small.text-muted %small.text-muted
= event.event_type.title = event.event_type.title
@ -10,10 +10,11 @@
= "in #{event.track.name}" if event.track = "in #{event.track.name}" if event.track
- if event.require_registration - if event.require_registration
%br %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;"} %td.col-md-2{ style: 'padding:20px 8px 20px 8px;' }
- event_schedule = event.event_schedules.find_by(schedule_id: @program.selected_schedule_id) - event_schedule = event.event_schedules.find_by(schedule_id: program.selected_schedule_id)
- if event_schedule.present? - if event_schedule.present?
= inyourtz(event_schedule.start_time, @conference.timezone) do = inyourtz(event_schedule.start_time, conference.timezone) do
= event_schedule.start_time.strftime("%Y %B %e - %H:%M") = event_schedule.start_time.strftime('%Y %B %e - %H:%M')

View file

@ -121,7 +121,7 @@
Volunteer Duties Volunteer Duties
%small %small
Thanks for being a host at #{@conference.title} 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 .row
.col-md-12 .col-md-12

View file

@ -33,7 +33,7 @@
= f.input :title, as: :string, required: true, input_html: { required: true } = f.input :title, as: :string, required: true, input_html: { required: true }
= f.input :event_type_id, as: :select, = f.input :event_type_id, as: :select,
collection: @program.event_types.map {|type| ["#{type.title} - #{show_time(type.length)}", type.id, 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' } include_blank: false, label: 'Type', input_html: { class: 'select-help-toggle' }
- if @program.languages.present? - if @program.languages.present?
@ -76,6 +76,8 @@
= f.input :submission_text, input_html: { rows: 5, data: { provide: 'markdown' } }, = f.input :submission_text, input_html: { rows: 5, data: { provide: 'markdown' } },
hint: markdown_hint 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? - if @program.cfp.enable_registrations?
= f.input :require_registration, label: 'Require participants to register to your event' = f.input :require_registration, label: 'Require participants to register to your event'

View file

@ -1,15 +1,15 @@
.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' - 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" } .panel-heading{ style: "background-color: #{header_color}; color: #{ contrast_color(header_color) }; border-radius: 4px" }
- event.speakers_ordered.each do |speaker| - 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 %p
= canceled_replacement_event_label(event, event_schedule) = canceled_replacement_event_label(event, event_schedule)
= replacement_event_notice(event_schedule) = replacement_event_notice(event_schedule)
%span.h3{style: "margin-bottom: 14px"} %span.h3{ style: 'margin-bottom: 14px' }
= event.title = event.title
%br %br
%small{ style: "color: #{contrast_color(header_color)}" } %small{ style: "color: #{contrast_color(header_color)}" }
@ -30,13 +30,13 @@
= inyourtz(event_schedule.start_time) do = inyourtz(event_schedule.start_time) do
%span.track %span.track
%span.fa.fa-clock-o %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.start_time.strftime('%l:%M %P')
\- \-
= event_schedule.end_time.strftime('%l:%M %P') = event_schedule.end_time.strftime('%l:%M %P')
%span.track %span.track
%span.fa.fa-map-marker %span.fa.fa-map-marker
%span.label{ style: "background-color: grey" } %span.label{ style: 'background-color: grey' }
= event_schedule.room.name = event_schedule.room.name
- if event.track - if event.track
%span.track %span.track

View file

@ -22,12 +22,15 @@
- unless event_schedule.start_time.strftime('%Y-%m-%d').eql?(date) - unless event_schedule.start_time.strftime('%Y-%m-%d').eql?(date)
.col-xs-12.col-md-12 .col-xs-12.col-md-12
.date-content .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 = inyourtz(event_schedule.start_time, @conference.timezone) do
= date = event_schedule.start_time.strftime('%Y-%m-%d') = 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 } %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 .col-xs-12.col-md-1
.start-time .start-time
= inyourtz(event_schedule.start_time, @conference.timezone) do = inyourtz(event_schedule.start_time, @conference.timezone) do
@ -35,10 +38,6 @@
.col-xs-12.col-md-11 .col-xs-12.col-md-11
.new-time-event .new-time-event
= render 'event', event: event_schedule.event, event_schedule: event_schedule = 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 :javascript
// Refresh the page every 5 minutes. // Refresh the page every 5 minutes.

View file

@ -12,23 +12,23 @@ else
fi fi
case $TEST_SUITE in case $TEST_SUITE in
linters) linters|all)
bundle exec rubocop -Dc .rubocop.yml bundle exec rubocop -Dc .rubocop.yml
bundle exec haml-lint app/views bundle exec haml-lint app/views
;; ;;&
models) models|all)
bundle exec rspec --format documentation spec/models bundle exec rspec --format documentation spec/models
;; ;;&
features) features|all)
bundle exec rspec --format documentation spec/features bundle exec rspec --format documentation spec/features
;; ;;&
controllers) controllers|all)
bundle exec rspec --format documentation spec/controllers bundle exec rspec --format documentation spec/controllers
;; ;;&
ability) ability|all)
bundle exec rspec --format documentation spec/ability bundle exec rspec --format documentation spec/ability
;; ;;&
rest) rest|all)
bundle exec rspec --format documentation --exclude-pattern "spec/{models,features,controllers,ability}/**/*_spec.rb" bundle exec rspec --format documentation --exclude-pattern "spec/{models,features,controllers,ability}/**/*_spec.rb"
;; ;;
esac esac

View file

@ -113,5 +113,7 @@ Osem::Application.configure do
devise_config.ichain_test_mode = true devise_config.ichain_test_mode = true
end end
end end
config.assets.precompile += ['mailbot.css']
config.active_record.verbose_query_logs = true config.active_record.verbose_query_logs = true
end end

View file

@ -26,7 +26,7 @@ Osem::Application.configure do
config.assets.digest = true config.assets.digest = true
config.assets.css_compressor = :sass config.assets.css_compressor = :sass
config.assets.js_compressor = :uglifier config.assets.js_compressor = Uglifier.new(harmony: true)
config.assets.gzip = true config.assets.gzip = true
# Defaults to nil and saved in location specified by config.assets.prefix # Defaults to nil and saved in location specified by config.assets.prefix

View file

@ -52,4 +52,5 @@ Osem::Application.configure do
ActiveSupport::Deprecation.silenced = true ActiveSupport::Deprecation.silenced = true
end end
config.assets.precompile += ['mailbot.css']
end end

View file

@ -49,6 +49,7 @@ FactoryBot.define do
ticket_layout { 'portrait' } ticket_layout { 'portrait' }
description { Faker::Hipster.paragraph } description { Faker::Hipster.paragraph }
organization organization
color { '#FFFFFF' }
after(:create) do |conference| 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: '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') Role.where(name: 'cfp', resource: conference).first_or_create(description: 'For the members of the CfP team')

View file

@ -7,7 +7,6 @@
# id :bigint not null, primary key # id :bigint not null, primary key
# abstract :text # abstract :text
# comments_count :integer default(0), not null # comments_count :integer default(0), not null
# committee_review :text
# description :text # description :text
# guid :string not null # guid :string not null
# is_highlight :boolean default(FALSE) # is_highlight :boolean default(FALSE)

View file

@ -191,5 +191,24 @@ feature Event do
@event.reload @event.reload
expect(@event.state).to eq('withdrawn') expect(@event.state).to eq('withdrawn')
end 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
end end

View file

@ -7,7 +7,8 @@ feature Registration, feature: true, js: true do
let!(:free_ticket) { create(:ticket, price_cents: 0) } let!(:free_ticket) { create(:ticket, price_cents: 0) }
let!(:first_registration_ticket) { create(:registration_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!(: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) } let!(:participant) { create(:user) }
def make_stripe_purchase(card_number = '4242424242424242') def make_stripe_purchase(card_number = '4242424242424242')
@ -16,7 +17,7 @@ feature Registration, feature: true, js: true do
stripe_iframe = all('iframe[name=stripe_checkout_app]').last stripe_iframe = all('iframe[name=stripe_checkout_app]').last
sleep(5) sleep(5)
Capybara.within_frame stripe_iframe do 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 'Card number', with: card_number
fill_in 'Expiry', with: '08/22' fill_in 'Expiry', with: '08/22'
fill_in 'CVC', with: '123' fill_in 'CVC', with: '123'
@ -108,6 +109,49 @@ feature Registration, feature: true, js: true do
expect(purchase.paid).to be true expect(purchase.paid).to be true
end 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 scenario 'purchases more than one registration tickets of a single type' do
visit root_path visit root_path
click_link 'Register' click_link 'Register'
@ -144,7 +188,7 @@ feature Registration, feature: true, js: true do
context 'who is registered' do context 'who is registered' do
scenario 'unregisters from conference, but ticket purchases dont delete' 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 visit root_path
click_link 'Register' click_link 'Register'

View file

@ -67,4 +67,36 @@ describe ConferenceHelper, type: :helper do
expect(sponsorship_mailto(conference)).to match conference.short_title expect(sponsorship_mailto(conference)).to match conference.short_title
end end
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 end

View file

@ -26,6 +26,14 @@ describe Mailbot do
expect(mail.body).to include 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit' expect(mail.body).to include 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit'
end 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 it 'delivers the email' do
expect(ActionMailer::Base.deliveries).to include(mail) expect(ActionMailer::Base.deliveries).to include(mail)
end end

View file

@ -7,7 +7,6 @@
# id :bigint not null, primary key # id :bigint not null, primary key
# abstract :text # abstract :text
# comments_count :integer default(0), not null # comments_count :integer default(0), not null
# committee_review :text
# description :text # description :text
# guid :string not null # guid :string not null
# is_highlight :boolean default(FALSE) # is_highlight :boolean default(FALSE)

View file

@ -441,6 +441,19 @@ describe User do
end end
end 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 end
describe 'rolify' do describe 'rolify' do

View file

@ -7,7 +7,6 @@
# id :bigint not null, primary key # id :bigint not null, primary key
# abstract :text # abstract :text
# comments_count :integer default(0), not null # comments_count :integer default(0), not null
# committee_review :text
# description :text # description :text
# guid :string not null # guid :string not null
# is_highlight :boolean default(FALSE) # is_highlight :boolean default(FALSE)

View file

@ -3,7 +3,7 @@
# This file is copied to spec/ when you run 'rails generate rspec:install' # This file is copied to spec/ when you run 'rails generate rspec:install'
require 'simplecov' require 'simplecov'
if ENV['GITHUB_ACTIONS'] if ENV['GITHUB_ACTIONS'] || ENV['TRAVIS']
require 'simplecov-cobertura' require 'simplecov-cobertura'
SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter SimpleCov.formatter = SimpleCov::Formatter::CoberturaFormatter
end end