Skip to content

Commit 2889228

Browse files
committed
Some callouts added so that the teacher will not miss there are plagiarisms detected in solution lists.
1 parent 0ec89d6 commit 2889228

File tree

7 files changed

+88
-6
lines changed

7 files changed

+88
-6
lines changed

src/locales/cs.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
"app.assignmentStats.noSolutions": "Momentálně zde nejsou žádná odevzdaná řešení.",
162162
"app.assignmentStats.onlyBestSolutionsCheckbox": "Pouze nejlepší řešení",
163163
"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.",
164+
"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.",
164165
"app.assignmentStats.title": "Všechna řešení zadané úlohy",
165166
"app.assignments.deadline": "Termín odevzdání",
166167
"app.assignments.deleteAllButton": "Smazat",
@@ -1664,6 +1665,7 @@
16641665
"app.solution.submittedAt": "Odevzdáno",
16651666
"app.solution.submittedBeforeFirstDeadline": "Řešení bylo odevzdáno včas před termínem",
16661667
"app.solution.submittedBeforeSecondDeadline": "Řešení bylo odevzdáno po prvním termínu, ale stále ještě před druhým termínem",
1668+
"app.solution.suspectedPlagiarismWarning": "Byla detekována podobná řešení, toto řešení by mohlo být plagiátem. Detialy naleznete na stránce 'Podobnosti'.",
16671669
"app.solution.title": "Řešení",
16681670
"app.solutionArchiveInfoBox.description": "Všechny soubory v ZIPu",
16691671
"app.solutionDetail.comments.additionalSwitchNote": "(autor tohoto řešení a vedoucí této skupiny)",

src/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
"app.assignmentStats.noSolutions": "There are currently no submitted solutions.",
162162
"app.assignmentStats.onlyBestSolutionsCheckbox": "Best solutions only",
163163
"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.",
164+
"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.",
164165
"app.assignmentStats.title": "All Submissions of The Assignment",
165166
"app.assignments.deadline": "Deadline",
166167
"app.assignments.deleteAllButton": "Delete",
@@ -1664,6 +1665,7 @@
16641665
"app.solution.submittedAt": "Submitted at",
16651666
"app.solution.submittedBeforeFirstDeadline": "The solution was submitted before the deadline",
16661667
"app.solution.submittedBeforeSecondDeadline": "The solution was submitted after the first but still before the second deadline",
1668+
"app.solution.suspectedPlagiarismWarning": "Similar solutions have been detected, the solution is suspected of being a plagiarism. Details can be found on 'Similarities' page.",
16671669
"app.solution.title": "The Solution",
16681670
"app.solutionArchiveInfoBox.description": "All files in a ZIP archive",
16691671
"app.solutionDetail.comments.additionalSwitchNote": "(author of the solution and supervisors of this group)",

src/pages/AssignmentStats/AssignmentStats.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import Icon, {
2121
DetailIcon,
2222
CodeFileIcon,
2323
LoadingIcon,
24+
PlagiarismIcon,
2425
ResultsIcon,
2526
UserIcon,
2627
} from '../../components/icons';
@@ -262,6 +263,13 @@ const getPendingReviewSolutions = defaultMemoize(assignmentSolutions =>
262263
.filter(solution => solution && solution.review && solution.review.startedAt && !solution.review.closedAt)
263264
);
264265

266+
const getPlagiarisms = defaultMemoize(assignmentSolutions =>
267+
assignmentSolutions
268+
.toArray()
269+
.map(getJsData)
270+
.filter(solution => solution && solution.plagiarism)
271+
);
272+
265273
const localStorageStateKey = 'AssignmentStats.state';
266274

