diff --git a/Gemfile b/Gemfile index 5684c25b..400299d2 100644 --- a/Gemfile +++ b/Gemfile @@ -82,6 +82,9 @@ gem 'coveralls', require: false gem 'prawn' gem 'prawn-table' +# pdf inspection +gem 'pdf-inspector', require: "pdf/inspector" + # Simple, Heroku-friendly Rails app configuration using ENV and a single YAML file gem 'figaro' @@ -135,9 +138,9 @@ group :test do gem 'parser', '~> 2.2.2.5' # Stubbing external calls by blocking traffic with WebMock.disable_net_connect! or allow: # gem 'webmock' + +end - # PDF testing - gem 'pdf-inspector', require: "pdf/inspector"end group :production do # Use Puma web server diff --git a/app/assets/images/example.png b/app/assets/images/example.png new file mode 100644 index 00000000..cd2f7e49 Binary files /dev/null and b/app/assets/images/example.png differ diff --git a/app/assets/images/front-welcome.png b/app/assets/images/front-welcome.png new file mode 100644 index 00000000..8b9f4124 Binary files /dev/null and b/app/assets/images/front-welcome.png differ diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 0470acf4..fbda8256 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -19,3 +19,45 @@ label.required:after { content:" *"; color: red } + +body { + /* font styles as found in bootstrap v4 */ + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; +} + +footer.front-section { + border: none; +} +footer { + margin-top: 60px; +} +.m-l-1 { margin-left: 15px; } +.m-r-1 { margin-right: 15px; } +.m-t-1 { margin-top: 15px; } +.m-b-1 { margin-bottom: 15px; } + +.img-float-corner-tr { + float: right; + margin: 0 0 15px 15px; +} +@media (max-width: 768px) { + .img-float-corner-tr { + float: none; + margin: auto; + margin-bottom: 15px; + } +} +.front-section { + border-bottom: 1px solid #eee; + padding: 60px 0; +} +.front-section:first-child { + padding-top: 30px; +} +.front-section:last-of-type { + border: none; +} +.front-section:nth-child(even), footer { + background-color: #333; + color: #eee; +} diff --git a/app/assets/stylesheets/bootstrap_and_overrides.css b/app/assets/stylesheets/bootstrap_and_overrides.css index c8916b21..d220c2c2 100644 --- a/app/assets/stylesheets/bootstrap_and_overrides.css +++ b/app/assets/stylesheets/bootstrap_and_overrides.css @@ -1,9 +1,6 @@ /* =require twitter-bootstrap-static/bootstrap - - Use Font Awesome icons (default) - To use Glyphicons sprites instead of Font Awesome, replace with "require twitter-bootstrap-static/sprites" - =require twitter-bootstrap-static/fontawesome + =require twitter-bootstrap-static/sprites */ .no-padding { diff --git a/app/assets/stylesheets/events.css b/app/assets/stylesheets/events.css index 80b9c9dc..bc6b05f6 100644 --- a/app/assets/stylesheets/events.css +++ b/app/assets/stylesheets/events.css @@ -27,3 +27,60 @@ .tooltip .btn[disabled] { pointer-events: none; } + +/* styles for the event preview (every item in an event list) */ +.event-preview { + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + margin: 15px 0; + padding-bottom: 15px; +} +.event-preview.event-past { + opacity: 0.7; +} +.front-section:nth-child(even) .event-preview { + border-bottom: 1px solid rgba(255, 255, 255, 0.3); +} +.event-list .event-preview:last-of-type { + border-bottom: none; +} +.event-preview h3 { + margin-top: 0; +} +.event-date { + text-align: center; + line-height: 3em; + margin-right: 15px; + float: left; +} +.event-date > span { + display: block; +} +.event-day { + font-weight: 800; + font-size: 4em; +} +.event-month { + font-size: 2em; + font-weight: 100; +} +.event-year { + margin: -1.2em 0; +} +@media (max-width: 768px) { + .event-date { + float: none; + margin-bottom: 15px; + } + .event-day:after { + content: '.'; + } + .event-year { + } + .event-date > span { + margin-left: 5px; + font-weight: 100; + display: inline-block; + vertical-align: middle; + font-size: 1.5em; + } +} diff --git a/app/assets/stylesheets/scaffold.css b/app/assets/stylesheets/scaffold.css index 4ca09b20..a7a52df2 100644 --- a/app/assets/stylesheets/scaffold.css +++ b/app/assets/stylesheets/scaffold.css @@ -1,22 +1,9 @@ -body { background-color: #fff; color: #333; } - -body, p, ol, ul, td { - font-family: verdana, arial, helvetica, sans-serif; - font-size: 13px; - line-height: 18px; -} - pre { background-color: #eee; padding: 10px; font-size: 11px; } -/* not-selector to prevent override of bootstrap button color */ -a:not(.btn) { color: #000; } -a:visited:not(.btn) { color: #666; } -a:hover:not(.btn) { color: #fff; background-color:#000; } - .field, .actions { margin-bottom: 10px; } diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2520217d..8efcadb1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -13,7 +13,14 @@ class ApplicationController < ActionController::Base end def index - + # FIXME application-side filtering isn't all that great, but + # unless we want to write custom SQL joins (which + # we should if this becomes a perf problem), there is no + # other solution + @events = Event.sorted_by_start_date(true) + .select { |a| a.start_date > Time.now } + .first(3) + render 'index', locals: { full_width: true } end protected diff --git a/app/controllers/application_letters_controller.rb b/app/controllers/application_letters_controller.rb index d1c71fb8..040d0df3 100644 --- a/app/controllers/application_letters_controller.rb +++ b/app/controllers/application_letters_controller.rb @@ -43,7 +43,7 @@ def create @application_letter.user_id = current_user.id if @application_letter.save - redirect_to @application_letter, notice: 'Application was successfully created.' + redirect_to @application_letter, notice: I18n.t('application_letters.successful_creation') else render :new end diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index c4eb82fa..75f0e6df 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -5,7 +5,7 @@ class EventsController < ApplicationController # GET /events def index - @events = Event.draft_is false + @events = Event.sorted_by_start_date(!can?(:edit, Event)).reverse end # GET /events/1 @@ -13,6 +13,7 @@ def show @free_places = @event.compute_free_places @occupied_places = @event.compute_occupied_places @application_letters = filter_application_letters(@event.application_letters) + @material_files = get_material_files(@event) end # GET /events/new @@ -108,6 +109,26 @@ def send_rejection_emails render :email end + # POST /events/1/upload_material + def upload_material + event = Event.find(params[:event_id]) + material_path = event.material_path + Dir.mkdir(material_path) unless File.exists?(material_path) + + file = params[:file_upload] + unless is_file?(file) + redirect_to event_path(event), alert: t("events.material_area.no_file_given") + return false + end + begin + File.write(File.join(material_path, file.original_filename), file.read, mode: "wb") + rescue IOError + redirect_to event_path(event), alert: I18n.t("events.material_area.saving_fails") + return false + end + redirect_to event_path(event), notice: I18n.t("events.material_area.success_message") + end + private # Use callbacks to share common setup or constraints between actions. def set_event @@ -163,4 +184,21 @@ def create_badge_page(pdf, names, index) create_badge(pdf, right, 260, 750 - row * 150) unless right.nil? end end + + # Checks if a file is valid and not empty + # + # @param [ActionDispatch::Http::UploadedFile] is a file object + # @return [Boolean] whether @file is a valid file + def is_file?(file) + file.respond_to?(:open) && file.respond_to?(:content_type) && file.respond_to?(:size) + end + + # Gets all file names stored in the material storage of the event + # + # @param [Event] + # @return [Array of Strings] + def get_material_files(event) + material_path = event.material_path + File.exists?(material_path) ? Dir.glob(File.join(material_path, "*")) : [] + end end diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index 97eb7d77..6d3ae0f2 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -29,9 +29,9 @@ def create if @profile.save if flash[:event_id] - redirect_to new_application_letter_path(:event_id => flash[:event_id]) + redirect_to new_application_letter_path(:event_id => flash[:event_id]), notice: I18n.t('profiles.successful_creation') else - redirect_to @profile + redirect_to @profile, notice: I18n.t('profiles.successful_creation') end else render :new @@ -41,7 +41,7 @@ def create # PATCH/PUT /profiles/1 def update if @profile.update(profile_params) - redirect_to @profile, notice: 'Profile was successfully updated.' + redirect_to @profile, notice: I18n.t('profiles.successful_update') else render :edit end @@ -50,7 +50,7 @@ def update # DELETE /profiles/1 def destroy @profile.destroy - redirect_to profiles_url, notice: 'Profile was successfully destroyed.' + redirect_to profiles_url, notice: I18n.t('profiles.successful_deletion') end private diff --git a/app/controllers/requests_controller.rb b/app/controllers/requests_controller.rb index 06f58720..17d70f10 100644 --- a/app/controllers/requests_controller.rb +++ b/app/controllers/requests_controller.rb @@ -53,6 +53,6 @@ def set_request # Only allow a trusted parameter "white list" through. def request_params - params.require(:request).permit(:topics, :user_id) + params.require(:request).permit(:form_of_address, :first_name, :last_name, :phone_number, :address, :topic_of_workshop, :time_period, :email, :number_of_participants, :knowledge_level, :annotations) end end diff --git a/app/helpers/applicants_overview_helper.rb b/app/helpers/applicants_overview_helper.rb index 7f32cebc..ebe3db81 100644 --- a/app/helpers/applicants_overview_helper.rb +++ b/app/helpers/applicants_overview_helper.rb @@ -6,4 +6,10 @@ def sort_caret(label, attr) #{label} ".html_safe end + + def sort_application_letters + @application_letters.sort_by! {|l| l.user.profile.send(params[:sort]) } if params[:sort] && params[:sort] != 'applicant_age_when_event_starts' + @application_letters.sort_by! {|l| l.send(params[:sort]) } if params[:sort] && params[:sort] == 'applicant_age_when_event_starts' + @application_letters.reverse! if params[:order] == 'descending' + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 99ab9faf..653cac48 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,6 +1,5 @@ module ApplicationHelper def menu_items - (menu_item t(:home, scope: 'navbar'), root_path) + (menu_item t(:events, scope: 'navbar'), events_path) + (menu_item t(:requests, scope: 'navbar'), requests_path) end diff --git a/app/models/ability.rb b/app/models/ability.rb index 68725950..102ade2e 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -45,8 +45,8 @@ def initialize(user) can [:new, :create], Request end if user.role? :coach - # Coaches can view Applications and participants for Event - can [:view_applicants, :view_participants], Event + # Coaches can view Applications and participants for and upload materials for Event + can [:view_applicants, :view_participants, :upload_material], Event can [:view_and_add_notes, :show], ApplicationLetter can [:print_applications], Event end @@ -54,8 +54,8 @@ def initialize(user) can [:index, :show], Profile can [:index, :show, :view_and_add_notes, :update_status], ApplicationLetter cannot :update, ApplicationLetter - # Organizers can view, edit and print Applications, view participants for and manage Events - can [:view_applicants, :edit_applicants, :view_participants, :print_applications, :manage], Event + # Organizers can view, edit and print Applications, view participants for, upload materials for and manage Events + can [:view_applicants, :edit_applicants, :view_participants, :print_applications, :manage, :upload_material], Event can :manage, Request end if user.role? :admin diff --git a/app/models/agreement_letter.rb b/app/models/agreement_letter.rb index 433f2c92..74d0a5c4 100644 --- a/app/models/agreement_letter.rb +++ b/app/models/agreement_letter.rb @@ -9,6 +9,7 @@ # created_at :datetime not null # updated_at :datetime not null # + class AgreementLetter < ActiveRecord::Base belongs_to :user belongs_to :event @@ -74,6 +75,9 @@ def valid_file?(file) elsif wrong_filetype?(file) errors.add(:file, I18n.t("agreement_letters.wrong_filetype")) false + elsif unable_to_open?(file) + errors.add(:file, I18n.t("agreement_letters.corrupt_document")) + false else true end @@ -90,4 +94,13 @@ def too_big?(file) def wrong_filetype?(file) file.content_type != ALLOWED_MIMETYPE end + + def unable_to_open? file + begin + PDF::Inspector::Page.analyze_file(file.open) + false + rescue PDF::Reader::UnsupportedFeatureError, PDF::Reader::MalformedPDFError + true + end + end end diff --git a/app/models/application_letter.rb b/app/models/application_letter.rb index e124a4a2..7c6d3a38 100644 --- a/app/models/application_letter.rb +++ b/app/models/application_letter.rb @@ -83,4 +83,12 @@ def status_cannot_be_changed errors.add(:event, "Die Bewerbungen wurden bereits bearbeitet, eine Statusänderung ist nicht mehr erlaubt.") end end + + # Returns the age of the user based on the date the event starts + # + # @param none + # @return [Int] for age as number of years + def applicant_age_when_event_starts + user.profile.age_at_time(event.start_date) + end end diff --git a/app/models/event.rb b/app/models/event.rb index 7b701c1f..9b23e7b3 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -15,6 +15,7 @@ class Event < ActiveRecord::Base UNREASONABLY_LONG_DATE_SPAN = 300 + TRUNCATE_DESCRIPTION_TEXT_LENGTH = 250 has_many :application_letters has_many :agreement_letters @@ -154,6 +155,40 @@ def compute_occupied_places application_letters.where(status: ApplicationLetter.statuses[:accepted]).count end + # Returns a label listing the number of days to the deadline if + # it's <= 7 days to go. Otherwise returns nil. + # + # @return string containing the label or nil + def application_deadline_label + days = (application_deadline - Date.current).to_i + I18n.t('events.notices.deadline_approaching', count: days) if days <= 7 and days > 0 + end + + # Uses the start date to determine whether or not this event is in the past (or more + # precisely, in the past or currently running) + # + # @return boolean if it's in the past + def is_past + return start_date < Date.current + end + + # Returns a label that describes the duration of the event in days, + # also mentioning whether or not the event happens on consecutive + # days. If the event is only on a single day, it returns nothing. + # + # @return the duration label or nil + def duration_label + # gotta add 1 since from Sunday to Monday is on two days, but only + # a difference of a single day + days = (end_date - start_date).to_i + 1 + + if date_ranges.size > 1 + I18n.t('events.notices.time_span_non_consecutive', count: days) + elsif days > 1 + I18n.t('events.notices.time_span_consecutive', count: days) + end + end + # Make sure any assignment coming from the controller # replaces all date ranges instead of adding new ones def date_ranges_attributes=(*args) @@ -161,6 +196,13 @@ def date_ranges_attributes=(*args) super(*args) end + # Gets the path of the event in the material storage + # + # @return [String] path in the material storage + def material_path + File.join("storage/materials/", self.id.to_s + "_" + self.name) + end + # Make sure we add errors from our date_range children # to the base event object for displaying validate do |event| @@ -174,6 +216,17 @@ def date_ranges_attributes=(*args) scope :draft_is, ->(draft) { where("draft = ?", draft) } + # Returns events sorted by start date, returning only public ones + # if requested + # + # @param limit Maximum number of events to return + # @param only_public Set to true to not include drafts + # @return List of events + def self.sorted_by_start_date(only_public) + (only_public ? Event.draft_is(false) : Event.all) + .sort_by(&:start_date) + end + protected # Compares two participants to achieve following order: # 1. All participants that have to submit an letter of agreement but did not yet do so, ordered by name. diff --git a/app/models/profile.rb b/app/models/profile.rb index 2288c0d1..e98e4450 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -31,9 +31,16 @@ def adult?() # @param none # @return [Int] for age as number of years def age - now = Time.now.utc.to_date - current_time_is_before_birthday = now.month > birth_date.month || (now.month == birth_date.month && now.day >= birth_date.day) - return now.year - birth_date.year - (current_time_is_before_birthday ? 0 : 1) + return age_at_time(Time.now) + end + + # Returns the age of the user based on the given date + # + # @param none + # @return [Int] for age as number of years + def age_at_time (given_date) + given_date_is_before_birth_date = given_date.month > birth_date.month || (given_date.month == birth_date.month && given_date.day >= birth_date.day) + return given_date.year - birth_date.year - (given_date_is_before_birth_date ? 0 : 1) end # Returns the Full Name of the user diff --git a/app/models/request.rb b/app/models/request.rb index 6a00a6cb..7ccb1f9c 100644 --- a/app/models/request.rb +++ b/app/models/request.rb @@ -3,13 +3,14 @@ # Table name: requests # # id :integer not null, primary key -# topics :string -# user_id :integer not null # created_at :datetime not null # updated_at :datetime not null # class Request < ActiveRecord::Base - belongs_to :user - validates :user, presence: true + validates_presence_of :form_of_address, :last_name, :first_name, :phone_number, :address, :email, :topic_of_workshop + validates :number_of_participants, numericality: { only_integer: true, greater_than: 0 } + validates_format_of :email, :with => Devise::email_regexp + + enum form_of_address: [:mr, :mrs, :prefer_to_omit] end diff --git a/app/models/user.rb b/app/models/user.rb index 8c894600..ab12502a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -79,16 +79,13 @@ def requires_agreement_letter_for_event?(given_event) # @return [Boolean] def older_than_required_age_at_start_date_of_event?(given_event, age) return false unless self.profile - event_start = given_event.start_date - event_start_is_before_birthday = event_start.month > self.profile.birth_date.month || (event_start.month == self.profile.birth_date.month && event_start.day >= self.profile.birth_date.day) - age_at_event_start = event_start.year - self.profile.birth_date.year - (event_start_is_before_birthday ? 0 : 1) - return age_at_event_start >= age + age_at_event_start = self.profile.age_at_time(given_event.start_date) + return age_at_event_start >= age end has_one :profile has_many :application_letters has_many :agreement_letters - has_many :requests # Returns the number of accepted applications from the user without counting status of current event application # diff --git a/app/views/application/index.html.erb b/app/views/application/index.html.erb index c9d3af4b..7c858afd 100644 --- a/app/views/application/index.html.erb +++ b/app/views/application/index.html.erb @@ -1 +1,39 @@ -

