Compare commits

..

No commits in common. "master" and "maintenance" have entirely different histories.

287 changed files with 2060 additions and 6700 deletions

View File

@ -1,43 +0,0 @@
# See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files.
# Ignore git directory.
/.git/
# Ignore bundler config.
/.bundle
# Ignore all environment files (except templates).
/.env*
!/.env*.erb
# Ignore all default key files.
/config/master.key
/config/credentials/*.key
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore pidfiles, but keep the directory.
/tmp/pids/*
!/tmp/pids/.keep
# Ignore storage (uploaded files in development and any SQLite databases).
/storage/*
!/storage/.keep
/tmp/storage/*
!/tmp/storage/.keep
# Ignore assets.
/node_modules/
/app/assets/builds/*
!/app/assets/builds/.keep
/public/assets
# Archives
*.tar.gz
# SQL
*.sql

37
.gitignore vendored
View File

@ -7,29 +7,18 @@
# Ignore bundler config.
/.bundle
# Ignore all environment files (except templates).
/.env*
!/.env*.erb
# Ignore the default SQLite database.
/db/*.sqlite3
/db/*.sqlite3-journal
# Ignore all logfiles and tempfiles.
/log/*
/tmp/*
!/log/.keep
!/tmp/.keep
# Ignore pidfiles, but keep the directory.
/tmp/pids/*
!/tmp/pids/
!/tmp/pids/.keep
# Ignore storage (uploaded files in development and any SQLite databases).
/storage/*
!/storage/.keep
/tmp/storage/*
!/tmp/storage/
!/tmp/storage/.keep
/public/assets
# Ignore master key for decrypting credentials and more.
/config/master.key
/log/*.log
/tmp
/config/database.yml
/config/secrets.yml
/db/schema.rb
/erd.pdf
/public/uploads/tmp/*
/public/uploads/personal_profile/*
.sass-cache/
/coverage/

View File

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

View File

@ -1 +0,0 @@
3.3.5

View File

@ -1,16 +1,7 @@
language: ruby
dist: xenial
cache: bundler
rvm:
- 3.3
- 2.4.5
script:
- RAILS_ENV=test bundle exec rake --trace bootstrap spec
addons:
chrome: stable
apt:
packages:
- chromium-chromedriver
services:
- postgresql
before_script:
- ln -s /usr/lib/chromium-browser/chromedriver ~/bin/chromedriver
sudo: false

22
Capfile
View File

@ -1,11 +1,8 @@
# Load DSL and set up stages
require "capistrano/setup"
require 'capistrano/setup'
# Include default deployment tasks
require "capistrano/deploy"
require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git
require 'capistrano/deploy'
# Include tasks from other gems included in your Gemfile
#
@ -18,19 +15,16 @@ install_plugin Capistrano::SCM::Git
# https://github.com/capistrano/rails
# https://github.com/capistrano/passenger
#
require 'capistrano/rvm'
# require 'capistrano/rvm'
# require 'capistrano/rbenv'
# require 'capistrano/chruby'
require "capistrano/bundler"
require "capistrano/rails/assets"
require "capistrano/rails/migrations"
require "capistrano/puma"
install_plugin Capistrano::Puma # Default puma tasks
install_plugin Capistrano::Puma::Workers # if you want to control the workers (in cluster mode)
install_plugin Capistrano::Puma::Nginx # if you want to upload a nginx site template
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/puma'
# require 'capistrano/puma/nginx' # if you want to upload a nginx site template
# require 'capistrano/passenger'
# require 'capistrano/rvm'
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }

View File

@ -1,62 +0,0 @@
# syntax = docker/dockerfile:1
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile
ARG RUBY_VERSION=3.3.5
FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base
# Rails app lives here
WORKDIR /rails
# Set production environment
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development"
# Throw-away build stage to reduce size of final image
FROM base as build
# Install packages needed to build gems
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential git libvips pkg-config libpq-dev libsqlite3-dev nodejs yarn
# Install application gems
COPY Gemfile Gemfile.lock ./
RUN bundle install && \
rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \
bundle exec bootsnap precompile --gemfile
# Copy application code
COPY . .
# Precompile bootsnap code for faster boot times
RUN bundle exec bootsnap precompile app/ lib/
# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile
# Final stage for app image
FROM base
# Install packages needed for deployment
RUN apt-get update -qq && \
apt-get install --no-install-recommends -y curl libsqlite3-0 nodejs libpq5 libvips && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives
# Copy built artifacts: gems, application
COPY --from=build /usr/local/bundle /usr/local/bundle
COPY --from=build /rails /rails
# Run and own only the runtime files as a non-root user for security
RUN useradd rails --create-home --shell /bin/bash && \
chown -R rails:rails db log storage tmp
USER rails:rails
# Entrypoint prepares the database.
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"]

119
Gemfile
View File

@ -1,92 +1,95 @@
source "https://rubygems.org"
source 'https://rubygems.org'
gem "rails", "~> 7.1.0"
gem "bootsnap"
gem "sprockets"
gem 'rails', '~> 4.2.11'
gem "sqlite3"
gem "pg"
gem 'sqlite3'
gem 'pg'
gem "sass-rails"
gem 'sass-rails'
gem "uglifier"
gem "coffee-rails"
gem "jquery-rails"
gem 'uglifier'
gem 'coffee-rails'
gem 'mini_racer', platforms: :ruby
gem 'jquery-rails'
gem "slim-rails"
gem 'slim-rails'
gem "rails-i18n"
gem 'rails-i18n'
gem "devise"
gem "devise-i18n"
gem 'devise'
gem 'devise-i18n'
gem "simple_form"
gem 'simple_form'
# Phone validation
gem "phony"
gem "phony_rails"
gem 'phony_rails'
gem "puma", group: :production
# Picture uploads
gem 'carrierwave'
#gem 'rmagick'
gem "mini_magick"
gem "globalize"
gem "refile", require: ['refile/rails', 'refile/simple_form']
gem "refile-mini_magick"
gem "yaml_db"
gem 'puma', group: :production
gem "bootstrap-sass"
gem "bootstrap-sass-extras"
gem "bootswatch-rails"
gem "autoprefixer-rails"
gem "font-awesome-sass", "~> 4.6.2"
gem 'globalize'
gem "nested_form"
gem "jquery-datatables-rails"
# gem "morrisjs-rails"
gem "raphael-rails"
gem 'yaml_db'
gem "copy_carrierwave_file"
gem 'bootstrap-sass'
gem 'bootstrap-sass-extras'
gem 'bootswatch-rails'
gem 'autoprefixer-rails'
gem 'font-awesome-sass'
gem "jbuilder"
gem 'nested_form'
gem 'jquery-datatables-rails'
gem 'morrisjs-rails'
gem 'raphael-rails'
gem "search_object"
gem 'copy_carrierwave_file'
gem "faraday"
gem 'jbuilder'
gem "rqrcode"
gem 'search_object'
gem "draper"
gem 'faraday'
gem "icalendar", require: ['icalendar', 'icalendar/tzinfo']
gem 'rqrcode'
group :development do
gem "spring"
gem "spring-commands-rspec"
gem "guard-rspec" # Continuous testing with Guard
gem "rails-erd"
gem "pry-rails"
gem 'spring'
gem 'spring-commands-rspec'
gem 'guard-rspec' # Continuous testing with Guard
gem 'rails-erd'
gem 'pry-rails'
# gem 'hirb'
gem "awesome_print"
gem "better_errors"
gem "binding_of_caller"
gem 'awesome_print'
gem 'quiet_assets'
gem 'capistrano'
gem 'capistrano-rails'
# gem 'capistrano-rvm'
gem 'capistrano3-puma'
gem 'better_errors'
gem 'binding_of_caller'
end
group :development, :test do
gem "rspec-rails"
gem "faker"
gem "capybara"
gem "selenium-webdriver"
gem 'rspec-rails'
gem 'factory_girl_rails'
gem 'faker'
gem 'capybara'
gem 'selenium-webdriver'
gem "byebug"
gem "simplecov"
gem "i18n-tasks"
gem 'byebug'
gem 'simplecov'
gem 'i18n-tasks'
gem "delorean"
gem "standard"
gem 'delorean'
end
group :test do
gem "database_cleaner"
gem "factory_bot_rails"
gem 'database_cleaner'
end
gem "thruster", "~> 0.1.8"

View File

@ -1,208 +1,158 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (7.1.3)
actionpack (= 7.1.3)
activesupport (= 7.1.3)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
zeitwerk (~> 2.6)
actionmailbox (7.1.3)
actionpack (= 7.1.3)
activejob (= 7.1.3)
activerecord (= 7.1.3)
activestorage (= 7.1.3)
activesupport (= 7.1.3)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.1.3)
actionpack (= 7.1.3)
actionview (= 7.1.3)
activejob (= 7.1.3)
activesupport (= 7.1.3)
actionmailer (4.2.11)
actionpack (= 4.2.11)
actionview (= 4.2.11)
activejob (= 4.2.11)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.2)
actionpack (7.1.3)
actionview (= 7.1.3)
activesupport (= 7.1.3)
nokogiri (>= 1.8.5)
racc
rack (>= 2.2.4)
rack-session (>= 1.0.1)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
actiontext (7.1.3)
actionpack (= 7.1.3)
activerecord (= 7.1.3)
activestorage (= 7.1.3)
activesupport (= 7.1.3)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.1.3)
activesupport (= 7.1.3)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.11)
actionview (= 4.2.11)
activesupport (= 4.2.11)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (4.2.11)
activesupport (= 4.2.11)
builder (~> 3.1)
erubi (~> 1.11)
rails-dom-testing (~> 2.2)
rails-html-sanitizer (~> 1.6)
activejob (7.1.3)
activesupport (= 7.1.3)
globalid (>= 0.3.6)
activemodel (7.1.3)
activesupport (= 7.1.3)
activemodel-serializers-xml (1.0.2)
activemodel (> 5.x)
activesupport (> 5.x)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (4.2.11)
activesupport (= 4.2.11)
globalid (>= 0.3.0)
activemodel (4.2.11)
activesupport (= 4.2.11)
builder (~> 3.1)
activerecord (7.1.3)
activemodel (= 7.1.3)
activesupport (= 7.1.3)
timeout (>= 0.4.0)
activestorage (7.1.3)
actionpack (= 7.1.3)
activejob (= 7.1.3)
activerecord (= 7.1.3)
activesupport (= 7.1.3)
marcel (~> 1.0)
activesupport (7.1.3)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
ast (2.4.2)
autoprefixer-rails (10.4.16.0)
execjs (~> 2)
awesome_print (1.9.2)
base64 (0.2.0)
bcrypt (3.1.20)
better_errors (2.10.1)
erubi (>= 1.0.0)
activerecord (4.2.11)
activemodel (= 4.2.11)
activesupport (= 4.2.11)
arel (~> 6.0)
activesupport (4.2.11)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.5.2)
public_suffix (>= 2.0.2, < 4.0)
airbrussh (1.1.1)
sshkit (>= 1.6.1, != 1.7.0)
arel (6.0.4)
ast (2.3.0)
autoprefixer-rails (6.5.1)
execjs
awesome_print (1.7.0)
bcrypt (3.1.11)
better_errors (2.1.1)
coderay (>= 1.0.0)
erubis (>= 2.6.6)
rack (>= 0.9.0)
rouge (>= 1.0.0)
better_html (2.0.2)
actionview (>= 6.0)
activesupport (>= 6.0)
ast (~> 2.0)
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
bigdecimal (3.1.6)
binding_of_caller (1.0.0)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
bootsnap (1.18.3)
msgpack (~> 1.2)
bootstrap-sass (3.4.1)
bootstrap-sass (3.3.7)
autoprefixer-rails (>= 5.2.1)
sassc (>= 2.0.0)
bootstrap-sass-extras (0.1.0)
sass (>= 3.3.4)
bootstrap-sass-extras (0.0.7)
rails (>= 3.1.0)
bootswatch-rails (3.3.5)
railties (>= 3.1)
builder (3.2.4)
byebug (11.1.3)
capybara (3.40.0)
builder (3.2.3)
byebug (10.0.2)
capistrano (3.6.1)
airbrussh (>= 1.0.0)
capistrano-harrow
i18n
rake (>= 10.0.0)
sshkit (>= 1.9.0)
capistrano-bundler (1.2.0)
capistrano (~> 3.1)
sshkit (~> 1.2)
capistrano-harrow (0.5.3)
capistrano-rails (1.1.8)
capistrano (~> 3.1)
capistrano-bundler (~> 1.1)
capistrano3-puma (1.2.1)
capistrano (~> 3.0)
puma (>= 2.6)
capybara (3.10.1)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.11)
nokogiri (~> 1.8)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
regexp_parser (~> 1.2)
xpath (~> 3.2)
carrierwave (3.0.5)
activemodel (>= 6.0.0)
activesupport (>= 6.0.0)
addressable (~> 2.6)
image_processing (~> 1.1)
marcel (~> 1.0.0)
ssrf_filter (~> 1.0)
carrierwave (0.11.2)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
json (>= 1.7)
mime-types (>= 1.16)
mimemagic (>= 0.3.0)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
choice (0.2.0)
chronic (0.10.2)
chunky_png (1.4.0)
coderay (1.1.3)
coffee-rails (5.0.0)
chunky_png (1.3.8)
coderay (1.1.1)
coffee-rails (4.2.1)
coffee-script (>= 2.2.0)
railties (>= 5.2.0)
railties (>= 4.0.0, < 5.2.x)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
coffee-script-source (1.10.0)
concurrent-ruby (1.1.4)
copy_carrierwave_file (1.3.0)
carrierwave (>= 0.9)
crass (1.0.6)
database_cleaner (2.0.2)
database_cleaner-active_record (>= 2, < 3)
database_cleaner-active_record (2.1.0)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
date (3.3.4)
debug_inspector (1.2.0)
crass (1.0.4)
database_cleaner (1.7.0)
debug_inspector (0.0.2)
delorean (2.1.0)
chronic
devise (4.9.3)
devise (4.2.0)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
railties (>= 4.1.0, < 5.1)
responders
warden (~> 1.2.3)
devise-i18n (1.12.0)
devise (>= 4.9.0)
diff-lcs (1.5.1)
docile (1.4.0)
draper (4.0.2)
actionpack (>= 5.0)
activemodel (>= 5.0)
activemodel-serializers-xml (>= 1.0)
activesupport (>= 5.0)
request_store (>= 1.0)
ruby2_keywords
drb (2.2.0)
ruby2_keywords
erubi (1.12.0)
execjs (2.9.1)
factory_bot (6.4.6)
activesupport (>= 5.0.0)
factory_bot_rails (6.4.3)
factory_bot (~> 6.4)
railties (>= 5.0.0)
faker (3.2.3)
i18n (>= 1.8.11, < 2)
faraday (2.9.0)
faraday-net_http (>= 2.0, < 3.2)
faraday-net_http (3.1.0)
net-http
ffi (1.16.3)
devise-i18n (1.1.0)
diff-lcs (1.3)
docile (1.1.5)
domain_name (0.5.20160826)
unf (>= 0.0.5, < 1.0.0)
easy_translate (0.5.0)
json
thread
thread_safe
erubis (2.7.0)
execjs (2.7.0)
factory_girl (4.7.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.7.0)
factory_girl (~> 4.7.0)
railties (>= 3.0.0)
faker (1.6.6)
i18n (~> 0.5)
faraday (0.9.2)
multipart-post (>= 1.2, < 3)
ffi (1.10.0)
font-awesome-sass (4.6.2)
sass (>= 3.2)
formatador (1.1.0)
globalid (1.2.1)
activesupport (>= 6.1)
globalize (6.3.0)
activemodel (>= 4.2, < 7.2)
activerecord (>= 4.2, < 7.2)
request_store (~> 1.0)
guard (2.18.1)
formatador (0.2.5)
globalid (0.4.1)
activesupport (>= 4.2.0)
globalize (5.0.1)
activemodel (>= 4.2.0, < 4.3)
activerecord (>= 4.2.0, < 4.3)
guard (2.14.0)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
lumberjack (>= 1.0.12, < 2.0)
lumberjack (~> 1.0)
nenv (~> 0.1)
notiffany (~> 0.0)
pry (>= 0.13.0)
pry (>= 0.9.12)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-compat (1.2.1)
@ -210,309 +160,241 @@ GEM
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
highline (3.0.1)
i18n (1.14.1)
highline (1.7.8)
http-cookie (1.0.3)
domain_name (~> 0.5)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
i18n-tasks (1.0.13)
i18n-tasks (0.9.5)
activesupport (>= 4.0.2)
ast (>= 2.1.0)
better_html (>= 1.0, < 3.0)
erubi
highline (>= 2.0.0)
easy_translate (>= 0.5.0)
erubis
highline (>= 1.7.3)
i18n
parser (>= 3.2.2.1)
rails-i18n
rainbow (>= 2.2.2, < 4.0)
parser (>= 2.2.3.0)
term-ansicolor (>= 1.3.2)
terminal-table (>= 1.5.1)
icalendar (2.10.1)
ice_cube (~> 0.16)
ice_cube (0.16.4)
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
io-console (0.7.2)
irb (1.11.2)
rdoc
reline (>= 0.4.2)
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jbuilder (2.6.0)
activesupport (>= 3.0.0, < 5.1)
multi_json (~> 1.2)
jquery-datatables-rails (3.4.0)
actionpack (>= 3.1)
jquery-rails
railties (>= 3.1)
sass-rails
jquery-rails (4.6.0)
jquery-rails (4.2.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
json (2.7.1)
language_server-protocol (3.17.0.3)
lint_roller (1.1.0)
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.22.0)
json (2.1.0)
libv8 (6.7.288.46.1)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
lumberjack (1.2.10)
mail (2.8.1)
nokogiri (>= 1.5.9)
lumberjack (1.0.10)
mail (2.7.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.2)
matrix (0.4.2)
method_source (1.0.0)
mini_magick (4.12.0)
mini_mime (1.1.5)
mini_portile2 (2.8.5)
minitest (5.22.2)
msgpack (1.7.2)
mutex_m (0.2.0)
method_source (0.8.2)
mime-types (2.99.3)
mimemagic (0.3.2)
mini_magick (4.5.1)
mini_mime (1.0.1)
mini_portile2 (2.4.0)
mini_racer (0.2.4)
libv8 (>= 6.3)
minitest (5.11.3)
morrisjs-rails (0.5.1)
railties (> 3.1, < 5)
multi_json (1.12.1)
multipart-post (2.0.0)
nenv (0.3.0)
nested_form (0.3.2)
net-http (0.4.1)
uri
net-imap (0.4.10)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.2)
timeout
net-smtp (0.4.0.1)
net-protocol
nio4r (2.7.0)
nokogiri (1.16.2)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
notiffany (0.1.3)
net-scp (1.2.1)
net-ssh (>= 2.6.5)
net-ssh (3.2.0)
netrc (0.11.0)
nokogiri (1.10.0)
mini_portile2 (~> 2.4.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
orm_adapter (0.5.0)
parallel (1.24.0)
parser (3.3.0.5)
ast (~> 2.4.1)
racc
pg (1.5.5)
phony (2.20.12)
phony_rails (0.15.0)
parser (2.3.1.4)
ast (~> 2.2)
pg (0.19.0)
phony (2.15.32)
phony_rails (0.14.4)
activesupport (>= 3.0)
phony (>= 2.18.12)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-rails (0.3.9)
pry (>= 0.10.4)
psych (5.1.2)
stringio
public_suffix (5.0.4)
puma (6.4.2)
nio4r (~> 2.0)
racc (1.7.3)
rack (3.0.9)
rack-session (2.0.0)
rack (>= 3.0.0)
rack-test (2.1.0)
rack (>= 1.3)
rackup (2.1.0)
rack (>= 3)
webrick (~> 1.8)
rails (7.1.3)
actioncable (= 7.1.3)
actionmailbox (= 7.1.3)
actionmailer (= 7.1.3)
actionpack (= 7.1.3)
actiontext (= 7.1.3)
actionview (= 7.1.3)
activejob (= 7.1.3)
activemodel (= 7.1.3)
activerecord (= 7.1.3)
activestorage (= 7.1.3)
activesupport (= 7.1.3)
bundler (>= 1.15.0)
railties (= 7.1.3)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-erd (1.7.2)
activerecord (>= 4.2)
activesupport (>= 4.2)
phony (~> 2.15)
pry (0.10.4)
coderay (~> 1.1.0)
method_source (~> 0.8.1)
slop (~> 3.4)
pry-rails (0.3.4)
pry (>= 0.9.10)
public_suffix (3.0.3)
puma (3.10.0)
quiet_assets (1.1.0)
railties (>= 3.1, < 5.0)
rack (1.6.11)
rack-protection (1.5.5)
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.2.11)
actionmailer (= 4.2.11)
actionpack (= 4.2.11)
actionview (= 4.2.11)
activejob (= 4.2.11)
activemodel (= 4.2.11)
activerecord (= 4.2.11)
activesupport (= 4.2.11)
bundler (>= 1.3.0, < 2.0)
railties (= 4.2.11)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.9)
activesupport (>= 4.2.0, < 5.0)
nokogiri (~> 1.6)
rails-deprecated_sanitizer (>= 1.0.1)
rails-erd (1.5.0)
activerecord (>= 3.2)
activesupport (>= 3.2)
choice (~> 0.2.0)
ruby-graphviz (~> 1.2)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
rails-i18n (7.0.8)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 8)
railties (7.1.3)
actionpack (= 7.1.3)
activesupport (= 7.1.3)
irb
rackup (>= 1.0.0)
rake (>= 12.2)
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.1.0)
rails-html-sanitizer (1.0.4)
loofah (~> 2.2, >= 2.2.2)
rails-i18n (4.0.9)
i18n (~> 0.7)
railties (~> 4.0)
railties (4.2.11)
actionpack (= 4.2.11)
activesupport (= 4.2.11)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (12.3.2)
raphael-rails (2.1.2)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rdoc (6.6.2)
psych (>= 4.0.0)
regexp_parser (2.9.0)
reline (0.4.2)
io-console (~> 0.5)
request_store (1.6.0)
rack (>= 1.4)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
rexml (3.2.6)
rouge (4.2.0)
rqrcode (2.2.0)
rb-fsevent (0.9.7)
rb-inotify (0.9.7)
ffi (>= 0.5.0)
refile (0.6.2)
mime-types
rest-client (~> 1.8)
sinatra (~> 1.4.5)
refile-mini_magick (0.2.0)
mini_magick (~> 4.0)
refile (~> 0.5)
regexp_parser (1.2.0)
responders (2.3.0)
railties (>= 4.2.0, < 5.1)
rest-client (1.8.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 3.0)
netrc (~> 0.7)
rqrcode (0.10.1)
chunky_png (~> 1.0)
rqrcode_core (~> 1.0)
rqrcode_core (1.2.0)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.0)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (6.1.1)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.12)
rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12)
rspec-support (~> 3.12)
rspec-support (3.13.0)
rubocop (1.60.2)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.30.0)
parser (>= 3.2.1.0)
rubocop-performance (1.20.2)
rubocop (>= 1.48.1, < 2.0)
rubocop-ast (>= 1.30.0, < 2.0)
ruby-graphviz (1.2.5)
rexml
ruby-progressbar (1.13.0)
ruby-vips (2.2.0)
ffi (~> 1.12)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sass-rails (6.0.0)
sassc-rails (~> 2.1, >= 2.1.1)
sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
railties (>= 4.0.0)
sassc (>= 2.0)
sprockets (> 3.0)
sprockets-rails
tilt
search_object (1.2.5)
selenium-webdriver (4.18.1)
base64 (~> 0.2)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
rspec-support (~> 3.5.0)
rspec-rails (3.5.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
ruby-graphviz (1.2.2)
ruby_dep (1.5.0)
rubyzip (1.2.2)
sass (3.4.22)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
search_object (1.1.1)
selenium-webdriver (3.141.0)
childprocess (~> 0.5)
rubyzip (~> 1.2, >= 1.2.2)
shellany (0.0.1)
simple_form (5.3.0)
actionpack (>= 5.2)
activemodel (>= 5.2)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov_json_formatter (0.1.4)
slim (5.2.1)
temple (~> 0.10.0)
tilt (>= 2.1.0)
slim-rails (3.6.3)
simple_form (3.3.1)
actionpack (> 4, < 5.1)
activemodel (> 4, < 5.1)
simplecov (0.12.0)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
sinatra (1.4.7)
rack (~> 1.5)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
slim (3.0.7)
temple (~> 0.7.6)
tilt (>= 1.3.3, < 2.1)
slim-rails (3.1.1)
actionpack (>= 3.1)
railties (>= 3.1)
slim (>= 3.0, < 6.0, != 5.0.0)
smart_properties (1.17.0)
spring (4.1.3)
slim (~> 3.0)
slop (3.6.0)
spring (2.0.0)
activesupport (>= 4.2)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
sprockets (4.2.1)
sprockets (3.7.2)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
rack (> 1, < 3)
sprockets-rails (3.2.1)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.7.2)
mini_portile2 (~> 2.8.0)
ssrf_filter (1.1.2)
standard (1.34.0)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.0)
rubocop (~> 1.60)
standard-custom (~> 1.0.0)
standard-performance (~> 1.3)
standard-custom (1.0.2)
lint_roller (~> 1.0)
rubocop (~> 1.50)
standard-performance (1.3.1)
lint_roller (~> 1.1)
rubocop-performance (~> 1.20.2)
stringio (3.1.0)
temple (0.10.3)
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)
concurrent-ruby (~> 1.0)
uglifier (4.2.0)
sqlite3 (1.3.12)
sshkit (1.11.3)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
temple (0.7.7)
term-ansicolor (1.4.0)
tins (~> 1.0)
terminal-table (1.7.3)
unicode-display_width (~> 1.1.1)
thor (0.20.3)
thread (0.2.2)
thread_safe (0.3.6)
tilt (2.0.5)
tins (1.12.0)
tzinfo (1.2.5)
thread_safe (~> 0.1)
uglifier (3.0.2)
execjs (>= 0.3.0, < 3)
unicode-display_width (2.5.0)
uri (0.13.0)
warden (1.2.9)
rack (>= 2.0.9)
webrick (1.8.1)
websocket (1.2.10)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.2)
unicode-display_width (1.1.1)
warden (1.2.6)
rack (>= 1.0)
xpath (3.2.0)
nokogiri (~> 1.8)
yaml_db (0.7.0)
rails (>= 3.0)
yaml_db (0.4.2)
rails (>= 3.0, < 5.1)
rake (>= 0.8.7)
zeitwerk (2.6.13)
PLATFORMS
ruby
@ -522,40 +404,46 @@ DEPENDENCIES
awesome_print
better_errors
binding_of_caller
bootsnap
bootstrap-sass
bootstrap-sass-extras
bootswatch-rails
byebug
capistrano
capistrano-rails
capistrano3-puma
capybara
carrierwave
coffee-rails
copy_carrierwave_file
database_cleaner
delorean
devise
devise-i18n
draper
factory_bot_rails
factory_girl_rails
faker
faraday
font-awesome-sass (~> 4.6.2)
font-awesome-sass
globalize
guard-rspec
i18n-tasks
icalendar
jbuilder
jquery-datatables-rails
jquery-rails
mini_magick
mini_racer
morrisjs-rails
nested_form
pg
phony
phony_rails
pry-rails
puma
rails (~> 7.1.0)
quiet_assets
rails (~> 4.2.11)
rails-erd
rails-i18n
raphael-rails
refile
refile-mini_magick
rqrcode
rspec-rails
sass-rails
@ -566,12 +454,9 @@ DEPENDENCIES
slim-rails
spring
spring-commands-rspec
sprockets
sqlite3
standard
thruster (~> 0.1.8)
uglifier
yaml_db
BUNDLED WITH
2.5.6
1.17.1

View File

@ -1,20 +1,18 @@
# More info at https://github.com/guard/guard#readme
guard :rspec, cmd: "spring rspec" do
guard :rspec, cmd: 'spring rspec' do
watch(%r{^spec/.+_spec\.rb$})
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
watch("spec/spec_helper.rb") { "spec" }
watch("spec/rails_helper.rb") { "spec" }
watch('spec/spec_helper.rb') { 'spec' }
watch('spec/rails_helper.rb') { 'spec' }
watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
watch("config/routes.rb") { "spec/routing" }
watch("app/controllers/application_controller.rb") { "spec/controllers" }
watch(%r{^spec/support/(.+)\.rb$}) { 'spec' }
watch('config/routes.rb') { 'spec/routing' }
watch('app/controllers/application_controller.rb') { 'spec/controllers' }
# Capybara features specs
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
notification :off
end

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

@ -1,6 +1,6 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path("../config/application", __FILE__)
require File.expand_path('../config/application', __FILE__)
Rails.application.load_tasks

15
TODO
View File

@ -1,14 +1,14 @@
- User-facing:
- # Event proposal: lecture, workshop, open space (CRUD)
- # Volunteership
- Event proposal: lecture, workshop, open space (CRUD)
- Volunteership
- Sponsorship
- Admin:
- # Create a conference, halls, tracks
- # Starting a CFP
- # conferences#show -> admin dashboard
- # volunteers#index -> approved volunteers
- # sponsorships#index -> generate token, links to send around
- volunteers#index -> approved volunteers
- sponsorships#index -> generate token, links to send around
- scheduling -> calendar with events
- # proposals#index -> undecided events, grouped by user
@ -17,11 +17,12 @@
- users:
- # edit profile: image upload and stuff
- # show profile
- # Edit profiles instead
- Edit profiles instead
- # Home-area user CRUD
- Home-area user CRUD
- # Controller before_action that checks for current_conference
- # Devise view styling
- Devise view styling
Notes:
- .row > .col-lg-12 -> put that outside of the "yield"?
- human_attribute_name -> create a short alias?

View File

@ -1,6 +0,0 @@
//= link_tree ../images
//= link_tree ../../../lib/initfest/assets/images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
//= link initfest/application.css
//= link initfest/application.js

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
height="665"
width="1185"
id="svg4"
version="1.1"
viewBox="0 0 1185 665"
role="img"
class="svg-inline--fa fa-user-secret fa-w-14"
data-icon="user-secret"
data-prefix="fas"
focusable="false"
aria-hidden="true">
<metadata
id="metadata10">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs8" />
<path
style="fill:currentColor"
id="path2"
d="m 752.4,384.79271 23.9,-62.6 c 4,-10.5 -3.7,-21.7 -15,-21.7 h -58.5 c 11,-18.9 17.8,-40.6 17.8,-64 v -0.3 c 39.2,-7.8 64,-19.1 64,-31.7 0,-13.3 -27.3,-25.1 -70.1,-33 -9.2,-32.8 -27,-65.8 -40.6,-82.799998 -9.5,-11.9 -25.9,-15.6 -39.5,-8.8 l -27.6,13.8 c -9,4.5 -19.6,4.5 -28.6,0 l -27.6,-13.8 c -13.6,-6.8 -30,-3.1 -39.5,8.8 -13.5,16.999998 -31.4,49.999998 -40.6,82.799998 -42.7,7.9 -70,19.7 -70,33 0,12.6 24.8,23.9 64,31.7 v 0.3 c 0,23.4 6.8,45.1 17.8,64 h -57.5 c -11.5,0 -19.2,11.7 -14.7,22.3 l 25.8,60.2 c -40.1,23.3 -67.4,66.2 -67.4,115.9 v 44.8 c 0,24.7 20.1,44.8 44.8,44.8 h 358.4 c 24.7,0 44.8,-20.1 44.8,-44.8 v -44.8 c 0,-48.4 -25.8,-90.4 -64.1,-114.1 z m -207.9,171.7 -41.6,-192 49.6,32 24,40 z m 96,0 -32,-120 24,-40 49.6,-32 z m 41.7,-298.5 c -3.9,11.9 -7,24.6 -16.5,33.4 -10.1,9.3 -48,22.4 -64,-25 -2.8,-8.4 -15.4,-8.4 -18.3,0 -17,50.2 -56,32.4 -64,25 -9.5,-8.8 -12.7,-21.5 -16.5,-33.4 -0.8,-2.5 -6.3,-5.7 -6.3,-5.8 v -10.8 c 28.3,3.6 61,5.8 96,5.8 35,0 67.7,-2.1 96,-5.8 v 10.8 c -0.1,0.1 -5.6,3.2 -6.4,5.8 z" />
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -3,5 +3,6 @@
//= require jquery_nested_form
//= require bootstrap-sprockets
//= require raphael
//= require morris
//= require chroma-js/chroma
//= require_directory .

View File

@ -22,10 +22,6 @@ th.action, td.action {
}
}
th.main {
width: 100%;
}
.conference-title {
display: inline-block;
@include button-size($padding-base-vertical, $padding-base-horizontal, $font-size-base, $line-height-base, $btn-border-radius-base);

View File

@ -1,10 +1,24 @@
.panel .panel-image img {
display: block;
max-width: 100%;
max-height: 250px;
height: auto;
margin-right: auto;
margin-left: auto;
width: 100%;
object-fit: cover;
.speaker-profile {
@extend .col-sm-offset-2;
@extend .col-sm-8;
.center {
text-align: center;
}
.profile-image {
@extend .img-thumbnail;
max-width: 171px;
max-height: 180px;
}
.social {
@extend .btn-group;
margin-top: 10px;
a {
@extend .btn;
@extend .btn-default;
}
}
}

View File

@ -6,7 +6,7 @@
@import "bootstrap";
@import "bootswatch/simplex/bootswatch";
/* @import "morris"; */
@import "morris";
@import "users";
@import "colors";
@ -19,4 +19,4 @@
& > div {
display: inline-block;
}
}
}

