Skip to content

Commit

Permalink
Some callouts added so that the teacher will not miss there are plagi…
Browse files Browse the repository at this point in the history
…arisms detected in solution lists.
  • Loading branch information
krulis-martin committed Apr 23, 2023
1 parent 0ec89d6 commit 2889228
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 6 deletions.
2 changes: 2 additions & 0 deletions src/locales/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
"app.assignmentStats.noSolutions": "Momentálně zde nejsou žádná odevzdaná řešení.",
"app.assignmentStats.onlyBestSolutionsCheckbox": "Pouze nejlepší řešení",
"app.assignmentStats.pendingReviews": "V tuto chvíli {count, plural, one {je otevřena} =2 {jsou otevřeny} =3 {jsou otevřeny} =4 {jsou otevřeny} other {je otevřeno}} {count} {count, plural, one {revize} =2 {revize} =3 {revize} =4 {revize} other {revizí}} ze všech řešení vybrané úlohy. Nezapomeňte, že autoři úloh vidí vaše komentáře zdrojových kódů až poté, co jsou příslušné revize uzavřeny.",
"app.assignmentStats.plagiarismsDetected": "V seznamu {count, plural, one {je zobrazeno} =2 {jsou zobrazena} =3 {jsou zobrazena} =4 {jsou zobrazena} other {je zobrazeno}} {count} řešení, {count, plural, one {ke kterému} other {ke kterým}} byla nelezena podobná řešení. V takových případech se může jednat o plagiáty.",
"app.assignmentStats.title": "Všechna řešení zadané úlohy",
"app.assignments.deadline": "Termín odevzdání",
"app.assignments.deleteAllButton": "Smazat",
Expand Down Expand Up @@ -1664,6 +1665,7 @@
"app.solution.submittedAt": "Odevzdáno",
"app.solution.submittedBeforeFirstDeadline": "Řešení bylo odevzdáno včas před termínem",
"app.solution.submittedBeforeSecondDeadline": "Řešení bylo odevzdáno po prvním termínu, ale stále ještě před druhým termínem",
"app.solution.suspectedPlagiarismWarning": "Byla detekována podobná řešení, toto řešení by mohlo být plagiátem. Detialy naleznete na stránce 'Podobnosti'.",
"app.solution.title": "Řešení",
"app.solutionArchiveInfoBox.description": "Všechny soubory v ZIPu",
"app.solutionDetail.comments.additionalSwitchNote": "(autor tohoto řešení a vedoucí této skupiny)",
Expand Down
2 changes: 2 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@
"app.assignmentStats.noSolutions": "There are currently no submitted solutions.",
"app.assignmentStats.onlyBestSolutionsCheckbox": "Best solutions only",
"app.assignmentStats.pendingReviews": "There {count, plural, one {is} other {are}} {count} pending {count, plural, one {review} other {reviews}} among the solutions of the selected assignment. Remember that the review comments are visible to the author after a review is closed.",
"app.assignmentStats.plagiarismsDetected": "There {count, plural, one {is} other {are}} {count} {count, plural, one {solution} other {solutions}} with detected similarities. Such solutions may be plagiarisms.",
"app.assignmentStats.title": "All Submissions of The Assignment",
"app.assignments.deadline": "Deadline",
"app.assignments.deleteAllButton": "Delete",
Expand Down Expand Up @@ -1664,6 +1665,7 @@
"app.solution.submittedAt": "Submitted at",
"app.solution.submittedBeforeFirstDeadline": "The solution was submitted before the deadline",
"app.solution.submittedBeforeSecondDeadline": "The solution was submitted after the first but still before the second deadline",
"app.solution.suspectedPlagiarismWarning": "Similar solutions have been detected, the solution is suspected of being a plagiarism. Details can be found on 'Similarities' page.",
"app.solution.title": "The Solution",
"app.solutionArchiveInfoBox.description": "All files in a ZIP archive",
"app.solutionDetail.comments.additionalSwitchNote": "(author of the solution and supervisors of this group)",
Expand Down
19 changes: 19 additions & 0 deletions src/pages/AssignmentStats/AssignmentStats.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Icon, {
DetailIcon,
CodeFileIcon,
LoadingIcon,
PlagiarismIcon,
ResultsIcon,
UserIcon,
} from '../../components/icons';
Expand Down Expand Up @@ -262,6 +263,13 @@ const getPendingReviewSolutions = defaultMemoize(assignmentSolutions =>
.filter(solution => solution && solution.review && solution.review.startedAt && !solution.review.closedAt)
);

