Compare commits

..

2 Commits

Author SHA1 Message Date
Albert Stefanov 830b71df76 Fix some grammar in devise translations 2024-05-26 09:29:29 +03:00
Tocho Tochev 4e0e281328 Add devise BG locale 2024-05-26 00:05:25 +03:00
51 changed files with 53 additions and 2201 deletions

4
.docker-ignore Normal file
View File

@ -0,0 +1,4 @@
.git
*.tar.gz
*.sql
node_modules

View File

@ -35,9 +35,3 @@
/app/assets/builds/*
!/app/assets/builds/.keep
/public/assets
# Archives
*.tar.gz
# SQL
*.sql

View File

@ -1,7 +0,0 @@
require: standard
inherit_gem:
standard: config/base.yml
AllCops:
DisabledByDefault: true

View File

@ -1 +1 @@
3.3.5
3.3.0

View File

@ -2,7 +2,7 @@ language: ruby
dist: xenial
cache: bundler
rvm:
- 3.3
- 2.6
script:
- RAILS_ENV=test bundle exec rake --trace bootstrap spec
addons:

View File

@ -1,7 +1,7 @@
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.3.5
ARG RUBY_VERSION=3.3.0
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
# Rails app lives here
@ -58,5 +58,5 @@ USER rails:rails
ENTRYPOINT ["/rails/bin/docker-entrypoint"]
# Start the server by default, this can be overwritten at runtime
EXPOSE 80
CMD ["./bin/thrust", "./bin/rails", "server", "--early-hints"]
EXPOSE 3000
CMD ["./bin/rails", "server", "--early-hints"]

View File

@ -88,5 +88,3 @@ group :test do
gem "database_cleaner"
gem "factory_bot_rails"
end
gem "thruster", "~> 0.1.8"

View File

@ -491,7 +491,6 @@ GEM
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
thor (1.3.0)
thruster (0.1.8)
tilt (2.3.0)
timeout (0.4.1)
tzinfo (2.0.6)
@ -569,7 +568,6 @@ DEPENDENCIES
sprockets
sqlite3
standard
thruster (~> 0.1.8)
uglifier
yaml_db

View File

@ -1,31 +1,11 @@
# Clarion
Clarion
=======
A CfP automation system for OpenFest.
## Installation
Installation
------------
### For local development
1. `git clone https://git.openfest.org/Site/clarion/`
2. Run `rvm install "ruby-$(cat .ruby-version)"; rvm install "ruby-$(cat .ruby-version)"`
3. Start up postgresql
4. Run `bundle install; bin/rake bootstrap`
5. You can now run the rails server with `bin/rails s`
### For production
`docker build -t clarion:latest -f Dockerfile .`
Note that the docker image contains a default user (for credentials see `db/seeds.rb`).
### docker-compose
`docker-compose up` will bring everything up on `http://127.0.0.1:3000` with production configuration.
## Initial Usage
1. Go to `http://127.0.0.1:3000/management/`
2. Login (for initial creds see `db/seeds.rb`)
3. Change the credentials
4. Create a conference.
- NB: When creating a conference make sure to use the same `domain` as the one you are currently using, otherwise nothing will be shown.
1. `git clone https://github.com/ignisf/clarion.git`
2. Run `bundle install; bin/rake bootstrap`
3. You can now run the rails server with `bin/rails s`

View File

@ -3,6 +3,5 @@ class Api::ConferencesController < Api::ApplicationController
def index
@conferences = Conference.all
fresh_when @conferences
end
end

View File

@ -5,6 +5,5 @@ class Api::EventTypesController < Api::ApplicationController
def index
@event_types = current_conference.event_types.includes(:translations)
fresh_when @event_types
end
end

View File

@ -9,5 +9,6 @@ class Api::EventsController < Api::ApplicationController
def halfnarp_friendly
@events = current_conference.events.joins(:proposition).includes(:track, :event_type).where.not(propositions: {status: :rejected})
render json: @events, include: [:track, :event_type]
end
end

View File

@ -5,6 +5,5 @@ class Api::HallsController < Api::ApplicationController
def index
@halls = current_conference.halls
fresh_when @halls
end
end

View File

@ -1,9 +0,0 @@
class Api::SchedulesController < Api::ApplicationController
include ::CurrentConferenceAssigning
include ::PublicApiExposing
before_action :require_current_conference!
def show
@halls = Conference.last.halls.includes(:translations, slots: {approved_event: [:participants_with_personal_profiles, :proposition]})
end
end

View File

@ -5,7 +5,5 @@ class Api::SlotsController < Api::ApplicationController
def index
@slots = current_conference.slots
fresh_when @slots
end
end

View File

@ -5,6 +5,5 @@ class Api::SpeakersController < Api::ApplicationController
def index
@speakers = PersonalProfile.joins(user: {participations: {event: :proposition}}).where(events: {id: current_conference.approved_events.pluck(:id)}, conference: current_conference).distinct
fresh_when @speakers
end
end

View File

@ -5,6 +5,5 @@ class Api::TracksController < Api::ApplicationController
def index
@tracks = current_conference.tracks.includes(:translations)
fresh_when @tracks
end
end

View File

@ -33,8 +33,7 @@ class ApplicationController < ActionController::Base
# TODO: make this get the domain from the database
prepend_view_path "lib/initfest/views" if request.host =~ /openfest/
prepend_view_path "lib/initfest/views" if request.host =~ /example/
prepend_view_path "lib/initfest/views" if request.host =~ /^127\.0\.0/
prepend_view_path "lib/initfest/views" if request.host =~ /^localhost$/
prepend_view_path "lib/initfest/views" if request.host =~ /127\.0\.0/
end
protected

View File

@ -8,11 +8,7 @@ module Management
private
def authorize_user!
if params[:conference_id] && params[:conference_id].to_i < Conference.last.id
head :forbidden unless current_user.admin? && current_user.owner?
else
head :forbidden unless current_user.admin?
end
end
end
end

View File

@ -15,12 +15,6 @@ module Management
@volunteer = current_conference.volunteers.find(params[:id])
end
def destroy
@volunteer = current_conference.volunteers.find(params[:id])
@volunteer.destroy!
redirect_to management_conference_volunteers_path(conference_id: current_conference.id)
end
def update
@volunteer = current_conference.volunteers.find(params[:id])
@ -41,7 +35,7 @@ module Management
params.require(:volunteer).permit(:name, :picture, :email, :phone,
:tshirt_size, :tshirt_cut,
:food_preferences, :previous_experience,
:notes, :language, :terms_accepted,
:notes, :language,
:volunteer_team_id,
additional_volunteer_team_ids: [])
end

View File

@ -39,7 +39,7 @@ module Public
params.require(:volunteer).permit(
:name, :picture, :email, :phone, :tshirt_size, :tshirt_cut,
:food_preferences, :previous_experience, :notes, :language,
:terms_accepted, :volunteer_team_id,
:volunteer_team_id
)
end
end

View File

@ -4,7 +4,7 @@ class VolunteerMailer < ActionMailer::Base
mail(
to: @volunteer.conference.email,
subject: "Нов доброволец за #{@volunteer.conference.title} - #{@volunteer.volunteer_team.name}"
subject: "Нов доброволец за #{@volunteer.conference.title}"
)
end

View File

@ -20,7 +20,6 @@ class Event < ActiveRecord::Base
scope :ranked, -> { where.not(ranked: nil).where.not(votes: nil) }
scope :approved, -> { where(propositions: {status: Proposition.statuses[:approved]})}
scope :approved_joined, -> { joins(:proposition).merge(Proposition.approved) }
validates :conference, presence: true
validates :title, presence: true, length: {maximum: 65}

View File

@ -4,7 +4,7 @@ class Proposition < ActiveRecord::Base
enum status: [:undecided, :approved, :rejected, :backup]
delegate :proposable_title, :proposable_type, :proposable_description, to: :proposable
after_commit :send_creation_notification, on: [:create]
after_create :send_creation_notification
before_destroy :send_withdrawal_notification
def confirm!

View File

@ -1,5 +1,4 @@
class Slot < ActiveRecord::Base
belongs_to :hall
belongs_to :event, required: false
belongs_to :approved_event, -> { joins(:proposition).approved_joined }, class_name: 'Event', foreign_key: 'event_id'
end

View File

@ -12,7 +12,6 @@ class Volunteer < ActiveRecord::Base
validates :email, format: {with: /\A[^@]+@[^@]+\z/}, presence: true, uniqueness: {scope: :conference_id}
validates :phone, presence: true, format: {with: /\A[+\- \(\)0-9]+\z/}
validates :volunteer_team, presence: true
validates :terms_accepted, acceptance: true
validate :volunteer_teams_belong_to_conference
phony_normalize :phone, default_country_code: "BG"
@ -25,7 +24,6 @@ class Volunteer < ActiveRecord::Base
before_create :assign_unique_id
before_create :assign_confirmation_token
after_commit :send_email_confirmation_to_volunteer, on: [:create]
after_commit :send_email_to_organisers, on: [:create] # technically the volunteer's email is not confirmed yet
def send_notification_to_volunteer
VolunteerMailer.volunteer_notification(self).deliver_later
@ -49,10 +47,6 @@ class Volunteer < ActiveRecord::Base
VolunteerMailer.volunteer_email_confirmation(self).deliver_later
end
def send_email_to_organisers
VolunteerMailer.team_notification(self).deliver_later
end
def volunteer_teams_belong_to_conference
conference_volunteer_teams = conference.volunteer_teams
unless additional_volunteer_teams.all? { |team| conference_volunteer_teams.include? team }

View File

@ -1,7 +1,6 @@
class VolunteerTeam < ActiveRecord::Base
belongs_to :conference
has_many :volunteers, inverse_of: :volunteer_team
has_and_belongs_to_many :supporters, class_name: "Volunteer", inverse_of: :additional_volunteer_teams
has_and_belongs_to_many :volunteers
validates :name, presence: true
validates :color, presence: true, format: {with: /\A#?[a-f0-9]{6}\z/i}

View File

@ -1,13 +0,0 @@
json.array! @events, cached: ->(event) { [event, event.track, event.event_type] } do |event|
json.id event.id
json.title event.title
json.abstract event.abstract
json.track_id event.track_id
json.track do
json.name event.track.name
end
json.event_type do
json.name event.event_type.name
end
end

View File

@ -1,22 +0,0 @@
@halls.each do |hall|
json.set! hall.name do
json.days do
hall.slots.to_a.sort_by(&:starts_at).group_by { |slot| slot.starts_at.to_date }.each do |day, slots|
json.set! day do
json.array! slots do |slot|
next unless slot.approved_event
json.starts_at slot.starts_at
json.starts_at_human l(slot.starts_at, format: '%a, %H:%M')
json.title slot.approved_event.title
json.speakers do
json.array! slot.approved_event.participants_with_personal_profiles do |participant|
json.name participant.name
json.email participant.public_email
end
end
end
end
end
end
end
end

View File

@ -1,6 +1,6 @@
@speakers.each do |speaker|
json.set! speaker.user_id do
json.extract! speaker, :twitter, :github, :biography, :public_email, :organisation, :last_name, :first_name, :name
json.picture rails_blob_url(speaker.picture.variant(resize_to_fill: [100, 100]))
json.extract! speaker, :twitter, :github, :biography, :public_email, :organisation, :last_name, :first_name
json.picture speaker.picture.serializable_hash
end
end

View File

@ -11,5 +11,7 @@
С приложения QR код към този имейл ще можете да достъпите формуляра за обратна връзка на предложеното от Вас събитие. Моля, включете го в презентацията си.
Ако планирате да представяте отдалечено или използвате MacBook, моля, отговорете на този имейл, за да ни уведомите. Също така, ако имате въпроси или нужда от допълнителна информация, не се колебайте да се свържете с нас, като отговорите на този имейл.
Поздрави,
Екипът на <%= @event.conference.title %>

View File

@ -11,6 +11,8 @@ To confirm your participation please follow the link below as soon as you can:
We kindly request that you ensure the inclusion of the QR code attached to this email in your presentation. It links directly to the feedback form for your presentation, making it easier for attendees to provide valuable insights.
Additionally, please respond to this email to let us know whether your presentation will be remote or if you plan to present using a MacBook.
Should you have any questions or require further information, please do not hesitate to contact us by replying to this email.
Best regards,

View File

@ -20,6 +20,5 @@
= f.input :food_preferences, collection: Volunteer::FOOD_PREFERENCES, wrapper: :horizontal_radio_and_checkboxes, as: :radio_buttons, checked: (@volunteer.food_preferences.presence || :none)
= f.input :previous_experience
= f.input :notes
= f.input :terms_accepted
.panel-footer.text-right
= f.submit class: 'btn btn-primary'

View File

@ -3,7 +3,7 @@
<%- @volunteers.each do |volunteer| -%>
<%= CSV.generate_line([volunteer.id,
volunteer.name,
"#{volunteer.confirmed_at.nil? ? '(unverified) ' : ''}#{volunteer.email}",
volunteer.email,
volunteer.language,
volunteer.unique_id,
volunteer.phone,

View File

@ -48,7 +48,7 @@
h4.media-heading
= volunteer.name
p
= icon(volunteer.confirmed_at.present? ? "envelope" : "envelope-o", "#{volunteer.confirmed_at.nil? ? '(unverified) ' : ''}#{volunteer.email}")
= icon(:envelope, volunteer.email)
td
= volunteer.volunteer_team.name
td.actions

View File

@ -38,7 +38,7 @@
h4 = t '.other_info'
= icon(:language, t("locales.#{@volunteer.language}"))
br
= icon(@volunteer.confirmed_at.present? ? "envelope" : "envelope-o", @volunteer.email)
= icon(:envelope, @volunteer.email)
br
= icon(:phone, @volunteer.phone.try(:phony_formatted, format: :international))
br

View File

@ -1,11 +1,21 @@
Здравейте,
Някой изпрати кандидатура за доброволец.
<%= @volunteer.name %> <<%= @volunteer.email %>> изпрати кандидатура за доброволец.
Екип: <%= @volunteer.volunteer_team.name %>
Връзка към профил: <%= management_conference_volunteer_url(@volunteer.conference, @volunteer) %>
Екипи: <%= @volunteer.volunteer_teams.map(&:name).join(', ') %>
Език: <%= @volunteer.language %>
Телефон: <%= @volunteer.phone %>
Размер на тениска: <%= @volunteer.tshirt_size %>
Кройка на тениска: <%= @volunteer.tshirt_cut %>
Предпочитания за храна: <%= @volunteer.food_preferences %>
<% if @volunteer.previous_experience.present? -%>
Предходен опит:
<%= @volunteer.previous_experience %>
<% end -%>
<% if @volunteer.notes.present? -%>
Бележки:
<%= @volunteer.notes %>
<% end -%>

View File

@ -1,5 +0,0 @@
#!/usr/bin/env ruby
require "rubygems"
require "bundler/setup"
load Gem.bin_path("thruster", "thrust")

View File

@ -79,7 +79,7 @@ test:
#
production:
<<: *default
host: <%= ENV.fetch("CLARION_DATABASE_HOST") { "host.containers.internal" } %>
host: host.containers.internal
database: clarion
username: clarion
password: <%= ENV["CLARION_DATABASE_PASSWORD"] %>

View File

@ -39,7 +39,7 @@ set :linked_dirs, fetch(:linked_dirs, []).push("log", "tmp/uploads", "tmp/pids",
# Default value for keep_releases is 5
set :keep_releases, 550
set :rvm_ruby_version, "3.3.5"
set :rvm_ruby_version, "2.6.5"
set :puma_bind, ["tcp://127.0.0.1:9087"]
set :puma_init_active_record, true

View File

@ -46,10 +46,10 @@ Rails.application.configure do
# Assume all access to the app is happening through a SSL-terminating reverse proxy.
# Can be used together with config.force_ssl for Strict-Transport-Security and secure cookies.
config.assume_ssl = true
# config.assume_ssl = true
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = ENV["CLARION_USE_PLAINTEXT"] != "yes"
config.force_ssl = true
# Log to STDOUT by default
config.logger = ActiveSupport::Logger.new(STDOUT)
@ -90,7 +90,7 @@ Rails.application.configure do
config.action_mailer.default_options = {from: "OpenFest <cfp@openfest.org>"}
config.action_mailer.default_url_options = {host: "cfp.openfest.org"}
config.action_mailer.smtp_settings = {
address: ENV.fetch("CLARION_MAIL_SERVER", "mail.openfest.org")
address: "mail.openfest.org"
}
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to

View File

@ -118,7 +118,6 @@ bg:
food_preferences: Предпочитана храна
previous_experience: Предишен опит
notes: Бележки
terms_accepted: Съгласен съм екипът да се свързва с мен
language: Език
volunteer_team: Екип доброволци
additional_volunteer_teams: Допълнителни екипи доброволци

View File

@ -118,7 +118,6 @@ en:
food_preferences: Food preference
previous_experience: Previous experience
notes: Notes
terms_accepted: I agree to be contacted by the team
language: Language
volunteer_team: Volunteer team
additional_volunteer_teams: Additional volunteer teams

View File

@ -32,7 +32,6 @@ Rails.application.routes.draw do
resources :event_types, only: :index
resources :halls, only: :index
resources :slots, only: :index
resource :schedule, only: :show
resources :volunteers
end
end

View File

@ -1,5 +0,0 @@
class AddTermsAcceptedToVolunteer < ActiveRecord::Migration[7.1]
def change
add_column :volunteers, :terms_accepted, :boolean, default: false
end
end

View File

@ -1,5 +0,0 @@
class AddOwnerFieldToUsers < ActiveRecord::Migration[7.1]
def change
add_column :users, :owner, :boolean, null: false, default: false
end
end

View File

@ -11,5 +11,4 @@ User.create(
password_confirmation: "123qweASD",
confirmed_at: Time.current,
admin: true
owner: true
)

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +0,0 @@
services:
clarion:
build:
dockerfile: Dockerfile
context: .
environment:
RAILS_ENV: production
CLARION_DATABASE_HOST: db
CLARION_DATABASE_PASSWORD: not-a-real-db-password-tiliez4phei9oZoo1Shoyitee2zoon8O
REDIS_URL: redis://redis:6379/1
CLARION_MAIL_SERVER: mail-dummy
CLARION_USE_PLAINTEXT: yes
SECRET_KEY_BASE: not-a-real-secret-oodeig8etho1usik5Eehoh9jah9yuS3o
ports:
- 127.0.0.1:3000:3000
depends_on:
- db
- redis
- mail-dummy
db:
image: postgres:16.3
environment:
POSTGRES_USER: clarion
POSTGRES_PASSWORD: not-a-real-db-password-tiliez4phei9oZoo1Shoyitee2zoon8O
POSTGRES_DB: clarion
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7
mail-dummy:
image: python:3.11-slim
command: python3 -m smtpd --debug --class DebuggingServer 0.0.0.0:25
expose:
- 25
volumes:
pgdata:

View File

@ -22,6 +22,5 @@
= f.input :food_preferences, collection: Volunteer::FOOD_PREFERENCES, as: :radio_buttons, wrapper: :default, checked: (@volunteer.food_preferences.presence || :none)
= f.input :previous_experience
= f.input :notes
= f.input :terms_accepted
.form-actions
= f.button :submit

View File

@ -11,7 +11,6 @@ FactoryBot.define do
factory :administrator do
admin { true }
owner { true }
end
end
end