View File

@ -1,8 +0,0 @@
class Api::ConferencesController < Api::ApplicationController
include ::PublicApiExposing
def index
@conferences = Conference.all
fresh_when @conferences
end
end

View File

@ -1,10 +1,9 @@
class Api::EventTypesController < Api::ApplicationController
include ::CurrentConferenceAssigning
include ::PublicApiExposing
before_action :require_current_conference!
before_filter :require_current_conference!
def index
@event_types = current_conference.event_types.includes(:translations)
fresh_when @event_types
end
end

View File

@ -1,13 +1,14 @@
class Api::EventsController < Api::ApplicationController
include ::CurrentConferenceAssigning
include ::PublicApiExposing
before_action :require_current_conference!
before_filter :require_current_conference!
def index
@events = current_conference.events.approved.joins(:proposition).includes(:participations)
end
def halfnarp_friendly
@events = current_conference.events.joins(:proposition).includes(:track, :event_type).where.not(propositions: {status: :rejected})
@events = current_conference.events.includes(:track, :event_type)
render json: @events, include: [:track, :event_type]
end
end

View File

@ -1,10 +1,9 @@
class Api::HallsController < Api::ApplicationController
include ::CurrentConferenceAssigning
include ::PublicApiExposing
before_action :require_current_conference!
before_filter :require_current_conference!
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

