Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exam Mode: Add sidebar to student view to display exams #8662

Closed
wants to merge 81 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
1764e8e
Add Sidebar to Course exam overview
edkaya May 6, 2024
58a9ac4
Integrate sidebar into the course-exams
edkaya May 6, 2024
05166c2
Add SidebarCard Elements for exams
edkaya May 7, 2024
d513238
Add translation + fix grouping
edkaya May 7, 2024
13f8d09
Fix undefined date object
edkaya May 7, 2024
e0bbabc
Fix routing + adjust exam participation page layout
edkaya May 7, 2024
2d45811
Merge develop
edkaya May 7, 2024
bce010b
Integrate sidebar-cards of other developer
edkaya May 9, 2024
a927844
Implement large cards for exam + adjust displayed information
edkaya May 10, 2024
b8417a9
Fix icon coloring
edkaya May 10, 2024
928c05f
Remove status icons and its colors
edkaya May 10, 2024
99e8173
Add translations
edkaya May 10, 2024
32bade8
Add sidebar card tests
edkaya May 10, 2024
eac7860
Fix course exams test configuration
edkaya May 11, 2024
e56b0e8
Fix test runs
edkaya May 11, 2024
8b1d129
Separate exam participation files
edkaya May 14, 2024
da5f798
Fix routing
edkaya May 14, 2024
3d0a494
Fix undefined exercises
edkaya May 15, 2024
9dcb38a
Add exam-summary in the sidebar-content
edkaya May 15, 2024
345a252
Add edge case
edkaya May 15, 2024
e8135ba
Fix displaying summary overview
edkaya May 16, 2024
9eff570
Put exam summary in sidebar content after exam is finished
edkaya May 16, 2024
6227c49
Remove console.log
edkaya May 16, 2024
4b6ea12
Fix landing page appearing
edkaya May 16, 2024
1789778
Remove unused properties
edkaya May 16, 2024
0decc0d
Add no submission page
edkaya May 16, 2024
b340a6c
Add testrun route
edkaya May 16, 2024
e1347a6
add production and testserver style
edkaya May 16, 2024
27c2ea6
Fix handInEarly behaviour
edkaya May 17, 2024
bafc4aa
Fix endbutton
edkaya May 17, 2024
d331c1b
remove logs
edkaya May 17, 2024
e99068d
Clean up code
edkaya May 18, 2024
6992ed3
Remove placeholder
edkaya May 19, 2024
e7f5a5a
Fix studentExam update
edkaya May 19, 2024
82a2c0d
Remove additional observable properties
edkaya May 19, 2024
5c2c937
Load exam summary directly after test exam
edkaya May 19, 2024
fd6a501
Implement back exam funct in case of page refresh
edkaya May 19, 2024
4f01160
Fix exam-participation tests
edkaya May 21, 2024
336f026
Add more tests to ensure functionality
edkaya May 21, 2024
9d2e3e3
Remove backup files
edkaya May 22, 2024
16fc0b7
Fix exam result summary test
edkaya May 22, 2024
006d702
Code clean up
edkaya May 22, 2024
ed72765
Fix scrollTop bug
edkaya May 24, 2024
aab946e
Merge develop into branch
edkaya May 24, 2024
f602f65
Fix displaying exam start texts
edkaya May 24, 2024
bf6e484
Merge develop into branch
edkaya May 25, 2024
c9703ef
Fix routing
edkaya May 25, 2024
20a47b5
Adapt navbar and routing changes
edkaya May 25, 2024
3b29c84
Implement feedback
edkaya May 26, 2024
039012b
Fix selected exam bug
edkaya May 27, 2024
df2a593
Implement hide approach
edkaya May 28, 2024
3ec91b6
Adjust exam layout
edkaya May 28, 2024
410c052
fix sticky position
edkaya May 28, 2024
00d5352
Fix exam height
edkaya May 29, 2024
f3a4441
Fix param + add scrollable
edkaya May 29, 2024
9f25f57
Adjust paddings
edkaya May 30, 2024
166216c
Add scrollable
edkaya May 30, 2024
ddacfe2
Fix test runs
edkaya May 30, 2024
6ef1540
Add padding to showExamSummary button
edkaya May 30, 2024
b590145
Handle edge cases
edkaya May 31, 2024
2a81e2b
Fix deactivate subrouting
edkaya May 31, 2024
2e93d5a
Adjust exam layout for testRuns
edkaya May 31, 2024
8bda224
Adjust layout for dev and prod
edkaya May 31, 2024
89384b2
Fix tests + fix routing
edkaya Jun 1, 2024
943c2b9
Fix large sidebar card test
edkaya Jun 1, 2024
2063f9f
Merge branch 'develop' into feature/exam-mode/add-sidebar-with-large-…
edkaya Jun 2, 2024
b5900f4
Remove unused files
edkaya Jun 2, 2024
3eedf12
Remove deleted components from test files
edkaya Jun 2, 2024
00a2033
Add more tests
edkaya Jun 3, 2024
2ffb81d
Fix typo
edkaya Jun 3, 2024
0af4c3f
Remove notification and course overview button in exam view
edkaya Jun 3, 2024
f895b83
Merge branch 'develop' into feature/exam-mode/add-sidebar-with-large-…
edkaya Jun 6, 2024
d66d4c7
Implement feedback
edkaya Jun 6, 2024
fe2d1bc
remove empty line to fix prettier
edkaya Jun 6, 2024
78ea0dd
Add more tests to increase branch coverage
edkaya Jun 6, 2024
ef458b4
Resolve merge conflict
edkaya Jun 10, 2024
5a6e6ce
Resolve merge conflict
edkaya Jun 17, 2024
b5cce62
Merge branch 'develop' into feature/exam-mode/add-sidebar-with-large-…
edkaya Jun 18, 2024
843c23d
Add files manually to resolve merge conflict
edkaya Jun 20, 2024
fe85502
Resolve merge conflict
edkaya Jun 20, 2024
62c80f2
Remove the manually added files to resolve merge conflict
edkaya Jun 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/main/webapp/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,6 @@ const LAYOUT_ROUTES: Routes = [navbarRoute, ...errorRoute];
},

