From 6dd0b7642de5ad696b6676d23aba8b687ad1f810 Mon Sep 17 00:00:00 2001 From: Bjarne Sievers Date: Thu, 15 Dec 2016 16:36:49 +0100 Subject: [PATCH 01/18] Fix: Task for sample data (#208) * Add rake task db:populate_sample_data * Change function call to ruby style * Add rake task to travis Call db:populate_sample_data on our db on heroku in order to have more test data available * Refactoring populate_sample_data task * Added user sample data * Added profile sample data * Added request, application and agreement letter example data * Cleared seeds.rb * Refactoring sample data * Fixing seeds.rb * Replace Date.today with Date.current. Look at #162 for details * pre merge commit * Add smaple data * Fix sample data * Fix tobis data * Only use create!, not find_or_create_by! Using find_or_create_by on date ranges will try to find date ranges on the same days and then reuse those, potentially leading to reassigning an existing daterange to a new event, leaving the old event without dateranges --- db/sample_data.rb | 61 +++++++++++++ db/sample_data/agreement_letters.rb | 7 ++ db/sample_data/application_letters.rb | 64 +++++++++++++ db/sample_data/events.rb | 116 ++++++++++++++++++++++++ db/sample_data/profiles.rb | 118 ++++++++++++++++++++++++ db/sample_data/requests.rb | 6 ++ db/sample_data/users.rb | 84 +++++++++++++++++ db/seeds.rb | 124 ++------------------------ lib/tasks/sample_data.rake | 8 ++ 9 files changed, 471 insertions(+), 117 deletions(-) create mode 100644 db/sample_data.rb create mode 100644 db/sample_data/agreement_letters.rb create mode 100644 db/sample_data/application_letters.rb create mode 100644 db/sample_data/events.rb create mode 100644 db/sample_data/profiles.rb create mode 100644 db/sample_data/requests.rb create mode 100644 db/sample_data/users.rb create mode 100644 lib/tasks/sample_data.rake diff --git a/db/sample_data.rb b/db/sample_data.rb new file mode 100644 index 00000000..2992e15a --- /dev/null +++ b/db/sample_data.rb @@ -0,0 +1,61 @@ +require './db/sample_data/agreement_letters' +require './db/sample_data/application_letters' +require './db/sample_data/events' +require './db/sample_data/profiles' +require './db/sample_data/requests' +require './db/sample_data/users' + +def add_sample_data + events = Hash.new + events[:bechersaeuberungsevent] = event_bechersaeuberungsevent + events[:gongakrobatik] = event_gongakrobatik + events[:batterie_akustik] = event_batterie_akustik + events[:bachlorpodium] = event_bachlorpodium + events[:programmierkurs] = event_programmierkurs + + users = Hash.new + users[:pupil] = user_pupil + users[:teacher] = user_teacher + users[:applicant] = user_applicant + users[:ptobi] = user_tobi_pupil + users[:tobi] = user_tobi + users[:lisa] = user_lisa + users[:max] = user_max + users[:organizer] = user_organizer + users[:coach] = user_coach + + profiles = Hash.new + profiles[:pupil] = profile_pupil(users[:pupil]) + profiles[:teacher] = profile_teacher(users[:teacher]) + profiles[:applicant] = profile_applicant(users[:applicant]) + + profiles[:tobi] = profile_tobi(users[:tobi]) + profiles[:ptobi] = profile_tobi(users[:ptobi]) + profiles[:lisa] = profile_lisa(users[:lisa]) + profiles[:max] = profile_pupil_1(users[:max]) + profiles[:organizer] = profile_pupil_1(users[:organizer]) + profiles[:coach] = profile_pupil_1(users[:coach]) + + application_letters = Hash.new + application_letters[:applicant_gongakrobatik] = application_letter_applicant_gongakrobatik(users[:applicant], events[:gongakrobatik]) + application_letters[:applicant_programmierkurs_lisa] = application_letter_applicant_programmierkurs_1(users[:lisa], events[:programmierkurs]) + application_letters[:applicant_programmierkurs_max] = application_letter_applicant_programmierkurs_2(users[:max], events[:programmierkurs]) + application_letters[:applicant_programmierkurs_tobi] = application_letter_applicant_programmierkurs_3(users[:ptobi], events[:programmierkurs]) + + requests = Hash.new + requests[:hardware_entwicklung] = request_hardware_entwicklung(users[:teacher]) + + agreement_letters = Hash.new + agreement_letters[:applicant_gongakrobatik] = agreement_letter_applicant_gongakrobatik(users[:applicant], events[:gongakrobatik]) + + [events, users, profiles, application_letters, requests, agreement_letters].each do |models| + save_models(models) + end +end + +private + def save_models(models) + models.each do |key, model| + model.save! + end + end diff --git a/db/sample_data/agreement_letters.rb b/db/sample_data/agreement_letters.rb new file mode 100644 index 00000000..2f558914 --- /dev/null +++ b/db/sample_data/agreement_letters.rb @@ -0,0 +1,7 @@ +def agreement_letter_applicant_gongakrobatik(user, event) + AgreementLetter.new( + user: user, + event: event, + path: "/storage/agreement_letters/foo.pdf" + ) +end \ No newline at end of file diff --git a/db/sample_data/application_letters.rb b/db/sample_data/application_letters.rb new file mode 100644 index 00000000..f40a6580 --- /dev/null +++ b/db/sample_data/application_letters.rb @@ -0,0 +1,64 @@ +def application_letter_applicant_gongakrobatik(user, event) + ApplicationLetter.new( + motivation: "Ich habe vor kurzem davon erfahren und war direkt hellaufbegeistert. Gerne würde ich mich bei Ihnen näher über das Thema informieren", + grade: 10, + experience: "Über einen Facebookpost ihrer Seite bin ich auf das Angebot aufmerksam geworden", + coding_skills: "HTML", + emergency_number: "01234567891", + vegeterian: false, + vegan: false, + allergic: false, + allergies: "", + user: user, + event: event + ) +end + +def application_letter_applicant_programmierkurs_1(user, event) + ApplicationLetter.new( + motivation: "Den normalen Unterricht in der Schule finde ich ziemlich langweilig und würde mich darüber freuen, etwas über den Tellerrand zu schauen und spannende Dinge lernen. Ich arbeite sehr gerne im Team und freue mich darauf, Gleichgesinnte kennen zu lernen.", + grade: 9, + experience: "Über einen Zeitungsartikel", + coding_skills: "For, While und If-Schleifen in Java", + emergency_number: "01234567891", + vegeterian: false, + vegan: false, + allergic: true, + allergies: "Tomaten", + user: user, + event: event + ) +end + +def application_letter_applicant_programmierkurs_2(user, event) + ApplicationLetter.new( + motivation: "Ich habe vor kurzem davon erfahren und war direkt hellaufbegeistert. Gerne würde ich mich bei Ihnen näher über das Thema informieren", + grade: 10, + experience: "Suche im Internet", + coding_skills: "keine", + emergency_number: "01234567891", + vegeterian: true, + vegan: false, + allergic: false, + allergies: "", + user: user, + event: event + ) +end + +def application_letter_applicant_programmierkurs_3(user, event) + ApplicationLetter.new( + motivation: "Ich habe vor LANGEM davon erfahren und war direkt hellaufbegeistert. Gerne würde ich mich bei Ihnen +näher über das Thema informieren", + grade: 10, + experience: "Suche im Internetz", + coding_skills: "absolut keine", + emergency_number: "01234567819", + vegeterian: true, + vegan: false, + allergic: false, + allergies: "", + user: user, + event: event + ) +end \ No newline at end of file diff --git a/db/sample_data/events.rb b/db/sample_data/events.rb new file mode 100644 index 00000000..d7709e73 --- /dev/null +++ b/db/sample_data/events.rb @@ -0,0 +1,116 @@ +def event_programmierkurs + date_range_singleday = DateRange.create!( + start_date: Date.new(2017, 05, 04), + end_date: Date.new(2017, 05, 05) + ) + Event.new( + name: 'Bechersäuberungsevent', + description: 'Ihr wolltet schon immer einmal eine eigene App programmieren? In diesem Workshop lernt ihr object-orientierte Programmierung am Beispiel von einer Android App.', + max_participants: 25, + organizer: 'HPI Schülerklub', + knowledge_level: 'Anfänger', + date_ranges: [date_range_singleday], + application_deadline: Date.tomorrow, + draft: false, + application_status_locked: false + ) +end + +def event_bechersaeuberungsevent + date_range_singleday = DateRange.create!( + start_date: Date.new(2017, 04, 04), + end_date: Date.new(2017, 04, 05) + ) + Event.new( + name: 'Bechersäuberungsevent', + description: 'Es dreht sich den ganzen Tag um das Säubern von Bechern. Wie säubert man einen Becher am +effizientesten oder am schnellsten? Wie immer bieten wir eine Reihe an Expertenvorträgen an. Dieses Mal erfahrt ihr +unter anderem wie ihr Edding-Markierungen selbst nach einer Spülmaschinen-Reinigung noch entfernen könnt oder wie man +die richtige Größe für Becher-Stapel herausfindet und anwendet.', + max_participants: 25, + organizer: 'FSR', + knowledge_level: 'Anfänger', + date_ranges: [date_range_singleday], + application_deadline: Date.tomorrow, + draft: false, + application_status_locked: false + ) +end + +def event_gongakrobatik + date_range_long = DateRange.create!( + start_date: Date.new(2020, 02, 29), + end_date: Date.new(2021, 03, 05) + ) + Event.new( + name: 'Einführung in die Kunst der Gongakrobatik', + description: 'Schon im alten China erzählte man sich von den sa­gen­um­wo­benen Legenden der Gongakrobatik. +Spätestens seit dieser Trend auch seinen Weg nach Japan gefunden hat, stellt sich die Gongakrobatik auch für uns als +ernstzunehmende Alternative gegenüber herkömmlichen Stimmbildungübungen und ähnlichem dar. In dieser Einführung möchten +wir euch einen groben Überblick über das Thema geben: Wie findet man am besten seinen Weg in die Gongakrobatik, was +braucht man dafür. In den letzten Jahren hat sich zudem eine große Community rund um dieses faszinierende Thema gebildet. +Höhepunkt der Veranstaltung ist demnach unser Besuch einer echten Gongmanufaktor im Herzen Berlins, durchgeführt von dem +Ding Gong-Verein Berlin. Bei Bedarf können wir eine zweite Veranstaltung durchführen, bis dahin gilt first come first serve :)', + max_participants: 19, + knowledge_level: 'Ihr braucht kein besonderes Vorwissen, jeder ist Willkommen!', + date_ranges: [date_range_long], + application_deadline: Date.tomorrow, + draft: false, + application_status_locked: false + ) +end + +def event_batterie_akustik + date_range_short = DateRange.create!( + start_date: Date.tomorrow.next_day(3), + end_date: Date.tomorrow.next_day(5) + ) + + date_range_medium = DateRange.create!( + start_date: Date.new(2017, 06, 01), + end_date: Date.new(2017, 06, 14) + ) + Event.new( + name: 'Batterie-Akustik für Fortgeschrittene', + description: 'Viele Menschen sammeln bereits im jungen Alter Erfahrung mit der überaus komplexen Batterie-Akustik. +"Leider wird daraus bei vielen aber nicht mehr als bloßes Jugendwissen, das sich höchstens für den jährlichen Party-Gag +eignet" erklärt Dr. Warta Durazell vom Institut für Angewandte Batterie-Akustik (IAB). Mit dieser Workshop-Serie möchten +wir etwas an diesem Missstand ändern. Wie viele Batterien werden benötigt um einen Echo-Effekt gleichwertig zum +Akkumulator-Echo zu erzeugen? Ist dies überhaupt außerhalb von Laborbedingungen möglich? Die Teilnehmer haben nach den +Veranstaltungen ein fundiertes Wissen über die Klangeigenschaften sowie das (nicht äquivalente) Klangverhalten von +Batterien. Zudem erhalten sie ein offizielles Zertifikat des IAB, welches es ihnen ermöglicht an weiterführenden +Veranstaltungen zum Thema teilzunehmen. Gerade in Zeit von E-Autos ist dies ein wichtiges Alleinstellungsmerkmal auf dem +Arbeitsmarkt. Bitte beachtet die maximale Teilnehmeranzahl! Wichtig: Es gilt first come last served.', + max_participants: 32, + organizer: 'IAB', + date_ranges: [date_range_short, date_range_medium], + application_deadline: Date.tomorrow, + draft: false, + application_status_locked: false + ) +end + +def event_bachlorpodium + date_range_singleday1 = DateRange.create!( + start_date: Date.tomorrow, + end_date: Date.tomorrow + ) + date_range_singleday2 = DateRange.create!( + start_date: Date.new(2017, 04, 04), + end_date: Date.new(2017, 04, 05) + ) + date_range_singleday3 = DateRange.create!( + start_date: Date.new(2017, 04, 06), + end_date: Date.new(2017, 04, 06) + ) + Event.new( + name: 'Bachelorpodium', + description: 'Trotz modernem Videostreaming in HD in die anderen Hörsäle bleibt Hörsaal 1 doch der Publikumsliebling +bei diesem jährlich mit größter Sorgfalt organisierten spektakulären PR Gag', + max_participants: 442, + date_ranges: [date_range_singleday1, date_range_singleday2, date_range_singleday3], + application_deadline: Date.tomorrow, + draft: false, + application_status_locked: false + ) +end diff --git a/db/sample_data/profiles.rb b/db/sample_data/profiles.rb new file mode 100644 index 00000000..e97f2567 --- /dev/null +++ b/db/sample_data/profiles.rb @@ -0,0 +1,118 @@ +def profile_pupil(user) + Profile.new( + user: user, + first_name: "Karl", + last_name: "Doe", + gender: "male", + birth_date: Date.parse('2000.11.29'), + school: "Schule am Griebnitzsee", + street_name: "Rudolf-Breitscheid-Str. 52", + zip_code: "14482", + city: "Potsdam", + state: "Brandenburg", + country: "Deutschland", + graduates_school_in: "2019" + ) +end + +def profile_pupil_1(user) + Profile.new( + user: user, + first_name: "Max", + last_name: "Mustermann", + gender: "male", + birth_date: Date.parse('2000.12.09'), + school: "Musterschule", + street_name: "Musterstraße 42", + zip_code: "14482", + city: "Potsdam", + state: "Brandenburg", + country: "Deutschland", + graduates_school_in: "2018" + ) +end + +def profile_pupil_2(user) + Profile.new( + user: user, + first_name: "Lisa", + last_name: "Schmidt", + gender: "female", + birth_date: Date.parse('2001.02.19'), + school: "Musterschule", + street_name: "Musterstraße 42", + zip_code: "14482", + city: "Potsdam", + state: "Brandenburg", + country: "Deutschland", + graduates_school_in: "2019" + ) +end + +def profile_teacher(user) + Profile.new( + user: user, + first_name: "Ernst", + last_name: "Teacher", + gender: "male", + birth_date: Date.parse('1970.1.1'), + school: "Schule am Griebnitzsee", + street_name: "Domstraße 14", + zip_code: "14482", + city: "Potsdam", + state: "Brandenburg", + country: "Deutschland", + graduates_school_in: "Bereits Abitur" + ) +end + +def profile_applicant(user) + Profile.new( + user: user, + first_name: "Erika", + last_name: "Mustermann", + gender: "female", + birth_date: Date.parse('1999.08.14'), + school: "Schule am Griebnitzsee", + street_name: "Rudolf-Breitscheid-Str. 52", + zip_code: "14482", + city: "Potsdam", + state: "Brandenburg", + country: "Deutschland", + graduates_school_in: "2017" + ) +end + +def profile_tobi(user) + Profile.new( + user: user, + first_name: "Tobias", + last_name: "Dürschmid", + gender: "male", + birth_date: Date.parse('1995.08.31'), + school: "Goetheschule Ilmenau", + street_name: "Stahnsdorfer Str.", + zip_code: "14482", + city: "Potsdam", + state: "Brandenburg", + country: "Deutschland", + graduates_school_in: "Bereits Abitur" + ) +end + +def profile_lisa(user) + Profile.new( + user: user, + first_name: "Lisa", + last_name: "Ihde", + gender: "female", + birth_date: Date.parse('1996.09.21'), + school: "Sophie-Scholl-Gymnasium", + street_name: "Stahnsdorfer Str.", + zip_code: "14482", + city: "Potsdam", + state: "Brandenburg", + country: "Deutschland", + graduates_school_in: "Bereits Abitur" + ) +end \ No newline at end of file diff --git a/db/sample_data/requests.rb b/db/sample_data/requests.rb new file mode 100644 index 00000000..f36e9cb4 --- /dev/null +++ b/db/sample_data/requests.rb @@ -0,0 +1,6 @@ +def request_hardware_entwicklung(user) + Request.new( + topics: "Hardware-Entwicklung mit einem CAD-System", + user: user + ) +end \ No newline at end of file diff --git a/db/sample_data/users.rb b/db/sample_data/users.rb new file mode 100644 index 00000000..613a66d7 --- /dev/null +++ b/db/sample_data/users.rb @@ -0,0 +1,84 @@ +def user_password + "123456" +end + +def user_pupil + User.new( + name: "Schueler", + email: "schueler@example.com", + password: user_password, + role: :pupil + ) +end + +def user_teacher + User.new( + name: "Lehrer", + email: "lehrer@example.com", + password: user_password, + role: :teacher + ) +end + +def user_applicant + User.new( + name: "Bewerber", + email: "bewerber@example.com", + password: user_password, + role: :pupil + ) +end + +def user_max + User.new( + name: "Max Mustermann", + email: "max@schueler.com", + password: user_password, + role: :pupil + ) +end + +def user_lisa + User.new( + name: "Lisa Schmidt", + email: "lisa@schueler.com", + password: user_password, + role: :pupil + ) +end + +def user_tobi + User.new( + name: "Tobias Dürschmid", + email: "tobias.duerschmid@student.hpi.de", + password: user_password, + role: :organizer + ) +end + +def user_tobi_pupil + User.new( + name: "Tobias Dürschmid", + email: "tobias.duerschmid@t-online.de", + password: user_password, + role: :pupil + ) +end + +def user_organizer + User.new( + name: "Organizer", + email: "organizer@workshops.hpi.de", + password: user_password, + role: :admin + ) +end + +def user_coach + User.new( + name: "Coach", + email: "coach@workshops.hpi.de", + password: user_password, + role: :coach + ) +end \ No newline at end of file diff --git a/db/seeds.rb b/db/seeds.rb index 15360e37..9ede90eb 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -2,123 +2,13 @@ # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). # -# Users -users = [] -pupil = User.find_or_initialize_by( - name: "Schueler", - email: "schueler@example.com" +# Create Superuser +admin = User.find_or_initialize_by( + name: "admin", + email: "info@domain.com", + role: :admin ) -users.push(pupil) +admin.password = "system" +admin.save! -teacher = User.find_or_initialize_by( - name: "Lehrer", - email: "lehrer@example.com" -) -users.push(teacher) - -applicant = User.find_or_initialize_by( - name: "Bewerber", - email: "bewerber@example.com" -) -users.push(applicant) - -# Set a password for every user -# They are only initialized, save them to the db -users.each do |user| - user.password = "123456" - user.save! -end - -date_range = DateRange.find_or_create_by!( - start_date: Date.tomorrow.next_day(3), - end_date: Date.tomorrow.next_day(5) -) - -# An event -event = Event.new( - name: "Messung und Verarbeitung von Umweltdaten", - description: "Veranstaltung mit Phidgets und Etoys", - max_participants: 20, - application_deadline: Date.tomorrow, - draft: false, - application_status_locked: false -) -event.date_ranges << date_range -event.save - -# Pupil's profile -Profile.find_or_create_by!( - user: pupil, - first_name: "Karl", - last_name: "Doe", - gender: "male", - birth_date: Date.parse('2000.11.29'), - school: "Schule am Griebnitzsee", - street_name: "Rudolf-Breitscheid-Str. 52", - zip_code: "14482", - city: "Potsdam", - state: "Brandenburg", - country: "Deutschland", - graduates_school_in: "2019" -) - -# Teacher's profile -Profile.find_or_create_by!( - user: teacher, - first_name: "Ernst", - last_name: "Teacher", - gender: "male", - birth_date: Date.parse('1970.1.1'), - school: "Schule am Griebnitzsee", - street_name: "Domstraße 14", - zip_code: "14482", - city: "Potsdam", - state: "Brandenburg", - country: "Deutschland", - graduates_school_in: "Bereits Abitur" -) - -# Applicant's profile -Profile.find_or_create_by!( - user: applicant, - first_name: "Erika", - last_name: "Mustermann", - gender: "female", - birth_date: Date.parse('1999.08.14'), - school: "Schule am Griebnitzsee", - street_name: "Rudolf-Breitscheid-Str. 52", - zip_code: "14482", - city: "Potsdam", - state: "Brandenburg", - country: "Deutschland", - graduates_school_in: "2017" -) - -# Teacher's event request -Request.find_or_create_by!( - topics: "Hardware-Entwicklung mit einem CAD-System", - user: teacher -) - -# Applicant's application letter -ApplicationLetter.find_or_create_by!( - motivation: "Ich würde sehr gerne an eurer Veranstaltung teilnehmen", - grade: 10, - experience: "Internet", - coding_skills: "HTML", - emergency_number: "01234567891", - vegeterian: false, - vegan: false, - allergic: false, - allergies: "", - status: ApplicationLetter.statuses[:pending], - user: applicant, - event: event -) - -AgreementLetter.find_or_create_by!( - user: applicant, - event: event, - path: "/storage/agreement_letters/foo.pdf" -) diff --git a/lib/tasks/sample_data.rake b/lib/tasks/sample_data.rake new file mode 100644 index 00000000..1421a6d3 --- /dev/null +++ b/lib/tasks/sample_data.rake @@ -0,0 +1,8 @@ +require './db/sample_data' + +namespace :db do + desc 'Populates the database with sample data' + task populate_sample_data: :environment do + add_sample_data + end +end \ No newline at end of file From ea62eb1af4661d9f9bb0aa009419918d19b88e5e Mon Sep 17 00:00:00 2001 From: Bjarne Sievers Date: Thu, 15 Dec 2016 17:08:52 +0100 Subject: [PATCH 02/18] Add travis execution of sample data back in (#211) --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3929e02b..35ee3ee5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,4 +21,5 @@ deploy: run: - rake db:schema:load - rake db:seed + - rake db:populate_sample_data - restart From 31796c070e8167cdd624986291b8dffd69604bf8 Mon Sep 17 00:00:00 2001 From: Alexander Riese Date: Thu, 15 Dec 2016 17:19:04 +0100 Subject: [PATCH 03/18] 45 3.11 Update access rights for application status update (#183) * Failing test for #45: change application status with radio buttons * Implementation for #45: add radio buttons to change application status * Failing test for #45: add feature tests to ensure access rights * Implementation for #45: add functionality to ensure access rights * Implementation for #45: use elsif in erb file * Implementation for #45: Set default value for application statuses to pending * Implementation for #45: Add migration for default status value * Merge for #45: Update database schema * Merge for #45: Solve merge conflict * Refactoring for #45: add/use specialized application letter factories * Refactoring for #45: Realize Feedback from PR * Refactoring for #45: Remove legacy "status: true" * Implementation for #45: Add exception handling if redirect back doesn't work * Update for #45: Update factory for rejected application letters * Refs #54: Give organizers the power to update application letters * WIP Refs #45: add update_status as own controller action * WIP Refs #45: Comment out not working tests * Refs #45: Translate success message to German * Refs #45: Add validation for status in application letter * Refs #45: Solve merge conflict in schema.rb * Refs #45: Add tests to ensure that pupils and coaches cannot change application status --- .../application_letters_controller.rb | 18 +++++++- app/models/ability.rb | 3 ++ app/models/application_letter.rb | 2 + .../_application_selective.html.erb | 2 +- config/locales/de.application_letters.yml | 1 + config/routes.rb | 3 ++ .../application_letters_controller_spec.rb | 43 +++++++++++++++++-- spec/models/ability_spec.rb | 18 ++++++++ 8 files changed, 83 insertions(+), 7 deletions(-) diff --git a/app/controllers/application_letters_controller.rb b/app/controllers/application_letters_controller.rb index 084703de..455139ed 100644 --- a/app/controllers/application_letters_controller.rb +++ b/app/controllers/application_letters_controller.rb @@ -52,7 +52,16 @@ def create # PATCH/PUT /applications/1 def update if @application_letter.update_attributes(application_params) - redirect_to :back, notice: 'Application was successfully updated.' rescue ActionController::RedirectBackError redirect_to root_path + redirect_to :back, notice: I18n.t('application_letters.successful_update') rescue ActionController::RedirectBackError redirect_to root_path + else + render :edit + end + end + + # PATCH/PUT /applications/1/status + def update_status + if @application_letter.update_attributes(application_status_param) + redirect_to :back, notice: I18n.t('application_letters.successful_update') rescue ActionController::RedirectBackError redirect_to root_path else render :edit end @@ -73,6 +82,11 @@ def set_application # Only allow a trusted parameter "white list" through. # Don't allow user_id as you shouldn't be able to set the user from outside of create/update. def application_params - params.require(:application_letter).permit(:grade, :experience, :motivation, :coding_skills, :emergency_number, :vegeterian, :vegan, :allergic, :allergies, :user_id, :event_id, :status) + params.require(:application_letter).permit(:grade, :experience, :motivation, :coding_skills, :emergency_number, :vegeterian, :vegan, :allergic, :allergies, :user_id, :event_id) + end + + # Only allow to update the status + def application_status_param + params.require(:application_letter).permit(:status) end end diff --git a/app/models/ability.rb b/app/models/ability.rb index 42e55e3f..34d6f0a1 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -51,8 +51,11 @@ def initialize(user) if user.role? :organizer can [:index, :show], Profile can [:index, :show, :view_and_add_notes], ApplicationLetter + cannot :update, ApplicationLetter + can :update_status, ApplicationLetter # Organizers can view and edit Applications and view participants for Events can [:view_applicants, :edit_applicants, :view_participants], Event + end if user.role? :admin can :manage, :all diff --git a/app/models/application_letter.rb b/app/models/application_letter.rb index da35c0b4..c22cfad1 100644 --- a/app/models/application_letter.rb +++ b/app/models/application_letter.rb @@ -27,6 +27,8 @@ class ApplicationLetter < ActiveRecord::Base validate :status_cannot_be_changed, :if => Proc.new { |letter| letter.status_changed?} enum status: {accepted: 1, rejected: 0, pending: 2, alternative: 3} + validates :status, inclusion: { in: statuses.keys } + # Checks if the deadline is over # additionally only return if event and event.application_deadline is present diff --git a/app/views/application_letters/_application_selective.html.erb b/app/views/application_letters/_application_selective.html.erb index 6b770a64..c2c3a012 100644 --- a/app/views/application_letters/_application_selective.html.erb +++ b/app/views/application_letters/_application_selective.html.erb @@ -1,5 +1,5 @@ <% if can? :edit_applicants, Event and not (application_letter.event.application_status_locked == true) %> - <%= form_for :application_letter, url: application_letter_path(application_letter), html: {method: :put} do |f| %> + <%= form_for :application_letter, url: update_application_letter_status_path(application_letter), html: {method: :put} do |f| %>
<% ApplicationLetter.statuses.keys.each do |key| %> diff --git a/config/locales/de.application_letters.yml b/config/locales/de.application_letters.yml index 6c6e077a..553b1696 100644 --- a/config/locales/de.application_letters.yml +++ b/config/locales/de.application_letters.yml @@ -14,6 +14,7 @@ de: Programmierkenntnisse sind keine Voraussetzung zur Teilnahme. Diese Information wird zur Gruppeneinteilung benötigt." login_before_creation: "Du musst angemeldet sein, um dich für Workshops bewerben zu können." + successful_update: "Die Bewerbung wurde erfolgreich aktualisiert" fill_in_profile_before_creation: "Du musst erst dein Profil ausfüllen, um dich für Workshops bewerben zu können." activerecord: diff --git a/config/routes.rb b/config/routes.rb index f5688550..05b5f902 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,9 @@ get 'agreement_letters/show' resources :requests + + put 'applications/:id/status' => 'application_letters#update_status', as: :update_application_letter_status + resources :application_letters, path: 'applications' do resources :application_notes, only: :create diff --git a/spec/controllers/application_letters_controller_spec.rb b/spec/controllers/application_letters_controller_spec.rb index 4d5feaad..19ee27ee 100644 --- a/spec/controllers/application_letters_controller_spec.rb +++ b/spec/controllers/application_letters_controller_spec.rb @@ -78,8 +78,7 @@ vegeterian: true, vegan: true, allergic: true, - allergys: "Many", - status: "accepted" + allergys: "Many" } } @@ -87,7 +86,6 @@ put :update, id: @application.to_param, application_letter: new_attributes, session: valid_session @application.reload expect(@application.motivation).to eq(new_attributes[:motivation]) - expect(@application.status).to eq(new_attributes[:status]) end it "assigns the requested application as @application" do @@ -114,6 +112,43 @@ end end + describe "PUT #update_status" do + before :each do + sign_in FactoryGirl.create(:user, role: :admin) + end + context "with valid params" do + let(:new_status) { {status: 'accepted'} } + + it "assigns the requested application as @application" do + put :update_status, id: @application.to_param, application_letter: new_status, session: valid_session + expect(assigns(:application_letter)).to eq(@application) + end + + it "updates the status" do + put :update_status, id: @application.to_param, application_letter: new_status, session: valid_session + @application.reload + expect(@application.status).to eq(new_status[:status]) + end + + it "redirects back" do + put :update_status, id: @application.to_param, application_letter: new_status, session: valid_session + expect(response).to redirect_to(request.env['HTTP_REFERER']) + end + end + + context "with invalid params" do + it "assigns the application as @application" do + put :update_status, id: @application.to_param, application_letter: {status: nil}, session: valid_session + expect(assigns(:application_letter)).to eq(@application) + end + + it "re-renders the 'edit' template" do + put :update_status, id: @application.to_param, application_letter: {status: nil}, session: valid_session + expect(response).to render_template("edit") + end + end + end + describe "DELETE #destroy" do it "destroys the requested application" do expect { @@ -163,4 +198,4 @@ end end end -end \ No newline at end of file +end diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index 1eb745c5..b401f436 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -149,4 +149,22 @@ expect(ability).to_not be_able_to(:update, another_application) expect(ability).to_not be_able_to(:destroy, another_application) end + + %i[pupil coach].each do |role| + it "cannot update application letter status as #{role}" do + user = FactoryGirl.create(:user, role: role) + ability = Ability.new(user) + + expect(ability).to_not be_able_to(:update_status, ApplicationLetter) + end + end + + it "can update application letter status as organizer" do + user = FactoryGirl.create(:user, role: :organizer) + another_user = FactoryGirl.create(:user) + another_application = FactoryGirl.create(:application_letter, user: another_user) + ability = Ability.new(user) + + expect(ability).to be_able_to(:update_status, another_application) + end end From a1170329291323ac773ff021e302a4670a806efd Mon Sep 17 00:00:00 2001 From: Bjarne Sievers Date: Thu, 15 Dec 2016 17:36:17 +0100 Subject: [PATCH 04/18] Add german plural of "Veranstaltung", the german translation of "event" of events#index. (Closes #77) (#212) --- app/views/events/index.html.erb | 2 +- config/locales/de.events.yml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index e7d71f97..def1fb30 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -1,6 +1,6 @@ <%- model_class = Event -%> diff --git a/config/locales/de.events.yml b/config/locales/de.events.yml index c25ceb60..f7bc45db 100644 --- a/config/locales/de.events.yml +++ b/config/locales/de.events.yml @@ -59,7 +59,9 @@ de: activerecord: models: - event: "Veranstaltung" + event: + one: "Veranstaltung" + other: "Veranstaltungen" attributes: event: name: "Name" From 44219da4df53223fbc2cedcd62d4c2724b4a06f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20D=C3=BCrschmid?= Date: Thu, 15 Dec 2016 19:38:40 +0100 Subject: [PATCH 05/18] Improve Sample Data (#213) * Improve Sample Data * Fix sample data * Add test for adding sample data to database --- db/sample_data.rb | 19 ++++++++++++------- db/sample_data/events.rb | 22 +++++++++++++++++++++- db/sample_data/profiles.rb | 19 +------------------ db/sample_data/users.rb | 11 +---------- spec/db/seeds_spec.rb | 8 ++++++++ 5 files changed, 43 insertions(+), 36 deletions(-) diff --git a/db/sample_data.rb b/db/sample_data.rb index 2992e15a..b695a74d 100644 --- a/db/sample_data.rb +++ b/db/sample_data.rb @@ -7,17 +7,18 @@ def add_sample_data events = Hash.new + + events[:programmierkurs] = event_programmierkurs + events[:mintcamp] = event_mintcamp events[:bechersaeuberungsevent] = event_bechersaeuberungsevent events[:gongakrobatik] = event_gongakrobatik events[:batterie_akustik] = event_batterie_akustik events[:bachlorpodium] = event_bachlorpodium - events[:programmierkurs] = event_programmierkurs users = Hash.new users[:pupil] = user_pupil users[:teacher] = user_teacher users[:applicant] = user_applicant - users[:ptobi] = user_tobi_pupil users[:tobi] = user_tobi users[:lisa] = user_lisa users[:max] = user_max @@ -30,17 +31,21 @@ def add_sample_data profiles[:applicant] = profile_applicant(users[:applicant]) profiles[:tobi] = profile_tobi(users[:tobi]) - profiles[:ptobi] = profile_tobi(users[:ptobi]) + profiles[:tobi] = profile_tobi(users[:tobi]) profiles[:lisa] = profile_lisa(users[:lisa]) - profiles[:max] = profile_pupil_1(users[:max]) - profiles[:organizer] = profile_pupil_1(users[:organizer]) - profiles[:coach] = profile_pupil_1(users[:coach]) + profiles[:max] = profile_pupil_max(users[:max]) + profiles[:organizer] = profile_pupil_max(users[:organizer]) + profiles[:coach] = profile_pupil_max(users[:coach]) application_letters = Hash.new application_letters[:applicant_gongakrobatik] = application_letter_applicant_gongakrobatik(users[:applicant], events[:gongakrobatik]) application_letters[:applicant_programmierkurs_lisa] = application_letter_applicant_programmierkurs_1(users[:lisa], events[:programmierkurs]) application_letters[:applicant_programmierkurs_max] = application_letter_applicant_programmierkurs_2(users[:max], events[:programmierkurs]) - application_letters[:applicant_programmierkurs_tobi] = application_letter_applicant_programmierkurs_3(users[:ptobi], events[:programmierkurs]) + application_letters[:applicant_programmierkurs_tobi] = application_letter_applicant_programmierkurs_3(users[:tobi], events[:programmierkurs]) + + application_letters[:applicant_mintcamp_lisa] = application_letter_applicant_programmierkurs_1(users[:lisa], events[:mintcamp]) + application_letters[:applicant_mintcamp_max] = application_letter_applicant_programmierkurs_2(users[:max], events[:mintcamp]) + application_letters[:applicant_mintcamp_tobi] = application_letter_applicant_programmierkurs_3(users[:tobi], events[:mintcamp]) requests = Hash.new requests[:hardware_entwicklung] = request_hardware_entwicklung(users[:teacher]) diff --git a/db/sample_data/events.rb b/db/sample_data/events.rb index d7709e73..ca57bbae 100644 --- a/db/sample_data/events.rb +++ b/db/sample_data/events.rb @@ -3,8 +3,9 @@ def event_programmierkurs start_date: Date.new(2017, 05, 04), end_date: Date.new(2017, 05, 05) ) + Event.new( - name: 'Bechersäuberungsevent', + name: 'Android Programmierkurs', description: 'Ihr wolltet schon immer einmal eine eigene App programmieren? In diesem Workshop lernt ihr object-orientierte Programmierung am Beispiel von einer Android App.', max_participants: 25, organizer: 'HPI Schülerklub', @@ -16,6 +17,25 @@ def event_programmierkurs ) end +def event_mintcamp + date_range_mint_camp = DateRange.create!( + start_date: Date.new(2017, 03, 30), + end_date: Date.new(2017, 04, 04) + ) + + Event.new( + name: 'MINT-Camp', + description: 'Wie soll die digitale Zukunft in den Schulen aussehen? In immer mehr Schulen kommen Smartboards zum Einsatz. Diese elektronischen Tafeln haben das Potenzial den Unterricht und das Lernen nachhaltig zu verbessern. Häufig wird das Gerät allerdings auf seinen älteren Verwandten reduziert und nur zum Schreiben, bestenfalls auch für die Medienwiedergabe genutzt. Der Grund dafür sind meist schwer verständliche Programme, die weder die Bedürfnisse der Schüler noch die der Lehrer erfüllen. Dabei sind weitaus interessantere und vor allem sinnvollere Anwendungen für die intelligenten Tafeln denkbar. In diesem MINT-Camp entwickeln wir in kleinen Teams zunächst mit Hilfe von Design Thinking spannende neuartige Ideen für Smartboards. Anschließend werden die Ideen mit Webtechnologien implementiert und können direkt ausprobiert werden. Zum Abschluss hat jedes Team die Möglichkeit seine fertig entwickelte Anwendung zu präsentieren. Dabei stehen euch die ganze Zeit HPI-Studenten zur Seite und helfen euch bei Problemen aller Art. Vorkenntnisse sind keine erforderlich. ', + max_participants: 25, + organizer: 'HPI Schülerklub', + knowledge_level: 'Fortgeschrittene', + date_ranges: [date_range_mint_camp], + application_deadline: Date.tomorrow, + draft: false, + application_status_locked: false + ) +end + def event_bechersaeuberungsevent date_range_singleday = DateRange.create!( start_date: Date.new(2017, 04, 04), diff --git a/db/sample_data/profiles.rb b/db/sample_data/profiles.rb index e97f2567..7d9d2d61 100644 --- a/db/sample_data/profiles.rb +++ b/db/sample_data/profiles.rb @@ -15,7 +15,7 @@ def profile_pupil(user) ) end -def profile_pupil_1(user) +def profile_pupil_max(user) Profile.new( user: user, first_name: "Max", @@ -32,23 +32,6 @@ def profile_pupil_1(user) ) end -def profile_pupil_2(user) - Profile.new( - user: user, - first_name: "Lisa", - last_name: "Schmidt", - gender: "female", - birth_date: Date.parse('2001.02.19'), - school: "Musterschule", - street_name: "Musterstraße 42", - zip_code: "14482", - city: "Potsdam", - state: "Brandenburg", - country: "Deutschland", - graduates_school_in: "2019" - ) -end - def profile_teacher(user) Profile.new( user: user, diff --git a/db/sample_data/users.rb b/db/sample_data/users.rb index 613a66d7..c760f8db 100644 --- a/db/sample_data/users.rb +++ b/db/sample_data/users.rb @@ -40,7 +40,7 @@ def user_max def user_lisa User.new( - name: "Lisa Schmidt", + name: "Lisa Ihde", email: "lisa@schueler.com", password: user_password, role: :pupil @@ -48,15 +48,6 @@ def user_lisa end def user_tobi - User.new( - name: "Tobias Dürschmid", - email: "tobias.duerschmid@student.hpi.de", - password: user_password, - role: :organizer - ) -end - -def user_tobi_pupil User.new( name: "Tobias Dürschmid", email: "tobias.duerschmid@t-online.de", diff --git a/spec/db/seeds_spec.rb b/spec/db/seeds_spec.rb index bc5b9be1..0f56abac 100644 --- a/spec/db/seeds_spec.rb +++ b/spec/db/seeds_spec.rb @@ -1,4 +1,5 @@ require 'rails_helper' +require 'rake' describe 'Seeds' do it 'should seed the database without errors' do @@ -7,4 +8,11 @@ Rails.application.load_seed }.to_not raise_error end +end + +describe 'Sample data' do + it 'should load sample data without errors' do + Rails.application.load_tasks + Rake::Task['db:populate_sample_data'].invoke + end end \ No newline at end of file From a5cc3ff7cb100a1e6200722d6ea763528ee08f28 Mon Sep 17 00:00:00 2001 From: Cornelius Date: Fri, 16 Dec 2016 02:10:27 +0100 Subject: [PATCH 06/18] 100 4.1b pdf is real pdf (#200) * Add corrput PDF check - uploaded agreement letter * fix tests * fix bug: pdf broken after check real pdf * add review comments --- app/models/agreement_letter.rb | 14 ++++++++++++++ config/locales/de.agreement_letters.yml | 1 + .../agreement_letters_controller_spec.rb | 8 ++++---- spec/models/agreement_letter_spec.rb | 13 +++++++++++++ spec/testfiles/another_actual.pdf | Bin 43 -> 8370 bytes 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/app/models/agreement_letter.rb b/app/models/agreement_letter.rb index 433f2c92..494f2e5b 100644 --- a/app/models/agreement_letter.rb +++ b/app/models/agreement_letter.rb @@ -9,6 +9,8 @@ # created_at :datetime not null # updated_at :datetime not null # +require "pdf/inspector" + class AgreementLetter < ActiveRecord::Base belongs_to :user belongs_to :event @@ -74,6 +76,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 +95,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/config/locales/de.agreement_letters.yml b/config/locales/de.agreement_letters.yml index e31849f1..84480278 100644 --- a/config/locales/de.agreement_letters.yml +++ b/config/locales/de.agreement_letters.yml @@ -6,6 +6,7 @@ de: file_too_big: "Die Datei ist zu groß." not_a_file: "Bitte eine Datei angeben." wrong_filetype: "Ungültiger Datentyp." + corrupt_document: "PDF Dokument ist fehlerhaft." upload_success: "Datei erfolgreich hochgeladen." upload_failed: "Fehler beim Hochladen." already_uploaded: "Datei hochgeladen am %{timestamp}" diff --git a/spec/controllers/agreement_letters_controller_spec.rb b/spec/controllers/agreement_letters_controller_spec.rb index 5c47f2cd..26126d3c 100644 --- a/spec/controllers/agreement_letters_controller_spec.rb +++ b/spec/controllers/agreement_letters_controller_spec.rb @@ -21,9 +21,9 @@ post :create, { letter_upload: @file, event_id: @event.id } @agreement_letter = assigns(:agreement_letter) AgreementLetter.where( - user: @user, - event: @event, - path: Rails.root.join('storage/agreement_letters', @agreement_letter.filename).to_s) + user: @user, + event: @event, + path: Rails.root.join('storage/agreement_letters', @agreement_letter.filename).to_s) .take! end end @@ -56,4 +56,4 @@ expect(File.size(@agreement_letter.path)).to eq @another_file.size end end -end +end \ No newline at end of file diff --git a/spec/models/agreement_letter_spec.rb b/spec/models/agreement_letter_spec.rb index 88e0429d..72bf7a8c 100644 --- a/spec/models/agreement_letter_spec.rb +++ b/spec/models/agreement_letter_spec.rb @@ -26,6 +26,12 @@ def mock_writing_to_filesystem fixture_file_upload(filepath, 'text/x-fortran') end + let(:fake_pdf_file) do + extend ActionDispatch::TestProcess + filepath = Rails.root.join('spec/testfiles/fake.pdf') + fixture_file_upload(filepath, 'application/pdf') + end + it "returns the correct filename" do user = @agreement_letter.user event = @agreement_letter.event @@ -75,6 +81,13 @@ def mock_writing_to_filesystem end end + it "does not save a file that is not a real PDF" do + mock_writing_to_filesystem do + expect(@agreement_letter.save_file(fake_pdf_file)).to be false + expect(File.exists?(@agreement_letter.path)).to be false + end + end + it "sets the correct path" do @agreement_letter.set_path path = Rails.root.join('storage', 'agreement_letters', @agreement_letter.filename).to_s diff --git a/spec/testfiles/another_actual.pdf b/spec/testfiles/another_actual.pdf index d2365915978d36996d989e8b8c05aceb5ba05b62..5e84f35a32795474f382f9c7b98d234944c111da 100644 GIT binary patch literal 8370 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 Date: Fri, 16 Dec 2016 07:57:39 +0100 Subject: [PATCH 07/18] Revert "100 4.1b pdf is real pdf (#200)" This reverts commit a5cc3ff7cb100a1e6200722d6ea763528ee08f28. --- app/models/agreement_letter.rb | 14 -------------- config/locales/de.agreement_letters.yml | 1 - .../agreement_letters_controller_spec.rb | 8 ++++---- spec/models/agreement_letter_spec.rb | 13 ------------- spec/testfiles/another_actual.pdf | Bin 8370 -> 43 bytes 5 files changed, 4 insertions(+), 32 deletions(-) diff --git a/app/models/agreement_letter.rb b/app/models/agreement_letter.rb index 494f2e5b..433f2c92 100644 --- a/app/models/agreement_letter.rb +++ b/app/models/agreement_letter.rb @@ -9,8 +9,6 @@ # created_at :datetime not null # updated_at :datetime not null # -require "pdf/inspector" - class AgreementLetter < ActiveRecord::Base belongs_to :user belongs_to :event @@ -76,9 +74,6 @@ 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 @@ -95,13 +90,4 @@ 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/config/locales/de.agreement_letters.yml b/config/locales/de.agreement_letters.yml index 84480278..e31849f1 100644 --- a/config/locales/de.agreement_letters.yml +++ b/config/locales/de.agreement_letters.yml @@ -6,7 +6,6 @@ de: file_too_big: "Die Datei ist zu groß." not_a_file: "Bitte eine Datei angeben." wrong_filetype: "Ungültiger Datentyp." - corrupt_document: "PDF Dokument ist fehlerhaft." upload_success: "Datei erfolgreich hochgeladen." upload_failed: "Fehler beim Hochladen." already_uploaded: "Datei hochgeladen am %{timestamp}" diff --git a/spec/controllers/agreement_letters_controller_spec.rb b/spec/controllers/agreement_letters_controller_spec.rb index 26126d3c..5c47f2cd 100644 --- a/spec/controllers/agreement_letters_controller_spec.rb +++ b/spec/controllers/agreement_letters_controller_spec.rb @@ -21,9 +21,9 @@ post :create, { letter_upload: @file, event_id: @event.id } @agreement_letter = assigns(:agreement_letter) AgreementLetter.where( - user: @user, - event: @event, - path: Rails.root.join('storage/agreement_letters', @agreement_letter.filename).to_s) + user: @user, + event: @event, + path: Rails.root.join('storage/agreement_letters', @agreement_letter.filename).to_s) .take! end end @@ -56,4 +56,4 @@ expect(File.size(@agreement_letter.path)).to eq @another_file.size end end -end \ No newline at end of file +end diff --git a/spec/models/agreement_letter_spec.rb b/spec/models/agreement_letter_spec.rb index 72bf7a8c..88e0429d 100644 --- a/spec/models/agreement_letter_spec.rb +++ b/spec/models/agreement_letter_spec.rb @@ -26,12 +26,6 @@ def mock_writing_to_filesystem fixture_file_upload(filepath, 'text/x-fortran') end - let(:fake_pdf_file) do - extend ActionDispatch::TestProcess - filepath = Rails.root.join('spec/testfiles/fake.pdf') - fixture_file_upload(filepath, 'application/pdf') - end - it "returns the correct filename" do user = @agreement_letter.user event = @agreement_letter.event @@ -81,13 +75,6 @@ def mock_writing_to_filesystem end end - it "does not save a file that is not a real PDF" do - mock_writing_to_filesystem do - expect(@agreement_letter.save_file(fake_pdf_file)).to be false - expect(File.exists?(@agreement_letter.path)).to be false - end - end - it "sets the correct path" do @agreement_letter.set_path path = Rails.root.join('storage', 'agreement_letters', @agreement_letter.filename).to_s diff --git a/spec/testfiles/another_actual.pdf b/spec/testfiles/another_actual.pdf index 5e84f35a32795474f382f9c7b98d234944c111da..d2365915978d36996d989e8b8c05aceb5ba05b62 100644 GIT binary patch literal 43 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 Date: Fri, 16 Dec 2016 17:48:28 +0100 Subject: [PATCH 08/18] 202 1.20 fix date range errors. Fixes #202 (#221) * Failing test * Don't show duplicate errors on multiple date ranges, highlight on error * Make the test just a little more pretty --- app/models/event.rb | 2 +- app/views/events/_form.html.erb | 2 +- spec/features/event_spec.rb | 23 +++++++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/app/models/event.rb b/app/models/event.rb index 4e8e99dc..7b701c1f 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -167,7 +167,7 @@ def date_ranges_attributes=(*args) event.date_ranges.each do |date_range| next if date_range.valid? date_range.errors.full_messages.each do |msg| - errors.add :date_ranges, msg + errors.add :date_ranges, msg unless errors[:date_ranges].include? msg end end end diff --git a/app/views/events/_form.html.erb b/app/views/events/_form.html.erb index c335f382..4202142f 100644 --- a/app/views/events/_form.html.erb +++ b/app/views/events/_form.html.erb @@ -37,7 +37,7 @@
<%= f.label :date_ranges, :class => 'control-label col-lg-2' %> -
+
<% def date_picker_template(start_date = Date.current, end_date = Date.current) start_picker = text_field_tag "event[date_ranges_attributes][][start_date]", (I18n.l start_date), class: 'form-control', :"data-enable-datepicker" => 'true' diff --git a/spec/features/event_spec.rb b/spec/features/event_spec.rb index e84af04d..59c69393 100644 --- a/spec/features/event_spec.rb +++ b/spec/features/event_spec.rb @@ -97,6 +97,29 @@ expect(page).to have_text("Bewerbungsschluss muss vor Beginn der Veranstaltung liegen") end + + it "should not display errors on date ranges twice", js: true do + visit new_event_path + + fill_in "Maximale Teilnehmerzahl", :with => 25 + + within page.find("#event-date-pickers").all("div")[0] do + fill_in "event[date_ranges_attributes][][start_date]", with: I18n.l(Date.current.prev_day(7)) + fill_in "event[date_ranges_attributes][][end_date]", with: I18n.l(Date.yesterday.prev_day(7)) + end + + click_link "Zeitspanne hinzufügen" + + within page.find("#event-date-pickers").all("div")[1] do + fill_in "event[date_ranges_attributes][][start_date]", with: I18n.l(Date.current) + fill_in "event[date_ranges_attributes][][end_date]", with: I18n.l(Date.yesterday) + end + + click_button I18n.t(".events.form.publish") + + expect(page).to have_css("div.has-error") + expect(page).to have_content("kann nicht vor Start-Datum liegen", count: 1) + end end describe "show page" do From db164c405074a8dd23d69321aa205144ca23e2ac Mon Sep 17 00:00:00 2001 From: Lennart L Date: Sat, 17 Dec 2016 18:25:21 +0100 Subject: [PATCH 09/18] 30 4.6 print applications (#190) * Add test for print button Phew that was hard * Add Prawn gem * Add print_applications action to event controller * export and test for dummy pdf. #30 * Add pdf-inspector gem for testing PDF * Move PDF generation to separate class * print basic application detail page #30 * gitignore for storage * Generate overview page for Applications PDF * Empty commit * Add headers and footers to application PDF * Add cans for printing applications * Add translation to Applications PDF * finished applicants detail page, added translation * Fix overview table formatting * added application's annotations to pdf, added more tests. * fixed merge errors * Add documentation --- Gemfile | 8 +- Gemfile.lock | 30 ++-- app/controllers/events_controller.rb | 10 +- app/models/ability.rb | 9 +- .../events/_applicants_overview.html.erb | 6 +- config/locales/de.application_letters.yml | 3 + config/locales/de.events.yml | 7 +- config/locales/de.users.yml | 4 +- config/routes.rb | 1 + lib/pdf_generation/applications_pdf.rb | 158 ++++++++++++++++++ spec/controllers/events_controller_spec.rb | 75 +++++++++ spec/factories/application_letters.rb | 11 ++ spec/models/ability_spec.rb | 14 ++ spec/views/events/show.html.erb_spec.rb | 4 + 14 files changed, 313 insertions(+), 27 deletions(-) create mode 100644 lib/pdf_generation/applications_pdf.rb diff --git a/Gemfile b/Gemfile index 5960abcf..5684c25b 100644 --- a/Gemfile +++ b/Gemfile @@ -80,6 +80,7 @@ gem 'coveralls', require: false # pdf generation gem 'prawn' +gem 'prawn-table' # Simple, Heroku-friendly Rails app configuration using ENV and a single YAML file gem 'figaro' @@ -119,7 +120,7 @@ group :development do # Add a comment summarizing the current schema for models and others # usage: annotate gem 'annotate' - + # opens sent emails in a new browser tab # gem "letter_opener" end @@ -134,8 +135,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' - gem 'pdf-inspector', require: "pdf/inspector" -end + + # PDF testing + gem 'pdf-inspector', require: "pdf/inspector"end group :production do # Use Puma web server diff --git a/Gemfile.lock b/Gemfile.lock index ffd2319b..68e75cc3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -40,7 +40,8 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) - addressable (2.4.0) + addressable (2.5.0) + public_suffix (~> 2.0, >= 2.0.2) afm (0.2.2) airbrake (5.6.1) airbrake-ruby (~> 1.6) @@ -65,7 +66,7 @@ GEM builder (3.2.2) byebug (9.0.6) cancancan (1.15.0) - capybara (2.10.1) + capybara (2.11.0) addressable mime-types (>= 1.16) nokogiri (>= 1.3.3) @@ -73,14 +74,15 @@ GEM rack-test (>= 0.5.4) xpath (~> 2.0) cliver (0.3.2) - codeclimate-test-reporter (1.0.1) + codeclimate-test-reporter (1.0.3) + simplecov coderay (1.1.1) commonjs (0.2.7) concurrent-ruby (1.0.2) - coveralls (0.8.15) + coveralls (0.8.16) json (>= 1.8, < 3) simplecov (~> 0.12.0) - term-ansicolor (~> 1.3) + term-ansicolor (~> 1.3.0) thor (~> 0.19.1) tins (>= 1.6.0, < 2) database_cleaner (1.5.3) @@ -122,7 +124,7 @@ GEM jquery-turbolinks (2.1.0) railties (>= 3.1.0) turbolinks - jquery-ui-rails (5.0.5) + jquery-ui-rails (6.0.1) railties (>= 3.2.16) json (1.8.3) less (2.6.0) @@ -141,7 +143,7 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) mini_portile2 (2.1.0) - minitest (5.9.1) + minitest (5.10.1) nokogiri (1.6.8.1) mini_portile2 (~> 2.1.0) orm_adapter (0.5.0) @@ -165,14 +167,17 @@ GEM prawn (2.1.0) pdf-core (~> 0.6.1) ttfunk (~> 1.4.0) + prawn-table (0.2.2) + prawn (>= 1.3.0, < 3.0.0) 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) - puma (3.6.0) - rack (1.6.4) + public_suffix (2.0.4) + puma (3.6.2) + rack (1.6.5) rack-openid (1.4.2) rack (>= 1.1.0) ruby-openid (>= 2.1.8) @@ -253,12 +258,12 @@ GEM activesupport (>= 4.0) sprockets (>= 3.0.0) sqlite3 (1.3.12) - term-ansicolor (1.4.0) + term-ansicolor (1.3.2) tins (~> 1.0) - thor (0.19.1) + thor (0.19.4) thread_safe (0.3.5) tilt (2.0.5) - tins (1.12.0) + tins (1.13.0) ttfunk (1.4.0) turbolinks (5.0.1) turbolinks-source (~> 5) @@ -315,6 +320,7 @@ DEPENDENCIES pg poltergeist prawn + prawn-table pry pry-rails puma diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 87b05d4a..c4eb82fa 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -1,5 +1,7 @@ +require 'pdf_generation/applications_pdf' + class EventsController < ApplicationController - before_action :set_event, only: [:show, :edit, :update, :destroy] + before_action :set_event, only: [:show, :edit, :update, :destroy, :print_applications] # GET /events def index @@ -84,6 +86,12 @@ def participants @participants = @event.participants_by_agreement_letter end + # GET /events/1/print_applications + def print_applications + authorize! :print_applications, @event + pdf = ApplicationsPDF.generate(@event) + send_data pdf, filename: "applications_#{@event.name}_#{Date.today}.pdf", type: "application/pdf", disposition: "inline" + end # GET /events/1/send-acceptances-email def send_acceptance_emails event = Event.find(params[:id]) diff --git a/app/models/ability.rb b/app/models/ability.rb index 34d6f0a1..34f3f4ae 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -47,15 +47,14 @@ def initialize(user) # Coaches can view Applications and participants for Event can [:view_applicants, :view_participants], Event can [:view_and_add_notes, :show], ApplicationLetter + can [:print_applications], Event end if user.role? :organizer can [:index, :show], Profile - can [:index, :show, :view_and_add_notes], ApplicationLetter + can [:index, :show, :view_and_add_notes, :update_status], ApplicationLetter cannot :update, ApplicationLetter - can :update_status, ApplicationLetter - # Organizers can view and edit Applications and view participants for Events - can [:view_applicants, :edit_applicants, :view_participants], Event - + # Organizers can view, edit and print Applications and view participants for Events + can [:view_applicants, :edit_applicants, :view_participants, :print_applications], Event end if user.role? :admin can :manage, :all diff --git a/app/views/events/_applicants_overview.html.erb b/app/views/events/_applicants_overview.html.erb index b2a6d1af..be6bd247 100644 --- a/app/views/events/_applicants_overview.html.erb +++ b/app/views/events/_applicants_overview.html.erb @@ -55,11 +55,11 @@
- <%= link_to "Alle annehmen", + <%= link_to t('.accept_all'), events_path, :class => 'btn btn-default'%> - <%= link_to "Alle drucken", - events_path, :class => 'btn btn-default'%> + <%= link_to t('.print_all'), + print_applications_event_path(@event.id), :target => "_blank", :class => 'btn btn-default'%>
<% if not @event.applications_classified? %> diff --git a/config/locales/de.application_letters.yml b/config/locales/de.application_letters.yml index 553b1696..3799129e 100644 --- a/config/locales/de.application_letters.yml +++ b/config/locales/de.application_letters.yml @@ -16,6 +16,9 @@ de: login_before_creation: "Du musst angemeldet sein, um dich für Workshops bewerben zu können." successful_update: "Die Bewerbung wurde erfolgreich aktualisiert" fill_in_profile_before_creation: "Du musst erst dein Profil ausfüllen, um dich für Workshops bewerben zu können." + application_page: + title: "Bewerbung von %{name}" + for: "für %{event}" activerecord: models: diff --git a/config/locales/de.events.yml b/config/locales/de.events.yml index f7bc45db..5fbfa63a 100644 --- a/config/locales/de.events.yml +++ b/config/locales/de.events.yml @@ -16,6 +16,8 @@ de: occupied_places: one: '%{count} Platz belegt' other: '%{count} Plätze belegt' + print_all: "Alle ausdrucken" + accept_all: "Alle annehmen" unclassified_applications_left: 'Bewerbung(en) wurden noch nicht klassifiziert' maximum_number_of_participants_exeeded: 'Maximale Teilnehmeranzahl wurde überschritten' sending_acceptances: 'Zusagen verschicken' @@ -32,7 +34,6 @@ de: unnecessary: "nicht benötigt" available: "vorhanden" unavailable: "nicht vorhanden" - kinds: workshop: "Workshop" camp: "Camp" @@ -54,6 +55,10 @@ de: add_timespan: "Zeitspanne hinzufügen" email: templates: "Vorlagen" + applications_pdf: + free_places: "Freie Plätze" + occupied_places: "Belegte Plätze" + page: "Seite" errors: application_deadline_before_start_of_event: "Bewerbungsschluss muss vor Beginn der Veranstaltung liegen" diff --git a/config/locales/de.users.yml b/config/locales/de.users.yml index a6a7a6cb..49ad7922 100644 --- a/config/locales/de.users.yml +++ b/config/locales/de.users.yml @@ -4,5 +4,5 @@ de: activerecord: attributes: user: - accepted_application_count: "Anzahl der angenommenen Bewerbungen" - rejected_application_count: "Anzahl der abgelehnten Bewerbungen" + accepted_application_count: "Angenommene Bewerbungen" + rejected_application_count: "Abgelehnte Bewerbungen" diff --git a/config/routes.rb b/config/routes.rb index 05b5f902..b6cd569f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -12,6 +12,7 @@ end resources :events do resources :agreement_letters, only: [:create], shallow: true + get 'print_applications', on: :member get 'badges' post 'badges' => 'events#print_badges', as: :print_badges end diff --git a/lib/pdf_generation/applications_pdf.rb b/lib/pdf_generation/applications_pdf.rb new file mode 100644 index 00000000..b1e70608 --- /dev/null +++ b/lib/pdf_generation/applications_pdf.rb @@ -0,0 +1,158 @@ +class ApplicationsPDF + include Prawn::View + Prawn::Font::AFM.hide_m17n_warning = true #consider adding TTF font + + # Generates a PDF file containing the details of every application for an event + # + # param event [Event] the event whose applications are taken + # return [String] the generated PDF + def self.generate(event) + self.new(event).create.render + end + + def initialize(event) + @event = event + @document = Prawn::Document.new(page_size: 'A4') + @application_letters_count = @event.application_letters.count + end + + # Adds all necessary data and formatting to the ApplicationsPDF + # + # param none + # return [ApplicationsPDF] self + def create + create_overview + @event.application_letters.each_with_index do |a,i| + create_application_page(a, i) + end + self + end + + private + def create_overview + text t("events.applicants_overview.title", title: @event.name), size: 20 + table description_table_data do + cells.borders = [] + cells.padding = 3 + column(0).font_style = :bold + column(0).align = :right + end + unless @event.application_letters.empty? + table overview_table_data, + header: 2, position: :center, row_colors: ["F9F9F9", "FFFFFF"] do + cells.borders = [] + row(1).borders = [:bottom] + row(1).font_style = :bold + row(0).font_style = :bold + row(0).padding = [5, 0, 5, 5] #minimize padding between first two rows + row(1).padding = [0, 5, 5, 5] + end + end + end + + def description_table_data + data = [[Event.human_attribute_name(:description)+":", @event.description], + [Event.human_attribute_name(:max_participants) + ":", @event.max_participants], + [Event.human_attribute_name(:date_ranges) + ":", @event.date_ranges[0].to_s]] + data += @event.date_ranges.drop(1).map { |d| ["", d.to_s] } + data += [[Event.human_attribute_name(:organizer) + ":", @event.organizer]] if @event.organizer + data += [[Event.human_attribute_name(:knowledge_level) + ":", @event.knowledge_level]] if @event.knowledge_level + data += [[t("events.applications_pdf.free_places") + ":", @event.compute_free_places], + [t("events.applications_pdf.occupied_places") + ":", @event.compute_occupied_places]] + end + + def overview_table_data + #line breaks lead to weird table formatting, so we create 2 header rows to fit all the text + data = [["", "", "", t("events.applicants_overview.participations"), ""]] + data += [[Profile.human_attribute_name(:name), + Profile.human_attribute_name(:gender), + Profile.human_attribute_name(:age), + t("events.applicants_overview.accepted_rejected"), + ApplicationLetter.human_attribute_name(:status)]] + data += @event.application_letters.map do |a| + [a.user.profile.name, + a.user.profile.gender, + a.user.profile.age, + "#{a.user.accepted_applications_count(@event)} / #{a.user.rejected_applications_count(@event)}", + t("application_status.#{a.status}")] + end + end + + def create_application_page(application_letter, index) + start_new_page + first_page = page_number + create_main_header(application_letter) + + bounding_box([bounds.left, bounds.top - 50], + width: bounds.width, + height: bounds.height - 100) do + create_application_page_content(application_letter) + end + + create_headers(application_letter, first_page, page_number) + create_footers(index, first_page, page_number) + end + + def create_application_page_content(application_letter) + table applicants_detail_data(application_letter) do + cells.borders = [] + cells.padding = 3 + column(0).font_style = :bold + column(0).align = :right + end + pad_top(20) { text "#{ApplicationLetter.human_attribute_name(:motivation)}", inline_format: true} + pad_top(5) { text application_letter.motivation } + unless application_letter.application_notes.count == 0 + pad_top(15) do + text "#{ApplicationNote.model_name.human(count: application_letter.application_notes.count)}", inline_format: true + application_letter.application_notes.each do |note| + pad_top(5) { text note.note } + end + end + end + end + + def applicants_detail_data(application_letter) + [[Profile.human_attribute_name(:gender)+":", application_letter.user.profile.gender], + [Profile.human_attribute_name(:age)+":", application_letter.user.profile.age], + [Profile.human_attribute_name(:address)+":", application_letter.user.profile.address], + [User.human_attribute_name(:accepted_application_count)+":", application_letter.user.accepted_applications_count(@event)], + [User.human_attribute_name(:rejected_application_count)+":", application_letter.user.rejected_applications_count(@event)], + [Profile.human_attribute_name(:status)+":", t("application_status.#{application_letter.status}")]] + end + + def create_main_header(application_letter) + text t("application_letters.application_page.title", name: application_letter.user.profile.name), size: 20 + text t("application_letters.application_page.for", event: @event.name), size: 14 + stroke_horizontal_rule + end + + def create_headers(application_letter, first_page, last_page) + repeat(first_page + 1..last_page) do + bounding_box [bounds.left, bounds.top], width: bounds.width do + text @event.name + text_box application_letter.user.profile.name, align: :right + stroke_horizontal_rule + end + end + end + + def create_footers(index, first_page, last_page) + repeat(first_page..last_page, dynamic: true) do + bounding_box [bounds.left, bounds.bottom + 25], width: bounds.width do + relative_page = page_number - first_page + 1 + relative_last_page = last_page - first_page + 1 + stroke_horizontal_rule + move_down(5) + text_box(t("events.applications_pdf.page") + " #{relative_page}/#{relative_last_page}", + at: [0, cursor], + align: :right) + text ApplicationLetter.model_name.human + " #{index + 1}/#{@application_letters_count}" + end + end + end + + def t(string, options = {}) + I18n.t(string, options) + end +end diff --git a/spec/controllers/events_controller_spec.rb b/spec/controllers/events_controller_spec.rb index 59e7d11d..50726465 100644 --- a/spec/controllers/events_controller_spec.rb +++ b/spec/controllers/events_controller_spec.rb @@ -256,4 +256,79 @@ expect(assigns(:event).date_ranges.first.end_date).to eq(date_range.end_date) end end + + describe "GET #print_applications" do + before :each do + @event = Event.create! valid_attributes + @user = FactoryGirl.create(:user, role: :organizer) + sign_in @user + end + + it "returns success" do + get :print_applications, id: @event.to_param, session: valid_session + expect(response).to be_success + end + + it 'returns downloadable PDF' do + get :print_applications, id: @event.to_param, session: valid_session + PDF::Inspector::Text.analyze response.body + end + + it "returns a PDF with a correct overview page" do + get :print_applications, id: @event.to_param, session: valid_session + page_analysis = PDF::Inspector::Page.analyze(response.body) + expect(page_analysis.pages.size).to be 1 + analysis = PDF::Inspector::Text.analyze response.body + text = analysis.strings.join + expect(text).to include( + @event.name, + @event.max_participants.to_s, + @event.organizer, + @event.knowledge_level, + @event.compute_free_places.to_s, + @event.compute_occupied_places.to_s) + @event.date_ranges.each { |d| expect(text).to include(d.to_s) } + end + + it "shows an overview of all and details of every application" do + al = FactoryGirl.create(:application_letter, event: @event,) + FactoryGirl.create(:application_note, application_letter_id: al.id) + User.find_each { |u| FactoryGirl.create(:profile, user: u) } + get :print_applications, id: @event.to_param, session: valid_session + analysis = PDF::Inspector::Text.analyze response.body + text = analysis.strings.join(' ') + @event.application_letters.each do |a| + expect(text).to include( + a.user.profile.name, + a.user.profile.age.to_s, + a.user.profile.gender, + a.user.accepted_applications_count(@event).to_s, + a.user.rejected_applications_count(@event).to_s, + I18n.t("application_status.#{a.status}"), + a.user.profile.address, + a.motivation + ) + a.application_notes.each do |note| + expect(text).to include(note.note) + end + end + end + + it "includes at last one page per application" do + FactoryGirl.create(:application_letter, event: @event,) + FactoryGirl.create(:application_letter2, event: @event,) + User.find_each { |u| FactoryGirl.create(:profile, user: u) } + get :print_applications, id: @event.to_param, session: valid_session + page_analysis = PDF::Inspector::Page.analyze(response.body) + expect(page_analysis.pages.size).to be >= 3 + end + + it "extends long applications over several pages" do + FactoryGirl.create(:application_letter_long, event: @event,) + User.find_each { |u| FactoryGirl.create(:profile, user: u) } + get :print_applications, id: @event.to_param, session: valid_session + page_analysis = PDF::Inspector::Page.analyze(response.body) + expect(page_analysis.pages.size).to be >= 3 + end + end end diff --git a/spec/factories/application_letters.rb b/spec/factories/application_letters.rb index d8476e3b..b0a542b8 100644 --- a/spec/factories/application_letters.rb +++ b/spec/factories/application_letters.rb @@ -25,6 +25,17 @@ event end + factory :application_letter2, parent: :application_letter do + grade 11 + experience "A lot" + motivation "Ich bin sehr motiviert, glaubt mir." + emergency_number "110" + vegeterian true + end + + factory :application_letter_long, parent: :application_letter do + motivation "Ich bin sehr motiviert, glaubt mir." * 200 + end factory :application_letter_deadline_over, parent: :application_letter do association :event, factory: :event, application_deadline: Date.yesterday diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index b401f436..74d3af53 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -106,6 +106,13 @@ expect(ability).to be_able_to(:view_applicants, Event) end + + it "can print an event's applications as #{role}" do + user = FactoryGirl.create(:user, role: role) + ability = Ability.new(user) + + expect(ability).to be_able_to(:print_applications, Event) + end end it "cannot view and add notes to application letters as pupil" do @@ -122,6 +129,13 @@ expect(ability).to_not be_able_to(:view_applicants, Event) end + it "cannot print applications for an event as pupil" do + user = FactoryGirl.create(:user, role: :pupil) + ability = Ability.new(user) + + expect(ability).to_not be_able_to(:print_applications, Event) + end + it "can do everything as admin" do user = FactoryGirl.create(:user, role: :admin) ability = Ability.new(user) diff --git a/spec/views/events/show.html.erb_spec.rb b/spec/views/events/show.html.erb_spec.rb index 7bc3cb70..546eabf5 100644 --- a/spec/views/events/show.html.erb_spec.rb +++ b/spec/views/events/show.html.erb_spec.rb @@ -53,6 +53,10 @@ expect(rendered).to have_link(t(:details, scope: 'events.applicants_overview')) end + it "displays print applications button" do + render + expect(rendered).to have_link(t(:print_all, scope: 'events.applicants_overview')) + end it "displays print badges button" do render From fdbe11131e6a5eb89ce727a2d53b43ba1dfb582f Mon Sep 17 00:00:00 2001 From: Nils Strelow Date: Sun, 18 Dec 2016 17:56:07 +0100 Subject: [PATCH 10/18] remove todo line --- app/models/application_letter.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/models/application_letter.rb b/app/models/application_letter.rb index c22cfad1..0c2a9744 100644 --- a/app/models/application_letter.rb +++ b/app/models/application_letter.rb @@ -32,7 +32,6 @@ class ApplicationLetter < ActiveRecord::Base # Checks if the deadline is over # additionally only return if event and event.application_deadline is present - # TODO: 'event.application_deadline' should never be nil, when #18 is finished. Please remove this in #18. # # @param none # @return [Boolean] true if deadline is over From 96d7e6aeaeb94ea9f8f333d1299833a79b2378e1 Mon Sep 17 00:00:00 2001 From: Nils Strelow Date: Sun, 18 Dec 2016 18:13:15 +0100 Subject: [PATCH 11/18] change application_letters page for #56 --- app/models/application_letter.rb | 21 ++++++++++++++++++++ app/views/application_letters/index.html.erb | 14 ++++--------- config/locales/de.application_letters.yml | 2 ++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/app/models/application_letter.rb b/app/models/application_letter.rb index 0c2a9744..e124a4a2 100644 --- a/app/models/application_letter.rb +++ b/app/models/application_letter.rb @@ -55,6 +55,27 @@ def deadline_cannot_be_in_the_past end end + # Chooses right status based on status and event deadline + # + # @param none + # @return [String] to display on the website + def status_type + case ApplicationLetter.statuses[status] + when ApplicationLetter.statuses[:accepted] + return I18n.t("application_status.accepted") + when ApplicationLetter.statuses[:rejected] + return I18n.t("application_status.rejected") + when ApplicationLetter.statuses[:pending] + if after_deadline? + return I18n.t("application_status.pending_after_deadline") + else + return I18n.t("application_status.pending_before_deadline") + end + else + return I18n.t("application_status.alternative") + end + end + # Validator for status_change_allowed? # Adds error def status_cannot_be_changed diff --git a/app/views/application_letters/index.html.erb b/app/views/application_letters/index.html.erb index 3794c676..cde535fd 100644 --- a/app/views/application_letters/index.html.erb +++ b/app/views/application_letters/index.html.erb @@ -5,11 +5,8 @@
- - - - - + + @@ -17,11 +14,8 @@ <% @application_letters.each do |application| %> <% if can? :destroy, application %> - - - - - + +
<%= model_class.human_attribute_name(:id) %><%= model_class.human_attribute_name(:motivation) %><%= model_class.human_attribute_name(:user_id) %><%= model_class.human_attribute_name(:event_id) %><%= model_class.human_attribute_name(:created_at) %><%= Event.model_name.human(:count => model_class.count).titleize %><%= model_class.human_attribute_name(:status) %> <%=t '.actions', :default => t("helpers.actions") %>
<%= link_to application.id, application_letter_path(application) %><%= application.motivation %><%= application.user_id %><%= application.event_id %><%=l application.created_at %><%= link_to application.event.name, event_path(application.event) %><%= application.status_type %> <%= link_to t('.edit', :default => t("helpers.links.edit")), edit_application_letter_path(application), :class => 'btn btn-default btn-xs' %> diff --git a/config/locales/de.application_letters.yml b/config/locales/de.application_letters.yml index 3799129e..5406e086 100644 --- a/config/locales/de.application_letters.yml +++ b/config/locales/de.application_letters.yml @@ -44,4 +44,6 @@ de: accepted: "Angenommen" rejected: "Abgelehnt" pending: "Ausstehend" + pending_before_deadline: "Beworben" + pending_after_deadline: "In Bearbeitung" alternative: "Nachrücker" From faf6c3f9dae0cbbb00c9c312ecf0e9d8aad43694 Mon Sep 17 00:00:00 2001 From: Nils Strelow Date: Sun, 18 Dec 2016 18:26:13 +0100 Subject: [PATCH 12/18] add sample data for all application statuses --- db/sample_data.rb | 8 +++++++ db/sample_data/application_letters.rb | 34 +++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/db/sample_data.rb b/db/sample_data.rb index b695a74d..5d2e0ea7 100644 --- a/db/sample_data.rb +++ b/db/sample_data.rb @@ -14,6 +14,7 @@ def add_sample_data events[:gongakrobatik] = event_gongakrobatik events[:batterie_akustik] = event_batterie_akustik events[:bachlorpodium] = event_bachlorpodium + events[:past_deadline_event] = event_gongakrobatik users = Hash.new users[:pupil] = user_pupil @@ -39,6 +40,9 @@ def add_sample_data application_letters = Hash.new application_letters[:applicant_gongakrobatik] = application_letter_applicant_gongakrobatik(users[:applicant], events[:gongakrobatik]) + application_letters[:applicant_gongakrobatik_past_deadline] = application_letter_applicant_gongakrobatik(users[:applicant], events[:past_deadline_event]) + application_letters[:applicant_gongakrobatik_accepcted] = application_letter_applicant_gongakrobatik_accepted(users[:applicant], events[:past_deadline_event]) + application_letters[:applicant_gongakrobatik_rejected] = application_letter_applicant_gongakrobatik_rejected(users[:applicant], events[:past_deadline_event]) application_letters[:applicant_programmierkurs_lisa] = application_letter_applicant_programmierkurs_1(users[:lisa], events[:programmierkurs]) application_letters[:applicant_programmierkurs_max] = application_letter_applicant_programmierkurs_2(users[:max], events[:programmierkurs]) application_letters[:applicant_programmierkurs_tobi] = application_letter_applicant_programmierkurs_3(users[:tobi], events[:programmierkurs]) @@ -56,6 +60,10 @@ def add_sample_data [events, users, profiles, application_letters, requests, agreement_letters].each do |models| save_models(models) end + + # set deadline to past to work around validation of application letters + events[:past_deadline_event].application_deadline = Date.yesterday + events[:past_deadline_event].save! end private diff --git a/db/sample_data/application_letters.rb b/db/sample_data/application_letters.rb index f40a6580..51ee71cf 100644 --- a/db/sample_data/application_letters.rb +++ b/db/sample_data/application_letters.rb @@ -14,6 +14,40 @@ def application_letter_applicant_gongakrobatik(user, event) ) end +def application_letter_applicant_gongakrobatik_rejected(user, event) + ApplicationLetter.new( + motivation: "Ich habe vor kurzem davon erfahren und war direkt hellaufbegeistert. Gerne würde ich mich bei Ihnen näher über das Thema informieren", + grade: 10, + experience: "Über einen Facebookpost ihrer Seite bin ich auf das Angebot aufmerksam geworden", + coding_skills: "HTML", + emergency_number: "01234567891", + vegeterian: false, + vegan: false, + allergic: false, + allergies: "", + user: user, + event: event, + status: ApplicationLetter.statuses[:rejected] + ) +end + +def application_letter_applicant_gongakrobatik_accepted(user, event) + ApplicationLetter.new( + motivation: "Den normalen Unterricht in der Schule finde ich ziemlich langweilig und würde mich darüber freuen, etwas über den Tellerrand zu schauen und spannende Dinge lernen. Ich arbeite sehr gerne im Team und freue mich darauf, Gleichgesinnte kennen zu lernen.", + grade: 9, + experience: "Über einen Zeitungsartikel", + coding_skills: "For, While und If-Schleifen in Java", + emergency_number: "01234567891", + vegeterian: false, + vegan: false, + allergic: true, + allergies: "Tomaten", + user: user, + event: event, + status: ApplicationLetter.statuses[:accepted] + ) +end + def application_letter_applicant_programmierkurs_1(user, event) ApplicationLetter.new( motivation: "Den normalen Unterricht in der Schule finde ich ziemlich langweilig und würde mich darüber freuen, etwas über den Tellerrand zu schauen und spannende Dinge lernen. Ich arbeite sehr gerne im Team und freue mich darauf, Gleichgesinnte kennen zu lernen.", From 867c721e51eced41c8cbe61979b435fd7eeaf866 Mon Sep 17 00:00:00 2001 From: Nils Strelow Date: Sun, 18 Dec 2016 21:24:51 +0100 Subject: [PATCH 13/18] filter applications by user instead of using can? in view --- .../application_letters_controller.rb | 2 +- app/views/application_letters/index.html.erb | 46 +++++++++---------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/app/controllers/application_letters_controller.rb b/app/controllers/application_letters_controller.rb index 455139ed..6fc07fff 100644 --- a/app/controllers/application_letters_controller.rb +++ b/app/controllers/application_letters_controller.rb @@ -6,7 +6,7 @@ class ApplicationLettersController < ApplicationController # GET /applications def index - @application_letters = ApplicationLetter.all + @application_letters = ApplicationLetter.where(user_id: current_user.id) end # GET /applications/1 diff --git a/app/views/application_letters/index.html.erb b/app/views/application_letters/index.html.erb index cde535fd..5d5c80b7 100644 --- a/app/views/application_letters/index.html.erb +++ b/app/views/application_letters/index.html.erb @@ -1,32 +1,32 @@ <%- model_class = ApplicationLetter -%> - - - - - + + + + + - <% @application_letters.each do |application| %> - <% if can? :destroy, application %> - - - - - - <% end %> - <% end %> + <% @application_letters.each do |application| %> + + + + + + <% end %>
<%= Event.model_name.human(:count => model_class.count).titleize %><%= model_class.human_attribute_name(:status) %><%=t '.actions', :default => t("helpers.actions") %>
<%= Event.model_name.human(:count => model_class.count).titleize %><%= model_class.human_attribute_name(:status) %><%= t '.actions', :default => t("helpers.actions") %>
<%= link_to application.event.name, event_path(application.event) %><%= application.status_type %> - <%= link_to t('.edit', :default => t("helpers.links.edit")), - edit_application_letter_path(application), :class => 'btn btn-default btn-xs' %> - <%= link_to t('.destroy', :default => t("helpers.links.destroy")), - application_letter_path(application), - :method => :delete, - :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) }, - :class => 'btn btn-xs btn-danger' %> -
<%= link_to application.event.name, event_path(application.event) %><%= application.status_type %> + <% if not application.after_deadline? %> + <%= link_to t('.edit', :default => t("helpers.links.edit")), + edit_application_letter_path(application), :class => 'btn btn-default btn-xs' %> + <%= link_to t('.destroy', :default => t("helpers.links.destroy")), + application_letter_path(application), + :method => :delete, + :data => {:confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?'))}, + :class => 'btn btn-xs btn-danger' %> + <% end %> +
From f074d5007c70fea7fae2b3094b64459f9715799e Mon Sep 17 00:00:00 2001 From: Nils Strelow Date: Sun, 18 Dec 2016 21:25:26 +0100 Subject: [PATCH 14/18] add view tests for #56 --- .../index.html.erb_spec.rb | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 spec/views/application_letters/index.html.erb_spec.rb diff --git a/spec/views/application_letters/index.html.erb_spec.rb b/spec/views/application_letters/index.html.erb_spec.rb new file mode 100644 index 00000000..7b0ea49e --- /dev/null +++ b/spec/views/application_letters/index.html.erb_spec.rb @@ -0,0 +1,50 @@ +require 'rails_helper' + +RSpec.describe "application_letters/index", type: :view do + + context "checks states of applications" do + it "checks if page displays accepted application" do + @application_letters = [FactoryGirl.create(:application_letter_accepted)] + render + expect(rendered).to have_content("Angenommen") + end + it "checks if page displays rejected application" do + @application_letters = [FactoryGirl.create(:application_letter_rejected)] + render + expect(rendered).to have_content("Abgelehnt") + end + it "checks if page displays pending application after deadline" do + @application_letters = [FactoryGirl.create(:application_letter)] + @application_letters[0].event.application_deadline = Date.yesterday + render + expect(rendered).to have_content("In Bearbeitung") + end + it "checks if page displays pending application before deadline" do + @application_letters = [FactoryGirl.create(:application_letter)] + render + expect(rendered).to have_content("Beworben") + end + end + + it "should display the name of the event" do + @application_letters = [FactoryGirl.create(:application_letter)] + render + expect(rendered).to have_content(@application_letters[0].event.name) + end + + it "should display the edit button for a pending event" do + @application_letters = [FactoryGirl.create(:application_letter)] + render + expect(rendered).to have_css("a.btn", :text => "Bearbeiten") + end + it "should not display edit button after deadline" do + @application_letters = [FactoryGirl.build(:application_letter_deadline_over)] + render + expect(rendered).to_not have_css("a.btn", :text => "Bearbeiten") + end + it "should have link with the event name" do + @application_letters = [FactoryGirl.create(:application_letter)] + render + expect(rendered).to have_link(@application_letters[0].event.name, href: event_path(@application_letters[0].event.id)) + end +end \ No newline at end of file From 3490a2b22fb874abf605051aeb579901fa431200 Mon Sep 17 00:00:00 2001 From: Nils Strelow Date: Sun, 18 Dec 2016 21:38:18 +0100 Subject: [PATCH 15/18] forgot alternative status, use locales for the test --- spec/factories/application_letters.rb | 4 ++++ .../application_letters/index.html.erb_spec.rb | 13 +++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/spec/factories/application_letters.rb b/spec/factories/application_letters.rb index b0a542b8..d7c2c79d 100644 --- a/spec/factories/application_letters.rb +++ b/spec/factories/application_letters.rb @@ -48,4 +48,8 @@ factory :application_letter_rejected, parent: :application_letter do status :rejected end + + factory :application_letter_alternative, parent: :application_letter do + status :alternative + end end diff --git a/spec/views/application_letters/index.html.erb_spec.rb b/spec/views/application_letters/index.html.erb_spec.rb index 7b0ea49e..0e94c102 100644 --- a/spec/views/application_letters/index.html.erb_spec.rb +++ b/spec/views/application_letters/index.html.erb_spec.rb @@ -6,23 +6,28 @@ it "checks if page displays accepted application" do @application_letters = [FactoryGirl.create(:application_letter_accepted)] render - expect(rendered).to have_content("Angenommen") + expect(rendered).to have_content(I18n.t("application_status.accepted")) end it "checks if page displays rejected application" do @application_letters = [FactoryGirl.create(:application_letter_rejected)] render - expect(rendered).to have_content("Abgelehnt") + expect(rendered).to have_content(I18n.t("application_status.rejected")) end it "checks if page displays pending application after deadline" do @application_letters = [FactoryGirl.create(:application_letter)] @application_letters[0].event.application_deadline = Date.yesterday render - expect(rendered).to have_content("In Bearbeitung") + expect(rendered).to have_content(I18n.t("application_status.pending_after_deadline")) end it "checks if page displays pending application before deadline" do @application_letters = [FactoryGirl.create(:application_letter)] render - expect(rendered).to have_content("Beworben") + expect(rendered).to have_content(I18n.t("application_status.pending_before_deadline")) + end + it "checks if page displays alternative status application letter" do + @application_letters = [FactoryGirl.create(:application_letter_alternative)] + render + expect(rendered).to have_content(I18n.t("application_status.alternative")) end end From 4568c9283114a19e29dbb125299e8c9aa225e291 Mon Sep 17 00:00:00 2001 From: Hendrik Folkerts Date: Tue, 3 Jan 2017 12:30:38 +0100 Subject: [PATCH 16/18] 186 2.14 new delete edit button rights (#228) * Allow organizers to manage events. * Allow pupils to create requests and organizers to manage them. * Failing tests for buttons on events and requests pages. * Hide buttons on event and request pages if user doesn't have sufficient rights. * Adjust comment. --- app/models/ability.rb | 6 ++++-- app/views/events/index.html.erb | 12 +++++++++--- app/views/requests/index.html.erb | 12 +++++++++--- app/views/requests/show.html.erb | 8 ++++++-- spec/models/ability_spec.rb | 19 +++++++++++++++++++ spec/views/events/index.html.erb_spec.rb | 17 +++++++++++++++++ spec/views/requests/index.html.erb_spec.rb | 22 ++++++++++++++++++++++ spec/views/requests/show.html.erb_spec.rb | 18 ++++++++++++++++-- 8 files changed, 102 insertions(+), 12 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index 34f3f4ae..68725950 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -42,6 +42,7 @@ def initialize(user) can [:index, :show, :edit, :update, :destroy], ApplicationLetter, user: { id: user.id } # Pupils can upload their letters of agreement can [:create], AgreementLetter + can [:new, :create], Request end if user.role? :coach # Coaches can view Applications and participants for Event @@ -53,8 +54,9 @@ 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 and view participants for Events - can [:view_applicants, :edit_applicants, :view_participants, :print_applications], Event + # Organizers can view, edit and print Applications, view participants for and manage Events + can [:view_applicants, :edit_applicants, :view_participants, :print_applications, :manage], Event + can :manage, Request end if user.role? :admin can :manage, :all diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb index def1fb30..9fc69024 100644 --- a/app/views/events/index.html.erb +++ b/app/views/events/index.html.erb @@ -22,13 +22,17 @@
<%= event.end_date %> <%= event.draft %> - <%= link_to t('.edit', :default => t('helpers.links.edit')), + <% if can? :edit, event %> + <%= link_to t('.edit', :default => t('helpers.links.edit')), edit_event_path(event), :class => 'btn btn-default btn-xs' %> - <%= link_to t('.destroy', :default => t('helpers.links.destroy')), + <% 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' %> @@ -38,6 +42,8 @@
-<%= link_to t('.new', :default => t('helpers.links.new')), +<% 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/requests/index.html.erb b/app/views/requests/index.html.erb index 1acb4c24..fabf72c2 100644 --- a/app/views/requests/index.html.erb +++ b/app/views/requests/index.html.erb @@ -20,19 +20,25 @@ <%= request.user_id %> <%=l request.created_at %> - <%= link_to t('.edit', :default => t("helpers.links.edit")), + <% if can? :edit, request %> + <%= link_to t('.edit', :default => t("helpers.links.edit")), edit_request_path(request), :class => 'btn btn-default btn-xs' %> - <%= link_to t('.destroy', :default => t("helpers.links.destroy")), + <% end %> + <% if can? :destroy, request %> + <%= link_to t('.destroy', :default => t("helpers.links.destroy")), request_path(request), :method => :delete, :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) }, :class => 'btn btn-xs btn-danger' %> + <% end %> <% end %> -<%= link_to t('.new', :default => t("helpers.links.new")), +<% if can? :new, Request %> + <%= link_to t('.new', :default => t("helpers.links.new")), new_request_path, :class => 'btn btn-primary' %> +<% end %> \ No newline at end of file diff --git a/app/views/requests/show.html.erb b/app/views/requests/show.html.erb index ffe12b8b..72b328a2 100644 --- a/app/views/requests/show.html.erb +++ b/app/views/requests/show.html.erb @@ -12,10 +12,14 @@ <%= link_to t('.back', :default => t("helpers.links.back")), requests_path, :class => 'btn btn-default' %> -<%= link_to t('.edit', :default => t("helpers.links.edit")), +<% if can? :edit, @request %> + <%= link_to t('.edit', :default => t("helpers.links.edit")), edit_request_path(@request), :class => 'btn btn-default' %> -<%= link_to t('.destroy', :default => t("helpers.links.destroy")), +<% end %> +<% if can? :destroy, @request %> + <%= link_to t('.destroy', :default => t("helpers.links.destroy")), request_path(@request), :method => 'delete', :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) }, :class => 'btn btn-danger' %> +<% end %> diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index 74d3af53..763ada1e 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -181,4 +181,23 @@ expect(ability).to be_able_to(:update_status, another_application) end + + it "can manage events as organzier" do + user = FactoryGirl.create(:user, role: :organizer) + ability = Ability.new(user) + expect(ability).to be_able_to(:manage, Event) + end + + it "can create requests as pupil" do + user = FactoryGirl.create(:user, role: :pupil) + ability = Ability.new(user) + expect(ability).to be_able_to(:create, Request) + expect(ability).to be_able_to(:new, Request) + end + + it "can manage requests as organzier" do + user = FactoryGirl.create(:user, role: :organizer) + ability = Ability.new(user) + expect(ability).to be_able_to(:manage, Request) + end end diff --git a/spec/views/events/index.html.erb_spec.rb b/spec/views/events/index.html.erb_spec.rb index 57d0cc55..f9214a35 100644 --- a/spec/views/events/index.html.erb_spec.rb +++ b/spec/views/events/index.html.erb_spec.rb @@ -19,4 +19,21 @@ render expect(rendered).to_not have_text("Id") end + + it "should not display new, edit, delete buttons for non-organizers" do + sign_in(FactoryGirl.create(:user, role: :coach)) + render + expect(rendered).to_not have_link(I18n.t('helpers.links.new')) + expect(rendered).to_not have_link(I18n.t('helpers.links.edit')) + expect(rendered).to_not have_link(I18n.t('helpers.links.destroy')) + + end + + it "should display new, edit, delete buttons for organizers" do + sign_in(FactoryGirl.create(:user, role: :organizer)) + render + expect(rendered).to have_link(I18n.t('helpers.links.new')) + expect(rendered).to have_link(I18n.t('helpers.links.edit')) + expect(rendered).to have_link(I18n.t('helpers.links.destroy')) + end end diff --git a/spec/views/requests/index.html.erb_spec.rb b/spec/views/requests/index.html.erb_spec.rb index 6b9321f9..bf16dd93 100644 --- a/spec/views/requests/index.html.erb_spec.rb +++ b/spec/views/requests/index.html.erb_spec.rb @@ -13,4 +13,26 @@ render assert_select "tr>td", :text => @topics, :count => 2 end + + it "should not display the new button for non-pupils" do + render + expect(rendered).to_not have_link(I18n.t('helpers.links.new')) + end + + it "should display new button but not display edit, delete buttons for non-organizers" do + sign_in(FactoryGirl.create(:user, role: :coach)) + render + expect(rendered).to have_link(I18n.t('helpers.links.new')) + + expect(rendered).to_not have_link(I18n.t('helpers.links.edit')) + expect(rendered).to_not have_link(I18n.t('helpers.links.destroy')) + end + + it "should display edit, delete buttons for organizers" do + sign_in(FactoryGirl.create(:user, role: :organizer)) + render + + expect(rendered).to have_link(I18n.t('helpers.links.edit')) + expect(rendered).to have_link(I18n.t('helpers.links.destroy')) + end end diff --git a/spec/views/requests/show.html.erb_spec.rb b/spec/views/requests/show.html.erb_spec.rb index b11da680..ccdf7179 100644 --- a/spec/views/requests/show.html.erb_spec.rb +++ b/spec/views/requests/show.html.erb_spec.rb @@ -2,11 +2,25 @@ RSpec.describe "requests/show", type: :view do before(:each) do - @request = assign(:request, FactoryGirl.create(:request, topics: 'Topics')) + @aRequest = assign(:request, FactoryGirl.create(:request, topics: 'Topics')) end it "renders attributes" do render - expect(rendered).to have_text(@request.topics) + expect(rendered).to have_text(@aRequest.topics) + end + + it "should not display edit, delete buttons for non-organizers" do + sign_in(FactoryGirl.create(:user, role: :coach)) + render + expect(rendered).to_not have_link(I18n.t('helpers.links.edit')) + expect(rendered).to_not have_link(I18n.t('helpers.links.destroy')) + end + + it "should display edit, delete buttons for organizers" do + sign_in(FactoryGirl.create(:user, role: :organizer)) + render + expect(rendered).to have_link(I18n.t('helpers.links.edit')) + expect(rendered).to have_link(I18n.t('helpers.links.destroy')) end end From dbabae487944799ddd1faa6e9e58a147cfe64578 Mon Sep 17 00:00:00 2001 From: Nils Thamm Date: Tue, 3 Jan 2017 12:33:20 +0100 Subject: [PATCH 17/18] Refactoring locales (#229) --- app/controllers/application_letters_controller.rb | 2 +- app/views/application_letters/index.html.erb | 2 +- app/views/application_letters/show.html.erb | 2 +- app/views/profiles/index.html.erb | 2 +- app/views/profiles/show.html.erb | 2 +- config/locales/de.application_letters.yml | 3 +++ config/locales/de.profiles.yml | 4 ++++ 7 files changed, 12 insertions(+), 5 deletions(-) diff --git a/app/controllers/application_letters_controller.rb b/app/controllers/application_letters_controller.rb index 6fc07fff..d1c71fb8 100644 --- a/app/controllers/application_letters_controller.rb +++ b/app/controllers/application_letters_controller.rb @@ -70,7 +70,7 @@ def update_status # DELETE /applications/1 def destroy @application_letter.destroy - redirect_to application_letters_url, notice: 'Application was successfully destroyed.' + redirect_to application_letters_url, notice: I18n.t('application_letters.successful_deletion') end private diff --git a/app/views/application_letters/index.html.erb b/app/views/application_letters/index.html.erb index 5d5c80b7..6ea46399 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("helpers.links.confirm", :default => 'Are you sure?'))}, + :data => {:confirm => t('.confirm', :default => t("application_letters.confirm_deletion", :default => 'Are you sure?'))}, :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 a2984dcf..57a7db70 100644 --- a/app/views/application_letters/show.html.erb +++ b/app/views/application_letters/show.html.erb @@ -25,7 +25,7 @@ <%= link_to t('.destroy', :default => t("helpers.links.destroy")), application_letter_path(@application_letter), :method => 'delete', - :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) }, + :data => { :confirm => t('.confirm', :default => t("application_letters.confirm_deletion", :default => 'Are you sure?')) }, :class => 'btn btn-danger' %>

<%= t('.application_title', title: @application_letter.event.name) %>

diff --git a/app/views/profiles/index.html.erb b/app/views/profiles/index.html.erb index 6450f242..a6975569 100644 --- a/app/views/profiles/index.html.erb +++ b/app/views/profiles/index.html.erb @@ -24,7 +24,7 @@ <%= link_to t('.destroy', :default => t("helpers.links.destroy")), profile_path(profile), :method => :delete, - :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) }, + :data => { :confirm => t('.confirm', :default => t("profiles.confirm_deletion", :default => 'Are you sure?')) }, :class => 'btn btn-xs btn-danger' %> diff --git a/app/views/profiles/show.html.erb b/app/views/profiles/show.html.erb index 9c44d4ae..951085f0 100644 --- a/app/views/profiles/show.html.erb +++ b/app/views/profiles/show.html.erb @@ -21,7 +21,7 @@ <%= link_to t('.destroy', :default => t("helpers.links.destroy")), profile_path(@profile), :method => 'delete', - :data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) }, + :data => { :confirm => t('.confirm', :default => t("profiles.confirm_deletion", :default => 'Are you sure?')) }, :class => 'btn btn-danger' %>