@ -1,11 +1,9 @@
class Api::SlotsController < Api::ApplicationController
include ::CurrentConferenceAssigning
include ::PublicApiExposing
before_action :require_current_conference!
before_filter :require_current_conference!
def index
@slots = current_conference.slots
fresh_when @slots
end
end

View File

@ -1,10 +1,9 @@
class Api::SpeakersController < Api::ApplicationController
include ::CurrentConferenceAssigning
include ::PublicApiExposing
before_action :require_current_conference!
before_filter :require_current_conference!
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

@ -1,10 +1,9 @@
class Api::TracksController < Api::ApplicationController
include ::CurrentConferenceAssigning
include ::PublicApiExposing
before_action :require_current_conference!
before_filter :require_current_conference!
def index
@tracks = current_conference.tracks.includes(:translations)
fresh_when @tracks
end
end

View File

@ -4,15 +4,15 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
before_filter :configure_permitted_parameters, if: :devise_controller?
before_action :set_locale
before_action :set_view_paths
# TODO: make this get the domain from the database
# layout Proc.new { |controller| controller.request.host }
layout "public/application"
#layout Proc.new { |controller| controller.request.host }
layout 'public/application'
def self.default_url_options(options = {})
def self.default_url_options(options={})
if I18n.locale != I18n.default_locale
options.merge({locale: I18n.locale})
else
@ -24,17 +24,17 @@ class ApplicationController < ActionController::Base
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
if user_signed_in? && (current_user.language != I18n.locale)
if user_signed_in? and current_user.language != I18n.locale
current_user.update(language: I18n.locale)
end
end
def set_view_paths
# 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 =~ /openfest/
prepend_view_path 'lib/initfest/views' if request.host =~ /example/
prepend_view_path 'lib/initfest/views' if request.host =~ /127\.0\.0/
end
protected

View File

@ -11,8 +11,8 @@ module CurrentConferenceAssigning
end
def current_conference
unless @current_conference
if @conference && !@conference.new_record?
if not @current_conference
if @conference and not @conference.new_record?
@current_conference = @conference
elsif params[:conference_id].present?
@current_conference = Conference.find(params[:conference_id])
@ -23,8 +23,8 @@ module CurrentConferenceAssigning
end
def require_current_conference!
unless current_conference?
raise ActionController::RoutingError.new("Not Found")
if not current_conference?
raise ActionController::RoutingError.new('Not Found')
end
end
end

View File

@ -1,14 +1,14 @@
require "active_support/concern"
require 'active_support/concern'
module PublicApiExposing
extend ActiveSupport::Concern
def set_access_control_headers
if request.format.json?
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers['Access-Control-Allow-Origin'] = '*'
end
end
included do
before_action :set_access_control_headers
end

View File

@ -6,9 +6,9 @@ class ConfirmationsController < Devise::ConfirmationsController
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_flashing_format?
sign_in(resource_name, resource)
respond_with_navigational(resource) { redirect_to after_confirmation_path_for(resource_name, resource) }
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, status: :unprocessable_entity) { render :new }
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
end
end
end

View File

@ -2,12 +2,12 @@ module Management
class CallForParticipationsController < ManagementController
def create
current_conference.call_for_participation.open!
redirect_back fallback_location: [:management, current_conference]
redirect_to :back
end
def destroy
current_conference.call_for_participation.close!
redirect_back fallback_location: [:management, current_conference]
redirect_to :back
end
end
end

View File

@ -2,10 +2,10 @@ module Management
class ConferencesController < ManagementController
def new
@conference = Conference.new
@conference.event_types.build(name: "Event type 1")
@conference.tracks.build(name: "Track 1")
@conference.halls.build(name: "Hall 1")
@conference.volunteer_teams.build(name: "Volunteer Team 1")
@conference.event_types.build(name: 'Event type 1')
@conference.tracks.build(name: 'Track 1')
@conference.halls.build(name: 'Hall 1')
@conference.volunteer_teams.build(name: 'Volunteer Team 1')
end
def create
@ -49,13 +49,13 @@ module Management
begin
if @conference.update_vote_data!
flash[:notice] = t(".vote_data_successfully_updated")
flash[:notice] = t('.vote_data_successfully_updated')
else
flash[:alert] = t(".error_during_vote_data_save")
flash[:alert] = t('.error_during_vote_data_save')
end
redirect_back fallback_location: [:management, @conference]
rescue => e
flash[:alert] = t(".error_during_connection_with_voting_endpoint", error: e.message)
redirect_to :back
rescue StandardError => e
flash[:alert] = t('.error_during_connection_with_voting_endpoint', error: e.message)
render :vote_results
end
end
@ -75,9 +75,9 @@ module Management
:title, :email, :start_date, :end_date, :description, :host_name,
:planned_cfp_end_date, :vote_data_endpoint,
event_types_attributes: [:id, :name, :description, :maximum_length,
:minimum_length, :_destroy,],
:minimum_length, :_destroy],
tracks_attributes: [:id, :name, :color, :css_class, :description,
:css_style, :foreground_color, :_destroy,],
:css_style, :foreground_color, :_destroy],
halls_attributes: [:id, :name, :_destroy],
volunteer_teams_attributes: [:id, :name, :description, :color, :_destroy]
)

View File

@ -2,15 +2,8 @@ module Management
class EventsController < ManagementController
def index
@conference = find_conference
@filters = filter_params || {}
@events = EventSearch
.new(scope: Event.where(conference: @conference)
.eager_load(:participants_with_personal_profiles,
:proposition, :proposer, {track: [:translations]},
{event_type: [:translations]}, :feedbacks)
.preload(:conference), filters: params[:filters]).results
@filters = params[:filters] || {}
@events = EventSearch.new(scope: Event.where(conference: @conference).eager_load(:participants_with_personal_profiles, :proposition, :proposer, :track, :event_type).preload(:conference), filters: params[:filters]).results
# @events = @conference.events.order(:title).includes(:proposition, :proposer, :track, :event_type)
end
@ -29,10 +22,10 @@ module Management
@event = @conference.events.find(params[:id])
if @event.update(event_params)
flash[:notice] = t(".event_successfully_updated")
flash[:notice] = 'Event was successfully updated.'
redirect_to [:management, @conference, @event]
else
render action: "edit"
render action: 'edit'
end
end
@ -53,38 +46,27 @@ module Management
private
def find_conference
Conference.eager_load({tracks: :translations}, {event_types: :translations}).find(params[:conference_id])
end
def filter_params
params.fetch(:filters, {}).permit(
:event_type_id,
:track_id,
:language,
:status,
:confirmed,
:not_confirmed,
)
Conference.find(params[:conference_id])
end
def event_params
params.require(:event).permit(
:title,
:subtitle,
:length,
:language,
:abstract,
:description,
:notes,
:track_id,
:event_type_id,
participations_attributes: [
:id,
:participant_id,
:approved,
:_destroy,
]
)
:title,
:subtitle,
:length,
:language,
:abstract,
:description,
:notes,
:track_id,
:event_type_id,
participations_attributes: [
:id,
:participant_id,
:approved,
:_destroy
]
)
end
end
end

View File

@ -1,13 +0,0 @@
module Management
class FeedbackController < ManagementController
def index
@conference = find_conference
end
private
def find_conference
Conference.find(params[:conference_id])
end
end
end

View File

@ -1,18 +1,14 @@
require "csv"
require 'csv'
module Management
class ManagementController < ::ApplicationController
before_action :authenticate_user!, :authorize_user!
layout "management"
layout '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
head :forbidden unless current_user.admin?
end
end
end

View File

@ -10,7 +10,7 @@ module Management
@user = find_profile.user
@user.toggle_admin!
redirect_back fallback_location: {action: :show}
redirect_to :back
end
def show
@ -18,7 +18,7 @@ module Management
@profile = find_profile
@user = @profile.user
unless @profile
if not @profile
flash[:error] = "No profile, needs to be created"
redirect_to action: :edit
end
@ -36,7 +36,7 @@ module Management
@profile = @user.build_personal_profile(@conference, profile_params)
if @profile.save
flash[:notice] = t(".successfully_created")
flash[:notice] = t('.successfully_created')
redirect_to management_conference_personal_profile_path(@profile, conference_id: @conference.id)
else
render action: :new
@ -53,10 +53,10 @@ module Management
@conference = find_conference
@profile = find_profile
if @profile.update(profile_params)
if @profile.update_attributes(profile_params)
redirect_to [:management, @conference, @profile]
else
render action: "edit"
render action: 'edit'
end
end

View File

@ -10,7 +10,7 @@ module Management
@proposition.update(proposition_params)
redirect_back fallback_location: [:management, current_conference, @proposition]
redirect_to :back
end
private

View File

@ -3,8 +3,8 @@ module Management
include CurrentConferenceAssigning
def index
@filters = filter_params || {}
@volunteers = VolunteerSearch.new(scope: Volunteer.where(conference: current_conference).eager_load(:volunteer_team), filters: params[:filters]).results
@filters = params[:filters] || {}
@volunteers = VolunteerSearch.new(scope: Volunteer.where(conference: current_conference).eager_load(:volunteer_teams), filters: params[:filters]).results
end
def show
@ -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])
@ -32,18 +26,12 @@ module Management
end
private
def filter_params
params.fetch(:filters, {}).permit(:volunteer_team_id)
end
def volunteer_params
params.require(:volunteer).permit(:name, :picture, :email, :phone,
:tshirt_size, :tshirt_cut,
:food_preferences, :previous_experience,
:notes, :language, :terms_accepted,
:volunteer_team_id,
additional_volunteer_team_ids: [])
:tshirt_size, :tshirt_cut,
:food_preferences, :previous_experience,
:notes, :language,
volunteer_team_ids: [])
end
end
end

View File

@ -1,7 +1,7 @@
module Public
class ApplicationController < ::ApplicationController
include ::CurrentConferenceAssigning
before_action :require_current_conference!
before_filter :require_current_conference!
def current_conference
@current_conference ||= Conference.order(created_at: :desc).find_by(host_name: request.host)

View File