// ===== EXAM =====
{
path: 'courses/:courseId/exams/:examId',
loadChildren: () => import('./exam/participate/exam-participation.module').then((m) => m.ArtemisExamParticipationModule),
},
{
path: 'course-management/:courseId/exams',
loadChildren: () => import('./exam/manage/exam-management.module').then((m) => m.ArtemisExamManagementModule),
Expand Down
210 changes: 109 additions & 101 deletions src/main/webapp/app/exam/participate/exam-participation.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,122 +3,128 @@
}
@if (exam) {
@if (isVisible() && !isGracePeriodOver() && !this.studentExam?.submitted && !examStartConfirmed) {
<jhi-exam-participation-cover [startView]="true" [exam]="exam" [studentExam]="studentExam" [testRunStartTime]="testStartTime" (onExamStarted)="examStarted($event)" />
<div [ngClass]="{ 'content-height-dev': (!isProduction || isTestServer) && !testRunId, 'px-3 py-3 scrollable-content': !testRunId }">
edkaya marked this conversation as resolved.
Show resolved Hide resolved
<jhi-exam-participation-cover [startView]="true" [exam]="exam" [studentExam]="studentExam" [testRunStartTime]="testStartTime" (onExamStarted)="examStarted($event)" />
</div>
}
@if (studentExam) {
<!-- exam participation -->
@if (isVisible() && isActive() && !isOver() && examStartConfirmed) {
<!-- exam nav -->
<jhi-exam-navigation-bar
id="exam-navigation-bar"
class="exam-navigation-sticky d-block"
[exercises]="studentExam.exercises!"
[exerciseIndex]="exerciseIndex"
[endDate]="individualStudentEndDate"
[overviewPageOpen]="activePageIndex === -1"
[examSessions]="studentExam.examSessions"
(onPageChanged)="onPageChange($event)"
(examAboutToEnd)="examEnded()"
(onExamHandInEarly)="toggleHandInEarly()"
/>
<!-- exercises -->
<div [hidden]="activePageIndex !== -1">
<jhi-exam-exercise-overview-page [studentExam]="studentExam" (onPageChanged)="onPageChange($event)" />
</div>
@for (exercise of studentExam.exercises; track exercise; let i = $index) {
@if (exercise && exercise.studentParticipations && exercise.studentParticipations[0]) {
@if (pageComponentVisited[i]) {
<div class="mb-4" [hidden]="i !== activePageIndex" [id]="'exercise-' + exercise.id">
@switch (exercise.type) {
@case (QUIZ) {
<jhi-quiz-submission-exam [quizConfiguration]="exercise" [studentSubmission]="exercise.studentParticipations[0].submissions![0]" />
}
@case (FILEUPLOAD) {
<jhi-file-upload-submission-exam [exercise]="exercise" [studentSubmission]="exercise.studentParticipations[0].submissions![0]" />
}
@case (TEXT) {
<jhi-text-editor-exam [exercise]="exercise" [studentSubmission]="exercise.studentParticipations[0].submissions![0]" />
}
@case (MODELING) {
<jhi-modeling-submission-exam [exercise]="exercise" [studentSubmission]="exercise.studentParticipations[0].submissions![0]" />
}
@case (PROGRAMMING) {
<jhi-programming-submission-exam [exercise]="exercise" [studentParticipation]="exercise.studentParticipations[0]" [courseId]="courseId" />
<div [ngClass]="{ 'card-body': !testRunId }">
<!-- exam nav -->
<jhi-exam-navigation-bar
id="exam-navigation-bar"
class="exam-navigation-sticky d-block"
[exercises]="studentExam.exercises!"
[exerciseIndex]="exerciseIndex"
[endDate]="individualStudentEndDate"
[overviewPageOpen]="activePageIndex === -1"
[examSessions]="studentExam.examSessions"
(onPageChanged)="onPageChange($event)"
(examAboutToEnd)="examEnded()"
(onExamHandInEarly)="toggleHandInEarly()"
/>
<!-- exercises -->
<div [hidden]="activePageIndex !== -1">
<jhi-exam-exercise-overview-page [studentExam]="studentExam" (onPageChanged)="onPageChange($event)" />
</div>
@for (exercise of studentExam.exercises; track exercise; let i = $index) {
@if (exercise && exercise.studentParticipations && exercise.studentParticipations[0]) {
@if (pageComponentVisited[i]) {
<div class="mb-4" [hidden]="i !== activePageIndex" [id]="'exercise-' + exercise.id">
@switch (exercise.type) {
@case (QUIZ) {
<jhi-quiz-submission-exam [quizConfiguration]="exercise" [studentSubmission]="exercise.studentParticipations[0].submissions![0]" />
}
@case (FILEUPLOAD) {
<jhi-file-upload-submission-exam [exercise]="exercise" [studentSubmission]="exercise.studentParticipations[0].submissions![0]" />
}
@case (TEXT) {
<jhi-text-editor-exam [exercise]="exercise" [studentSubmission]="exercise.studentParticipations[0].submissions![0]" />
}
@case (MODELING) {
<jhi-modeling-submission-exam [exercise]="exercise" [studentSubmission]="exercise.studentParticipations[0].submissions![0]" />
}
@case (PROGRAMMING) {
<jhi-programming-submission-exam [exercise]="exercise" [studentParticipation]="exercise.studentParticipations[0]" [courseId]="courseId" />
}
}
}
</div>
</div>
}
}
}
}
@if ((generateParticipationStatus | async) === 'generating') {
<div class="d-flex justify-content-center align-items-center">
<p class="mb-0" jhiTranslate="artemisApp.examParticipation.preparingParticipation"></p>
<div class="spinner-border ms-2" role="status">
<span class="sr-only">Loading...</span>
@if ((generateParticipationStatus | async) === 'generating') {
<div class="d-flex justify-content-center align-items-center">
<p class="mb-0" jhiTranslate="artemisApp.examParticipation.preparingParticipation"></p>
<div class="spinner-border ms-2" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</div>
}
@if ((generateParticipationStatus | async) === 'failed') {
<div class="d-flex justify-content-center align-items-center">
<p class="mb-0" jhiTranslate="artemisApp.examParticipation.generateParticipationFailed"></p>
<button class="btn btn-sm btn-primary px-3 ms-2" (click)="createParticipationForExercise(this.activeExamPage.exercise!).subscribe()">
{{ 'artemisApp.examParticipation.generateParticipationRetry' | artemisTranslate }}
</button>
</div>
}
<!-- exam connection status footer bar -->
@if (connected) {
<div class="exam-footer connected">
<div class="container">
<div class="exam-footer-content">
<!-- Note by SK: this case shows an empty <p> on purpose -->
@if (isProgrammingExercise()) {
<p jhiTranslate="artemisApp.examParticipation.ideConnected" class="mb-0"></p>
} @else {
<p jhiTranslate="artemisApp.examParticipation.connected" class="mb-0"></p>
}
<jhi-connection-status class="connection-status-exam-participation" />
}
@if ((generateParticipationStatus | async) === 'failed') {
<div class="d-flex justify-content-center align-items-center">
<p class="mb-0" jhiTranslate="artemisApp.examParticipation.generateParticipationFailed"></p>
<button class="btn btn-sm btn-primary px-3 ms-2" (click)="createParticipationForExercise(this.activeExamPage.exercise!).subscribe()">
{{ 'artemisApp.examParticipation.generateParticipationRetry' | artemisTranslate }}
</button>
</div>
}
<!-- exam connection status footer bar -->
@if (connected) {
<div class="exam-footer connected">
<div class="container">
<div class="exam-footer-content">
<!-- Note by SK: this case shows an empty <p> on purpose -->
@if (isProgrammingExercise()) {
<p jhiTranslate="artemisApp.examParticipation.ideConnected" class="mb-0"></p>
} @else {
<p jhiTranslate="artemisApp.examParticipation.connected" class="mb-0"></p>
}
<jhi-connection-status class="connection-status-exam-participation" />
</div>
</div>
</div>
</div>
}
@if (!connected) {
<div class="exam-footer disconnected">
<div class="container">
<div class="exam-footer-content">
@if (!isProgrammingExercise()) {
<p jhiTranslate="artemisApp.examParticipation.disconnected" class="mb-0"></p>
}
@if (isProgrammingExerciseWithCodeEditor() && isProgrammingExerciseWithOfflineIDE()) {
<p jhiTranslate="artemisApp.examParticipation.disconnectedCodeEditorAndOfflineIDE" class="mb-0"></p>
}
@if (isProgrammingExerciseWithCodeEditor() && !isProgrammingExerciseWithOfflineIDE()) {
<p jhiTranslate="artemisApp.examParticipation.disconnectedCodeEditorNoOfflineIDE" class="mb-0"></p>
}
@if (!isProgrammingExerciseWithCodeEditor() && isProgrammingExerciseWithOfflineIDE()) {
<p jhiTranslate="artemisApp.examParticipation.disconnectedNoCodeEditor" class="mb-0"></p>
}
<jhi-connection-status class="connection-status-exam-participation" />
}
@if (!connected) {
<div class="exam-footer disconnected">
<div class="container">
<div class="exam-footer-content">
@if (!isProgrammingExercise()) {
<p jhiTranslate="artemisApp.examParticipation.disconnected" class="mb-0"></p>
}
@if (isProgrammingExerciseWithCodeEditor() && isProgrammingExerciseWithOfflineIDE()) {
<p jhiTranslate="artemisApp.examParticipation.disconnectedCodeEditorAndOfflineIDE" class="mb-0"></p>
}
@if (isProgrammingExerciseWithCodeEditor() && !isProgrammingExerciseWithOfflineIDE()) {
<p jhiTranslate="artemisApp.examParticipation.disconnectedCodeEditorNoOfflineIDE" class="mb-0"></p>
}
@if (!isProgrammingExerciseWithCodeEditor() && isProgrammingExerciseWithOfflineIDE()) {
<p jhiTranslate="artemisApp.examParticipation.disconnectedNoCodeEditor" class="mb-0"></p>
}
<jhi-connection-status class="connection-status-exam-participation" />
</div>
</div>
</div>
</div>
}
}
</div>
}
@if (!studentExam.submitted && ((isOver() && examStartConfirmed) || isGracePeriodOver())) {
<jhi-exam-participation-cover
[startView]="false"
[exam]="exam"
[studentExam]="studentExam"
[handInEarly]="handInEarly"
[handInPossible]="handInPossible"
[submitInProgress]="submitInProgress"
[attendanceChecked]="attendanceChecked"
(onExamEnded)="onExamEndConfirmed()"
(onExamContinueAfterHandInEarly)="toggleHandInEarly()"
/>
<div class="px-3 py-3">
edkaya marked this conversation as resolved.
Show resolved Hide resolved
<jhi-exam-participation-cover
[startView]="false"
[exam]="exam"
[studentExam]="studentExam"
[handInEarly]="handInEarly"
[handInPossible]="handInPossible"
[submitInProgress]="submitInProgress"
[attendanceChecked]="attendanceChecked"
(onExamEnded)="onExamEndConfirmed()"
(onExamContinueAfterHandInEarly)="toggleHandInEarly()"
/>
</div>
}
@if (this.studentExam?.submitted && !showExamSummary && !loadingExam) {
<div class="submissionSuccessfulHint">
<div class="submissionSuccessfulHint pb-3">
<fa-icon [icon]="faCheckCircle" class="check" />
<h2 jhiTranslate="artemisApp.examParticipation.submissionSuccessful.title"></h2>
<p jhiTranslate="artemisApp.examParticipation.submissionSuccessful.noActionRequired"></p>
Expand All @@ -135,7 +141,9 @@ <h2 jhiTranslate="artemisApp.examParticipation.submissionSuccessful.title"></h2>
</div>
}
@if (showExamSummary) {
<jhi-exam-participation-summary [studentExam]="studentExam" />
<div [ngClass]="{ 'content-height-dev': (!isProduction || isTestServer) && !testRunId, 'px-3 py-3 scrollable-content': !testRunId }">
edkaya marked this conversation as resolved.
Show resolved Hide resolved
<jhi-exam-participation-summary [studentExam]="studentExam" />
</div>
}
}
}
Expand Down
Loading
Loading