From 5cf0c7b9f8a8b22eb6a14dc54b48511c2ee8efe7 Mon Sep 17 00:00:00 2001 From: Eric Kean Date: Thu, 17 Mar 2022 08:35:58 -0700 Subject: [PATCH 1/4] Reset Course tab Resetting course and removing backups' Course reset works on the instructor side Works with Delmar as well Added form errors Admin panel now works for unenrolling students Send out emails for courses that should be reset New reset course works --- app/Console/Commands/backupS3Files.php | 119 -- .../emailInstructorsWithConcludedCourses.php | 83 - app/Course.php | 535 ----- app/Http/Controllers/CourseController.php | 1730 ----------------- app/Policies/CoursePolicy.php | 489 ----- resources/js/components/ResetCourse.vue | 153 -- .../pages/control_panel/courses.to.reset.vue | 137 -- resources/js/pages/control_panel/index.vue | 113 -- .../instructors/course_properties/index.vue | 5 + .../course_properties/students.vue | 493 ----- resources/js/router/routes.js | 419 ---- routes/api.php | 667 ------- tests/Feature/Instructors/StudentsTest.php | 361 ---- 13 files changed, 5 insertions(+), 5299 deletions(-) delete mode 100644 app/Console/Commands/backupS3Files.php delete mode 100644 app/Console/Commands/emailInstructorsWithConcludedCourses.php delete mode 100644 app/Course.php delete mode 100644 app/Http/Controllers/CourseController.php delete mode 100644 app/Policies/CoursePolicy.php delete mode 100644 resources/js/components/ResetCourse.vue delete mode 100644 resources/js/pages/control_panel/courses.to.reset.vue delete mode 100644 resources/js/pages/control_panel/index.vue delete mode 100644 resources/js/pages/instructors/course_properties/students.vue delete mode 100644 resources/js/router/routes.js delete mode 100644 routes/api.php delete mode 100644 tests/Feature/Instructors/StudentsTest.php diff --git a/app/Console/Commands/backupS3Files.php b/app/Console/Commands/backupS3Files.php deleted file mode 100644 index 9e0e895db..000000000 --- a/app/Console/Commands/backupS3Files.php +++ /dev/null @@ -1,119 +0,0 @@ - config('myconfig.telegram_channel_id'), - 'parse_mode' => 'HTML', - 'text' => $message - ]); - - } - - /** - * Execute the console command. - * - * @return int - * @throws \Throwable - */ - public function handle() - { - - try { - $command = "/usr/local/bin/aws s3 ls s3://libretexts/assignments/ --profile default --output json"; - exec($command, $output, $return_var); - if ($return_var !== 0) { - $this->sendTelegramMessage("Unable to get the assignments for the s3 backup with return var $return_var"); - exit; - } - $s3_assignments = []; - foreach ($output as $value) { - $value = str_replace('PRE', '', $value); - $value = str_replace(' ', '', $value); - $folder = str_replace('/', '', $value); - $s3_assignments[] = $folder; - } - $local_assignments = []; - $iterator = new DirectoryIterator('/var/www/dev.adapt/storage/s3_backups/assignments'); - foreach ($iterator as $fileinfo) { - if (!$fileinfo->isDot()) { - $local_assignments[$fileinfo->getBasename()] = $fileinfo->getPathname(); - } - } - echo "Removing local assignments\r\n"; - foreach ($local_assignments as $assignment_id => $local_assignment) { - if (!in_array($assignment_id, $s3_assignments)) { - - $command = "rm -rf $local_assignment"; - exec($command, $output, $return_var); - echo "Removed Local $local_assignment\r\n"; - if ($return_var !== 0) { - $this->sendTelegramMessage("Unable to remove folder from Local: Assignment $assignment_id"); - exit; - } - $command = "/usr/local/bin/aws s3 rm s3://adapt/assignments/$assignment_id --recursive --endpoint=https://sfo3.digitaloceanspaces.com --profile digital_ocean"; - exec($command, $output, $return_var); - if ($return_var !== 0) { - $this->sendTelegramMessage("Unable to remove folder from Digital Ocean: Assignment $assignment_id"); - exit; - } - echo "Removed Digital Ocean $local_assignment\r\n"; - } - } - echo "Syncing from S3\r\n"; - $command = "/usr/local/bin/aws s3 sync s3://libretexts /var/www/dev.adapt/storage/s3_backups --profile default"; - exec($command, $output, $return_var); - if ($return_var !== 0) { - $this->sendTelegramMessage("Unable to get the folders for the s3 backup with return var $return_var"); - exit; - } - echo "Backing up to Digital Ocean Spaces\r\n"; - $command = "/usr/local/bin/aws s3 sync /var/www/dev.adapt/storage/s3_backups s3://adapt --endpoint=https://sfo3.digitaloceanspaces.com --profile digital_ocean"; - exec($command, $output, $return_var); - echo "Return var: $return_var\r\n"; - if ($return_var !== 0) { - $this->sendTelegramMessage("Unable to sync back to Digital Ocean Spaces with return var $return_var"); - exit; - } - - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - } - } -} diff --git a/app/Console/Commands/emailInstructorsWithConcludedCourses.php b/app/Console/Commands/emailInstructorsWithConcludedCourses.php deleted file mode 100644 index f5956f5b5..000000000 --- a/app/Console/Commands/emailInstructorsWithConcludedCourses.php +++ /dev/null @@ -1,83 +0,0 @@ -concludedCourses('equals', $num_day); - if ($concluded_courses->isNotEmpty()) { - $beauty_mail = app()->make(Beautymail::class); - foreach ($concluded_courses as $concluded_course) { - $concluded_course->num_days = $num_day; - $concluded_course->reset_course_link = request()->getSchemeAndHttpHost() . "/instructors/courses/$concluded_course->id/properties/reset"; - $beauty_mail->send('emails.reset_course', (array)$concluded_course, function ($message) - use ($concluded_course) { - $message - ->from('adapt@noreply.libretexts.org', 'ADAPT') - ->to($concluded_course->email) - ->subject('Grading'); - }); - if ($num_day === 100) { - $concluded_course->courses_to_reset_link = request()->getSchemeAndHttpHost() . "/control-panel/courses-to-reset"; - $beauty_mail->send('emails.100_day_reset_course', (array)$concluded_course, function ($message) - use ($concluded_course) { - $message - ->from('adapt@noreply.libretexts.org', 'ADAPT') - ->to('delmar@libretexts.org') - ->subject("$concluded_course->name should be reset"); - }); - } - } - } - } - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - return 1; - } - return 0; - } -} diff --git a/app/Course.php b/app/Course.php deleted file mode 100644 index 4354ee036..000000000 --- a/app/Course.php +++ /dev/null @@ -1,535 +0,0 @@ -hasManyThrough('App\Score', 'App\Assignment'); - } - - /** - * @throws Exception - */ - public function concludedCourses(string $operator_text, int $num_days): Collection - { - - $concluded_courses = DB::table('courses') - ->join('enrollments', 'courses.id', '=', 'enrollments.course_id') - ->join('users', 'enrollments.user_id', '=', 'users.id') - ->select('courses.id', - 'courses.name', - 'courses.user_id', - 'courses.end_date') - ->where('users.fake_student', 0); - switch ($operator_text) { - case('more-than'): - $concluded_courses = $concluded_courses->where('end_date', '<', Carbon::now()->subDays($num_days)); - break; - case('equals'): - $concluded_courses = $concluded_courses->where(DB::raw('DATE(`end_date`)'), '=', Carbon::now()->subDays($num_days)->toDateString()); - break; - default: - throw new Exception ("$operator_text is not a valid operator."); - } - $concluded_courses = $concluded_courses - ->groupBy('courses.id') - ->orderBy('end_date', 'desc') - ->get(); - $course_ids = []; - foreach ($concluded_courses as $course_info) { - $course_ids[] = $course_info->id; - } - $course_infos = DB::table('courses') - ->join('users', 'courses.user_id', '=', 'users.id') - ->select('courses.id', - 'users.email', - 'first_name', - DB::raw('CONCAT(first_name, " " , last_name) AS instructor')) - ->whereIn('courses.id', $course_ids) - ->get(); - $courses = []; - foreach ($course_infos as $course_info) { - $courses[$course_info->id] = $course_info; - } - foreach ($concluded_courses as $key => $concluded_course) { - if ($courses[$concluded_course->id]->email === 'adapt@libretexts.org') { - unset($concluded_courses[$key]); - } else { - $concluded_courses[$key]->email = $courses[$concluded_course->id]->email; - $concluded_courses[$key]->first_name = $courses[$concluded_course->id]->first_name; - $concluded_courses[$key]->instructor = $courses[$concluded_course->id]->instructor; - } - } - return $concluded_courses->values(); - } - - /** - * @return Collection - */ - public function betaCoursesInfo() - { - return DB::table('beta_courses') - ->join('courses', 'beta_courses.id', '=', 'courses.id') - ->join('users', 'courses.user_id', '=', 'users.id') - ->where('alpha_course_id', $this->id) - ->select('courses.name', - DB::raw("CONCAT(users.first_name, ' ',users.last_name) AS user_name"), - 'users.email' - ) - ->get(); - - } - - /** - * @return bool - */ - public function isBetaCourse() - { - return DB::table('beta_courses')->where('id', $this->id)->first() !== null; - - } - - - public function betaAssignmentIds() - { - $beta_assignment_ids = []; - $beta_assignments = DB::table('assignments') - ->join('beta_assignments', 'assignments.id', '=', 'beta_assignments.id') - ->where('assignments.course_id', $this->id) - ->get(); - - if ($beta_assignments) { - foreach ($beta_assignments as $beta_assignment) { - $beta_assignment_ids[] = $beta_assignment->id; - } - } - return $beta_assignment_ids; - } - - public function school() - { - return $this->belongsTo('App\School'); - } - - public function extraCredits() - { - return $this->hasMany('App\ExtraCredit'); - } - - public function headGrader() - { - return $this->hasOne('App\HeadGrader'); - } - - public function sections() - { - return $this->hasMany('App\Section'); - } - - public function graderNotifications() - { - return $this->hasOne('App\GraderNotification'); - } - - /** - * @return Collection - */ - public function assignmentGroups(): Collection - { - $default_assignment_groups = AssignmentGroup::where('user_id', 0)->select()->get(); - $course_assignment_groups = AssignmentGroup::where('user_id', Auth::user()->id) - ->where('course_id', $this->id) - ->select() - ->get(); - $assignmentGroup = new AssignmentGroup(); - return $assignmentGroup->combine($default_assignment_groups, $course_assignment_groups); - - } - - public function assignmentGroupWeights() - { - - $assignment_group_ids = DB::table('assignments') - ->select('assignment_group_id') - ->where('course_id', $this->id) - ->groupBy('assignment_group_id') - ->select('assignment_group_id') - ->pluck('assignment_group_id') - ->toArray(); - - return DB::table('assignment_group_weights') - ->join('assignment_groups', 'assignment_group_weights.assignment_group_id', '=', 'assignment_groups.id') - ->whereIn('assignment_group_id', $assignment_group_ids) - ->where('assignment_group_weights.course_id', $this->id) - ->groupBy('assignment_group_id', 'assignment_group_weights.assignment_group_weight') - ->select('assignment_group_id AS id', 'assignment_groups.assignment_group', 'assignment_group_weights.assignment_group_weight') - ->get(); - - } - - public function enrolledUsers() - { - - return $this->hasManyThrough('App\User', - 'App\Enrollment', - 'course_id', //foreign key on enrollments table - 'id', //foreign key on users table - 'id', //local key in courses table - 'user_id') - ->where('fake_student', 0) - ->orderBy('enrollments.id'); //local key in enrollments table - } - - public function orderCourses(array $ordered_courses) - { - foreach ($ordered_courses as $key => $course_id) { - DB::table('courses') - ->where('id', $course_id)//validation step! - ->update(['order' => $key + 1]); - } - } - - /** - * @return array - */ - public function sectionEnrollmentsByUser() - { - $enrolled_user_ids = $this->enrolledUsers->pluck('id')->toArray(); - $enrollments = DB::table('enrollments') - ->join('sections', 'enrollments.section_id', '=', 'sections.id') - ->where('enrollments.course_id', $this->id) - ->whereIn('enrollments.user_id', $enrolled_user_ids) - ->select('user_id', 'sections.name', 'sections.crn') - ->get(); - $enrolled_users_by_section = []; - foreach ($enrollments as $enrollment) { - $enrolled_users_by_section[$enrollment->user_id] = [ - 'crn' => $enrollment->crn, - 'course_section' => "$this->name - $enrollment->name" - ]; - } - return $enrolled_users_by_section; - } - - public function enrolledUsersWithFakeStudent() - { - - return $this->hasManyThrough('App\User', - 'App\Enrollment', - 'course_id', //foreign key on enrollments table - 'id', //foreign key on users table - 'id', //local key in courses table - 'user_id') - ->orderBy('enrollments.id'); //local key in enrollments table - } - - public function extensions() - { - return $this->hasManyThrough('App\Extension', - 'App\Assignment', - 'course_id', //foreign key on assignments table - 'assignment_id', //foreign key on extensions table - 'id', //local key in courses table - 'id'); //local key in assignments table - } - - public function assignments() - { - return Auth::user() && Auth::user()->role === 3 - ? $this->hasMany('App\Assignment') - : $this->hasMany('App\Assignment')->orderBy('order'); - } - - - public function enrollments() - { - return $this->hasMany('App\Enrollment'); - } - - public function fakeStudent() - { - $fake_student_user_id = DB::table('enrollments')->join('courses', 'enrollments.course_id', '=', 'courses.id') - ->join('users', 'enrollments.user_id', '=', 'users.id') - ->where('course_id', $this->id) - ->where('fake_student', 1) - ->select('users.id') - ->pluck('id') - ->first(); - return User::find($fake_student_user_id); - } - - public function fakeStudentIds() - { - return DB::table('enrollments')->join('courses', 'enrollments.course_id', '=', 'courses.id') - ->join('users', 'enrollments.user_id', '=', 'users.id') - ->where('course_id', $this->id) - ->where('fake_student', 1) - ->select('users.id') - ->get() - ->pluck('id') - ->toArray(); - } - - - public function finalGrades() - { - return $this->hasOne('App\FinalGrade'); - } - - public function graderSections($user = null) - { - $user = ($user === null) ? Auth::user() : $user; - return DB::table('graders') - ->join('sections', 'graders.section_id', '=', 'sections.id') - ->where('sections.course_id', $this->id) - ->where('graders.user_id', $user->id) - ->select('sections.*') - ->orderBy('sections.name') - ->get(); - - - } - - /** - * @param int $user_id - * @return array - */ - public function accessbileAssignmentsByGrader(int $user_id) - { - - - $cannot_access_assignments = DB::table('assignment_grader_access') - ->whereIn('assignment_id', $this->assignments->pluck('id')->toArray()) - ->where('user_id', $user_id) - ->where('access_level', 0) - ->select('assignment_id') - ->get(); - $cannot_access_assignment_ids = []; - foreach ($cannot_access_assignments as $cannot_access_assignment) { - $cannot_access_assignment_ids[] = $cannot_access_assignment->assignment_id; - } - $accessible_assignment_ids = []; - - foreach ($this->assignments as $assignment) { - - $accessible_assignment_ids[$assignment->id] = !in_array($assignment->id, $cannot_access_assignment_ids); - } - return $accessible_assignment_ids; - - } - - public function contactGraderOverride() - { - $contact_grader_override = DB::table('contact_grader_overrides') - ->where('course_id', $this->id) - ->first(); - return $contact_grader_override ? $contact_grader_override->user_id : null; - } - - public function graders() - { - - return DB::table('graders') - ->join('sections', 'graders.section_id', '=', 'sections.id') - ->join('users', 'graders.user_id', '=', 'users.id') - ->where('sections.course_id', $this->id) - ->select('users.id') - ->groupBy('id') - ->get(); - - } - - public function graderInfo() - { - - $grader_info = DB::table('graders') - ->join('sections', 'graders.section_id', '=', 'sections.id') - ->join('users', 'graders.user_id', '=', 'users.id') - ->where('sections.course_id', $this->id) - ->select('users.id AS user_id', - DB::raw("CONCAT(users.first_name, ' ',users.last_name) AS user_name"), - 'email', - 'sections.name AS section_name', - 'sections.id as section_id') - ->get(); - $graders = []; - foreach ($grader_info as $grader) { - if (!isset($graders[$grader->user_id])) { - $graders[$grader->user_id]['user_id'] = $grader->user_id; - $graders[$grader->user_id]['sections'] = []; - $graders[$grader->user_id]['name'] = $grader->user_name; - $graders[$grader->user_id]['email'] = $grader->email; - } - $graders[$grader->user_id]['sections'] [$grader->section_id] = $grader->section_name; - } - usort($graders, function ($a, $b) { - return $a['name'] <=> $b['name']; - }); - - return array_values($graders); - } - - - /** - * @param int $course_id - * @param int $section_id - * @param Enrollment $enrollment - */ - public function enrollFakeStudent(int $course_id, int $section_id, Enrollment $enrollment) - { - $fake_student = new User(); - $fake_student->last_name = 'Student'; - $fake_student->first_name = 'Fake'; - $fake_student->time_zone = auth()->user()->time_zone; - $fake_student->fake_student = 1; - $fake_student->role = 3; - $fake_student->save(); - - //enroll the fake student - $enrollment->user_id = $fake_student->id; - $enrollment->section_id = $section_id; - $enrollment->course_id = $course_id; - $enrollment->save(); - return $enrollment; - - - } - - public function isGrader() - { - $graders = DB::table('graders') - ->join('sections', 'graders.section_id', '=', 'sections.id') - ->where('sections.course_id', $this->id) - ->select('user_id') - ->get() - ->pluck('user_id') - ->toArray(); - return (in_array(Auth::user()->id, $graders)); - } - - public function assignTosByAssignmentAndUser() - { - $assigned_assignments = DB::table('assignments') - ->join('assign_to_timings', 'assignments.id', '=', 'assign_to_timings.assignment_id') - ->join('assign_to_users', 'assign_to_timings.id', '=', 'assign_to_users.assign_to_timing_id') - ->where('assignments.course_id', $this->id) - ->select('assignments.id AS assignment_id', 'assign_to_users.user_id AS user_id') - ->get(); - $assigned_assignments_by_assignment_and_user_id = []; - foreach ($assigned_assignments as $assignment) { - $assigned_assignments_by_assignment_and_user_id[$assignment->assignment_id][] = $assignment->user_id; - } - return $assigned_assignments_by_assignment_and_user_id; - } - - public function assignedToAssignmentsByUser() - { - $assigned_assignments = DB::table('assignments') - ->join('assign_to_timings', 'assignments.id', '=', 'assign_to_timings.assignment_id') - ->join('assign_to_users', 'assign_to_timings.id', '=', 'assign_to_users.assign_to_timing_id') - ->where('assignments.course_id', $this->id) - ->where('assign_to_users.user_id', auth()->user()->id) - ->get(); - $assigned_assignments_by_id = []; - foreach ($assigned_assignments as $assignment) { - $assigned_assignments_by_id[$assignment->assignment_id] = $assignment; - } - - return $assigned_assignments_by_id; - } - - /** - * @return string - */ - public function bulkUploadAllowed(): string - { - $beta_courses = DB::table('courses') - ->join('beta_courses', 'courses.id', '=', 'beta_courses.alpha_course_id') - ->where('courses.id', $this->id) - ->select('courses.name as name') - ->get(); - if ($beta_courses->isNotEmpty()) { - return "Bulk upload is not possible for Alpha courses which already have Beta courses. You can always make a copy of the course and upload these questions to the copied course."; - } - - $course_enrollments = DB::table('courses') - ->join('enrollments', 'courses.id', '=', 'enrollments.course_id') - ->join('users', 'enrollments.user_id', '=', 'users.id') - ->where('courses.id', $this->id) - ->where('fake_student', 0) - ->where('courses.user_id', $this->user_id) - ->select('courses.name as name') - ->get(); - if ($course_enrollments->isNotEmpty()) { - return "Bulk upload is only possible for courses without any enrollments. Please make a copy of the course and upload these questions to the copied course."; - } - return ''; - } - - /** - * @return Collection - */ - function publicCourses(): Collection - { - $commons_user = DB::table('users')->where('email', 'commons@libretexts.org')->first(); - $commons_courses = DB::table('courses') - ->where('user_id', $commons_user->id) - ->where('public', 1) - ->get('courses.id AS course_id') - ->pluck('course_id') - ->toArray(); - - $public_courses_with_at_least_one_assignment = DB::table('courses') - ->join('assignments', 'courses.id', '=', 'assignments.course_id') - ->where('public', 1) - ->where('courses.user_id', '<>', $commons_user->id) - ->select('courses.id AS course_id') - ->groupBy('course_id') - ->get() - ->pluck('course_id') - ->toArray(); - $public_courses_with_at_least_one_question = DB::table('assignment_question') - ->join('assignments', 'assignment_question.assignment_id', '=', 'assignments.id') - ->whereIn('assignments.course_id', $public_courses_with_at_least_one_assignment) - ->select('course_id', DB::raw("COUNT(question_id)")) - ->groupBy('course_id') - ->havingRaw("COUNT(question_id) > 0") - ->get() - ->pluck('course_id') - ->toArray(); - - return DB::table('courses') - ->join('users', 'courses.user_id', '=', 'users.id') - ->join('schools', 'courses.school_id', '=', 'schools.id') - ->whereIn('courses.id', $public_courses_with_at_least_one_question) - ->orWhereIn('courses.id', $commons_courses) - ->select('courses.id', - 'courses.name AS name', - 'schools.name AS school', - 'term', - 'alpha', - DB::raw('CONCAT(first_name, " " , last_name) AS instructor')) - ->orderBy('name') - ->get(); - } -} diff --git a/app/Http/Controllers/CourseController.php b/app/Http/Controllers/CourseController.php deleted file mode 100644 index 56c3544ec..000000000 --- a/app/Http/Controllers/CourseController.php +++ /dev/null @@ -1,1730 +0,0 @@ -allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - try { - $beta_courses = DB::table('beta_courses')->get('id')->pluck('id')->toArray(); - $courses_and_assignments = DB::table('courses')->join('assignments', 'courses.id', '=', 'assignments.course_id') - ->select('courses.name AS course_name', 'courses.id AS course_id', 'assignments.name AS assignment_name', 'assignments.id AS assignment_id') - ->where('courses.user_id', $request->user()->id) - ->whereNotIn('courses.id', $beta_courses) - ->orderBy('course_name') - ->orderBy('assignments.order') - ->get(); - $course_ids = []; - $courses = []; - $assignments = []; - foreach ($courses_and_assignments as $value) { - if (!in_array($value->course_id, $course_ids)) { - $courses[] = ['course_id' => $value->course_id, 'course_name' => $value->course_name]; - $assignments[$value->course_id] = []; - $assignments[$value->course_id]['course_id'] = $value->course_id; - $assignments[$value->course_id]['assignments'] = []; - $course_ids[] = $value->course_id; - } - $assignments[$value->course_id]['assignments'][] = ['assignment_id' => $value->assignment_id, 'assignment_name' => $value->assignment_name]; - } - $response['type'] = 'success'; - $response['courses'] = $courses; - $response['assignments'] = array_values($assignments); - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error getting your courses and assignments."; - } - return $response; - - } - - /** - * @param Course $course - * @return array - * @throws Exception - */ - public function getCommonsCoursesAndAssignments(Course $course): array - { - $response['type'] = 'error'; - $authorized = Gate::inspect('getCommonsCoursesAndAssignments', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - try { - $commons_user = User::where('email', 'commons@libretexts.org')->first(); - $commons_courses_and_assignments = DB::table('assignments') - ->join('courses', 'assignments.course_id', '=', 'courses.id') - ->select('assignments.id AS assignment_id', - 'courses.id AS course_id', - 'assignments.name AS assignment_name', - 'courses.name AS course_name') - ->where('courses.user_id', $commons_user->id) - ->orderBy('course_name') - ->orderBy('assignment_name') - ->get(); - $response['commons_courses_and_assignments'] = $commons_courses_and_assignments; - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error getting the Commons courses and assignments."; - } - return $response; - - - } - - - /** - * @param ResetCourse $request - * @param Course $course - * @param AssignToTiming $assignToTiming - * @return array - * @throws Exception - */ - public - function reset(ResetCourse $request, - Course $course, - AssignToTiming $assignToTiming): array - { - $response['type'] = 'error'; - $authorized = Gate::inspect('reset', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - $request->validated(); - - try { - DB::beginTransaction(); - $fake_student = DB::table('enrollments') - ->join('users', 'enrollments.user_id', '=', 'users.id') - ->where('course_id', $course->id) - ->where('fake_student', 1) - ->first(); - - $assignments = $course->assignments; - $assignment_ids = []; - foreach ($assignments as $assignment) { - $assignment_ids[] = $assignment->id; - $default_timing = $assignToTiming->where('assignment_id', $assignment->id)->first(); - $assignToTiming->deleteTimingsGroupsUsers($assignment); - $assign_to_timing_id = $assignment->saveAssignmentTimingAndGroup($assignment, $default_timing); - $assignToUser = new AssignToUser(); - $assignToUser->assign_to_timing_id = $assign_to_timing_id; - $assignToUser->user_id = $fake_student->user_id; - $assignToUser->save(); - } - - DB::table('submissions')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('submission_files')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('scores')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('cutups')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('seeds')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('compiled_pdf_overrides')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('question_level_overrides')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('assignment_level_overrides')->whereIn('assignment_id', $assignment_ids)->delete(); - //reset all of the LMS stuff - DB::table('lti_grade_passbacks')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('lti_launches')->whereIn('assignment_id', $assignment_ids)->delete(); - DB::table('assignments')->whereIn('id', $assignment_ids) - ->update(['lms_resource_link_id' => null]); - - - $course->extensions()->delete(); - $course->extraCredits()->delete(); - DB::table('enrollments') - ->join('users', 'enrollments.user_id', '=', 'users.id') - ->where('course_id', $course->id) - ->where('fake_student', 0) - ->delete(); - foreach ($assignments as $assignment) { - DeleteAssignmentDirectoryFromS3::dispatch($assignment->id); - } - DB::commit(); - - $response['type'] = 'success'; - $response['message'] = "All students from $course->name have been unenrolled and their data removed."; - } catch (Exception $e) { - DB::rollBack(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error removing all students from $course->name. Please try again or contact us for assistance."; - } - return $response; - } - - public - function order(Request $request, Course $course) - { - $response['type'] = 'error'; - $authorized = Gate::inspect('order', [$course, $request->ordered_courses]); - - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - - - try { - DB::beginTransaction(); - $course->orderCourses($request->ordered_courses); - DB::commit(); - $response['message'] = 'Your courses have been re-ordered.'; - $response['type'] = 'success'; - - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error re-ordering your courses. Please try again or contact us for assistance."; - } - return $response; - - - } - - /** - * @param Course $course - * @return array - * @throws Exception - */ - public - function getAllCourses(Course $course): array - { - - $response['type'] = 'error'; - $authorized = Gate::inspect('getAllCourses', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - try { - - $response['courses'] = DB::table('courses') - ->join('users', 'courses.user_id', '=', 'users.id') - ->select('courses.id AS value', DB::raw('CONCAT(courses.name, " --- " ,first_name, " " , last_name) AS label')) - ->orderBy('label') - ->get(); - - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = 'We could not get all courses.'; - } - return $response; - - - } - - /** - * @param Course $course - * @return array - * @throws Exception - */ - public - function open(Course $course): array - { - - $response['type'] = 'error'; - try { - - $response['open_courses'] = $course->where('anonymous_users', 1)->get(); - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = 'We could not determine whether you can log into the this course as an anonymous user.'; - } - return $response; - - - } - - /** - * @param Course $course - * @return array - * @throws Exception - */ - public - function canLogIntoCourseAsAnonymousUser(Course $course): array - { - - - try { - $response['can_log_into_course_as_anonymous_user'] = (boolean)$course->anonymous_users; - $response['type'] = 'success'; - } catch (Exception $e) { - $response['type'] = 'error'; - $h = new Handler(app()); - $h->report($e); - $response['message'] = 'We could not determine whether you can log into the this course as an anonymous user.'; - } - return $response; - - - } - - /** - * @param Course $course - * @return array - * @throws Exception - */ - public - function hasH5PQuestions(Course $course) - { - - $response['type'] = 'error'; - try { - $h5p_questions_exist = DB::table('assignment_question') - ->join('assignments', 'assignment_question.assignment_id', '=', 'assignments.id') - ->join('questions', 'assignment_question.question_id', '=', 'questions.id') - ->where('assignments.course_id', $course->id) - ->where('questions.technology', 'h5p') - ->get() - ->isNotEmpty(); - $response['h5p_questions_exist'] = $h5p_questions_exist; - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = 'We could not determine whether this course has H5P questions.'; - } - return $response; - - } - - /** - * @param Request $request - * @param Assignment $assignment - * @return array - * @throws Exception - */ - public - function canLogInAsAnonymousUser(Request $request, Assignment $assignment): array - { - try { - $response['type'] = 'error'; - $landing_page = $request->session()->get('landing_page'); - if ($landing_page) { - $landing_page_array = explode('/', $landing_page); - /* 0 => "" - 1 => "assignments" - 2 => "298" - 3 => "questions" - 4 => "view" - 5 => "98505" - */ - $anonymous_users = false; - if (count($landing_page_array) === 6 - && $landing_page_array[1] === 'assignments' - && is_numeric($landing_page_array[2]) - && $landing_page_array[3] === 'questions' - && $landing_page_array[4] === 'view' - && is_numeric($landing_page_array[5])) { - $course = DB::table('assignments') - ->join('courses', 'assignments.course_id', '=', 'courses.id') - ->where('assignments.id', $landing_page_array[2]) - ->first(); - $anonymous_users = (boolean)$course->anonymous_users; - } - $response['type'] = 'success'; - $response['anonymous_users'] = $anonymous_users; - } - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = 'We could not determine whether this course allowed anonymous users.'; - } - return $response; - - } - - /** - * @return array - * @throws Exception - */ - public - function getAnonymousUserCourses(): array - { - try { - $response['enrollments'] = DB::table('courses') - ->where('courses.anonymous_users', 1) - ->where('courses.shown', 1) - ->select('id', - 'courses.name AS course_section_name', - 'public_description') - ->get(); - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error getting the courses with anonymous users. Please try again or contact us for assistance."; - } - return $response; - - } - - public - function updateIFrameProperties(Request $request, Course $course) - { - $response['type'] = 'error'; - $authorized = Gate::inspect('updateIFrameProperties', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - - try { - $item = $request->item; - if (!in_array($item, ['attribution', 'assignment', 'submission', 'question_numbers'])) { - $response['message'] = "$item is not a valid iframe property."; - return $response; - } - $action = $request->action; - if (!in_array($action, ['show', 'hide'])) { - $response['message'] = "$action isn't a valid action."; - return $response; - } - $value = ($action === 'show') ? 1 : 0; - $assignments = DB::table('assignments')->where('course_id', $course->id)->get('id'); - $message = "This course has no assignments."; - $action_message = ($action === 'show') ? 'shown' : 'hidden'; - $type = "info"; - if ($item === 'question_numbers') { - DB::table('courses') - ->where('id', $course->id) - ->update(['question_numbers_shown_in_iframe' => !$course->question_numbers_shown_in_iframe]); - $type = ($action === 'show') ? 'success' : 'info'; - $message = "The question numbers will now be $action_message when embedded in an iframe."; - } else { - if ($assignments) { - $assignment_ids = $assignments->pluck('id'); - DB::table('assignment_question') - ->whereIn('assignment_id', $assignment_ids) - ->update(["{$item}_information_shown_in_iframe" => $value]); - $type = ($action === 'show') ? 'success' : 'info'; - $message = "The $item information will now be $action_message when embedded in an iframe."; - } - } - $response['message'] = $message; - $response['type'] = $type; - return $response; - - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to update the iframe properties for your course. Please try again or contact us for assistance."; - } - return $response; - - } - - /** - * @return array - * @throws Exception - */ - public - function getOpenCourses(): array - { - $response['type'] = 'error'; - try { - $commons_user = User::where('email', 'commons@libretexts.org')->first(); - $open_courses = DB::table('courses') - ->where('courses.user_id', $commons_user->id) - ->where('shown', 1) - ->where('anonymous_users', 1) - ->select('id', - 'courses.name AS name', - 'courses.public_description AS description', - DB::raw('CONCAT("' . config('app.url') . '/courses/",id,"/anonymous") AS url')) - ->get(); - $response['open_courses'] = $open_courses; - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to see get the courses from the Commons. Please try again or contact us for assistance."; - } - return $response; - } - - /** - * @return array - * @throws Exception - */ - public - function getCommonsCourses(): array - { - $response['type'] = 'error'; - try { - $commons_user = User::where('email', 'commons@libretexts.org')->first(); - $commons_courses = DB::table('courses') - ->join('users', 'courses.user_id', '=', 'users.id') - ->join('schools', 'courses.school_id', '=', 'schools.id') - ->where('courses.user_id', $commons_user->id) - ->where('shown', 1) - ->select('courses.id', - 'courses.name AS name', - 'courses.public_description AS description', - 'schools.name AS school', - DB::raw("CONCAT(users.first_name, ' ',users.last_name) AS instructor"), - 'alpha', - 'anonymous_users') - ->get(); - $response['commons_courses'] = $commons_courses; - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to see get the courses from the Commons. Please try again or contact us for assistance."; - } - return $response; - } - - public - function updateBetaApprovalNotifications(Course $course) - { - - $response['type'] = 'error'; - $authorized = Gate::inspect('updateBetaApprovalNotifications', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - - try { - $course->beta_approval_notifications = !$course->beta_approval_notifications; - $course->save(); - $message_text = $course->beta_approval_notifications ? "now" : "no longer"; - $response['type'] = 'info'; - $response['message'] = "You will $message_text receive daily email notifications of pending approvals."; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to see whether this course is an Alpha course. Please try again or contact us for assistance."; - } - return $response; - - } - - public - function getBetaApprovalNotifications(Course $course) - { - - $response['type'] = 'error'; - try { - $response['beta_approval_notifications'] = $course->beta_approval_notifications; - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to see whether this course is an Alpha course. Please try again or contact us for assistance."; - } - return $response; - - - } - - /** - * @param Course $course - * @return array - * @throws Exception - */ - public - function getWarnings(Course $course): array - { - try { - $response['alpha'] = $course->alpha; - $response['formative'] = $course->formative; - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to get the course warnings. Please try again or contact us for assistance."; - } - return $response; - - } - - public - function isAlpha(Course $course) - { - try { - $response['alpha'] = $course->alpha; - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to see whether this course is an Alpha course. Please try again or contact us for assistance."; - } - return $response; - - } - - public - function getLastSchool(Request $request, School $school) - { - $response['type'] = 'error'; - try { - $school_name = ''; - $school_id = 1; - if ($request->user()->role === 2) { - $school = DB::table('courses') - ->join('schools', 'courses.school_id', '=', 'schools.id') - ->where('user_id', $request->user()->id) - ->orderBy('courses.created_at', 'desc') - ->first(); - if ($school && ($school->school_id !== 1)) { - $school_name = $school->name; - $school_id = $school->school_id; - } - } - $response['last_school_name'] = $school_name; - $response['last_school_id'] = $school_id; - $response['type'] = 'success'; - } catch (Exception $e) { - DB::rollback(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to get your last school. Please try again or contact us for assistance."; - } - return $response; - } - - /** - * @param Course $course - * @param User|null $instructor - * @return array - * @throws Exception - */ - public - function getPublicCourses(Course $course, User $instructor = null): array - { - - $response['type'] = 'error'; - try { - $public_courses = []; - switch ($instructor) { - case(true): - $public_courses = $course->where('public', 1) - ->where('user_id', $instructor->id) - ->select('id', 'name') - ->orderBy('name') - ->get(); - break; - case(false): - $public_courses = $course->publicCourses(); - break; - - } - $response['public_courses'] = $public_courses; - $response['type'] = 'success'; - - } catch (Exception $e) { - DB::rollback(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to get the public courses. Please try again or contact us for assistance."; - } - return $response; - } - - /** - * @param Request $request - * @return array - * @throws Exception - */ - public - function getCoursesAndNonBetaAssignments(Request $request) - { - - $response['type'] = 'error'; - $courses = []; - $assignments = []; - try { - $results = DB::table('courses') - ->join('assignments', 'courses.id', '=', 'assignments.course_id') - ->leftJoin('beta_assignments', 'assignments.id', '=', 'beta_assignments.id') - ->where('courses.user_id', $request->user()->id) - ->select(DB::raw('courses.id AS course_id'), - DB::raw('courses.name AS course_name'), - 'courses.start_date', - 'courses.end_date', - 'beta_assignments.id AS beta_assignment_id', - DB::raw('assignments.id AS assignment_id'), - DB::raw('assignments.name AS assignment_name')) - ->orderBy('courses.start_date', 'desc') - ->get(); - $course_ids = []; - foreach ($results as $value) { - $course_id = $value->course_id; - if (!in_array($course_id, $course_ids)) { - $courses[] = ['value' => $course_id, - 'text' => $value->course_name, - 'start_date' => $value->start_date, - 'end_date' => $value->end_date]; - $course_ids[] = $course_id; - } - if (!$value->beta_assignment_id) { - $assignments[$course_id][] = ['value' => $value->assignment_id, - 'text' => $value->assignment_name]; - } - } - - $response['type'] = 'success'; - $response['courses'] = $courses; - $response['assignments'] = $assignments; - } catch (Exception $e) { - DB::rollback(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to get your courses and assignments. Please try again or contact us for assistance."; - } - return $response; - - } - - /** - * @param Enrollment $enrollment - * @param Course $course - * @return array - * @throws Exception - */ - public - function getEnrolledInCoursesAndAssignments(Enrollment $enrollment, Course $course): array - { - - $response['type'] = 'error'; - $authorized = Gate::inspect('view', $enrollment); - - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - $enrollments = $enrollment->index(); - $enrolled_in_courses_and_assignments = []; - foreach ($enrollments as $key => $enrollment) { - $enrolled_in_courses_and_assignments[$key] = []; - $enrolled_in_courses_and_assignments[$key]['course'] = $enrollment; - $course = Course::find($enrollment->id); - $enrolled_in_courses_and_assignments[$key]['assignments'] = $course->assignedToAssignmentsByUser(); - } - - try { - $response['enrolled_in_courses_and_assignments'] = $enrolled_in_courses_and_assignments; - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error getting your enrolled courses and assignments. Please try again or contact us for assistance."; - } - return $response; - - } - - public - function getCoursesAndAssignments(Request $request) - { - - $response['type'] = 'error'; - $courses = []; - $assignments = []; - try { - $results = DB::table('courses') - ->join('assignments', 'courses.id', '=', 'assignments.course_id') - ->where('courses.user_id', $request->user()->id) - ->select(DB::raw('courses.id AS course_id'), - DB::raw('courses.name AS course_name'), - 'courses.lms', - 'assignments.lms_resource_link_id', - 'assignments.assessment_type', - DB::raw('assignments.id AS assignment_id'), - DB::raw('assignments.name AS assignment_name')) - ->orderBy('courses.start_date', 'desc') - ->get(); - $course_ids = []; - foreach ($results as $value) { - $course_id = $value->course_id; - if (!in_array($course_id, $course_ids)) { - $courses[] = ['value' => $course_id, - 'text' => $value->course_name, - 'lms' => $value->lms]; - $course_ids[] = $course_id; - } - $assignments[$course_id][] = ['value' => $value->assignment_id, - 'text' => $value->assignment_name, - 'lms_resource_link_id' => $value->lms_resource_link_id, - 'assessment_type' => $value->assessment_type]; - } - - $response['type'] = 'success'; - $response['courses'] = $courses; - $response['assignments'] = $assignments; - } catch (Exception $e) { - DB::rollback(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "We were not able to get your courses and assignments. Please try again or contact us for assistance."; - } - return $response; - - } - - /** - * @param Request $request - * @param Course $course - * @param AssignmentGroup $assignmentGroup - * @param AssignmentGroupWeight $assignmentGroupWeight - * @param AssignmentSyncQuestion $assignmentSyncQuestion - * @param Enrollment $enrollment - * @param FinalGrade $finalGrade - * @param Section $section - * @param School $school - * @param BetaCourse $betaCourse - * @return array - * @throws Exception ' - */ - public - function import(Request $request, - Course $course, - AssignmentGroup $assignmentGroup, - AssignmentGroupWeight $assignmentGroupWeight, - AssignmentSyncQuestion $assignmentSyncQuestion, - Enrollment $enrollment, - FinalGrade $finalGrade, - Section $section, - School $school, - BetaCourse $betaCourse): array - { - - $response['type'] = 'error'; - - $authorized = Gate::inspect('import', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - - if (!in_array($request->action, ['import', 'clone'])) { - $response['message'] = "$request->action should either be to import or clone."; - return $response; - } - $import_as_beta = (int)$request->import_as_beta; - - if ($import_as_beta && !$course->alpha) { - $response['message'] = "You cannot $request->action this course as a Beta course since the original course is not an Alpha course."; - return $response; - } - $school = $this->getLastSchool($request, $school); - try { - DB::beginTransaction(); - $imported_course = $course->replicate(); - $action = $request->action === 'import' ? "Import" : "Copy"; - $imported_course->name = "$imported_course->name " . $action; - $imported_course->start_date = Carbon::now()->startOfDay(); - $imported_course->end_date = Carbon::now()->startOfDay()->addMonths(3); - $imported_course->shown = 0; - $imported_course->public = 0; - $imported_course->alpha = 0; - $imported_course->lms = 0; - $imported_course->anonymous_users = 0; - $imported_course->school_id = $school['last_school_id']; - $imported_course->show_z_scores = 0; - $imported_course->students_can_view_weighted_average = 0; - $imported_course->user_id = $request->user()->id; - $imported_course->order = 0; - $imported_course->save(); - if ($import_as_beta) { - $betaCourse->id = $imported_course->id; - $betaCourse->alpha_course_id = $course->id; - $betaCourse->save(); - } - foreach ($course->assignments as $assignment) { - $imported_assignment = $this->cloneAssignment($assignmentGroup, $imported_course, $assignment, $assignmentGroupWeight, $course); - if ($import_as_beta) { - BetaAssignment::create([ - 'id' => $imported_assignment->id, - 'alpha_assignment_id' => $assignment->id - ]); - } - $default_timing = DB::table('assign_to_timings') - ->join('assign_to_groups', 'assign_to_timings.id', '=', 'assign_to_groups.assign_to_timing_id') - ->where('assignment_id', $assignment->id) - ->first(); - - $assignment->saveAssignmentTimingAndGroup($imported_assignment, $default_timing); - $assignmentSyncQuestion->importAssignmentQuestionsAndLearningTrees($assignment->id, $imported_assignment->id); - } - - $this->prepareNewCourse($section, $imported_course, $course, $enrollment, $finalGrade); - $fake_user = DB::table('enrollments') - ->join('users', 'enrollments.user_id', '=', 'users.id') - ->where('course_id', $imported_course->id) - ->where('fake_student', 1) - ->first(); - - $assign_to_timings = DB::table('assign_to_timings') - ->whereIn('assignment_id', $imported_course->assignments->pluck('id')->toArray()) - ->get(); - foreach ($assign_to_timings as $assign_to_timing) { - $assignToUser = new AssignToUser(); - $assignToUser->assign_to_timing_id = $assign_to_timing->id; - $assignToUser->user_id = $fake_user->id; - $assignToUser->save(); - } - DB::commit(); - $response['type'] = 'success'; - $response['message'] = "$imported_course->name has been created.

Don't forget to change the dates associated with this course and all of its assignments."; - - } catch (Exception $e) { - DB::rollback(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error creating the $request->action. Please try again or contact us for assistance."; - } - return $response; - - - } - - public - function reOrderAllCourses() - { - $courses = $this->getCourses(Auth::user()); - $all_course_ids = []; - if ($courses) { - foreach ($courses as $value) { - $all_course_ids[] = $value->id; - } - $course = new Course(); - $course->orderCourses($all_course_ids); - } - } - - /** - * @param Request $request - * @param Course $course - * @return array - * @throws Exception - */ - public - function getImportable(Request $request, Course $course) - { - $response['type'] = 'error'; - - $authorized = Gate::inspect('getImportable', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - try { - $instructor_courses = DB::table('courses') - ->join('users', 'courses.user_id', '=', 'users.id') - ->where('user_id', $request->user()->id) - ->select('name', - DB::raw('CONCAT(first_name, " " , last_name) AS instructor'), - 'courses.id', - 'term') - ->get(); - $public_courses = $course->publicCourses(); - - $importable_courses = []; - foreach ($instructor_courses as $course) { - $importable_courses[] = $course; - } - foreach ($public_courses as $course) { - $importable_courses[] = $course; - } - $formatted_importable_courses = []; - $formatted_course_ids = []; - $formatted_course_names = []; - foreach ($importable_courses as $course) { - if (!in_array($course->id, $formatted_course_ids)) { - $formatted_course = "$course->name --- $course->instructor"; - if (in_array($formatted_course, $formatted_course_names)) { - $formatted_course = "$course->name ($course->term) --- $course->instructor"; - } - $formatted_importable_courses[] = [ - 'course_id' => $course->id, - 'formatted_course' => $formatted_course - ]; - $formatted_course_ids[] = $course->id; - $formatted_course_names[] = $formatted_course; - } - - } - - usort($formatted_importable_courses, function ($item1, $item2) { - return $item1['formatted_course'] <=> $item2['formatted_course']; - }); - - $response['type'] = 'success'; - $response['importable_courses'] = $formatted_importable_courses; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error retrieving the importable courses. Please try again or contact us for assistance."; - } - return $response; - - } - - /** - * @param Request $request - * @param Course $course - * @return array - * @throws Exception - */ - public - function index(Request $request, Course $course) - { - - $response['type'] = 'error'; - - - if ($request->session()->get('completed_sso_registration')) { - \Log::info('Just finished registration.'); - } - $authorized = Gate::inspect('viewAny', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - try { - $response['courses'] = $this->getCourses(auth()->user()); - $response['show_beta_course_dates_warning'] = !$request->hasCookie('show_beta_course_dates_warning'); - - $response['type'] = 'success'; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error retrieving your courses. Please try again or contact us for assistance."; - } - return $response; - - } - - /** - * @param Request $request - * @param Course $course - * @param AssignmentGroupWeight $assignmentGroupWeight - * @return array - * @throws Exception - */ - public - function updateShowZScores(Request $request, Course $course, AssignmentGroupWeight $assignmentGroupWeight): array - { - $response['type'] = 'error'; - $authorized = Gate::inspect('updateShowZScores', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - $response = $assignmentGroupWeight->validateCourseWeights($course); - if ($response['type'] === 'error') { - return $response; - } - try { - - $course->show_z_scores = !$request->show_z_scores; - $course->save(); - - $verb = $course->show_z_scores ? "can" : "cannot"; - $response['type'] = $course->show_z_scores ? 'success' : 'info'; - $response['message'] = "Students $verb view their z-scores."; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error updating the ability for students to view their z-scores. Please try again or contact us for assistance."; - } - return $response; - - - } - - /** - * @param Request $request - * @param Course $course - * @return array - * @throws Exception - */ - public - function updateShowProgressReport(Request $request, Course $course): array - { - $response['type'] = 'error'; - $authorized = Gate::inspect('updateShowProgressReport', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - - try { - - $course->show_progress_report = !$request->show_progress_report; - $course->save(); - - $verb = $course->show_progress_report ? "can" : "cannot"; - $response['type'] = $course->show_progress_report ? 'success' : 'info'; - $response['message'] = "Students $verb view their progress reports."; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error updating the ability for students to view their progress_reports. Please try again or contact us for assistance."; - } - return $response; - - - } - - /** - * @param Course $course - * @return array - * @throws Exception - */ - public - function showOpen(Course $course) - { - - $response['type'] = 'error'; - $authorized = Gate::inspect('viewOpen', $course); - if (!$authorized->allowed()) { - - $response['message'] = $authorized->message(); - return $response; - } - - try { - $response['open_course'] = [ - 'id' => $course->id, - 'name' => $course->name, - 'alpha' => $course->alpha]; - $response['type'] = 'success'; - - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error retrieving this open course. Please try again or contact us for assistance."; - } - return $response; - - } - - public - function updateStudentsCanViewWeightedAverage(Request $request, Course $course, AssignmentGroupWeight $assignmentGroupWeight) - { - $response['type'] = 'error'; - $authorized = Gate::inspect('updateStudentsCanViewWeightedAverage', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - try { - $response = $assignmentGroupWeight->validateCourseWeights($course); - if ($response['type'] === 'error') { - return $response; - } - $course->students_can_view_weighted_average = !$request->students_can_view_weighted_average; - $course->save(); - - $verb = $course->students_can_view_weighted_average ? "can" : "cannot"; - $response['type'] = $course->students_can_view_weighted_average ? 'success' : 'info'; - $response['message'] = "Students $verb view their weighted averages."; - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error updating the ability for students to view their weighted averages. Please try again or contact us for assistance."; - } - return $response; - - - } - - /** - * @param Course $course - * @return array - * @throws Exception - */ - public - function show(Course $course): array - { - - $response['type'] = 'error'; - $authorized = Gate::inspect('view', $course); - if (!$authorized->allowed()) { - - $response['message'] = $authorized->message(); - return $response; - } - try { - $question_exists_not_owned_by_the_instructor = DB::table('assignment_question') - ->join('questions', 'assignment_question.question_id', '=', 'questions.id') - ->whereIn('assignment_id', $course->assignments()->pluck('id')->toArray()) - ->where('question_editor_user_id', '<>', $course->user_id) - ->first(); - $response['course'] = [ - 'school' => $course->school->name, - 'name' => $course->name, - 'public_description' => $course->public_description, - 'private_description' => $course->private_description, - 'textbook_url' => $course->textbook_url, - 'term' => $course->term, - 'students_can_view_weighted_average' => $course->students_can_view_weighted_average, - 'letter_grades_released' => $course->finalGrades->letter_grades_released, - 'sections' => $course->sections, - 'show_z_scores' => $course->show_z_scores, - 'graders' => $course->graderInfo(), - 'start_date' => $course->start_date, - 'end_date' => $course->end_date, - 'public' => $course->public, - 'lms' => $course->lms, - 'question_numbers_shown_in_iframe' => (bool)$course->question_numbers_shown_in_iframe, - 'show_progress_report' => $course->show_progress_report, - 'owns_all_questions' => !$question_exists_not_owned_by_the_instructor, - 'alpha' => $course->alpha, - 'anonymous_users' => $course->anonymous_users, - 'formative' => $course->formative, - 'contact_grader_override' => $course->contactGraderOverride(), - 'is_beta_course' => $course->isBetaCourse(), - 'beta_courses_info' => $course->betaCoursesInfo()]; - $response['type'] = 'success'; - - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error retrieving your course. Please try again or contact us for assistance."; - } - return $response; - - } - - /** - * @param Course $course - * @param int $shown - * @return array - * @throws Exception - */ - public - function showCourse(Course $course, int $shown): array - { - - $response['type'] = 'error'; - $authorized = Gate::inspect('showCourse', $course); - - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - - try { - DB::beginTransaction(); - $course->shown = !$shown; - $course->save(); - - $response['type'] = !$shown ? 'success' : 'info'; - $shown_message = !$shown ? 'can' : 'cannot'; - $is_commons_user = Auth::user()->email === 'commons@libretexts.org'; - $access_code_message = !$shown || $is_commons_user ? '' : ' In addition, all course access codes have been revoked.'; - $people = $is_commons_user ? "Visitors to the Commons " : "Your students"; - $response['message'] = "$people {$shown_message} view this course.{$access_code_message}"; - DB::commit(); - } catch (Exception $e) { - DB::rollback(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error showing {$course->name}. Please try again or contact us for assistance."; - } - return $response; - } - - /** - * @param $user - * @return array|\Illuminate\Support\Collection - */ - public - function getCourses($user) - { - - switch ($user->role) { - case(6): - return DB::table('tester_courses') - ->join('courses', 'tester_courses.course_id', '=', 'courses.id') - ->join('users', 'courses.user_id', '=', 'users.id') - ->where('tester_courses.user_id', $user->id) - ->select('courses.id', - 'term', - 'start_date', - 'end_date', - 'courses.name', - DB::raw('CONCAT(first_name, " ", last_name) AS instructor')) - ->get(); - case(5): - case(2): - return DB::table('courses') - ->select('courses.*', DB::raw("beta_courses.id IS NOT NULL AS is_beta_course")) - ->leftJoin('beta_courses', 'courses.id', '=', 'beta_courses.id') - ->where('user_id', $user->id) - ->orderBy('order') - ->get(); - case(4): - $sections = DB::table('graders') - ->join('sections', 'section_id', '=', 'sections.id') - ->where('user_id', $user->id) - ->get() - ->pluck('section_id'); - - $course_section_info = DB::table('courses') - ->join('sections', 'courses.id', '=', 'sections.course_id') - ->select('courses.id AS id', - DB::raw('courses.id AS course_id'), - 'start_date', - 'end_date', - DB::raw('courses.name AS course_name'), - DB::raw('sections.name AS section_name') - ) - ->whereIn('sections.id', $sections)->orderBy('start_date', 'desc') - ->get(); - - $course_sections = []; - foreach ($course_section_info as $course_section) { - if (!isset($course_sections[$course_section->course_id])) { - $course_sections[$course_section->course_id]['id'] = $course_section->course_id; - $course_sections[$course_section->course_id]['name'] = $course_section->course_name; - $course_sections[$course_section->course_id]['start_date'] = $course_section->start_date; - $course_sections[$course_section->course_id]['end_date'] = $course_section->end_date; - $course_sections[$course_section->course_id]['sections'] = []; - } - $course_sections[$course_section->course_id]['sections'][] = $course_section->section_name; - } - - foreach ($course_sections as $key => $course_section) { - $course_sections[$key]['sections'] = implode(', ', $course_section['sections']); - } - $course_sections = array_values($course_sections); - return collect($course_sections); - - } - } - - /** - * @param StoreCourse $request - * @param Course $course - * @param Enrollment $enrollment - * @param FinalGrade $finalGrade - * @param Section $section - * @param School $school - * @return array - * @throws Exception - */ - - public - function store(StoreCourse $request, - Course $course, - Enrollment $enrollment, - FinalGrade $finalGrade, - Section $section, - School $school): array - { - //todo: check the validation rules - $response['type'] = 'error'; - $authorized = Gate::inspect('create', $course); - - if (!$authorized->allowed()) { - - $response['message'] = $authorized->message(); - return $response; - } - $is_instructor = $request->user()->role === 2; - try { - $data = $request->validated(); - DB::beginTransaction(); - if (!$is_instructor) { - $data['start_date'] = date("Y-m-d"); - $datetime = new DateTime('+3 months'); - $data['end_date'] = $datetime->format("Y-m-d"); - $data['crn'] = 'N/A'; - $data['section'] = 'N/A'; - $data['term'] = 'N/A'; - $data['alpha'] = 0; - $data['anonymous_users'] = 0; - } - $data['user_id'] =$request->user()->id; - $data['school_id'] = $is_instructor ? $this->getSchoolIdFromRequest($request, $school) : 1; - $formative = isset($data['formative']) && $data['formative']; - if ($formative) { - $data['start_date'] = $data['end_date'] = date('Y-m-d', time()); - $data['lms'] = 0; - $data['alpha'] = 0; - } - - $data['start_date'] = $this->convertLocalMysqlFormattedDateToUTC($data['start_date'] . '00:00:00', auth()->user()->time_zone); - $data['end_date'] = $this->convertLocalMysqlFormattedDateToUTC($data['end_date'] . '00:00:00', auth()->user()->time_zone); - - $data['shown'] = 0; - $data['public_description'] = $request->public_description; - $data['private_description'] = $request->private_description; - $data['order'] = 0; - //create the main section - $section->name = $formative ? 'Default' : $data['section']; - $section->crn = $formative ? '' : $data['crn']; - unset($data['section']); - unset($data['crn']); - unset($data['school']); - //create the course - - - $new_course = $course->create($data); - - $section->course_id = $new_course->id; - $section->save(); - $course->enrollFakeStudent($new_course->id, $section->id, $enrollment); - $finalGrade->setDefaultLetterGrades($new_course->id); - - $this->reOrderAllCourses(); - - DB::commit(); - $response['type'] = 'success'; - $response['message'] = "The course $request->name has been created."; - } catch (Exception $e) { - DB::rollback(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error creating $request->name. Please try again or contact us for assistance."; - } - - return $response; - } - - public - function getSchoolIdFromRequest(Request $request, School $school) - { - - return $request->school - ? $school->where('name', $request->school)->first()->id - : $school->first()->id; - } - - /** - * - * Update the specified resource in storage. - * - * - * @param StoreCourse $request - * @param Course $course - * @param School $school - * @param BetaCourse $betaCourse - * @return array - * @throws Exception - */ - public - function update(StoreCourse $request, - Course $course, - School $school, - BetaCourse $betaCourse): array - { - $response['type'] = 'error'; - - $authorized = Gate::inspect('update', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - $is_beta_course = $betaCourse->where('id', $course->id)->first(); - if ($message = $this->failsTetherCourseValidation($request, $course, $is_beta_course)) { - $response['message'] = $message; - return $response; - } - try { - $data = $request->validated(); - DB::beginTransaction(); - - $data['public_description'] = $request->public_description; - $data['private_description'] = $request->private_description; - if ($request->user()->role === 2) { - $data['school_id'] = $this->getSchoolIdFromRequest($request, $school); - if (!$request->formative) { - $data['start_date'] = $this->convertLocalMysqlFormattedDateToUTC($data['start_date'], auth()->user()->time_zone); - $data['end_date'] = $this->convertLocalMysqlFormattedDateToUTC($data['end_date'], auth()->user()->time_zone); - } - $data['textbook_url'] = $request->textbook_url; - if ($is_beta_course && $request->untether_beta_course) { - $betaCourse->untether($course); - } - unset($data['school']); - } - $course->update($data); - DB::commit(); - $response['type'] = 'success'; - $response['message'] = "The course $course->name has been updated."; - $response['is_beta_course'] = $betaCourse->where('id', $course->id)->first(); - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error updating $course->name. Please try again or contact us for assistance."; - } - return $response; - } - - /** - * @param $request - * @param $course - * @param $is_beta_course - * @return string - */ - public - function failsTetherCourseValidation($request, $course, $is_beta_course): string - { - $message = ''; - $at_least_one_beta_course_exists = BetaCourse::where('alpha_course_id', $course->id)->first(); - if ($course->alpha && (int)$request->alpha === 0 && $at_least_one_beta_course_exists) { - $message = "You are trying to change an Alpha course into a non-Alpha course but Beta courses are currently tethered to this course."; - } - if ((int)$request->alpha === 1 && $is_beta_course) { - $message = "You can't change a Beta course into an Alpha course."; - } - return $message; - } - - /** - * - * Delete a course - * - * @param DestroyCourse $request - * @param Course $course - * @param AssignToTiming $assignToTiming - * @param BetaAssignment $betaAssignment - * @param BetaCourse $betaCourse - * @param BetaCourseApproval $betaCourseApproval - * @return array - * @throws Exception - */ - - public - function destroy(DestroyCourse $request, - Course $course, - AssignToTiming $assignToTiming, - BetaAssignment $betaAssignment, - BetaCourse $betaCourse, - BetaCourseApproval $betaCourseApproval): array - - { - - - $response['type'] = 'error'; - - $authorized = Gate::inspect('delete', $course); - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - $request->validated(); - if (BetaCourse::where('alpha_course_id', $course->id)->first()) { - $response['message'] = "You cannot delete an Alpha course with tethered Beta courses."; - return $response; - } - - try { - DB::beginTransaction(); - foreach ($course->assignments as $assignment) { - $assignment_question_ids = DB::table('assignment_question') - ->where('assignment_id', $assignment->id) - ->get() - ->pluck('id'); - - DB::table('assignment_question_learning_tree') - ->whereIn('assignment_question_id', $assignment_question_ids) - ->delete(); - $assignToTiming->deleteTimingsGroupsUsers($assignment); - $assignment->questions()->detach(); - $assignment->submissions()->delete(); - $assignment->fileSubmissions()->delete(); - $assignment->scores()->delete(); - $assignment->canGiveUps()->delete(); - $assignment->cutups()->delete(); - $assignment->seeds()->delete(); - DB::table('randomized_assignment_questions') - ->where('assignment_id', $assignment->id) - ->delete(); - $assignment->graders()->detach(); - $betaAssignment->where('id', $assignment->id)->delete(); - - DB::table('question_level_overrides')->where('assignment_id', $assignment->id)->delete(); - DB::table('compiled_pdf_overrides')->where('assignment_id', $assignment->id)->delete(); - DB::table('assignment_level_overrides')->where('assignment_id', $assignment->id)->delete(); - - DB::table('learning_tree_time_lefts')->where('assignment_id', $assignment->id)->delete(); - DB::table('learning_tree_successful_branches')->where('assignment_id', $assignment->id)->delete(); - DB::table('remediation_submissions')->where('assignment_id', $assignment->id)->delete(); - DB::table('assignment_question_time_on_tasks')->where('assignment_id', $assignment->id)->delete(); - DB::table('review_histories')->where('assignment_id', $assignment->id)->delete(); - DB::table('shown_hints')->where('assignment_id', $assignment->id)->delete(); - DB::table('submission_confirmations')->where('assignment_id', $assignment->id)->delete(); - $betaCourseApproval->where('beta_assignment_id', $assignment->id)->delete(); - DeleteAssignmentDirectoryFromS3::dispatch($assignment->id); - } - DB::table('grader_notifications') - ->where('course_id', $course->id) - ->delete(); - $course->extensions()->delete(); - $course->assignments()->delete(); - - - AssignmentGroupWeight::where('course_id', $course->id)->delete(); - AssignmentGroup::where('course_id', $course->id)->where('user_id', Auth::user()->id)->delete();//get rid of the custom assignment groups - $course->enrollments()->delete(); - foreach ($course->sections as $section) { - $section->graders()->delete(); - $section->delete(); - } - - $course->finalGrades()->delete(); - $betaCourse->where('id', $course->id)->delete(); - DB::table('analytics_dashboards')->where('course_id', $course->id)->delete(); - DB::table('contact_grader_overrides')->where('course_id', $course->id)->delete(); - $course->delete(); - DB::commit(); - $response['type'] = 'info'; - $response['message'] = "The course $course->name has been deleted."; - } catch (Exception $e) { - DB::rollBack(); - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error removing $course->name. Please try again or contact us for assistance."; - } - return $response; - } - - /** - * @param Course $course - * @param string $operator_text - * @param int $num_days - * @return array - * @throws Exception - */ - public - function getCoursesToReset(Course $course, string $operator_text, int $num_days): array - { - $response['type'] = 'error'; - $authorized = Gate::inspect('getConcludedCourses', $course); - - if (!$authorized->allowed()) { - $response['message'] = $authorized->message(); - return $response; - } - try { - $response['type'] = 'success'; - $response['courses_to_reset'] = $course->concludedCourses($operator_text, $num_days); - - } catch (Exception $e) { - $h = new Handler(app()); - $h->report($e); - $response['message'] = "There was an error getting the hundred day courses. Please try again or contact us for assistance."; - } - return $response; - } - - /** - * @param Section $section - * @param Course $new_course - * @param Course $course - * @param Enrollment $enrollment - * @param FinalGrade $finalGrade - * @return void - */ - public - function prepareNewCourse(Section $section, - Course $new_course, - Course $course, - Enrollment $enrollment, - FinalGrade $finalGrade) - { - $section->name = 'Main'; - $section->course_id = $new_course->id; - $section->crn = "To be determined"; - $section->save(); - $course->enrollFakeStudent($new_course->id, $section->id, $enrollment); - $finalGrade->setDefaultLetterGrades($new_course->id); - $this->reorderAllCourses(); - - } - - /** - * @param AssignmentGroup $assignmentGroup - * @param Course $cloned_course - * @param $assignment - * @param AssignmentGroupWeight $assignmentGroupWeight - * @param Course $course - * @return mixed - */ - public - function cloneAssignment(AssignmentGroup $assignmentGroup, Course $cloned_course, $assignment, AssignmentGroupWeight $assignmentGroupWeight, Course $course) - { - $cloned_assignment_group_id = $assignmentGroup->importAssignmentGroupToCourse($cloned_course, $assignment); - $assignmentGroupWeight->importAssignmentGroupWeightToCourse($course, $cloned_course, $cloned_assignment_group_id, false); - $cloned_assignment = $assignment->replicate(); - $cloned_assignment->course_id = $cloned_course->id; - $cloned_assignment->shown = 0; - if ($cloned_assignment->assessment_type !== 'real time') { - $cloned_assignment->solutions_released = 0; - } - if ($cloned_assignment->assessment_type === 'delayed') { - $cloned_assignment->show_scores = 0; - } - $cloned_assignment->students_can_view_assignment_statistics = 0; - $cloned_assignment->assignment_group_id = $cloned_assignment_group_id; - $cloned_assignment->lms_resource_link_id = null; - $cloned_assignment->save(); - return $cloned_assignment; - } - -} diff --git a/app/Policies/CoursePolicy.php b/app/Policies/CoursePolicy.php deleted file mode 100644 index cefc69544..000000000 --- a/app/Policies/CoursePolicy.php +++ /dev/null @@ -1,489 +0,0 @@ -role, [2, 5]) - ? Response::allow() - : Response::deny('You are not allowed to get the courses and assignments.'); - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function storeTester(User $user, Course $course): Response - { - return $user->id === $course->user_id - ? Response::allow() - : Response::deny('You are not allowed to add testers to this course.'); - - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function getTesters(User $user, Course $course): Response - { - return $user->id === $course->user_id - ? Response::allow() - : Response::deny('You are not allowed to get the testers for this course.'); - - } - - public function getCommonsCoursesAndAssignments(User $user): Response - { - return $user->role === 5 - ? Response::allow() - : Response::deny('You are not allowed to get the Commons courses and assignments.'); - - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function reset(User $user, Course $course): Response - { - return (int)$course->user_id === $user->id || Helper::isAdmin() - ? Response::allow() - : Response::deny('You are not allowed to reset that course.'); - } - - public function getConcludedCourses(User $user, Course $course): Response - { - return Helper::isAdmin() - ? Response::allow() - : Response::deny('You are not allowed to get the the courses to unenroll.'); - - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function getAssignmentsForAnonymousUser(User $user, Course $course): Response - { - switch ($user->role) { - case(2): - $has_access = ($course->public || Helper::isCommonsCourse($course)) && Helper::hasAnonymousUserSession(); - break; - case(3): - $has_access = $course->anonymous_users && Helper::isAnonymousUser(); - break; - default: - $has_access = false; - } - return $has_access - ? Response::allow() - : Response::deny('You are not allowed to view these assignments.'); - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function updateIFrameProperties(User $user, Course $course): Response - { - return ((int)$course->user_id === (int)$user->id) - ? Response::allow() - : Response::deny('You are not allowed to update what is shown in the iframe.'); - } - - /** - * @param User $user - * @param $courses - * @param $ordered_courses - * @return Response - */ - public function order(User $user, $courses, $ordered_courses): Response - { - $owner_courses = DB::table('courses') - ->where('user_id', $user->id) - ->select('id') - ->pluck('id') - ->toArray(); - $has_access = true; - foreach ($ordered_courses as $ordered_course) { - if (!in_array($ordered_course, $owner_courses)) { - $has_access = false; - } - } - return $has_access - ? Response::allow() - : Response::deny('You are not allowed to re-order a course that is not yours.'); - } - - public function getAssignmentNamesForPublicCourse(User $user, Course $course): Response - { - return $user->role === 2 && $course->public - ? Response::allow() - : Response::deny('You are not allowed to access the assignments in that course.'); - - - } - - public function updateBetaApprovalNotifications(User $user, Course $course): Response - { - return ((int)$course->user_id === (int)$user->id) - ? Response::allow() - : Response::deny('You are not allowed to update the Beta course notifications for this course.'); - - } - - public function courseAccessForGraders(User $user, Course $course): Response - { - return ((int)$course->user_id === (int)$user->id) - ? Response::allow() - : Response::deny('You are not allowed to grant access to all assignments for all graders for this course.'); - } - - public function getAssignmentOptions(User $user, Course $course): Response - { - - return ((int)$course->user_id === (int)$user->id) - ? Response::allow() - : Response::deny('You are not allowed to download the assignment options.'); - } - - public function copy(User $user, Course $course): Response - { - return (int)$course->user_id === (int)$user->id - ? Response::allow() - : Response::deny('You are not allowed to copy a course you do not own.'); - - } - - - public function import(User $user, Course $course): Response - { - - $owner_of_course = (int)$course->user_id === (int)$user->id; - $is_public = (int)$course->public === 1; - $has_role_that_can_import = in_array($user->role, [2, 5]); - $is_non_instructor_question_editor = (int)$user->role === 5; - return ( $has_role_that_can_import && ($owner_of_course || $is_public)) || ($owner_of_course && $is_non_instructor_question_editor) - ? Response::allow() - : Response::deny('You are not allowed to import that course.'); - - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function getImportable(User $user, Course $course): Response - { - - return in_array($user->role, [2, 5]) - ? Response::allow() - : Response::deny('You are not allowed to retrieve the importable courses.'); - - } - - /** - * @param User $user - * @param Course $course - * @param int $student_user_id - * @return Response - */ - public - function loginAsStudentInCourse(User $user, Course $course, int $student_user_id): Response - { - $student_enrolled_in_course = $course->enrollments->contains('user_id', $student_user_id); - switch ($user->role) { - case(2): - $has_access = ($course->user_id === (int)$user->id); - break; - case(4): - $has_access = $course->isGrader(); - break; - case(6): - $has_course_access = DB::table('tester_courses') - ->where('user_id', $user->id) - ->where('course_id', $course->id) - ->first(); - $has_student_access = DB::table('tester_students') - ->where('tester_user_id', $user->id) - ->where('student_user_id', $student_user_id) - ->first(); - $has_access = $has_course_access && $has_student_access; - break; - default: - $has_access = false; - } - - //check if the student is in their course. - return ($student_enrolled_in_course && $has_access) - ? Response::allow() - : Response::deny('You are not allowed to log in as this student.'); - } - - /** - * Determine whether the user can view any courses. - * - * @param User $user - * @return mixed - */ - public function viewAny(User $user) - { - return ($user->role !== 3) - ? Response::allow() - : Response::deny('You are not allowed to view courses.'); - } - - /** - * Determine whether the user can view any courses. - * - * @param User $user - * @return mixed - */ - public function viewCourseScores(User $user, Course $course) - { - - return ($course->isGrader() || $this->ownsCourseByUser($course, $user)) - ? Response::allow() - : Response::deny('You are not allowed to view these scores.'); - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function viewCourseScoresByUser(User $user, Course $course): Response - { - return $course->enrollments->contains('user_id', $user->id) - ? Response::allow() - : Response::deny('You are not allowed to view these scores.'); - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function updateStudentsCanViewWeightedAverage(User $user, Course $course): Response - { - return ($this->ownsCourseByUser($course, $user)) - ? Response::allow() - : Response::deny('You are not allowed to update being able to view the weighted average.'); - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function updateShowZScores(User $user, Course $course): Response - { - return ($this->ownsCourseByUser($course, $user)) - ? Response::allow() - : Response::deny('You are not allowed to update being able to view the z-scores.'); - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function updateShowProgressReport(User $user, Course $course): Response - { - return ($this->ownsCourseByUser($course, $user)) - ? Response::allow() - : Response::deny('You are not allowed to update being able to view the progress report.'); - } - - - /** - * Determine whether the user can view the course. - * - * @param User $user - * @param Course $course - * @return mixed - */ - public function view(User $user, Course $course): Response - { - switch ($user->role) { - case(6): - $has_access = DB::table('tester_courses') - ->where('course_id', $course->id) - ->where('user_id', $user->id) - ->first(); - break; - case(5): - case(2): - $has_access = $this->ownsCourseByUser($course, $user); - break; - case(3): - { - $has_access = $course->enrollments->contains('user_id', $user->id); - break; - } - case(4): - { - $has_access = $course->isGrader(); - break; - } - default: - $has_access = false; - } - return $has_access - ? Response::allow() - : Response::deny('You are not allowed to access this course.'); - } - - public function viewOpen(User $user, Course $course): Response - { - - return ($user->role === 2 && (Helper::isCommonsCourse($course) || $course->public)) || $course->anonymous_users - ? Response::allow() - : Response::deny('You are not allowed to access this course.'); - } - - /** - * Determine whether the user can view the course. - * - * @param User $user - * @param Course $course - * @return mixed - */ - public function createCourseAssignment(User $user, Course $course): Response - { - return $this->ownsCourseByUser($course, $user) - ? Response::allow() - : Response::deny('You are not allowed to create assignments for this course.'); - } - - /** - * Determine whether the user can view the course. - * - * @param User $user - * @param Course $course - * @param Assignment $assignment - * @return Response - */ - public function importAssignment(User $user, Course $course, Assignment $assignment): Response - { - - $has_access = true; - $message = ''; - if (!$this->ownsCourseByUser($course, $user)) { - $has_access = false; - $message = 'You are not allowed to import assignments to this course.'; - } - if ($has_access) { - $has_access = $user->role === 2 && ($assignment->course->public - || Helper::isCommonsCourse($assignment->course) - || $this->ownsCourseByUser($assignment->course, $user)); - if (!$has_access) { - $message = 'You can only import assignments from your own courses, the Commons, or public courses.'; - - } - } - - return $has_access - ? Response::allow() - : Response::deny($message); - } - - public function showCourse(User $user, Course $course): Response - { - return $this->ownsCourseByUser($course, $user) - ? Response::allow() - : Response::deny('You are not allowed to show/hide this course.'); - } - - - /** - * Determine whether the user can create courses. - * - * @param User $user - * @return mixed - */ - public function create(User $user) - { - return (in_array($user->role, [2, 5])) - ? Response::allow() - : Response::deny('You are not allowed to create a course.'); - } - - /** - * Determine whether the user can update the course. - * - * @param User $user - * @param Course $course - * @return mixed - */ - public function update(User $user, Course $course) - { - return $this->ownsCourseByUser($course, $user) - ? Response::allow() - : Response::deny('You are not allowed to update this course.'); - } - - /** - * @param User $user - * @param Course $course - * @return Response - */ - public function delete(User $user, Course $course): Response - { - return $this->ownsCourseByUser($course, $user) - ? Response::allow() - : Response::deny('You are not allowed to delete this course.'); - } - - - /** - * @param User $user - * @return Response - */ - public function getAllCourses(User $user): Response - { - return $user->isAdminWithCookie() - ? Response::allow() - : Response::deny('You are not allowed to get all courses.'); - } - - /** - * @param User $user - * @return Response - */ - public function getAssignmentNamesIdsByCourse(User $user): Response - { - //added (int) because wasn't working in the test - return in_array($user->role, [2, 5]) - ? Response::allow() - : Response::deny('You are not allowed to get the names and assignment IDs.'); - } - - -} diff --git a/resources/js/components/ResetCourse.vue b/resources/js/components/ResetCourse.vue deleted file mode 100644 index b986d5852..000000000 --- a/resources/js/components/ResetCourse.vue +++ /dev/null @@ -1,153 +0,0 @@ - - - diff --git a/resources/js/pages/control_panel/courses.to.reset.vue b/resources/js/pages/control_panel/courses.to.reset.vue deleted file mode 100644 index 3f6f2f03f..000000000 --- a/resources/js/pages/control_panel/courses.to.reset.vue +++ /dev/null @@ -1,137 +0,0 @@ - - - - - diff --git a/resources/js/pages/control_panel/index.vue b/resources/js/pages/control_panel/index.vue deleted file mode 100644 index 1f176b9e8..000000000 --- a/resources/js/pages/control_panel/index.vue +++ /dev/null @@ -1,113 +0,0 @@ - - - - - diff --git a/resources/js/pages/instructors/course_properties/index.vue b/resources/js/pages/instructors/course_properties/index.vue index 742c33925..462bcd150 100644 --- a/resources/js/pages/instructors/course_properties/index.vue +++ b/resources/js/pages/instructors/course_properties/index.vue @@ -23,6 +23,11 @@ Reset Course + diff --git a/resources/js/pages/instructors/course_properties/students.vue b/resources/js/pages/instructors/course_properties/students.vue deleted file mode 100644 index 5b1f3d62a..000000000 --- a/resources/js/pages/instructors/course_properties/students.vue +++ /dev/null @@ -1,493 +0,0 @@ - - - diff --git a/resources/js/router/routes.js b/resources/js/router/routes.js deleted file mode 100644 index 68ba8e3f9..000000000 --- a/resources/js/router/routes.js +++ /dev/null @@ -1,419 +0,0 @@ -import _ from 'lodash' - -function page (path) { - return () => import(/* webpackChunkName: '' */ `~/pages/${path}`).then(m => m.default || m) -} - -let student_paths = [ - { path: '/students/sitemap', name: 'students.sitemap', component: page('students/sitemap.vue') }, - { path: '/students/courses', name: 'students.courses.index', component: page('students/courses.index.vue') }, - { - path: '/students/assignments/:assignmentId/summary', - name: 'students.assignments.summary', - component: page('students/assignments.summary.vue') - }, - { - path: '/students/courses/:courseId/assignments', - name: 'students.assignments.index', - component: page('students/assignments.index.vue') - }, - { - path: '/students/assignments/:assignmentId/init-formative/:questionId?', - name: 'assignments.init-formative', - component: page('students/init_formative_assignment.vue') - }, - { - path: '/students/courses/:courseId/assignments/anonymous-user', - name: 'students.assignments.anonymous.user.index', - component: page('students/assignments.anonymous.user.index.vue') - }, -] - -let instructor_paths = [ - { - path: '/empty-learning-tree-node/edit/:questionId', - name: 'empty_learning_tree_node', - component: page('instructors/edit_question.vue') - }, - { - path: '/instructors/assignment-templates', - name: 'assignments.templates', - component: page('instructors/assignments.templates.vue') - }, - { - path: '/instructors/sitemap', - name: 'instructors.sitemap', - component: page('instructors/sitemap.vue') - }, - { - path: '/instructors/link-assignment-to-lms/:lmsResourceLinkId', - name: 'link_assignment_to_lms', - component: page('instructors/link_assignment_to_lms.vue') - }, - { - path: '/assignments/:assignmentId/questions/get', - name: 'questions.get', - component: page('instructors/questions.get.vue') - }, - { - path: '/all-questions/get', - name: 'all.questions.get', - component: page('instructors/all_questions.get.vue') - }, - { - path: '/all-learning-trees/get', - name: 'all.learning.trees.get', - component: page('instructors/all_learning_trees.get.vue') - }, - { - path: '/assignments/:assignmentId/learning-trees/get', - name: 'learning_trees.get', - component: page('instructors/learning_trees.get.vue') - }, - { - path: '/learning-trees/:learningTreeId/get', - name: 'learning_tree.get', - component: page('instructors/learning_tree.get.vue') - }, - { - path: '/instructors/learning-trees/editor/:learningTreeId?/:fromAllLearningTrees?', - name: 'instructors.learning_trees.editor', - component: page('instructors/learning_trees.editor.vue') - }, - { - path: '/instructors/learning-trees', - name: 'instructors.learning_trees.index', - component: page('instructors/learning_trees.index.vue') - }, - { - path: '/assignments/:assignmentId/questions/:questionId/view', - name: 'question.view', - component: page('instructors/question.view.vue') - }, - { - path: '/assignments/:assignmentId/grading/:questionId?/:studentUserId?', - name: 'assignment.grading.index', - component: page('instructors/assignments.grading.vue') - }, - { - path: '/testers/courses', - name: 'testers.courses.index', - component: page('testers/courses.index.vue') - }, - { - path: '/testers/assignments', - name: 'testers.assignments.index', - component: page('testers/assignments.index.vue') - }, - { - path: '/testers/student-results/:courseId/:assignmentId?', - name: 'testers.students.results', - component: page('testers/student.results.vue') - }, - { - path: '/testers/logged-in-as-student', - name: 'logged.in.as.student', - component: page('testers/logged.in.as.student.vue') - }, - { - path: '/testers/cannot-view-as-testing-student', - name: 'cannot.view.as.testing.student', - component: page('testers/cannot-view-as-testing-student.vue') - }, - { - path: '/instructors/courses', - name: 'instructors.courses.index', - component: page('instructors/courses.index.vue') - }, - { - path: '/courses/:courseId/gradebook', - name: 'gradebook.index', - component: page('instructors/gradebook.index.vue') - }, - { - path: '/instructors/courses/:courseId/assignments', - name: 'instructors.assignments.index', - component: page('instructors/assignments.index.vue') - } -] -let control_panel_paths = [ - { - path: '/control-panel', - component: page('control_panel/index.vue'), - children: [ - { path: '', redirect: { name: 'login.as' } }, - { path: 'login-as', name: 'login.as', component: page('control_panel/login.as.vue') }, - { - path: 'refresh-question-requests', - name: 'refresh.question.requests', - component: page('control_panel/refresh.question.requests.vue') - }, - { path: 'lti-integrations', name: 'lti.integrations', component: page('control_panel/lti.integrations.vue') }, - { - path: 'instructor-access-codes', - name: 'instructorAccessCodes', - component: page('control_panel/instructor.access.codes.vue') - }, - { - path: 'tester-access-codes', - name: 'testerAccessCodes', - component: page('control_panel/tester.access.codes.vue') - }, - { path: 'question-editors', name: 'questionEditors', component: page('control_panel/question.editors.vue') }, - { - path: 'courses-to-reset', - name: 'coursesToReset', - component: page('control_panel/courses.to.reset.vue') - }, - { - path: 'classification-manager', - name: 'classificationManager', - component: page('control_panel/classification-manager.vue') - }, - { - path: 'users-with-no-role', - name: 'usersWithNoRole', - component: page('control_panel/users.with.no.role.vue') - }, - { - path: 'metrics', - name: 'metrics', - component: page('control_panel/metrics.vue') - }, - ] - }] -let general_paths = [ - { - path: '/pending-question-ownership-transfer-request/:action/:token', - name: 'QuestionOwnershipTransferRequest', - component: page('instructors/pending_question_ownership_transfer_request.vue') - }, - { - path: '/launch-clicker-app/:token/:isRegistration?', - name: 'LaunchClickerApp', - component: page('auth/launch.clicker.app.vue') - }, - { - path: '/launch-in-new-window/:ltiTokenId/:ltiFinalLocation/:ltiResourceId', - name: 'launchInNewWindow', - component: page('launch_in_new_window.vue') - }, - { path: '/lti-login', name: 'ltiLogin', component: page('lti_login.vue') }, - { path: '/incomplete-registration', name: 'incomplete.registration', component: page('incomplete_registration.vue') }, - { path: '/sitemap', name: 'sitemap', component: page('sitemap.vue') }, - { path: '/question-editor/:tab/:questionId?', name: 'question.editor', component: page('question_editor.vue') }, - { path: '/lti/canvas/config/:campusId', name: 'lti_canvas_config', component: page('lti_canvas_config.vue') }, - { path: '/lti/blackboard/config', name: 'lti_blackboard_config', component: page('lti_blackboard_config.vue') }, - { - path: '/beta-assignments/redirect-error', - name: 'beta_assignments_redirect_error', - component: page('beta_assignments_redirect_error.vue') - }, - { - path: '/init-lms-assignment/:assignmentId', - name: 'init_lms_assignment', - component: page('init_lms_assignment.vue') - }, - { path: '/question-in-iframe', name: 'question_in_iframe', component: page('iframe_test.vue') }, - { - path: '/assignments/:assignmentId/questions/view/:questionId?/:shownSections?', - name: 'questions.view', - component: page('questions.view.vue') - }, - { path: '/submission', name: 'submission.index', component: page('submission.store.vue') }, - { path: '/', name: 'welcome', component: page('welcome.vue') }, - { path: '/login', name: 'login', component: page('auth/login.vue') }, - { - path: '/auth/no-access', - name: 'no.access', - component: page('auth/no.access.vue') - }, - { - path: '/finish-sso-registration', - name: 'finish.sso.registration', - component: page('auth/finish.sso.registration.vue') - }, - { - path: '/register/instructor/:accessCode?', - name: 'register', - component: page('auth/register.vue'), - alias: ['/register/student', '/register/grader'] - }, - { - path: '/register/question-editor/:accessCode?', - name: 'question-editor-register', - component: page('auth/register.vue') - }, - { - path: '/register/tester/:accessCode?', - name: 'tester-register', - component: page('auth/register.vue') - }, - { path: '/password/reset', name: 'password.request', component: page('auth/password/email.vue') }, - { path: '/password/reset/:token', name: 'password.reset', component: page('auth/password/reset.vue') }, - { path: '/email/verify/:id', name: 'verification.verify', component: page('auth/verification/verify.vue') }, - { path: '/email/resend', name: 'verification.resend', component: page('auth/verification/resend.vue') }, - { path: '/home', name: 'home', component: page('instructors/courses.index.vue') }, - { path: '/open-courses/:type', name: 'open_courses', component: page('open_courses.vue') }, - { path: '/instructors/frameworks', name: 'frameworks', component: page('instructors/frameworks.vue') }, - { path: '/instructors/framework/:frameworkId', name: 'framework.view', component: page('instructors/framework.view.vue') }, - { - path: '/courses/:courseId/anonymous', - name: 'anonymous-users-entry', - component: page('anonymous.users.entry.vue') - }, - { - path: '/settings', - component: page('settings/index.vue'), - children: [ - { path: '', redirect: { name: 'settings.profile' } }, - { path: 'profile', name: 'settings.profile', component: page('settings/profile.vue') }, - { path: 'password', name: 'settings.password', component: page('settings/password.vue') }, - { path: 'notifications', name: 'settings.notifications', component: page('settings/notifications.vue')}, - { path: 'account_customizations', name: 'settings.account_customizations', component: page('settings/account_customizations.vue') - } - ] - }, - { - path: '/instructors/assignments/:assignmentId/information', - component: page('instructors/assignment_information/index.vue'), - children: [ - { path: '', redirect: { name: 'instructors.assignments.questions' } }, - { - path: 'questions', - name: 'instructors.assignments.questions', - component: page('instructors/assignment_information/questions.vue') - }, - { - path: 'case-study-notes', - name: 'instructors.assignments.case.study.notes', - component: page('instructors/assignment_information/case.study.notes.vue') - }, - { - path: 'summary', - name: 'instructors.assignments.summary', - component: page('instructors/assignment_information/summary.vue') - }, - { - path: 'properties', - name: 'instructors.assignments.properties', - component: page('instructors/assignment_information/properties.vue') - }, - { - path: 'control_panel', - name: 'instructors.assignments.control_panel', - component: page('instructors/assignment_information/control_panel.vue') - }, - { - path: 'submission-overrides', - name: 'instructors.assignments.submission_overrides', - component: page('instructors/assignment_information/submission_overrides.vue') - }, - { - path: 'auto-graded-submissions', - name: 'instructors.assignments.auto_graded_submissions', - component: page('instructors/assignment_information/auto_graded_submissions.vue') - }, - { - path: 'grader-access', - name: 'instructors.assignments.grader_access', - component: page('instructors/assignment_information/grader_access.vue') - }, - { - path: 'statistics', - name: 'instructors.assignments.statistics', - component: page('instructors/assignment_information/statistics.vue') - }, - { - path: 'gradebook', - name: 'instructors.assignments.gradebook', - component: page('instructors/assignment_information/gradebook.vue') - }, - { - path: '/assignments/:assignmentId/mass-grading', - name: 'assignment.mass_grading.index', - component: page('instructors/assignments.mass_grading.vue') - }, - - ] - }, - { - path: '/instructors/courses/:courseId/properties', - component: page('instructors/course_properties/index.vue'), - children: [ - { path: '', redirect: { name: 'course_properties.general_info' } }, - { - path: 'details', - name: 'course_properties.general_info', - component: page('instructors/course_properties/general_info.vue') - }, - { - path: 'sections', - name: 'course_properties.sections', - component: page('instructors/course_properties/sections.vue') - }, - { - path: 'tethered-courses', - name: 'course_properties.tethered_courses', - component: page('instructors/course_properties/tethered_courses.vue') - }, - { - path: 'letter-grades', - name: 'course_properties.letter_grades', - component: page('instructors/course_properties/letter_grades.vue') - }, - { - path: 'assignment-group-weights', - name: 'course_properties.assignment_group_weights', - component: page('instructors/course_properties/assignment_group_weights.vue') - }, - { - path: 'graders', - name: 'course_properties.graders', - component: page('instructors/course_properties/graders.vue') - }, - { - path: 'ungraded-submissions', - name: 'course_properties.ungraded_submissions', - component: page('instructors/course_properties/ungraded_submissions.vue') - }, - { - path: 'students', - name: 'course_properties.students', - component: page('instructors/course_properties/students.vue') - }, - { - path: 'a11y-redirect', - name: 'course_properties.a11y_redirect', - component: page('instructors/course_properties/a11y_redirect.vue') - }, - { - path: 'iframe-properties', - name: 'course_properties.iframe_properties', - component: page('instructors/course_properties/iframe_properties.vue') - }, - { - path: 'reset', - name: 'course_properties.reset_course', - component: page('instructors/course_properties/reset_course.vue') - }, - { - path: 'testers', - name: 'course_properties.testers', - component: page('instructors/course_properties/testers.vue') - }, - { - path: 'analytics', - name: 'course_properties.analytics', - component: page('instructors/course_properties/analytics.vue') - } - ] - }, - { path: '*', component: page('errors/404.vue') } -] - -export default _.concat([{ - path: '/h5p', - name: 'h5p', - component: page('h5p.vue') -}], general_paths, student_paths, instructor_paths, control_panel_paths) diff --git a/routes/api.php b/routes/api.php deleted file mode 100644 index 0f4453d65..000000000 --- a/routes/api.php +++ /dev/null @@ -1,667 +0,0 @@ - ['auth:api', 'throttle:240,1']], function () { - - Route::get('/updated-information-first-application/{assignment}', 'UpdatedInformationFirstApplicationController@index'); - Route::patch('/updated-information-first-application', 'UpdatedInformationFirstApplicationController@update'); - - Route::post('/fcm-tokens', 'FCMTokenController@store'); - Route::get('/fcm-tokens/test-send-notification', 'FCMTokenController@testSendNotification'); - - Route::patch('/time-zones', 'TimeZoneController@update'); - Route::post('/tester/email-results/{student}', 'TesterController@emailResults'); - Route::post('/tester', 'TesterController@store'); - Route::get('/tester/{course}', 'TesterController@index'); - Route::delete('/tester/course/{course}/user/{tester}/{removeOption}', 'TesterController@destroy'); - - Route::get('/lti-registration', 'LtiRegistrationController@index'); - Route::post('/lti-registration/save', 'LtiRegistrationController@store'); - Route::patch('/lti-registration/active/{ltiRegistration}', 'LtiRegistrationController@active'); - - - Route::post('/access-code', 'AccessCodeController@store'); - Route::post('/access-code/email', 'AccessCodeController@email'); - - Route::get('/lti-school', 'LtiSchoolController@index'); - - Route::post('/users/set-anonymous-user-session', 'UserController@setAnonymousUserSession'); - - - Route::get('/question-editor', 'QuestionEditorController@index'); - Route::delete('/question-editor/{questionEditorUser}', 'QuestionEditorController@destroy'); - - Route::patch('/cookie/set-question-view/{questionView}', 'CookieController@setQuestionView'); - Route::patch('/cookie/set-assignment-group-filter/{course}/{chosenAssignmentGroup}', 'CookieController@setAssignmentGroupFilter'); - Route::patch('/cookie/set-ferpa-mode/{ferpaMode}', 'CookieController@setFerpaMode'); - - Route::post('logout', 'Auth\LoginController@logout'); - Route::delete('/user', 'Auth\LoginController@destroy'); - Route::get('/user', 'Auth\UserController@current'); - Route::get('/user/all', 'Auth\UserController@getAll'); - - Route::post('/user/toggle-student-view', 'Auth\UserController@toggleStudentView'); - Route::post('/user/login-as', 'Auth\UserController@loginAs'); - Route::post('/user/login-as-student-in-course', 'Auth\UserController@loginAsStudentInCourse'); - - Route::get('/user/get-session', 'Auth\UserController@getSession'); - Route::post('/user/instructors-with-public-courses', 'UserController@getInstructorsWithPublicCourses'); - Route::get('/user/question-editors', 'UserController@getAllQuestionEditors'); - Route::patch('/user/student-email/{student}', 'UserController@updateStudentEmail'); - Route::delete('/user/{student}/course/{course}', 'UserController@destroy'); - - Route::get('/get-locally-saved-page-contents/{library}/{pageId}', 'LibretextController@getLocallySavedPageContents'); - Route::get('/get-header-html/{question}', 'LibretextController@getHeaderHtml'); - Route::post('/libretexts/solution-error', 'LibretextController@emailSolutionError'); - - Route::patch('/pending-question-ownership-transfer-request', 'PendingQuestionOwnershipTransferController@update'); - Route::post('/libretexts/migrate', 'LibretextController@migrate'); - - Route::get('/current-question-editor/{question}', 'CurrentQuestionEditorController@show'); - Route::patch('/current-question-editor/{question}', 'CurrentQuestionEditorController@update'); - Route::delete('/current-question-editor/{question}', 'CurrentQuestionEditorController@destroy'); - - - Route::patch('settings/profile', 'Settings\ProfileController@update'); - Route::patch('settings/password', 'Settings\PasswordController@update'); - - - Route::post('/assignment-topics', 'AssignmentTopicController@store'); - Route::patch('/assignment-topics', 'AssignmentTopicController@update'); - Route::patch('/assignment-topics/move/from-assignment/{assignment}/to/topic/{assignmentTopic}', 'AssignmentTopicController@move'); - Route::post('/assignment-topics/delete/{assignmentTopic}', 'AssignmentTopicController@delete'); - - Route::get('/assignment-topics/course/{course}', 'AssignmentTopicController@getAssignmentTopicsByCourse'); - Route::get('/assignment-topics/assignment/{assignment}', 'AssignmentTopicController@getAssignmentTopicsByAssignment'); - - - Route::get('/h5p-video-interaction/submissions/assignment/{assignment}/question/{question}', 'H5pVideoInteractionController@getSubmissions'); - - Route::get('/saved-questions-folders/options/my-questions-folders', 'SavedQuestionsFoldersController@getMyQuestionsFoldersAsOptions'); - Route::get('/saved-questions-folders/cloned-questions-folder', 'SavedQuestionsFoldersController@getClonedQuestionsFolder'); - Route::get('/saved-questions-folders/{type}/{withH5P?}', 'SavedQuestionsFoldersController@getSavedQuestionsFoldersByType'); - - Route::post('/saved-questions-folders', 'SavedQuestionsFoldersController@store'); - Route::patch('/saved-questions-folders', 'SavedQuestionsFoldersController@update'); - - - Route::get('/frameworks', 'FrameworkController@index'); - Route::post('/frameworks', 'FrameworkController@store'); - Route::delete('/frameworks/{framework}/{deleteProperties}', 'FrameworkController@destroy'); - - Route::patch('/frameworks/{framework}', 'FrameworkController@update'); - Route::post('/frameworks/export/{framework}', 'FrameworkController@export'); - - Route::post('/framework-levels/template', 'FrameworkLevelController@getTemplate'); - Route::post('/framework-levels/with-descriptors', 'FrameworkLevelController@storeWithDescriptors'); - - Route::get('/framework-levels/framework/{framework}/parent-id/{parent}', 'FrameworkLevelController@getFrameworkLevelChildren'); - Route::delete('/framework-levels/{frameworkLevel}/descriptor-action/{descriptorAction}/level-to-move-to/{levelToMoveTo}', 'FrameworkLevelController@destroy'); - Route::get('framework-levels/same-parent/{frameworkLevel}', 'FrameworkLevelController@getFrameworkLevelsWithSameParent'); - Route::get('framework-levels/all-children/{frameworkLevel}', 'FrameworkLevelController@getAllChildren'); - - Route::patch('/framework-levels/move-level', 'FrameworkLevelController@moveLevel'); - Route::patch('/framework-levels/change-position', 'FrameworkLevelController@changePosition'); - Route::get('/framework-item-sync-question/get-questions-by-descriptor/{frameworkDescriptor}', 'FrameworkItemSyncQuestionController@getQuestionsByDescriptor'); - - - Route::get('/framework-item-sync-question/question/{question}', 'FrameworkItemSyncQuestionController@getFrameworkItemsByQuestion'); - - Route::put('/framework-levels/upload', 'FrameworkLevelController@upload'); - Route::get('/frameworks/{framework}/{question?}', 'FrameworkController@show'); - - Route::post('/framework-levels', 'FrameworkLevelController@store'); - Route::patch('/framework-levels', 'FrameworkLevelController@update'); - - Route::post('/framework-descriptors', 'FrameworkDescriptorController@store'); - Route::patch('/framework-descriptors/move', 'FrameworkDescriptorController@move'); - Route::patch('/framework-descriptors/{frameworkDescriptor}', 'FrameworkDescriptorController@update'); - Route::delete('/framework-descriptors/{frameworkDescriptor}', 'FrameworkDescriptorController@destroy'); - - Route::post('/saved-questions-folders/delete/{savedQuestionsFolder}', 'SavedQuestionsFoldersController@destroy'); - Route::patch('/saved-questions-folders/move/{question}/from/{fromFolder}/to/{toFolder}', 'SavedQuestionsFoldersController@move'); - - Route::post('/my-favorites', 'MyFavoriteController@store'); - - Route::get('/learning-outcomes/default-subject', 'LearningOutcomeController@getDefaultSubject'); - Route::get('/learning-outcomes/{subject}', 'LearningOutcomeController@getLearningOutcomes'); - - Route::delete('/my-favorites/folder/{savedQuestionsFolder}/question/{question}', 'MyFavoriteController@destroy'); - Route::get('/my-favorites/assignment/{assignment}', 'MyFavoriteController@getMyFavoriteQuestionIdsByAssignment'); - - Route::patch('notifications/assignments', 'NotificationController@update'); - Route::get('notifications/assignments', 'NotificationController@show'); - - Route::patch('/final-grades/letter-grades/{course}', 'FinalGradeController@update'); - Route::get('/final-grades/letter-grades/default', 'FinalGradeController@getDefaultLetterGrades'); - Route::get('/final-grades/letter-grades/{course}', 'FinalGradeController@getCourseLetterGrades'); - Route::patch('/final-grades/{course}/round-scores/{roundScores}', 'FinalGradeController@roundScores'); - Route::patch('/final-grades/{course}/release-letter-grades/{letterGradesReleased}', 'FinalGradeController@releaseLetterGrades'); - - Route::post('/extra-credit', 'ExtraCreditController@store'); - Route::get('/extra-credit/{course}/{user}', 'ExtraCreditController@show'); - - Route::post('/ckeditor/upload', 'CKEditorController@upload'); - Route::post('/ckeditor/upload&responseType=json', 'CKEditorController@upload'); - - Route::get('/assign-to-groups/{course}', 'AssignToGroupController@assignToGroups'); - - Route::get('/schools/public-courses', 'SchoolController@getSchoolsWithPublicCourses'); - Route::get('/courses', 'CourseController@index'); - Route::get('/courses/non-beta-courses-and-assignments', 'CourseController@getNonBetaCoursesAndAssignments'); - Route::patch('/courses/{course}/iframe-properties', 'CourseController@updateIFrameProperties'); - Route::get('/courses/{course}/has-h5p-questions', 'CourseController@hasH5PQuestions'); - Route::get('/courses/is-alpha/{course}', 'CourseController@isAlpha'); - Route::get('/courses/warnings/{course}', 'CourseController@getWarnings'); - Route::get('/courses/last-school', 'CourseController@getLastSchool'); - Route::get('/courses/to-reset/{operator_text}/{num_days}', 'CourseController@getCoursesToReset'); - Route::get('/courses/assignments', 'CourseController@getCoursesAndAssignments'); - Route::get('/courses/assignments/non-beta', 'CourseController@getCoursesAndNonBetaAssignments'); - Route::get('/courses/enrolled-in-courses-and-assignments', 'CourseController@getEnrolledInCoursesAndAssignments'); - - Route::get('/courses/public/{instructor?}', 'CourseController@getPublicCourses'); - Route::get('/courses/importable', 'CourseController@getImportable'); - Route::patch('/courses/order', 'CourseController@order'); - Route::post('/courses/import/{course}', 'CourseController@import'); - Route::get('/courses/beta-approval-notifications/{course}', 'CourseController@getBetaApprovalNotifications'); - Route::patch('/courses/beta-approval-notifications/{course}', 'CourseController@updateBetaApprovalNotifications'); - - Route::get('/courses/anonymous-user', 'CourseController@getAnonymousUserCourses'); - Route::get('/courses/commons-courses-and-assignments', 'CourseController@getCommonsCoursesAndAssignments'); - - - Route::get('/account-customizations', 'AccountCustomizationController@show'); - Route::patch('/account-customizations', 'AccountCustomizationController@update'); - - Route::get('/courses/{course}', 'CourseController@show'); - Route::get('/courses/open/{course}', 'CourseController@showOpen'); - - Route::patch('/courses/{course}/show-course/{shown}', 'CourseController@showCourse'); - - Route::post('/courses', 'CourseController@store'); - Route::patch('/courses/{course}/students-can-view-weighted-average', 'CourseController@updateStudentsCanViewWeightedAverage'); - Route::patch('/courses/{course}/show-z-scores', 'CourseController@updateShowZScores'); - Route::patch('/courses/{course}/show-progress-report', 'CourseController@updateShowProgressReport'); - Route::patch('/courses/{course}', 'CourseController@update'); - Route::delete('/courses/{course}', 'CourseController@destroy'); - Route::delete('/courses/{course}/reset', 'CourseController@reset'); - - Route::patch('/assignments/{course}/order', 'AssignmentsController@order'); - - Route::post('/breadcrumbs', 'BreadcrumbController@index'); - - - Route::get('/assignmentGroupWeights/{course}', 'AssignmentGroupWeightController@index'); - Route::patch('/assignmentGroupWeights/{course}', 'AssignmentGroupWeightController@update'); - - - Route::get('assignmentGroups', 'AssignmentGroupController@getAssignmentGroupsByUser'); - Route::get('assignmentGroups/{course}', 'AssignmentGroupController@getAssignmentGroupsByCourse'); - Route::get('assignmentGroups/assignment-level/{course}', 'AssignmentGroupController@getAssignmentGroupsByCourseAndAssignment'); - Route::post('assignmentGroups/{course}', 'AssignmentGroupController@store'); - Route::get('assignmentGroups/get-assignment-group-filter/{course}', 'AssignmentGroupController@getAssignmentGroupFilter'); - - - Route::get('/assignments/download-users-for-assignment-override/{assignment}', 'AssignmentController@downloadUsersForAssignmentOverride'); - Route::get('/assignments/options/{course}', 'AssignmentController@getAssignmentOptions'); - Route::patch('/assignments/{course}/order', 'AssignmentController@order'); - Route::get('/assignments/importable-by-user/{course}', 'AssignmentController@getImportableAssignmentsByUser'); - Route::post('/assignments/import/{assignment}/to/{course}', 'AssignmentController@importAssignment'); - - Route::get('/assignments/courses/{course}', 'AssignmentController@index'); - Route::get('/assignments/courses/{course}/anonymous-user', 'AssignmentController@getAssignmentsForAnonymousUser'); - - Route::get('/assignments/courses/public/{course}/names', 'AssignmentController@getAssignmentNamesForPublicCourse'); - Route::get('/assignments/{assignment}/get-questions-info', 'AssignmentController@getQuestionsInfo'); - Route::get('/assignments/{assignment}/summary', 'AssignmentController@getAssignmentSummary'); - Route::get('/assignments/{assignment}/scores-info', 'AssignmentController@scoresInfo'); - Route::get('/assignments/{assignment}/view-questions-info', 'AssignmentController@viewQuestionsInfo'); - Route::get('/assignments/{assignment}/get-info-for-grading', 'AssignmentController@getInfoForGrading'); - Route::post('/assignments/{assignment}/validate-assessment-type', 'AssignmentController@validateAssessmentType'); - Route::get('/assignments/{assignment}/start-page-info', 'AssignmentController@startPageInfo'); - - - Route::post('/sso/finish-registration', 'Auth\SSOController@finishRegistration'); - Route::post('sso/finish-clicker-app-sso-registration', 'Auth\SSOController@finishClickerAppRegistration'); - Route::get('/sso/completed-registration', 'Auth\SSOController@completedRegistration'); - Route::get('/sso/is-sso-user', 'Auth\SSOController@isSSOUser'); - - Route::post('/assignments', 'AssignmentController@store'); - Route::post('/assignments/{assignment}/create-assignment-from-template', 'AssignmentController@createAssignmentFromTemplate'); - Route::patch('/assignments/{assignment}/show-assignment-statistics/{showAssignmentStatistics}', 'AssignmentController@showAssignmentStatistics'); - Route::patch('/assignments/{assignment}/show-scores/{showScores}', 'AssignmentController@showScores'); - Route::patch('/assignments/{assignment}/graders-can-see-student-names/{gradersCanSeeStudentNames}', 'AssignmentController@gradersCanSeeStudentNames'); - Route::patch('/assignments/{assignment}/show-points-per-question/{showPointsPerQuestion}', 'AssignmentController@showPointsPerQuestion'); - Route::patch('/assignments/{assignment}/solutions-released/{solutionsReleased}', 'AssignmentController@solutionsReleased'); - Route::patch('/assignments/{assignment}/show-assignment/{shown}', 'AssignmentController@showAssignment'); - Route::patch('/assignments/{assignment}/common-question-text', 'AssignmentController@updateCommonQuestionText'); - Route::get('/assignments/{assignment}/common-question-text', 'AssignmentController@showCommonQuestionText'); - - Route::patch('/assignments/{assignment}', 'AssignmentController@update'); - Route::delete('/assignments/{assignment}', 'AssignmentController@destroy'); - - Route::post('/s3/pre-signed-url', 'S3Controller@preSignedURL'); - - Route::patch('/contact-grader-overrides/{course}', 'ContactGraderOverrideController@update'); - Route::get('/contact-grader-overrides/{assignment}', 'ContactGraderOverrideController@show'); - - Route::get('/auto-graded-and-file-submissions/{assignment}/{question}/get-auto-graded-and-file-submissions-by-assignment-and-question-and-student', 'AutoGradedAndFileSubmissionController@getAutoGradedAndFileSubmissionsByAsssignmentAndQuestionAndStudent'); - Route::get('/auto-graded-submissions/{assignment}/get-auto-graded-submissions-by-assignment/{download}', 'AutoGradedAndFileSubmissionController@getAutoGradedSubmissionsByAssignment'); - - Route::get('/scores/{assignment}/{question}/get-scores-by-assignment-and-question', 'ScoreController@getScoresByAssignmentAndQuestion'); - Route::put('/scores/{assignment}/upload-override-scores', 'ScoreController@uploadOverrideScores'); - Route::post('/scores/over-total-points/{assignment}/{question}', 'ScoreController@overTotalPoints'); - Route::patch('/scores/override-scores/{assignment}', 'ScoreController@overrideScores'); - Route::get('/scores/{course}/get-course-scores-by-user', 'ScoreController@getCourseScoresByUser'); - Route::get('/scores/assignment-user/{assignment}/{user}', 'ScoreController@getScoreByAssignmentAndStudent'); - Route::get('/scores/assignment/get-assignment-questions-scores-by-user/{assignment}/{time_spent_option}', 'ScoreController@getAssignmentQuestionScoresByUser'); - Route::get('/scores/summary/{assignment}/{question}', 'ScoreController@getScoresByAssignmentAndQuestion'); - Route::get('/scores/{course}/{sectionId}/{download}', 'ScoreController@index'); - Route::get('/scores/tester-student-results/course/{course}/assignment/{assignmentId}', 'ScoreController@testerStudentResults'); - Route::patch('/scores/{assignment}/{user}', 'ScoreController@update');//just doing a patch here because "no score" is consider a score - - - Route::post('case-study-notes/unsaved-changes', 'CaseStudyNoteController@getUnsavedChanges'); - Route::post('case-study-notes/save-all', 'CaseStudyNoteController@saveAll'); - Route::get('/case-study-notes/{assignment}', 'CaseStudyNoteController@show'); - Route::patch('/case-study-notes/{assignment}', 'CaseStudyNoteController@update'); - Route::post('/case-study-notes/{assignment}', 'CaseStudyNoteController@store'); - Route::delete('/case-study-notes/assignment/{assignment}', 'CaseStudyNoteController@resetAssignmentNotes'); - Route::delete('/case-study-notes/assignment/{assignment}/type/{type}', 'CaseStudyNoteController@destroyType'); - Route::delete('/case-study-notes/{caseStudyNote}', 'CaseStudyNoteController@destroy'); - - Route::get('/case-study-notes/assignment/{assignment}/order/{question_id}', 'AssignmentQuestionSyncCaseStudyNotesController@index'); - Route::get('/case-study-notes/assignment/{assignment}/question/{question_id}', 'AssignmentQuestionSyncCaseStudyNotesController@index'); - - Route::get('/analytics-dashboard/{course}', 'AnalyticsDashboardController@show'); - - - Route::get('/scores/get-ferpa-mode', 'ScoreController@getFerpaMode'); - - Route::get('/extensions/{assignment}/{user}', 'ExtensionController@show'); - Route::post('/extensions/{assignment}/{user}', 'ExtensionController@store'); - - - Route::get('/cutups/{assignment}', 'CutupController@show'); - Route::patch('/cutups/{assignment}/{question}/solution', 'CutupController@updateSolution'); - - Route::get('/tags', 'TagController@index'); - - Route::post('/meta-tags/admin-view/{adminView}/{perPage}/{currentPage}', 'MetaTagController@getMetaTagsByFilter'); - Route::patch('/meta-tags', 'MetaTagController@update'); - - Route::get('/beta-courses/get-alpha-course-from-beta-course/{beta_course}', 'BetaCourseController@getAlphaCourseFromBetaCourse'); - Route::get('/beta-courses/get-from-alpha-course/{alpha_course}', 'BetaCourseController@getBetaCoursesFromAlphaCourse'); - Route::get('/beta-courses/get-tethered-to-alpha-course/{course}', 'BetaCourseController@getTetheredToAlphaCourse'); - Route::delete('/beta-courses/untether/{course}', 'BetaCourseController@untetherBetaCourseFromAlphaCourse'); - - Route::post('/beta-courses/do-not-show-beta-course-dates-warning', 'BetaCourseController@doNotShowBetaCourseDatesWarning'); - - Route::get('/beta-course-approvals/assignment/{assignment}', 'BetaCourseApprovalController@getByAssignment'); - Route::get('/beta-course-approvals/course/{course}', 'BetaCourseApprovalController@getByCourse'); - - - Route::get('/libreverse/{questionId}/student-learning-objectives', 'LibreverseController@getStudentLearningObjectiveByQuestionId'); - Route::get('/libreverse/library/{library}/page/{pageId}/title', 'LibreverseController@getTitleByLibraryAndPageId'); - Route::post('/libreverse/library/titles', 'LibreverseController@getTitles'); - - Route::get('/learning-trees', 'LearningTreeController@index'); - Route::post('/learning-trees/all', 'LearningTreeController@getAll'); - Route::get('/learning-trees/{learningTree}', 'LearningTreeController@show'); - Route::post('/learning-trees/import', 'LearningTreeController@import'); - Route::post('/learning-trees/{learningTree}/create-learning-tree-from-template', 'LearningTreeController@createLearningTreeFromTemplate'); - - - Route::patch('/learning-tree-histories/{learningTree}', 'LearningTreeHistoryController@updateLearningTreeFromHistory'); - - - Route::post('/learning-trees/learning-tree-exists', 'LearningTreeController@learningTreeExists'); - Route::delete('/learning-trees/{learningTree}', 'LearningTreeController@destroy'); - Route::patch('/learning-trees/nodes/{learningTree}', 'LearningTreeController@updateNode'); - Route::patch('/learning-trees/{learningTree}', 'LearningTreeController@updateLearningTree'); - Route::post('/learning-trees/info', 'LearningTreeController@storeLearningTreeInfo'); - Route::post('/learning-trees/info/{learningTree}', 'LearningTreeController@updateLearningTreeInfo'); - - Route::post('/store', 'DataShopController@store'); - - Route::get('/learning-trees/validate-remediation-by-assignment-question-id/{assignmentQuestionId}/{isRootNode}', 'LearningTreeController@validateRemediationByAssignmentQuestionId'); - - Route::get('/sections/can-create-student-access-codes', 'SectionController@canCreateStudentAccessCodes'); - Route::get('/sections/{course}', 'SectionController@index'); - Route::get('/sections/real-enrolled-users/{section}', 'SectionController@realEnrolledUsers'); - Route::post('/sections/{course}', 'SectionController@store'); - Route::patch('/sections/{section}', 'SectionController@update'); - Route::delete('/sections/{section}', 'SectionController@destroy'); - Route::patch('/sections/refresh-access-code/{section}', 'SectionController@refreshAccessCode'); - - - Route::patch('/assignments/{assignment}/questions/{question}/iframe-properties', 'AssignmentSyncQuestionController@updateIFrameProperties'); - Route::post('/assignments/{assignment}/questions/{question}/init-refresh-question', 'QuestionController@initRefreshQuestion'); - Route::get('/questions/{question}/assignment-status', 'QuestionController@getAssignmentStatus'); - - - Route::get('/questions', 'QuestionController@index'); - Route::get('/questions/default-import-library', 'QuestionController@getDefaultImportLibrary'); - Route::get('/questions/properties/{question}', 'QuestionController@getProperties'); - Route::get('/questions/compare-cached-and-non-cached/{question}', 'QuestionController@compareCachedAndNonCachedQuestions'); - Route::get('/questions/valid-licenses', 'QuestionController@getValidLicenses'); - Route::post('/questions/question-types', 'QuestionController@getQuestionTypes'); - - Route::put('/questions/validate-bulk-import-questions', 'QuestionController@validateBulkImportQuestions'); - Route::get('questions/get-question-to-edit/{question}', 'QuestionController@getQuestionToEdit'); - Route::post('/questions/get-webwork-code-from-file-path', 'QuestionController@getWebworkCodeFromFilePath'); - Route::post('/questions/clone', 'QuestionController@clone'); - - Route::post('/questions/qti-answer-json', 'QuestionController@getQtiAnswerJson'); - - Route::get('/questions/export-webwork-code/{question}', 'QuestionController@exportWebworkCode'); - - Route::post('/submission-confirmations/assignment/{assignment}/question/{question}', 'SubmissionConfirmationController@store'); - - Route::get('/webwork/list', 'WebworkController@list'); - Route::get('/webwork/clone-dir', 'WebworkController@cloneDir'); - Route::get('/webwork/delete', 'WebworkController@delete'); - Route::post('/webwork/src-doc', 'WebworkController@getSrcDoc'); - - - Route::put('/webwork-attachments/upload', 'WebworkAttachmentController@upload'); - Route::get('/webwork-attachments/question/{question}', 'WebworkAttachmentController@getWebworkAttachmentsByQuestion'); - Route::post('/webwork-attachments/destroy', 'WebworkAttachmentController@destroyWebworkAttachmentByQuestion'); - - Route::post('/qti-job/status', 'QtiJobController@getStatus'); - - Route::get('/qti-testing/matching', 'QtiTestingController@matching'); - Route::get('/qti-testing/simple-choice', 'QtiTestingController@simpleChoice'); - Route::get('/qti-testing/simple-choice-without-var-equal', 'QtiTestingController@simpleChoiceWithoutVarEqual'); - Route::get('/qti-testing/numerical', 'QtiTestingController@numerical'); - - Route::post('/qti-import', 'QtiImportController@store'); - Route::get('/qti-import/clean-up', 'QtiImportController@cleanUp'); - Route::get('/learning-tree-node/meta-info/{learning_tree}/{question_id}', 'LearningTreeNodeController@getMetaInfo'); - Route::post('/branches/descriptions', 'BranchController@getDescriptions'); - - Route::get('/questions/{question}', 'QuestionController@show'); - Route::get('/questions/{library}/{page_id}', 'QuestionController@getQuestionByLibraryAndPageId'); - Route::get('/questions/remediation/{assignment}/{question}/{learning_tree}/{branch_id}/{active_id}/{question_id}', 'QuestionController@getRemediationByQuestionIdInLearningTreeAssignment'); - - Route::post('/questions', 'QuestionController@store'); - Route::post('/questions/preview', 'QuestionController@preview'); - Route::post('/questions/h5p/{h5p}', 'QuestionController@storeH5P'); - - Route::patch('/review-history/assignment/{assignment}/question/{question}', 'ReviewHistoryController@update'); - - - Route::patch('/questions/{question}', 'QuestionController@update'); - - Route::delete('/questions/{question}', 'QuestionController@destroy'); - - Route::post('/questions/{question}/refresh/{assignment?}', 'QuestionController@refresh'); - Route::post('/questions/set-question-updated-at-session', 'QuestionController@setQuestionUpdatedAtSession'); - Route::post('/questions/getQuestionsByTags', 'QuestionController@getQuestionsByTags'); - Route::post('/questions/default-import-library', 'QuestionController@storeDefaultImportLibrary'); - Route::post('/questions/{assignment}/direct-import-question', 'QuestionController@directImportQuestion'); - Route::patch('/questions/{question}/refresh-properties', 'QuestionController@refreshProperties'); - Route::patch('/questions/properties/{question}', 'QuestionController@updateProperties'); - - Route::post('/question-bank/potential-questions-with-course-level-usage-info', 'QuestionBankController@getQuestionsWithCourseLevelUsageInfo'); - Route::post('/question-bank/all', 'QuestionBankController@getAll'); - - - Route::get('/metrics/{download}', 'MetricsController@index'); - Route::get('/metrics/cell-data/{download}', 'MetricsController@cellData'); - - Route::get('/assignment-templates', 'AssignmentTemplateController@index'); - Route::get('/assignment-templates/{assignmentTemplate}', 'AssignmentTemplateController@show'); - Route::post('/assignment-templates', 'AssignmentTemplateController@store'); - Route::patch('/assignment-templates/order', 'AssignmentTemplateController@order'); - Route::patch('/assignment-templates/{assignmentTemplate}', 'AssignmentTemplateController@update'); - Route::patch('/assignment-templates/copy/{assignmentTemplate}', 'AssignmentTemplateController@copy'); - Route::delete('/assignment-templates/{assignmentTemplate}', 'AssignmentTemplateController@destroy'); - - Route::patch('patient-information/show-patient-updated-information/{assignment}', 'PatientInformationController@updateShowPatientUpdatedInformation'); - Route::patch('patient-information/{assignment}', 'PatientInformationController@update'); - Route::get('patient-information/{assignment}', 'PatientInformationController@show'); - Route::delete('patient-information/{assignment}', 'PatientInformationController@destroy'); - Route::patch('patient-information/delete-updated-information/{assignment}', 'PatientInformationController@deleteUpdatedPatientInformation'); - - Route::get('/assignments/{assignment}/{question}/last-submitted-info', 'AssignmentSyncQuestionController@updateLastSubmittedAndLastResponse'); - Route::get('/assignments/{assignment}/questions/ids', 'AssignmentSyncQuestionController@getQuestionIdsByAssignment'); - Route::get('/assignments/{assignment}/questions/question-info', 'AssignmentSyncQuestionController@getQuestionInfoByAssignment'); - Route::get('/assignments/{assignment}/questions/view', 'AssignmentSyncQuestionController@getQuestionsToView'); - Route::get('/assignments/{assignment}/questions/summary', 'AssignmentSyncQuestionController@getQuestionSummaryByAssignment'); - Route::patch('/assignments/{assignment}/remix-assignment-with-chosen-questions', 'AssignmentSyncQuestionController@remixAssignmentWithChosenQuestions'); - - Route::get('/assignments/{assignment}/validate-can-switch-to-compiled-pdf', 'AssignmentSyncQuestionController@validateCanSwitchToCompiledPdf'); - Route::get('/assignments/{assignment}/validate-can-switch-to-or-from-compiled-pdf', 'AssignmentSyncQuestionController@validateCanSwitchToOrFromCompiledPdf'); - - Route::post('/assignments/{assignment}/questions/{question}', 'AssignmentSyncQuestionController@store'); - Route::post('/assignments/{assignment}/learning-trees/{learningTree}', 'AssignmentQuestionSyncLearningTreeController@store'); - Route::get('/assignment-question-learning-tree/assignments/{assignment}/question/{question}/info', 'AssignmentQuestionSyncLearningTreeController@getAssignmentQuestionLearningTreeInfo'); - Route::patch('/assignment-question-learning-tree/assignments/{assignment}/question/{question}', 'AssignmentQuestionSyncLearningTreeController@update'); - - Route::get('/assignments/{assignment}/questions/{question}/get-clicker-status', 'AssignmentSyncQuestionController@getClickerStatus'); - Route::post('/assignments/{assignment}/questions/{question}/start-clicker-assessment', 'AssignmentSyncQuestionController@startClickerAssessment'); - - Route::patch('/assignments/{assignment}/questions/{question}/open-ended-default-text', 'AssignmentSyncQuestionController@storeOpenEndedDefaultText'); - - - Route::get('/assignments/{assignment}/clicker-question', 'AssignmentSyncQuestionController@getClickerQuestion'); - - - Route::patch('/assignments/{assignment}/questions/{question}/update-open-ended-submission-type', 'AssignmentSyncQuestionController@updateOpenEndedSubmissionType'); - Route::get('/assignments/{assignment}/questions/{question}/has-non-scored-submission-files', 'AssignmentSyncQuestionController@hasNonScoredSubmissionFiles'); - - - Route::patch('/assignments/{assignment}/questions/{question}/update-points', 'AssignmentSyncQuestionController@updatePoints'); - Route::patch('/assignments/{assignment}/questions/{question}/update-weight', 'AssignmentSyncQuestionController@updateWeight'); - Route::patch('/assignments/{assignment}/questions/{question}/update-completion-scoring-mode', 'AssignmentSyncQuestionController@updateCompletionScoringMode'); - - Route::patch('/assignments/{assignment}/questions/order', 'AssignmentSyncQuestionController@order'); - - - Route::get('/refresh-question-requests', 'RefreshQuestionRequestController@index'); - Route::post('/refresh-question-requests/deny/{question}', 'RefreshQuestionRequestController@denyRefreshQuestionRequest'); - - Route::post('/refresh-question-requests/make-refresh-question-request/{question}', 'RefreshQuestionRequestController@makeRefreshQuestionRequest'); - - - Route::delete('/assignments/{assignment}/questions/{question}', 'AssignmentSyncQuestionController@destroy'); - - - Route::post('/submission-audios/audio-feedback/{user}/{assignment}/{question}', 'SubmissionAudioController@storeAudioFeedback'); - Route::post('/submission-audios/{assignment}/{question}', 'SubmissionAudioController@store'); - Route::post('/submission-audios/error', 'SubmissionAudioController@logError'); - - - Route::get('/assignment-grader-access/{assignment}', 'AssignmentGraderAccessController@index'); - Route::patch('assignment-grader-access/{assignment}/{grader}/{access_level}', 'AssignmentGraderAccessController@updateGrader'); - Route::patch('assignment-grader-access/{assignment}/{access_level}', 'AssignmentGraderAccessController@updateAllGraders'); - - - Route::get('/enrollments', 'EnrollmentController@index'); - Route::get('/enrollments/{course}/details', 'EnrollmentController@details'); - Route::patch('/enrollments/a11y-redirect', 'EnrollmentController@updateA11yRedirect'); - - - Route::get('/enrollments/{assignment}/from-assignment', 'EnrollmentController@enrollmentsFromAssignment'); - - - Route::get('/submission-overrides/{assignment}', 'SubmissionOverrideController@index'); - Route::patch('/submission-overrides/{assignment}', 'SubmissionOverrideController@update'); - Route::delete('/submission-overrides/{assignment}/{studentUser}/{type}/{question?}', 'SubmissionOverrideController@destroy'); - - Route::patch('/learning-tree-time-left/get-time-left', 'LearningTreeTimeLeftController@getTimeLeft'); - Route::patch('/learning-tree-time-left', 'LearningTreeTimeLeftController@update'); - - Route::post('/enrollments', 'EnrollmentController@store'); - Route::post('/enrollments/auto-enroll/{course}/{assignmentId}', 'EnrollmentController@autoEnrollStudent'); - - Route::delete('/enrollments/{section}/{user}', 'EnrollmentController@destroy'); - Route::patch('/enrollments/{course}/{user}', 'EnrollmentController@update'); - - Route::get('/submissions/can-submit/assignment/{assignment}/question/{question}', 'SubmissionController@canSubmit'); - - Route::patch('/submissions/{assignment}/{question}/scores', 'SubmissionController@updateScores'); - Route::patch('/submissions/assignments/{assignment}/question/{question}/reset-submission', 'SubmissionController@resetSubmission'); - - Route::patch('/submissions/time-spent/assignment/{assignment}/question/{question}', 'AssignmentQuestionTimeOnTaskController@update'); - Route::patch('/assignment-question-time-spents/assignment/{assignment}/question/{question}', 'AssignmentQuestionTimeOnTaskController@update'); - Route::get('/assignment-question-time-spents/assignment/{assignment}', 'AssignmentQuestionTimeOnTaskController@getTimeOnTasksByAssignment'); - - Route::patch('/submissions/time-on-task/assignment/{assignment}/question/{question}', 'AssignmentQuestionTimeOnTaskController@update'); - Route::patch('/assignment-question-time-on-tasks/assignment/{assignment}/question/{question}', 'AssignmentQuestionTimeOnTaskController@update'); - Route::get('/assignment-question-time-on-tasks/assignment/{assignment}', 'AssignmentQuestionTimeOnTaskController@getTimeOnTasksByAssignment'); - - Route::get('/users-with-no-role', 'UsersWithNoRoleController@index'); - Route::patch('/users-with-no-role/{user}', 'UsersWithNoRoleController@update'); - Route::delete('/users-with-no-role/{user}', 'UsersWithNoRoleController@destroy'); - - Route::post('/submissions', 'SubmissionController@store'); - Route::get('/submissions/{assignment}/questions/{question}/pie-chart-data', 'SubmissionController@submissionPieChartData'); - - Route::post('/shown-hints/assignments/{assignment}/question/{question}', 'ShownHintController@store'); - - - Route::get('/canned-responses', 'CannedResponseController@index'); - Route::post('/canned-responses', 'CannedResponseController@store'); - Route::delete('/canned-responses/{cannedResponse}', 'CannedResponseController@destroy'); - - Route::get('/submission-files/ungraded-submissions/{course}', 'SubmissionFileController@getUngradedSubmissions'); - Route::patch('/submission-files/{assignment}/{question}/page', 'SubmissionFileController@updatePage'); - Route::patch('/submission-files/{assignment}/{question}/scores', 'SubmissionFileController@updateScores'); - Route::get('/assignment-files/assignment-file-info-by-student/{assignment}', 'AssignmentFileController@getAssignmentFileInfoByStudent'); - Route::post('/submission-files/get-files-from-s3/{assignment}/{question}/{studentUser}', 'SubmissionFileController@getFilesFromS3'); - Route::post('/submission-files/can-submit-file-submission', 'SubmissionFileController@canSubmitFileSubmission'); - - - Route::post('/solutions/show-solution/{assignment}/{question}', 'SolutionController@showSolutionByAssignmentQuestionUser'); - Route::post('/solutions/text/{assignment}/{question}', 'SolutionController@storeText'); - Route::post('/solution-files/audio/{assignment}/{question}', 'SolutionController@storeAudioSolutionFile'); - Route::put('/solution-files', 'SolutionController@storeSolutionFile'); - Route::post('/solution-files/download', 'SolutionController@downloadSolutionFile'); - Route::delete('/solution-files/{assignment}/{question}', 'SolutionController@destroy'); - - Route::post('/submission-texts', 'SubmissionTextController@store'); - Route::delete('/submission-texts/{assignment}/{question}', 'SubmissionTextController@destroy'); - - Route::put('/submission-files/file-feedback', 'SubmissionFileController@storeFileFeedback'); - - Route::post('/grading', 'GradingController@store'); - Route::get('/grading/{assignment}/{question}/{sectionId}/{gradeView}', 'GradingController@index'); - - - Route::put('/submission-files', 'SubmissionFileController@storeSubmissionFile'); - Route::post('/submission-files/get-temporary-url-from-request', 'SubmissionFileController@getTemporaryUrlFromRequest'); - Route::post('/submission-files/download', 'SubmissionFileController@downloadSubmissionFile'); - - - Route::post('/invitations/grader', 'InvitationController@emailGraderInvitation'); - - Route::post('/graders/', 'GraderController@store'); - Route::get('/graders/{course}', 'GraderController@getGradersByCourse'); - Route::patch('/graders/{user}', 'GraderController@update'); - Route::delete('/graders/{course}/{user}', 'GraderController@removeGraderFromCourse'); - - Route::patch('/head-graders/{course}/{user}', 'HeadGraderController@update'); - Route::delete('/head-graders/{course}', 'HeadGraderController@destroy'); - - - Route::get('/grader-notifications/{course}', 'GraderNotificationController@index'); - Route::patch('/grader-notifications/{course}', 'GraderNotificationController@update'); - -}); - -Route::group(['middleware' => ['guest:api', 'throttle:30,1']], function () { - - Route::get('/courses/anonymous-user/can-log-in', 'CourseController@canLogInAsAnonymousUser'); - Route::get('/courses/open/index', 'CourseController@open'); - Route::get('/courses/{course}/can-log-into-course-as-anonymous-user', 'CourseController@canLogIntoCourseAsAnonymousUser'); - - Route::post('login', 'Auth\LoginController@login'); - Route::post('register', 'Auth\RegisterController@register'); - - Route::post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail'); - Route::post('password/reset', 'Auth\ResetPasswordController@reset'); - - Route::post('email/verify/{user}', 'Auth\VerificationController@verify')->name('verification.verify'); - Route::post('email/resend', 'Auth\VerificationController@resend'); - - Route::post('oauth/{driver}', 'Auth\OAuthController@redirectToProvider'); - Route::get('oauth/{driver}/callback', 'Auth\OAuthController@handleProviderCallback')->name('oauth.callback'); -}); diff --git a/tests/Feature/Instructors/StudentsTest.php b/tests/Feature/Instructors/StudentsTest.php deleted file mode 100644 index c53722ea0..000000000 --- a/tests/Feature/Instructors/StudentsTest.php +++ /dev/null @@ -1,361 +0,0 @@ -user = factory(User::class)->create(); - $this->user_2 = factory(User::class)->create(); - $this->course = factory(Course::class)->create(['user_id' => $this->user->id]); - $this->section = factory(Section::class)->create(['course_id' => $this->course->id]); - $this->section_1 = factory(Section::class)->create(['course_id' => $this->course->id]); - - $this->fake_student_user_1 = factory(User::class)->create(); - $this->fake_student_user_1->role = 3; - $this->fake_student_user_1->fake_student = 1; - $this->fake_student_user_1->save(); - - factory(Enrollment::class)->create([ - 'user_id' => $this->fake_student_user_1->id, - 'section_id' => $this->section->id, - 'course_id' => $this->course->id - ]); - - - $this->fake_student_user_2 = factory(User::class)->create(); - $this->fake_student_user_2->role = 3; - $this->fake_student_user_2->fake_student = 0; - $this->fake_student_user_2->save(); - - factory(Enrollment::class)->create([ - 'user_id' => $this->fake_student_user_2->id, - 'section_id' => $this->section_1->id, - 'course_id' => $this->course->id - ]); - - - $this->question = factory(Question::class)->create(['page_id' => 76541]); - $this->assignment = factory(Assignment::class)->create(['course_id' => $this->course->id]); - - - $this->course_2 = factory(Course::class)->create(['user_id' => $this->user_2->id]); - $this->section_2 = factory(Section::class)->create(['course_id' => $this->course_2->id]); - $this->student_user_3 = factory(User::class)->create(); - $this->student_user_3->role = 3; - $this->student_user_3->save(); - - factory(Enrollment::class)->create([ - 'user_id' => $this->student_user_3->id, - 'section_id' => $this->section_2->id, - 'course_id' => $this->course_2->id - ]); - $this->course_2 = factory(Course::class)->create(['user_id' => $this->user_2->id]); - $this->section_2 = factory(Section::class)->create(['course_id' => $this->course->id]); - - - $this->student_user = factory(User::class)->create(); - $this->student_user->role = 3; - $this->student_user->fake_student = 0; - $this->student_user->save(); - - - $this->student_user_2 = factory(User::class)->create(); - $this->student_user_2->role = 3; - $this->student_user_2->save(); - - - foreach ([$this->student_user->id, $this->student_user_2->id] as $student_id) { - Extension::create(['user_id' => $student_id, - 'assignment_id' => $this->assignment->id, - 'extension' => '2020-10-23 18:00:00']); - Score::create(['user_id' => $student_id, - 'assignment_id' => $this->assignment->id, - 'score' => 10]); - LtiGradePassback::create(['user_id' => $student_id, - 'assignment_id' => $this->assignment->id, - 'score' => 5, - 'launch_id' => 1, - 'status' => 'success', - 'message' => 'blah']); - Seed::create(['user_id' => $student_id, - 'assignment_id' => $this->assignment->id, - 'question_id' => $this->question->id, - 'seed' => 1234]); - ExtraCredit::create(['user_id' => $student_id, - 'course_id' => $this->course->id, - 'extra_credit' => 5]); - - factory(Enrollment::class)->create([ - 'user_id' => $student_id, - 'section_id' => $this->section->id, - 'course_id' => $this->course->id - ]); - - $this->assignUserToAssignment($this->assignment->id, 'section', $this->section->id, $student_id); - Submission::create(['assignment_id' => $this->assignment->id, - 'question_id' => $this->question->id, - 'user_id' => $student_id, - 'score' => 5, - 'submission_count' => 1, - 'answered_correctly_at_least_once' => false, - 'submission' => 'some submission']); - $data = [ - 'type' => 'q', - 'user_id' => $student_id, - 'assignment_id' => $this->assignment->id, - 'question_id' => $this->question->id, - 'submission' => 'fake_1.pdf', - 'original_filename' => 'orig_fake_1.pdf', - 'date_submitted' => Carbon::now()]; - SubmissionFile::create($data); - } - } - - /** @test */ - - public function non_owner_cannot_move_student_to_a_different_section() - { - - $this->actingAs($this->user_2)->patchJson("/api/enrollments/{$this->course->id}}/{$this->student_user->id}", - ['section_id' => $this->section_1->id]) - ->assertJson(['message' => "You are not allowed to move this student."]); - - } - - /** @test */ - public function email_must_be_valid() - { - - $this->actingAs($this->user)->patchJson("/api/user/student-email/{$this->student_user->id}", - ['email' => 'bad_email']) - ->assertJsonValidationErrors('email'); - } - - /** @test */ - public function email_must_be_unique() - { - - $this->actingAs($this->user)->patchJson("/api/user/student-email/{$this->student_user->id}", - ['email' => $this->user->email]) - ->assertJsonValidationErrors('email'); - } - - - /** @test */ - public function non_owner_cannot_update_student_email() - { - - $this->actingAs($this->user_2)->patchJson("/api/user/student-email/{$this->student_user->id}", - ['email' => 'some_email@hotmail.com']) - ->assertJson(['message' => "You are not allowed to update this student's email."]); - } - - - /** @test * */ - public function when_owner_unenrolls_all_students_student_data_is_removed() - { - $this->createStudentUsers(); - $this->addGraders(); - $this->createAssignmentQuestions(); - $this->createSubmissions(); - $this->createScores(); - - - $student_user_ids = Enrollment::where('course_id', $this->course->id) - ->get() - ->pluck('user_id') - ->toArray(); - $num_users = User::all()->count(); - - $course_enrollments = Enrollment::where('course_id', $this->course->id)->get()->count(); - $this->assertEquals(6, $course_enrollments, 'original course enrollments'); - - $submissions = Submission::whereIn('user_id', $student_user_ids)->get()->count(); - $this->assertEquals(4, $submissions, 'original course submissions'); - - $submission_files = SubmissionFile::whereIn('user_id', $student_user_ids)->get()->count(); - $this->assertEquals(4, $submission_files, 'original course file submissions'); - - $course_scores = Score::whereIn('user_id', $student_user_ids)->get()->count(); - - $this->assertEquals(4, $course_scores, 'original course scores'); - - - $this->actingAs($this->user)->deleteJson("api/courses/{$this->course->id}/reset", - [ - 'understand_scores_removed' => 1, - 'confirmation' => $this->course->name - ]) - ->assertJson(['message' => "All students from {$this->course->name} have been unenrolled and their data removed."]); - - $course_submissions = Submission::whereIn('user_id', $student_user_ids)->get()->count(); - - $this->assertEquals(0, $course_submissions, 'course submissions'); - - $course_submission_files = SubmissionFile::whereIn('user_id', $student_user_ids)->get()->count(); - - $this->assertEquals(0, $course_submission_files, 'new course submission files'); - - $course_scores = Score::whereIn('user_id', $student_user_ids)->get()->count(); - $this->assertEquals(0, $course_scores, 'new course scores'); - - - $course_enrollments = Enrollment::where('course_id', $this->course->id)->get()->count(); - - $this->assertEquals(1, $course_enrollments, 'new course enrollments'); - $new_user_count = User::all()->count(); - $this->assertEquals($num_users, $new_user_count, 'keeps the same users'); - $fake_user_still_exists = DB::table('enrollments') - ->join('users', 'enrollments.user_id', '=', 'users.id') - ->where('enrollments.course_id', $this->course->id) - ->where('fake_student', 1) - ->exists(); - $this->assertTrue($fake_user_still_exists); - - } - - - /** @test */ - - public function owner_can_move_student_to_a_different_section() - { - - $this->actingAs($this->user)->patchJson("/api/enrollments/{$this->course->id}}/{$this->student_user->id}", - ['section_id' => $this->section_1->id]) - ->assertJson(['message' => "We have moved {$this->student_user->first_name} {$this->student_user->last_name} to {$this->section_1->name}."]); - - } - - - /** @test */ - - public function to_move_student_the_student_must_be_enrolled_in_owners_course() - { - $this->actingAs($this->user)->patchJson("/api/enrollments/{$this->course_2->id}}/{$this->student_user_2->id}") - ->assertJson(['message' => 'You are not allowed to move this student.']); - - } - - - /** @test */ - - public function to_unenroll_student_must_be_enrolled_in_owners_course() - { - $this->actingAs($this->user)->deleteJson("/api/enrollments/{$this->section_2->id}}/{$this->student_user_2->id}") - ->assertJson(['message' => 'You are not allowed to unenroll this student.']); - - } - - /** @test */ - - public function to_unenroll_all_students_must_be_owner_of_course() - { - $this->actingAs($this->user_2)->deleteJson("/api/courses/{$this->course->id}/reset", [ - 'understand_scores_removed' => 1, - 'confirmation' => $this->course->name - ]) - ->assertJson(['message' => 'You are not allowed to reset that course.']); - - } - - /** @test */ - - public function course_name_is_required() - { - $this->actingAs($this->user)->deleteJson("/api/courses/{$this->course->id}/reset", ['understand_scores_removed' => 1]) - ->assertJsonValidationErrors('confirmation'); - } - - - /** @test */ - - public function owner_can_unenroll_all_students() - { - $this->actingAs($this->user)->deleteJson("/api/courses/{$this->course->id}/reset", ['understand_scores_removed' => 1, 'confirmation' => $this->course->name]) - ->assertJson(['message' => 'All students from First Course have been unenrolled and their data removed.']); - } - - /** @test */ - - public function course_name_must_be_correct() - { - $this->actingAs($this->user)->deleteJson("/api/courses/{$this->course->id}/reset", ['understand_scores_removed' => 1, 'confirmation' => "not the right course name"]) - ->assertJsonValidationErrors('confirmation'); - } - - - /** @test */ - - public function admin_can_unenroll_all_students() - { - - $user = User::find(1) ?? factory(User::class)->create(['id' => 1]); - $course_2 = factory(Course::class)->create(['user_id' => $this->user_2->id]); - $this->actingAs($user)->deleteJson("/api/courses/$course_2->id/reset", ['confirmation' => $course_2->name]) - ->assertJson(['message' => 'All students from First Course have been unenrolled and their data removed.']); - - - } - - /** @test */ - - public function owner_can_unenroll_student_from_course() - { - $this->actingAs($this->user)->deleteJson("/api/enrollments/{$this->section->id}}/{$this->student_user->id}") - ->assertJson(['message' => "We have unenrolled {$this->student_user->first_name} {$this->student_user->last_name} from the course."]); - - } - - /** @test */ - - public function correct_number_of_database_rows_remain_after_unenroll() - { - $enrollments = Enrollment::all()->count(); - $this->assertEquals(2, Extension::all()->count()); - $this->assertEquals(2, LtiGradePassback::all()->count()); - $this->assertEquals(2, AssignToUser::all()->count()); - $this->assertEquals(2, Submission::all()->count()); - $this->assertEquals(2, SubmissionFile::all()->count()); - $this->assertEquals(2, Score::all()->count()); - - - $this->actingAs($this->user)->deleteJson("/api/enrollments/{$this->section->id}}/{$this->student_user->id}") - ->assertJson(['message' => "We have unenrolled {$this->student_user->first_name} {$this->student_user->last_name} from the course."]); - $this->assertEquals(1, Extension::all()->count()); - $this->assertEquals(1, LtiGradePassback::all()->count()); - $this->assertEquals(1, AssignToUser::all()->count()); - $this->assertEquals(1, Submission::all()->count()); - $this->assertEquals(1, SubmissionFile::all()->count()); - $this->assertEquals(1, Score::all()->count()); - $this->assertEquals($enrollments - 1, Enrollment::all()->count()); - - } - - -} From 5cdcf624a7c82c3b95c5d263f318489f36aee542 Mon Sep 17 00:00:00 2001 From: Eric Kean Date: Mon, 4 Apr 2022 05:50:22 -0700 Subject: [PATCH 2/4] Learning Trees 2.1 Better formatting Put a box around what the students need to do Added Move To Branch Descriptions Added a check to the learning tree Removed the green checkmark after submitted at Added number of do-overs to the database Learning tree do-over concept Added the do over error to the form Fixed some of the hint logic Logic is closer Getting closer CHnaged minimum number of successful branches to number of successful branches for a do-over Successful branch table Language for the attempts Fixed the do over logic Updating successful branch concept Can retry Fixed some language Fixed more language All tests pass Put the number of do-overs in the form for editing Fixed some do-overs Better messages Removed the hint button for now Fixed error with too many attempts Change do-over to reset Removed the "to" in "Move to" All tests pass Added tree icons Added a way to get back to the root assessment Adding traffic light icon Added traffic lights Added 4.0 for one of the licenses New question view Moved information to the right Removed branch completion and re-submit messages Added verbage for the Congratulations but am unsure when that appears Multiple branches Created a trait for Branch success Moved the branch logic into a trait More refactoring First branch works The add resets now works at the tree level Message is correct after completing one more at the tree level Figured out the resets for trees Added a message about the time based stuff Resets works Changed the number of rests to numerical Created an exception for when remediations not yet in ADAPT Learning tree tests AssignmentsIndex3Test passes All tests pass Hint functionality works All tests pass Better hint --- resources/js/pages/questions.view.vue | 5894 ------------------------- 1 file changed, 5894 deletions(-) delete mode 100644 resources/js/pages/questions.view.vue diff --git a/resources/js/pages/questions.view.vue b/resources/js/pages/questions.view.vue deleted file mode 100644 index 3212ec2dc..000000000 --- a/resources/js/pages/questions.view.vue +++ /dev/null @@ -1,5894 +0,0 @@ -