@ -2,32 +2,33 @@ class Public::ConferenceFeedbacksController < Public::ApplicationController
def index
@conference = current_conference
@unrated_events = @conference.events
.joins(:proposition).approved
.joins("LEFT JOIN feedbacks ON feedbacks.feedback_receiving_id = events.id AND feedbacks.feedback_receiving_type = 'Event'")
.where("feedbacks.session_id != ? OR feedbacks.id IS NULL", session.id.to_s).distinct
.joins(:proposition).approved
.joins('LEFT JOIN feedbacks ON feedbacks.feedback_receiving_id = events.id AND feedbacks.feedback_receiving_type = \'Event\'')
.where('feedbacks.session_id != ? OR feedbacks.id IS NULL', session.id).distinct
@rated_events = @conference.events
.joins(:proposition).approved
.joins(:feedbacks)
.where(feedbacks: {session_id: session.id.to_s}).distinct
.joins(:proposition).approved
.joins(:feedbacks)
.where(feedbacks: {session_id: session.id}).distinct
end
def new
if current_conference.feedbacks.where(session_id: session.id.to_s).exists?
@feedback = current_conference.feedbacks.where(session_id: session.id.to_s).order(updated_at: :asc).last
if current_conference.feedbacks.where(session_id: session.id).exists?
@feedback = current_conference.feedbacks.where(session_id: session.id).order(updated_at: :asc).last
else
@feedback = current_conference.feedbacks.build
@feedback.author_email = Feedback.where(session_id: session.id.to_s).order(updated_at: :asc).last.try(:author_email)
@feedback.author_email = Feedback.where(session_id: session.id).order(updated_at: :asc).last.try(:author_email)
end
end
def create
@feedback = current_conference.feedbacks.build(feedback_params)
@feedback.ip_address = request.remote_ip
@feedback.session_id = session.id.to_s
@feedback.session_id = session.id
if @feedback.save
flash[:notice] = I18n.t("public.conference_feedbacks.new.success")
flash[:notice] = I18n.t('public.conference_feedbacks.new.success')
redirect_to conference_feedbacks_path
else
render :new, status: :unprocessable_entity

View File

@ -1,10 +1,11 @@
class Public::EventFeedbackQrcodesController < Public::ApplicationController
def show
event = current_conference.events.joins(:proposition).approved.find(params[:event_id]).decorate
event = current_conference.events.joins(:proposition).approved.find(params[:event_id])
@qr = RQRCode::QRCode.new(new_event_feedback_url(event_id: event.id), level: :l)
respond_to do |format|
format.svg do
render(inline: event.feedback_qr_code_as_svg,
render(inline: @qr.as_svg(shape_rendering: 'crispEdges', module_size: 11, fill: 'ffffff', offset: 10),
filename: "feedback_qr_code_#{event.id}.svg")
end
end

View File

@ -1,20 +1,20 @@
class Public::EventFeedbacksController < Public::ApplicationController
def new
if event.feedbacks.where(session_id: session.id.to_s).exists?
@feedback = event.feedbacks.where(session_id: session.id.to_s).order(updated_at: :asc).last
if event.feedbacks.where(session_id: session.id).exists?
@feedback = event.feedbacks.where(session_id: session.id).order(updated_at: :asc).last
else
@feedback = event.feedbacks.build
@feedback.author_email = Feedback.where(session_id: session.id.to_s).order(updated_at: :asc).last.try(:author_email)
@feedback.author_email = Feedback.where(session_id: session.id).order(updated_at: :asc).last.try(:author_email)
end
end
def create
@feedback = event.feedbacks.build(feedback_params)
@feedback.ip_address = request.remote_ip
@feedback.session_id = session.id.to_s
@feedback.session_id = session.id
if @feedback.save
flash[:notice] = I18n.t("public.event_feedbacks.new.success")
flash[:notice] = I18n.t('public.event_feedbacks.new.success')
redirect_to conference_feedbacks_path
else
render :new, status: :unprocessable_entity

View File

@ -1,9 +1,9 @@
module Public
class EventsController < Public::ApplicationController
before_action :authenticate_user!
before_filter :authenticate_user!
def index
@events = Event.joins(:conference, :proposition, :participations).where(conference: current_conference).where("propositions.proposer_id = ? OR participations.participant_id = ?", current_user.id, current_user.id)
@events = Event.joins(:conference, :proposition, :participations).where(conference: current_conference).where('propositions.proposer_id = ? OR participations.participant_id = ?', current_user.id, current_user.id)
end
def edit
@ -22,7 +22,7 @@ module Public
@event.participations.build participant: current_user, approved: true
if @event.save
flash[:notice] = I18n.t("views.events.event_successfully_created", event_type: @event.event_type.name.mb_chars.downcase)
flash[:notice] = I18n.t('views.events.event_successfully_created', event_type: @event.event_type.name.mb_chars.downcase)
after_save_redirect
else
render action: :new
@ -33,7 +33,7 @@ module Public
@event = Event.joins(:participations).find_by(id: params[:id], participations: {participant_id: current_user.id})
if @event.update(event_params)
flash[:notice] = I18n.t("views.events.event_successfully_updated", event_type: @event.event_type.name.mb_chars.downcase)
flash[:notice] = I18n.t('views.events.event_successfully_updated', event_type: @event.event_type.name.mb_chars.downcase)
after_save_redirect
else
render action: :edit
@ -44,9 +44,9 @@ module Public
@event = current_user.events.approved.find(params[:id])
if @event.confirm!
flash[:notice] = I18n.t("views.events.successfully_confirmed", event_type: @event.event_type.name.mb_chars.downcase)
flash[:notice] = I18n.t('views.events.successfully_confirmed', event_type: @event.event_type.name.mb_chars.downcase)
else
flash[:alert] = I18n.t("views.events.error_on_confirmation", event_type: @event.event_type.name.mb_chars.downcase)
flash[:alert] = I18n.t('views.events.error_on_confirmation', event_type: @event.event_type.name.mb_chars.downcase)
end
after_save_redirect

View File

@ -1,12 +1,12 @@
module Public
class PersonalProfilesController < Public::ApplicationController
before_action :authenticate_user!
before_filter :authenticate_user!
def create
@profile = current_user.build_personal_profile(current_conference, profile_params)
if @profile.save
flash[:notice] = t("views.personal_profiles.successfully_created")
flash[:notice] = t('views.personal_profiles.successfully_created')
redirect_to root_path
else
render action: :new
@ -20,11 +20,11 @@ module Public
def update
@profile = current_user.personal_profile(current_conference)
if @profile.update(profile_params)
flash[:notice] = t("views.personal_profiles.successfully_updated")
if @profile.update_attributes(profile_params)
flash[:notice] = t('views.personal_profiles.successfully_updated')
redirect_to root_path
else
render action: "edit"
render action: 'edit'
end
end

View File

@ -1,20 +0,0 @@
module Public
class VolunteerConfirmationsController < Public::ApplicationController
def create
@volunteer = Volunteer.find_by!(unique_id: params[:id])
if ActiveSupport::SecurityUtils.secure_compare(@volunteer.confirmation_token, params[:confirmation_token])
@volunteer.transaction do
@volunteer.touch(:confirmed_at)
@volunteer.update(confirmation_token: nil)
end
@volunteer.send_notification_to_volunteer
redirect_to edit_volunteer_path(@volunteer.unique_id), notice: I18n.t("views.volunteers.email_confirmed_successfully")
else
redirect_to root_path, alert: I18n.t("views.volunteers.email_confirmation_error")
end
end
end
end

View File

@ -1,6 +1,5 @@
module Public
class VolunteersController < Public::ApplicationController
before_action :check_honey_pot, only: [:create, :edit]
def new
@volunteer = current_conference.volunteers.build
end
@ -12,7 +11,7 @@ module Public
def create
@volunteer = current_conference.volunteers.build volunteer_params
if @volunteer.save
flash[:notice] = I18n.t("views.volunteers.successful_application")
flash[:notice] = I18n.t('views.volunteers.successful_application')
redirect_to edit_volunteer_path(@volunteer.unique_id)
else
render :new, status: :unprocessable_entity
@ -22,7 +21,7 @@ module Public
def update
@volunteer = current_conference.volunteers.find_by! unique_id: params[:id]
if @volunteer.update volunteer_params
flash[:notice] = I18n.t("views.volunteers.successful_application_edit")
flash[:notice] = I18n.t('views.volunteers.successful_application_edit')
redirect_to edit_volunteer_path(@volunteer.unique_id)
else
render :edit, status: :unprocessable_entity
@ -31,15 +30,11 @@ module Public
private
def check_honey_pot
head :unauthorized unless params.dig(:volunteer_ht, :full_name).blank?
end
def volunteer_params
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_ids: []
)
end
end

View File

@ -1,6 +1,6 @@
module Public
class VolunteershipsController < Public::ApplicationController
before_action :authenticate_user!, only: [:create, :destroy]
before_filter :authenticate_user!, only: [:create, :destroy]
def index
@volunteer_teams = current_conference.volunteer_teams
@ -12,9 +12,9 @@ module Public
@volunteership.build_proposition proposer: current_user, status: :undecided
if @volunteership.save
flash[:notice] = I18n.t("views.volunteerships.you_successfully_applied_for", team: @volunteership.volunteer_team.name)
flash[:notice] = I18n.t('views.volunteerships.you_successfully_applied_for', team: @volunteership.volunteer_team.name)
else
flash[:error] = I18n.t("views.volunteerships.an error_occurred_while_applying")
flash[:error] = I18n.t('views.volunteerships.an error_occurred_while_applying')
end
after_save_redirect
@ -24,7 +24,7 @@ module Public
@volunteership = current_user.volunteerships.find params[:id]
if @volunteership.destroy
flash[:notice] = I18n.t("views.volunteerships.you_successfully_retracted_your_application_for", team: @volunteership.volunteer_team.name)
flash[:notice] = I18n.t('views.volunteerships.you_successfully_retracted_your_application_for', team: @volunteership.volunteer_team.name)
end
redirect_to volunteerships_path

View File

@ -1,8 +0,0 @@
class ApplicationDecorator < Draper::Decorator
# Define methods for all decorated objects.
# Helpers are accessed through `helpers` (aka `h`). For example:
#
# def percent_amount
# h.number_to_percentage object.amount, precision: 2
# end
end

View File

@ -1,20 +0,0 @@
class EventDecorator < Draper::Decorator
delegate_all
# Define presentation-specific methods here. Helpers are accessed through
# `helpers` (aka `h`). You can override attributes, for example:
#
# def created_at
# helpers.content_tag :span, class: 'time' do
# object.created_at.strftime("%a %m/%d/%y")
# end
# end
def feedback_qr_code
RQRCode::QRCode.new(h.new_event_feedback_url(event_id: id), level: :l)
end
def feedback_qr_code_as_svg
feedback_qr_code.as_svg(shape_rendering: "crispEdges", module_size: 11, fill: "ffffff", offset: 10)
end
end

View File

@ -10,7 +10,7 @@ module ApplicationHelper
"undecided" => "default",
"approved" => "info",
"rejected" => "danger",
"backup" => "warning",
"backup" => "warning"
}.with_indifferent_access[status]
end
@ -19,7 +19,7 @@ module ApplicationHelper
"undecided" => "question",
"approved" => "thumbs-up",
"rejected" => "thumbs-down",
"backup" => "refresh",
"backup" => "refresh"
}.with_indifferent_access[status]
end
@ -29,60 +29,38 @@ module ApplicationHelper
def action_buttons(conference, record, actions = [:index, :show, :edit, :destroy])
klass = record.class
output = ""
output = ''
if actions.include? :index
output += link_to(icon(:list), [:management, conference, klass], {
title: t("actions.index.button", models: klass.model_name.human(count: 2)),
class: "btn btn-info",
title: t('actions.index.button', models: klass.model_name.human(count: 2)),
class: 'btn btn-info'
})
end
if actions.include? :show
output += link_to(icon(:eye), [:management, conference, record], {
title: t("actions.view.button", model: klass.model_name.human),
class: "btn btn-info",
title: t('actions.view.button', model: klass.model_name.human),
class: 'btn btn-info'
})
end
if actions.include? :edit
output += link_to(icon(:edit), [:edit, :management, conference, record], {
title: t("actions.edit.button", model: klass.model_name.human),
class: "btn btn-warning",
})
output += link_to(icon(:edit), [:edit, :management, conference, record], {
title: t('actions.edit.button', model: klass.model_name.human),
class: 'btn btn-warning'
})
end
if actions.include? :destroy
output += link_to(icon(:trash), [:management, conference, record], {
method: :delete,
data: {confirm: t("actions.are_you_sure")},
title: t("actions.destroy.button", model: klass.model_name.human),
class: "btn btn-danger",
})
output += link_to(icon(:trash), [:management, conference, record], {
method: :delete,
data: {confirm: t('actions.are_you_sure')},
title: t('actions.destroy.button', model: klass.model_name.human),
class: 'btn btn-danger'
})
end
output.html_safe
end
def rating_label_color(rating)
return nil if rating.nil?
case rating.round
when (0...3) then 'primary'
when 3 then 'danger'
when 4 then 'warning'
when 5 then 'info'
when 6 then 'success'
end
end
def human_rating(rating)
return nil if rating.nil?
case rating.round
when (0...3) then t('ratings.poor')
when 3 then t('ratings.average')
when 4 then t('ratings.good')
when 5 then t('ratings.very_good')
when 6 then t('ratings.excellent')
end
end
end

View File

@ -5,26 +5,26 @@ module ConferencesHelper
start_date = conference.created_at.to_date
end_date = Time.zone.now.to_date < conference.start_date.to_date ? Time.zone.now.to_date : conference.start_date.to_date
chart_data = (start_date..end_date).map { |date|
chart_data = (start_date..end_date).map do |date|
{
created_at: date,
new_submissions: submissions_by_day[date].try(:first).try(:number) || 0,
new_confirmations: confirmed_by_day[date].try(:first).try(:number) || 0,
new_confirmations: confirmed_by_day[date].try(:first).try(:number) || 0
}
}
end
chart_data.each_with_index do |entry, index|
entry[:all_submissions] = if index == 0
entry[:new_submissions]
else
chart_data[index - 1][:all_submissions] + entry[:new_submissions]
end
entry[:new_submissions]
else
chart_data[index - 1][:all_submissions] + entry[:new_submissions]
end
entry[:all_confirmations] = if index == 0
entry[:new_confirmations]
else
chart_data[index - 1][:all_confirmations] + entry[:new_confirmations]
end
entry[:new_confirmations]
else
chart_data[index - 1][:all_confirmations] + entry[:new_confirmations]
end
end
chart_data
end

View File

@ -1,16 +1,16 @@
module EventsHelper
def links_to_event_participants_for(event)
event.participants_with_personal_profiles.map { |participant|
event.participants_with_personal_profiles.map do |participant|
if participant.has_personal_profile?
link_to icon(:user, participant.name),
management_conference_personal_profile_path(participant.personal_profile_id, conference_id: event.conference.id)
else
link_to icon("user-plus", participant.personal_email),
link_to icon('user-plus', participant.personal_email),
new_management_conference_personal_profile_path(conference_id: event.conference.id,
user_id: participant.id),
title: t("management.events.event.create_profile"), class: "bg-danger"
title: t('management.events.event.create_profile'), class: 'bg-danger'
end
}.join(", ").html_safe
end.join(', ').html_safe
end
def participant_names_with_emails(event)
@ -25,11 +25,13 @@ module EventsHelper
end
def participant_names(event)
event.participants.map { |participant|
event.participants.map do |participant|
if participant.personal_profile(event.conference).present?
profile = participant.personal_profile(event.conference)
profile.name.to_s
"#{profile.name}"
else
nil
end
}.compact
end.compact
end
end

View File