<%= t('hello') %>

\ No newline at end of file +
+
+ <%= image_tag "front-welcome.png", class: "center-block img-responsive img-rounded img-float-corner-tr" %> +

<%= t "start_page.hello" %>

+

<%= t "start_page.intro_text" %>

+
+
+ +
+
+

Veranstaltungen + + <%= glyph 'calendar' %> <%= t "start_page.all_events" %> + +

+

<%= t "start_page.intro_text_events" %>

+ + +
+
+ +
+
+

Workshop anfragen

+

<%= t "start_page.intro_text_requests" %>

+

+ + <%= glyph 'send' %> <%= t "start_page.place_request" %> + +

+

<%= t "start_page.outro_text_requests" %>

+
+
+ diff --git a/app/views/application_letters/_form.html.erb b/app/views/application_letters/_form.html.erb index b3bbf79b..0a3e2187 100644 --- a/app/views/application_letters/_form.html.erb +++ b/app/views/application_letters/_form.html.erb @@ -11,9 +11,9 @@
<%= f.label :grade, :class => 'control-label col-lg-2 required' %>
- <%= f.collection_select :grade, ApplicationLetter::VALID_GRADES, :to_s, :to_s, {}, :class => 'form-control' %> + <%= f.collection_select :grade, ApplicationLetter::VALID_GRADES, :to_s, :to_s, {}, :class => 'form-control' %> <%=f.error_span(:grade) %>
- <%=f.error_span(:grade) %> +
<%= f.label :experience, :class => 'control-label col-lg-2 required' %> @@ -71,7 +71,7 @@
<%=f.error_span(:allergies) %> - <%= hidden_field_tag 'event_id', params[:event_id] %> + <%= hidden_field_tag 'event_id', params[:event_id] %>
diff --git a/app/views/application_letters/index.html.erb b/app/views/application_letters/index.html.erb index 6ea46399..0a4e8e7e 100644 --- a/app/views/application_letters/index.html.erb +++ b/app/views/application_letters/index.html.erb @@ -22,7 +22,7 @@ <%= link_to t('.destroy', :default => t("helpers.links.destroy")), application_letter_path(application), :method => :delete, - :data => {:confirm => t('.confirm', :default => t("application_letters.confirm_deletion", :default => 'Are you sure?'))}, + :data => {:confirm => t('.confirm', :default => t("helpers.links.confirm", :default => t("application_letters.confirmApplicationDelete")))}, :class => 'btn btn-xs btn-danger' %> <% end %> diff --git a/app/views/application_letters/show.html.erb b/app/views/application_letters/show.html.erb index 57a7db70..c248a036 100644 --- a/app/views/application_letters/show.html.erb +++ b/app/views/application_letters/show.html.erb @@ -8,8 +8,8 @@
<%= Profile.human_attribute_name(:gender) %>:
<%= @application_letter.user.profile.gender %>
-
<%= Profile.human_attribute_name(:age) %>:
-
<%= @application_letter.user.profile.age %>
+
<%= t('.age_when_event_starts') %>:
+
<%= @application_letter.user.profile.age_at_time(@application_letter.event.start_date) %>
<%= Profile.human_attribute_name(:address) %>:
<%= @application_letter.user.profile.address %>
<%= User.human_attribute_name(:accepted_application_count) %>:
diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index 42c8521c..6a35011c 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -10,19 +10,15 @@ <%= f.email_field :email, autofocus: true, class: "form-control" %>
- <%= f.label :name %> - <%= f.text_field :name, autofocus: true, class: "form-control" %> -
-
- <%= f.label :password %> (<%= t('.leave_blank_if_you_don_t_want_to_change_it', :default => "leave blank if you don't want to change it") %>) + <%= f.label :password %> (<%= t('devise.messages.leave_blank_if_you_don_t_want_to_change_it', :default => "leave blank if you don't want to change it") %>) <%= f.password_field :password, :autocomplete => "off", class: "form-control" %>
- <%= f.label :password_confirmation %> + <%= f.label :password_confirmation %> (<%= t('devise.messages.leave_blank_if_you_don_t_want_to_change_it', :default => "leave blank if you don't want to change it") %>) <%= f.password_field :password_confirmation, class: "form-control" %>
- <%= f.label :current_password %> (<%= t('.we_need_your_current_password_to_confirm_your_changes', :default => 'we need your current password to confirm your changes') %>) + <%= f.label :current_password %> (<%= t('devise.messages.we_need_your_current_password_to_confirm_your_changes', :default => 'we need your current password to confirm your changes') %>) <%= f.password_field :current_password, class: "form-control" %>
@@ -36,4 +32,4 @@