const getPlagiarisms = defaultMemoize(assignmentSolutions =>
assignmentSolutions
.toArray()
.map(getJsData)
.filter(solution => solution && solution.plagiarism)
);

const localStorageStateKey = 'AssignmentStats.state';

class AssignmentStats extends Component {
Expand Down Expand Up @@ -351,6 +359,7 @@ class AssignmentStats extends Component {
} = this.props;

const pendingReviews = getPendingReviewSolutions(assignmentSolutions);
const plagiarisms = getPlagiarisms(assignmentSolutions);

return (
<Page
Expand All @@ -368,6 +377,16 @@ class AssignmentStats extends Component {
canViewExercise={true}
/>

{plagiarisms && plagiarisms.length > 0 && (
<Callout variant="danger" icon={<PlagiarismIcon />}>
<FormattedMessage
id="app.assignmentStats.plagiarismsDetected"
defaultMessage="There {count, plural, one {is} other {are}} {count} {count, plural, one {solution} other {solutions}} with detected similarities. Such solutions may be plagiarisms."
values={{ count: plagiarisms.length }}
/>
</Callout>
)}

{pendingReviews && pendingReviews.length > 0 && (
<Callout variant="warning">
<Row className="align-items-center">
Expand Down
39 changes: 38 additions & 1 deletion src/pages/GroupUserSolutions/GroupUserSolutions.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ import ReviewSolutionContainer from '../../containers/ReviewSolutionContainer';

import Page from '../../components/layout/Page';
import { GroupNavigation } from '../../components/layout/Navigation';
import Icon, { AssignmentIcon, DetailIcon, CodeFileIcon, LoadingIcon, UserIcon } from '../../components/icons';
import Icon, {
AssignmentIcon,
DetailIcon,
CodeFileIcon,
LoadingIcon,
PlagiarismIcon,
UserIcon,
} from '../../components/icons';
import SolutionTableRowIcons from '../../components/Assignments/SolutionsTable/SolutionTableRowIcons';
import Points from '../../components/Assignments/SolutionsTable/Points';
import SolutionsTable from '../../components/Assignments/SolutionsTable';
Expand Down Expand Up @@ -302,6 +309,25 @@ const getPendingReviewSolutions = defaultMemoize((assignments, getAssignmentSolu
: []
);

const getPlagiarisms = defaultMemoize((assignments, getAssignmentSolutions) =>
assignments
? assignments
.toArray()
.map(getJsData)
.filter(identity)
.reduce(
(acc, assignment) => [
...acc,
...getAssignmentSolutions(assignment.id)
.toArray()
.map(getJsData)
.filter(solution => solution && solution.plagiarism),
],
[]
)
: []
);

const localStorageStateKey = 'GroupUserSolutions.state';

class GroupUserSolutions extends Component {
Expand Down Expand Up @@ -379,6 +405,7 @@ class GroupUserSolutions extends Component {
} = this.props;

const pendingReviews = getPendingReviewSolutions(assignments, getAssignmentSolutions);
const plagiarisms = getPlagiarisms(assignments, getAssignmentSolutions);

return (
<Page
Expand All @@ -402,6 +429,16 @@ class GroupUserSolutions extends Component {
linkFactory={links.GROUP_EDIT_URI_FACTORY}
/>

{plagiarisms && plagiarisms.length > 0 && (
<Callout variant="danger" icon={<PlagiarismIcon />}>
<FormattedMessage
id="app.assignmentStats.plagiarismsDetected"
defaultMessage="There {count, plural, one {is} other {are}} {count} {count, plural, one {solution} other {solutions}} with detected similarities. Such solutions may be plagiarisms."
values={{ count: plagiarisms.length }}
/>
</Callout>
)}

{pendingReviews && pendingReviews.length > 0 && (
<Callout variant="warning">
<Row className="align-items-center">
Expand Down
13 changes: 11 additions & 2 deletions src/pages/Solution/Solution.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import { assignmentSubmissionScoreConfigSelector } from '../../redux/selectors/e

import { registerSolutionVisit } from '../../components/Solutions/RecentlyVisited/functions';
import { hasPermissions } from '../../helpers/common';
import { SolutionResultsIcon, WarningIcon } from '../../components/icons';
import { PlagiarismIcon, SolutionResultsIcon, WarningIcon } from '../../components/icons';

const assignmentHasRuntime = defaultMemoize(
(assignment, runtimeId) =>
Expand Down Expand Up @@ -117,7 +117,7 @@ class Solution extends Component {
userId={solution.authorId}
groupId={assignment.groupId}
attemptIndex={solution.attemptIndex}
plagiarism={Boolean(solution.plagiarism)}
plagiarism={Boolean(solution.plagiarism) && hasPermissions(solution, 'viewDetectedPlagiarisms')}
canViewSolutions={hasPermissions(assignment, 'viewAssignmentSolutions')}
canViewExercise={
hasPermissions(
Expand All @@ -128,6 +128,15 @@ class Solution extends Component {
canViewUserProfile={hasPermissions(assignment, 'viewAssignmentSolutions')}
/>

{solution.plagiarism && hasPermissions(solution, 'viewDetectedPlagiarisms') && (
<Callout variant="warning" icon={<PlagiarismIcon />}>
<FormattedMessage
id="app.solution.suspectedPlagiarismWarning"
defaultMessage="Similar solutions have been detected, the solution is suspected of being a plagiarism. Details can be found on 'Similarities' page."
/>
</Callout>
)}

{(hasPermissions(solution, 'setFlag') ||
hasPermissions(solution, 'review') ||
hasPermissions(assignment, 'resubmitSubmissions')) && (
Expand Down
2 changes: 1 addition & 1 deletion src/pages/SolutionPlagiarisms/SolutionPlagiarisms.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ class SolutionPlagiarisms extends Component {
userId={solution.authorId}
groupId={assignment.groupId}
attemptIndex={solution.attemptIndex}
plagiarism={Boolean(solution.plagiarism)}
plagiarism={Boolean(solution.plagiarism) && hasPermissions(solution, 'viewDetectedPlagiarisms')}
canViewSolutions={hasPermissions(assignment, 'viewAssignmentSolutions')}
canViewExercise={
hasPermissions(
Expand Down
17 changes: 15 additions & 2 deletions src/pages/SolutionSourceCodes/SolutionSourceCodes.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Button, { TheButtonGroup } from '../../components/widgets/TheButton';
import {
CircleIcon,
CodeCompareIcon,
PlagiarismIcon,
RefreshIcon,
SolutionResultsIcon,
StopIcon,
Expand Down Expand Up @@ -255,7 +256,7 @@ class SolutionSourceCodes extends Component {
userId={solution.authorId}
groupId={assignment.groupId}
attemptIndex={solution.attemptIndex}
plagiarism={Boolean(solution.plagiarism)}
plagiarism={Boolean(solution.plagiarism) && hasPermissions(solution, 'viewDetectedPlagiarisms')}
canViewSolutions={hasPermissions(assignment, 'viewAssignmentSolutions')}
canViewExercise={
hasPermissions(
Expand All @@ -272,6 +273,7 @@ class SolutionSourceCodes extends Component {
) : null
}
/>

{diffMode && (
<>
<h4 className="text-muted text-center my-2">
Expand All @@ -290,7 +292,9 @@ class SolutionSourceCodes extends Component {
userId={secondSolution.authorId}
groupId={secondAssignment.groupId}
attemptIndex={secondSolution.attemptIndex}
plagiarism={Boolean(secondSolution.plagiarism)}
plagiarism={
Boolean(secondSolution.plagiarism) && hasPermissions(secondSolution, 'viewDetectedPlagiarisms')
}
canViewSolutions={hasPermissions(secondAssignment, 'viewAssignmentSolutions')}
canViewExercise={
hasPermissions(
Expand All @@ -310,6 +314,15 @@ class SolutionSourceCodes extends Component {

{isSupervisorRole(effectiveRole) && (
<>
{solution.plagiarism && hasPermissions(solution, 'viewDetectedPlagiarisms') && (
<Callout variant="warning" icon={<PlagiarismIcon />}>
<FormattedMessage
id="app.solution.suspectedPlagiarismWarning"
defaultMessage="Similar solutions have been detected, the solution is suspected of being a plagiarism. Details can be found on 'Similarities' page."
/>
</Callout>
)}

<Row className="justify-content-sm-between">
<Col sm="auto" className="mb-3">
{!diffMode && (
Expand Down

0 comments on commit 2889228

Please sign in to comment.