@ -1,21 +1,15 @@
# coding: utf-8
class EventMailer < ActionMailer::Base
helper ApplicationHelper
def confirmation_request(event)
@event = event.decorate
@event = event
I18n.locale = @event.proposer.language
attachments['feedback-link-qr-code.svg'] = {
mime_type: 'image/svg+xml',
content: @event.feedback_qr_code_as_svg
}
mail to: @event.proposer.email,
from: "program@openfest.org",
subject: I18n.t("event_mailer.acceptance_notification.subject",
conference: @event.conference.title,
submission_type: @event.event_type.name.mb_chars.downcase.to_s,
title: @event.title)
from: 'program@openfest.org',
subject: I18n.t('event_mailer.acceptance_notification.subject',
conference: @event.conference.title,
submission_type: @event.event_type.name.mb_chars.downcase.to_s,
title: @event.title)
end
def rejection_notification(event)
@ -23,10 +17,11 @@ class EventMailer < ActionMailer::Base
I18n.locale = @event.proposer.language
mail to: @event.proposer.email,
from: "program@openfest.org",
subject: I18n.t("event_mailer.rejection_notification.subject",
conference: @event.conference.title,
submission_type: @event.event_type.name.mb_chars.downcase.to_s,
title: @event.title)
from: 'program@openfest.org',
subject: I18n.t('event_mailer.rejection_notification.subject',
conference: @event.conference.title,
submission_type: @event.event_type.name.mb_chars.downcase.to_s,
title: @event.title)
end
end

View File

@ -1,3 +1,4 @@
# coding: utf-8
class PropositionMailer < ActionMailer::Base
def new_proposition_notification(proposition)
@proposition = proposition

View File

@ -1,11 +1,10 @@
# coding: utf-8
class VolunteerMailer < ActionMailer::Base
def team_notification(new_volunteer)
@volunteer = new_volunteer
mail(
to: @volunteer.conference.email,
subject: "Нов доброволец за #{@volunteer.conference.title} - #{@volunteer.volunteer_team.name}"
)
mail(to: @volunteer.conference.email,
subject: "Нов доброволец #{@volunteer.name} <#{@volunteer.email}> за екип(и) #{@volunteer.volunteer_teams.map(&:name).join(', ')}")
end
def volunteer_notification(new_volunteer)
@ -13,19 +12,8 @@ class VolunteerMailer < ActionMailer::Base
I18n.locale = @volunteer.language
mail(to: @volunteer.email,
reply_to: @volunteer.conference.email,
from: "OpenFest <cfp@openfest.org>",
subject: I18n.t("volunteer_mailer.success_notification.subject",
conference_name: @volunteer.conference.title))
end
def volunteer_email_confirmation(new_volunteer)
@volunteer = new_volunteer
I18n.locale = @volunteer.language
mail(to: @volunteer.email,
reply_to: @volunteer.conference.email,
from: "OpenFest <cfp@openfest.org>",
subject: I18n.t("volunteer_mailer.email_confirmation.subject",
from: 'no-reply@openfest.org',
subject: I18n.t('volunteer_mailer.success_notification.subject',
conference_name: @volunteer.conference.title))
end
end

View File

@ -2,7 +2,7 @@ class CallForParticipation < ActiveRecord::Base
belongs_to :conference
def open!
self.opens_at = Time.now unless opens_at.present?
self.opens_at = Time.now unless self.opens_at.present?
self.closes_at = nil
save
end
@ -13,14 +13,14 @@ class CallForParticipation < ActiveRecord::Base
end
def open?
opens_at.present? && (opens_at < Time.now)
self.opens_at.present? and self.opens_at < Time.now
end
def closed?
closes_at.present? && (closes_at < Time.now)
self.closes_at.present? and self.closes_at < Time.now
end
def in_progress?
open? && !closed?
open? and not closed?
end
end

View File

@ -1,11 +0,0 @@
module FeedbackReceiving
extend ActiveSupport::Concern
def average_rating
feedbacks.average(:rating)
end
def rated?
feedbacks.size > 0
end
end

View File

@ -14,35 +14,30 @@ class Conference < ActiveRecord::Base
has_many :halls
has_many :event_types
has_many :events
has_many :approved_events, -> { joins(:proposition).approved }, class_name: "Event"
has_many :approved_events, -> { joins(:proposition).approved }, class_name: 'Event'
has_many :conflict_counts, through: :events
has_many :volunteer_teams
has_many :volunteers
has_one :call_for_participation
has_many :participants, -> { distinct }, class_name: "User", through: :events
has_many :participant_profiles, class_name: "PersonalProfile"
has_one :call_for_participation, dependent: :destroy
has_many :participants, -> { uniq }, class_name: 'User', through: :events
has_many :participant_profiles, class_name: 'PersonalProfile'
has_many :slots, through: :halls
has_many :editions, primary_key: :host_name, foreign_key: :host_name, class_name: "Conference"
has_many :feedbacks, as: :feedback_receiving, dependent: :destroy
has_many :editions, primary_key: :host_name, foreign_key: :host_name, class_name: 'Conference'
has_many :events_of_all_editions, through: :editions, source: :events
include FeedbackReceiving
has_many :feedbacks, as: :feedback_receiving
has_many :feedbacks_with_comment, -> { where.not(comment: [nil, ""]) }, as: :feedback_receiving, class_name: 'Feedback'
has_many :event_feedbacks, through: :events, source: :feedbacks
has_many :event_feedbacks_with_comment, through: :events, source: :feedbacks_with_comment
accepts_nested_attributes_for :tracks, :halls, :event_types, :volunteer_teams,
reject_if: :all_blank, allow_destroy: true
reject_if: :all_blank, allow_destroy: true
after_create :create_call_for_participation
def submissions_grouped_by_day
submissions = events.group("date(events.created_at)").select("date(events.created_at) as created_at, count(events.id) as number")
submissions = events.group('date(events.created_at)').select('date(events.created_at) as created_at, count(events.id) as number')
submissions.group_by { |s| s.created_at.to_date }
end
def submissions_grouped_by_confirmation_day
submissions = events.joins(:proposition).approved.confirmed.group("date(propositions.confirmed_at)").select("date(propositions.confirmed_at) as confirmed_at, count(events.id) as number")
submissions = events.joins(:proposition).approved.confirmed.group('date(propositions.confirmed_at)').select('date(propositions.confirmed_at) as confirmed_at, count(events.id) as number')
submissions.group_by { |s| s.confirmed_at.to_date }
end
@ -51,7 +46,7 @@ class Conference < ActiveRecord::Base
end
def has_vote_results?
vote_data_updated_at.present? && (number_of_ballots_cast > 0)
vote_data_updated_at.present? and number_of_ballots_cast > 0
end
def has_voting_endpoint?
@ -59,8 +54,8 @@ class Conference < ActiveRecord::Base
end
def update_conflict_data!
update_vote_data! || raise(ActiveRecord::Rollback)
events.all? { |event| event.update_conflict_data(false) } || raise(ActiveRecord::Rollback)
update_vote_data! or raise ActiveRecord::Rollback
events.all? { |event| event.update_conflict_data(false) } or raise ActiveRecord::Rollback
end
def most_conflicts
@ -79,16 +74,17 @@ class Conference < ActiveRecord::Base
conflict_counts.unscoped.where(left: approved_events, right: approved_events).order(number_of_conflicts: :asc).first.try(:number_of_conflicts) || 0
end
private
def planned_cfp_end_date_is_before_start_date
if planned_cfp_end_date.present? && start_date.present? && (planned_cfp_end_date > start_date)
if planned_cfp_end_date.present? and start_date.present? and planned_cfp_end_date > start_date
errors.add(:planned_cfp_end_date, :cannot_be_after_start_date)
end
end
def start_date_is_before_end_date
if start_date.present? && end_date.present? && (start_date > end_date)
if start_date.present? and end_date.present? and start_date > end_date
errors.add(:end_date, :cannot_be_before_start_date)
end
end
@ -99,38 +95,38 @@ class Conference < ActiveRecord::Base
attr_accessor :conference
def number_of_ballots
@number_of_ballots ||= remote_summary_data["number_of_ballots"]
@number_of_ballots ||= remote_summary_data['number_of_ballots']
end
def ranking
@ranking ||= remote_summary_data["ranking"].map { |ranking_entry| EventRanking.new ranking_entry }
@ranking ||= remote_summary_data['ranking'].map { |ranking_entry| EventRanking.new ranking_entry }
end
def conflicts
@conflicts ||= remote_summary_data["conflicts"].map { |conflicts_entry| ConflictsForEvent.new conflicts_entry }
@conflicts ||= remote_summary_data['conflicts'].map { |conflicts_entry| ConflictsForEvent.new conflicts_entry }
end
def save
conference.transaction do
conference.number_of_ballots_cast = number_of_ballots
conflicts.all?(&:save) || raise(ActiveRecord::Rollback)
ranking.all?(&:save) || raise(ActiveRecord::Rollback)
conflicts.all?(&:save) or raise ActiveRecord::Rollback
ranking.all?(&:save) or raise ActiveRecord::Rollback
conference.touch :vote_data_updated_at
conference.save || raise(ActiveRecord::Rollback)
conference.save or raise ActiveRecord::Rollback
end
end
private
def connection
@connection ||= Faraday.new(url: conference.vote_data_endpoint + "/summary.json",
headers: {"Content-Type" => "application/json"})
@connection ||= Faraday.new(url: conference.vote_data_endpoint + '/summary.json',
headers: {'Content-Type' => 'application/json'})
end
def remote_summary_data
@remote_summary_data ||= JSON.parse(connection.get { |request|
@remote_summary_data ||= JSON.parse(connection.get do |request|
request.body = {summary: {talk_ids: conference.events.pluck(:id)}}.to_json
}.body)
end.body)
end
class ConflictsForEvent
@ -140,13 +136,14 @@ class Conference < ActiveRecord::Base
def save
@event = Event.find(talk_id)
@event.conflict_counts.destroy_all || raise(ActiveRecord::Rollback)
@event.conflict_counts.destroy_all or raise ActiveRecord::Rollback
conflicts.all? do |right_event_id, number_of_conflicts|
ConflictCount.create left_id: talk_id, right_id: right_event_id, number_of_conflicts: number_of_conflicts
end || raise(ActiveRecord::Rollback)
end or raise ActiveRecord::Rollback
end
end
class EventRanking
include ActiveModel::Model

View File

@ -1,5 +1,5 @@
class ConflictCount < ActiveRecord::Base
belongs_to :left, class_name: "Event"
belongs_to :right, class_name: "Event"
belongs_to :left, class_name: 'Event'
belongs_to :right, class_name: 'Event'
has_one :conference, through: :left
end

View File

@ -6,24 +6,20 @@ class Event < ActiveRecord::Base
has_one :slot
has_many :participations, dependent: :destroy
has_many :pending_participations, -> { pending }, class_name: "Participation"
has_many :approved_participations, -> { approved }, class_name: "Participation"
has_many :pending_participations, ->() { pending }, class_name: 'Participation'
has_many :approved_participations, ->() { approved }, class_name: 'Participation'
has_many :participants, through: :approved_participations
has_many :participants_with_personal_profiles, through: :approved_participations, source: :participant_with_personal_profile
has_many :conflict_counts, -> { order(number_of_conflicts: :desc) }, foreign_key: :left_id
has_many :feedbacks, as: :feedback_receiving
has_many :feedbacks_with_comment, -> { where.not(comment: [nil, ""]) }, as: :feedback_receiving, class_name: 'Feedback'
include FeedbackReceiving
has_many :feedbacks, as: :feedback_receiving, dependent: :destroy
belongs_to :event_type
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}
validates :title, presence: true, length: { maximum: 65 }
validates :abstract, presence: true
validates :description, presence: true
validates :agreement, acceptance: true
@ -65,16 +61,16 @@ class Event < ActiveRecord::Base
language: language,
abstract: abstract,
description: description,
notes: notes,
notes: notes
}
end
def ranked?
conference.has_vote_results? && rank.present? && number_of_votes.present?
conference.has_vote_results? and rank.present? and number_of_votes.present?
end
def per_cent_of_votes
if conference.has_vote_results? && (conference.number_of_ballots_cast > 0)
if conference.has_vote_results? and conference.number_of_ballots_cast > 0
Rational(number_of_votes * 100, conference.number_of_ballots_cast)
else
Float::NAN
@ -84,20 +80,20 @@ class Event < ActiveRecord::Base
private
def event_type_belongs_to_the_selected_conference
unless conference.present? && conference.event_types.include?(event_type)
unless conference.present? and conference.event_types.include?(event_type)
errors.add :event_type, :must_be_a_valid_event_type
end
end
def track_belongs_to_the_selected_conference
unless conference.present? && conference.tracks.include?(track)
unless conference.present? and conference.tracks.include?(track)
errors.add :track, :must_be_a_valid_track
end
end
def length_is_within_the_permitted_interval
if event_type.present?
unless (length >= event_type.minimum_length) && (length <= event_type.maximum_length)
unless length >= event_type.minimum_length and length <= event_type.maximum_length
errors.add :length, :must_be_between, minimum: event_type.minimum_length, maximum: event_type.maximum_length
end
end

View File

@ -9,6 +9,6 @@ class EventSearch
option(:confirmed) { |scope, value| scope.joins(:proposition).approved.where.not(propositions: {confirmed_at: nil}) }
option(:not_confirmed) { |scope, value| scope.joins(:proposition).approved.where(propositions: {confirmed_at: nil}) }
sort_by "title"
config[:defaults]["sort"] = "#{config[:sort_attributes].first} asc"
sort_by 'title'
config[:defaults]['sort'] = "#{config[:sort_attributes].first} asc"
end

View File

@ -1,7 +1,7 @@
class Feedback < ActiveRecord::Base
belongs_to :feedback_receiving, polymorphic: true
validates :rating, presence: true, inclusion: {in: [2, 3, 4, 5, 6]}
validates :rating, presence: true, inclusion: {in: [2, 3, 4, 5 ,6]}
before_create :destroy_older_feedbacks_by_the_session

View File

@ -3,7 +3,7 @@ class Participant < ActiveRecord::Base
self.primary_key = :participant_id
def twitter=(handle)
write_attribute :twitter, handle.gsub(/\A@/, "") if handle
write_attribute :twitter, handle.gsub(/\A@/,'') if handle
end
def name

View File

@ -1,8 +1,8 @@
class Participation < ActiveRecord::Base
belongs_to :participant, class_name: "User"
has_one :participant_with_personal_profile, class_name: "Participant"
belongs_to :participant, class_name: User
has_one :participant_with_personal_profile, class_name: Participant
belongs_to :event
validates :participant_id, presence: true
scope :approved, -> { where approved: true }
scope :pending, -> { where.not approved: true }
scope :approved, ->() { where approved: true }
scope :pending, ->() { where.not approved: true }
end

View File

@ -11,14 +11,14 @@ class PersonalProfile < ActiveRecord::Base
validates :twitter, format: {with: /\A[a-z0-9_]{1,15}\z/i}, allow_blank: true
validates :github, format: {with: /\A[a-z0-9][a-z0-9\-]*\z/i}, allow_blank: true
phony_normalize :mobile_phone, default_country_code: "BG", add_plus: false
phony_normalize :mobile_phone, default_country_code: 'BG', add_plus: false
has_one_attached :picture
mount_uploader :picture, PictureUploader
accepts_nested_attributes_for :user
def twitter=(handle)
write_attribute :twitter, handle.gsub(/\A@/, "") if handle
write_attribute :twitter, handle.gsub(/\A@/,'') if handle
end
def name