<%= t('.unhappy', :default => 'Unhappy') %>? <%= link_to t('.cancel_my_account', :default => "Cancel my account"), registration_path(resource_name), :data => { :confirm => t('.are_you_sure', :default => "Are you sure?") }, :method => :delete %>.

-<%= link_to t('.back', :default => 'Back'), :back %> +<%= link_to t('.back', :default => t('navigational.back')), :back %> diff --git a/app/views/events/_applicants_overview.html.erb b/app/views/events/_applicants_overview.html.erb index be6bd247..612c5baf 100644 --- a/app/views/events/_applicants_overview.html.erb +++ b/app/views/events/_applicants_overview.html.erb @@ -12,8 +12,8 @@ <%= sort_caret(Profile.human_attribute_name(:gender), :gender) %> - - <%= sort_caret(Profile.human_attribute_name(:age), :age) %> + + <%= sort_caret(( t('.age_when_event_starts')), :applicant_age_when_event_starts ) %> <%= t '.participations' %>
@@ -33,14 +33,12 @@ - <% - @application_letters.sort_by! {|l| l.user.profile.send(params[:sort]) } if params[:sort] - @application_letters.reverse! if params[:order] == 'descending' - @application_letters.select {|l| l.user.profile }.each do | application_letter | %> + <% sort_application_letters + @application_letters.select {|l| l.user.profile }.each do | application_letter |%> <%= application_letter.user.profile.name %> <%= application_letter.user.profile.gender %> - <%= application_letter.user.profile.age %> + <%= application_letter.user.profile.age_at_time(@event.start_date) %> <%= application_letter.user.accepted_applications_count(@event) %> / <%= application_letter.user.rejected_applications_count(@event) %> <%= render :partial => 'application_letters/application_selective', locals: {application_letter: application_letter} %> diff --git a/app/views/events/_event.html.erb b/app/views/events/_event.html.erb new file mode 100644 index 00000000..8bfb5d2e --- /dev/null +++ b/app/views/events/_event.html.erb @@ -0,0 +1,44 @@ +
+ <%= image_tag "example.png", class: "img-rounded img-responsive img-float-corner-tr center-block" %> +
+ <%= l event.start_date, format: "%d" %> + <%= l event.start_date, format: "%b" %> + <% if event.start_date.year != Time.now.year %> + <%= event.start_date.year %> + <% end %> +
+ +