Events

diff --git a/config/locales/de.application_letters.yml b/config/locales/de.application_letters.yml index 5406e086..45d85292 100644 --- a/config/locales/de.application_letters.yml +++ b/config/locales/de.application_letters.yml @@ -15,10 +15,13 @@ de: wird zur Gruppeneinteilung benötigt." login_before_creation: "Du musst angemeldet sein, um dich für Workshops bewerben zu können." successful_update: "Die Bewerbung wurde erfolgreich aktualisiert" + successful_deletion: "Bewerbung erfolgreich gelöscht" + successful_creation: "Bewerbung erfolgreich erstellt" fill_in_profile_before_creation: "Du musst erst dein Profil ausfüllen, um dich für Workshops bewerben zu können." application_page: title: "Bewerbung von %{name}" for: "für %{event}" + confirm_deletion: "Willst du diese Bewerbung wirklich löschen?" activerecord: models: diff --git a/config/locales/de.profiles.yml b/config/locales/de.profiles.yml index b54b9827..4d0b5380 100644 --- a/config/locales/de.profiles.yml +++ b/config/locales/de.profiles.yml @@ -10,6 +10,10 @@ de: male: "Männlich" female: "Weiblich" other: "Andere" + confirm_deletion: "Willst du dieses Profil wirklich löschen?" + successful_update: "Profil erfolgreich aktualisiert" + successful_deletion: "Profil erfolgreich gelöscht" + successful_creation: "Profil erfolgreich erstellt" activerecord: models: From 126a10004d5c88c60aa41c29b8212af760c04afc Mon Sep 17 00:00:00 2001 From: Nils Thamm Date: Wed, 4 Jan 2017 10:45:22 +0100 Subject: [PATCH 18/18] #187 2.16 language issues (#234) * Refactoring locales * Added missing locales in controllers * Fixing Test --- app/controllers/application_letters_controller.rb | 2 +- app/controllers/profiles_controller.rb | 8 ++++---- config/locales/de.application_letters.yml | 2 +- spec/features/profile_spec.rb | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) 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/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/config/locales/de.application_letters.yml b/config/locales/de.application_letters.yml index 45d85292..4d9d25a6 100644 --- a/config/locales/de.application_letters.yml +++ b/config/locales/de.application_letters.yml @@ -14,7 +14,7 @@ de: Programmierkenntnisse sind keine Voraussetzung zur Teilnahme. Diese Information wird zur Gruppeneinteilung benötigt." login_before_creation: "Du musst angemeldet sein, um dich für Workshops bewerben zu können." - successful_update: "Die Bewerbung wurde erfolgreich aktualisiert" + successful_update: "Bewerbung erfolgreich bearbeitet" successful_deletion: "Bewerbung erfolgreich gelöscht" successful_creation: "Bewerbung erfolgreich erstellt" fill_in_profile_before_creation: "Du musst erst dein Profil ausfüllen, um dich für Workshops bewerben zu können." diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 6fa394fe..db49213e 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -124,7 +124,7 @@ def mock_writing_to_filesystem find('input[name=commit]').click - expect(page).to have_text('Profile was successfully updated.') + expect(page).to have_text(I18n.t('profiles.successful_update')) end scenario "user fills in an invalid birth date" do