267275
class AssignmentStats extends Component {
@@ -351,6 +359,7 @@ class AssignmentStats extends Component {
351359
} = this.props;
352360

353361
const pendingReviews = getPendingReviewSolutions(assignmentSolutions);
362+
const plagiarisms = getPlagiarisms(assignmentSolutions);
354363

355364
return (
356365
<Page
@@ -368,6 +377,16 @@ class AssignmentStats extends Component {
368377
canViewExercise={true}
369378
/>
370379

380+
{plagiarisms && plagiarisms.length > 0 && (
381+
<Callout variant="danger" icon={<PlagiarismIcon />}>
382+
<FormattedMessage
383+
id="app.assignmentStats.plagiarismsDetected"
384+
defaultMessage="There {count, plural, one {is} other {are}} {count} {count, plural, one {solution} other {solutions}} with detected similarities. Such solutions may be plagiarisms."
385+
values={{ count: plagiarisms.length }}
386+
/>
387+
</Callout>
388+
)}
389+
371390
{pendingReviews && pendingReviews.length > 0 && (
372391
<Callout variant="warning">
373392
<Row className="align-items-center">

src/pages/GroupUserSolutions/GroupUserSolutions.js

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,14 @@ import ReviewSolutionContainer from '../../containers/ReviewSolutionContainer';
1313

1414
import Page from '../../components/layout/Page';
1515
import { GroupNavigation } from '../../components/layout/Navigation';
16-
import Icon, { AssignmentIcon, DetailIcon, CodeFileIcon, LoadingIcon, UserIcon } from '../../components/icons';
16+
import Icon, {
17+
AssignmentIcon,
18+
DetailIcon,
19+
CodeFileIcon,
20+
LoadingIcon,
21+
PlagiarismIcon,
22+
UserIcon,
23+
} from '../../components/icons';
1724
import SolutionTableRowIcons from '../../components/Assignments/SolutionsTable/SolutionTableRowIcons';
1825
import Points from '../../components/Assignments/SolutionsTable/Points';
1926
import SolutionsTable from '../../components/Assignments/SolutionsTable';
@@ -302,6 +309,25 @@ const getPendingReviewSolutions = defaultMemoize((assignments, getAssignmentSolu
302309
: []
303310
);
304311

312+
const getPlagiarisms = defaultMemoize((assignments, getAssignmentSolutions) =>
313+
assignments
314+
? assignments
315+
.toArray()
316+
.map(getJsData)
317+
.filter(identity)
318+
.reduce(
319+
(acc, assignment) => [
320+
...acc,
321+
...getAssignmentSolutions(assignment.id)
322+
.toArray()
323+
.map(getJsData)
324+
.filter(solution => solution && solution.plagiarism),
325+
],
326+
[]
327+
)
328+
: []
329+
);
330+
305331
const localStorageStateKey = 'GroupUserSolutions.state';
306332

307333
class GroupUserSolutions extends Component {
@@ -379,6 +405,7 @@ class GroupUserSolutions extends Component {
379405
} = this.props;
380406

381407
const pendingReviews = getPendingReviewSolutions(assignments, getAssignmentSolutions);
408+
const plagiarisms = getPlagiarisms(assignments, getAssignmentSolutions);
382409

383410
return (
384411
<Page
@@ -402,6 +429,16 @@ class GroupUserSolutions extends Component {
402429
linkFactory={links.GROUP_EDIT_URI_FACTORY}
403430
/>
404431

432+
{plagiarisms && plagiarisms.length > 0 && (
433+
<Callout variant="danger" icon={<PlagiarismIcon />}>
434+
<FormattedMessage
435+
id="app.assignmentStats.plagiarismsDetected"
436+
defaultMessage="There {count, plural, one {is} other {are}} {count} {count, plural, one {solution} other {solutions}} with detected similarities. Such solutions may be plagiarisms."
437+
values={{ count: plagiarisms.length }}
438+
/>
439+
</Callout>
440+
)}
441+
405442
{pendingReviews && pendingReviews.length > 0 && (
406443
<Callout variant="warning">
407444
<Row className="align-items-center">

src/pages/Solution/Solution.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import { assignmentSubmissionScoreConfigSelector } from '../../redux/selectors/e
4545

4646
import { registerSolutionVisit } from '../../components/Solutions/RecentlyVisited/functions';
4747
import { hasPermissions } from '../../helpers/common';
48-
import { SolutionResultsIcon, WarningIcon } from '../../components/icons';
48+
import { PlagiarismIcon, SolutionResultsIcon, WarningIcon } from '../../components/icons';
4949

5050
const assignmentHasRuntime = defaultMemoize(
5151
(assignment, runtimeId) =>
@@ -117,7 +117,7 @@ class Solution extends Component {
117117
userId={solution.authorId}
118118
groupId={assignment.groupId}
119119
attemptIndex={solution.attemptIndex}
120-
plagiarism={Boolean(solution.plagiarism)}
120+
plagiarism={Boolean(solution.plagiarism) && hasPermissions(solution, 'viewDetectedPlagiarisms')}
121121
canViewSolutions={hasPermissions(assignment, 'viewAssignmentSolutions')}
122122
canViewExercise={
123123
hasPermissions(
@@ -128,6 +128,15 @@ class Solution extends Component {
128128
canViewUserProfile={hasPermissions(assignment, 'viewAssignmentSolutions')}
129129
/>
130130

131+
{solution.plagiarism && hasPermissions(solution, 'viewDetectedPlagiarisms') && (
132+
<Callout variant="warning" icon={<PlagiarismIcon />}>
133+
<FormattedMessage
134+
id="app.solution.suspectedPlagiarismWarning"
135+
defaultMessage="Similar solutions have been detected, the solution is suspected of being a plagiarism. Details can be found on 'Similarities' page."
136+
/>
137+
</Callout>
138+
)}
139+
131140
{(hasPermissions(solution, 'setFlag') ||
132141
hasPermissions(solution, 'review') ||
133142
hasPermissions(assignment, 'resubmitSubmissions')) && (

src/pages/SolutionPlagiarisms/SolutionPlagiarisms.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ class SolutionPlagiarisms extends Component {
175175
userId={solution.authorId}
176176
groupId={assignment.groupId}
177177
attemptIndex={solution.attemptIndex}
178-
plagiarism={Boolean(solution.plagiarism)}
178+
plagiarism={Boolean(solution.plagiarism) && hasPermissions(solution, 'viewDetectedPlagiarisms')}
179179
canViewSolutions={hasPermissions(assignment, 'viewAssignmentSolutions')}
180180
canViewExercise={
181181
hasPermissions(

src/pages/SolutionSourceCodes/SolutionSourceCodes.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Button, { TheButtonGroup } from '../../components/widgets/TheButton';
1616
import {
1717
CircleIcon,
1818
CodeCompareIcon,
19+
PlagiarismIcon,
1920
RefreshIcon,
2021
SolutionResultsIcon,
2122
StopIcon,
@@ -255,7 +256,7 @@ class SolutionSourceCodes extends Component {
255256
userId={solution.authorId}
256257
groupId={assignment.groupId}
257258
attemptIndex={solution.attemptIndex}
258-
plagiarism={Boolean(solution.plagiarism)}
259+
plagiarism={Boolean(solution.plagiarism) && hasPermissions(solution, 'viewDetectedPlagiarisms')}
259260
canViewSolutions={hasPermissions(assignment, 'viewAssignmentSolutions')}
260261
canViewExercise={
261262
hasPermissions(
@@ -272,6 +273,7 @@ class SolutionSourceCodes extends Component {
272273
) : null
273274
}
274275
/>
276+
275277
{diffMode && (
276278
<>
277279
<h4 className="text-muted text-center my-2">
@@ -290,7 +292,9 @@ class SolutionSourceCodes extends Component {
290292
userId={secondSolution.authorId}
291293
groupId={secondAssignment.groupId}
292294
attemptIndex={secondSolution.attemptIndex}
293-
plagiarism={Boolean(secondSolution.plagiarism)}
295+
plagiarism={
296+
Boolean(secondSolution.plagiarism) && hasPermissions(secondSolution, 'viewDetectedPlagiarisms')
297+
}
294298
canViewSolutions={hasPermissions(secondAssignment, 'viewAssignmentSolutions')}
295299
canViewExercise={
296300
hasPermissions(
@@ -310,6 +314,15 @@ class SolutionSourceCodes extends Component {
310314

311315
{isSupervisorRole(effectiveRole) && (
312316
<>
317+
{solution.plagiarism && hasPermissions(solution, 'viewDetectedPlagiarisms') && (
318+
<Callout variant="warning" icon={<PlagiarismIcon />}>
319+
<FormattedMessage
320+
id="app.solution.suspectedPlagiarismWarning"
321+
defaultMessage="Similar solutions have been detected, the solution is suspected of being a plagiarism. Details can be found on 'Similarities' page."
322+
/>
323+
</Callout>
324+
)}
325+
313326
<Row className="justify-content-sm-between">
314327
<Col sm="auto" className="mb-3">
315328
{!diffMode && (

0 commit comments

Comments
 (0)