+ <%= event.name %> + + <%= tag_label t('activerecord.attributes.event.draft'), :default if event.draft %> + <%= tag_label t('events.notices.past_event'), :default if event.is_past %> + +

+ +

<%= truncate(event.description, length: Event::TRUNCATE_DESCRIPTION_TEXT_LENGTH) do + link_to " " + I18n.t('events.list.read_on'), event_path(event) + end %>

+ +
+ <%= event.application_deadline_label.try { |label| tag_label label, :default } %> + <%= event.duration_label.try { |label| tag_label label, :default } %> +
+ + <%= link_to t("helpers.links.apply"), new_application_letter_path(:event_id => event.id), class: "btn btn-success btn-sm" %> + + <%= link_to t('events.list.more'), event_path(event), class: "btn btn-default btn-sm" %> + +
+ <%= link_to t('.edit', :default => t('helpers.links.edit')), edit_event_path(event), + :class => 'btn btn-default btn-sm' if can? :edit, event %> + + <%= link_to t('.destroy', :default => t('helpers.links.destroy')), event_path(event), + :method => :delete, + :data => { + :confirm => t('events.confirmation_prompts.confirm_delete', + :default => t("helpers.links.confirm", + :default => 'Löschen kann nicht rückgängig gemacht werden!')) }, + :class => 'btn btn-sm btn-danger' if can? :destroy, event %> +
+
diff --git a/app/views/events/_material_area.html.erb b/app/views/events/_material_area.html.erb new file mode 100644 index 00000000..0e868d02 --- /dev/null +++ b/app/views/events/_material_area.html.erb @@ -0,0 +1,35 @@ +
+