View File

@ -1,10 +1,10 @@
class Proposition < ActiveRecord::Base
belongs_to :proposer, class_name: "User"
belongs_to :proposer, class_name: 'User'
belongs_to :proposable, polymorphic: true, dependent: :destroy
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'
belongs_to :event
end

View File

@ -9,7 +9,7 @@ class Track < ActiveRecord::Base
translates :name, :description
def color=(hex_triplet)
write_attribute :color, hex_triplet.gsub(/\A#/, "") if hex_triplet
write_attribute :color, hex_triplet.gsub(/\A#/,'') if hex_triplet
end
def color

View File

@ -2,29 +2,17 @@ class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable
:recoverable, :rememberable, :trackable, :validatable
has_many :personal_profiles, dependent: :destroy
has_many :lectures
has_many :workshops
has_many :propositions, foreign_key: :proposer_id
has_many :events, through: :propositions, source: :proposable, source_type: "Event"
has_many :feedbacks, through: :events
has_many :feedbacks_with_comment, -> { where.not(comment: [nil, '']) }, through: :events
has_many :events, through: :propositions, source: :proposable, source_type: 'Event'
has_many :participations, foreign_key: :participant_id
has_many :events_participated_in, through: :participations, source: :event
has_many :volunteerships, foreign_key: :volunteer_id
include FeedbackReceiving
def average_rating
return nil unless rated?
ratings_per_event = feedbacks.group(:feedback_receiving_type,
:feedback_receiving_id).average(:rating).values
BigDecimal(ratings_per_event.reduce(&:+)) / BigDecimal(ratings_per_event.size)
end
def find_or_build_personal_profile(conference, params = {})
current_profile = personal_profile(conference)
if current_profile.present?
@ -38,7 +26,7 @@ class User < ActiveRecord::Base
def build_personal_profile(conference, params = {})
if personal_profiles.last.present?
new_personal_profile = personal_profiles.last.try(:dup)
new_personal_profile.picture.attach(personal_profiles.last.picture.blob)
CopyCarrierwaveFile::CopyFileService.new(personal_profiles.last, new_personal_profile, :picture).set_file
else
new_personal_profile = personal_profiles.build
end

View File

@ -3,63 +3,44 @@ class Volunteer < ActiveRecord::Base
TSHIRT_CUTS = [:unisex, :female]
FOOD_PREFERENCES = [:none, :vegetarian, :vegan]
has_one_attached :picture
attachment :picture, type: :image
validates :name, :language, :tshirt_size, :tshirt_cut, :food_preferences, presence: true
validates :tshirt_size, inclusion: {in: TSHIRT_SIZES.map(&:to_s)}
validates :tshirt_cut, inclusion: {in: TSHIRT_CUTS.map(&:to_s)}
validates :food_preferences, inclusion: {in: FOOD_PREFERENCES.map(&:to_s)}
validates :email, format: {with: /\A[^@]+@[^@]+\z/}, presence: true, uniqueness: {scope: :conference_id}
validates :email, format: {with: /\A[^@]+@[^@]+\z/}, presence: true
validates :phone, presence: true, format: {with: /\A[+\- \(\)0-9]+\z/}
validates :volunteer_team, presence: true
validates :terms_accepted, acceptance: true
validates :volunteer_teams, presence: true
validate :volunteer_teams_belong_to_conference
phony_normalize :phone, default_country_code: "BG"
phony_normalize :phone, default_country_code: 'BG'
belongs_to :conference
belongs_to :volunteer_team
has_and_belongs_to_many :additional_volunteer_teams, class_name: "VolunteerTeam"
has_and_belongs_to_many :volunteer_teams
before_create :ensure_main_volunteer_team_is_part_of_additional_volunteer_teams
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
end
after_create :send_notification_to_organizers
after_create :send_notification_to_volunteer
private
def ensure_main_volunteer_team_is_part_of_additional_volunteer_teams
self.additional_volunteer_teams |= [volunteer_team] if volunteer_team
end
def assign_unique_id
self.unique_id = Digest::SHA256.hexdigest(SecureRandom.uuid)
end
def assign_confirmation_token
self.confirmation_token = Digest::SHA256.hexdigest(SecureRandom.uuid)
end
def send_email_confirmation_to_volunteer
VolunteerMailer.volunteer_email_confirmation(self).deliver_later
end
def send_email_to_organisers
def send_notification_to_organizers
VolunteerMailer.team_notification(self).deliver_later
end
def send_notification_to_volunteer
VolunteerMailer.volunteer_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 }
errors.add :additional_volunteer_teams, :invalid_volunteer_team
end
unless conference_volunteer_teams.include?(volunteer_team)
errors.add :volunteer_team, :invalid_volunteer_team
unless volunteer_teams.all? { |team| conference_volunteer_teams.include? team }
errors.add :volunteer_teams, :invalid_volunteer_team
end
end
end

View File

@ -1,8 +1,8 @@
class VolunteerSearch
include SearchObject.module(:sorting)
option(:volunteer_team_id) { |scope, value| scope.joins(:volunteer_team).where volunteer_team: {id: value} }
option(:volunteer_team_id) { |scope, value| scope.joins(:volunteer_teams).where volunteer_teams: {id: value} }
sort_by "name"
config[:defaults]["sort"] = "#{config[:sort_attributes].first} asc"
sort_by 'name'
config[:defaults]['sort'] = "#{config[:sort_attributes].first} asc"
end

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}
@ -14,7 +13,7 @@ class VolunteerTeam < ActiveRecord::Base
end
def color=(hex_triplet)
write_attribute :color, hex_triplet.gsub(/\A#/, "") if hex_triplet
write_attribute :color, hex_triplet.gsub(/\A#/,'') if hex_triplet
end
def color

View File

@ -2,7 +2,7 @@ class Volunteership < ActiveRecord::Base
include Proposable
belongs_to :volunteer_team
belongs_to :volunteer, class_name: "User"
belongs_to :volunteer, class_name: 'User'
has_one :conference, through: :volunteer_team
def proposable_title

View File

@ -0,0 +1,55 @@
class PictureUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
#include CarrierWave::RMagick
include CarrierWave::MiniMagick
# Choose what kind of storage to use for this uploader:
storage :file
# storage :fog
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
def default_url
ActionController::Base.helpers.asset_path("fallback/profile_picture/" + [version_name, "default.png"].compact.join('_'))
end
# Process files as they are uploaded:
# process :scale => [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
version :medium do
process :resize_to_fit => [171, 180]
end
version :thumb do
process :resize_to_fit => [50, 50]
end
version :schedule do
process :resize_to_fill => [100, 100]
end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(jpg jpeg png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end

View File

@ -1 +0,0 @@
json.array! @conferences, :id, :title, :start_date, :end_date, :created_at, :updated_at

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,24 +0,0 @@
<%
cal = Icalendar::Calendar.new
cal.add_timezone(Time.zone.tzinfo.ical_timezone(Time.now))
@events.each do |event|
next unless event&.slot&.starts_at
cal.event do |ical_event|
ical_event.dtstart = Icalendar::Values::DateTime.new(event.slot.starts_at, 'tzid' => event.slot.starts_at.time_zone.tzinfo.identifier)
ical_event.dtend = Icalendar::Values::DateTime.new(event.slot.ends_at, 'tzid' => event.slot.ends_at.time_zone.tzinfo.identifier)
ical_event.summary = event.title
ical_event.description = event.description
ical_event.created = Icalendar::Values::DateTime.new(event.created_at, 'tzid' => event.created_at.time_zone.tzinfo.identifier)
ical_event.last_modified = Icalendar::Values::DateTime.new(event.updated_at, 'tzid' => event.updated_at.time_zone.tzinfo.identifier)
ical_event.location = event.slot.hall.name
ical_event.alarm do |alarm|
alarm.summary = event.title
alarm.trigger = "-PT15M"
end
end
end
cal.publish
-%>
<%= raw cal.to_ical %>

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

@ -1,15 +1,22 @@
Здравейте,
Имаме удоволствието да ви информираме, че Вашето предложение за участие в „<%= @event.conference.title %>“ с <%= @event.event_type.name.mb_chars.downcase %> на тема „<%= @event.title %>“ беше одобрено. <% if @event.slot.present? -%>
Радваме се да Ви съобщим, че предложението Ви за участие в <%= @event.conference.title %> с <%= @event.event_type.name.mb_chars.downcase %> на тема „<%= @event.title %>“ беше одобрено. <% if @event.slot.present? -%>
Ще се проведе на <%= I18n.l @event.slot.starts_at, format: :long %> часа.
<% else %>
Определянето на датата и часа на провеждане все още предстои.
Все още не са избрани час и дата за провеждането му.
<% end %>
Моля, потвърдете Вашето участие възможно най-скоро като кликнете на следния линк:
Моля, потвърдете участието си възможно най-скоро като кликнете на следния линк:
<%= confirm_event_url @event, host: @event.conference.host_name, protocol: 'https' %>
С приложения QR код към този имейл ще можете да достъпите формуляра за обратна връзка на предложеното от Вас събитие. Моля, включете го в презентацията си.
Моля пишете на ofvideo@openfest.org, ако имате специфични изисквания, например:
* да ви осигурим лаптоп за презентация;
* звук от презентацията ви;
* имате нужда да изпозлвате жична или безжична връзка до Internet за презентацията си;
* ползвате macbook.
Отговорете на този email, ако възникнат някакви въпроси.
Поздрави,
Екипът на <%= @event.conference.title %>

View File

@ -1,17 +1,23 @@
Hello,
We are thrilled to inform you that your request for participation in <%= @event.conference.title %> with the <%= @event.event_type.name.downcase %> titled "<%= @event.title %>" has been approved. <% if @event.slot.present? -%>
We are happy to notify you that your request for participation in <%= @event.conference.title %> with the <%= @event.event_type.name.downcase %> titled "<%= @event.title %>" was approved. <% if @event.slot.present? -%>
It has been scheduled for <%= I18n.l @event.slot.starts_at, format: :long %>.
<% else %>
It has not been scheduled yet.
<% end %>
To confirm your participation please follow the link below as soon as you can:
Please confirm your participation as soon as you can by following the following link:
<%= confirm_event_url @event, host: @event.conference.host_name, protocol: 'https' %>
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.
Should you have any questions or require further information, please do not hesitate to contact us by replying to this email.
Please email ofvideo@openfest.org if you hav any specific requirements, for example:
Best regards,
* You need us to provide you with a laptop for your presentation;
* You need to play sound for your presentation;
* You need either wired or wireless Internet connectivity;
* You're using a macbook.
Please respond to this email in case you have any questions.
Regards,
The <%= @event.conference.title %> Team

View File

@ -1,10 +1,9 @@
Здравейте,
За съжаление, поради голямото количество предложения за лекции, които получихме тази година, и ограниченото ни време, предложението ви за <%= @event.event_type.name.mb_chars.downcase %> на тема „<%= @event.title %>“ няма да може да бъде включено в програмата.
За съжаление, поради големия брой предложения за лекции, които получихме тази година, както и ограниченото време и брой зали, с които разполагаме, вашето предложение за <%= @event.event_type.name.mb_chars.downcase %> на тема „<%= @event.title %>“ не влезе в основната програма.
Обаче, ако желаете, може да представите лекцията си в рамките на 5 минути като част от програмата на Lightning talks (кратки 5 минутни лекции). Записването за тези слотове ще бъде възможно на място.
Тъй като темата звучи интересно, бихме ви предложили да се включите с lightning talk (петминутна презентация с или без слайдове) в дните на конференциятa.
Благодарим ви за интереса и участието ви в нашето събитие. До скоро!
Записването тези кратки презентации ще се случва на регистрацията на <%= @event.conference.title %> след откриването на събитието в събота.
Поздрави,
Екипът на <%= @event.conference.title %>
До скоро! Екипът на <%= @event.conference.title %>

View File

@ -1,10 +1,10 @@
Hello,
Hi,
We regret to inform you that, due to an overwhelming number of talk submissions and the time constraints, we were unable to include your submission for a <%= @event.event_type.name.mb_chars.downcase %> titled "<%= @event.title %>" in the main schedule.
Regretfully, because of the high amount of talk submissions that we've received this year and the limited amounts of time and rooms that we have, your submission for a <%= @event.event_type.name.mb_chars.downcase %> titled "<%= @event.title %>" was not included in the program.
However, we have an alternative option available for you. If you're interested, you can present a condensed, 5-minute version of your talk during our Lightning Talks slot at the event venue. You can sign up for Lightning Talks in person during the event.
As the topic might still be interesting to our audience, it would be possible to join as a lightning talk (a five-minute talk with or without slides) during the conference.
We appreciate your interest in contributing to <%= @event.conference.title %> and hope to see you there!
The sign-up for these talks happens at the registration of <%= @event.conference.title %> after the opening on Saturday.
Best regards,
<%= @event.conference.title %> Team
See you soon,
<%= @event.conference.title %> team

View File

@ -12,10 +12,10 @@ html
- else
| Clarion
= stylesheet_link_tag "management/application", nopush: false
= stylesheet_link_tag "management/application"
= csrf_meta_tags
body
main
= render 'layouts/management/flash'
== yield
= javascript_include_tag "management/application", nopush: false
= javascript_include_tag "management/application"

View File

@ -15,11 +15,11 @@ html
- else
| Clarion
= stylesheet_link_tag "management/application", nopush: false
= stylesheet_link_tag "management/application"
= csrf_meta_tags
body
= render 'layouts/management/navigation'
main
= render 'layouts/management/flash'
== yield
= javascript_include_tag "management/application", nopush: false
= javascript_include_tag "management/application"

View File

@ -32,9 +32,7 @@ nav.navbar.navbar-static-top.navbar-inverse role="navigation"
/ li class="#{'active' if controller_name == 'propositions'}"
/ = link_to [:management, current_conference, :propositions] do
/ => icon 'question', Proposition.model_name.human(count: 2).mb_chars.capitalize, class: 'fa-fw'
li class="#{'active' if controller_name == 'feedback'}"
= link_to management_conference_feedback_index_path(current_conference) do
=> icon 'star-half-o', t('activerecord.models.feedback', count: 2).mb_chars.capitalize, class: 'fa-fw'
ul.nav.navbar-nav.navbar-right
li.dropdown
= link_to '#', class: 'dropdown-toggle', data: {toggle: 'dropdown'} do

View File

@ -20,12 +20,9 @@
.label.label-info
= event.rank
=< number_to_percentage(event.per_cent_of_votes, strip_insignificant_zeros: true, precision: 2)
- if event.rated?
dt = t(".average_rating")
dd
=> human_rating(event.average_rating)
.badge class="badge-#{rating_label_color(event.average_rating)}"
= number_with_precision event.average_rating, precision: 2, strip_insignificant_zeros: true
td.visible-md.visible-lg.visible-xl
= links_to_event_participants_for(event)
td.action

View File

@ -1,123 +1,89 @@
- personal_profile = speaker.personal_profile(@conference) || speaker.personal_profiles.last
.row
.col-sm-4
.panel.panel-default
- if personal_profile.present?
.panel-image
= image_tag personal_profile.picture
.panel-body
.media
.media-body
h4.media-heading
= personal_profile.name
hr
= simple_format(truncate(personal_profile.biography, omission: '... ', length: 300) { link_to(t('.continue'), [:management, @conference, personal_profile])})
ul.list-group
.panel.panel-default
.panel-body
.media
.media-left.hidden-sm.hidden-xs
- if personal_profile.present?
= image_tag personal_profile.picture.medium.url, class: "profile-image"
- else
= icon :user, class: 'fa-5x'
.media-body
.text-center.visible-sm.visible-xs
- if personal_profile.present?
= image_tag personal_profile.picture.medium.url, class: "profile-image img-thumbnail"
- else
= icon :user, class: 'fa-5x'
- if personal_profile.present?
h4.media-heading
= personal_profile.name
- unless personal_profile.conference == @conference
small<
| (
= t('.profile_from', conference: personal_profile.conference.title)
| )
hr
h4 = PersonalProfile.human_attribute_name(:biography)
= simple_format personal_profile.biography
h4 = t '.contacts'
- if personal_profile.organisation.present?
li.list-group-item
h5.list-group-item-heading = PersonalProfile.human_attribute_name :organisation
p.list-group-item-text = personal_profile.organisation
p #{icon :briefcase} @#{personal_profile.organisation}
- if personal_profile.twitter.present?
li.list-group-item
h5.list-group-item-heading = PersonalProfile.human_attribute_name :twitter
p.list-group-item-text
= link_to "@#{personal_profile.twitter}", "https://twitter.com/#{personal_profile.twitter}", target: '_blank'
- if personal_profile.github.present?
li.list-group-item
h5.list-group-item-heading = PersonalProfile.human_attribute_name :github
p.list-group-item-text
= link_to personal_profile.github, "https://github.com/#{personal_profile.github}", target: '_blank'
.panel-footer
.text-right
.btn-group.btn-group-sm
- if personal_profile.conference == @conference
= action_buttons @conference, personal_profile, [:show, :edit]
- else
= link_to [:management, @conference, :personal_profiles, {personal_profile: {user_id: speaker.id}}], class: ['btn', 'btn-primary'], title: t('actions.clone.title', model: PersonalProfile.model_name.human), method: :post do
=> icon('clone')
= link_to [:new, :management, @conference, :personal_profile, {user_id: speaker.id}], class: ['btn', 'btn-primary'], title: t('actions.create.title', model: PersonalProfile.model_name.human) do
=> icon('user-plus')
- else
.panel-image
= image_tag 'user-secret-solid.svg'
.panel-body
.media
.media-body
h4.media-heading
speaker.email
hr
p = t '.the_participant_has_not_created_a_profile'
ul.list-group
li.list-group-item
h5.list-group-item-heading = t '.private_email'
p.list-group-item-text = speaker.email
.col-sm-8
.row
.col-md-6
.panel.panel-info
.panel-heading
.row
.col-xs-3
= icon 'files-o', '', class: 'fa-5x'
.col-xs-9.text-right
.huge
= speaker.events_participated_in.size
div
= Event.model_name.human(count: speaker.events_participated_in.size)
.col-md-6
.panel class="panel-#{rating_label_color(speaker.average_rating || 5)}" title=human_rating(speaker.average_rating)
.panel-heading
.row
.col-xs-3
= icon 'star', '', class: 'fa-5x'
.col-xs-9.text-right
.huge
= number_with_precision(speaker.average_rating, precision: 2, strip_insignificant_zeros: true) || ''
div
= User.human_attribute_name(:average_rating).downcase
.row
.col-xs-12
h4 = t '.other_event_propositions'
- if speaker.events_participated_in.where.not(id: @event.id).any?
.panel.panel-default
table.table.table-striped.table-hover.record-table
thead
tr
th.main
= Event.human_attribute_name :title
th.text-center
= Event.human_attribute_name :rating
th.text-center.hidden-md.hidden-sm.hidden-xs
= Event.human_attribute_name :rank
th.hidden-md.hidden-sm.hidden-xs
= Event.human_attribute_name :conference
th.hidden-md.hidden-sm.hidden-xs
= Event.human_attribute_name :status
th.hidden-md.hidden-sm.hidden-xs
tbody
- speaker.events_participated_in.where.not(id: @event.id).order(created_at: :desc).each do |event|
tr
td = event.title
td.text-center
- if event.rated?
.large
.label class="label-#{rating_label_color(event.average_rating)}"
= number_with_precision event.average_rating, precision: 2, strip_insignificant_zeros: true
td.text-center.hidden-md.hidden-sm.hidden-xs
- if event.ranked?
.large
.label.label-info = event.rank
td.hidden-md.hidden-sm.hidden-xs = event.conference.title
td.hidden-md.hidden-sm.hidden-xs
span class="label label-lg label-#{proposition_status_class(event.status)}"
= icon(proposition_status_glyph(event.status), t("activerecord.attributes.proposition.statuses.#{event.status}"))
td.actions
.btn-group.btn-group-sm
= action_buttons event.conference, event, [:show]
p #{icon :twitter} @#{personal_profile.twitter}
- if personal_profile.public_email.present?
p #{icon :envelope} #{personal_profile.public_email} (#{PersonalProfile.human_attribute_name(:public_email).mb_chars.downcase})
p #{icon :envelope} #{speaker.email} (#{PersonalProfile.human_attribute_name(:email).mb_chars.downcase})
p #{glyph :phone} #{Phony.format(personal_profile.mobile_phone, format: :international)}
- else
p = t '.no_other_event_propositions'
h4.media-heading
= speaker.email
hr
p
= t('.no_profile')
=< link_to icon('user-plus', t('.create_profile')), new_management_conference_personal_profile_path(conference_id: @conference.id, user_id: speaker.id), class: ['btn', 'btn-primary', 'btn-xs']
- if speaker.events_participated_in.where.not(id: @event.id).any?
h4 = t '.previous_event_propositions'
table.table.table-striped.table-hover.record-table
thead
tr
th
= Event.human_attribute_name :title
th.text-center
= Event.human_attribute_name :rank
th
= Event.human_attribute_name :conference
th
= Event.human_attribute_name :status
th
tbody
- speaker.events_participated_in.where.not(id: @event.id).order(created_at: :desc).each do |event|
tr
td = event.title
td.text-center
- if event.ranked?
.large
.label.label-info = event.rank
td = event.conference.title
td
span class="label label-lg label-#{proposition_status_class(event.status)}"
= icon(proposition_status_glyph(event.status), t("activerecord.attributes.proposition.statuses.#{event.status}"))
td.actions
.btn-group.btn-group-sm
= action_buttons event.conference, event, [:show]
- if personal_profile.present?
.panel-footer
.text-right
.btn-group.btn-group-sm
- if personal_profile.conference == @conference
= action_buttons @conference, personal_profile, [:show, :edit]
- else
= link_to [:management, @conference, :personal_profiles, {personal_profile: {user_id: speaker.id}}], class: ['btn', 'btn-primary'], title: t('actions.clone.title', model: PersonalProfile.model_name.human), method: :post do
=> icon('clone')
= link_to [:new, :management, @conference, :personal_profile, {user_id: speaker.id}], class: ['btn', 'btn-primary'], title: t('actions.create.title', model: PersonalProfile.model_name.human) do
=> icon('user-plus')

View File

@ -1,5 +1,5 @@
<%- csv_headers = %w{id title subtitle type track language paticipants length status rank number_of_votes proposer_notes} -%>
<%- csv_headers = %w{id title subtitle type track language paticipants status rank number_of_votes} -%>
<%= CSV.generate_line(csv_headers).html_safe -%>
<%- @events.each do |event| -%>
<%= CSV.generate_line([event.id, event.title, event.subtitle, event.event_type.name, event.track.name, event.language, participant_names_with_emails(event).join(', '), event.length, event.status, event.rank, event.number_of_votes, event.notes]).html_safe -%>
<%= CSV.generate_line([event.id, event.title, event.subtitle, event.event_type.name, event.track.name, event.language, participant_names_with_emails(event).join(', '), event.status, event.rank, event.number_of_votes]).html_safe -%>
<%- end -%>

View File

@ -7,8 +7,8 @@
= Event.model_name.human(count: 2).mb_chars.titleize
small<
| (
= t '.total', current: @events.size, total: @conference.events.size
=< Event.model_name.human(count: @conference.events.size)
= t '.total', current: @events.count, total: current_conference.events.count
=< Event.model_name.human(count: current_conference.events.count)
| )
.row.visible-sm
.col-xs-12
@ -21,73 +21,73 @@
.panel-body
ul.nav.nav-pills.nav-stacked
= content_tag :li, role: "presentation", class: @filters[:event_type_id].blank? ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.except(:event_type_id))
= link_to management_conference_events_path(current_conference, filters: @filters.except(:event_type_id))
= t '.all'
span.badge.pull-right = @conference.events.size
- @conference.event_types.each do |event_type|
span.badge.pull-right = current_conference.events.count
- current_conference.event_types.each do |event_type|
= content_tag :li, role: "presentation", class: @filters[:event_type_id].to_i == event_type.id ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.merge({event_type_id: event_type.id}))
= link_to management_conference_events_path(current_conference, filters: @filters.merge({event_type_id: event_type.id}))
= event_type.name
span.badge.pull-right = @conference.events.where(event_type: event_type).size
span.badge.pull-right = current_conference.events.where(event_type: event_type).count
.panel.panel-default
.panel-heading
= Event.human_attribute_name(:track)
.panel-body
ul.nav.nav-pills.nav-stacked
= content_tag :li, role: "presentation", class: @filters[:track_id].blank? ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.except(:track_id))
= link_to management_conference_events_path(current_conference, filters: @filters.except(:track_id))
= t '.all'
span.badge.pull-right = @conference.events.size
- @conference.tracks.each do |track|
span.badge.pull-right = current_conference.events.count
- current_conference.tracks.each do |track|
= content_tag :li, role: "presentation", class: @filters[:track_id] == track.id.to_s ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.merge({track_id: track.id}))
= link_to management_conference_events_path(current_conference, filters: @filters.merge({track_id: track.id}))
= track.name
span.badge.pull-right = @conference.events.where(track: track).size
span.badge.pull-right = current_conference.events.where(track: track).count
.panel.panel-default
.panel-heading
= Event.human_attribute_name(:language)
.panel-body
ul.nav.nav-pills.nav-stacked
= content_tag :li, role: "presentation", class: @filters[:language].blank? ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.except(:language))
= link_to management_conference_events_path(current_conference, filters: @filters.except(:language))
= t '.all'
span.badge.pull-right = @conference.events.size
span.badge.pull-right = current_conference.events.count
- I18n.available_locales.map(&:to_s).each do |language|
= content_tag :li, role: "presentation", class: @filters[:language] == language ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.merge({language: language}))
= link_to management_conference_events_path(current_conference, filters: @filters.merge({language: language}))
= t("locales.#{language}")
span.badge.pull-right = @conference.events.where(language: language).size
span.badge.pull-right = current_conference.events.where(language: language).count
.panel.panel-default
.panel-heading
= Proposition.human_attribute_name(:status)
.panel-body
ul.nav.nav-pills.nav-stacked
= content_tag :li, role: "presentation", class: @filters[:status].blank? ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.except(:status))
= link_to management_conference_events_path(current_conference, filters: @filters.except(:status))
= t '.all'
span.badge.pull-right = @conference.events.size
span.badge.pull-right = current_conference.events.count
- Proposition.statuses.each do |status_name, status_id|
= content_tag :li, role: "presentation", class: @filters[:status] == status_id.to_s ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.merge({status: status_id}))
= link_to management_conference_events_path(current_conference, filters: @filters.merge({status: status_id}))
= t "activerecord.attributes.proposition.statuses.#{status_name}"
span.badge.pull-right = @conference.events.joins(:proposition).where(propositions: {status: status_id}).size
span.badge.pull-right = current_conference.events.joins(:proposition).where(propositions: {status: status_id}).count
.panel.panel-default
.panel-heading
= Proposition.human_attribute_name(:confirmed)
.panel-body
ul.nav.nav-pills.nav-stacked
= content_tag :li, role: "presentation", class: @filters[:confirmed].blank? && @filters[:not_confirmed].blank? ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.except(:confirmed, :not_confirmed))
= link_to management_conference_events_path(current_conference, filters: @filters.except(:confirmed, :not_confirmed))
= t '.all'
span.badge.pull-right = @conference.events.size
span.badge.pull-right = current_conference.events.count
= content_tag :li, role: "presentation", class: @filters[:confirmed].present? ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.except(:not_confirmed).merge({confirmed: true}))
= link_to management_conference_events_path(current_conference, filters: @filters.except(:not_confirmed).merge({confirmed: true}))
= t "activerecord.attributes.proposition.confirmation.confirmed"
span.badge.pull-right = @conference.events.joins(:proposition).approved.where.not(propositions: {confirmed_at: nil}).size
span.badge.pull-right = current_conference.events.joins(:proposition).approved.where.not(propositions: {confirmed_at: nil}).count
= content_tag :li, role: "presentation", class: @filters[:not_confirmed].present? ? 'active' : nil
= link_to management_conference_events_path(@conference, filters: @filters.except(:confirmed).merge({not_confirmed: true}))
= link_to management_conference_events_path(current_conference, filters: @filters.except(:confirmed).merge({not_confirmed: true}))
= t "activerecord.attributes.proposition.confirmation.not_confirmed"
span.badge.pull-right = @conference.events.joins(:proposition).approved.where(propositions: {confirmed_at: nil}).size
span.badge.pull-right = current_conference.events.joins(:proposition).approved.where(propositions: {confirmed_at: nil}).count
.col-md-9
.panel.panel-default
@ -102,5 +102,5 @@
tbody
= render(partial: 'event', collection: @events) || render(partial: 'no_records')
.panel-footer.text-right
= link_to management_conference_events_path(@conference, filters: @filters, format: 'csv'), class: 'btn btn-info'
= link_to management_conference_events_path(current_conference, filters: @filters, format: 'csv'), class: 'btn btn-info'
= icon :download, t('.export')

