diff --git a/assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java b/assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java index a96d2251b63d..425d0d3a2d22 100644 --- a/assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java +++ b/assignment/api/src/java/org/sakaiproject/assignment/api/AssignmentService.java @@ -627,10 +627,10 @@ public interface AssignmentService extends EntityProducer { * Given an Assignment and a User, rationalize who the submitter should be taking into account the assignment configuration * Will check the assignments access and group configuration to determine the submitter id * @param assignment The assignment - * @param user The user + * @param userId The user id * @return the correct submitter id to use for creating a submission or null if one can't be determined */ - String getSubmitterIdForAssignment(Assignment assignment, User user); + String getSubmitterIdForAssignment(Assignment assignment, String userId); /** * Retrieves the selected group users based on the given parameters. diff --git a/assignment/api/src/resources/assignment.properties b/assignment/api/src/resources/assignment.properties index f79068260957..12f4763c9c95 100644 --- a/assignment/api/src/resources/assignment.properties +++ b/assignment/api/src/resources/assignment.properties @@ -1071,14 +1071,13 @@ sendFeedback.error = Error returning feedback to {0} students. # Peer Review peerAssessmentSavedGrading=Comments and/or grade have been saved but not submitted. If you don't submit your review before the due date, it will be submitted for you. peerAssessmentSavedSubmission=Comments and/or grade have been saved and submitted. -peerAssessmentName=Peer Assessment - Students assess each other +peerAssessmentName=Peer Assessment - {0} noAdditionalOptionsName=No additional assignment options additionalOptionsName=Additional Assignment Options peerAssessmentUse=Use peer assessment -peerassessment.warn.nogroup=(Peer assessment cannot be used with group assignments. To enable this option, switch to one of the individual assignment options in the "Assign To" section.) peerassessment.periodfinishes=Evaluation Period Finishes: peerassessment.anonymousEvaluation=Anonymous evaluation peerassessment.studentViewReviews=Allow students to see reviews of their submissions @@ -1132,7 +1131,6 @@ settings.access.selectedGroupsGoneNoGroups = Note - The previously selected grou settings.access.selectedGroupsGoneOtherGroupsPresent = Note - The previously selected groups no longer exist. "{0}" has been selected as the "Assign To" option for this assignment. You may post this as an individual assignment for the entire site, or change the group selections. settings.access.selectGroups = Select one or more groups settings.access.noMembersInCommon=Group assignments require that the selected groups don't have any participants in common. -settings.access.noGroupAssignmentPeerInUse=(This option is not available because peer assessment has been enabled.) settings.access.checkNow=Check Now settings.access.checkSuccess=Success! There are no students who are members of more than one of the selected groups. settings.access.checkError=The following students are members of multiple selected groups: @@ -1169,8 +1167,6 @@ option.pointsoverride=Adjust individual student scores option.hidepoints=Hide point values (feedback only) option.studentpreview=Hide Rubric from student grading_rubric=Grading Rubric -asn.list.userubric=This assignment could be graded using a Rubric -rubrics.use=Use rubric # table toolbar common messages view.label=View @@ -1262,3 +1258,20 @@ ts.rem.err.userId=You need to be logged in to add time sheet entry ts.rem.err.empty=Selected time sheet must be provided ts.rem.err.submitterId=You need to supply the submissionId and ref ts.rem.err.permission=You can't modify this sumbitter + +#S2U-34 +peerAssessmentStudents=Students assess each other +peerAssessmentGroups=Groups assess each other +peerassessment.group=Group {0} +option.selfreport=Allow students to self-report their work +option.selfreport.must=Student must complete all self-report criterions to complete the submission +option.selfreport.partialmust=Student must complete at least one self-report criterion to complete the submission +option.selfreport.notamust=Student does not need to complete the self-report to complete the submission +youmustrubric=This is a self-report assignment. You must use the following rubric to grade your work before submitting. +youhavetorubric=This is a self-report assignment. You must use the following rubric to grade your work before submitting. You must complete the entire rubric in order to submit the task. +youhavetorubricone=This is a self-report assignment. You must use the following rubric to grade your work before submitting. You must complete at least one criterion of the rubric in order to submit the task. +studentrubric=This is a self-report assignment. You can check the self-report of submitter before grading. +autoevaluation=Autoevaluation: +instructor_grading=Instructor Grading: +reviewrubric=This is a self-report assignment. You can check your self-report before grading. +reviewrubricreport=This is your self-report. diff --git a/assignment/api/src/resources/assignment_ar.properties b/assignment/api/src/resources/assignment_ar.properties index 2228953480fc..24b9f43716cb 100644 --- a/assignment/api/src/resources/assignment_ar.properties +++ b/assignment/api/src/resources/assignment_ar.properties @@ -1038,7 +1038,6 @@ noAdditionalOptionsName=\u0644\u0627 \u062a\u0648\u062c\u062f \u062e\u064a\u0627 additionalOptionsName=\u062e\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u062a\u0639\u064a\u064a\u0646 \u0627\u0644\u0625\u0636\u0627\u0641\u064a\u0629 peerAssessmentUse=\u0627\u0633\u062a\u062e\u062f\u0645 \u062a\u0642\u064a\u064a\u0645 \u0627\u0644\u0623\u0642\u0631\u0627\u0646 -peerassessment.warn.nogroup=(\u0644\u0627 \u064a\u0645\u0643\u0646 \u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u062a\u0642\u064a\u064a\u0645 \u0627\u0644\u0623\u0642\u0631\u0627\u0646 \u0645\u0639 \u062a\u0639\u064a\u064a\u0646\u0627\u062a \u0627\u0644\u0645\u062c\u0645\u0648\u0639\u0629. \u0644\u062a\u0645\u0643\u064a\u0646 \u0647\u0630\u0627 \u0627\u0644\u062e\u064a\u0627\u0631 \u060c \u0642\u0645 \u0628\u0627\u0644\u062a\u0628\u062f\u064a\u0644 \u0625\u0644\u0649 \u0623\u062d\u062f \u062e\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u062a\u0639\u064a\u064a\u0646 \u0627\u0644\u0641\u0631\u062f\u064a\u0629 \u0641\u064a \u0642\u0633\u0645 "\u062a\u0639\u064a\u064a\u0646 \u0625\u0644\u0649".) peerassessment.periodfinishes=\u0627\u0646\u062a\u0647\u0627\u0621 \u0641\u062a\u0631\u0629 \u0627\u0644\u062a\u0642\u064a\u064a\u0645\: peerassessment.anonymousEvaluation=\u062a\u0642\u064a\u064a\u0645 \u0645\u062c\u0647\u0648\u0644 peerassessment.studentViewReviews=\u0627\u0644\u0633\u0645\u0627\u062d \u0644\u0644\u0637\u0644\u0627\u0628 \u0628\u0645\u0634\u0627\u0647\u062f\u0629 \u0627\u0644\u0645\u0631\u0627\u062c\u0639\u0627\u062a \u0627\u0644\u062e\u0627\u0635\u0629 \u0628\u0647\u0645 @@ -1092,7 +1091,6 @@ settings.access.selectedGroupsGoneNoGroups=\u0645\u0644\u0627\u062d\u0638\u0629 settings.access.selectedGroupsGoneOtherGroupsPresent=\u0645\u0644\u0627\u062d\u0638\u0629 - \u0644\u0645 \u062a\u0639\u062f \u0627\u0644\u0645\u062c\u0645\u0648\u0639\u0627\u062a \u0627\u0644\u0645\u062d\u062f\u062f\u0629 \u0645\u0633\u0628\u0642\u064b\u0627 \u0645\u0648\u062c\u0648\u062f\u0629. \u062a\u0645 \u062a\u062d\u062f\u064a\u062f "{0}" \u0643\u062e\u064a\u0627\u0631 "\u062a\u0639\u064a\u064a\u0646 \u0625\u0644\u0649" \u0644\u0647\u0630\u0647 \u0627\u0644\u0645\u0647\u0645\u0629. \u064a\u0645\u0643\u0646\u0643 \u0646\u0634\u0631 \u0647\u0630\u0627 \u0643\u0645\u0647\u0645\u0629 \u0641\u0631\u062f\u064a\u0629 \u0644\u0644\u0645\u0648\u0642\u0639 \u0628\u0623\u0643\u0645\u0644\u0647 \u060c \u0623\u0648 \u062a\u063a\u064a\u064a\u0631 \u0627\u062e\u062a\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u0645\u062c\u0645\u0648\u0639\u0629. settings.access.selectGroups=\u062d\u062f\u062f \u0645\u062c\u0645\u0648\u0639\u0629 \u0648\u0627\u062d\u062f\u0629 \u0623\u0648 \u0623\u0643\u062b\u0631 settings.access.noMembersInCommon=\u062a\u062a\u0637\u0644\u0628 \u0645\u0647\u0627\u0645 \u0627\u0644\u0645\u062c\u0645\u0648\u0639\u0629 \u0623\u0644\u0627 \u064a\u0643\u0648\u0646 \u0644\u0644\u0645\u062c\u0645\u0648\u0639\u0627\u062a \u0627\u0644\u0645\u062d\u062f\u062f\u0629 \u0623\u064a \u0645\u0634\u062a\u0631\u0643\u064a\u0646 \u0645\u0634\u062a\u0631\u0643\u064a\u0646. -settings.access.noGroupAssignmentPeerInUse=(\u0647\u0630\u0627 \u0627\u0644\u062e\u064a\u0627\u0631 \u063a\u064a\u0631 \u0645\u062a\u0627\u062d \u0644\u0623\u0646\u0647 \u062a\u0645 \u062a\u0645\u0643\u064a\u0646 \u062a\u0642\u064a\u064a\u0645 \u0627\u0644\u0623\u0642\u0631\u0627\u0646.) settings.access.checkNow=\u062a\u0623\u0643\u062f \u0627\u0644\u0627\u0646 settings.access.checkSuccess=\u0646\u062c\u0627\u062d\! \u0644\u0627 \u064a\u0648\u062c\u062f \u0637\u0644\u0627\u0628 \u0623\u0639\u0636\u0627\u0621 \u0641\u064a \u0623\u0643\u062b\u0631 \u0645\u0646 \u0645\u062c\u0645\u0648\u0639\u0629 \u0645\u062e\u062a\u0627\u0631\u0629. settings.access.checkError=\u0627\u0644\u0637\u0644\u0627\u0628 \u0627\u0644\u062a\u0627\u0644\u0648\u0646 \u0623\u0639\u0636\u0627\u0621 \u0641\u064a \u0645\u062c\u0645\u0648\u0639\u0627\u062a \u0645\u062d\u062f\u062f\u0629 \u0645\u062a\u0639\u062f\u062f\u0629\: @@ -1129,8 +1127,6 @@ option.pointsoverride=\u0627\u0636\u0628\u0637 \u062f\u0631\u062c\u0627\u062a \u option.hidepoints=\u0625\u062e\u0641\u0627\u0621 \u0642\u064a\u0645 \u0627\u0644\u0646\u0642\u0627\u0637 (\u0627\u0644\u062a\u0639\u0644\u064a\u0642\u0627\u062a \u0641\u0642\u0637) option.studentpreview=\u0625\u062e\u0641\u0627\u0621 \u0646\u0645\u0648\u0630\u062c \u0627\u0644\u062a\u0642\u064a\u064a\u0645 \u0639\u0646 \u0627\u0644\u0637\u0627\u0644\u0628 grading_rubric=\u062a\u0642\u064a\u064a\u0645 \u0627\u0644\u0646\u0645\u0648\u0630\u062c -asn.list.userubric=\u064a\u0645\u0643\u0646 \u062a\u0642\u062f\u064a\u0631 \u0647\u0630\u0627 \u0627\u0644\u0648\u0627\u062c\u0628 \u0628\u0627\u0633\u062a\u062e\u062f\u0627\u0645 \u0646\u0645\u0648\u0630\u062c \u062a\u0642\u064a\u064a\u0645 -rubrics.use=\u0627\u0633\u062a\u062e\u062f\u0645 \u0646\u0645\u0648\u0630\u062c \u0627\u0644\u062a\u0642\u064a\u064a\u0645 # table toolbar common messages view.label=\ \u0645\u0634\u0627\u0647\u062f\u0629 diff --git a/assignment/api/src/resources/assignment_ca.properties b/assignment/api/src/resources/assignment_ca.properties index 222d83553dd7..6c48da7f279e 100644 --- a/assignment/api/src/resources/assignment_ca.properties +++ b/assignment/api/src/resources/assignment_ca.properties @@ -1070,14 +1070,13 @@ sendFeedback.error=S\u2019ha produ\u00eft un error al fer p\u00fablics els comen # Peer Review peerAssessmentSavedGrading=Els comentaris i/o les qualificacions s\u2019han desat per\u00f2 no s\u2019han enviat. Si no lliureu la revisi\u00f3 abans del termini, s\u2019enviar\u00e0 de manera autom\u00e0tica. peerAssessmentSavedSubmission=Els comentaris i/o les qualificacions s\u2019han desat i enviat. -peerAssessmentName=Revisi\u00f3 per part dels companys - Els estudiants s\u2019avaluen entre ells +peerAssessmentName=Revisi\u00f3 per part dels companys - {0} noAdditionalOptionsName=No hi ha opcions addicionals de l\u2019activitat additionalOptionsName=Opcions addicionals de l\u2019activitat peerAssessmentUse=Usa l\u2019avaluaci\u00f3 dels companys -peerassessment.warn.nogroup=(L\u2019avaluaci\u00f3 per part dels companys no es pot usar en el cas d\u2019activitats de grup. Per habilitar aquesta opci\u00f3 cal que canvieu a una de les opcions d\u2019activitat individual que teniu a la secci\u00f3 per fer les assignacions.) peerassessment.periodfinishes=El per\u00edode d\u2019avaluaci\u00f3 acaba el\: peerassessment.anonymousEvaluation=Avaluaci\u00f3 an\u00f2nima peerassessment.studentViewReviews=Permet que els estudiants vegin les revisions dels seus lliuraments @@ -1131,7 +1130,6 @@ settings.access.selectedGroupsGoneNoGroups=Nota - Els grups seleccionats pr\u00e settings.access.selectedGroupsGoneOtherGroupsPresent=Nota - Els grups seleccionats pr\u00e8viament ja no existeixen. S\u2019ha seleccionat "{0}" com a l\u2019opci\u00f3 d\u2019assignaci\u00f3 per a aquesta activitat. Podeu publicar-la com a activitat individual per a l\u2019espai sencer o canviar la selecci\u00f3 de grups. settings.access.selectGroups=Selecciona un o m\u00e9s grups settings.access.noMembersInCommon=Les activitats de grup requereixen que els grups seleccionats no tinguin cap participant en com\u00fa. -settings.access.noGroupAssignmentPeerInUse=(Aquesta opci\u00f3 no est\u00e0 disponible perqu\u00e8 l\u2019avaluaci\u00f3 per part dels companys est\u00e0 habilitada.) settings.access.checkNow=Comprova-ho ara settings.access.checkSuccess=S\u2019ha comprovat que no hi ha estudiants membres de m\u00e9s d\u2019un dels grups seleccionats. settings.access.checkError=Els estudiants seg\u00fcents s\u00f3n membres de m\u00e9s d\u2019un dels grups seleccionats\: @@ -1168,8 +1166,6 @@ option.pointsoverride=Ajusta les puntuacions individuals dels estudiants option.hidepoints=Amaga les puntuacions (nom\u00e9s comentaris) option.studentpreview=Amaga la r\u00fabrica a l\u2019estudiant grading_rubric=R\u00fabrica per a qualificar -asn.list.userubric=Aquesta activitat es pot qualificar fent \u00fas d\u2019una r\u00fabrica -rubrics.use=Usa la r\u00fabrica # table toolbar common messages view.label=Mostra @@ -1260,3 +1256,20 @@ ts.rem.err.userId=Cal estar autenticat per a afegir un registre al control dels ts.rem.err.empty=Cal que seleccioneu un control de temps ts.rem.err.submitterId=Cal que proporcioneu un assignmentId i una ref ts.rem.err.permission=No podeu modificat qui ha fet el lliurament + +#S2U-34 +peerAssessmentStudents=Els estudiants s'avaluen entre ells +peerAssessmentGroups=Els grups s'avaluen entre ells +peerassessment.group=Grup {0} +option.selfreport=Permetre que els estudiants s'autoavalu\u00EFn la seva tasca +option.selfreport.must=Els estudiants han de completar sencera la seva autoavaluaci\u00F3 per poder realitzar l'enviament +option.selfreport.partialmust=Els estudiants han de completar almenys un criteri de la seva autoavaluaci\u00F3 per poder realitzar l'enviament +option.selfreport.notamust=Els estudiants no tenen per qu\u00E8 completar l'autoavaluaci\u00F3 per poder realitzar l'enviament +youmustrubric=Aquesta tasca \u00E9s autoavaluable. Pots autoavaluar la teva tasca amb la r\u00FAbrica abans d'enviar-la. +youhavetorubric=Aquesta tasca \u00fas autoavaluable. Has d'autoavaluar la teva tasca amb la r\u00FAbrica abans d'enviar-la. Has de completar sencera la r\u00FAbrica per fer l'enviament. +youhavetorubricone=Aquesta tasca \u00fas autoavaluable. Has d'autoavaluar la teva tasca amb la r\u00FAbrica abans d'enviar-la. Has de completar almenys un criteri de la r\u00FAbrica per fer l'enviament. +studentrubric=Aquesta tasca \u00E9s autoavaluable. Pots revisar l'autoavaluaci\u00F3 de l'estudiant abans de puntuar la tasca. +autoevaluation=Autoevaluaci\u00f3: +instructor_grading=Correcci\u00f3 del profesor: +reviewrubric=Aquesta tasca \u00E9s autoavaluable. Pot revisar la autoavaluaci\u00F3 abans d'enviar-la. +reviewrubricreport=Aquesta \u00E9s la teva autoavaluaci\u00F3. diff --git a/assignment/api/src/resources/assignment_de_DE.properties b/assignment/api/src/resources/assignment_de_DE.properties index ec0a504e4ffa..484ac96be1a8 100644 --- a/assignment/api/src/resources/assignment_de_DE.properties +++ b/assignment/api/src/resources/assignment_de_DE.properties @@ -805,7 +805,6 @@ peerAssessmentName=Peer Bewertung - Studenten bewerten sich untereinander noAdditionalOptionsName=Keine weiteren Aufgaben-Optionen additionalOptionsName=Weitere Aufgaben-Optionen peerAssessmentUse=Peer-Bewertungen verwenden -peerassessment.warn.nogroup=(Peer-Bewertungen k\u00f6nnen nicht in Gruppen-Aufgaben verwendet werden. Um dies zu erm\u00f6glichen, stellen Sie in den Aufgaben-Optionen auf "individuelle Aufgabe" um.) peerassessment.periodfinishes=Bewertungszeitraum endet\: peerassessment.anonymousEvaluation=Anonyme Bewertung peerassessment.studentViewReviews=Studierenden erlauben, die Peer-Bewertungen ihrer Einreichungen zu sehen @@ -857,7 +856,6 @@ settings.access.selectedGroupsGoneNoGroups=Hinweis - Die vormals ausgew\u00e4hlt settings.access.selectedGroupsGoneOtherGroupsPresent=Hinweis - Die vormals ausgew\u00e4hlten Gruppen existieren nicht mehr. "{0}" wurde als Einstellung f\u00fcr diese Aufgabe gew\u00e4hlt. Sie k\u00f6nnen diese Aufgabe entweder individuell f\u00fcr die ganze Seite erstellen oder abbrechen und eine andere Gruppe ausw\u00e4hlen. settings.access.selectGroups=W\u00e4hlen Sie eine oder mehrere Gruppen aus settings.access.noMembersInCommon=Gruppenaufgaben verlangen, dass die gew\u00e4hlten Gruppen keine gemeinsamen Teilnehmer haben. -settings.access.noGroupAssignmentPeerInUse=(Diese Einstellung ist nicht verf\u00fcgbar, da Peer-Bewertung ausgew\u00e4hlt wurde.) settings.access.checkNow=Jetzt \u00fcberpr\u00fcfen settings.access.checkSuccess=Erfolg\! Es sind keine Studierenden in mehr als einer der gew\u00e4hlten Gruppen. settings.access.checkError=Die folgenden Studierenden sind in mehr als einer der gew\u00e4htlen Gruppen Mitglieder\: @@ -887,8 +885,6 @@ option.pointsoverride=Individuelle Bewertung der Studierenden anpassen option.hidepoints=Punktebewertung ausblenden(nur Kommentar anzeigen) option.studentpreview=Kategorie vor dem Studierenden verbergen grading_rubric=Rubrik der Benotung -asn.list.userubric=Diese Aufgabe kann mit einer Rubrik benotet werden -rubrics.use=Rubrik verwenden view.label=Anzeigen gen.viewing.phrase=Zeige {0} - {1} von {2} Elementen gen.show=Zeige {0} Elemente... diff --git a/assignment/api/src/resources/assignment_es.properties b/assignment/api/src/resources/assignment_es.properties index d415e251af11..5fbb4f0a269c 100644 --- a/assignment/api/src/resources/assignment_es.properties +++ b/assignment/api/src/resources/assignment_es.properties @@ -1061,14 +1061,13 @@ sendFeedback.error=Error al devolver el feedback a {0} estudiantes. # Peer Review peerAssessmentSavedGrading=Comentarios y/o nota han sido guardados pero no entregados. Si no entrega su revisi\u00f3n antes de la fecha establecida, ser\u00e1 entregada por usted. peerAssessmentSavedSubmission=Los comentarios y/o la nota han sido guardados y entregados. -peerAssessmentName=Evaluaci\u00f3n por pares - Los estudiantes se eval\u00faan entre ellos +peerAssessmentName=Evaluaci\u00f3n por pares - {0} noAdditionalOptionsName=No hay opciones adicionales para la tarea additionalOptionsName=Opciones adicionales para la tarea peerAssessmentUse=Uso de evaluaci\u00f3n por pares -peerassessment.warn.nogroup=(La evaluaci\u00f3n por pares es incompatible con la opci\u00f3n de una entrega por grupo. Para poder habilitar evaluaci\u00f3n por pares cambie a entregas individuales) peerassessment.periodfinishes=El periodo de evaluaci\u00f3n finaliza\: peerassessment.anonymousEvaluation=Evaluaci\u00f3n an\u00f3nima peerassessment.studentViewReviews=Permitir que cada estudiante pueda ver las revisiones que le han hecho @@ -1122,7 +1121,6 @@ settings.access.selectedGroupsGoneNoGroups=Nota - El grupo previamente seleccion settings.access.selectedGroupsGoneOtherGroupsPresent=Nota - El grupo previamente seleccionado ya no existe. "Mostrar a los usuarios del sitio" se ha seleccionado como opci\u00f3n de "Acceso" para esta tarea. Puede enviar esta tarea a todo el sitio o cambiar los grupos seleccionados. settings.access.selectGroups=Nota - Debes seleccionar al menos un grupo settings.access.noMembersInCommon=La opci\u00f3n de env\u00edo por grupo requiere que los grupos seleccionados no compartan estudiantes. -settings.access.noGroupAssignmentPeerInUse=(Esta opci\u00f3n no est\u00e1 disponible porque se ha habilitado la evaluaci\u00f3n por pares) settings.access.checkNow=Comprobar ahora settings.access.checkSuccess=Correcto, no hay estudiantes que participen en m\u00e1s de un grupo seleccionado. settings.access.checkError=Estudiantes que participan en m\u00e1s de un grupo seleccionado\: @@ -1159,8 +1157,6 @@ option.pointsoverride=Ajustar notas individuales de estudiantes option.hidepoints=Ocultar valores de puntuaci\u00f3n (solo en feedback) option.studentpreview=Ocultar r\u00fabrica al alumnado grading_rubric=Evaluaci\u00f3n de r\u00fabricas -asn.list.userubric=Esta tarea podr\u00eda evaluarse utilizando una r\u00fabrica -rubrics.use=Utilizar r\u00fabrica # table toolbar common messages view.label=Vista @@ -1253,3 +1249,20 @@ ts.rem.err.userId=Debe estar registrado para eliminar registros de bit\u00e1cora ts.rem.err.empty=Debe proporcionar la bit\u00e1cora seleccionada ts.rem.err.submitterId=Debe proporcionar un submissionId y ref ts.rem.err.permission=Usted no puede modificar el submitter + +#S2U-34 +peerAssessmentStudents=Los estudiantes se eval\u00faan entre ellos +peerAssessmentGroups=Los grupos se eval\u00faan entre ellos +peerassessment.group=Grupo {0} +option.selfreport=Permitir que los estudiantes autoevaluen su tarea +option.selfreport.must=Los estudiantes deben completar entera su autoevaluaci\u00F3n para poder realizar el env\u00EDo +option.selfreport.partialmust=Los estudiantes deben completar al menos un criterio de su autoevaluaci\u00F3n para poder realizar el env\u00EDo +option.selfreport.notamust=Los estudiantes no tienen porqu\u00E9 completar la autoevaluaci\u00F3n para poder realizar el env\u00EDo +youmustrubric=Esta tarea es autoevaluable. Puedes autoevaluar tu tarea con la siguiente r\u00fabrica antes de enviarla. +youhavetorubric=Esta tarea es autoevaluable. Debes autoevaluar tu tarea con la siguiente r\u00fabrica antes de enviarla. Debes completar entera la r\u00fabrica para realizar el env\u00EDo. +youhavetorubricone=Esta tarea es autoevaluable. Debes autoevaluar tu tarea con la siguiente r\u00fabrica antes de enviarla. Debes completar al menos un criterio de la r\u00fabrica para realizar el env\u00EDo. +studentrubric=Esta tarea es autoevaluable. Puedes revisar la autoevaluaci\u00f3n del estudiante antes de puntuar la tarea. +autoevaluation=Autoevaluaci\u00f3n: +instructor_grading=Correcci\u00f3n del profesor: +reviewrubric=Esta tarea es autoevaluable. Puedes revisar tu autoevaluaci\u00f3n antes de enviarla. +reviewrubricreport=Esta es tu autoevaluaci\u00f3n. diff --git a/assignment/api/src/resources/assignment_eu.properties b/assignment/api/src/resources/assignment_eu.properties index 391bca8b3c44..20b614ee0bf9 100644 --- a/assignment/api/src/resources/assignment_eu.properties +++ b/assignment/api/src/resources/assignment_eu.properties @@ -1071,7 +1071,7 @@ sendFeedback.error=Akats bat izan da feedbacka {0} ikasleei bidaltzean. # Peer Review peerAssessmentSavedGrading=Iruzkinak eta/edo kalifikazioak gorde dira, baina ez dira bidali. Ebaluazio aldia bukatu baino lehenago ez baduzu berrikuspena bidali automatikoki bidaliko da zure izenean. peerAssessmentSavedSubmission=Iruzkinak eta/edo kalifikazioa gorde eta bidali dira. -peerAssessmentName=Pareen arteko berrikuspena- Ikasleek elkarri ebaluatzeko +peerAssessmentName=Pareen arteko berrikuspena\t - {0} noAdditionalOptionsName=Ez dago zereginerako aukera gehigarririk @@ -1169,7 +1169,6 @@ option.pointsoverride=Doitu ikasleen puntuazioak option.hidepoints=Ezkutatu notak (feedbacka soilik) option.studentpreview=Ezkutatu ikasleei errubriken aurrebista grading_rubric=Errubrikaren ebaluazioa -asn.list.userubric=Errubrika baten bidez ebaluatu dezakezu zeregin hau rubrics.use=Erabili errubrika hau\: # table toolbar common messages @@ -1262,3 +1261,20 @@ ts.rem.err.userId=Saioan balidatuta egon behar duzu erregistroak gehitu ahal iza ts.rem.err.empty=Hautatutako denbora-orria eman behar da ts.rem.err.submitterId=Eman behar dituzu SubmissionId eta erref bat ts.rem.err.permission=Ezin duzu sumbitter hau aldatu + +#S2U-34 +peerAssessmentStudents= Ikasleek elkarri ebaluatuko diete. +peerAssessmentGroups= Taldeek elkarri ebaluatuko diete. +peerassessment.group=Taldea {0} +option.selfreport=Baimendu autoebaluazioa +option.selfreport.must=Ikasleek autoebaluazio osoa osatu behar dute bidalketa egin ahal izateko. +option.selfreport.partialmust=Ikasleek beren autoebaluazioaren irizpide bat bete behar dute gutxienez, bidalketa egin ahal izateko. +option.selfreport.notamust=Ikasleek ez dute zertan autoebaluazioa osatu behar bidalketa egin ahal izateko. +youmustrubric=Zeregin hau autoebaluagarria da. Zure zeregina autoebaluatu dezakezu honako errubrika honekin bidali baino lehen. +youhavetorubric=Zeregin hau autoebaluagarria da. Zure zeregina autoebaluatu behar duzu honako errubrika honekin bidali baino lehen. Errubrika osoa bete behar duzu bidalketa egiteko. +youhavetorubricone=Zeregin hau autoebaluagarria da. Zure zeregina autoebaluatu behar duzu honako errubrika honekin bidali baino lehen. Gutxienez errubrikaren irizpide bat bete behar duzu bidalketa egiteko. +studentrubric=Zeregin hau autoebaluagarria da. Ikaslearen autoebaluazioa berrikusi dezakezu zeregina puntuatu baino lehen. +autoevaluation=Autoebaluazioa: +instructor_grading=Irakaslearen zuzenketa: +reviewrubric=Zeregin hau autoebaluagarria da. Zure ebaluazioa berrikusi dezakezu bidali baino lehen. +reviewrubricreport=Hau da zure ebaluazioa. diff --git a/assignment/api/src/resources/assignment_fr_FR.properties b/assignment/api/src/resources/assignment_fr_FR.properties index 1f0cf0da8942..310ca85524a3 100644 --- a/assignment/api/src/resources/assignment_fr_FR.properties +++ b/assignment/api/src/resources/assignment_fr_FR.properties @@ -1008,7 +1008,6 @@ noAdditionalOptionsName=No additional assignment options additionalOptionsName=Additional Assignment Options peerAssessmentUse=Use peer assessment -peerassessment.warn.nogroup=(Peer assessment cannot be used with group assignments. To enable this option, switch to one of the individual assignment options in the "Assign To" section.) peerassessment.periodfinishes=Evaluation Period Finishes\: peerassessment.anonymousEvaluation=Anonymous evaluation peerassessment.studentViewReviews=Allow students to see reviews of their submissions @@ -1062,7 +1061,6 @@ settings.access.selectedGroupsGoneNoGroups=Note - The previously selected groups settings.access.selectedGroupsGoneOtherGroupsPresent=Note - The previously selected groups no longer exist. "{0}" has been selected as the "Assign To" option for this assignment. You may post this as an individual assignment for the entire site, or change the group selections. settings.access.selectGroups=Select one or more groups settings.access.noMembersInCommon=Group assignments require that the selected groups don't have any participants in common. -settings.access.noGroupAssignmentPeerInUse=(This option is not available because peer assessment has been enabled.) settings.access.checkNow=Check Now settings.access.checkSuccess=Success\! There are no students who are members of more than one of the selected groups. settings.access.checkError=The following students are members of multiple selected groups\: @@ -1099,8 +1097,6 @@ option.pointsoverride=Adjust individual student scores option.hidepoints=Hide point values (feedback only) option.studentpreview=Hide Rubric from student grading_rubric=Grading Rubric -asn.list.userubric=This assignment could be graded using a Rubric -rubrics.use=Use rubric # table toolbar common messages view.label=View diff --git a/assignment/api/src/resources/assignment_ro_RO.properties b/assignment/api/src/resources/assignment_ro_RO.properties index 4500bd1b305a..cb362f6683b5 100644 --- a/assignment/api/src/resources/assignment_ro_RO.properties +++ b/assignment/api/src/resources/assignment_ro_RO.properties @@ -1049,7 +1049,6 @@ noAdditionalOptionsName=Nicio optiune pentru sarcina de lucru suplimentara. additionalOptionsName=Optiuni additionale tema peerAssessmentUse=Folositi evaluarea reciproca intre colegi -peerassessment.warn.nogroup=(Evaluarea reciproca intre colegi nu poate fi folosita pentru sarcinile de lucru in grup. Pentru a activa aceasta optiune, comutati la una din optiunile de sarcina de lucru individuala in sectiunea "Atribuie lui".) peerassessment.periodfinishes=Perioada de evaluare se termina\: peerassessment.anonymousEvaluation=Evaluare anonima peerassessment.studentViewReviews=Permiteti studentilor sa vada revizuirile sarcinilor de lucru @@ -1103,7 +1102,6 @@ settings.access.selectedGroupsGoneNoGroups=Nota - Grupurile selectate anterior n settings.access.selectedGroupsGoneOtherGroupsPresent=Nota - Grupurile selectate anterior nu mai exista. "{0}" a fost selectata drept optiunea "Atribuit lui" pentru aceasta tema. O puteti posta ca tema individuala pentru tot site-ul, sau sa schimbati selectarile din grup. settings.access.selectGroups=Selectati unul sau mai multe grupuri settings.access.noMembersInCommon=Temele de grup presupun ca grupurile selectate sa nu aiba vreun participant in comun. -settings.access.noGroupAssignmentPeerInUse=(Aceasta optiune nu este valabila deoarece evaluarea inter pares a fost activata.) settings.access.checkNow=Verificati acum settings.access.checkSuccess=Succes\! Nu exista studenti care sa fie membri ai mai multor grupuri selectate. settings.access.checkError=Urmatorii studenti sunt membri ai grupurilor selectate multiple\: @@ -1140,8 +1138,6 @@ option.pointsoverride=Ajustati rezultate individuale ale studentilor option.hidepoints=Ascundeti valorile punctelor (numai feedback) option.studentpreview=Ascundeti rubrica de studenti grading_rubric=Se acorda nota rubricii -asn.list.userubric=Aceasta tema nu a putut fi notata folosind o Rubrica -rubrics.use=Folositi rubrica # table toolbar common messages view.label=Vizualizare diff --git a/assignment/api/src/resources/assignment_tr_TR.properties b/assignment/api/src/resources/assignment_tr_TR.properties index 093e6946dd7c..33177967558f 100644 --- a/assignment/api/src/resources/assignment_tr_TR.properties +++ b/assignment/api/src/resources/assignment_tr_TR.properties @@ -817,7 +817,6 @@ peerAssessmentName=Akran De\u011ferlendirmesi - \u00d6\u011frenciler birbirlerin noAdditionalOptionsName=Ek \u00f6dev se\u00e7enekleri yok additionalOptionsName=Ek \u00d6dev Se\u00e7enekleri peerAssessmentUse=Akran De\u011ferlendirmesi Kullan\u0131n -peerassessment.warn.nogroup=(Grup \u00f6devleri i\u00e7in akran de\u011ferlendirmesi kullan\u0131lamaz. Bu se\u00e7ene\u011fi etkinle\u015ftirmek i\u00e7in, bir bireysel \u00f6dev se\u00e7ene\u011fini ''teslim et '' b\u00f6l\u00fcm\u00fcnde de\u011fi\u015ftiriniz.) peerassessment.periodfinishes=De\u011ferlendirme D\u00f6nemi Biti\u015f Tarihi\: peerassessment.anonymousEvaluation=Anonim De\u011ferlendirme peerassessment.studentViewReviews=\u00d6\u011frencilerin \u00f6devlerinin de\u011ferlendirmelerini g\u00f6rmelerine izin verin @@ -869,7 +868,6 @@ settings.access.selectedGroupsGoneNoGroups=Not - \u00f6nceden se\u00e7ilen grupl settings.access.selectedGroupsGoneOtherGroupsPresent=Not-\u00d6nceden se\u00e7ilmi\u015f gruplar art\u0131k mevcut de\u011fildir. Bu \u00f6dev i\u00e7in ''ata'' se\u00e7ene\u011fi olarak "{0}" se\u00e7ildi.Bunu sitenin tamam\u0131 i\u00e7in ayr\u0131 bir \u00f6dev olarak g\u00f6nderebilir, veya grup se\u00e7imlerini de\u011fi\u015ftirebilirsiniz. settings.access.selectGroups=Bir veya daha fazla grup se\u00e7iniz settings.access.noMembersInCommon=Grup \u00f6devleri, se\u00e7ilen gruplar\u0131n ortak kat\u0131l\u0131mc\u0131lar\u0131n\u0131n olmamas\u0131n\u0131 gerektirmektedir. -settings.access.noGroupAssignmentPeerInUse=(Bu se\u00e7enek etkin de\u011fil \u00e7\u00fcnk\u00fc akran de\u011ferlendirmesi etkinle\u015ftirilmedi.) settings.access.checkNow=\u015eimdi Kontrol Edin settings.access.checkSuccess=Ba\u015far\u0131l\u0131\! Se\u00e7ilmi\u015f birden fazla grubun \u00fcyesi olan \u00f6\u011frenci bulunmamaktad\u0131r. settings.access.checkError=A\u015fa\u011f\u0131daki \u00f6\u011frenciler \u00e7oklu se\u00e7ilmi\u015f gruplar\u0131n \u00fcyesidir\: @@ -899,8 +897,6 @@ option.pointsoverride=Bireysel \u00f6\u011frenci puanlar\u0131n\u0131 ayarlay\u0 option.hidepoints=Puan de\u011ferini saklay\u0131n (sadece geri bildirim) option.studentpreview=Rubrik'i \u00d6\u011frenciden Gizleyin grading_rubric=Rubrik Notland\u0131rma -asn.list.userubric=Bu \u00f6dev Rubrik kullanarak notland\u0131r\u0131labilir -rubrics.use=Rubrik kullan\u0131n view.label=G\u00f6ster gen.viewing.phrase=\ {0} - {1} / {2} gen.show={0} \u00f6geyi g\u00f6ster.... diff --git a/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentEventObserver.java b/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentEventObserver.java index 9ccfba716474..edbde8fd8e27 100644 --- a/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentEventObserver.java +++ b/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentEventObserver.java @@ -83,7 +83,7 @@ public void update(Observable o, Object arg) { submission = Optional.ofNullable(assignmentService.getSubmission(a.getId(), user.getId())); submission = Optional.ofNullable(submission.orElseGet(() -> { try { - return assignmentService.addSubmission(a.getId(), assignmentService.getSubmitterIdForAssignment(a, user)); + return assignmentService.addSubmission(a.getId(), assignmentService.getSubmitterIdForAssignment(a, user.getId())); } catch (PermissionException e) { log.warn("Can't access submission for assignment {} and user {}, {}", a.getId(), user.getId(), e.getMessage()); } diff --git a/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentPeerAssessmentServiceImpl.java b/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentPeerAssessmentServiceImpl.java index c34a5700f7ae..e35ca2f1cd51 100644 --- a/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentPeerAssessmentServiceImpl.java +++ b/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentPeerAssessmentServiceImpl.java @@ -20,6 +20,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -27,6 +28,8 @@ import java.util.Set; import java.util.stream.Collectors; +import lombok.Getter; +import lombok.Setter; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.hibernate.criterion.DetachedCriteria; @@ -42,10 +45,14 @@ import org.sakaiproject.assignment.api.model.AssignmentSubmissionSubmitter; import org.sakaiproject.assignment.api.model.PeerAssessmentAttachment; import org.sakaiproject.assignment.api.model.PeerAssessmentItem; +import org.sakaiproject.authz.api.Member; import org.sakaiproject.authz.api.SecurityAdvisor; import org.sakaiproject.authz.api.SecurityService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; +import org.sakaiproject.site.api.Group; +import org.sakaiproject.site.api.Site; +import org.sakaiproject.site.api.SiteService; import org.sakaiproject.tool.api.SessionManager; import org.sakaiproject.user.api.User; import org.springframework.orm.hibernate5.HibernateCallback; @@ -56,10 +63,11 @@ @Slf4j public class AssignmentPeerAssessmentServiceImpl extends HibernateDaoSupport implements AssignmentPeerAssessmentService { - private ScheduledInvocationManager scheduledInvocationManager; - protected AssignmentService assignmentService; - private SecurityService securityService = null; - private SessionManager sessionManager; + @Getter @Setter private ScheduledInvocationManager scheduledInvocationManager; + @Getter @Setter protected AssignmentService assignmentService; + @Getter @Setter private SecurityService securityService = null; + @Getter @Setter private SessionManager sessionManager; + @Getter @Setter private SiteService siteService; public void schedulePeerReview(String assignmentId) { //first remove any previously scheduled reviews: @@ -108,25 +116,27 @@ public void execute(String opaqueContext) { //keep track of how many assessor's each student has Map studentAssessorsMap = new HashMap(); List submitterUsersList = assignmentService.allowAddSubmissionUsers(assignmentService.createAssignmentEntity(assignment.getId()).getReference()); - List submitterIdsList = new ArrayList(); + Set submitterIdsList = new HashSet(); if (submitterUsersList != null) { for (User u : submitterUsersList) { - submitterIdsList.add(u.getId()); + String submitterId = assignmentService.getSubmitterIdForAssignment(assignment, u.getId()); + submitterIdsList.add(submitterId); } } //loop through the assignment submissions and setup the maps and lists for (AssignmentSubmission s : submissions) { Optional ass = assignmentService.getSubmissionSubmittee(s); List submitteeIds = s.getSubmitters().stream().map(AssignmentSubmissionSubmitter::getSubmitter).collect(Collectors.toList()); + String submitterId = ass.isPresent() ? assignmentService.getSubmitterIdForAssignment(assignment, ass.get().getSubmitter()) : ""; //check if the submission is submitted, if not, see if there is any submission data to review (i.e. draft was auto submitted) if (s.getDateSubmitted() != null && (s.getSubmitted() || (StringUtils.isNotBlank(s.getSubmittedText() ) || (CollectionUtils.isNotEmpty(s.getAttachments() )))) - && CollectionUtils.containsAny(submitterIdsList,submitteeIds) + && (CollectionUtils.containsAny(submitterIdsList, submitteeIds) || (assignment.getIsGroup() && submitterIdsList.contains(submitterId))) && !s.getSubmitters().contains("admin")) { //only deal with users in the submitter's list submissionIdMap.put(s.getId(), s); if (ass.isPresent()) { - assignedAssessmentsMap.put(ass.get().getSubmitter(), new HashMap<>()); - studentAssessorsMap.put(ass.get().getSubmitter(), 0); + assignedAssessmentsMap.put(submitterId, new HashMap<>()); + studentAssessorsMap.put(submitterId, 0); } } } @@ -151,13 +161,14 @@ public void execute(String opaqueContext) { //first, add this assessment to the AssignedAssessmentsMap AssignmentSubmission s = submissionIdMap.get(p.getId().getSubmissionId()); Optional ass = assignmentService.getSubmissionSubmittee(s);//Next, increment the count for studentAssessorsMap - Integer count = ass.isPresent() ?studentAssessorsMap.get(ass.get().getSubmitter()) : 0; + String submitterId = assignmentService.getSubmitterIdForAssignment(assignment, ass.get().getSubmitter()); + Integer count = ass.isPresent() ? studentAssessorsMap.get(submitterId) : 0; //check if the count is less than num of reviews before added another one, //otherwise, we need to delete this one (if it's empty) if (count < numOfReviews || p.getScore() != null || p.getComment() != null) { count++; - studentAssessorsMap.put(ass.get().getSubmitter(), count); + studentAssessorsMap.put(submitterId, count); Map peerAssessments = assignedAssessmentsMap.get(p.getId().getAssessorUserId()); if (peerAssessments == null) { //probably not possible, but just check @@ -185,7 +196,8 @@ public void execute(String opaqueContext) { for (String submissionId : randomSubmissionIds) { AssignmentSubmission s = submissionIdMap.get(submissionId); Optional ass = assignmentService.getSubmissionSubmittee(s);//first find out how many existing items exist for this user: - Integer assignedCount = ass.isPresent() ? studentAssessorsMap.get(ass.get().getSubmitter()) : 0; + String studentId = assignmentService.getSubmitterIdForAssignment(assignment, ass.get().getSubmitter()); + Integer assignedCount = ass.isPresent() ? studentAssessorsMap.get(studentId) : 0; //by creating a tailing list (snake style), we eliminate the issue where you can be stuck with //a submission and the same submission user left, making for uneven distributions of submission reviews List snakeSubmissionList = new ArrayList(randomSubmissionIds.subList(i, randomSubmissionIds.size())); @@ -194,7 +206,7 @@ public void execute(String opaqueContext) { } while (assignedCount < numOfReviews) { //we need to add more reviewers for this user's submission - String lowestAssignedAssessor = findLowestAssignedAssessor(assignedAssessmentsMap, ass.get().getSubmitter(), submissionId, snakeSubmissionList, submissionIdMap); + String lowestAssignedAssessor = findLowestAssignedAssessor(assignedAssessmentsMap, studentId, submissionId, snakeSubmissionList, submissionIdMap); if (lowestAssignedAssessor != null) { Map assessorsAssessmentMap = assignedAssessmentsMap.get(lowestAssignedAssessor); if (assessorsAssessmentMap == null) { @@ -237,7 +249,7 @@ private String findLowestAssignedAssessor(Map ass = assignmentService.getSubmissionSubmittee(s);//do not include assesseeId (aka the user being assessed) if (ass.isPresent()) { - String submitter = ass.get().getSubmitter(); + String submitter = assignmentService.getSubmitterIdForAssignment(s.getAssignment(), ass.get().getSubmitter()); if (!assesseeId.equals(submitter) && (lowestAssignedAssessorCount == null || peerAssessments.get(submitter).keySet().size() < lowestAssignedAssessorCount)) { //check if this user already has a peer assessment for this assessee @@ -487,29 +499,4 @@ public SecurityAdvice isAllowed(String userId, String function, String reference return saved; } - public void setScheduledInvocationManager( - ScheduledInvocationManager scheduledInvocationManager) { - this.scheduledInvocationManager = scheduledInvocationManager; - } - - public void setAssignmentService(AssignmentService assignmentService) { - this.assignmentService = assignmentService; - } - - public SecurityService getSecurityService() { - return securityService; - } - - public void setSecurityService(SecurityService securityService) { - this.securityService = securityService; - } - - public SessionManager getSessionManager() { - return sessionManager; - } - - public void setSessionManager(SessionManager sessionManager) { - this.sessionManager = sessionManager; - } - } diff --git a/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java b/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java index 665ea83278b1..6f4bd7a7a6b7 100644 --- a/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java +++ b/assignment/impl/src/java/org/sakaiproject/assignment/impl/AssignmentServiceImpl.java @@ -2579,7 +2579,7 @@ public Map getSubmitterMap(String searchFilterOnly, usersWithNoSubmission.removeAll(submitterMap.keySet()); for (final User user : usersWithNoSubmission) { - String submitterId = getSubmitterIdForAssignment(a, user); + String submitterId = getSubmitterIdForAssignment(a, user.getId()); if (StringUtils.isNotBlank(submitterId)) { try { AssignmentSubmission submission = addSubmission(assignmentId, submitterId); @@ -2627,42 +2627,46 @@ public Map getSubmitterMap(String searchFilterOnly, } @Override - public String getSubmitterIdForAssignment(Assignment assignment, User user) { + public String getSubmitterIdForAssignment(Assignment assignment, String userId) { String submitter = null; - if (user != null) { + if (userId != null) { switch (assignment.getTypeOfAccess()) { case SITE: // access is for the entire site and submitter is a user - submitter = user.getId(); + submitter = userId; break; case GROUP: // access is restricted to groups Site site; try { site = siteService.getSite(assignment.getContext()); + //if it is an actual group id we just return it + if (site.getGroup(userId) != null) { + return userId; + } Set assignmentGroups = assignment.getGroups(); - Collection userGroups = site.getGroupsWithMember(user.getId()); + Collection userGroups = site.getGroupsWithMember(userId); Set groupIdsMatchingAssignmentForUser = userGroups.stream().filter(g -> assignmentGroups.contains(g.getReference())).map(Group::getId).collect(Collectors.toSet()); if (groupIdsMatchingAssignmentForUser.size() < 1) { - log.debug("User {} is not a member of any groups for this assignment {}", user.getId(), assignment.getId()); + log.debug("User {} is not a member of any groups for this assignment {}", userId, assignment.getId()); } else if (groupIdsMatchingAssignmentForUser.size() == 1) { if (assignment.getIsGroup()) { submitter = groupIdsMatchingAssignmentForUser.toArray(new String[] {})[0]; } else { - submitter = user.getId(); + submitter = userId; } } else if (groupIdsMatchingAssignmentForUser.size() > 1 && !assignment.getIsGroup()) { - submitter = user.getId(); + submitter = userId; } else { - log.warn("User {} is on more than one group for this assignment {}, please remove the user from a group so that they are only a member of a single group", user.getId(), assignment.getId()); + log.warn("User {} is on more than one group for this assignment {}, please remove the user from a group so that they are only a member of a single group", userId, assignment.getId()); } } catch (IdUnusedException iue) { log.warn("Could not get the site {} for assignment {} while determining the submitter of the submission", assignment.getContext(), assignment.getId()); } break; default: - log.warn("Can't determine the type of submission to create for user {} in assignment {}", user.getId(), assignment.getId()); + log.warn("Can't determine the type of submission to create for user {} in assignment {}", userId, assignment.getId()); break; } } diff --git a/assignment/impl/src/webapp/WEB-INF/components.xml b/assignment/impl/src/webapp/WEB-INF/components.xml index 41479cf84e29..ce39eb032a0c 100644 --- a/assignment/impl/src/webapp/WEB-INF/components.xml +++ b/assignment/impl/src/webapp/WEB-INF/components.xml @@ -195,6 +195,7 @@ + submissionAttachmentReferences = new HashMap<>(); stripInvisibleAttachments(state.getAttribute(ATTACHMENTS)).forEach(r -> submissionAttachmentReferences.put(r.getId(), r)); @@ -2626,6 +2631,8 @@ protected String build_student_view_grade_context(VelocityPortlet portlet, Conte } context.put("users", assignmentService.getSubmissionSubmittersAsUsers(submission)); + context.put("rubricSelfReport", assignmentToolUtils.hasRubricSelfReview(assignment.getId())); + context.put("rubricHiddenToStudent", assignmentToolUtils.hasRubricHiddenToStudent(assignment.getId())); Map assignmentAttachmentReferences = new HashMap<>(); assignment.getAttachments().forEach(r -> assignmentAttachmentReferences.put(r, entityManager.newReference(r))); @@ -2639,6 +2646,7 @@ protected String build_student_view_grade_context(VelocityPortlet portlet, Conte context.put("submissionFeedbackAttachmentReferences", submissionFeedbackAttachmentReferences); String currentUser = userDirectoryService.getCurrentUser().getId(); + context.put("currentUserId", currentUser); String grade = assignmentService.getGradeForSubmitter(submission, currentUser); context.put("grade", grade); @@ -2681,9 +2689,15 @@ protected String build_student_view_grade_context(VelocityPortlet portlet, Conte } else { //need to set the assessor's display name try { - review.setAssessorDisplayName(userDirectoryService.getUser(review.getId().getAssessorUserId()).getDisplayName()); - } catch (UserNotDefinedException e) { - //reviewer doesn't exist or userId is wrong + if (assignment.getIsGroup()) { + String siteId = toolManager.getCurrentPlacement().getContext(); + Site site = siteService.getSite(siteId); + review.setAssessorDisplayName(site.getGroup(review.getId().getAssessorUserId()).getTitle()); + } else { + review.setAssessorDisplayName(userDirectoryService.getUser(review.getId().getAssessorUserId()).getDisplayName()); + } + } catch (IdUnusedException | UserNotDefinedException e) { + //reviewer doesn't exist or one of userId/groupId/siteId is wrong log.error(e.getMessage(), e); //set a default one: review.setAssessorDisplayName(rb.getFormattedMessage("gen.reviewer.countReview", completedReviews.size() + 1)); @@ -2822,7 +2836,8 @@ private String build_list_assignments_context(VelocityPortlet portlet, Context c //now lets create a map for peer reviews for each eligible assignment for (Assignment assignment : assignments) { if (assignment.getAllowPeerAssessment() && (assignmentService.isPeerAssessmentOpen(assignment) || assignmentService.isPeerAssessmentClosed(assignment))) { - peerAssessmentItemsMap.put(assignment.getId(), assignmentPeerAssessmentService.getPeerAssessmentItems(assignment.getId(), userDirectoryService.getCurrentUser().getId(), assignment.getScaleFactor())); + String peerId = assignmentService.getSubmitterIdForAssignment(assignment, userDirectoryService.getCurrentUser().getId()); + peerAssessmentItemsMap.put(assignment.getId(), assignmentPeerAssessmentService.getPeerAssessmentItems(assignment.getId(), peerId, assignment.getScaleFactor())); } } } @@ -3819,8 +3834,24 @@ protected String build_instructor_grade_submission_context(VelocityPortlet portl state.setAttribute(NEW_ASSIGNMENT_CHECK_ANONYMOUS_GRADING, assignmentService.assignmentUsesAnonymousGrading(a)); boolean allowToGrade = true; - if (StringUtils.isNotBlank(a.getProperties().get(PROP_ASSIGNMENT_ASSOCIATE_GRADEBOOK_ASSIGNMENT))) { + String assignmentAssociateGradebook = a.getProperties().get(PROP_ASSIGNMENT_ASSOCIATE_GRADEBOOK_ASSIGNMENT); + if (StringUtils.isNotBlank(assignmentAssociateGradebook)) { String gradebookUid = toolManager.getCurrentPlacement().getContext(); + // If the assignment reference is not equal to the associated gradebook item, then a custom gb item is being used + if (!assignmentRef.equals(assignmentAssociateGradebook)) { + try { + org.sakaiproject.grading.api.Assignment gbAssignment = gradingService.getAssignment(gradebookUid, + assignmentAssociateGradebook); + + Long associateGradebookAssignmentId = gbAssignment.getId(); + context.put("associatedToGbItem", true); + context.put("associatedToGbEntityId", associateGradebookAssignmentId); + } catch (AssessmentNotFoundException e) { + log.error("Assignment not found while building grade submission context for custom gradebook item due to: {} {}", + e.toString(), ExceptionUtils.getStackTrace(e)); + } + } + if (!gradingService.currentUserHasGradingPerm(gradebookUid)) { context.put("notAllowedToGradeWarning", rb.getString("not_allowed_to_grade_in_gradebook")); allowToGrade = false; @@ -3861,7 +3892,7 @@ protected String build_instructor_grade_submission_context(VelocityPortlet portl // try to put in grade overrides if (a.getIsGroup()) { - context.put("groupRef", "/site/" + a.getContext() + "/group/" + s.getGroupId()); + context.put("ownerGroupId", s.getGroupId()); Map grades = new HashMap<>(); for (String userId : users.keySet()) { String userGrade = (String) state.getAttribute(GRADE_SUBMISSION_GRADE + "_" + userId); @@ -3871,6 +3902,39 @@ protected String build_instructor_grade_submission_context(VelocityPortlet portl } context.put("value_grades", grades); } + + // Check if the assignment has a rubric associated or not + context.put("hasAssociatedRubric", rubricsService.hasAssociatedRubric(RubricsConstants.RBCS_TOOL_ASSIGNMENT_GRADES, a.getId())); + context.put("rubricSelfReport", assignmentToolUtils.hasRubricSelfReview(a.getId())); + + //peer review + if (a.getAllowPeerAssessment() && a.getPeerAssessmentStudentReview() && assignmentService.isPeerAssessmentClosed(a)) { + List reviews = assignmentPeerAssessmentService.getPeerAssessmentItems(s.getId(), a.getScaleFactor()); + List completedReviews = new ArrayList<>(); + for (PeerAssessmentItem review : reviews) { + if (!review.getRemoved() && (review.getScore() != null || (review.getComment() != null && !"".equals(review.getComment().trim())))) { + //only show peer reviews that have either a score or a comment saved + try { + if (a.getIsGroup()) { + String siteId = toolManager.getCurrentPlacement().getContext(); + Site site = siteService.getSite(siteId); + review.setAssessorDisplayName(site.getGroup(review.getId().getAssessorUserId()).getTitle()); + } else { + review.setAssessorDisplayName(userDirectoryService.getUser(review.getId().getAssessorUserId()).getDisplayName()); + } + } catch (IdUnusedException | UserNotDefinedException e) { + //reviewer doesn't exist or one of userId/groupId/siteId is wrong + log.error(e.getMessage(), e); + //set a default one: + review.setAssessorDisplayName(rb.getFormattedMessage("gen.reviewer.countReview", completedReviews.size() + 1)); + } + completedReviews.add(review); + } + } + if (completedReviews.size() > 0) { + context.put("peerReviews", completedReviews); + } + } } // show alert if student is working on a draft @@ -4115,9 +4179,6 @@ protected String build_instructor_grade_submission_context(VelocityPortlet portl // letter grading letterGradeOptionsIntoContext(context); - // Check if the assignment has a rubric associated or not - context.put("hasAssociatedRubric", assignment.isPresent() && rubricsService.hasAssociatedRubric(AssignmentConstants.TOOL_ID, assignment.get().getId())); - context.put(RUBRICS_EXPORT_PDF, serverConfigurationService.getBoolean(RubricsConstants.RBCS_EXPORT_PDF, true)); String siteId = (String) state.getAttribute(STATE_CONTEXT_STRING); @@ -4331,6 +4392,13 @@ public void doPrev_back_next_submission_review(RunData rundata, String option, b SessionState state = ((JetspeedRunData) rundata).getPortletSessionState(((JetspeedRunData) rundata).getJs_peid()); // save the instructor input boolean hasChange = saveReviewGradeForm(rundata, state, submit ? "submit" : "save"); + switch (option) { + case "back": + case "backListStudent": + state.removeAttribute(PEER_ASSESSMENT_ASSESSOR_ID); + break; + default: // Do nothing + } if (state.getAttribute(STATE_MESSAGE) == null) { ParameterParser params = rundata.getParameters(); @@ -4743,6 +4811,13 @@ private String build_instructor_grade_assignment_context(VelocityPortlet portlet //create a map for velocity to use in displaying the submission reviews Map> itemsMap = new HashMap>(); Map reviewersMap = new HashMap<>(); + Map groupsReviewersMap = new HashMap<>(); + Site site = null; + try { + site = siteService.getSite(assignment.getContext()); + } catch (IdUnusedException ex) { + log.error("Could not get the site {}", context); + } if (items != null) { for (PeerAssessmentItem item : items) { //update items map @@ -4752,14 +4827,22 @@ private String build_instructor_grade_assignment_context(VelocityPortlet portlet } sItems.add(item); itemsMap.put(item.getId().getSubmissionId(), sItems); - //update users map: - User u = reviewersMap.get(item.getId().getAssessorUserId()); - if (u == null) { - try { - u = userDirectoryService.getUser(item.getId().getAssessorUserId()); - reviewersMap.put(item.getId().getAssessorUserId(), u); - } catch (UserNotDefinedException e) { - log.error(e.getMessage(), e); + //update users/groups map: + if (assignment.getIsGroup()) { + Group gr = groupsReviewersMap.get(item.getId().getAssessorUserId()); + if (gr == null && site != null) { + gr = site.getGroup(item.getId().getAssessorUserId()); + groupsReviewersMap.put(item.getId().getAssessorUserId(), gr); + } + } else { + User u = reviewersMap.get(item.getId().getAssessorUserId()); + if (u == null) { + try { + u = userDirectoryService.getUser(item.getId().getAssessorUserId()); + reviewersMap.put(item.getId().getAssessorUserId(), u); + } catch (UserNotDefinedException e) { + log.error(e.getMessage(), e); + } } } } @@ -4774,6 +4857,7 @@ private String build_instructor_grade_assignment_context(VelocityPortlet portlet } context.put("peerAssessmentItems", itemsMap); context.put("reviewersMap", reviewersMap); + context.put("groupsReviewersMap", groupsReviewersMap); } // try to put in grade overrides @@ -5138,14 +5222,19 @@ private String build_student_review_edit_context(VelocityPortlet portlet, Contex context.put("context", state.getAttribute(STATE_CONTEXT_STRING)); List peerAssessmentItems = (List) state.getAttribute(PEER_ASSESSMENT_ITEMS); String assignmentId = (String) state.getAttribute(VIEW_ASSIGNMENT_ID); + Assignment assignment = getAssignment(assignmentId, "build_student_review_edit_context", state); User sessionUser = (User) state.getAttribute(STATE_USER); - String assessorId = sessionUser.getId(); - if (state.getAttribute(PEER_ASSESSMENT_ASSESSOR_ID) != null) { - assessorId = (String) state.getAttribute(PEER_ASSESSMENT_ASSESSOR_ID); + String assessorId = (String) state.getAttribute(PEER_ASSESSMENT_ASSESSOR_ID); + if (assessorId == null) assessorId = sessionUser.getId(); + String currentUserGroup = null; + if (assignment.getIsGroup()) { + assessorId = assignmentService.getSubmitterIdForAssignment(assignment, assessorId); + currentUserGroup = assignmentService.getSubmitterIdForAssignment(assignment, sessionUser.getId()); } + context.put("assessorId", assessorId); + int factor = assignmentService.getScaleFactor(); int dec = (int) Math.log10(factor); - Assignment assignment = getAssignment(assignmentId, "build_student_review_edit_context", state); if (assignment != null) { context.put("assignment", assignment); factor = assignment.getScaleFactor(); @@ -5179,6 +5268,7 @@ private String build_student_review_edit_context(VelocityPortlet portlet, Contex securityService.popAdvisor(secAdv); } } + context.put(RubricsConstants.RBCS_HAS_ASSOCIATED_RUBRIC, rubricsService.hasAssociatedRubric(RubricsConstants.RBCS_TOOL_ASSIGNMENT_GRADES, assignment.getId())); if (s != null) { submissionId = s.getId(); context.put("submission", s); @@ -5187,7 +5277,11 @@ private String build_student_review_edit_context(VelocityPortlet portlet, Contex final String submitterNames = assignmentToolUtils.getSubmitters(s) .map(u -> u.getDisplayName() + " (" + u.getDisplayId() + ")").collect(Collectors.joining(", ")); context.put("submitterNames", formattedText.escapeHtml(submitterNames)); - + if (assignment.getIsGroup()) { + context.put("ownerGroupId", s.getGroupId()); + } else { + s.getSubmitters().stream().findAny().ifPresent(u -> context.put("submitterId", u.getSubmitter())); + } Map p = s.getProperties(); if (p.get(ResourceProperties.PROP_SUBMISSION_PREVIOUS_FEEDBACK_TEXT) != null) { context.put("prevFeedbackText", p.get(ResourceProperties.PROP_SUBMISSION_PREVIOUS_FEEDBACK_TEXT)); @@ -5226,18 +5320,32 @@ private String build_student_review_edit_context(VelocityPortlet portlet, Contex } if (peerAssessmentItem != null) { //check if current user is the peer assessor, if not, only display data (no editing) - if (!sessionUser.getId().equals(peerAssessmentItem.getId().getAssessorUserId())) { + String currentUserReviewerId = sessionUser.getId(); + if (assignment.getIsGroup() && currentUserGroup != null) { + currentUserReviewerId = currentUserGroup; + } + if (!currentUserReviewerId.equals(peerAssessmentItem.getId().getAssessorUserId())) { context.put("view_only", true); try { - User reviewer = userDirectoryService.getUser(peerAssessmentItem.getId().getAssessorUserId()); - context.put("reviewer", reviewer); + if (assignment.getIsGroup()) { + try { + Site site = siteService.getSite(assignment.getContext()); + Group group = site.getGroup(peerAssessmentItem.getId().getAssessorUserId()); + context.put("reviewer", group); + } catch (IdUnusedException ex) { + log.warn("Could not get the site {}", context); + } + } else { + User reviewer = userDirectoryService.getUser(peerAssessmentItem.getId().getAssessorUserId()); + context.put("reviewer", reviewer); + } } catch (UserNotDefinedException e) { log.error(e.getMessage(), e); } } else { context.put("view_only", false); } - + context.put(RubricsConstants.RBCS_ASSESSOR_ID, peerAssessmentItem.getId().getAssessorUserId()); // get attachments for peer review item List attachments = assignmentPeerAssessmentService.getPeerAssessmentAttachments(peerAssessmentItem.getId().getSubmissionId(), peerAssessmentItem.getId().getAssessorUserId()); List attachmentRefList = new ArrayList<>(); @@ -7499,6 +7607,8 @@ private void setNewAssignmentParameters(RunData data, boolean validify) { Map rubricAssociationParameters = new HashMap<>(); rubricAssociationParameters.put("fineTunePoints", params.getString(RubricsConstants.RBCS_CONFIG + "fineTunePoints")); rubricAssociationParameters.put("hideStudentPreview", params.getString(RubricsConstants.RBCS_CONFIG + "hideStudentPreview")); + rubricAssociationParameters.put("studentSelfReport", params.getString(RubricsConstants.RBCS_CONFIG + "studentSelfReport")); + rubricAssociationParameters.put("studentSelfReportMode", params.getString("rbcs-multiple-options-config-studentSelfReportMode")); rubricAssociationMap.put("parameters", rubricAssociationParameters); try { state.setAttribute(RUBRIC_ASSOCIATION, (new ObjectMapper()).writeValueAsString(rubricAssociationMap)); @@ -7517,10 +7627,6 @@ private void setNewAssignmentParameters(RunData data, boolean validify) { } if (peerAssessment) { - //not allowed for group assignments: - if (groupAssignment) { - addAlert(state, rb.getString("peerassessment.invliadGroupAssignment")); - } //do not allow non-electronic assignments if (Assignment.SubmissionType.NON_ELECTRONIC_ASSIGNMENT_SUBMISSION == submissionType) { addAlert(state, rb.getString("peerassessment.invliadSubmissionTypeAssignment")); @@ -9807,7 +9913,7 @@ public void doView_assignment_as_student(RunData data) { public void doView_submissionReviews(RunData data) { String submissionId = data.getParameters().getString("submissionId"); SessionState state = ((JetspeedRunData) data).getPortletSessionState(((JetspeedRunData) data).getJs_peid()); - String assessorId = data.getParameters().getString("assessorId"); + String assessorId = data.getParameters().getString(RubricsConstants.RBCS_ASSESSOR_ID); String assignmentId = StringUtils.trimToNull(data.getParameters().getString("assignmentId")); Assignment a = getAssignment(assignmentId, "doEdit_assignment", state); if (submissionId != null && !"".equals(submissionId) && a != null) { @@ -9841,7 +9947,8 @@ public void doEdit_review(RunData data) { //set the page to go to state.setAttribute(VIEW_ASSIGNMENT_ID, assignmentId); String submissionId = null; - List peerAssessmentItems = assignmentPeerAssessmentService.getPeerAssessmentItems(a.getId(), userDirectoryService.getCurrentUser().getId(), a.getScaleFactor()); + String peerId = assignmentService.getSubmitterIdForAssignment(a, userDirectoryService.getCurrentUser().getId()); + List peerAssessmentItems = peerAssessmentItems = assignmentPeerAssessmentService.getPeerAssessmentItems(a.getId(), peerId, a.getScaleFactor()); state.setAttribute(PEER_ASSESSMENT_ITEMS, peerAssessmentItems); List submissionIds = new ArrayList(); if (peerAssessmentItems != null) { @@ -11268,11 +11375,6 @@ private void saveSubmitInputs(SessionState state, ParameterParser params) { * @return */ public boolean saveReviewGradeForm(RunData data, SessionState state, String gradeOption) { - String assessorUserId = userDirectoryService.getCurrentUser().getId(); - if (state.getAttribute(PEER_ASSESSMENT_ASSESSOR_ID) != null && !assessorUserId.equals(state.getAttribute(PEER_ASSESSMENT_ASSESSOR_ID))) { - //this is only set during the read only view, so just return - return false; - } boolean preExistingAlerts = state.getAttribute(STATE_MESSAGE) != null; @@ -11284,6 +11386,14 @@ public boolean saveReviewGradeForm(RunData data, SessionState state, String grad submissionId = s.getId();//using the id instead of the reference } + Assignment assignment = s.getAssignment(); + String assessorUserId = assignmentService.getSubmitterIdForAssignment(assignment, userDirectoryService.getCurrentUser().getId()); + + if (state.getAttribute(PEER_ASSESSMENT_ASSESSOR_ID) != null && !state.getAttribute(PEER_ASSESSMENT_ASSESSOR_ID).equals(assessorUserId)) { + //this is only set during the read only view, so just return + return false; + } + //call the DB to make sure this user can edit this assessment, otherwise it wouldn't exist PeerAssessmentItem item = assignmentPeerAssessmentService.getPeerAssessmentItem(submissionId, assessorUserId); if (item != null) { diff --git a/assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentToolUtils.java b/assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentToolUtils.java index d5bda4ca7478..828c192e31d7 100644 --- a/assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentToolUtils.java +++ b/assignment/tool/src/java/org/sakaiproject/assignment/tool/AssignmentToolUtils.java @@ -33,6 +33,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -52,6 +53,9 @@ import org.sakaiproject.grading.api.GradingService; import org.sakaiproject.grading.api.InvalidGradeItemNameException; import org.sakaiproject.lti.api.LTIService; +import org.sakaiproject.rubrics.api.RubricsConstants; +import org.sakaiproject.rubrics.api.RubricsService; +import org.sakaiproject.rubrics.api.model.ToolItemRubricAssociation; import org.sakaiproject.time.api.TimeService; import org.sakaiproject.tool.api.ToolManager; import org.sakaiproject.user.api.User; @@ -75,6 +79,7 @@ public class AssignmentToolUtils { private AssignmentService assignmentService; private UserDirectoryService userDirectoryService; private GradingService gradingService; + private RubricsService rubricsService; private TimeService timeService; private ToolManager toolManager; private LTIService ltiService; @@ -816,4 +821,41 @@ private void removeNonAssociatedExternalGradebookEntry(String context, String as } } } + + public boolean hasRubricSelfReview(String assignmentId) { + try { + Optional rubricAssociation = rubricsService.getRubricAssociation(RubricsConstants.RBCS_TOOL_ASSIGNMENT_GRADES, assignmentId); + if (rubricAssociation.isPresent()) { + return Integer.valueOf(1).equals(rubricAssociation.get().getParameters().get(RubricsConstants.RBCS_STUDENT_SELF_REPORT)); + } + } catch (Exception e) { + log.warn("Error trying to retrieve rubrics association for assignment : {}", e.getMessage()); + } + return false; + } + + public int getRubricSelfReviewMode(String assignmentId) { + try { + Optional rubricAssociation = rubricsService.getRubricAssociation(RubricsConstants.RBCS_TOOL_ASSIGNMENT_GRADES, assignmentId); + if (rubricAssociation.isPresent()) { + return rubricAssociation.get().getParameters().get(RubricsConstants.RBCS_STUDENT_SELF_REPORT_MODE); + } + } catch (Exception e) { + log.warn("Error trying to retrieve rubrics association for assignment : {}", e.getMessage()); + } + return -1; + } + + public boolean hasRubricHiddenToStudent(String assignmentId) { + try { + Optional rubricAssociation = rubricsService.getRubricAssociation(RubricsConstants.RBCS_TOOL_ASSIGNMENT_GRADES, assignmentId); + if (rubricAssociation.isPresent()) { + return Integer.valueOf(1).equals(rubricAssociation.get().getParameters().get("hideStudentPreview")); + } + } catch (Exception e) { + log.warn("Error trying to retrieve rubrics association for assignment : {}", e.getMessage()); + } + return false; + } + } diff --git a/assignment/tool/src/webapp/WEB-INF/applicationContext.xml b/assignment/tool/src/webapp/WEB-INF/applicationContext.xml index cbf51cd3b94b..037c5d866851 100644 --- a/assignment/tool/src/webapp/WEB-INF/applicationContext.xml +++ b/assignment/tool/src/webapp/WEB-INF/applicationContext.xml @@ -7,6 +7,7 @@ class="org.sakaiproject.assignment.tool.AssignmentToolUtils"> + diff --git a/assignment/tool/src/webapp/js/assignments.js b/assignment/tool/src/webapp/js/assignments.js index 21409833a19e..57e653decafb 100755 --- a/assignment/tool/src/webapp/js/assignments.js +++ b/assignment/tool/src/webapp/js/assignments.js @@ -698,11 +698,11 @@ ASN.enableSubmitUnlessNoFile = function(checkForFile) if (doEnable) { - btnPost.removeAttribute('disabled'); + btnPost.disabled = false; } else { - btnPost.setAttribute('disabled', 'disabled'); + btnPost.disabled = true; } }; @@ -983,6 +983,76 @@ ASN.disableTimesheetSetupSection = function() } $(document).ready(() => { + //peer-review and self-report + $('body').on('rubric-association-loaded', e => { + const dontAssociateCheck = document.getElementById("dont-associate-radio"); + const doAssociateCheck = document.getElementById("do-associate-radio"); + const studentSelfReport = document.getElementById('rbcs-config-studentSelfReport'); + const usePeerAssessment = document.getElementById("usePeerAssessment"); + + if(doAssociateCheck.checked) { + //page-loading + if (studentSelfReport.checked) { + // We do a click to hide "peerAssessmentOptions" container + if (usePeerAssessment.checked) { + usePeerAssessment.click(); + } + usePeerAssessment.disabled = true; + } else { + usePeerAssessment.disabled = false; + } + + if (usePeerAssessment.checked) { + studentSelfReport.disabled = true; + studentSelfReport.checked = false; + } else { + studentSelfReport.disabled = false; + } + } + + doAssociateCheck.addEventListener("change", function() { + studentSelfReport.disabled = false; + studentSelfReport.checked = false; + }); + + dontAssociateCheck.addEventListener("change", function() { + usePeerAssessment.disabled = false; + studentSelfReport.checked = false; + }); + + //event manage + studentSelfReport.addEventListener("change", function() { + if (studentSelfReport.checked) { + // We do a click to hide "peerAssessmentOptions" container + if (usePeerAssessment.checked) { + usePeerAssessment.click(); + } + usePeerAssessment.disabled = true; + } else { + usePeerAssessment.disabled = false; + } + }); + usePeerAssessment.addEventListener("change", function() { + if (usePeerAssessment.checked) { + studentSelfReport.disabled = true; + studentSelfReport.checked = false; + } else if (doAssociateCheck.checked) { + studentSelfReport.disabled = false; + } + }); + }); + + $("#peer-accordion").accordion({ + heightStyle: 'content', + active: 0, + collapsible: true, + change: function (event, ui) { + ASN.resizeFrame(); + }, + activate: function (event, ui) { + ASN.resizeFrame(); + } + }); const infoLink = document.getElementById("infoImg"); infoLink && (new bootstrap.Popover(document.getElementById("infoImg"))); @@ -1008,6 +1078,10 @@ $(document).ready(() => { [...document.getElementsByTagName("sakai-rubric-student-button")].forEach(b => promises.push(b.releaseEvaluation())); Promise.all(promises).then(() => ASN.submitForm('viewForm', 'releaseGrades', null, null)); }); + const confirmButton = document.getElementById("confirm"); + confirmButton && confirmButton.addEventListener("click", saveRubric); + const postButton = document.getElementById("post"); + postButton && postButton.addEventListener("click", saveRubric); // If grade is released, rubric must be released too const gradeIsReleasedInput = document.getElementById("grade-is-released"); diff --git a/assignment/tool/src/webapp/js/instructorNewEdit.js b/assignment/tool/src/webapp/js/instructorNewEdit.js index cc0d26ad6ca1..34c0a1570e44 100644 --- a/assignment/tool/src/webapp/js/instructorNewEdit.js +++ b/assignment/tool/src/webapp/js/instructorNewEdit.js @@ -80,7 +80,6 @@ ASN_INE.togglePeerAssessment = function(element) $("#site").parent().prop("class", ""); $("#site").parent().prop("style", ""); - ASN_INE.setGroupAssignmentRadioEnabled(!element.checked); if (element.checked) { section.style.display="block"; @@ -88,31 +87,6 @@ ASN_INE.togglePeerAssessment = function(element) } }; -ASN_INE.setGroupAssignmentRadioEnabled = function(enabled) -{ - var groupAssignRadio = document.getElementById("groupAssignment"); - if (groupAssignRadio !== null) - { - var label = document.getElementById("groupAssignmentCheckboxLabel"); - var peerInUseMsg = document.getElementById("msgNoGroupAssignmentPeerInUse"); - if (enabled) - { - if (ASN_INE.canEnableGroupAsnOption()) - { - groupAssignRadio.disabled = false; - label.classList.remove("disabled"); - } - peerInUseMsg.style.display = "none"; - } - else - { - groupAssignRadio.disabled = true; - label.classList.add("disabled"); - peerInUseMsg.style.display = "inline"; - } - } -}; - ASN_INE.isGradeTypePoints = function() { var select = document.getElementsByClassName("gradeScaleSelect")[0]; @@ -138,11 +112,7 @@ ASN_INE.handleGradeScaleChange = function(select, textfieldId) var isPoints = ASN_INE.isGradeTypePoints(); pointsPanel.style.display = isPoints ? "block" : "none"; - if (!isPoints) // we're switching away from points which means peer assessment is not valid, so re-enable the group option - { - ASN_INE.setGroupAssignmentRadioEnabled(true); - } - else // we're switching to points, peer assessment may already be enabled + if (isPoints) // we're switching to points { if (pointsField !== null && !/\d/.test(pointsField.value)) { @@ -152,24 +122,9 @@ ASN_INE.handleGradeScaleChange = function(select, textfieldId) { pointsField.focus(); } - ASN_INE.evaluateAssignToOptionsForPeerAssessment(); } }; -// evaluate the state of the assign to options based on the current -// state of peer assessment -ASN_INE.evaluateAssignToOptionsForPeerAssessment = function() -{ - var peerCheck = document.getElementById("usePeerAssessment"); - var gradeAsn = document.getElementById("gradeAssignment"); - if (peerCheck === null || gradeAsn === null) - { - return; - } - - ASN_INE.setGroupAssignmentRadioEnabled(!gradeAsn.checked || !peerCheck.checked); -}; - ASN_INE.handleSendToGradebookClick = function(checkbox, addToGbRadioId, assocWithGbRadioId) { if (checkbox.checked) @@ -185,56 +140,6 @@ ASN_INE.handleSendToGradebookClick = function(checkbox, addToGbRadioId, assocWit panel.style.display = checkbox.checked ? "block" : "none"; }; -// evaluate the state of the peer assessment option based on the current group -// assignment setting. -ASN_INE.evaluatePeerAssessmentOption = function() -{ - var groupAsn = document.getElementById("groupAssignment"); - var isGroup = groupAsn !== null && groupAsn.checked; - var peerCheck = document.getElementById("usePeerAssessment"); - if (peerCheck === null) - { - return; - } - - if (isGroup && peerCheck.checked) - { - peerCheck.click(); - } - ASN_INE.disablePeerAssessment(isGroup); -}; - -ASN_INE.disablePeerAssessment = function(disable) -{ - var peerCheck = document.getElementById("usePeerAssessment"); - if (peerCheck === null) - { - return; - } - - peerCheck.disabled = disable; - var label = document.getElementById("peerAssessmentCheckboxLabel"); - if (disable) - { - label.classList.add("disabled"); - document.getElementById("peerGroupAsnWarn").style.display = "block"; - } - else - { - label.classList.remove("disabled"); - document.getElementById("peerGroupAsnWarn").style.display = "none"; - } -}; - -ASN_INE.handleAssignToChangeForPeerAssessment = function() -{ - var peerCheck = document.getElementById("usePeerAssessment"); - if (peerCheck !== null) - { - ASN_INE.evaluatePeerAssessmentOption(); - } -}; - ASN_INE.enableNoMembersInCommon = function(selectedGroupCount) { ASN_INE.noMembersInCommonMsg(selectedGroupCount > 1); diff --git a/assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_submission.vm b/assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_submission.vm index 45a5b68f0f40..15c0a60fd3ba 100644 --- a/assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_submission.vm +++ b/assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_grading_submission.vm @@ -370,17 +370,79 @@ #if ($!hasAssociatedRubric)
+ ## Show reviewer feedback from peer review (if exist and the peer review is closed) + #if ($peerReviews) +

$tlang.getString("gen.peerReviews")

+
+ #foreach($review in $peerReviews) +
$review.assessorDisplayName
+
+ $tlang.getFormattedMessage("gen.score.display", $review.getScoreDisplay()) +
+ #if($!review.getComment() && $review.getComment().length()>0) + $tlang.getString("gen.comments") +
$formattedText.escapeHtmlFormattedText($review.getComment())
+ #end + +
+ #end +
+ #end + + #if($!rubricSelfReport) +

$tlang.getString("autoevaluation")

+ +

+ $tlang.getString("studentrubric") +

+
+ #end + +

$tlang.getString("instructor_grading")

+
diff --git a/assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm b/assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm index 8d2ecd9bf49d..e56f7198ffcf 100644 --- a/assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm +++ b/assignment/tool/src/webapp/vm/assignment/chef_assignments_instructor_list_submissions.vm @@ -547,13 +547,30 @@ function printView(url) { #else #end - #if($reviewersMap.containsKey($item.getId().getAssessorUserId())) - $formattedText.escapeHtml($!reviewersMap.get($item.getId().getAssessorUserId()).sortName) + #if($assignment.isGroup) + #if($groupsReviewersMap.containsKey($item.getId().getAssessorUserId())) + $formattedText.escapeHtml($!groupsReviewersMap.get($item.getId().getAssessorUserId()).title) + #else + $formattedText.escapeHtml($!item.getId().getAssessorUserId()) + #end #else - $formattedText.escapeHtml($!item.getId().getAssessorUserId()) + #if($reviewersMap.containsKey($item.getId().getAssessorUserId())) + $formattedText.escapeHtml($!reviewersMap.get($item.getId().getAssessorUserId()).sortName) + #else + $formattedText.escapeHtml($!item.getId().getAssessorUserId()) + #end #end + #if ($rubricId) + + + #end #if($!item.getScoreDisplay().length() > 0 || ($!item.getComment() && $!item.getComment().trim().length() > 0)) #if($item.isDraft()) @@ -595,6 +612,7 @@ function printView(url) { dont-check-association tool-id="sakai.assignment.grades" evaluated-item-id="$submission.Id" + evaluated-item-owner-id="$!submitterId" entity-id="$assignment.Id" instructor="true"> diff --git a/assignment/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm b/assignment/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm index 530266f15b57..398e48b552c1 100644 --- a/assignment/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm +++ b/assignment/tool/src/webapp/vm/assignment/chef_assignments_list_assignments.vm @@ -458,6 +458,11 @@ site-id="$assignment.getContext()" tool-id="sakai.assignment.grades" evaluated-item-id="$submissionId" + #if($!assignment.IsGroup) + evaluated-item-owner-id="$submission.GroupId" + #else + evaluated-item-owner-id="$user.getId()" + #end entity-id="$assignment.Id"> #end @@ -664,7 +669,11 @@ $formattedText.escapeHtml($assignment.Title) - $tlang.getString("peerAssessmentName") + #if ($assignment.IsGroup) + $tlang.getFormattedMessage("peerAssessmentName", $tlang.getString("peerAssessmentGroups")) + #else + $tlang.getFormattedMessage("peerAssessmentName", $tlang.getString("peerAssessmentStudents")) + #end #if ($!allowGradeSubmission) @@ -760,10 +769,18 @@ #if($review.getSubmitted()) - $tlang.getFormattedMessage("peerassessment.student", $reviewCount)  + #if ($assignment.IsGroup) + $tlang.getFormattedMessage("peerassessment.group", $reviewCount) $tlang.getString( + #else + $tlang.getFormattedMessage("peerassessment.student", $reviewCount) $tlang.getString( + #end #else - $tlang.getFormattedMessage("peerassessment.student", $reviewCount) + #if ($assignment.IsGroup) + $tlang.getFormattedMessage("peerassessment.group", $reviewCount) + #else + $tlang.getFormattedMessage("peerassessment.student", $reviewCount) + #end #end diff --git a/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_confirm_submission.vm b/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_confirm_submission.vm index 55418c450999..dbdf2ba3ca2e 100644 --- a/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_confirm_submission.vm +++ b/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_confirm_submission.vm @@ -1,5 +1,5 @@ -###header_append("") +#rubricsRequirements
- #navBarOnClick( $allowAddAssignment $withGrade $allowGradeSubmission $allowAddAssignment $allowRecoverAssignment $allowAllGroups $assignmentscheck $allowUpdateSite $enableViewOption $view "gradeForm" "" ) + #if ($allowAddAssignment || ($withGrade && $!allowGradeSubmission)) + ## for user who cannot create assignment nor grade submission, no need to show "Assignment List" link at all since there is really no other toolbar choices + #navBarOnClick( $allowAddAssignment $withGrade $allowGradeSubmission $allowAddAssignment $allowRecoverAssignment $allowAllGroups $assignmentscheck $allowUpdateSite $enableViewOption $view "gradeForm" "" ) + #end ## confirmation #if ($!gradingDone)
@@ -44,7 +56,9 @@ #assignmentIcons($assignment) - $tlang.getString("gen.reviewing"):  - #if(!$view_only && $assignment.getPeerAssessmentAnonEval()) + #if(!$view_only && $assignment.getPeerAssessmentAnonEval() && $assignment.IsGroup) + $tlang.getString("group") + #elseif (!$view_only && $assignment.getPeerAssessmentAnonEval()) $tlang.getString("gen.student") #elseif ($value_CheckAnonymousGrading) $formattedText.escapeHtml($!submission.Id) $tlang.getString("grading.anonymous.title") @@ -53,7 +67,11 @@ #end #if($view_only)
- $tlang.getFormattedMessage("gen.reviewer.who", $formattedText.escapeHtml($reviewer.getDisplayName()), $formattedText.escapeHtml($reviewer.getDisplayId())) + #if ($assignment.IsGroup) + $tlang.getFormattedMessage("gen.reviewer.who", $formattedText.escapeHtml($reviewer.getTitle()), $formattedText.escapeHtml($reviewer.getId())) + #else + $tlang.getFormattedMessage("gen.reviewer.who", $formattedText.escapeHtml($reviewer.getDisplayName()), $formattedText.escapeHtml($reviewer.getDisplayId())) + #end #else ($reviewNumber $tlang.getString("gen.of") $totalReviews)
@@ -159,6 +177,45 @@ #end #if ($withGrade) + + #if ($!hasAssociatedRubric) + #if ($!view_only) + + #else + + #end + #end +
#set ($gradeType = $assignment.TypeOfGrade.ordinal())

@@ -448,7 +505,7 @@ #end #else - + #end #if ($!prevSubmissionId) diff --git a/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_grade.vm b/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_grade.vm index a45132107cf0..b2f137e47014 100644 --- a/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_grade.vm +++ b/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_grade.vm @@ -1,22 +1,5 @@ #rubricsRequirements - - ## Include other javascript specific to this page #javascript("/sakai-assignment-tool/js/studentViewSubmission.js") @@ -317,12 +300,38 @@ #end #end - #if ($submission.Graded && ($submission.GradeReleased || $returned)) + #if($!rubricSelfReport) +

$tlang.getString("autoevaluation")

+ +

+ $tlang.getString("reviewrubricreport") +

+
+ #end + #if (!$rubricHiddenToStudent && $submission.Graded && ($submission.GradeReleased || $returned)) +

$tlang.getString("instructor_grading")

#end @@ -350,7 +359,7 @@ ## Show reviewer feedback from peer review (if exist and the peer review is closed) #if ($peerReviews)

$tlang.getString("gen.peerReviews")

-
+
#foreach($review in $peerReviews)
$review.assessorDisplayName
@@ -388,6 +397,17 @@ #end #end +
#end
diff --git a/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission.vm b/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission.vm index d712f76fe3f8..2928559dadf3 100644 --- a/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission.vm +++ b/assignment/tool/src/webapp/vm/assignment/chef_assignments_student_view_submission.vm @@ -20,7 +20,52 @@ $(document).ready(function(){ $('.cloned a').show(); ASN.resizeFrame('grow'); }); - + $('body').on('rubrics-grading-loaded', e => { + const studentSelfReportMode = $studentSelfReportMode; + switch (studentSelfReportMode) { + // The student has to select a criteria on every criterion + case 0: + default: + if($('.sakai-rubric-criteria-grading').length) { + $('body').on('rubric-ratings-changed', e => { + const criterionRatingsLength = $('.criterion-ratings').length; + const ratingsSelected = $('.rating-item.selected').length; + if (ratingsSelected === criterionRatingsLength) { + disableSubmitButtons(false); + } else { + disableSubmitButtons(true); + } + }); + } + break; + + // The student has to select at least one criteria in one criterion + case 1: + if($('.sakai-rubric-criteria-grading').length) { + $('body').on('rubric-ratings-changed', e => { + const ratingsSelected = $('.rating-item.selected').length; + if (ratingsSelected > 0) { + disableSubmitButtons(false); + } else { + disableSubmitButtons(true); + } + }); + } + break; + + // The student is not required to select any criteria + case 2: + disableSubmitButtons(false); + break; + } + }); + + function disableSubmitButtons(disabled) { + document.getElementById('confirm').disabled = disabled; + document.getElementById('preview').disabled = disabled; + document.getElementById('save').disabled = disabled; + } + }); ## Include other javascript specific to this page @@ -368,10 +413,13 @@ $(document).ready(function(){ #supplementItems($!allowViewModelAnswer $!allowReadAssignmentNoteItem $!allowViewAllPurposeItem $!assignmentModelAnswerItem $!assignmentNoteItem $!assignmentAllPurposeItem) + #if (!$!rubricSelfReport) + entity-id="$assignment.Id"> + + #end #if ($submission.Graded && ($submission.GradeReleased || $returned)) #end @@ -454,6 +503,32 @@ $(document).ready(function(){ + + #if ($!rubricSelfReport) +

+ #if ($studentSelfReportMode == 0) + $tlang.getString("youhavetorubric") + #elseif ($studentSelfReportMode == 1) + $tlang.getString("youhavetorubricone") + #elseif ($studentSelfReportMode == 2) + $tlang.getString("youmustrubric") + #end +

+ + #end #if ($!canSubmit) ## if a draft submission or the submission has been returned and has not yet submitted diff --git a/assignment/tool/src/webapp/vm/assignment/instructor_new_edit/assignto_section.vm b/assignment/tool/src/webapp/vm/assignment/instructor_new_edit/assignto_section.vm index 33fb475f32db..f6648e834c0c 100644 --- a/assignment/tool/src/webapp/vm/assignment/instructor_new_edit/assignto_section.vm +++ b/assignment/tool/src/webapp/vm/assignment/instructor_new_edit/assignto_section.vm @@ -24,10 +24,6 @@ can be either all members of the site, all members of selected groups, or the se #end #end #end -#set($peerAssessment = false) -#if($!value_UsePeerAssessment.equals("true")) - #set($peerAssessment = true) -#end

$tlang.getString("gen.cant.change.after.draft")

@@ -41,7 +37,7 @@ can be either all members of the site, all members of selected groups, or the se #set($showGB = "if (document.getElementById('addToGradebook') !=null){$('#addToGradebook').fadeOut('slow'); ASN.resizeFrame()};") #end $tlang.getString("displayto.site") @@ -57,7 +53,7 @@ can be either all members of the site, all members of selected groups, or the se #set($hideGB = "if (document.getElementById('addToGradebook') != null){document.getElementById('addToGradebook').style.display = 'none';document.getElementById('$!name_Addtogradebook').checked=false};") #end @@ -67,16 +63,15 @@ can be either all members of the site, all members of selected groups, or the se ## Radio Option 3: Group assignment (selected groups) #if($group_submissions_enabled) - #set($disableGroupAssignment = !$!groupsList || $peerAssessment || ($!assignment && !$assignment.draft && $value_AssignTo != $value_AssignTo_Groups)) + #set($disableGroupAssignment = !$!groupsList || ($!assignment && !$assignment.draft && $value_AssignTo != $value_AssignTo_Groups))
#end diff --git a/assignment/tool/src/webapp/vm/assignment/instructor_new_edit/grading_section.vm b/assignment/tool/src/webapp/vm/assignment/instructor_new_edit/grading_section.vm index 1c3f2d27818b..bc0270ec1d76 100644 --- a/assignment/tool/src/webapp/vm/assignment/instructor_new_edit/grading_section.vm +++ b/assignment/tool/src/webapp/vm/assignment/instructor_new_edit/grading_section.vm @@ -68,6 +68,11 @@ This section contains the options for grading this assignment, including rubrics #end fine-tune-points="$tlang.getString("option.pointsoverride")" hide-student-preview="$tlang.getString("option.studentpreview")" + student-self-report="$tlang.getString("option.selfreport")" + student-self-report-mode-0="$tlang.getString("option.selfreport.must")" + student-self-report-mode-1="$tlang.getString("option.selfreport.partialmust")" + student-self-report-mode-2="$tlang.getString("option.selfreport.notamust")" + show-self-report-check="true" >
@@ -130,22 +135,14 @@ This section contains the options for grading this assignment, including rubrics
#if ($allowPeerAssessment) - #set($groupAssignment = false) - #if ($value_AssignTo == $value_AssignTo_Groups && $!groupsList && !$selectedGroupsNotFound) - #set($groupAssignment = true) - #end `} @@ -215,12 +229,56 @@ class SakaiRubricAssociation extends RubricsElement { ${this.hideStudentPreview}
+ ${this.showSelfReportCheck ? html` +
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+ ` : "" + }
`} `; } + + updateStudentSelfReportInput(e) { + if (this.isAssociated) { + const showSelfReportMode = e.srcElement.checked; + document.getElementById('rbcs-multiple-options-config-studentSelfReportMode-container').classList.toggle('hidden', !showSelfReportMode); + } + } + + firstUpdated() { + setTimeout(() => { // in order to ensure proper loading order with the tool + this.dispatchEvent(new CustomEvent('rubric-association-loaded', { + bubbles: true, + composed: true + })); + }, 100); + } + } customElements.define("sakai-rubric-association", SakaiRubricAssociation); diff --git a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-grading.js b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-grading.js index f6e6403950e2..3dc351799d81 100644 --- a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-grading.js +++ b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-grading.js @@ -31,6 +31,8 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) { entityId: { attribute: "entity-id", type: String }, evaluatedItemId: { attribute: "evaluated-item-id", type: String }, evaluatedItemOwnerId: { attribute: "evaluated-item-owner-id", type: String }, + isPeerOrSelf: { attribute: "is-peer-or-self", type: Boolean }, + isPeerGroupGraded: { attribute: "is-peer-group-graded", type: Boolean }, group: { type: Boolean}, enablePdfExport: { attribute: "enable-pdf-export", type: Boolean }, @@ -114,7 +116,7 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) {
- ${this.evaluation && this.evaluation.status === "DRAFT" ? html` + ${this.evaluation && this.evaluation.status === "DRAFT" && !this.isPeerOrSelf ? html`
${tr('draft_evaluation', [tr(`draft_evaluation_${this.toolId}`)])}
@@ -315,7 +317,6 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) { this.totalPoints = this.totalPoints + criterion.pointoverride; } - this.dispatchEvent(new CustomEvent("rubric-ratings-changed", { bubbles: true, composed: true })); const detail = { evaluatedItemId: this.evaluatedItemId, entityId: this.entityId, @@ -344,7 +345,7 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) { }); const evaluation = { - evaluatorId: getUserId(), + evaluatorId: this.isPeerGroupGraded ? this.evaluatedItemId : getUserId(), id: this.evaluation.id, evaluatedItemId: this.evaluatedItemId, evaluatedItemOwnerId: this.evaluatedItemOwnerId, @@ -352,6 +353,7 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) { overallComment: "", criterionOutcomes: crit, associationId: this.association.id, + peerOrSelf: this.isPeerOrSelf, status, }; @@ -377,6 +379,7 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) { }) .then(data => { + this.dispatchEvent(new CustomEvent("rubric-ratings-changed", { bubbles: true, composed: true })); this.evaluation = data; return Promise.resolve(this.evaluation); }) @@ -439,7 +442,6 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) { // remove the strike out from the clicked points value this.querySelector(`#points-display-${criterionId}`).classList.remove("strike"); - this.dispatchEvent(new CustomEvent("rubric-ratings-changed", { bubbles: true, composed: true })); this.requestUpdate(); this.updateTotalPoints(); @@ -548,8 +550,6 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) { this.criteria = this.rubric.criteria; this.criteria.forEach(c => { - c.pointoverride = ""; - if (!c.selectedvalue) { c.selectedvalue = 0; } @@ -557,6 +557,11 @@ export class SakaiRubricGrading extends rubricsApiMixin(RubricsElement) { }); this.decorateCriteria(); + + if (this.isPeerOrSelf) { // For self-review buttons locking + this.dispatchEvent(new CustomEvent('rubrics-grading-loaded', {bubbles: true, composed: true})); + this.updateComplete.then(() => this.dispatchEvent(new CustomEvent('rubric-ratings-changed', {bubbles: true, composed: true}))); + } }) .catch(error => console.error(error)); } else { diff --git a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student-button.js b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student-button.js index 82a4397bf92a..b649e011dd03 100644 --- a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student-button.js +++ b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student-button.js @@ -33,6 +33,7 @@ class SakaiRubricStudentButton extends rubricsApiMixin(RubricsElement) { toolId: { attribute: "tool-id", type: String }, evaluatedItemId: { attribute: "evaluated-item-id", type: String }, hidden: { attribute: false, type: Boolean }, + evaluatedItemOwnerId: { attribute: "evaluated-item-owner-id", type: String }, instructor: Boolean, forcePreview: { attribute: "force-preview", type: Boolean }, dontCheckAssociation: { attribute: "dont-check-association", type: Boolean }, @@ -59,7 +60,7 @@ class SakaiRubricStudentButton extends rubricsApiMixin(RubricsElement) { if (this.forcePreview) { this.showRubricLightbox(this.rubricId); } else { - this.showRubricLightbox(this.rubricId, { "tool-id": this.toolId, "entity-id": this.entityId, "evaluated-item-id": this.evaluatedItemId }); + this.showRubricLightbox(this.rubricId, { "tool-id": this.toolId, "entity-id": this.entityId, "evaluated-item-id": this.evaluatedItemId, "evaluated-item-owner-id": this.evaluatedItemOwnerId }); } } diff --git a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student-comment.js b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student-comment.js index bf9ad0b37d30..ae17d3ef359b 100644 --- a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student-comment.js +++ b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student-comment.js @@ -23,7 +23,8 @@ export class SakaiRubricStudentComment extends RubricsElement { const oldValue = this._criterion; this._criterion = value; this._criterion.comments = value.comments && value.comments.indexOf("null") === 0 ? "" : value.comments; - this.triggerId = `criterion-comment-${value.id}-trigger`; + + this.triggerId = `criterion-comment-${value.id}-trigger${Math.floor(Math.random() * 90 + 10)}`; this.requestUpdate("criterion", oldValue); this.updateComplete.then(() => { diff --git a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student.js b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student.js index 3d5efa672332..5b53df5e0b2f 100644 --- a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student.js +++ b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubric-student.js @@ -29,10 +29,12 @@ class SakaiRubricStudent extends RubricsElement { preview: Boolean, instructor: Boolean, evaluatedItemId: { attribute: "evaluated-item-id", type: String }, + evaluatedItemOwnerId: { attribute: "evaluated-item-owner-id", type: String }, rubric: { type: Object }, rubricId: { attribute: "rubric-id", type: String }, forcePreview: { attribute: "force-preview", type: Boolean }, enablePdfExport: { attribute: "enable-pdf-export", type: Object }, + isPeerOrSelf: { attribute: "is-peer-or-self", type: Boolean } }; } @@ -209,7 +211,12 @@ class SakaiRubricStudent extends RubricsElement { .then(rubric => { if (this.evaluatedItemId) { - const evalUrl = `/api/sites/${association.siteId}/rubric-evaluations/tools/${this.toolId}/items/${this.entityId}/evaluations/${this.evaluatedItemId}`; + // Now, get the evaluation + let evalUrl = `/api/sites/${association.siteId}/rubric-evaluations/tools/${this.toolId}/items/${this.entityId}/evaluations/${this.evaluatedItemId}/owners/${this.evaluatedItemOwnerId}`; + if (this.isPeerOrSelf) { + //for permission filters + evalUrl += "?isPeer=true"; + } fetch(evalUrl, { credentials: "include", headers: { "Content-Type": "application/json" }, diff --git a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubrics-api-mixin.js b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubrics-api-mixin.js index 2ee41fb7c77d..e211e10b23ad 100644 --- a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubrics-api-mixin.js +++ b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubrics-api-mixin.js @@ -30,7 +30,12 @@ export const rubricsApiMixin = Base => class extends Base { apiGetEvaluation() { - const url = `/api/sites/${this.siteId}/rubric-evaluations/tools/${this.toolId}/items/${this.entityId}/evaluations/${this.evaluatedItemId}`; + let url = `/api/sites/${this.siteId}/rubric-evaluations/tools/${this.toolId}/items/${this.entityId}/evaluations/${this.evaluatedItemId}/owners/${this.evaluatedItemOwnerId}`; + + if (this.isPeerOrSelf) { + url += "?isPeer=true"; + } + return fetch(url, { credentials: "include" }) .then(r => { diff --git a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubrics-utils.js b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubrics-utils.js index c4a163a6f996..a7b50f0f8a34 100644 --- a/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubrics-utils.js +++ b/webcomponents/tool/src/main/frontend/js/rubrics/sakai-rubrics-utils.js @@ -58,6 +58,8 @@ window.top.rubrics.utils = window.top.rubrics.utils || { el.removeAttribute("entity-id"); el.removeAttribute("evaluated-item-id"); el.removeAttribute("instructor"); + el.removeAttribute("evaluated-item-owner-id"); + el.removeAttribute("peer-or-self"); rubrics.utils.lightbox.style.display = "none"; rubrics.utils.windowRef.document.body.style.overflow = "auto"; @@ -83,6 +85,8 @@ window.top.rubrics.utils = window.top.rubrics.utils || { el.removeAttribute("entity-id"); el.removeAttribute("evaluated-item-id"); el.removeAttribute("instructor"); + el.removeAttribute("evaluated-item-owner-id"); + el.removeAttribute("peer-or-self"); } else { el.removeAttribute("rubric-id"); if (attributes["force-preview"]) { @@ -94,6 +98,8 @@ window.top.rubrics.utils = window.top.rubrics.utils || { el.setAttribute("entity-id", attributes["entity-id"]); el.setAttribute("evaluated-item-id", attributes["evaluated-item-id"]); el.setAttribute("instructor", attributes.instructor); + el.setAttribute("evaluated-item-owner-id", attributes["evaluated-item-owner-id"]); + el.setAttribute("peer-or-self", attributes["peer-or-self"]); } rubrics.utils.lightbox.style.display = "block"; rubrics.utils.lightbox.focus();