<%= t '.title', title: @event.name %>

+ + + + + + + + + + <% @material_files.each do |file| %> + + + + + <% end %> + +
<%=t '.table_name' %><%=t '.table_type' %>
<%= File.basename(file, File.extname(file)) %><%= File.extname(file) %>
+ + <% if can? :upload_material, Event %> + <%= form_tag(event_upload_material_path(@event), class: 'btn btn-default', multipart: true) do %> + + <%= file_field_tag "file_upload", + class: "btn btn-default btn-file", + style: 'display:inline', + id: "material_upload_#{@event.id}" %> + <%= submit_tag t('.upload'), + class: 'btn btn-default', + id: "material_upload_btn_#{@event.id}"%> + <% end %> + <% end %> +
+
+ diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index 9fc69024..604d414e 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -1,49 +1,19 @@ <%- model_class = Event -%> + +
+ <% if can? :new, Event %> +
+ <%= link_to new_event_path, :class => 'btn btn-primary pull-right' do + glyph('plus') + ' ' + + t('.new', :default => t('helpers.links.new')) + end %> +
+ <% end %> + + <%= render @events %>
- - - - - - - - - - - - - <% @events.each do |event| %> - - - - - - - - - <% end %> - -
<%= model_class.human_attribute_name(:name) %><%= model_class.human_attribute_name(:kind) %><%= model_class.human_attribute_name(:start_date) %><%= model_class.human_attribute_name(:end_date) %><%= model_class.human_attribute_name(:draft) %><%=t '.actions', :default => t("helpers.actions") %>
<%= link_to event.name, event_path(event) %><%= I18n.t "events.kinds.#{event.kind}" %><%= event.start_date %><%= event.end_date %><%= event.draft %> - <% if can? :edit, event %> - <%= link_to t('.edit', :default => t('helpers.links.edit')), - edit_event_path(event), :class => 'btn btn-default btn-xs' %> - <% end %> - <% if can? :destroy, event %> - <%= link_to t('.destroy', :default => t('helpers.links.destroy')), - event_path(event), - :method => :delete, - :data => { :confirm => t('events.confirmation_prompts.confirm_delete', :default => t("helpers.links.confirm", :default => 'Löschen kann nicht rückgängig gemacht werden!')) }, - :class => 'btn btn-xs btn-danger' %> - <% end %> - <%= link_to t('.new', :default => t('helpers.links.apply')), - new_application_letter_path(:event_id => event.id), - :class => 'btn btn-xs btn-primary' %> -
-<% if can? :new, Event %> - <%= link_to t('.new', :default => t('helpers.links.new')), - new_event_path, - :class => 'btn btn-primary' %> -<% end %> \ No newline at end of file diff --git a/app/views/events/show.html.erb b/app/views/events/show.html.erb index a8ae00c0..f2746a63 100644 --- a/app/views/events/show.html.erb +++ b/app/views/events/show.html.erb @@ -17,6 +17,9 @@ <%= render :partial => 'applicants_overview' %> <% end %> +<%= render :partial => 'material_area' %> + + <%= link_to t('.back', :default => t('helpers.links.back')), events_path, :class => 'btn btn-default' %> <% if can? :view_participants, Event %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 3a58af87..09085860 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -2,6 +2,7 @@ Workshop-Portal + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>