View File

@ -65,88 +65,52 @@
h3 = Event.human_attribute_name :participants
= render partial: 'speaker', collection: @event.participants
- if @conference.start_date.past? || @event.rated?
.row
.col-xs-12
h3 = Event.human_attribute_name :feedbacks
- if @event.rated?
.row
.col-md-10
.panel.panel-default
.panel-heading = t('.comments')
- if @event.feedbacks_with_comment.size > 0
table.table.table-striped
tbody
= render partial: '/management/shared/feedback', collection: @event.feedbacks_with_comment
- else
.panel-body
= t ('.no_comments_received')
.col-md-2
.panel.panel-info
.panel-heading
= t '.average_grade'
.panel-body.text-right
.huge
= number_with_precision(@event.average_rating, precision: 2, strip_insignificant_zeros: true) || ''
= t('.total_feedback_grades', total_grades: @event.feedbacks.count, count: @event.feedbacks.count)
- else
p = t '.no_feedback_received'
- if @conference.has_vote_results? or @conference.has_voting_endpoint?
.row
.col-xs-12
h2
- if @conference.start_date.future?
= t '.conflicts'
- else
= t '.top_conflicts'
small< = t '.between_approved_events'
.panel.panel-default
table.table.table-striped.table-hover.record-table
- if @conference.has_vote_results? and @conference.approved_events.count > 2
thead
tr
th.text-right
= t '.percent'
th.main
= Event.model_name.human.mb_chars.capitalize
th
tbody
- if @conference.has_vote_results?
- if @conference.approved_events.count > 2
- if @conference.start_date.future?
- conflict_counts = @event.conflict_counts.where(right_id: @conference.approved_events.pluck(:id)).includes(:right)
- else
- conflict_counts = @event.conflict_counts.where(right_id: @conference.approved_events.pluck(:id)).includes(:right).limit(5)
- conflict_counts.each do |conflict_count|
- conflict_percent = Rational(conflict_count.number_of_conflicts, @conference.number_of_ballots_cast)
tr
td.text-right
.large
span.label.label-success data-conflicts="#{conflict_count.number_of_conflicts}" data-most-conflicts="#{@conference.most_conflicts_between_approved_events}" data-least-conflicts="#{@conference.least_conflicts_between_approved_events}"
= number_to_percentage(conflict_percent * 100, strip_insignificant_zeros: true, precision: 2)
td
h4 = conflict_count.right.title
h5 = conflict_count.right.subtitle
= links_to_event_participants_for(conflict_count.right)
td.actions
= action_buttons @conference, conflict_count.right, [:show]
- else
.row
.col-xs-12
h2
= t '.conflicts'
small< = t '.between_approved_events'
.panel.panel-default
table.table.table-striped.table-hover.record-table
- if @conference.has_vote_results? and @conference.approved_events.count > 2
thead
tr
th.text-right
= t '.percent'
th
= Event.model_name.human.mb_chars.capitalize
th
tbody
- if @conference.has_vote_results?
- if @conference.approved_events.count > 2
- @event.conflict_counts.where(right_id: @conference.approved_events.pluck(:id)).includes(:right).each do |conflict_count|
- conflict_percent = Rational(conflict_count.number_of_conflicts, @conference.number_of_ballots_cast)
tr
td colspan="20"
= t '.no_approved_events'
td.text-right
.large
span.label.label-success data-conflicts="#{conflict_count.number_of_conflicts}" data-most-conflicts="#{@conference.most_conflicts_between_approved_events}" data-least-conflicts="#{@conference.least_conflicts_between_approved_events}"
= number_to_percentage(conflict_percent * 100, strip_insignificant_zeros: true, precision: 2)
td
h4 = conflict_count.right.title
h5 = conflict_count.right.subtitle
= links_to_event_participants_for(conflict_count.right)
td.actions
= action_buttons @conference, conflict_count.right, [:show]
- else
tr
td colspan="20"
= t 'management.conferences.vote_results.vote_data_never_updated'
= link_to update_vote_data_management_conference_path(@conference), method: :patch, class: ['btn', 'btn-primary'] do
= icon :refresh, t('management.conferences.vote_results.fetch_vote_results')
- if @conference.has_vote_results?
.panel-footer.text-right
.btn-group
= link_to conflicts_management_conference_event_path(@event, conference_id: @conference.id), class: ['btn', 'btn-info'] do
= icon :percent, t('.conflicts')
= link_to update_vote_data_management_conference_path(@conference), method: :patch, class: ['btn', 'btn-primary'] do
= t '.no_approved_events'
- else
tr
td colspan="20"
= t 'management.conferences.vote_results.vote_data_never_updated'
= icon :refresh, t('management.conferences.vote_results.fetch_vote_results')
- if @conference.has_vote_results?
.panel-footer.text-right
.btn-group
= link_to conflicts_management_conference_event_path(@event, conference_id: @conference.id), class: ['btn', 'btn-info'] do
= icon :percent, t('.conflicts')
= link_to update_vote_data_management_conference_path(@conference), method: :patch, class: ['btn', 'btn-primary'] do
= icon :refresh, t('management.conferences.vote_results.fetch_vote_results')

