diff --git a/app/models/programming_group.rb b/app/models/programming_group.rb index dc583eab..86ee9eb7 100644 --- a/app/models/programming_group.rb +++ b/app/models/programming_group.rb @@ -11,7 +11,8 @@ class ProgrammingGroup < ApplicationRecord has_many :runners, as: :contributor, dependent: :destroy belongs_to :exercise - validate :group_size + validate :min_group_size + validate :max_group_size validate :no_erroneous_users accepts_nested_attributes_for :programming_group_memberships @@ -71,12 +72,18 @@ class ProgrammingGroup < ApplicationRecord private - def group_size + def min_group_size if users.size < 2 errors.add(:base, :size_too_small) end end + def max_group_size + if users.size > 2 + errors.add(:base, :size_too_large) + end + end + def no_erroneous_users @erroneous_users.each do |partner_id| errors.add(:base, :invalid_partner_id, partner_id:) diff --git a/app/views/programming_groups/_form.html.slim b/app/views/programming_groups/_form.html.slim index 20a5cc20..cc9f2f64 100644 --- a/app/views/programming_groups/_form.html.slim +++ b/app/views/programming_groups/_form.html.slim @@ -1,7 +1,7 @@ = form_for(@programming_group, url: exercise_programming_groups_path) do |f| = render('shared/form_errors', object: @programming_group) .mb-3 - = f.label(:programming_partner_ids, class: 'form-label') + = f.label(:programming_partner_id, class: 'form-label') = f.text_field(:programming_partner_ids, class: 'form-control', required: true, value: (@programming_group.programming_partner_ids - [current_user.id_with_type]).join(', ')) - .help-block.form-text = t('.hints.programming_partner_ids') + /.help-block.form-text = t('.hints.programming_partner_ids') .actions.mb-0 = render('shared/submit_button', f: f, object: @programming_group) diff --git a/app/views/programming_groups/new.html.slim b/app/views/programming_groups/new.html.slim index dbecda7a..7a14c407 100644 --- a/app/views/programming_groups/new.html.slim +++ b/app/views/programming_groups/new.html.slim @@ -1,4 +1,4 @@ -h1 = t('shared.new_model', model: ProgrammingGroup.model_name.human) +h1 = t('programming_groups.new.create_programming_pair') .row .col-md-6 p diff --git a/config/locales/de.yml b/config/locales/de.yml index 357d523d..bb353006 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -57,7 +57,7 @@ de: uuid: UUID unpublished: Deaktiviert programming_group: - programming_partner_ids: Nutzer-IDs der Programmierpartner + programming_partner_id: Nutzer-ID der Programmierpartnerin / des Programmierpartners programming_group/programming_group_memberships: base: Programmiergruppenmitgliedschaft proxy_exercise: @@ -270,7 +270,8 @@ de: password: weak: ist zu schwach. Versuchen Sie es mit einem langen Passwort, welches Groß-, Kleinbuchstaben, Zahlen und Sonderzeichen enthält. programming_group: - size_too_small: Die Größe dieser Programmiergruppe ist zu klein. Geben Sie mindestens eine andere Nutzer-ID an. + size_too_large: Die Größe dieser Programmiergruppe ist zu groß. Geben Sie nur eine andere Nutzer-ID an. + size_too_small: Die Größe dieser Programmiergruppe ist zu klein. Geben Sie eine andere Nutzer-ID an. invalid_partner_id: Die Nutzer-ID '%{partner_id}' ist ungültig und wurde entfernt. Bitte überprüfen Sie die Nutzer-IDs der Programmierpartner. programming_group_membership: already_exists: 'existiert bereits für diese Aufgabe für den Nutzer mit der ID %{id_with_type}.' @@ -589,12 +590,13 @@ de: hints: programming_partner_ids: "Sie können mehrere Nutzer-IDs mit Kommata getrennt eingeben, wie z.B.: 'e123, e234'." new: + create_programming_pair: Programmierpaar erstellen check_invitation: "Einladung prüfen" - enter_partner_id: "Bitte geben Sie hier die Nutzer-IDs der Personen ein, mit denen Sie zusammen die Aufgabe '%{exercise_title}' lösen möchten. Beachten Sie jedoch, dass anschließend keiner aus der Gruppe austreten kann. Alle Teammitglieder können also sehen, was Sie in dieser Aufgabe schreiben und umgekehrt. Für die nächste Aufgabe können Sie sich erneuert entscheiden, ob und mit wem Sie zusammen arbeiten möchten." - find_partner_title: "Finde einen Programmierpartner für die Aufgabe" - find_partner_description: "Kopiere eine andere Nutzer-ID aus der Liste unten und lösche sie anschließend. Wenn noch keine Nutzer-IDs in der Liste vorhanden sind, fügen Sie Ihre Nutzer-ID hinzu und warten Sie, bis ein anderer Nutzer eine Programmiergruppe mit Ihnen erstellt. Dies können Sie mit dem Knopf 'Einladung prüfen' testen. Wenn Sie allein arbeiten möchten, löschen Sie bitte Ihre Nutzer-ID aus der Liste." - own_user_id: "Ihre Nutzer-ID:" - work_alone: "Sie können sich einmalig dafür entscheiden, die Aufgabe alleine zu bearbeiten. Anschließend können Sie jedoch nicht mehr in die Gruppenarbeit für diese Aufgabe wechseln. Klicken Sie hier, um die Aufgabe im Einzelmodus zu starten." + enter_partner_id: "Bitte gib hier die Nutzer-ID der Person ein, mit der du zusammen die Aufgabe '%{exercise_title}' lösen möchtest. Beachte jedoch, dass anschließend keiner die Zusammenarbeit beenden kann. Dein:e Teampartner:in kann sehen, was du in dieser Aufgabe schreibst und umgekehrt. Für die nächste Aufgabe kannst du dich erneuert entscheiden, ob und mit wem du zusammen arbeiten möchtest." + find_partner_title: "Finde eine:n Programmierpartner:in für die Aufgabe" + find_partner_description: "Kopiere eine andere Nutzer-ID aus der Liste unten und lösche sie anschließend. Wenn noch keine Nutzer-IDs in der Liste vorhanden sind, füge deine Nutzer-ID hinzu und warte, bis ein andere:r Nutzer:in ein Programmierpaar mit dir erstellt. Dies kannst du mit dem Knopf 'Einladung prüfen' testen. Wenn du allein arbeiten möchtest, lösche bitte deine Nutzer-ID aus der Liste, falls du sie hinzugefügt hast." + own_user_id: "Deine Nutzer-ID:" + work_alone: "Du kannst dich einmalig dafür entscheiden, die Aufgabe alleine zu bearbeiten. Anschließend kannst du jedoch nicht mehr in die Partnerarbeit für diese Aufgabe wechseln. Klicke hier, um die Aufgabe im Einzelmodus zu starten." external_users: statistics: title: Statistiken für Externe Benutzer diff --git a/config/locales/en.yml b/config/locales/en.yml index 94e72c92..5fa4e592 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -57,7 +57,7 @@ en: uuid: UUID unpublished: Unpublished programming_group: - programming_partner_ids: Programming Partner IDs + programming_partner_id: Programming Partner ID programming_group/programming_group_memberships: base: Programming Group Membership proxy_exercise: @@ -270,6 +270,7 @@ en: password: weak: is too weak. Try to use a long password with upper and lower case letters, numbers and special characters. programming_group: + size_too_large: The size of this programming group is too large. Enter at most one other user ID to work with. size_too_small: The size of this programming group is too small. Enter at least one other user ID to work with. invalid_partner_id: The user ID '%{partner_id}' is invalid and was removed. Please check the user IDs of your programming partners. programming_group_membership: @@ -589,12 +590,13 @@ en: hints: programming_partner_ids: "You can enter several user IDs separated by commas such as 'e123, e234'." new: + create_programming_pair: Create Programming Pair check_invitation: "Check invitation" - enter_partner_id: "Please enter the user IDs from the practice partners with whom you want to solve the exercise '%{exercise_title}'. However, note that no one can leave the group afterward. Hence, all team members can see what you write in this exercise and vice versa. For the next exercise, you can decide again whether and with whom you want to work together." + enter_partner_id: "Please enter the user ID from the practice partner with whom you want to solve the exercise '%{exercise_title}'. However, note that no one can leave the pair afterward. Hence, your team partner can see what you write in this exercise and vice versa. For the next exercise, you can decide again whether and with whom you want to work together." find_partner_title: "Find a programming partner for the exercise" - find_partner_description: "Copy another user ID from the list below and delete it afterward. If there are no user IDs on the list yet, add your user ID and wait for another user to create a programming group with you. You can test this with the 'Check invitation' button. If you decide to work alone, please delete your user ID from the list." + find_partner_description: "Copy another user ID from the list below and delete it afterward. If there are no user IDs on the list yet, add your user ID and wait for another user to create a programming group with you. You can test this with the 'Check invitation' button. If you decide to work alone, please delete your user ID from the list if you added it before." own_user_id: "Your user ID:" - work_alone: "You can choose once to work on the exercise alone. Afterward, however, you will not be able to switch to group work for this exercise. Click here to get to the exercise in single mode." + work_alone: "You can choose once to work on the exercise alone. Afterward, however, you will not be able to switch to work in a pair for this exercise. Click here to get to the exercise in single mode." external_users: statistics: title: External User Statistics diff --git a/spec/policies/request_for_comment_policy_spec.rb b/spec/policies/request_for_comment_policy_spec.rb index 88745ead..0e47191a 100644 --- a/spec/policies/request_for_comment_policy_spec.rb +++ b/spec/policies/request_for_comment_policy_spec.rb @@ -62,7 +62,6 @@ describe RequestForCommentPolicy do it 'grant access to other authors of the programming group' do rfc.submission.update(contributor: programming_group) - expect(policy).to permit(author_other_group_member, rfc) expect(policy).to permit(viewer_other_group_member, rfc) end end @@ -78,7 +77,6 @@ describe RequestForCommentPolicy do it 'grant access to other authors of the programming group' do rfc.submission.update(contributor: programming_group) - expect(policy).to permit(author_other_group_member, rfc) expect(policy).to permit(viewer_other_group_member, rfc) end @@ -93,9 +91,8 @@ describe RequestForCommentPolicy do let(:author_study_groups) { create_list(:study_group, 1, consumer: author_consumer) } let(:rfc) { create(:rfc, user: rfc_author) } - let(:author_other_group_member) { create(:external_user, consumer: author_consumer) } let(:viewer_other_group_member) { create(:external_user, consumer: viewer_consumer) } - let(:programming_group) { create(:programming_group, exercise: rfc.submission.exercise, users: [rfc.author, author_other_group_member, viewer_other_group_member]) } + let(:programming_group) { create(:programming_group, exercise: rfc.submission.exercise, users: [rfc.author, viewer_other_group_member]) } context "when the author's rfc_visibility is set to all" do let(:author_consumer) { create(:consumer, rfc_visibility: 'all') }