View File

@ -1,8 +0,0 @@
<%- csv_headers = %w{id feedback_receiving_type feedback_receiving_id name/title author_email rating comment ip session_id created_at} -%>
<%= CSV.generate_line(csv_headers).html_safe -%>
<%- @conference.feedbacks.each do |feedback| -%>
<%= CSV.generate_line([feedback.id, feedback.feedback_receiving_type, feedback.feedback_receiving_id, feedback.feedback_receiving&.title || feefback.feedback_receiving&.name, feedback.author_email, feedback.rating, feedback.comment, feedback.ip_address, feedback.session_id, feedback.created_at]).html_safe -%>
<%- end -%>
<%- @conference.event_feedbacks.each do |feedback| -%>
<%= CSV.generate_line([feedback.id, feedback.feedback_receiving_type, feedback.feedback_receiving_id, feedback.feedback_receiving&.title || feefback.feedback_receiving&.name, feedback.author_email, feedback.rating, feedback.comment, feedback.ip_address, feedback.session_id, feedback.created_at]).html_safe -%>
<%- end -%>

View File

@ -1,62 +0,0 @@
- content_for :title
= t '.feedback'
.row
.col-lg-12
h1.page-header
= t '.feedback'
= link_to management_conference_feedback_index_path(@conference, format: 'csv'), class: 'btn btn-info pull-right'
= icon :download, t('.export')
- if @conference.start_date.past? || @conference.rated?
.row
.col-xs-12
h3
=< t '.overall_organisation'
- if @conference.rated?
.row
.col-md-10
.panel.panel-default
.panel-heading = t('.comments')
- if @conference.feedbacks_with_comment.order(created_at: :asc).size > 0
table.table.table-striped
tbody
= render partial: '/management/shared/feedback', collection: @conference.feedbacks_with_comment.order(created_at: :asc), locals: {hide_title: true}
- else
.panel-body
= t ('.no_comments_received')
.col-md-2
.panel.panel-info
.panel-heading
= t '.average_grade'
.panel-body.text-right
.huge
= number_with_precision(@conference.average_rating, precision: 2, strip_insignificant_zeros: true) || ''
= t('.total_feedback_grades', total_grades: @conference.feedbacks.count, count: @conference.feedbacks.count)
- else
p = t '.no_feedback_received'
- if @conference.start_date.past? || @conference.event_feedbacks_with_comment.order(created_at: :asc).size > 0
.row
.col-xs-12
h3
=< t '.events'
- if @conference.event_feedbacks.size > 0
.row
.col-md-10
.panel.panel-default
.panel-heading = t('.comments')
table.table.table-striped
tbody
= render partial: '/management/shared/feedback', collection: @conference.event_feedbacks_with_comment.order(created_at: :asc)
.col-md-2
.panel.panel-info
.panel-heading
= t '.average_grade'
.panel-body.text-right
.huge
= number_with_precision(@conference.event_feedbacks.average(:rating), precision: 2, strip_insignificant_zeros: true) || ''
= t('.total_feedback_grades', total_grades: @conference.event_feedbacks.count, count: @conference.event_feedbacks.count)
- else
p = t '.no_comments_received'

View File

@ -10,9 +10,9 @@
.panel-body
.row
.col-lg-12
- if f.object.picture.attached?
- if f.object.picture.present?
.col-sm-offset-3.col-sm-9
= image_tag f.object.picture.variant(resize_to_limit: [150, 150]), class: 'img-thumbnail'
= image_tag f.object.picture.medium.url, class: 'img-thumbnail'
= f.input :picture, wrapper: :horizontal_file_input

View File

@ -27,9 +27,10 @@
.media
.media-left
- if profile.present?
= image_tag(profile.picture.variant(resize_to_fill: [50, 50]))
= image_tag(profile.picture.thumb.url)
- else
= image_tag('avatar-placeholder.png')
= image_tag(PictureUploader.new.thumb.url)
.media-body
h4.media-heading
- if profile.try(:name).present?

View File

@ -5,117 +5,65 @@
.col-lg-12
h1.page-header
= PersonalProfile.model_name.human.mb_chars.capitalize
.row
.col-sm-5.col-md-4
.panel.panel-default
.panel-image
= image_tag @profile.picture
.panel-body
.media
.media-body
h4.media-heading
= @profile.name
hr
= simple_format @profile.biography
ul.list-group
- if @profile.mobile_phone.present?
li.list-group-item
h5.list-group-item-heading = PersonalProfile.human_attribute_name :mobile_phone
p.list-group-item-text = Phony.format(@profile.mobile_phone, format: :international)
- if @profile.organisation.present?
li.list-group-item
h5.list-group-item-heading = PersonalProfile.human_attribute_name :organisation
p.list-group-item-text = @profile.organisation
- if @profile.twitter.present?
li.list-group-item
h5.list-group-item-heading = PersonalProfile.human_attribute_name :twitter
p.list-group-item-text
= link_to "@#{@profile.twitter}", "https://twitter.com/#{@profile.twitter}", target: '_blank'
- if @profile.github.present?
li.list-group-item
h5.list-group-item-heading = PersonalProfile.human_attribute_name :github
p.list-group-item-text
= link_to @profile.github, "https://github.com/#{@profile.github}", target: '_blank'
- if @profile.public_email.present?
li.list-group-item
h5.list-group-item-heading = PersonalProfile.human_attribute_name :public_email
p.list-group-item-text = @profile.public_email
li.list-group-item
h5.list-group-item-heading = t '.private_email'
p.list-group-item-text = @user.email
.panel-footer
.text-right
.btn-group.btn-group-sm
= action_buttons @conference, @profile, [:edit, :destroy]
.col-sm-7.col-md-8
.row
.col-md-6
.panel.panel-info
.panel-heading
.row
.col-xs-3
= icon 'files-o', '', class: 'fa-5x'
.col-xs-9.text-right
.huge
= @user.events_participated_in.size
div
= Event.model_name.human(count: @user.events_participated_in.size)
.col-md-6
.panel class="panel-#{rating_label_color(@user.average_rating || 5)}" title=human_rating(@user.average_rating)
.panel-heading
.row
.col-xs-3
= icon 'star', '', class: 'fa-5x'
.col-xs-9.text-right
.huge
= number_with_precision(@user.average_rating, precision: 2, strip_insignificant_zeros: true) || ''
div
= User.human_attribute_name(:average_rating).downcase
h2 = t '.talk_history'
.panel.panel-default
- if @user.events_participated_in.any?
.panel.panel-default
.panel-body
.media
.media-left.hidden-sm.hidden-xs
= image_tag @profile.picture.medium.url, class: "profile-image"
.media-body
.text-center.visible-sm.visible-xs
= image_tag @profile.picture.medium.url, class: "profile-image img-thumbnail"
h4.media-heading
= @profile.name
hr
h4 = PersonalProfile.human_attribute_name(:biography)
= simple_format @profile.biography
h4 = t '.contacts'
- if @profile.organisation.present?
p = icon :briefcase, @profile.organisation
- if @profile.twitter.present?
p = icon :twitter, "@#{@profile.twitter}"
- if @profile.github.present?
p = icon :github, @profile.github
- if @profile.public_email.present?
p = icon :envelope, "#{@profile.public_email} (#{PersonalProfile.human_attribute_name(:public_email).mb_chars.downcase})"
p = icon :envelope, "#{@user.email} (#{User.human_attribute_name(:email).mb_chars.downcase})"
- if @user.events_participated_in.any?
h4 = t '.event_propositions'
table.table.table-striped.table-hover.record-table
thead
tr
th.main
th
= Event.human_attribute_name :title
th.text-center
= Event.human_attribute_name :rating
th.text-center.hidden-md.hidden-sm.hidden-xs
= Event.human_attribute_name :rank
th.hidden-md.hidden-sm.hidden-xs
th
= Event.human_attribute_name :conference
th.hidden-md.hidden-sm.hidden-xs
th
= Event.human_attribute_name :status
th
tbody
- @user.events_participated_in.order(created_at: :desc).each do |event|
tr
td = event.title
td.text-center
- if event.rated?
.large
.label class="label-#{rating_label_color(event.average_rating)}" title=human_rating(event.average_rating)
= number_with_precision event.average_rating, precision: 2, strip_insignificant_zeros: true
td.text-center.hidden-md.hidden-sm.hidden-xs
- if event.ranked?
.large
.label.label-info = event.rank
td.hidden-md.hidden-sm.hidden-xs
= event.conference.title
td.hidden-md.hidden-sm.hidden-xs
td = event.conference.title
td
span class="label label-lg label-#{proposition_status_class(event.status)}"
= icon(proposition_status_glyph(event.status), t("activerecord.attributes.proposition.statuses.#{event.status}"))
td.actions
.btn-group.btn-group-sm
= action_buttons event.conference, event, [:show]
h2 = t '.comments_from_the_audience'
- if @user.feedbacks_with_comment.size > 0
.panel.panel-default
table.table.table-striped
tbody
= render partial: '/management/shared/feedback', collection: @user.feedbacks_with_comment.order(created_at: :desc)
- else
p = t '.no_comments_received'
.panel-footer
.text-right
.btn-group.btn-group-sm
= action_buttons @conference, @profile, [:edit, :destroy]

View File

@ -1,16 +0,0 @@
tr
td.text-center
.huge
.label class="label-#{rating_label_color(feedback.rating)}" title=human_rating(feedback.rating)
= feedback.rating
td
blockquote
= simple_format feedback.comment
footer
- if feedback.author_email.present?
= feedback.author_email
- else
= t(".anonymous")
- if !local_assigns[:hide_title]
span<> = t '.about'
= link_to feedback.feedback_receiving.title, [:management, current_conference, feedback.feedback_receiving]

View File

@ -5,14 +5,13 @@
.col-lg-12
- if f.object.picture.present?
.col-sm-offset-3.col-sm-9
= @volunteer.picture.variant(resize_to_limit: [150, 150]) if @volunteer.picture.attached?
= attachment_image_tag(@volunteer, :picture, :fill, 150, 150) if @volunteer.picture.present?
= f.input :picture, as: :file, wrapper: :horizontal_file_input, direct: true
= f.input :picture, as: :attachment, wrapper: :horizontal_file_input, direct: true
= f.input :name, autofocus: true
= f.input :email
= f.association :volunteer_team, as: :radio_buttons, wrapper: :horizontal_radio_and_checkboxes, collection: current_conference.volunteer_teams
= f.association :additional_volunteer_teams, as: :check_boxes, wrapper: :horizontal_radio_and_checkboxes, collection: current_conference.volunteer_teams
= f.association :volunteer_teams, as: :check_boxes, wrapper: :horizontal_radio_and_checkboxes, collection: current_conference.volunteer_teams
= f.input :phone, input_html: {value: @volunteer.phone.try(:phony_formatted, format: :international)}
= f.input :language, as: :radio_buttons, wrapper: :horizontal_radio_and_checkboxes, collection: locale_collection, include_blank: false, checked: (@volunteer.language.presence || I18n.locale)
= f.input :tshirt_size, collection: Volunteer::TSHIRT_SIZES, as: :radio_buttons, wrapper: :horizontal_radio_and_checkboxes, checked: (@volunteer.tshirt_size.presence || :m)
@ -20,6 +19,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'

Some files were not shown because too many files have changed in this diff Show More