├── log └── .keep ├── lib ├── assets │ └── .keep ├── extensions │ ├── legacy.rb │ ├── attachable.rb │ ├── conditional.rb │ ├── materials.rb │ ├── database_event.rb │ ├── acts_as_helpers.rb │ ├── core_extensions.rb │ ├── discussion_topic.rb │ ├── pathname_helpers.rb │ ├── destroy_callbacks.rb │ ├── devise_async_email.rb │ ├── time_bounded_record.rb │ ├── duplication_traceable.rb │ ├── legacy │ │ ├── active_record.rb │ │ └── active_record │ │ │ └── connection_adapters.rb │ ├── materials │ │ ├── action_view.rb │ │ ├── active_record.rb │ │ ├── action_controller.rb │ │ └── action_view │ │ │ └── helpers.rb │ ├── polyglot_with_database.rb │ ├── attachable │ │ ├── action_view.rb │ │ ├── active_record.rb │ │ └── action_controller.rb │ ├── action_mailer_suppression.rb │ ├── conditional │ │ └── active_record.rb │ ├── devise_async_email │ │ ├── devise.rb │ │ └── devise │ │ │ └── models.rb │ ├── acts_as_helpers │ │ └── active_record.rb │ ├── core_extensions │ │ └── active_record.rb │ ├── database_event │ │ └── active_record.rb │ ├── association_inverse_suppression.rb │ ├── date_time_helpers │ │ ├── active_support.rb │ │ ├── time.rb │ │ └── active_support │ │ │ └── time_zone.rb │ ├── destroy_callbacks │ │ └── active_record.rb │ ├── discussion_topic │ │ └── active_record.rb │ ├── deferred_workflow_state_persistence.rb │ ├── time_bounded_record │ │ ├── active_record.rb │ │ └── active_record │ │ │ └── connection_adapters.rb │ ├── duplication_traceable │ │ └── active_record.rb │ ├── polyglot_with_database │ │ ├── coursemology.rb │ │ └── coursemology │ │ │ └── polyglot.rb │ ├── render_collection_with_prefix_suffix.rb │ ├── action_mailer_suppression │ │ └── action_mailer.rb │ ├── has_many_inverse_through │ │ ├── active_record.rb │ │ └── active_record │ │ │ ├── reflection.rb │ │ │ ├── associations.rb │ │ │ └── associations │ │ │ └── builder.rb │ ├── render_collection_with_prefix_suffix │ │ ├── action_view.rb │ │ └── action_view │ │ │ └── abstract_renderer.rb │ ├── deferred_workflow_state_persistence │ │ └── active_record.rb │ ├── after_commit_action.rb │ └── date_time_helpers.rb ├── tasks │ └── coursemology │ │ └── programming_question.zip └── autoload │ ├── illegal_state_error.rb │ ├── authentication_error.rb │ ├── component_not_found_error.rb │ ├── invalid_data_error.rb │ ├── ssid_error.rb │ ├── koditsu_error.rb │ └── codaveri_error.rb ├── db ├── seeds │ └── production.rb └── migrate │ ├── 20160722020938_add_time_zone_to_users.rb │ ├── 20230904095037_change_jobs_column_type.rb │ ├── 20241118152013_drop_virtual_classroom_table.rb │ ├── 20161007061116_add_fields_to_assessments.rb │ ├── 20150314025251_add_logo_to_courses.rb │ ├── 20240512092424_add_session_id_column_to_user_table.rb │ ├── 20170608050653_add_description_to_course_groups.rb │ ├── 20170925095335_add_answer_to_posts.rb │ ├── 20180208070853_remove_read_marks_foreign_key.rb │ ├── 20230111111646_add_locale_column_to_user_table.rb │ ├── 20150116102204_add_name_to_users.rb │ ├── 20161108030759_add_gamified_to_courses.rb │ ├── 20170915083041_remove_token_authentication_from_user.rb │ ├── 20211215055726_rename_delayed_to_is_delayed.rb │ ├── 20241216104132_add_deleted_column_in_course_user.rb │ ├── 20151202030421_add_profile_photo_to_users.rb │ ├── 20160916101014_change_discussion_posts_title.rb │ ├── 20170915071654_add_last_active_at_to_instance_users.rb │ ├── 20161214050848_add_sent_at_to_course_user_invitations.rb │ ├── 20180220010332_remove_opening_reminder_token.rb │ ├── 20211210085034_add_delayed_post_column.rb │ ├── 20170602094949_change_length_of_invitation_key.rb │ ├── 20211226160941_add_satisfiability_type_to_videos.rb │ ├── 20150106073750_add_name_to_instances.rb │ ├── 20160628052136_add_staff_only_comments_to_questions.rb │ ├── 20160716091234_add_autograded_to_course_assessments.rb │ ├── 20161027074807_add_session_id_to_submissions.rb │ ├── 20170214062036_add_index_for_survey_response_user.rb │ ├── 20170220123952_remove_image_from_survey_question_option.rb │ ├── 20211221163337_add_satisfiability_type_to_surveys.rb │ ├── 20150702122955_instance_users_change_user_id_unique.rb │ ├── 20160126094510_add_badge_to_course_achievements.rb │ ├── 20160811064336_change_test_cases_expected_type.rb │ ├── 20170110022335_remove_extra_bonus_exp_from_lesson_plan.rb │ ├── 20170819040619_add_role_to_course_user_invitation.rb │ ├── 20220519055836_add_timeline_algorithm_to_user_invitation.rb │ ├── 20220701045213_add_skip_grading_to_mrq.rb │ ├── 20241129164745_remove_draft_programming_answer_column.rb │ ├── 20170420063829_remove_length_limit_of_expression.rb │ ├── 20230404030133_add_auto_grading_queue_to_question.rb │ ├── 20160808023535_change_course_assessment_questions_title_nullity.rb │ ├── 20161006063146_rename_assessments_display_mode.rb │ ├── 20161116075305_add_tabbed_view_to_course_assessments.rb │ ├── 20210112074249_add_show_mcq_answer_to_course_assessments.rb │ ├── 20240510173545_add_time_limit_for_timed_assessment.rb │ ├── 20240830080332_remove_live_feedback_settings_from_assessment.rb │ ├── 20151018122902_add_grade_to_course_assessment_answer.rb │ ├── 20161107023238_add_attempt_limit_to_programming_questions.rb │ ├── 20180403011936_add_phantom_to_course_user_invitations.rb │ ├── 20210819132022_block_student_viewing_submission.rb │ ├── 20211027083820_add_topics_auto_subscribe_to_forum.rb │ ├── 20150512014731_add_workflow_state_to_course_users.rb │ ├── 20170120063357_change_default_value_of_assessment_questions_weight.rb │ ├── 20170210073247_add_selected_to_survey_answer_options.rb │ ├── 20170306051518_rename_lectures_to_virtual_classrooms.rb │ ├── 20181018043204_make_scribing_scribbles_answer_id_non_null.rb │ ├── 20211210015400_change_forum_post_response_answer_text_type.rb │ ├── 20231026165911_add_misses_to_monitoring.rb │ ├── 20160801084814_rename_question_type_to_grading_scheme.rb │ ├── 20210817040704_add_show_mcq_mrq_solution_to_course_assessments.rb │ ├── 20230410121228_add_allow_record_draft_answer_to_assessments.rb │ ├── 20231017055234_add_blocks_to_monitoring.rb │ ├── 20240312101723_add_max_size_to_attachment.rb │ ├── 20141222074908_add_userstamps_to_courses.rb │ ├── 20150726130555_set_achievement_condition_nullity.rb │ ├── 20151028151258_add_unique_index_to_materials.rb │ ├── 20230104073345_add_anonymous_to_forum_post.rb │ ├── 20150126080047_add_sticky_to_course_announcements.rb │ ├── 20150803080715_add_assessment_answer_workflow_state.rb │ ├── 20160714053644_add_timestamps_to_course_assessment_answers.rb │ ├── 20170308044737_add_recorded_videos_to_virtual_classrooms.rb │ ├── 20170816073714_add_confirmer_id_to_course_user_invitations.rb │ ├── 20220519015535_add_default_timeline_algorithm_to_course.rb │ ├── 20150729133128_rename_course_events_to_course_lesson_plan_events.rb │ ├── 20161013115452_migrate_graded_submissions_to_published.rb │ ├── 20170115105609_add_delayed_grade_publication_to_course_assessments.rb │ ├── 20150413043822_add_settings_to_instances_and_courses.rb │ ├── 20151030063045_add_unique_index_to_course_material_folders.rb │ ├── 20160822092000_add_publisher_to_submissions.rb │ └── 20181211133628_add_show_personalized_timeline_features_to_course.rb ├── app ├── assets │ └── config │ │ └── manifest.js ├── views │ ├── layouts │ │ ├── no_greeting_mailer.text.erb │ │ ├── mailer.text.erb │ │ ├── no_greeting_mailer.html.slim │ │ └── mailer.html.slim │ ├── jobs │ │ ├── show.json.jbuilder │ │ ├── _submitted.json.jbuilder │ │ ├── _completed.json.jbuilder │ │ └── _errored.json.jbuilder │ ├── course │ │ ├── admin │ │ │ ├── lesson_plan_settings │ │ │ │ └── edit.json.jbuilder │ │ │ ├── notification_settings │ │ │ │ └── edit.json.jbuilder │ │ │ ├── material_settings │ │ │ │ └── edit.json.jbuilder │ │ │ ├── announcement_settings │ │ │ │ └── edit.json.jbuilder │ │ │ ├── discussion │ │ │ │ └── topic_settings │ │ │ │ │ └── edit.json.jbuilder │ │ │ ├── rag_wise_settings │ │ │ │ ├── edit.json.jbuilder │ │ │ │ ├── folders.json.jbuilder │ │ │ │ └── courses.json.jbuilder │ │ │ ├── admin │ │ │ │ └── time_zones.json.jbuilder │ │ │ ├── sidebar_settings │ │ │ │ └── show.json.jbuilder │ │ │ └── forum_settings │ │ │ │ └── edit.json.jbuilder │ │ ├── scholaistic │ │ │ ├── assistants │ │ │ │ ├── index.json.jbuilder │ │ │ │ └── show.json.jbuilder │ │ │ └── scholaistic_assessments │ │ │ │ └── new.json.jbuilder │ │ ├── condition │ │ │ ├── surveys │ │ │ │ └── _survey.json.jbuilder │ │ │ ├── levels │ │ │ │ └── _level.json.jbuilder │ │ │ ├── achievements │ │ │ │ └── _achievement.json.jbuilder │ │ │ ├── _condition_list_data.json.jbuilder │ │ │ ├── scholaistic_assessments │ │ │ │ └── _scholaistic_assessment.json.jbuilder │ │ │ └── assessments │ │ │ │ ├── _assessment.json.jbuilder │ │ │ │ └── _assessment_condition.json.jbuilder │ │ ├── mailer │ │ │ ├── course_duplicate_failed_email.text.erb │ │ │ ├── course_duplicate_failed_email.html.slim │ │ │ ├── course_user_deletion_failed_email.text.erb │ │ │ ├── course_user_deletion_failed_email.html.slim │ │ │ ├── user_rejected_email.text.erb │ │ │ ├── user_rejected_email.html.slim │ │ │ └── course_duplicated_email.text.erb │ │ ├── video │ │ │ ├── submission │ │ │ │ └── sessions │ │ │ │ │ └── create.json.jbuilder │ │ │ ├── topics │ │ │ │ ├── _topics.json.jbuilder │ │ │ │ ├── index.json.jbuilder │ │ │ │ ├── _posts.json.jbuilder │ │ │ │ └── create.json.jbuilder │ │ │ └── videos │ │ │ │ └── _video_statistics.json.jbuilder │ │ ├── assessment │ │ │ ├── question │ │ │ │ ├── programming │ │ │ │ │ ├── import_result.json.jbuilder │ │ │ │ │ ├── edit.json.jbuilder │ │ │ │ │ ├── new.json.jbuilder │ │ │ │ │ └── metadata │ │ │ │ │ │ ├── _r.json.jbuilder │ │ │ │ │ │ ├── _c_cpp.json.jbuilder │ │ │ │ │ │ ├── _csharp.json.jbuilder │ │ │ │ │ │ ├── _golang.json.jbuilder │ │ │ │ │ │ ├── _python.json.jbuilder │ │ │ │ │ │ ├── _rust.json.jbuilder │ │ │ │ │ │ ├── _javascript.json.jbuilder │ │ │ │ │ │ ├── _typescript.json.jbuilder │ │ │ │ │ │ └── partials │ │ │ │ │ │ ├── _file.json.jbuilder │ │ │ │ │ │ └── _test_cases.json.jbuilder │ │ │ │ ├── scribing │ │ │ │ │ └── _scribing.json.jbuilder │ │ │ │ ├── voice_responses │ │ │ │ │ ├── _voice_response.json.jbuilder │ │ │ │ │ ├── _form.json.jbuilder │ │ │ │ │ └── new.json.jbuilder │ │ │ │ ├── forum_post_responses │ │ │ │ │ ├── _form.json.jbuilder │ │ │ │ │ ├── new.json.jbuilder │ │ │ │ │ └── _forum_post_response.json.jbuilder │ │ │ │ ├── text_responses │ │ │ │ │ └── new.json.jbuilder │ │ │ │ └── rubric_based_responses │ │ │ │ │ ├── new.json.jbuilder │ │ │ │ │ └── _grade_details.json.jbuilder │ │ │ ├── question_groups │ │ │ │ ├── _form.html.slim │ │ │ │ └── new.html.slim │ │ │ ├── programming_evaluations │ │ │ │ ├── update_result.json.jbuilder │ │ │ │ ├── show.json.jbuilder │ │ │ │ ├── _programming_evaluation.json.jbuilder │ │ │ │ └── allocate.json.jbuilder │ │ │ ├── assessments │ │ │ │ ├── monitoring.json.jbuilder │ │ │ │ ├── _assessment_conditional.json.jbuilder │ │ │ │ ├── blocked_by_monitor.json.jbuilder │ │ │ │ └── _assessment_list_data.json.jbuilder │ │ │ ├── categories │ │ │ │ ├── index.json.jbuilder │ │ │ │ └── _category.json.jbuilder │ │ │ ├── submission │ │ │ │ ├── submissions │ │ │ │ │ └── _answers.json.jbuilder │ │ │ │ ├── answer │ │ │ │ │ └── forum_post_response │ │ │ │ │ │ └── posts │ │ │ │ │ │ └── selected.json.jbuilder │ │ │ │ └── logs │ │ │ │ │ └── index.json.jbuilder │ │ │ ├── rubrics │ │ │ │ ├── index.json.jbuilder │ │ │ │ ├── fetch_answer_evaluations.json.jbuilder │ │ │ │ └── fetch_mock_answer_evaluations.json.jbuilder │ │ │ ├── question_bundles │ │ │ │ ├── _form.html.slim │ │ │ │ └── new.html.slim │ │ │ ├── skills │ │ │ │ └── _options.json.jbuilder │ │ │ ├── mock_answers │ │ │ │ └── index.json.jbuilder │ │ │ └── question_bundle_questions │ │ │ │ └── _form.html.slim │ │ ├── user_invitations │ │ │ ├── new.json.jbuilder │ │ │ └── _course_user_invitation_list.json.jbuilder │ │ ├── leaderboards │ │ │ ├── _leaderboard_group_list_data.json.jbuilder │ │ │ ├── _leaderboard_list_data.json.jbuilder │ │ │ └── _leaderboard_achievement_list_data.json.jbuilder │ │ ├── rubrics │ │ │ └── index.json.jbuilder │ │ ├── group │ │ │ ├── groups │ │ │ │ └── update.json.jbuilder │ │ │ └── group_categories │ │ │ │ └── show_users.json.jbuilder │ │ ├── users │ │ │ ├── _user.json.jbuilder │ │ │ ├── show.json.jbuilder │ │ │ └── _tabs_data.json.jbuilder │ │ ├── statistics │ │ │ ├── statistics │ │ │ │ └── index.json.jbuilder │ │ │ ├── assessments │ │ │ │ ├── ancestor_info.json.jbuilder │ │ │ │ └── _course_user.json.jbuilder │ │ │ └── users │ │ │ │ └── learning_rate_records.json.jbuilder │ │ ├── learning_map │ │ │ └── index.json.jbuilder │ │ ├── survey │ │ │ ├── responses │ │ │ │ └── _see_other.json.jbuilder │ │ │ ├── surveys │ │ │ │ └── _survey_with_questions.json.jbuilder │ │ │ └── questions │ │ │ │ └── _option.json.jbuilder │ │ ├── lesson_plan │ │ │ ├── milestones │ │ │ │ └── _milestone.json.jbuilder │ │ │ └── events │ │ │ │ └── _event_lesson_plan_item.json.jbuilder │ │ ├── achievement │ │ │ └── achievements │ │ │ │ └── _achievement_conditional.json.jbuilder │ │ ├── forum │ │ │ └── posts │ │ │ │ ├── _post_publish_data.json.jbuilder │ │ │ │ └── create.json.jbuilder │ │ ├── plagiarism │ │ │ └── assessments │ │ │ │ └── _plagiarism_checks.json.jbuilder │ │ ├── material │ │ │ ├── _material.json.jbuilder │ │ │ └── folders │ │ │ │ ├── upload_materials.json.jbuilder │ │ │ │ └── breadcrumbs.json.jbuilder │ │ ├── levels │ │ │ └── index.json.jbuilder │ │ ├── surveys │ │ │ └── _survey_lesson_plan_item.json.jbuilder │ │ └── courses │ │ │ └── _course_list_data.json.jbuilder │ ├── user │ │ ├── registrations │ │ │ └── create.json.jbuilder │ │ ├── profiles │ │ │ ├── show.json.jbuilder │ │ │ └── edit.json.jbuilder │ │ └── emails │ │ │ └── index.json.jbuilder │ ├── users │ │ └── _instance_list_data.json.jbuilder │ ├── announcements │ │ └── index.json.jbuilder │ ├── attachments │ │ └── _attachment_reference.json.jbuilder │ ├── system │ │ └── admin │ │ │ └── instance │ │ │ ├── admin │ │ │ └── index.json.jbuilder │ │ │ └── user_invitations │ │ │ └── index.json.jbuilder │ ├── instance_user_role_requests │ │ └── index.json.jbuilder │ ├── instance_user_role_request_mailer │ │ ├── role_request_approved.text.erb │ │ ├── role_request_rejected.html.slim │ │ ├── role_request_rejected.text.erb │ │ └── role_request_approved.html.slim │ ├── instance │ │ └── mailer │ │ │ ├── user_added_email.text.erb │ │ │ └── user_added_email.html.slim │ ├── notifiers │ │ └── course │ │ │ └── consolidated_opening_reminder_notifier │ │ │ └── opening_reminder │ │ │ └── course_notifications │ │ │ └── course │ │ │ ├── _video.html.slim │ │ │ ├── _survey.html.slim │ │ │ └── _assessment.html.slim │ └── attachment_references │ │ └── create.json.jbuilder ├── models │ ├── course │ │ ├── settings.rb │ │ ├── lesson_plan │ │ │ └── event_material.rb │ │ ├── settings │ │ │ ├── components.rb │ │ │ └── users_component.rb │ │ ├── discussion.rb │ │ ├── monitoring.rb │ │ ├── lesson_plan.rb │ │ └── learning_map.rb │ ├── instance │ │ ├── settings.rb │ │ └── settings │ │ │ └── components.rb │ ├── .rubocop.yml │ ├── system │ │ └── announcement.rb │ ├── concerns │ │ └── user_notifications_concern.rb │ ├── application_record.rb │ └── cikgo_user.rb ├── jobs │ └── application_job.rb ├── mailers │ └── application_mailer.rb ├── services │ ├── course │ │ └── assessment │ │ │ ├── question │ │ │ └── programming │ │ │ │ ├── cpp │ │ │ │ └── cpp_autograde_include.cc │ │ │ │ └── python │ │ │ │ └── python_autograde_pre.py │ │ │ └── answer │ │ │ └── prompts │ │ │ └── rubric_auto_grading_user_prompt.json │ └── authentication │ │ └── verification_service.rb ├── controllers │ ├── course │ │ ├── forum │ │ │ └── component_controller.rb │ │ ├── assessment │ │ │ ├── component_controller.rb │ │ │ ├── condition │ │ │ │ ├── levels_controller.rb │ │ │ │ ├── surveys_controller.rb │ │ │ │ ├── achievements_controller.rb │ │ │ │ ├── assessments_controller.rb │ │ │ │ └── scholaistic_assessments_controller.rb │ │ │ └── submission │ │ │ │ ├── logs_controller.rb │ │ │ │ └── controller.rb │ │ ├── achievement │ │ │ └── condition │ │ │ │ ├── levels_controller.rb │ │ │ │ ├── surveys_controller.rb │ │ │ │ ├── assessments_controller.rb │ │ │ │ └── achievements_controller.rb │ │ └── video │ │ │ └── submission │ │ │ └── controller.rb │ ├── system │ │ └── admin │ │ │ ├── instance │ │ │ └── admin_controller.rb │ │ │ └── controller.rb │ ├── concerns │ │ └── signals │ │ │ └── slices │ │ │ ├── cikgo_open_threads_count.rb │ │ │ ├── videos.rb │ │ │ ├── cikgo_mission_control.rb │ │ │ ├── forums.rb │ │ │ ├── comments.rb │ │ │ ├── announcements.rb │ │ │ └── enrol_requests.rb │ ├── health_check_controller.rb │ └── test │ │ └── controller.rb └── helpers │ └── course │ └── group │ └── group_categories_helper.rb ├── spec ├── fixtures │ ├── files │ │ ├── text.txt │ │ ├── text2.txt │ │ ├── template_file │ │ ├── template_file_2 │ │ ├── picture.jpg │ │ ├── one-page-document.pdf │ │ ├── two-page-document.pdf │ │ ├── one-page-word-document.docx │ │ └── two-page-document-with-text.pdf │ ├── libraries │ │ ├── inherited_nested_layouts │ │ │ ├── content.html │ │ │ └── layouts │ │ │ │ └── test_layout.html.erb │ │ ├── render_within_layout │ │ │ ├── content.html.erb │ │ │ ├── layouts │ │ │ │ └── outer_layout.html.erb │ │ │ └── inner_layout.html.erb │ │ ├── render_partial_with_prefix_suffix │ │ │ ├── _base.html │ │ │ ├── _base_suffix.html │ │ │ └── _prefix_base.html │ │ └── componentize │ │ │ └── test_component.rb │ ├── course │ │ ├── invitation_with_utf_bom.csv │ │ ├── empty_programming_question_template.zip │ │ ├── invitation_no_header.csv │ │ ├── invitation_invalid_email.csv │ │ ├── invitation_empty.csv │ │ ├── invitation_invalid.csv │ │ ├── ssid │ │ │ └── submissions.zip │ │ ├── koditsu │ │ │ ├── koditsu_question_failure_response_test.json │ │ │ └── koditsu_assessment_failure_response_test.json │ │ ├── programming_question_template.zip │ │ ├── invitation_whitespace.csv │ │ ├── programming_question_template_codaveri.zip │ │ └── programming_question_template_with_add_files.zip │ └── activity_mailer │ │ ├── test_email.text.erb │ │ └── test_email.html.slim ├── support │ ├── minion.png │ ├── factory_bot.rb │ ├── stubs │ │ ├── ssid │ │ │ └── _root.rb │ │ ├── codaveri │ │ │ └── _root.rb │ │ └── langchain │ │ │ └── _root.rb │ ├── userstamp.rb │ ├── shoulda_matchers.rb │ └── rspec_html_matchers.rb ├── jobs │ └── application_job_spec.rb ├── .rubocop.yml ├── models │ ├── instance │ │ └── announcement_spec.rb │ ├── duplication_traceable_spec.rb │ ├── user │ │ └── identity_spec.rb │ └── course │ │ ├── assessment │ │ ├── plagiarism_check_spec.rb │ │ ├── answer │ │ │ └── auto_grading_spec.rb │ │ └── submission │ │ │ └── log_spec.rb │ │ ├── learning_map_spec.rb │ │ ├── requirement_spec.rb │ │ └── forum │ │ ├── topic │ │ └── view_spec.rb │ │ └── subscription_spec.rb ├── factories │ ├── course_learning_map.rb │ ├── nested_attribute_new_ids.rb │ ├── system_announcements.rb │ ├── course_levels.rb │ ├── course_forum_topic_views.rb │ ├── course_group_categories.rb │ ├── duplication_traceable_courses.rb │ ├── course_assessment_plagiarism_checks.rb │ ├── duplication_traceable_assessments.rb │ ├── course_assessment_answer_auto_gradings.rb │ ├── course_assessment_question_scribings.rb │ └── course_assessment_skills.rb └── controllers │ └── course │ └── assessment │ └── condition │ ├── levels_controller_spec.rb │ ├── surveys_controller_spec.rb │ ├── assessments_controller_spec.rb │ └── achievements_controller_spec.rb ├── config ├── image_optim.yml ├── credentials │ ├── test.key │ ├── development.key │ └── test.yml.enc ├── initializers │ ├── locale.rb │ ├── userstamp.rb │ ├── rack_mini_profiler.rb │ ├── acts_as_tenant.rb │ ├── extensions.rb │ ├── mime_types.rb │ ├── redis.rb │ └── session_store.rb ├── locales │ ├── ko │ │ ├── course │ │ │ ├── plagiarism.yml │ │ │ ├── surveys.yml │ │ │ ├── material │ │ │ │ └── materials.yml │ │ │ ├── scholaistic.yml │ │ │ ├── learning_map.yml │ │ │ ├── enrol_requests.yml │ │ │ ├── stories.yml │ │ │ ├── reference_timelines.yml │ │ │ ├── survey │ │ │ │ └── responses.yml │ │ │ ├── levels.yml │ │ │ ├── statistics.yml │ │ │ ├── forum │ │ │ │ └── forums.yml │ │ │ ├── assessment │ │ │ │ ├── skills.yml │ │ │ │ ├── question │ │ │ │ │ ├── voice_responses.yml │ │ │ │ │ ├── forum_post_response.yml │ │ │ │ │ └── multiple_responses.yml │ │ │ │ ├── live_feedback │ │ │ │ │ └── thread.yml │ │ │ │ └── submissions.yml │ │ │ ├── announcements.yml │ │ │ ├── video │ │ │ │ └── videos.yml │ │ │ ├── experience_points │ │ │ │ ├── disbursement.yml │ │ │ │ └── forum_disbursement.yml │ │ │ ├── user_invitations.yml │ │ │ ├── achievement │ │ │ │ └── achievements.yml │ │ │ ├── leaderboards.yml │ │ │ └── mailer │ │ │ │ ├── submission_graded_email.yml │ │ │ │ ├── survey_closing_reminder_email.yml │ │ │ │ ├── user_rejected_email.yml │ │ │ │ ├── course_duplicate_failed_email.yml │ │ │ │ └── user_added_email.yml │ │ ├── time.yml │ │ ├── notifiers.yml │ │ ├── jobs.yml │ │ ├── activerecord │ │ │ ├── course │ │ │ │ ├── condition │ │ │ │ │ ├── level.yml │ │ │ │ │ └── condition.yml │ │ │ │ ├── experience_points_record.yml │ │ │ │ ├── survey │ │ │ │ │ └── answer.yml │ │ │ │ ├── user_invitation.yml │ │ │ │ ├── forum │ │ │ │ │ └── topic.yml │ │ │ │ ├── assessment │ │ │ │ │ ├── skill.yml │ │ │ │ │ └── answer │ │ │ │ │ │ └── text_response.yml │ │ │ │ ├── announcement.yml │ │ │ │ ├── personal_time.yml │ │ │ │ ├── user_achievement.yml │ │ │ │ ├── video │ │ │ │ │ └── session.yml │ │ │ │ ├── video.yml │ │ │ │ ├── group_user.yml │ │ │ │ ├── scholaistic_assessment.yml │ │ │ │ └── monitoring │ │ │ │ │ └── heartbeat.yml │ │ │ ├── time_zone_validator.yml │ │ │ ├── course_user.yml │ │ │ ├── generic_announcement.yml │ │ │ ├── duplication_traceable.yml │ │ │ ├── filename_validator.yml │ │ │ └── instance.yml │ │ ├── common.yml │ │ └── user │ │ │ └── emails.yml │ ├── zh │ │ ├── course │ │ │ ├── plagiarism.yml │ │ │ ├── surveys.yml │ │ │ ├── material │ │ │ │ └── materials.yml │ │ │ ├── scholaistic.yml │ │ │ ├── enrol_requests.yml │ │ │ ├── stories.yml │ │ │ ├── learning_map.yml │ │ │ ├── survey │ │ │ │ └── responses.yml │ │ │ ├── reference_timelines.yml │ │ │ ├── forum │ │ │ │ └── forums.yml │ │ │ ├── levels.yml │ │ │ ├── statistics.yml │ │ │ ├── assessment │ │ │ │ ├── skills.yml │ │ │ │ ├── question │ │ │ │ │ ├── voice_responses.yml │ │ │ │ │ ├── forum_post_response.yml │ │ │ │ │ └── multiple_responses.yml │ │ │ │ ├── live_feedback │ │ │ │ │ └── thread.yml │ │ │ │ └── submissions.yml │ │ │ ├── announcements.yml │ │ │ ├── video │ │ │ │ └── videos.yml │ │ │ ├── experience_points │ │ │ │ ├── disbursement.yml │ │ │ │ └── forum_disbursement.yml │ │ │ ├── user_invitations.yml │ │ │ ├── achievement │ │ │ │ └── achievements.yml │ │ │ ├── leaderboards.yml │ │ │ └── mailer │ │ │ │ ├── submission_graded_email.yml │ │ │ │ ├── user_rejected_email.yml │ │ │ │ ├── survey_closing_reminder_email.yml │ │ │ │ ├── user_added_email.yml │ │ │ │ └── course_duplicate_failed_email.yml │ │ ├── time.yml │ │ ├── notifiers.yml │ │ ├── jobs.yml │ │ ├── activerecord │ │ │ ├── course │ │ │ │ ├── condition │ │ │ │ │ ├── level.yml │ │ │ │ │ └── condition.yml │ │ │ │ ├── experience_points_record.yml │ │ │ │ ├── survey │ │ │ │ │ └── answer.yml │ │ │ │ ├── user_invitation.yml │ │ │ │ ├── forum │ │ │ │ │ └── topic.yml │ │ │ │ ├── announcement.yml │ │ │ │ ├── personal_time.yml │ │ │ │ ├── user_achievement.yml │ │ │ │ ├── video.yml │ │ │ │ ├── assessment │ │ │ │ │ ├── skill.yml │ │ │ │ │ ├── answer │ │ │ │ │ │ └── text_response.yml │ │ │ │ │ └── question │ │ │ │ │ │ └── text_response_solution.yml │ │ │ │ ├── video │ │ │ │ │ └── session.yml │ │ │ │ ├── group_user.yml │ │ │ │ ├── scholaistic_assessment.yml │ │ │ │ └── monitoring │ │ │ │ │ └── heartbeat.yml │ │ │ ├── time_zone_validator.yml │ │ │ ├── course_user.yml │ │ │ ├── generic_announcement.yml │ │ │ ├── duplication_traceable.yml │ │ │ ├── filename_validator.yml │ │ │ └── instance.yml │ │ ├── common.yml │ │ ├── user │ │ │ └── emails.yml │ │ ├── activemodel │ │ │ └── course │ │ │ │ └── experience_points │ │ │ │ └── forum_disbursement.yml │ │ └── instance │ │ │ └── mailer │ │ │ └── user_added_email.yml │ └── en │ │ ├── course │ │ ├── surveys.yml │ │ ├── plagiarism.yml │ │ ├── material │ │ │ └── materials.yml │ │ ├── scholaistic.yml │ │ ├── learning_map.yml │ │ ├── enrol_requests.yml │ │ ├── stories.yml │ │ ├── levels.yml │ │ ├── reference_timelines.yml │ │ ├── forum │ │ │ └── forums.yml │ │ ├── assessment │ │ │ ├── skills.yml │ │ │ ├── question │ │ │ │ ├── voice_responses.yml │ │ │ │ ├── forum_post_response.yml │ │ │ │ └── multiple_responses.yml │ │ │ └── live_feedback │ │ │ │ └── thread.yml │ │ ├── statistics.yml │ │ ├── survey │ │ │ └── responses.yml │ │ ├── announcements.yml │ │ ├── video │ │ │ └── videos.yml │ │ ├── experience_points │ │ │ ├── forum_disbursement.yml │ │ │ └── disbursement.yml │ │ ├── achievement │ │ │ └── achievements.yml │ │ ├── leaderboards.yml │ │ ├── user_invitations.yml │ │ └── mailer │ │ │ ├── submission_graded_email.yml │ │ │ └── survey_closing_reminder_email.yml │ │ ├── time.yml │ │ ├── notifiers.yml │ │ ├── activerecord │ │ ├── course │ │ │ ├── condition │ │ │ │ └── level.yml │ │ │ ├── experience_points_record.yml │ │ │ ├── survey │ │ │ │ └── answer.yml │ │ │ ├── user_invitation.yml │ │ │ ├── announcement.yml │ │ │ ├── personal_time.yml │ │ │ ├── assessment │ │ │ │ ├── skill.yml │ │ │ │ └── answer │ │ │ │ │ └── text_response.yml │ │ │ ├── forum │ │ │ │ └── topic.yml │ │ │ ├── user_achievement.yml │ │ │ ├── video │ │ │ │ └── session.yml │ │ │ └── group_user.yml │ │ ├── time_zone_validator.yml │ │ ├── course_user.yml │ │ ├── generic_announcement.yml │ │ └── duplication_traceable.yml │ │ ├── jobs.yml │ │ └── common.yml ├── boot.rb ├── spring.rb └── environment.rb ├── client ├── app │ ├── routers │ │ └── index.ts │ ├── bundles │ │ └── course │ │ │ ├── container │ │ │ ├── Sidebar │ │ │ │ └── index.ts │ │ │ └── Breadcrumbs │ │ │ │ └── index.ts │ │ │ ├── reference-timelines │ │ │ ├── contexts │ │ │ │ └── index.ts │ │ │ ├── views │ │ │ │ └── DayView │ │ │ │ │ └── index.ts │ │ │ └── components │ │ │ │ ├── TimeBar │ │ │ │ └── index.ts │ │ │ │ ├── TimePopup │ │ │ │ └── index.ts │ │ │ │ ├── DayCalendar │ │ │ │ └── index.ts │ │ │ │ ├── TimelinesStack │ │ │ │ └── index.ts │ │ │ │ └── TimelinesOverview │ │ │ │ └── index.ts │ │ │ ├── plagiarism │ │ │ ├── constants.ts │ │ │ └── selectors.ts │ │ │ ├── group │ │ │ ├── pages │ │ │ │ └── GroupShow │ │ │ │ │ └── GroupManager │ │ │ │ │ └── index.js │ │ │ └── actions │ │ │ │ └── index.js │ │ │ ├── video │ │ │ └── submission │ │ │ │ └── containers │ │ │ │ └── Statistics.scss │ │ │ ├── learning-map │ │ │ └── components │ │ │ │ └── ConnectionPoint │ │ │ │ └── ConnectionPoint.scss │ │ │ ├── level │ │ │ └── selector.ts │ │ │ ├── statistics │ │ │ └── utils │ │ │ │ └── parseStaffResponse.js │ │ │ └── assessment │ │ │ └── question │ │ │ ├── reducers │ │ │ └── index.ts │ │ │ └── scribing │ │ │ └── types.ts │ ├── lib │ │ ├── components │ │ │ ├── table │ │ │ │ ├── MuiTableAdapter │ │ │ │ │ └── index.ts │ │ │ │ ├── TanStackTableBuilder │ │ │ │ │ └── index.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── adapters │ │ │ │ │ ├── Handlers.ts │ │ │ │ │ └── Sort.ts │ │ │ │ └── builder │ │ │ │ │ └── index.ts │ │ │ └── core │ │ │ │ ├── fields │ │ │ │ └── AceEditor.css │ │ │ │ └── layouts │ │ │ │ └── layout.scss │ │ ├── hooks │ │ │ └── toast │ │ │ │ └── index.ts │ │ ├── containers │ │ │ └── AppContainer │ │ │ │ └── index.ts │ │ ├── history.js │ │ └── constants │ │ │ └── index.js │ ├── types │ │ ├── course │ │ │ ├── learn.ts │ │ │ ├── material │ │ │ │ └── files.ts │ │ │ ├── duplication.ts │ │ │ ├── assessment │ │ │ │ ├── submission │ │ │ │ │ └── annotations.ts │ │ │ │ ├── monitoring.ts │ │ │ │ └── sessions.ts │ │ │ └── admin │ │ │ │ ├── materials.ts │ │ │ │ └── announcements.ts │ │ └── system │ │ │ └── instance │ │ │ └── components.ts │ ├── __test__ │ │ └── mocks │ │ │ ├── fileMock.js │ │ │ ├── svgMock.js │ │ │ ├── requestAnimationFrame.js │ │ │ └── ResizeObserver.js │ ├── assets │ │ ├── images │ │ │ ├── home │ │ │ │ ├── jumbotron.png │ │ │ │ ├── icon-simple.png │ │ │ │ ├── icon-engaging.png │ │ │ │ └── icon-general.png │ │ │ └── achievement-blank.png │ │ ├── templates │ │ │ └── course-user-invitation-template.csv │ │ └── icons │ │ │ └── pointer.svg │ └── api │ │ ├── system │ │ ├── Base.ts │ │ └── index.js │ │ └── course │ │ └── Admin │ │ └── Base.ts ├── .yarn-integrity ├── .eslintignore ├── .prettierignore ├── postcss.config.js ├── .prettierrc.js └── CONTRIBUTING.md ├── .yardopts ├── public └── img │ ├── un_main.png │ ├── 504-error.png │ └── rocket_service.png ├── bin ├── rake ├── bundle └── rails ├── .rspec ├── tests └── declaration.d.ts ├── .hound.yml ├── authentication ├── theme │ └── coursemology-keycloakify-keycloak-theme-6.1.7.jar └── env ├── config.ru └── CONTRIBUTING.md /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /db/seeds/production.rb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /spec/fixtures/files/text.txt: -------------------------------------------------------------------------------- 1 | This is a test file -------------------------------------------------------------------------------- /config/image_optim.yml: -------------------------------------------------------------------------------- 1 | skip_missing_workers: true 2 | -------------------------------------------------------------------------------- /spec/fixtures/files/text2.txt: -------------------------------------------------------------------------------- 1 | This is some test text. -------------------------------------------------------------------------------- /app/views/layouts/no_greeting_mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /config/credentials/test.key: -------------------------------------------------------------------------------- 1 | 00bcc95e1b3a44b1ba9766807383d3cb -------------------------------------------------------------------------------- /spec/fixtures/files/template_file: -------------------------------------------------------------------------------- 1 | sample template file 1 2 | -------------------------------------------------------------------------------- /spec/fixtures/files/template_file_2: -------------------------------------------------------------------------------- 1 | sample template file 2 2 | -------------------------------------------------------------------------------- /spec/fixtures/libraries/inherited_nested_layouts/content.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/credentials/development.key: -------------------------------------------------------------------------------- 1 | 921054b69df2e11efe48fcc33e5e6c3b -------------------------------------------------------------------------------- /spec/fixtures/course/invitation_with_utf_bom.csv: -------------------------------------------------------------------------------- 1 | Test,baz@foo.com,student -------------------------------------------------------------------------------- /spec/fixtures/libraries/render_within_layout/content.html.erb: -------------------------------------------------------------------------------- 1 | test! 2 | -------------------------------------------------------------------------------- /client/app/routers/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './AuthenticatableApp'; 2 | -------------------------------------------------------------------------------- /spec/fixtures/course/empty_programming_question_template.zip: -------------------------------------------------------------------------------- 1 | PK -------------------------------------------------------------------------------- /client/.yarn-integrity: -------------------------------------------------------------------------------- 1 | 549854b8a60607db81d4c58008d59f812d744acba026266f380acd942941356a -------------------------------------------------------------------------------- /client/.eslintignore: -------------------------------------------------------------------------------- 1 | vendor/**/* 2 | node_modules/**/* 3 | build/**/* 4 | coverage/** 5 | -------------------------------------------------------------------------------- /client/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | build 3 | coverage 4 | vendor 5 | *.yml 6 | public/* -------------------------------------------------------------------------------- /client/app/bundles/course/container/Sidebar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Sidebar'; 2 | -------------------------------------------------------------------------------- /spec/fixtures/activity_mailer/test_email.text.erb: -------------------------------------------------------------------------------- 1 | Plain text test 2 | <%= @object.id %> 3 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --protected 2 | --no-private 3 | --embed-mixin ClassMethods 4 | --markup markdown 5 | -------------------------------------------------------------------------------- /app/models/course/settings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Settings; end 3 | -------------------------------------------------------------------------------- /client/app/lib/components/table/MuiTableAdapter/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './MuiTable'; 2 | -------------------------------------------------------------------------------- /lib/extensions/legacy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Legacy 3 | end 4 | -------------------------------------------------------------------------------- /spec/fixtures/course/invitation_no_header.csv: -------------------------------------------------------------------------------- 1 | Foo,bar@foo.com 2 | Blank Email,blank@name.com 3 | -------------------------------------------------------------------------------- /spec/fixtures/libraries/render_partial_with_prefix_suffix/_base.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /app/models/instance/settings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Instance::Settings; end 3 | -------------------------------------------------------------------------------- /client/app/bundles/course/container/Breadcrumbs/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './Breadcrumbs'; 2 | -------------------------------------------------------------------------------- /client/app/bundles/course/reference-timelines/contexts/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LastSavedContext'; 2 | -------------------------------------------------------------------------------- /client/app/types/course/learn.ts: -------------------------------------------------------------------------------- 1 | export interface LearnSettingsData { 2 | title: string; 3 | } 4 | -------------------------------------------------------------------------------- /lib/extensions/attachable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Attachable; end 3 | -------------------------------------------------------------------------------- /lib/extensions/conditional.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Conditional; end 3 | -------------------------------------------------------------------------------- /lib/extensions/materials.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Materials; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/course/invitation_invalid_email.csv: -------------------------------------------------------------------------------- 1 | name,email,role 2 | baz,foo.com 3 | bar,twang.com 4 | -------------------------------------------------------------------------------- /app/views/jobs/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! @job.status, job: @job 3 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= t('.greeting', user: @recipient.name) %> 2 | 3 | <%= yield %> 4 | -------------------------------------------------------------------------------- /client/app/__test__/mocks/fileMock.js: -------------------------------------------------------------------------------- 1 | // File used for jest moduleNameMapper 2 | module.exports = {}; 3 | -------------------------------------------------------------------------------- /client/app/__test__/mocks/svgMock.js: -------------------------------------------------------------------------------- 1 | // File used for jest moduleNameMapper 2 | module.exports = 'div'; 3 | -------------------------------------------------------------------------------- /config/initializers/locale.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | I18n.available_locales = [:en, :zh, :ko] 3 | -------------------------------------------------------------------------------- /config/locales/ko/course/plagiarism.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | plagiarism: 4 | header: '표절 검사' 5 | -------------------------------------------------------------------------------- /config/locales/ko/course/surveys.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | surveys: 4 | sidebar_title: '설문' 5 | -------------------------------------------------------------------------------- /config/locales/zh/course/plagiarism.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | plagiarism: 4 | header: '抄袭检查' 5 | -------------------------------------------------------------------------------- /config/locales/zh/course/surveys.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | surveys: 4 | sidebar_title: '调查' 5 | -------------------------------------------------------------------------------- /config/locales/zh/time.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | time: 3 | formats: 4 | default: '%a, %Y %b %d %H:%M:%S' 5 | -------------------------------------------------------------------------------- /lib/extensions/database_event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DatabaseEvent; end 3 | -------------------------------------------------------------------------------- /public/img/un_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/public/img/un_main.png -------------------------------------------------------------------------------- /spec/fixtures/libraries/render_partial_with_prefix_suffix/_base_suffix.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /spec/fixtures/libraries/render_partial_with_prefix_suffix/_prefix_base.html: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /spec/support/minion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/support/minion.png -------------------------------------------------------------------------------- /client/app/bundles/course/plagiarism/constants.ts: -------------------------------------------------------------------------------- 1 | export const ASSESSMENTS_POLL_INTERVAL_MILLISECONDS = 5000; 2 | -------------------------------------------------------------------------------- /client/app/bundles/course/reference-timelines/views/DayView/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './DayView'; 2 | -------------------------------------------------------------------------------- /config/locales/en/course/surveys.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | surveys: 4 | sidebar_title: 'Surveys' 5 | -------------------------------------------------------------------------------- /config/locales/en/time.yml: -------------------------------------------------------------------------------- 1 | en: 2 | time: 3 | formats: 4 | default: '%a, %d %b %Y %I:%M:%S %p' 5 | -------------------------------------------------------------------------------- /config/locales/ko/time.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | time: 3 | formats: 4 | default: '%a, %Y %b %d %p %I:%M:%S' 5 | -------------------------------------------------------------------------------- /lib/extensions/acts_as_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::ActsAsHelpers; end 3 | -------------------------------------------------------------------------------- /lib/extensions/core_extensions.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::CoreExtensions; end 3 | -------------------------------------------------------------------------------- /lib/extensions/discussion_topic.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DiscussionTopic; end 3 | -------------------------------------------------------------------------------- /lib/extensions/pathname_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::PathnameHelpers; end 3 | -------------------------------------------------------------------------------- /public/img/504-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/public/img/504-error.png -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /client/app/bundles/course/group/pages/GroupShow/GroupManager/index.js: -------------------------------------------------------------------------------- 1 | export { default } from './GroupManager'; 2 | -------------------------------------------------------------------------------- /client/app/bundles/course/reference-timelines/components/TimeBar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TimeBar'; 2 | -------------------------------------------------------------------------------- /client/app/bundles/course/reference-timelines/components/TimePopup/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TimePopup'; 2 | -------------------------------------------------------------------------------- /client/app/lib/components/table/TanStackTableBuilder/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './useTanStackTableBuilder'; 2 | -------------------------------------------------------------------------------- /config/locales/en/course/plagiarism.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | plagiarism: 4 | header: 'Plagiarism Check' 5 | -------------------------------------------------------------------------------- /config/locales/ko/course/material/materials.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | material: 4 | sidebar_title: '자료' 5 | -------------------------------------------------------------------------------- /config/locales/ko/course/scholaistic.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | scholaistic: 4 | assessments: "롤플레잉 평가" 5 | -------------------------------------------------------------------------------- /config/locales/zh/course/material/materials.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | material: 4 | sidebar_title: '材料' 5 | -------------------------------------------------------------------------------- /config/locales/zh/course/scholaistic.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | scholaistic: 4 | assessments: "角色扮演评估" 5 | -------------------------------------------------------------------------------- /lib/extensions/destroy_callbacks.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DestroyCallbacks; end 3 | -------------------------------------------------------------------------------- /lib/extensions/devise_async_email.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DeviseAsyncEmail; end 3 | -------------------------------------------------------------------------------- /lib/extensions/time_bounded_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::TimeBoundedRecord; end 3 | -------------------------------------------------------------------------------- /app/views/course/admin/lesson_plan_settings/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.merge! @page_data 3 | -------------------------------------------------------------------------------- /app/views/course/scholaistic/assistants/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.embedSrc @embed_src 3 | -------------------------------------------------------------------------------- /client/app/bundles/course/reference-timelines/components/DayCalendar/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './DayCalendar'; 2 | -------------------------------------------------------------------------------- /client/app/types/course/material/files.ts: -------------------------------------------------------------------------------- 1 | export interface FileListData { 2 | url: string; 3 | name: string; 4 | } 5 | -------------------------------------------------------------------------------- /lib/extensions/duplication_traceable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DuplicationTraceable; end 3 | -------------------------------------------------------------------------------- /lib/extensions/legacy/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Legacy::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/materials/action_view.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Materials::ActionView; end 3 | -------------------------------------------------------------------------------- /lib/extensions/polyglot_with_database.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::PolyglotWithDatabase; end 3 | -------------------------------------------------------------------------------- /public/img/rocket_service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/public/img/rocket_service.png -------------------------------------------------------------------------------- /spec/fixtures/course/invitation_empty.csv: -------------------------------------------------------------------------------- 1 | name,email 2 | Foo,bar@foo.com 3 | Blank Email, 4 | ,blank@name.com 5 | , 6 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --format progress 3 | --format ParallelTests::RSpec::RuntimeLogger --out tmp/parallel_runtime_rspec.log 4 | -------------------------------------------------------------------------------- /app/views/course/admin/notification_settings/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.array! @page_data 3 | -------------------------------------------------------------------------------- /app/views/course/condition/surveys/_survey.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.surveyId condition.survey_id 3 | -------------------------------------------------------------------------------- /app/views/course/mailer/course_duplicate_failed_email.text.erb: -------------------------------------------------------------------------------- 1 | <%= t('.message', original_course: @original_course.title) %> 2 | -------------------------------------------------------------------------------- /app/views/course/video/submission/sessions/create.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.id @session.id.to_s 3 | -------------------------------------------------------------------------------- /client/app/__test__/mocks/requestAnimationFrame.js: -------------------------------------------------------------------------------- 1 | global.requestAnimationFrame = (callback) => setTimeout(callback, 0); 2 | -------------------------------------------------------------------------------- /client/app/bundles/course/reference-timelines/components/TimelinesStack/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TimelinesStack'; 2 | -------------------------------------------------------------------------------- /config/locales/en/course/material/materials.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | material: 4 | sidebar_title: 'Materials' 5 | -------------------------------------------------------------------------------- /lib/extensions/attachable/action_view.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Attachable::ActionView; end 3 | -------------------------------------------------------------------------------- /lib/extensions/materials/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Materials::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/files/picture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/files/picture.jpg -------------------------------------------------------------------------------- /app/views/course/admin/material_settings/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.title @settings.title || '' 3 | -------------------------------------------------------------------------------- /app/views/jobs/_submitted.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.status job.status 3 | json.jobUrl job_path(job) 4 | -------------------------------------------------------------------------------- /client/app/lib/components/table/index.tsx: -------------------------------------------------------------------------------- 1 | export type { ColumnTemplate } from './builder'; 2 | export { default } from './Table'; 3 | -------------------------------------------------------------------------------- /config/locales/en/course/scholaistic.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | scholaistic: 4 | assessments: "Role-Playing Assessments" 5 | -------------------------------------------------------------------------------- /config/locales/ko/course/learning_map.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | learning_map: 4 | index: 5 | header: '학습 지도' 6 | -------------------------------------------------------------------------------- /config/locales/zh/course/enrol_requests.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | enrol_requests: 4 | index: 5 | header: '用户需求' 6 | -------------------------------------------------------------------------------- /config/locales/zh/course/stories.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | stories: 4 | learn: '学' 5 | mission_control: '任务控制' 6 | -------------------------------------------------------------------------------- /lib/extensions/action_mailer_suppression.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::ActionMailerSuppression; end 3 | -------------------------------------------------------------------------------- /lib/extensions/attachable/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Attachable::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/conditional/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Conditional::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/devise_async_email/devise.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DeviseAsyncEmail::Devise; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/libraries/inherited_nested_layouts/layouts/test_layout.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= yield %> 3 |
4 | -------------------------------------------------------------------------------- /spec/fixtures/libraries/render_within_layout/layouts/outer_layout.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= yield %> 3 |
4 | -------------------------------------------------------------------------------- /tests/declaration.d.ts: -------------------------------------------------------------------------------- 1 | interface Window { 2 | collectCoverage: (coverage: string) => void; 3 | __coverage__: object; 4 | } 5 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class ApplicationJob < ActiveJob::Base 3 | queue_as :default 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/admin/announcement_settings/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.title @settings.title || '' 3 | -------------------------------------------------------------------------------- /app/views/course/condition/levels/_level.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.minimumLevel condition.minimum_level 3 | -------------------------------------------------------------------------------- /client/app/bundles/course/reference-timelines/components/TimelinesOverview/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './TimelinesOverview'; 2 | -------------------------------------------------------------------------------- /client/app/lib/hooks/toast/index.ts: -------------------------------------------------------------------------------- 1 | export { default as loadingToast } from './loadingToast'; 2 | export { default } from './toast'; 3 | -------------------------------------------------------------------------------- /config/locales/en/course/learning_map.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | learning_map: 4 | index: 5 | header: 'Learning Map' 6 | -------------------------------------------------------------------------------- /config/locales/ko/course/enrol_requests.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | enrol_requests: 4 | index: 5 | header: '사용자 요청' 6 | -------------------------------------------------------------------------------- /config/locales/ko/course/stories.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | stories: 4 | learn: '배우다' 5 | mission_control: '미션 컨트롤' 6 | -------------------------------------------------------------------------------- /config/locales/ko/notifiers.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | notifiers: 3 | course: 4 | phantom: '(팬텀)' 5 | anonymous_user: '익명의 사용자' 6 | -------------------------------------------------------------------------------- /config/locales/zh/course/learning_map.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | learning_map: 4 | index: 5 | header: '学习路线' 6 | 7 | -------------------------------------------------------------------------------- /config/locales/zh/notifiers.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | notifiers: 3 | course: 4 | phantom: '(旁听用户)' 5 | anonymous_user: '一个匿名用户' 6 | -------------------------------------------------------------------------------- /lib/extensions/acts_as_helpers/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::ActsAsHelpers::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/attachable/action_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Attachable::ActionController; end 3 | -------------------------------------------------------------------------------- /lib/extensions/core_extensions/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::CoreExtensions::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/database_event/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DatabaseEvent::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/materials/action_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Materials::ActionController; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/activity_mailer/test_email.html.slim: -------------------------------------------------------------------------------- 1 | - message.subject = 'test mailer' 2 | h3 3 | | HTML test 4 | h3 5 | = @object.id 6 | -------------------------------------------------------------------------------- /app/views/course/mailer/course_duplicate_failed_email.html.slim: -------------------------------------------------------------------------------- 1 | = simple_format(t('.message', original_course: @original_course.title)) 2 | -------------------------------------------------------------------------------- /app/views/user/registrations/create.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.id @user.id 3 | json.confirmed @user.confirmed? 4 | -------------------------------------------------------------------------------- /client/app/bundles/course/group/actions/index.js: -------------------------------------------------------------------------------- 1 | export * from './categories'; 2 | export * from './general'; 3 | export * from './groups'; 4 | -------------------------------------------------------------------------------- /client/app/lib/containers/AppContainer/index.ts: -------------------------------------------------------------------------------- 1 | export { default } from './AppContainer'; 2 | export { useAppContext } from './AppLoader'; 3 | -------------------------------------------------------------------------------- /config/locales/en/course/enrol_requests.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | enrol_requests: 4 | index: 5 | header: 'User Requests' 6 | -------------------------------------------------------------------------------- /config/locales/zh/jobs.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | jobs: 3 | completed: 4 | completed: '任务已完成。' 5 | errored: 6 | errored: '任务出错。' 7 | -------------------------------------------------------------------------------- /lib/extensions/association_inverse_suppression.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::AssociationInverseSuppression; end 3 | -------------------------------------------------------------------------------- /lib/extensions/date_time_helpers/active_support.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DateTimeHelpers::ActiveSupport; end 3 | -------------------------------------------------------------------------------- /lib/extensions/destroy_callbacks/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DestroyCallbacks::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/discussion_topic/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DiscussionTopic::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/materials/action_view/helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Materials::ActionView::Helpers; end 3 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class ApplicationMailer < ActionMailer::Base 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/import_result.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'import_result' 3 | -------------------------------------------------------------------------------- /app/views/course/condition/achievements/_achievement.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.achievementId condition.achievement_id 3 | -------------------------------------------------------------------------------- /client/app/assets/images/home/jumbotron.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/client/app/assets/images/home/jumbotron.png -------------------------------------------------------------------------------- /config/locales/en/course/stories.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | stories: 4 | learn: 'Learn' 5 | mission_control: 'Mission Control' 6 | -------------------------------------------------------------------------------- /lib/extensions/deferred_workflow_state_persistence.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DeferredWorkflowStatePersistence; end 3 | -------------------------------------------------------------------------------- /lib/extensions/devise_async_email/devise/models.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DeviseAsyncEmail::Devise::Models; end 3 | -------------------------------------------------------------------------------- /lib/extensions/time_bounded_record/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::TimeBoundedRecord::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/course/invitation_invalid.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/course/invitation_invalid.csv -------------------------------------------------------------------------------- /spec/fixtures/course/ssid/submissions.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/course/ssid/submissions.zip -------------------------------------------------------------------------------- /spec/fixtures/files/one-page-document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/files/one-page-document.pdf -------------------------------------------------------------------------------- /spec/fixtures/files/two-page-document.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/files/two-page-document.pdf -------------------------------------------------------------------------------- /spec/jobs/application_job_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe ApplicationJob do 5 | end 6 | -------------------------------------------------------------------------------- /.hound.yml: -------------------------------------------------------------------------------- 1 | fail_on_violations: true 2 | 3 | rubocop: 4 | config_file: .rubocop.yml 5 | version: 1.22.1 6 | 7 | javascript: 8 | enabled: false 9 | -------------------------------------------------------------------------------- /app/models/.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: 2 | - ../../.rubocop.yml 3 | 4 | Style/MultilineBlockChain: # Needed for Squeel blocks. 5 | Enabled: false 6 | -------------------------------------------------------------------------------- /app/models/course/lesson_plan/event_material.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::LessonPlan::EventMaterial < ApplicationRecord 3 | end 4 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'form', course: current_course 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/new.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'form', course: current_course 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/scribing/_scribing.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.autogradable question.auto_gradable? 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question_groups/_form.html.slim: -------------------------------------------------------------------------------- 1 | = f.error_notification 2 | = f.input :title 3 | = f.input :weight 4 | = f.button :submit 5 | -------------------------------------------------------------------------------- /app/views/course/user_invitations/new.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.courseRegistrationKey current_course.registration_key.to_s 3 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /client/app/assets/images/home/icon-simple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/client/app/assets/images/home/icon-simple.png -------------------------------------------------------------------------------- /client/app/types/course/duplication.ts: -------------------------------------------------------------------------------- 1 | export interface DuplicationInstanceListData { 2 | id: number; 3 | name: string; 4 | host: string; 5 | } 6 | -------------------------------------------------------------------------------- /config/locales/en/notifiers.yml: -------------------------------------------------------------------------------- 1 | en: 2 | notifiers: 3 | course: 4 | phantom: '(Phantom)' 5 | anonymous_user: 'An anonymous user' 6 | -------------------------------------------------------------------------------- /config/locales/zh/course/survey/responses.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | survey: 4 | responses: 5 | no_course_user: '你必须是本课程的成员才能开始调研。' 6 | -------------------------------------------------------------------------------- /lib/extensions/duplication_traceable/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DuplicationTraceable::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/polyglot_with_database/coursemology.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::PolyglotWithDatabase::Coursemology; end 3 | -------------------------------------------------------------------------------- /lib/extensions/render_collection_with_prefix_suffix.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::RenderCollectionWithPrefixSuffix; end 3 | -------------------------------------------------------------------------------- /spec/support/factory_bot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | RSpec.configure do |config| 3 | config.include FactoryBot::Syntax::Methods 4 | end 5 | -------------------------------------------------------------------------------- /app/services/course/assessment/question/programming/cpp/cpp_autograde_include.cc: -------------------------------------------------------------------------------- 1 | #include "gtest/gtest.h" 2 | #include 3 | #include 4 | -------------------------------------------------------------------------------- /client/app/assets/images/achievement-blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/client/app/assets/images/achievement-blank.png -------------------------------------------------------------------------------- /client/app/assets/images/home/icon-engaging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/client/app/assets/images/home/icon-engaging.png -------------------------------------------------------------------------------- /client/app/assets/images/home/icon-general.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/client/app/assets/images/home/icon-general.png -------------------------------------------------------------------------------- /config/locales/ko/jobs.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | jobs: 3 | completed: 4 | completed: '작업이 완료되었습니다.' 5 | errored: 6 | errored: '작업에 오류가 발생했습니다.' 7 | -------------------------------------------------------------------------------- /lib/extensions/action_mailer_suppression/action_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::ActionMailerSuppression::ActionMailer; end 3 | -------------------------------------------------------------------------------- /lib/extensions/has_many_inverse_through/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::HasManyInverseThrough::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/tasks/coursemology/programming_question.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/lib/tasks/coursemology/programming_question.zip -------------------------------------------------------------------------------- /spec/.rubocop.yml: -------------------------------------------------------------------------------- 1 | inherit_from: 2 | - ../.rubocop.yml 3 | 4 | Metrics/AbcSize: 5 | Enabled: false 6 | 7 | Style/Documentation: 8 | Enabled: false 9 | -------------------------------------------------------------------------------- /spec/fixtures/files/one-page-word-document.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/files/one-page-word-document.docx -------------------------------------------------------------------------------- /app/views/course/assessment/question/voice_responses/_voice_response.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.autogradable question.auto_gradable? 3 | -------------------------------------------------------------------------------- /app/views/course/leaderboards/_leaderboard_group_list_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.id group.id 4 | json.name group.name.strip 5 | -------------------------------------------------------------------------------- /app/views/users/_instance_list_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.id instance.id 3 | json.name instance.name 4 | json.host instance.host 5 | -------------------------------------------------------------------------------- /client/app/types/course/assessment/submission/annotations.ts: -------------------------------------------------------------------------------- 1 | export interface Annotation { 2 | id: number; 3 | line: number; 4 | postIds: number[]; 5 | } 6 | -------------------------------------------------------------------------------- /client/app/types/system/instance/components.ts: -------------------------------------------------------------------------------- 1 | export interface ComponentData { 2 | key: string; 3 | displayName: string; 4 | enabled: boolean; 5 | } 6 | -------------------------------------------------------------------------------- /config/initializers/userstamp.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | ActiveRecord::Userstamp.configure do |config| 3 | config.deleter_attribute = nil 4 | end 5 | -------------------------------------------------------------------------------- /lib/extensions/legacy/active_record/connection_adapters.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::Legacy::ActiveRecord::ConnectionAdapters; end 3 | -------------------------------------------------------------------------------- /spec/support/stubs/ssid/_root.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # this file's name starts with _ because it needs to be required first 3 | module Ssid; end 4 | -------------------------------------------------------------------------------- /app/controllers/course/forum/component_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Forum::ComponentController < Course::Forum::Controller 3 | end 4 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /client/app/lib/components/core/fields/AceEditor.css: -------------------------------------------------------------------------------- 1 | .ace_invisible { 2 | opacity: 0; 3 | } 4 | 5 | .ace_invisible.ace_invisible_tab { 6 | opacity: 1; 7 | } 8 | -------------------------------------------------------------------------------- /config/initializers/rack_mini_profiler.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # TODO: Remove this once fully SPA 3 | Rack::MiniProfiler.config.position = 'top-right' 4 | -------------------------------------------------------------------------------- /config/locales/ko/course/reference_timelines.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | reference_timelines: 4 | reference_timeline: 5 | default_title: '기본 타임라인' 6 | -------------------------------------------------------------------------------- /config/locales/ko/course/survey/responses.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | survey: 4 | responses: 5 | no_course_user: '설문 조사를 시작하려면 이 과정의 멤버가 되어야 합니다.' 6 | -------------------------------------------------------------------------------- /config/locales/zh/course/reference_timelines.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | reference_timelines: 4 | reference_timeline: 5 | default_title: '默认时间线' 6 | -------------------------------------------------------------------------------- /spec/fixtures/files/two-page-document-with-text.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/files/two-page-document-with-text.pdf -------------------------------------------------------------------------------- /app/models/course/settings/components.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Settings::Components < Settings 3 | include ComponentSettingsConcern 4 | end 5 | -------------------------------------------------------------------------------- /app/models/system/announcement.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class System::Announcement < GenericAnnouncement 3 | validates :instance, absence: true 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/rubrics/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.array! @rubrics do |rubric| 4 | json.partial! 'rubric', rubric: rubric 5 | end 6 | -------------------------------------------------------------------------------- /app/views/jobs/_completed.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.status job.status 3 | json.redirectUrl job.redirect_to 4 | json.message t('.completed') 5 | -------------------------------------------------------------------------------- /config/locales/ko/course/levels.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | levels: 4 | sidebar_title: :'course.levels.index.header' 5 | index: 6 | header: '레벨' 7 | -------------------------------------------------------------------------------- /config/locales/ko/course/statistics.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | statistics: 4 | name: '이름' 5 | type: '학생 유형' 6 | email: '이메일' 7 | header: '통계' 8 | -------------------------------------------------------------------------------- /lib/extensions/polyglot_with_database/coursemology/polyglot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::PolyglotWithDatabase::Coursemology::Polyglot; end 3 | -------------------------------------------------------------------------------- /lib/extensions/render_collection_with_prefix_suffix/action_view.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::RenderCollectionWithPrefixSuffix::ActionView; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/course/koditsu/koditsu_question_failure_response_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorCode": "DTO", 3 | "messages": ["The provided id is not a valid ObjectId"] 4 | } 5 | -------------------------------------------------------------------------------- /spec/fixtures/course/programming_question_template.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/course/programming_question_template.zip -------------------------------------------------------------------------------- /spec/support/stubs/codaveri/_root.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # this file's name starts with _ because it needs to be required first 3 | module Codaveri; end 4 | -------------------------------------------------------------------------------- /spec/support/stubs/langchain/_root.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # this file's name starts with _ because it needs to be required first 3 | module Langchain; end 4 | -------------------------------------------------------------------------------- /app/models/course/discussion.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Course::Discussion 3 | def self.table_name_prefix 4 | 'course_discussion_' 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/models/course/monitoring.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Course::Monitoring 3 | def self.table_name_prefix 4 | 'course_monitoring_' 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/models/instance/settings/components.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Instance::Settings::Components < Settings 3 | include ComponentSettingsConcern 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/voice_responses/_form.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/skills', course: course 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/voice_responses/new.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'form', locals: { 3 | course: current_course 4 | } 5 | -------------------------------------------------------------------------------- /app/views/course/condition/_condition_list_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.id condition.id 3 | json.description format_inline_text(condition.title) 4 | -------------------------------------------------------------------------------- /app/views/course/group/groups/update.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.group do 3 | json.partial! partial: 'course/group/group', group: @group 4 | end 5 | -------------------------------------------------------------------------------- /config/locales/en/course/levels.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | levels: 4 | sidebar_title: :'course.levels.index.header' 5 | index: 6 | header: 'Levels' 7 | -------------------------------------------------------------------------------- /config/locales/en/course/reference_timelines.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | reference_timelines: 4 | reference_timeline: 5 | default_title: 'Default Timeline' 6 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/condition/level.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | attributes: 4 | course/condition/level/title: 5 | title: '레벨 %{value}' 6 | -------------------------------------------------------------------------------- /config/locales/ko/course/forum/forums.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | forum: 4 | forums: 5 | sidebar_title: '포럼' 6 | index: 7 | header: '포럼' 8 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/condition/level.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | attributes: 4 | course/condition/level/title: 5 | title: '等级 %{value}' 6 | -------------------------------------------------------------------------------- /config/locales/zh/course/forum/forums.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | forum: 4 | forums: 5 | sidebar_title: '论坛' 6 | index: 7 | header: '论坛' 8 | -------------------------------------------------------------------------------- /config/locales/zh/course/levels.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | levels: 4 | sidebar_title: :'course.levels.index.header' 5 | index: 6 | header: '等级' 7 | 8 | -------------------------------------------------------------------------------- /config/locales/zh/course/statistics.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | statistics: 4 | name: '用户名' 5 | type: '学生类型' 6 | email: 'Email' 7 | header: '数据' 8 | -------------------------------------------------------------------------------- /lib/extensions/deferred_workflow_state_persistence/active_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DeferredWorkflowStatePersistence::ActiveRecord; end 3 | -------------------------------------------------------------------------------- /lib/extensions/has_many_inverse_through/active_record/reflection.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::HasManyInverseThrough::ActiveRecord::Reflection; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/course/koditsu/koditsu_assessment_failure_response_test.json: -------------------------------------------------------------------------------- 1 | { 2 | "errorCode": "DTO", 3 | "messages": ["The provided id is not a valid ObjectId"] 4 | } 5 | -------------------------------------------------------------------------------- /spec/models/instance/announcement_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Instance::Announcement, type: :model do 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/course/assessment/component_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Assessment::ComponentController < Course::Assessment::Controller 3 | end 4 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/forum_post_responses/_form.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/skills', course: course 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/forum_post_responses/new.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'form', locals: { 3 | course: current_course 4 | } 5 | -------------------------------------------------------------------------------- /app/views/course/condition/scholaistic_assessments/_scholaistic_assessment.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.assessmentId condition.scholaistic_assessment_id 3 | -------------------------------------------------------------------------------- /app/views/course/mailer/course_user_deletion_failed_email.text.erb: -------------------------------------------------------------------------------- 1 | <%= t('.message', course_user_name: @course_user.name, 2 | course_name: @course.title) %> 3 | 4 | -------------------------------------------------------------------------------- /app/views/course/users/_user.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.userName user.name 3 | json.userLink link_to_user(user) 4 | json.userPicElement user_image(user) 5 | -------------------------------------------------------------------------------- /app/views/jobs/_errored.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.status job.status 3 | json.message t('.errored') 4 | json.errorMessage job_error_message(job.error) 5 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/condition/level.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | attributes: 4 | course/condition/level/title: 5 | title: 'Level %{value}' 6 | -------------------------------------------------------------------------------- /config/locales/en/course/forum/forums.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | forum: 4 | forums: 5 | sidebar_title: 'Forums' 6 | index: 7 | header: 'Forums' 8 | -------------------------------------------------------------------------------- /config/locales/en/jobs.yml: -------------------------------------------------------------------------------- 1 | en: 2 | jobs: 3 | completed: 4 | completed: 'The job has completed.' 5 | errored: 6 | errored: 'The job has encountered an error.' 7 | -------------------------------------------------------------------------------- /lib/extensions/has_many_inverse_through/active_record/associations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::HasManyInverseThrough::ActiveRecord::Associations; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/course/invitation_whitespace.csv: -------------------------------------------------------------------------------- 1 | name,email,role 2 | Foo ,bar@foo.com ,student 3 | Bar, baz@bar.com,teaching_assistant 4 | Baz , foo@baz.com ,student 5 | -------------------------------------------------------------------------------- /app/views/course/admin/discussion/topic_settings/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.title @settings.title || '' 3 | json.pagination @settings.pagination.to_i 4 | -------------------------------------------------------------------------------- /app/views/course/admin/rag_wise_settings/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.responseWorkflow @settings.response_workflow 3 | json.roleplay @settings.roleplay 4 | -------------------------------------------------------------------------------- /app/views/course/assessment/programming_evaluations/update_result.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.message @programming_evaluation.errors.full_messages.to_sentence 3 | -------------------------------------------------------------------------------- /app/views/course/statistics/statistics/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.codaveriComponentEnabled current_course.component_enabled?(Course::CodaveriComponent) 3 | -------------------------------------------------------------------------------- /app/views/course/users/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.user do 3 | json.partial! 'user_data', course_user: @course_user, should_show_timeline: true 4 | end 5 | -------------------------------------------------------------------------------- /client/app/api/system/Base.ts: -------------------------------------------------------------------------------- 1 | import BaseAPI from '../Base'; 2 | 3 | /** Course level Api helpers should be defined here */ 4 | export default class BaseSystemAPI extends BaseAPI {} 5 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 3 | 4 | require 'bundler/setup' # Set up gems listed in the Gemfile. 5 | -------------------------------------------------------------------------------- /config/locales/ko/course/assessment/skills.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | assessment: 4 | skills: 5 | sidebar_title: '기술' 6 | index: 7 | header: '기술' 8 | -------------------------------------------------------------------------------- /config/locales/zh/common.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | common: 3 | plain_text_link: '%{text} (%{url})' 4 | click_here: '点击此处' 5 | helpers: 6 | password: 7 | wrong_password: '密码错误' 8 | -------------------------------------------------------------------------------- /config/locales/zh/course/assessment/skills.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | assessment: 4 | skills: 5 | sidebar_title: '技能' 6 | index: 7 | header: '技能' 8 | -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | %w[ 3 | .ruby-version 4 | .rbenv-vars 5 | tmp/restart.txt 6 | tmp/caching-dev.txt 7 | ].each { |path| Spring.watch(path) } 8 | -------------------------------------------------------------------------------- /lib/extensions/time_bounded_record/active_record/connection_adapters.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::TimeBoundedRecord::ActiveRecord::ConnectionAdapters; end 3 | -------------------------------------------------------------------------------- /spec/factories/course_learning_map.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :learning_map, class: Course::LearningMap do 4 | course 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/fixtures/course/programming_question_template_codaveri.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/course/programming_question_template_codaveri.zip -------------------------------------------------------------------------------- /app/helpers/course/group/group_categories_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Course::Group::GroupCategoriesHelper 3 | include Course::Group::GroupManagerConcern 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/assessments/monitoring.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.courseId @course.id 3 | json.monitorId @monitor.id 4 | json.title @assessment.title 5 | -------------------------------------------------------------------------------- /client/app/assets/templates/course-user-invitation-template.csv: -------------------------------------------------------------------------------- 1 | Name,Email,Role,Phantom,Timeline 2 | John,test1@example.com,student,y,otot 3 | Mary,test2@example.com,teaching_assistant,n,fixed -------------------------------------------------------------------------------- /client/app/bundles/course/video/submission/containers/Statistics.scss: -------------------------------------------------------------------------------- 1 | .statisticsVideoView { 2 | display: block; 3 | margin-left: auto; 4 | margin-right: auto; 5 | width: 70%; 6 | } 7 | -------------------------------------------------------------------------------- /client/app/lib/components/core/layouts/layout.scss: -------------------------------------------------------------------------------- 1 | img { 2 | max-width: 100%; 3 | } 4 | 5 | .centeredTableHead { 6 | > span { 7 | justify-content: center; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /config/initializers/acts_as_tenant.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | ActsAsTenant.configure do |config| 3 | # We need to specify a tenant. 4 | config.require_tenant = true 5 | end 6 | -------------------------------------------------------------------------------- /config/locales/en/course/assessment/skills.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | assessment: 4 | skills: 5 | sidebar_title: 'Skills' 6 | index: 7 | header: 'Skills' 8 | -------------------------------------------------------------------------------- /config/locales/en/course/statistics.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | statistics: 4 | name: 'Name' 5 | type: 'Student Type' 6 | email: 'Email' 7 | header: 'Statistics' 8 | -------------------------------------------------------------------------------- /config/locales/en/course/survey/responses.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | survey: 4 | responses: 5 | no_course_user: 'You must be a member of this course to start the survey.' 6 | -------------------------------------------------------------------------------- /config/locales/ko/course/announcements.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | announcements: 4 | sidebar_title: :'course.announcements.index.header' 5 | index: 6 | header: '공지사항' 7 | -------------------------------------------------------------------------------- /config/locales/ko/course/assessment/question/voice_responses.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | assessment: 4 | question: 5 | voice_responses: 6 | question_type: '오디오 응답' 7 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/time_zone_validator.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | messages: 5 | time_zone_validator: 6 | invalid_time_zone: '时区不可用。' 7 | -------------------------------------------------------------------------------- /config/locales/zh/course/announcements.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | announcements: 4 | sidebar_title: :'course.announcements.index.header' 5 | index: 6 | header: '公告' 7 | -------------------------------------------------------------------------------- /config/locales/zh/course/assessment/question/voice_responses.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | assessment: 4 | question: 5 | voice_responses: 6 | question_type: 音频回答题 7 | -------------------------------------------------------------------------------- /db/migrate/20160722020938_add_time_zone_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddTimeZoneToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :users, :time_zone, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/autoload/illegal_state_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class IllegalStateError < StandardError 3 | def initialize(message = self.class.name) 4 | super 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/services/course/assessment/answer/prompts/rubric_auto_grading_user_prompt.json: -------------------------------------------------------------------------------- 1 | { 2 | "_type": "prompt", 3 | "input_variables": ["answer_text"], 4 | "template": "{answer_text}" 5 | } 6 | -------------------------------------------------------------------------------- /app/views/course/assessment/categories/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.categories do 3 | json.partial! 'category', collection: @categories, as: :category 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/programming_evaluations/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'programming_evaluation', programming_evaluation: @programming_evaluation 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/_r.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/programming/metadata/default', data: data 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/submission/submissions/_answers.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.answers answers do |answer| 3 | json.partial! answer, answer: answer 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/scholaistic/assistants/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.embedSrc @embed_src 3 | 4 | json.display do 5 | json.assistantTitle @assistant_title 6 | end 7 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/experience_points_record.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | attributes: 4 | course/experience_points_record: 5 | points_awarded: '경험치 부여됨' 6 | -------------------------------------------------------------------------------- /config/locales/ko/common.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | common: 3 | plain_text_link: '%{text} (%{url})' 4 | click_here: '여기를 클릭하세요' 5 | helpers: 6 | password: 7 | wrong_password: '잘못된 비밀번호' 8 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/experience_points_record.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | attributes: 4 | course/experience_points_record: 5 | points_awarded: '经验值奖励已获取' 6 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/survey/answer.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/survey/answer: 6 | cannot_be_empty: '这个问题的答案不能为空。' 7 | -------------------------------------------------------------------------------- /db/migrate/20230904095037_change_jobs_column_type.rb: -------------------------------------------------------------------------------- 1 | class ChangeJobsColumnType < ActiveRecord::Migration[6.0] 2 | def change 3 | change_column :jobs, :redirect_to, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/autoload/authentication_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AuthenticationError < StandardError 3 | def initialize(message = self.class.name) 4 | super 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/extensions/after_commit_action.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::AfterCommitAction; end 3 | ActiveRecord::Base.class_eval do 4 | include AfterCommitAction 5 | end 6 | -------------------------------------------------------------------------------- /lib/extensions/date_time_helpers/time.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DateTimeHelpers::Time 3 | ClassMethods = Extensions::DateTimeHelpers::TimeClassMethods 4 | end 5 | -------------------------------------------------------------------------------- /lib/extensions/has_many_inverse_through/active_record/associations/builder.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::HasManyInverseThrough::ActiveRecord::Associations::Builder; end 3 | -------------------------------------------------------------------------------- /spec/fixtures/libraries/render_within_layout/inner_layout.html.erb: -------------------------------------------------------------------------------- 1 | <%= render within_layout: 'outer_layout' do %> 2 |
3 | <%= yield %> 4 |
5 | <% end %> 6 | 7 | -------------------------------------------------------------------------------- /spec/models/duplication_traceable_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe DuplicationTraceable do 5 | it { is_expected.to be_actable } 6 | end 7 | -------------------------------------------------------------------------------- /app/models/course/lesson_plan.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Course::LessonPlan 3 | def self.table_name_prefix 4 | "#{Course.table_name.singularize}_lesson_plan_" 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/services/course/assessment/question/programming/python/python_autograde_pre.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | # Needs xmlrunner: pip install unittest-xml-reporting 3 | import xmlrunner 4 | import sys 5 | 6 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/_c_cpp.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/programming/metadata/default', data: data 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/_csharp.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/programming/metadata/default', data: data 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/_golang.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/programming/metadata/default', data: data 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/_python.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/programming/metadata/default', data: data 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/_rust.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/programming/metadata/default', data: data 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/rubrics/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.array! @rubrics do |rubric| 4 | json.partial! 'course/rubrics/rubric', rubric: rubric 5 | end 6 | -------------------------------------------------------------------------------- /app/views/course/assessment/submission/answer/forum_post_response/posts/selected.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'post_packs', selected_posts: @answer.compute_post_packs 3 | -------------------------------------------------------------------------------- /authentication/theme/coursemology-keycloakify-keycloak-theme-6.1.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/authentication/theme/coursemology-keycloakify-keycloak-theme-6.1.7.jar -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Load the Rails application. 3 | require_relative 'application' 4 | 5 | # Initialize the Rails application. 6 | Rails.application.initialize! 7 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/experience_points_record.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | attributes: 4 | course/experience_points_record: 5 | points_awarded: 'EXP Awarded' 6 | -------------------------------------------------------------------------------- /config/locales/en/common.yml: -------------------------------------------------------------------------------- 1 | en: 2 | common: 3 | plain_text_link: '%{text} (%{url})' 4 | click_here: 'Click here' 5 | helpers: 6 | password: 7 | wrong_password: 'Wrong password' 8 | -------------------------------------------------------------------------------- /config/locales/en/course/announcements.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | announcements: 4 | sidebar_title: :'course.announcements.index.header' 5 | index: 6 | header: 'Announcements' 7 | -------------------------------------------------------------------------------- /config/locales/en/course/assessment/question/voice_responses.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | assessment: 4 | question: 5 | voice_responses: 6 | question_type: Audio Response 7 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/time_zone_validator.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | messages: 5 | time_zone_validator: 6 | invalid_time_zone: '시간대가 유효하지 않습니다.' 7 | -------------------------------------------------------------------------------- /config/locales/zh/course/assessment/live_feedback/thread.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | assessment: 4 | live_feedback: 5 | thread: 6 | only_one_active_thread: '每个提交问题只能有一个活动线程' 7 | -------------------------------------------------------------------------------- /spec/fixtures/course/programming_question_template_with_add_files.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Coursemology/coursemology2/HEAD/spec/fixtures/course/programming_question_template_with_add_files.zip -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/_javascript.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/programming/metadata/default', data: data 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/_typescript.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/assessment/question/programming/metadata/default', data: data 3 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/partials/_file.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.filename file[:filename] 3 | json.size file[:size] 4 | json.hash file[:hash] 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/question_bundles/_form.html.slim: -------------------------------------------------------------------------------- 1 | = f.error_notification 2 | = f.input :title 3 | = f.association :question_group, collection: @assessment.question_groups 4 | = f.button :submit 5 | -------------------------------------------------------------------------------- /app/views/course/mailer/course_user_deletion_failed_email.html.slim: -------------------------------------------------------------------------------- 1 | = simple_format(t('.message', course_user_name: @course_user.name, 2 | course_name: @course.title)) 3 | 4 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # This file is used by Rack-based servers to start the application. 3 | 4 | require ::File.expand_path('config/environment', __dir__) 5 | run Rails.application 6 | -------------------------------------------------------------------------------- /config/initializers/extensions.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | Rails.application.config.before_initialize do 3 | require "#{Rails.root}/lib/extensions.rb" 4 | 5 | Extensions.load_all 6 | end 7 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/survey/answer.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/survey/answer: 6 | cannot_be_empty: '이 질문의 답변은 비워둘 수 없습니다.' 7 | -------------------------------------------------------------------------------- /config/locales/ko/course/video/videos.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | video: 4 | videos: 5 | sidebar_title: :'course.video.videos.index.header' 6 | index: 7 | header: '비디오' 8 | -------------------------------------------------------------------------------- /config/locales/zh/course/video/videos.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | video: 4 | videos: 5 | sidebar_title: :'course.video.videos.index.header' 6 | index: 7 | header: '视频' 8 | -------------------------------------------------------------------------------- /db/migrate/20241118152013_drop_virtual_classroom_table.rb: -------------------------------------------------------------------------------- 1 | class DropVirtualClassroomTable < ActiveRecord::Migration[7.0] 2 | def change 3 | drop_table :course_virtual_classrooms 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/nested_attribute_new_ids.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | sequence :nested_attribute_new_id do |n| 4 | Time.zone.now.to_i.to_s + n.to_s 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/condition/assessments/_assessment.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.assessmentId condition.assessment_id 3 | json.minimumGradePercentage condition.minimum_grade_percentage 4 | -------------------------------------------------------------------------------- /app/views/course/learning_map/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.nodes(@nodes.map { |node| node.deep_transform_keys { |key| key.to_s.camelize(:lower) } }) 3 | json.canModify @can_modify 4 | -------------------------------------------------------------------------------- /app/views/course/survey/responses/_see_other.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.responseId @response.id 3 | json.canModify can?(:modify, @response) 4 | json.canSubmit can?(:submit, @response) 5 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/time_zone_validator.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | messages: 5 | time_zone_validator: 6 | invalid_time_zone: 'The time zone is invalid.' 7 | -------------------------------------------------------------------------------- /config/locales/en/course/video/videos.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | video: 4 | videos: 5 | sidebar_title: :'course.video.videos.index.header' 6 | index: 7 | header: 'Videos' 8 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/user_invitation.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/user_invitation: 6 | existing_invitation: '此电子邮件地址已存在一个未完成的邀请' 7 | -------------------------------------------------------------------------------- /db/migrate/20161007061116_add_fields_to_assessments.rb: -------------------------------------------------------------------------------- 1 | class AddFieldsToAssessments < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_assessments, :password, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/extensions/render_collection_with_prefix_suffix/action_view/abstract_renderer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::RenderCollectionWithPrefixSuffix::ActionView::AbstractRenderer; end 3 | -------------------------------------------------------------------------------- /spec/support/userstamp.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | ActsAsTenant.with_tenant(Instance.default) do 3 | # Create a global stamper for this spec run 4 | User.stamper = User.human_users.first 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/system/admin/instance/admin_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class System::Admin::Instance::AdminController < System::Admin::Instance::Controller 3 | def index 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/models/course/learning_map.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::LearningMap < ApplicationRecord 3 | validates :course, presence: true 4 | belongs_to :course, inverse_of: :learning_map 5 | end 6 | -------------------------------------------------------------------------------- /app/views/course/leaderboards/_leaderboard_list_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.id course_user.id 4 | json.name course_user.name.strip 5 | json.imageUrl user_image(course_user.user) 6 | -------------------------------------------------------------------------------- /config/locales/ko/course/experience_points/disbursement.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | experience_points: 4 | disbursement: 5 | sidebar_title: '경험치' 6 | new: 7 | header: '경험 포인트 지급' 8 | -------------------------------------------------------------------------------- /config/locales/zh/course/experience_points/disbursement.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | experience_points: 4 | disbursement: 5 | sidebar_title: '经验值发放' 6 | new: 7 | header: '发放经验值' 8 | -------------------------------------------------------------------------------- /config/locales/zh/course/user_invitations.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | user_invitations: 4 | errors: 5 | duplicate_user: '%{user}在提交中出现了多次。' 6 | invalid_email: '%{email}无效:%{message}。' 7 | 8 | -------------------------------------------------------------------------------- /db/migrate/20150314025251_add_logo_to_courses.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddLogoToCourses < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :courses, :logo, :text 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20240512092424_add_session_id_column_to_user_table.rb: -------------------------------------------------------------------------------- 1 | class AddSessionIdColumnToUserTable < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :session_id, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/system_announcements.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :system_announcement, class: System::Announcement.name, parent: :generic_announcement do 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/fixtures/libraries/componentize/test_component.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class TestComponent 3 | include RSpec::ExampleGroups::Componentize::WhenIncludedInAClass::ComponentHost::Component 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/rubrics/fetch_answer_evaluations.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.partial! 'course/rubrics/answer_evaluation', collection: @answer_evaluations, as: :answer_evaluation 4 | -------------------------------------------------------------------------------- /app/views/course/lesson_plan/milestones/_milestone.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.(milestone, :id, :title, :description) 3 | json.start_at milestone.time_for(current_course_user).start_at&.iso8601 4 | -------------------------------------------------------------------------------- /app/views/course/users/_tabs_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.requestsCount current_course.enrol_requests.pending.count 3 | json.invitationsCount current_course.invitations.unconfirmed.count 4 | -------------------------------------------------------------------------------- /app/views/course/video/topics/_topics.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.topics do 3 | topics.each do |topic| 4 | json.set! topic.id do 5 | json.partial! topic 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/layouts/no_greeting_mailer.html.slim: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title 5 | = message.subject 6 | meta http-equiv="X-UA-Compatible" content="IE=edge" 7 | 8 | body 9 | = yield 10 | -------------------------------------------------------------------------------- /config/locales/ko/course/assessment/live_feedback/thread.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | assessment: 4 | live_feedback: 5 | thread: 6 | only_one_active_thread: '제출 질문당 활성화된 스레드는 하나만 존재할 수 있습니다' 7 | -------------------------------------------------------------------------------- /db/migrate/20170608050653_add_description_to_course_groups.rb: -------------------------------------------------------------------------------- 1 | class AddDescriptionToCourseGroups < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_groups, :description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170925095335_add_answer_to_posts.rb: -------------------------------------------------------------------------------- 1 | class AddAnswerToPosts < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_discussion_posts, :answer, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180208070853_remove_read_marks_foreign_key.rb: -------------------------------------------------------------------------------- 1 | class RemoveReadMarksForeignKey < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_foreign_key :read_marks, column: :reader_id 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230111111646_add_locale_column_to_user_table.rb: -------------------------------------------------------------------------------- 1 | class AddLocaleColumnToUserTable < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :users, :locale, :string, default: nil 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/extensions/date_time_helpers/active_support/time_zone.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DateTimeHelpers::ActiveSupport 3 | TimeZone = Extensions::DateTimeHelpers::TimeClassMethods 4 | end 5 | -------------------------------------------------------------------------------- /app/views/announcements/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.announcements @announcements do |announcement| 4 | json.partial! 'announcements/announcement_data', announcement: announcement 5 | end 6 | -------------------------------------------------------------------------------- /app/views/attachments/_attachment_reference.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.name attachment_reference.name 3 | json.path attachment_reference.path 4 | json.updater_name attachment_reference.updater.name 5 | -------------------------------------------------------------------------------- /app/views/system/admin/instance/admin/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.instance do 3 | json.id current_tenant.id 4 | json.name current_tenant.name 5 | json.host current_tenant.host 6 | end 7 | -------------------------------------------------------------------------------- /client/app/bundles/course/learning-map/components/ConnectionPoint/ConnectionPoint.scss: -------------------------------------------------------------------------------- 1 | $green: #2be809 !default; 2 | 3 | .selectableConnectionPoint:hover { 4 | box-shadow: 0 0 10px 5px $green; 5 | cursor: pointer; 6 | } 7 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/user_invitation.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/user_invitation: 6 | existing_invitation: '이 이메일 주소에는 아직 완료되지 않은 초대장이 있습니다' 7 | -------------------------------------------------------------------------------- /db/migrate/20150116102204_add_name_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddNameToUsers < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :users, :name, :string, null: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20161108030759_add_gamified_to_courses.rb: -------------------------------------------------------------------------------- 1 | class AddGamifiedToCourses < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :courses, :gamified, :boolean, default: true, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170915083041_remove_token_authentication_from_user.rb: -------------------------------------------------------------------------------- 1 | class RemoveTokenAuthenticationFromUser < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :users, :authentication_token 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211215055726_rename_delayed_to_is_delayed.rb: -------------------------------------------------------------------------------- 1 | class RenameDelayedToIsDelayed < ActiveRecord::Migration[6.0] 2 | def change 3 | rename_column :course_discussion_posts, :delayed, :is_delayed 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241216104132_add_deleted_column_in_course_user.rb: -------------------------------------------------------------------------------- 1 | class AddDeletedColumnInCourseUser < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :course_users, :deleted_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/autoload/component_not_found_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class ComponentNotFoundError < StandardError 3 | def initialize 4 | super('The component was disabled or does not exist') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /lib/autoload/invalid_data_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class InvalidDataError < StandardError 3 | def initialize(message = nil) 4 | super(message || 'The data is not in a valid format') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/models/user/identity_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe User::Identity, type: :model do 5 | it { is_expected.to belong_to(:user).inverse_of(:identities) } 6 | end 7 | -------------------------------------------------------------------------------- /spec/support/shoulda_matchers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | Shoulda::Matchers.configure do |config| 3 | config.integrate do |with| 4 | with.test_framework :rspec 5 | with.library :rails 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | We have shifted our contributing guides to our [Wiki](https://github.com/Coursemology/coursemology2/wiki). 4 | Please consult the guide before submitting a pull request to this repository. 5 | -------------------------------------------------------------------------------- /app/models/course/settings/users_component.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Settings::UsersComponent < Course::Settings::Component 3 | def self.component_class 4 | Course::UsersComponent 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/admin/rag_wise_settings/folders.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.folders @folders do |folder| 3 | json.id folder.id 4 | json.parentId folder.parent_id 5 | json.name folder.name 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/assessment/assessments/_assessment_conditional.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.title assessment_conditional.title 3 | json.url course_assessment_path(current_course, assessment_conditional) 4 | -------------------------------------------------------------------------------- /app/views/course/video/topics/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/video/topics/topics', locals: { topics: @topics } 3 | json.partial! 'course/video/topics/posts', locals: { posts: @posts } 4 | -------------------------------------------------------------------------------- /app/views/user/profiles/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.id current_user.id 3 | json.name current_user.name 4 | json.imageUrl user_image(current_user, url: true) 5 | json.primaryEmail current_user.email 6 | -------------------------------------------------------------------------------- /client/app/bundles/course/level/selector.ts: -------------------------------------------------------------------------------- 1 | import { AppState } from 'store'; 2 | 3 | import { LevelsState } from './types'; 4 | 5 | export const getLevels = (state: AppState): LevelsState => { 6 | return state.levels; 7 | }; 8 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/survey/answer.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/survey/answer: 6 | cannot_be_empty: 'The answer to this question must not be empty.' 7 | -------------------------------------------------------------------------------- /config/locales/ko/course/user_invitations.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | user_invitations: 4 | errors: 5 | duplicate_user: '%{user}가 제출물에 여러 번 나타납니다.' 6 | invalid_email: '%{email}이(가) 유효하지 않습니다: %{message}.' 7 | -------------------------------------------------------------------------------- /spec/controllers/course/assessment/condition/levels_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Assessment::Condition::LevelsController, type: :controller do 5 | end 6 | -------------------------------------------------------------------------------- /app/models/concerns/user_notifications_concern.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module UserNotificationsConcern 3 | # Get user's unread notifications 4 | def unread 5 | unread_by(proxy_association.owner) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/views/course/achievement/achievements/_achievement_conditional.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.title achievement_conditional.title 3 | json.url course_achievement_path(current_course, achievement_conditional) 4 | -------------------------------------------------------------------------------- /app/views/user/emails/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | sorted_emails = @emails.order(:confirmed_at).to_a 3 | 4 | json.emails sorted_emails do |email| 5 | json.partial! 'email_list_data', email: email 6 | end 7 | -------------------------------------------------------------------------------- /config/locales/en/course/experience_points/forum_disbursement.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | experience_points: 4 | forum_disbursement: 5 | new: 6 | header: :'course.experience_points.disbursement.new.header' 7 | -------------------------------------------------------------------------------- /config/locales/ko/course/experience_points/forum_disbursement.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | experience_points: 4 | forum_disbursement: 5 | new: 6 | header: :'course.experience_points.disbursement.new.header' 7 | -------------------------------------------------------------------------------- /config/locales/zh/course/experience_points/forum_disbursement.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | experience_points: 4 | forum_disbursement: 5 | new: 6 | header: :'course.experience_points.disbursement.new.header' 7 | -------------------------------------------------------------------------------- /db/migrate/20151202030421_add_profile_photo_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddProfilePhotoToUsers < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :users, :profile_photo, :text 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160916101014_change_discussion_posts_title.rb: -------------------------------------------------------------------------------- 1 | class ChangeDiscussionPostsTitle < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column :course_discussion_posts, :title, :string, null: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170915071654_add_last_active_at_to_instance_users.rb: -------------------------------------------------------------------------------- 1 | class AddLastActiveAtToInstanceUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :instance_users, :last_active_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/controllers/course/assessment/condition/surveys_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Assessment::Condition::SurveysController, type: :controller do 5 | end 6 | -------------------------------------------------------------------------------- /spec/models/course/assessment/plagiarism_check_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Assessment::PlagiarismCheck do 5 | it { is_expected.to belong_to(:assessment) } 6 | end 7 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class ApplicationRecord < ActiveRecord::Base 3 | self.abstract_class = true 4 | 5 | include ApplicationUserstampConcern 6 | include ApplicationActsAsConcern 7 | end 8 | -------------------------------------------------------------------------------- /app/services/authentication/verification_service.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Authentication::VerificationService 4 | Error = Struct.new(:message, :status) 5 | Response = Struct.new(:decoded_token, :error) 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/condition/assessments/_assessment_condition.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! partial: assessment_condition.conditional, suffix: 'conditional' 3 | json.description assessment_condition.title 4 | -------------------------------------------------------------------------------- /client/app/api/course/Admin/Base.ts: -------------------------------------------------------------------------------- 1 | import BaseCourseAPI from '../Base'; 2 | 3 | export default class BaseAdminAPI extends BaseCourseAPI { 4 | get urlPrefix(): string { 5 | return `/courses/${this.courseId}/admin`; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /client/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | 'tailwindcss/nesting': {}, 4 | tailwindcss: {}, 5 | autoprefixer: {}, 6 | ...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}), 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Be sure to restart your server when you modify this file. 3 | 4 | # Add new mime types for use in respond_to blocks: 5 | # Mime::Type.register "text/richtext", :rtf 6 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/user_invitation.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/user_invitation: 6 | existing_invitation: 'an open invitation exists for this email address' 7 | -------------------------------------------------------------------------------- /config/locales/ko/course/achievement/achievements.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | achievement: 4 | achievements: 5 | sidebar_title: :'course.achievement.achievements.index.header' 6 | index: 7 | header: '성과' 8 | -------------------------------------------------------------------------------- /config/locales/ko/course/leaderboards.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | leaderboards: 4 | sidebar_title: :'course.leaderboards.index.header' 5 | title: :'course.leaderboards.index.header' 6 | index: 7 | header: '리더보드' 8 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course_user.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course_user: 6 | attributes: 7 | reference_timeline: 8 | belongs_to_course: '必须隶属于课程' 9 | -------------------------------------------------------------------------------- /config/locales/zh/course/achievement/achievements.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | achievement: 4 | achievements: 5 | sidebar_title: :'course.achievement.achievements.index.header' 6 | index: 7 | header: '成就' 8 | -------------------------------------------------------------------------------- /config/locales/zh/course/leaderboards.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | leaderboards: 4 | sidebar_title: :'course.leaderboards.index.header' 5 | title: :'course.leaderboards.index.header' 6 | index: 7 | header: '排行榜' 8 | -------------------------------------------------------------------------------- /db/migrate/20161214050848_add_sent_at_to_course_user_invitations.rb: -------------------------------------------------------------------------------- 1 | class AddSentAtToCourseUserInvitations < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_user_invitations, :sent_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180220010332_remove_opening_reminder_token.rb: -------------------------------------------------------------------------------- 1 | class RemoveOpeningReminderToken < ActiveRecord::Migration[5.1] 2 | def change 3 | remove_column :course_lesson_plan_items, :opening_reminder_token, :float 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211210085034_add_delayed_post_column.rb: -------------------------------------------------------------------------------- 1 | class AddDelayedPostColumn < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :course_discussion_posts, :delayed, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/autoload/ssid_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class SsidError < StandardError 3 | def initialize(message = nil) 4 | super(message || 'SSID might be moody :(. Please try again later or contact admin') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/controllers/course/assessment/condition/assessments_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Assessment::Condition::AssessmentsController, type: :controller do 5 | end 6 | -------------------------------------------------------------------------------- /spec/models/course/assessment/answer/auto_grading_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Assessment::Answer::AutoGrading do 5 | it { is_expected.to belong_to(:answer) } 6 | end 7 | -------------------------------------------------------------------------------- /spec/models/course/learning_map_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::LearningMap, type: :model do 5 | it { is_expected.to belong_to(:course).inverse_of(:learning_map) } 6 | end 7 | -------------------------------------------------------------------------------- /app/models/cikgo_user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class CikgoUser < ApplicationRecord 3 | validates :user, presence: true 4 | validates :provided_user_id, presence: true 5 | 6 | belongs_to :user, inverse_of: :cikgo_user 7 | end 8 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/text_responses/new.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'form', locals: { 3 | course: current_course, 4 | question: @text_response_question, 5 | assessment: @assessment 6 | } 7 | -------------------------------------------------------------------------------- /app/views/course/assessment/submission/logs/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'info', course: current_course, assessment: @assessment, submission: @submission 3 | json.partial! 'logs', submission: @submission 4 | -------------------------------------------------------------------------------- /app/views/system/admin/instance/user_invitations/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.invitations @invitations.each do |invitation| 3 | json.partial! 'instance_user_invitation_list_data', invitation: invitation 4 | end 5 | -------------------------------------------------------------------------------- /client/app/bundles/course/statistics/utils/parseStaffResponse.js: -------------------------------------------------------------------------------- 1 | export const processStaff = (staff) => ({ 2 | ...staff, 3 | numGraded: parseInt(staff.numGraded ?? 0, 10), 4 | numStudents: parseInt(staff.numStudents ?? 0, 10), 5 | }); 6 | -------------------------------------------------------------------------------- /config/locales/en/course/assessment/live_feedback/thread.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | assessment: 4 | live_feedback: 5 | thread: 6 | only_one_active_thread: 'There can be only one active thread per submission question' 7 | -------------------------------------------------------------------------------- /config/locales/en/course/experience_points/disbursement.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | experience_points: 4 | disbursement: 5 | sidebar_title: 'Experience Points' 6 | new: 7 | header: 'Disburse Experience Points' 8 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course_user.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course_user: 6 | attributes: 7 | reference_timeline: 8 | belongs_to_course: '코스에 속해야 합니다' 9 | -------------------------------------------------------------------------------- /config/locales/zh/course/mailer/submission_graded_email.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | mailer: 4 | submission_graded_email: 5 | subject: '%{course}: 你%{assessment}的提交已被批改' 6 | message: > 7 | 点击%{submission}查看你的评分。 8 | -------------------------------------------------------------------------------- /db/migrate/20170602094949_change_length_of_invitation_key.rb: -------------------------------------------------------------------------------- 1 | class ChangeLengthOfInvitationKey < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column :course_user_invitations, :invitation_key, :string, limit: 32 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211226160941_add_satisfiability_type_to_videos.rb: -------------------------------------------------------------------------------- 1 | class AddSatisfiabilityTypeToVideos < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :course_videos, :satisfiability_type, :integer, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/controllers/course/assessment/condition/achievements_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Assessment::Condition::AchievementsController, type: :controller do 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/course_levels.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :course_level, class: Course::Level.name do 4 | course 5 | sequence(:experience_points_threshold) { |n| n * 100 } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/course/assessment/condition/levels_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Assessment::Condition::LevelsController < Course::Condition::LevelsController 3 | include Course::AssessmentConditionalConcern 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/programming_evaluations/_programming_evaluation.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.(programming_evaluation, :id, :memory_limit, :time_limit) 3 | json.language programming_evaluation.language.class.name 4 | -------------------------------------------------------------------------------- /app/views/course/assessment/skills/_options.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # required for scribing questions 3 | 4 | json.skills current_course.assessment_skills.order_by_title do |skill| 5 | json.(skill, :id, :title) 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/forum/posts/_post_publish_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.isTopicResolved topic.resolved? 4 | json.workflowState post.workflow_state 5 | json.partial! 'course/forum/posts/post_creator_data', post: post 6 | -------------------------------------------------------------------------------- /app/views/instance_user_role_requests/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.roleRequests @user_role_requests.each do |role_request| 3 | json.partial! 'instance_user_role_request_list_data', role_request: role_request 4 | end 5 | -------------------------------------------------------------------------------- /client/app/__test__/mocks/ResizeObserver.js: -------------------------------------------------------------------------------- 1 | class ResizeObserver { 2 | observe() {} 3 | 4 | unobserve() {} 5 | 6 | disconnect() {} 7 | } 8 | 9 | window.ResizeObserver = ResizeObserver; 10 | 11 | export default ResizeObserver; 12 | -------------------------------------------------------------------------------- /config/locales/en/course/achievement/achievements.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | achievement: 4 | achievements: 5 | sidebar_title: :'course.achievement.achievements.index.header' 6 | index: 7 | header: 'Achievements' 8 | -------------------------------------------------------------------------------- /config/locales/en/course/leaderboards.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | leaderboards: 4 | sidebar_title: :'course.leaderboards.index.header' 5 | title: :'course.leaderboards.index.header' 6 | index: 7 | header: 'Leaderboard' 8 | -------------------------------------------------------------------------------- /config/locales/en/course/user_invitations.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | user_invitations: 4 | errors: 5 | duplicate_user: '%{user} appears more than once in the submission.' 6 | invalid_email: '%{email} is invalid: %{message}.' 7 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/forum/topic.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | attributes: 4 | course/forum/topic/topic_type: 5 | normal: '일반' 6 | announcement: '공지' 7 | question: '질문' 8 | sticky: '고정' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/forum/topic.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | attributes: 4 | course/forum/topic/topic_type: 5 | normal: '常规' 6 | announcement: '公告' 7 | question: '提问' 8 | sticky: '便签' 9 | -------------------------------------------------------------------------------- /config/locales/zh/course/mailer/user_rejected_email.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | mailer: 4 | user_rejected_email: 5 | subject: '课程注册请求被拒绝 - %{course}' 6 | message: > 7 | 你在%{coursemology}上关于%{course}的课程申请已被拒绝! 8 | 9 | -------------------------------------------------------------------------------- /db/migrate/20150106073750_add_name_to_instances.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddNameToInstances < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :instances, :name, :string, null: false, unique: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160628052136_add_staff_only_comments_to_questions.rb: -------------------------------------------------------------------------------- 1 | class AddStaffOnlyCommentsToQuestions < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_assessment_questions, :staff_only_comments, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160716091234_add_autograded_to_course_assessments.rb: -------------------------------------------------------------------------------- 1 | class AddAutogradedToCourseAssessments < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_assessments, :autograded, :boolean, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20161027074807_add_session_id_to_submissions.rb: -------------------------------------------------------------------------------- 1 | class AddSessionIdToSubmissions < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_assessment_submissions, :session_id, :string, foreign_key: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170214062036_add_index_for_survey_response_user.rb: -------------------------------------------------------------------------------- 1 | class AddIndexForSurveyResponseUser < ActiveRecord::Migration[4.2] 2 | def change 3 | add_index :course_survey_responses, [:survey_id, :creator_id], unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170220123952_remove_image_from_survey_question_option.rb: -------------------------------------------------------------------------------- 1 | class RemoveImageFromSurveyQuestionOption < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :course_survey_question_options, :image, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211221163337_add_satisfiability_type_to_surveys.rb: -------------------------------------------------------------------------------- 1 | class AddSatisfiabilityTypeToSurveys < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :course_surveys, :satisfiability_type, :integer, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/autoload/koditsu_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class KoditsuError < StandardError 3 | def initialize(message = nil) 4 | super(message || 'Koditsu might be moody :(. Please try again later or contact admin') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/models/course/assessment/submission/log_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Assessment::Submission::Log, type: :model do 5 | it { is_expected.to belong_to(:submission) } 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/course/achievement/condition/levels_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Achievement::Condition::LevelsController < Course::Condition::LevelsController 3 | include Course::AchievementConditionalConcern 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/course/assessment/condition/surveys_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Assessment::Condition::SurveysController < Course::Condition::SurveysController 3 | include Course::AssessmentConditionalConcern 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/assessments/blocked_by_monitor.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'assessment_list_data', assessment: @assessment, category: @category, tab: @tab, course: current_course 3 | 4 | json.blocked true 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/mock_answers/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.array! @mock_answers do |mock_answer| 3 | json.id mock_answer.id 4 | json.answerText mock_answer.answer_text 5 | json.title '(Mock Answer)' 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/plagiarism/assessments/_plagiarism_checks.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.array! plagiarism_checks do |plagiarism_check| 3 | json.partial! 'plagiarism_check', locals: { plagiarism_check: plagiarism_check } 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/statistics/assessments/ancestor_info.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.array! @ancestors do |ancestor| 3 | json.id ancestor.id 4 | json.title ancestor.title 5 | json.courseTitle ancestor.course&.title 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/user_invitations/_course_user_invitation_list.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.invitations @invitations.each do |invitation| 4 | json.partial! 'course_user_invitation_list_data', invitation: invitation 5 | end 6 | -------------------------------------------------------------------------------- /app/views/instance_user_role_request_mailer/role_request_approved.text.erb: -------------------------------------------------------------------------------- 1 | <%= 2 | t( 3 | '.message', 4 | role: @instance_user.role, 5 | click_here: plain_link_to(t('common.click_here'), courses_url(host: @instance.host)) 6 | ) 7 | %> 8 | -------------------------------------------------------------------------------- /app/views/instance_user_role_request_mailer/role_request_rejected.html.slim: -------------------------------------------------------------------------------- 1 | - if @message 2 | = simple_format(t('.message', role: @instance_user.role, message: @message)) 3 | - else 4 | = simple_format(t('.message_empty', role: @instance_user.role)) 5 | -------------------------------------------------------------------------------- /app/views/instance_user_role_request_mailer/role_request_rejected.text.erb: -------------------------------------------------------------------------------- 1 | <% if @message %> 2 | <%= t('.message', role: @instance_user.role, message: @message) %> 3 | <% else %> 4 | <%= t('.message_empty', role: @instance_user.role) %> 5 | <% end %> 6 | -------------------------------------------------------------------------------- /client/app/bundles/course/assessment/question/reducers/index.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux'; 2 | 3 | import questionRubricsReducer from './rubrics'; 4 | 5 | export default combineReducers({ 6 | rubrics: questionRubricsReducer, 7 | }); 8 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course_user.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course_user: 6 | attributes: 7 | reference_timeline: 8 | belongs_to_course: 'must belong to course' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/announcement.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/announcement: 6 | attributes: 7 | end_at: 8 | cannot_be_before_start_at: '不能早于起始时间' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/personal_time.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/personal_time: 6 | attributes: 7 | start_at: 8 | cannot_be_after_end_at: '不能晚于结束时间' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/generic_announcement.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | generic_announcement: 6 | attributes: 7 | end_at: 8 | cannot_be_before_start_at: '不能早于起始时间' 9 | -------------------------------------------------------------------------------- /config/locales/zh/course/assessment/question/forum_post_response.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | assessment: 4 | question: 5 | forum_post_responses: 6 | new: 7 | header: '新论坛帖子回复问题' 8 | question_type: 论坛帖子回复问题 9 | -------------------------------------------------------------------------------- /config/locales/zh/course/mailer/survey_closing_reminder_email.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | mailer: 4 | survey_closing_reminder_email: 5 | subject: '%{course}: 相关提醒 %{survey}' 6 | message: > 7 | 请注意%{survey}将于%{time}过期。 8 | -------------------------------------------------------------------------------- /db/migrate/20150702122955_instance_users_change_user_id_unique.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class InstanceUsersChangeUserIdUnique < ActiveRecord::Migration[4.2] 3 | def change 4 | remove_index :instance_users, :user_id 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160126094510_add_badge_to_course_achievements.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddBadgeToCourseAchievements < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :course_achievements, :badge, :text 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160811064336_change_test_cases_expected_type.rb: -------------------------------------------------------------------------------- 1 | class ChangeTestCasesExpectedType < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column :course_assessment_question_programming_test_cases, :expected, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170110022335_remove_extra_bonus_exp_from_lesson_plan.rb: -------------------------------------------------------------------------------- 1 | class RemoveExtraBonusExpFromLessonPlan < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :course_lesson_plan_items, :extra_bonus_exp, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170819040619_add_role_to_course_user_invitation.rb: -------------------------------------------------------------------------------- 1 | class AddRoleToCourseUserInvitation < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_user_invitations, :role, :integer, default: 0, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220519055836_add_timeline_algorithm_to_user_invitation.rb: -------------------------------------------------------------------------------- 1 | class AddTimelineAlgorithmToUserInvitation < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :course_user_invitations, :timeline_algorithm, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220701045213_add_skip_grading_to_mrq.rb: -------------------------------------------------------------------------------- 1 | class AddSkipGradingToMrq < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :course_assessment_question_multiple_responses, :skip_grading, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20241129164745_remove_draft_programming_answer_column.rb: -------------------------------------------------------------------------------- 1 | class RemoveDraftProgrammingAnswerColumn < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_column :course_assessments, :allow_record_draft_answer, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/autoload/codaveri_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class CodaveriError < StandardError 3 | def initialize(message = nil) 4 | super(message || 'Codaveri might be moody :(. Please try again later or contact admin') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/factories/course_forum_topic_views.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :forum_topic_view, class: Course::Forum::Topic::View.name do 4 | association :topic, factory: :forum_topic 5 | user 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/models/course/requirement_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Condition, type: :model do 5 | it { is_expected.to be_actable } 6 | it { is_expected.to belong_to(:conditional) } 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/concerns/signals/slices/cikgo_open_threads_count.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Signals::Slices::CikgoOpenThreadsCount 3 | def generate_sync_for_cikgo_open_threads_count 4 | { learn: @open_threads_count } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/concerns/signals/slices/videos.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Signals::Slices::Videos 3 | include Course::UnreadCountsConcern 4 | 5 | def generate_sync_for_videos 6 | { videos: unwatched_videos_count } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/course/achievement/condition/surveys_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Achievement::Condition::SurveysController < Course::Condition::SurveysController 3 | include Course::AchievementConditionalConcern 4 | end 5 | -------------------------------------------------------------------------------- /app/controllers/health_check_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class HealthCheckController < ActionController::Base 4 | rescue_from(Exception) { head :service_unavailable } 5 | 6 | def show 7 | head :ok 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/views/course/admin/admin/time_zones.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.array! ActiveSupport::TimeZone.all do |time_zone| 3 | json.name time_zone.name 4 | json.displayName "(GMT#{time_zone.formatted_offset}) #{time_zone.name}" 5 | end 6 | -------------------------------------------------------------------------------- /app/views/course/assessment/categories/_category.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.(category, :id, :title, :weight) 3 | 4 | json.tabs do 5 | json.array! category.tabs do |tab| 6 | json.(tab, :id, :title, :weight) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/course/assessment/programming_evaluations/allocate.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'programming_evaluation', collection: @programming_evaluations, 3 | as: :programming_evaluation 4 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/forum_post_responses/_forum_post_response.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.autogradable question.auto_gradable? 3 | json.hasTextResponse question.has_text_response 4 | json.maxPosts question.max_posts 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/rubric_based_responses/new.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'form', locals: { 3 | course: current_course, 4 | question: @rubric_based_response_question, 5 | assessment: @assessment 6 | } 7 | -------------------------------------------------------------------------------- /app/views/course/video/topics/_posts.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.posts do 3 | posts.each do |post| 4 | json.set! post.id do 5 | json.partial! 'course/video/topics/post', locals: { post: post } 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /client/app/lib/history.js: -------------------------------------------------------------------------------- 1 | import { createBrowserHistory, createMemoryHistory } from 'history'; 2 | 3 | const history = 4 | process.env.NODE_ENV === 'test' 5 | ? createMemoryHistory({}) 6 | : createBrowserHistory({}); 7 | export default history; 8 | -------------------------------------------------------------------------------- /config/initializers/redis.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | redis_host = ENV['REDIS_HOST'] 4 | redis_port = 6379 5 | redis_password = ENV['REDIS_PASS'] 6 | 7 | REDIS = Redis.new(host: redis_host, port: redis_port, password: redis_password, db: 0) 8 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/assessment/skill.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/assessment/skill: 6 | attributes: 7 | course: 8 | consistent_course: '동일한 과정에 속해야 합니다' 9 | -------------------------------------------------------------------------------- /config/locales/ko/course/mailer/submission_graded_email.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | mailer: 4 | submission_graded_email: 5 | subject: '%{course}: %{assessment} 제출물이 채점되었습니다' 6 | message: > 7 | 성적을 보려면 %{submission}을 클릭하세요. 8 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/user_achievement.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/user_achievement: 6 | attributes: 7 | course_user: 8 | not_in_course: '选中的用户不在指定课程中' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/video.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/video: 6 | attributes: 7 | url: 8 | invalid_url: > 9 | 您输入的URL格式不正确,请重试。 10 | -------------------------------------------------------------------------------- /db/migrate/20170420063829_remove_length_limit_of_expression.rb: -------------------------------------------------------------------------------- 1 | class RemoveLengthLimitOfExpression < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column :course_assessment_question_programming_test_cases, :expression, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230404030133_add_auto_grading_queue_to_question.rb: -------------------------------------------------------------------------------- 1 | class AddAutoGradingQueueToQuestion < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :course_assessment_questions, :is_low_priority, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/course_group_categories.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :course_group_category, class: Course::GroupCategory.name do 4 | course 5 | sequence(:name) { |n| "Group Category #{n}" } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/duplication_traceable_courses.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :duplication_traceable_course, class: DuplicationTraceable::Course.name do 4 | source { build(:course) } 5 | course 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/concerns/signals/slices/cikgo_mission_control.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Signals::Slices::CikgoMissionControl 3 | def generate_sync_for_cikgo_mission_control 4 | { mission_control: @pending_threads_count } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/concerns/signals/slices/forums.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Signals::Slices::Forums 3 | include Course::UnreadCountsConcern 4 | 5 | def generate_sync_for_forums 6 | { forums: unread_forum_topics_count } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/course/admin/sidebar_settings/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.array! controller.sidebar_items(type: :settings) do |option| 3 | json.title option[:title] 4 | json.weight option[:weight] 5 | json.path option[:path] 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/forum/posts/create.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.post do 4 | json.partial! 'post_list_data', forum: @forum, topic: @topic, post: @post 5 | end 6 | 7 | json.postTreeIds @topic.posts.ordered_topologically.sorted_ids 8 | -------------------------------------------------------------------------------- /app/views/course/mailer/user_rejected_email.text.erb: -------------------------------------------------------------------------------- 1 | <%= t('.message', course: plain_link_to(@course.title, course_url(@course, host: @course.instance.host)), 2 | coursemology: plain_link_to(t('layout.coursemology'), @course.instance.host)) %> 3 | -------------------------------------------------------------------------------- /app/views/course/material/_material.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.id material.id 3 | json.updated_at material.updated_at&.iso8601 4 | json.name format_inline_text(material.name) 5 | json.url url_to_material(current_course, folder, material) 6 | -------------------------------------------------------------------------------- /app/views/course/scholaistic/scholaistic_assessments/new.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.embedSrc @embed_src 3 | 4 | json.display do 5 | json.assessmentsTitle current_course.settings(:course_scholaistic_component)&.assessments_title 6 | end 7 | -------------------------------------------------------------------------------- /app/views/instance_user_role_request_mailer/role_request_approved.html.slim: -------------------------------------------------------------------------------- 1 | = simple_format(\ 2 | t('.message', 3 | role: @instance_user.role, 4 | click_here: link_to(t('common.click_here'), courses_url(host: @instance.host))\ 5 | )\ 6 | ) 7 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/announcement.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/announcement: 6 | attributes: 7 | end_at: 8 | cannot_be_before_start_at: '시작 시각보다 이를 수 없습니다' 9 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/personal_time.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/personal_time: 6 | attributes: 7 | start_at: 8 | cannot_be_after_end_at: '종료 시각 이후일 수 없습니다' 9 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/generic_announcement.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | generic_announcement: 6 | attributes: 7 | end_at: 8 | cannot_be_before_start_at: '시작 시각보다 이를 수 없습니다' 9 | -------------------------------------------------------------------------------- /config/locales/ko/course/assessment/question/forum_post_response.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | assessment: 4 | question: 5 | forum_post_responses: 6 | new: 7 | header: '새 포럼 게시물 응답 질문' 8 | question_type: '포럼 게시물 응답' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/condition/condition.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/condition: 6 | attributes: 7 | conditional: 8 | not_in_same_course: '您选择的条件与当前条件不在同一课程中' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/duplication_traceable.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | duplication_traceable: 6 | attributes: 7 | source_id: 8 | must_exist: '源必须存在并且是dependent_class的一个实例。' 9 | -------------------------------------------------------------------------------- /config/locales/zh/course/assessment/question/multiple_responses.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | assessment: 4 | question: 5 | multiple_responses: 6 | question_type: 7 | multiple_response: 多解题 8 | multiple_choice: 多选题 9 | -------------------------------------------------------------------------------- /db/migrate/20160808023535_change_course_assessment_questions_title_nullity.rb: -------------------------------------------------------------------------------- 1 | class ChangeCourseAssessmentQuestionsTitleNullity < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column_null :course_assessment_questions, :title, true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20161006063146_rename_assessments_display_mode.rb: -------------------------------------------------------------------------------- 1 | class RenameAssessmentsDisplayMode < ActiveRecord::Migration[4.2] 2 | def change 3 | change_table :course_assessments do |t| 4 | t.rename :display_mode, :mode 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20161116075305_add_tabbed_view_to_course_assessments.rb: -------------------------------------------------------------------------------- 1 | class AddTabbedViewToCourseAssessments < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_assessments, :tabbed_view, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20210112074249_add_show_mcq_answer_to_course_assessments.rb: -------------------------------------------------------------------------------- 1 | class AddShowMcqAnswerToCourseAssessments < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :course_assessments, :show_mcq_answer, :boolean, default: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20240510173545_add_time_limit_for_timed_assessment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddTimeLimitForTimedAssessment < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :course_assessments, :time_limit, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20240830080332_remove_live_feedback_settings_from_assessment.rb: -------------------------------------------------------------------------------- 1 | class RemoveLiveFeedbackSettingsFromAssessment < ActiveRecord::Migration[7.0] 2 | def change 3 | remove_column :course_assessments, :live_feedback_enabled, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /lib/extensions/date_time_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Extensions::DateTimeHelpers 3 | module TimeClassMethods 4 | def min 5 | utc(0) 6 | end 7 | 8 | def max 9 | utc(5000) 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/controllers/course/video/submission/controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Video::Submission::Controller < Course::Video::Controller 3 | load_and_authorize_resource :submission, class: 'Course::Video::Submission', through: :video 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/question_groups/new.html.slim: -------------------------------------------------------------------------------- 1 | / = page_header 'New Question Group' 2 | 3 | = simple_form_for @question_group, url: course_assessment_question_groups_path(current_course, @assessment) do |f| 4 | = render partial: 'form', locals: { f: f } 5 | -------------------------------------------------------------------------------- /app/views/course/levels/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.levels @levels.map do |level| 3 | json.levelId level.id 4 | json.experiencePointsThreshold level.experience_points_threshold 5 | end 6 | json.canManage can?(:manage, @levels.first) 7 | -------------------------------------------------------------------------------- /app/views/course/video/videos/_video_statistics.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.video do 3 | json.videoUrl @video.url 4 | end 5 | 6 | json.statistics do 7 | json.watchFrequency @video.statistic&.watch_freq || @video.watch_frequency 8 | end 9 | -------------------------------------------------------------------------------- /app/views/instance/mailer/user_added_email.text.erb: -------------------------------------------------------------------------------- 1 | <%= t('.message', instance: plain_link_to(@instance.name, @instance.host), 2 | coursemology: plain_link_to(t('layout.coursemology'), @instance.host), 3 | email: @recipient.email) %> 4 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Be sure to restart your server when you modify this file. 3 | 4 | Rails.application.config.session_store( 5 | :cookie_store, 6 | key: '_coursemology2_session', 7 | same_site: :lax 8 | ) 9 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/announcement.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/announcement: 6 | attributes: 7 | end_at: 8 | cannot_be_before_start_at: 'cannot be before start at' 9 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/personal_time.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/personal_time: 6 | attributes: 7 | start_at: 8 | cannot_be_after_end_at: 'cannot be after end at' 9 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/user_achievement.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/user_achievement: 6 | attributes: 7 | course_user: 8 | not_in_course: '선택한 사용자가 지정된 코스에 없습니다' 9 | -------------------------------------------------------------------------------- /config/locales/ko/course/assessment/question/multiple_responses.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | assessment: 4 | question: 5 | multiple_responses: 6 | question_type: 7 | multiple_response: '다답형' 8 | multiple_choice: '객관식' 9 | -------------------------------------------------------------------------------- /config/locales/ko/course/mailer/survey_closing_reminder_email.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | mailer: 4 | survey_closing_reminder_email: 5 | subject: '%{course}: %{survey}에 대한 알림' 6 | message: > 7 | %{survey}가 %{time}에 만료될 예정이니 참고하시기 바랍니다. 8 | -------------------------------------------------------------------------------- /config/locales/ko/course/mailer/user_rejected_email.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | mailer: 4 | user_rejected_email: 5 | subject: '강좌 등록 요청이 거부되었습니다 - %{course}' 6 | message: > 7 | %{coursemology}에서 %{course} 강좌에 대한 귀하의 등록 요청이 거부되었습니다! 8 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/assessment/skill.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/assessment/skill: 6 | attributes: 7 | course: 8 | consistent_course: '必须属于同一课程' 9 | 10 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/video/session.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/video/session: 6 | attributes: 7 | session_start: 8 | cannot_be_after_session_end: '课时开始时间不能晚于结束时间' 9 | -------------------------------------------------------------------------------- /db/migrate/20151018122902_add_grade_to_course_assessment_answer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddGradeToCourseAssessmentAnswer < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :course_assessment_answers, :grade, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20161107023238_add_attempt_limit_to_programming_questions.rb: -------------------------------------------------------------------------------- 1 | class AddAttemptLimitToProgrammingQuestions < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_assessment_question_programming, :attempt_limit, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180403011936_add_phantom_to_course_user_invitations.rb: -------------------------------------------------------------------------------- 1 | class AddPhantomToCourseUserInvitations < ActiveRecord::Migration[5.1] 2 | def change 3 | add_column :course_user_invitations, :phantom, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20210819132022_block_student_viewing_submission.rb: -------------------------------------------------------------------------------- 1 | class BlockStudentViewingSubmission < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :course_assessments, :block_student_viewing_after_submitted, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211027083820_add_topics_auto_subscribe_to_forum.rb: -------------------------------------------------------------------------------- 1 | class AddTopicsAutoSubscribeToForum < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :course_forums, :forum_topics_auto_subscribe, :boolean, default: true, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/concerns/signals/slices/comments.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Signals::Slices::Comments 3 | include Course::UnreadCountsConcern 4 | 5 | def generate_sync_for_comments 6 | { discussion_topics: unread_comments_count } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/course/achievement/condition/assessments_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Achievement::Condition::AssessmentsController < 3 | Course::Condition::AssessmentsController 4 | include Course::AchievementConditionalConcern 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/course/assessment/condition/achievements_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Assessment::Condition::AchievementsController < 3 | Course::Condition::AchievementsController 4 | include Course::AssessmentConditionalConcern 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/course/assessment/condition/assessments_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Assessment::Condition::AssessmentsController < 3 | Course::Condition::AssessmentsController 4 | include Course::AssessmentConditionalConcern 5 | end 6 | -------------------------------------------------------------------------------- /app/views/course/assessment/question_bundles/new.html.slim: -------------------------------------------------------------------------------- 1 | / = page_header 'New Question Bundle' 2 | 3 | = simple_form_for @question_bundle, url: course_assessment_question_bundles_path(current_course, @assessment) do |f| 4 | = render partial: 'form', locals: { f: f } 5 | -------------------------------------------------------------------------------- /app/views/course/assessment/rubrics/fetch_mock_answer_evaluations.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.partial! 'course/rubrics/mock_answer_evaluation', 4 | collection: @mock_answer_evaluations, 5 | as: :answer_evaluation 6 | -------------------------------------------------------------------------------- /app/views/course/material/folders/upload_materials.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Response with the uploaded materials 3 | json.materials @materials do |material| 4 | json.partial! 'course/material/material', material: material, folder: @folder 5 | end 6 | -------------------------------------------------------------------------------- /app/views/course/survey/surveys/_survey_with_questions.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/survey/surveys/survey', survey: survey, survey_time: survey_time 3 | json.sections @sections, partial: 'course/survey/sections/section', as: :section 4 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.slim: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title 5 | = message.subject 6 | meta http-equiv="X-UA-Compatible" content="IE=edge" 7 | 8 | body 9 | p 10 | = t('.greeting', user: @recipient.name) 11 | 12 | = yield 13 | -------------------------------------------------------------------------------- /client/app/assets/icons/pointer.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /client/app/lib/constants/index.js: -------------------------------------------------------------------------------- 1 | import mirrorCreator from 'mirror-creator'; 2 | 3 | const actionTypes = mirrorCreator([ 4 | 'SET_NOTIFICATION', 5 | 'SHOW_DELETE_CONFIRMATION', 6 | 'RESET_DELETE_CONFIRMATION', 7 | ]); 8 | 9 | export default actionTypes; 10 | -------------------------------------------------------------------------------- /client/app/types/course/admin/materials.ts: -------------------------------------------------------------------------------- 1 | export interface MaterialsSettingsData { 2 | title: string; 3 | } 4 | 5 | export interface MaterialsSettingsPostData { 6 | settings_materials_component: { 7 | title: MaterialsSettingsData['title']; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /client/app/types/course/assessment/monitoring.ts: -------------------------------------------------------------------------------- 1 | export interface MonitoringRequestData { 2 | courseId: number; 3 | monitorId: number; 4 | title: string; 5 | } 6 | 7 | export interface SebPayload { 8 | config_key_hash: string; 9 | url: string; 10 | } 11 | -------------------------------------------------------------------------------- /client/app/types/course/assessment/sessions.ts: -------------------------------------------------------------------------------- 1 | export interface SessionFormData { 2 | password: string; 3 | submissionId: string | number; 4 | } 5 | 6 | export interface SessionFormPostData { 7 | password: string; 8 | submission_id: string | number; 9 | } 10 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/assessment/skill.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/assessment/skill: 6 | attributes: 7 | course: 8 | consistent_course: 'must belong to the same course' 9 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/forum/topic.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | attributes: 4 | course/forum/topic/topic_type: 5 | normal: 'Normal' 6 | announcement: 'Announcement' 7 | question: 'Question' 8 | sticky: 'Sticky' 9 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/generic_announcement.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | generic_announcement: 6 | attributes: 7 | end_at: 8 | cannot_be_before_start_at: 'cannot be before start at' 9 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/video/session.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/video/session: 6 | attributes: 7 | session_start: 8 | cannot_be_after_session_end: '세션은 종료 후에 시작할 수 없습니다' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/group_user.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/group_user: 6 | not_enrolled: '必须与小组成员加入在同一课程' 7 | attributes: 8 | course/group_user: 9 | manager: '讲师' 10 | -------------------------------------------------------------------------------- /config/locales/zh/user/emails.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | user: 3 | emails: 4 | index: 5 | header: '邮箱' 6 | set_primary: 7 | no_confirmed_emails: '没有已验证的邮箱地址可以设置为主要邮箱。' 8 | send_confirmation: 9 | already_confirmed: '%{email}已验证。' 10 | -------------------------------------------------------------------------------- /db/migrate/20150512014731_add_workflow_state_to_course_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddWorkflowStateToCourseUsers < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :course_users, :workflow_state, :string, null: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20170120063357_change_default_value_of_assessment_questions_weight.rb: -------------------------------------------------------------------------------- 1 | class ChangeDefaultValueOfAssessmentQuestionsWeight < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column_default(:course_assessment_questions, :weight, nil) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170210073247_add_selected_to_survey_answer_options.rb: -------------------------------------------------------------------------------- 1 | class AddSelectedToSurveyAnswerOptions < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_survey_answer_options, :selected, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20170306051518_rename_lectures_to_virtual_classrooms.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class RenameLecturesToVirtualClassrooms < ActiveRecord::Migration[4.2] 3 | def change 4 | rename_table :course_lectures, :course_virtual_classrooms 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20181018043204_make_scribing_scribbles_answer_id_non_null.rb: -------------------------------------------------------------------------------- 1 | class MakeScribingScribblesAnswerIdNonNull < ActiveRecord::Migration[5.1] 2 | def change 3 | change_column_null :course_assessment_answer_scribing_scribbles, :answer_id, false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20211210015400_change_forum_post_response_answer_text_type.rb: -------------------------------------------------------------------------------- 1 | class ChangeForumPostResponseAnswerTextType < ActiveRecord::Migration[6.0] 2 | def change 3 | change_column :course_assessment_answer_forum_post_responses, :answer_text, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20231026165911_add_misses_to_monitoring.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddMissesToMonitoring < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :course_monitoring_sessions, :misses, :integer, null: false, default: 0 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/course/achievement/condition/achievements_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Achievement::Condition::AchievementsController < 3 | Course::Condition::AchievementsController 4 | include Course::AchievementConditionalConcern 5 | end 6 | -------------------------------------------------------------------------------- /app/views/course/surveys/_survey_lesson_plan_item.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/lesson_plan/items/item', item: item 3 | json.lesson_plan_item_type [t('components.surveys.name')] 4 | json.item_path course_survey_path(current_course, item) 5 | -------------------------------------------------------------------------------- /app/views/notifiers/course/consolidated_opening_reminder_notifier/opening_reminder/course_notifications/course/_video.html.slim: -------------------------------------------------------------------------------- 1 | = t('.section_header') 2 | ol 3 | - items.each do |item| 4 | li = link_to(item.title, course_video_url(course, item, host: course.instance.host)) 5 | -------------------------------------------------------------------------------- /client/app/lib/components/table/adapters/Handlers.ts: -------------------------------------------------------------------------------- 1 | import { PaginationState, RowSelectionState } from '@tanstack/react-table'; 2 | 3 | export interface HandlersProps { 4 | getPaginationState: () => PaginationState; 5 | getRowSelectionState: () => RowSelectionState; 6 | } 7 | -------------------------------------------------------------------------------- /config/credentials/test.yml.enc: -------------------------------------------------------------------------------- 1 | Os8x0dJeIe65MOnAk0gFzYpdoRmLUPm5FtE3EyWuf1HZuOXqEGvSSvRmGyHkSynTBJ1dcR1zOKr0WY0lCJr++Q23Vrx1mqTnoA+p3aqdjE26x+vdvyAYAJ2OAgPARSeiO4I8h0rbTVkSpJMTjiBoHMj3ehKTkexr3sYnnjM/5CST6ytwSJhV4uWMuc1JPkTFlBI2FCO8EQ==--VLikj22h5LPwB5hI--lo1VepV16EWRIhkByrtyhw== -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/condition/condition.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/condition: 6 | attributes: 7 | conditional: 8 | not_in_same_course: '선택한 조건이 현재 조건과 동일한 코스에 있지 않습니다' 9 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/video.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/video: 6 | attributes: 7 | url: 8 | invalid_url: > 9 | 입력하신 URL의 형식이 올바르지 않습니다. 다시 시도해 주세요. 10 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/duplication_traceable.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | duplication_traceable: 6 | attributes: 7 | source_id: 8 | must_exist: '소스는 존재해야 하며 dependent_class의 인스턴스여야 합니다.' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/assessment/answer/text_response.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/assessment/answer/text_response: 6 | attributes: 7 | attachments: 8 | unique: '文件名不能重复。' 9 | -------------------------------------------------------------------------------- /db/migrate/20160801084814_rename_question_type_to_grading_scheme.rb: -------------------------------------------------------------------------------- 1 | class RenameQuestionTypeToGradingScheme < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_column :course_assessment_question_multiple_responses, :question_type, :grading_scheme 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20210817040704_add_show_mcq_mrq_solution_to_course_assessments.rb: -------------------------------------------------------------------------------- 1 | class AddShowMcqMrqSolutionToCourseAssessments < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :course_assessments, :show_mcq_mrq_solution, :boolean, default: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230410121228_add_allow_record_draft_answer_to_assessments.rb: -------------------------------------------------------------------------------- 1 | class AddAllowRecordDraftAnswerToAssessments < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :course_assessments, :allow_record_draft_answer, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20231017055234_add_blocks_to_monitoring.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddBlocksToMonitoring < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :course_monitoring_monitors, :blocks, :boolean, null: false, default: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20240312101723_add_max_size_to_attachment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddMaxSizeToAttachment < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :course_assessment_question_text_responses, :max_attachment_size, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/factories/course_assessment_plagiarism_checks.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :course_assessment_plagiarism_check, class: 'Course::Assessment::PlagiarismCheck' do 4 | association :assessment, factory: :assessment 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/factories/duplication_traceable_assessments.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :duplication_traceable_assessment, class: DuplicationTraceable::Assessment.name do 4 | source { build(:assessment) } 5 | assessment 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/course/assessment/submission/logs_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Assessment::Submission::LogsController < \ 3 | Course::Assessment::Submission::Controller 4 | 5 | def index 6 | authorize!(:manage, @assessment) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/system/admin/controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class System::Admin::Controller < ApplicationController 3 | before_action :authorize_admin 4 | 5 | private 6 | 7 | def authorize_admin 8 | authorize!(:manage, :all) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/controllers/test/controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Test::Controller < ActionController::Base 3 | before_action :restrict_to_test 4 | 5 | private 6 | 7 | def restrict_to_test 8 | head :not_found unless Rails.env.test? 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/views/course/admin/rag_wise_settings/courses.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.courses @courses do |course_hash| 3 | json.id course_hash[:course].id 4 | json.name course_hash[:course].title 5 | json.canManageCourse course_hash[:canManageCourse] 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/rubric_based_responses/_grade_details.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.grades category.criterions do |criterion| 3 | json.id criterion.id 4 | json.grade criterion.grade 5 | json.explanation criterion.explanation 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/assessment/question_bundle_questions/_form.html.slim: -------------------------------------------------------------------------------- 1 | = f.error_notification 2 | = f.input :weight 3 | = f.association :question_bundle, collection: @assessment.question_bundles 4 | = f.association :question, collection: @assessment.questions 5 | = f.button :submit 6 | -------------------------------------------------------------------------------- /app/views/notifiers/course/consolidated_opening_reminder_notifier/opening_reminder/course_notifications/course/_survey.html.slim: -------------------------------------------------------------------------------- 1 | = t('.section_header') 2 | ol 3 | - items.each do |item| 4 | li = link_to(item.title, course_survey_url(course, item, host: course.instance.host)) 5 | -------------------------------------------------------------------------------- /client/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'always', 3 | endOfLine: 'lf', 4 | jsxSingleQuote: false, 5 | quoteProps: 'as-needed', 6 | semi: true, 7 | singleQuote: true, 8 | tabWidth: 2, 9 | trailingComma: 'all', 10 | useTabs: false, 11 | }; 12 | -------------------------------------------------------------------------------- /client/app/lib/components/table/adapters/Sort.ts: -------------------------------------------------------------------------------- 1 | import { MouseEventHandler } from 'react'; 2 | 3 | interface SortProps { 4 | sorted: boolean; 5 | direction?: 'asc' | 'desc'; 6 | onClickSort?: MouseEventHandler; 7 | } 8 | 9 | export default SortProps; 10 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/user_achievement.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/user_achievement: 6 | attributes: 7 | course_user: 8 | not_in_course: 'Selected user is not in specified course' 9 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/group_user.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/group_user: 6 | not_enrolled: '그룹과 동일한 과정에 등록되어 있어야 합니다' 7 | attributes: 8 | course/group_user: 9 | manager: '교사' 10 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/scholaistic_assessment.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/scholaistic_assessment: 6 | attributes: 7 | time_bonus_exp: 8 | bonus_attributes_not_allowed: '不允许使用奖励属性' 9 | -------------------------------------------------------------------------------- /config/locales/zh/course/mailer/user_added_email.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | mailer: 4 | user_added_email: 5 | 6 | subject: '添加至课程%{course}' 7 | message: > 8 | 您已被加入%{coursemology}的课程%{course}。 9 | 10 | 要查看该课程,请使用%{email}登录。 11 | -------------------------------------------------------------------------------- /db/migrate/20141222074908_add_userstamps_to_courses.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddUserstampsToCourses < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :courses, :updater_id, :integer, null: false, foreign_key: { references: :users } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20150726130555_set_achievement_condition_nullity.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class SetAchievementConditionNullity < ActiveRecord::Migration[4.2] 3 | def change 4 | change_column_null :course_condition_achievements, :achievement_id, false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20151028151258_add_unique_index_to_materials.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddUniqueIndexToMaterials < ActiveRecord::Migration[4.2] 3 | def change 4 | add_index :course_materials, [:folder_id, :name], unique: true, case_sensitive: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20230104073345_add_anonymous_to_forum_post.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddAnonymousToForumPost < ActiveRecord::Migration[6.0] 3 | def change 4 | add_column :course_discussion_posts, :is_anonymous, :boolean, default: false, null: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/concerns/signals/slices/announcements.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Signals::Slices::Announcements 3 | include Course::UnreadCountsConcern 4 | 5 | def generate_sync_for_announcements 6 | { announcements: unread_announcements_count } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/attachment_references/create.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | success = @attachment_reference&.persisted? 3 | 4 | json.success success 5 | if success 6 | json.id @attachment_reference.id 7 | json.attachmentUrl @attachment_reference.generate_public_url 8 | end 9 | -------------------------------------------------------------------------------- /app/views/course/courses/_course_list_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.id course.id 4 | json.title course.title 5 | json.description format_ckeditor_rich_text(course.description) 6 | json.logoUrl url_to_course_logo(course) 7 | json.startAt course.start_at 8 | -------------------------------------------------------------------------------- /app/views/course/leaderboards/_leaderboard_achievement_list_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.id achievement.id 4 | json.title achievement.title 5 | json.badge do 6 | json.name achievement[:badge] 7 | json.url achievement_badge_path(achievement) 8 | end 9 | -------------------------------------------------------------------------------- /app/views/course/lesson_plan/events/_event_lesson_plan_item.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.partial! 'course/lesson_plan/items/item', item: item 3 | 4 | json.eventId item.id 5 | json.(item, :description, :location) 6 | json.lesson_plan_item_type [item.event_type] 7 | -------------------------------------------------------------------------------- /app/views/course/mailer/user_rejected_email.html.slim: -------------------------------------------------------------------------------- 1 | = simple_format(\ 2 | t('.message', course: link_to(@course.title, course_url(@course, host: @course.instance.host)), 3 | coursemology: link_to(t('layout.coursemology'), @course.instance.host)\ 4 | )\ 5 | ) 6 | -------------------------------------------------------------------------------- /app/views/course/statistics/users/learning_rate_records.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.learningRateRecords @learning_rate_records do |record| 3 | json.id record.id 4 | json.learningRate record.learning_rate 5 | json.createdAt record.created_at.iso8601 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/video/topics/create.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.topicId @topic.id.to_s 3 | json.topic @topic, partial: 'course/video/topics/topic', as: :topic 4 | 5 | json.postId @post.id.to_s 6 | json.post @post, partial: 'course/video/topics/post', as: :post 7 | -------------------------------------------------------------------------------- /app/views/notifiers/course/consolidated_opening_reminder_notifier/opening_reminder/course_notifications/course/_assessment.html.slim: -------------------------------------------------------------------------------- 1 | = t('.section_header') 2 | ol 3 | - items.each do |item| 4 | li = link_to(item.title, course_assessment_url(course, item, host: course.instance.host)) 5 | -------------------------------------------------------------------------------- /authentication/env: -------------------------------------------------------------------------------- 1 | KC_NETWORK_MODE="bridge" 2 | KC_DB= "postgres" 3 | KC_DB_URL="jdbc:postgresql://host.docker.internal/coursemology_keycloak" 4 | KC_DB_USERNAME="postgres" 5 | KC_DB_PASSWORD="" 6 | KC_HOSTNAME="localhost" 7 | KEYCLOAK_ADMIN="admin" 8 | KEYCLOAK_ADMIN_PASSWORD="password" 9 | -------------------------------------------------------------------------------- /client/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing on React 2 | We have shifted our contributing guides to our Wiki on [Contributing to React](https://github.com/Coursemology/coursemology2/wiki/Contributing-on-React). 3 | Please consult the guide before submitting a pull request to this repository. 4 | -------------------------------------------------------------------------------- /client/app/bundles/course/assessment/question/scribing/types.ts: -------------------------------------------------------------------------------- 1 | import { ScribingQuestion } from 'types/course/assessment/question/scribing'; 2 | 3 | export interface ScribingQuestionState { 4 | question: ScribingQuestion; 5 | isLoading: boolean; 6 | isSubmitting: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/video/session.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/video/session: 6 | attributes: 7 | session_start: 8 | cannot_be_after_session_end: 'Session cannot start after ending' 9 | -------------------------------------------------------------------------------- /config/locales/en/course/assessment/question/forum_post_response.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | assessment: 4 | question: 5 | forum_post_responses: 6 | new: 7 | header: 'New Forum Post Response Question' 8 | question_type: Forum Post Response 9 | -------------------------------------------------------------------------------- /config/locales/en/course/assessment/question/multiple_responses.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | assessment: 4 | question: 5 | multiple_responses: 6 | question_type: 7 | multiple_response: Multiple Response 8 | multiple_choice: Multiple Choice 9 | -------------------------------------------------------------------------------- /config/locales/en/course/mailer/submission_graded_email.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | mailer: 4 | submission_graded_email: 5 | subject: '%{course}: Your submission for %{assessment} has been graded' 6 | message: > 7 | Click %{submission} to view your grade. 8 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/assessment/answer/text_response.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/assessment/answer/text_response: 6 | attributes: 7 | attachments: 8 | unique: '파일 이름은 중복되어선 안 됩니다' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/monitoring/heartbeat.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/monitoring/heartbeat: 6 | attributes: 7 | seb_payload: 8 | invalid_seb_payload: 'seb payload 必须为空或为有效的 JSON 对象' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/filename_validator.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | messages: 5 | filename_validator: 6 | invalid_characters: '%{characters}不合法。' 7 | tailing_dots: '点号不能出现在文件名末尾。' 8 | whitespaces: '空格不能出现在文件名开头或末尾。' 9 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/instance.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | instance/user_role_request: 6 | attributes: 7 | base: 8 | existing_pending_request: > 9 | '你有一个已存在的身份变更请求,请刷新页面。' 10 | -------------------------------------------------------------------------------- /config/locales/zh/course/mailer/course_duplicate_failed_email.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | mailer: 4 | course_duplicate_failed_email: 5 | subject: '课程复制失败: %{original_course}' 6 | message: > 7 | 复制%{original_course}失败。 8 | 请稍后再试,如果问题仍然存在,请联系开发人员。 9 | -------------------------------------------------------------------------------- /db/migrate/20150126080047_add_sticky_to_course_announcements.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddStickyToCourseAnnouncements < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :course_announcements, :sticky, :boolean, default: false, null: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20150803080715_add_assessment_answer_workflow_state.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddAssessmentAnswerWorkflowState < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :course_assessment_answers, :workflow_state, :string, null: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160714053644_add_timestamps_to_course_assessment_answers.rb: -------------------------------------------------------------------------------- 1 | class AddTimestampsToCourseAssessmentAnswers < ActiveRecord::Migration[4.2] 2 | def change 3 | change_table :course_assessment_answers do |t| 4 | t.timestamps null: false 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20170308044737_add_recorded_videos_to_virtual_classrooms.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddRecordedVideosToVirtualClassrooms < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :course_virtual_classrooms, :recorded_videos, :jsonb 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20170816073714_add_confirmer_id_to_course_user_invitations.rb: -------------------------------------------------------------------------------- 1 | class AddConfirmerIdToCourseUserInvitations < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_user_invitations, :confirmer_id, :integer, foreign_key: { references: :users } 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220519015535_add_default_timeline_algorithm_to_course.rb: -------------------------------------------------------------------------------- 1 | class AddDefaultTimelineAlgorithmToCourse < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :courses, :default_timeline_algorithm, :integer, default: 0, null: false # 'fixed' algorithm 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/course_assessment_answer_auto_gradings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :course_assessment_answer_auto_grading, class: Course::Assessment::Answer::AutoGrading do 4 | answer { build(:course_assessment_answer) } 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /spec/models/course/forum/topic/view_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Forum::Topic::View, type: :model do 5 | it { is_expected.to belong_to(:topic).inverse_of(:views) } 6 | it { is_expected.to belong_to(:user) } 7 | end 8 | -------------------------------------------------------------------------------- /spec/support/rspec_html_matchers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class RSpecHtmlMatchers::HaveTag 3 | module FrozenStringHelper 4 | def initialize(tag, *args) 5 | tag = tag.dup 6 | super 7 | end 8 | end 9 | 10 | prepend FrozenStringHelper 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/concerns/signals/slices/enrol_requests.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | module Signals::Slices::EnrolRequests 3 | include Course::UnreadCountsConcern 4 | 5 | def generate_sync_for_enrol_requests 6 | { manage_users: pending_enrol_requests_count } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/course/assessment/submission/controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Assessment::Submission::Controller < Course::Assessment::Controller 3 | load_and_authorize_resource :submission, class: 'Course::Assessment::Submission', through: :assessment 4 | end 5 | -------------------------------------------------------------------------------- /app/views/course/group/group_categories/show_users.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.courseUsers @course_users do |course_user| 3 | json.id course_user.id 4 | json.name course_user.name 5 | json.role course_user.role 6 | json.isPhantom course_user.phantom? 7 | end 8 | -------------------------------------------------------------------------------- /app/views/user/profiles/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.id current_user.id 4 | json.name current_user.name 5 | json.timeZone user_time_zone 6 | json.locale I18n.locale 7 | json.imageUrl user_image(current_user) 8 | json.availableLocales I18n.available_locales 9 | -------------------------------------------------------------------------------- /client/app/types/course/admin/announcements.ts: -------------------------------------------------------------------------------- 1 | export interface AnnouncementsSettingsData { 2 | title: string; 3 | } 4 | 5 | export interface AnnouncementsSettingsPostData { 6 | settings_announcements_component: { 7 | title: AnnouncementsSettingsData['title']; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/assessment/answer/text_response.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/assessment/answer/text_response: 6 | attributes: 7 | attachments: 8 | unique: 'File names must be unique' 9 | -------------------------------------------------------------------------------- /config/locales/en/course/mailer/survey_closing_reminder_email.yml: -------------------------------------------------------------------------------- 1 | en: 2 | course: 3 | mailer: 4 | survey_closing_reminder_email: 5 | subject: '%{course}: Reminder about %{survey}' 6 | message: > 7 | Please be reminded that %{survey} will expire on %{time}. 8 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/scholaistic_assessment.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/scholaistic_assessment: 6 | attributes: 7 | time_bonus_exp: 8 | bonus_attributes_not_allowed: '보너스 속성은 허용되지 않습니다' 9 | -------------------------------------------------------------------------------- /config/locales/ko/course/mailer/course_duplicate_failed_email.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | mailer: 4 | course_duplicate_failed_email: 5 | subject: '코스 복제 실패: %{original_course}' 6 | message: > 7 | %{original_course} 복제가 실패했습니다. 나중에 다시 시도하거나 문제가 지속되면 지원팀에 문의하세요. 8 | -------------------------------------------------------------------------------- /config/locales/zh/activemodel/course/experience_points/forum_disbursement.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activemodel: 3 | errors: 4 | models: 5 | course/experience_points/forum_disbursement: 6 | attributes: 7 | end_time: 8 | invalid_period: '结束时间不能早于起始时间。' 9 | -------------------------------------------------------------------------------- /config/locales/zh/course/assessment/submissions.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | course: 3 | assessment: 4 | submissions: 5 | sidebar_title: :'course.assessment.submissions.index.header' 6 | index: 7 | header: '提交' 8 | pending: 9 | header: '等待中的提交' 10 | -------------------------------------------------------------------------------- /config/locales/zh/instance/mailer/user_added_email.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | instance: 3 | mailer: 4 | user_added_email: 5 | 6 | subject: '已加入实例%{instance}' 7 | message: > 8 | 你已被加入%{coursemology}的实例%{instance}。 9 | 10 | 要查看该实例,请用以下方式登录%{email}. 11 | -------------------------------------------------------------------------------- /db/migrate/20150729133128_rename_course_events_to_course_lesson_plan_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class RenameCourseEventsToCourseLessonPlanEvents < ActiveRecord::Migration[4.2] 3 | def change 4 | rename_table :course_events, :course_lesson_plan_events 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20161013115452_migrate_graded_submissions_to_published.rb: -------------------------------------------------------------------------------- 1 | class MigrateGradedSubmissionsToPublished < ActiveRecord::Migration[4.2] 2 | def up 3 | Course::Assessment::Submission.where(workflow_state: 'graded'). 4 | update_all(workflow_state: 'published') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20170115105609_add_delayed_grade_publication_to_course_assessments.rb: -------------------------------------------------------------------------------- 1 | class AddDelayedGradePublicationToCourseAssessments < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :course_assessments, :delayed_grade_publication, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/factories/course_assessment_question_scribings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :course_assessment_question_scribing, 4 | class: Course::Assessment::Question::Scribing, 5 | parent: :course_assessment_question do 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/factories/course_assessment_skills.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | FactoryBot.define do 3 | factory :course_assessment_skill, class: Course::Assessment::Skill do 4 | course 5 | sequence(:title) { |n| "Skill #{n}" } 6 | description { 'Description' } 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/course/admin/forum_settings/edit.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.title @settings.title || '' 3 | json.pagination @settings.pagination.to_i 4 | json.markPostAsAnswerSetting @settings.mark_post_as_answer_setting 5 | json.allowAnonymousPost @settings.allow_anonymous_post 6 | -------------------------------------------------------------------------------- /app/views/course/mailer/course_duplicated_email.text.erb: -------------------------------------------------------------------------------- 1 | <%= t('.message', original_course: @original_course.title, 2 | new_course: @new_course.title, 3 | click_here: plain_link_to(t('.click_here'), course_url(@new_course, host: @new_course.instance.host))) %> 4 | -------------------------------------------------------------------------------- /app/views/instance/mailer/user_added_email.html.slim: -------------------------------------------------------------------------------- 1 | = simple_format(\ 2 | t('.message', instance: link_to(@instance.name, @instance.host), 3 | coursemology: link_to(t('layout.coursemology'), @instance.host), 4 | email: @recipient.email\ 5 | )\ 6 | ) 7 | -------------------------------------------------------------------------------- /client/app/bundles/course/plagiarism/selectors.ts: -------------------------------------------------------------------------------- 1 | import { AppState } from 'store'; 2 | import { PlagiarismAssessmentsState } from 'types/course/plagiarism'; 3 | 4 | export const getPlagiarismAssessments = ( 5 | state: AppState, 6 | ): PlagiarismAssessmentsState => state.plagiarism.assessments; 7 | -------------------------------------------------------------------------------- /client/app/lib/components/table/builder/index.ts: -------------------------------------------------------------------------------- 1 | export type { BuiltColumns } from './buildColumns'; 2 | export { buildColumns } from './buildColumns'; 3 | export type { default as ColumnTemplate, Data } from './ColumnTemplate'; 4 | export type { default as TableTemplate } from './TableTemplate'; 5 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/duplication_traceable.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | duplication_traceable: 6 | attributes: 7 | source_id: 8 | must_exist: 'the source must exist and be an instance of the dependent_class' 9 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/course/monitoring/heartbeat.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | course/monitoring/heartbeat: 6 | attributes: 7 | seb_payload: 8 | invalid_seb_payload: 'seb payload는 비어 있거나 유효한 JSON 객체여야 합니다' 9 | -------------------------------------------------------------------------------- /config/locales/ko/course/assessment/submissions.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | assessment: 4 | submissions: 5 | sidebar_title: :'course.assessment.submissions.index.header' 6 | index: 7 | header: '제출물' 8 | pending: 9 | header: '대기 중인 제출물' 10 | -------------------------------------------------------------------------------- /config/locales/ko/course/mailer/user_added_email.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | course: 3 | mailer: 4 | user_added_email: 5 | subject: '%{course} 과정에 추가됨' 6 | message: > 7 | %{coursemology}의 %{course} 과정에 추가되었습니다. 8 | 9 | 과정을 보려면 %{email}로 로그인하세요. 10 | -------------------------------------------------------------------------------- /config/locales/ko/user/emails.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | user: 3 | emails: 4 | index: 5 | header: '이메일' 6 | set_primary: 7 | no_confirmed_emails: '기본 이메일로 설정할 수 있는 확인된 이메일 주소가 없습니다.' 8 | send_confirmation: 9 | already_confirmed: '%{email}은(는) 이미 확인되었습니다.' 10 | -------------------------------------------------------------------------------- /db/migrate/20150413043822_add_settings_to_instances_and_courses.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddSettingsToInstancesAndCourses < ActiveRecord::Migration[4.2] 3 | def change 4 | add_column :instances, :settings, :text 5 | add_column :courses, :settings, :text 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20151030063045_add_unique_index_to_course_material_folders.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class AddUniqueIndexToCourseMaterialFolders < ActiveRecord::Migration[4.2] 3 | def change 4 | add_index :course_material_folders, [:owner_id, :owner_type], unique: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160822092000_add_publisher_to_submissions.rb: -------------------------------------------------------------------------------- 1 | class AddPublisherToSubmissions < ActiveRecord::Migration[4.2] 2 | change_table :course_assessment_submissions do |t| 3 | t.integer :publisher_id, foreign_key: { references: :users } 4 | t.datetime :published_at 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20181211133628_add_show_personalized_timeline_features_to_course.rb: -------------------------------------------------------------------------------- 1 | class AddShowPersonalizedTimelineFeaturesToCourse < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :courses, :show_personalized_timeline_features, :boolean, default: false, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /spec/models/course/forum/subscription_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | require 'rails_helper' 3 | 4 | RSpec.describe Course::Forum::Subscription, type: :model do 5 | it { is_expected.to belong_to(:forum).inverse_of(:subscriptions) } 6 | it { is_expected.to belong_to(:user) } 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/course/assessment/condition/scholaistic_assessments_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | class Course::Assessment::Condition::ScholaisticAssessmentsController < 3 | Course::Condition::ScholaisticAssessmentsController 4 | include Course::AssessmentConditionalConcern 5 | end 6 | -------------------------------------------------------------------------------- /app/views/course/assessment/assessments/_assessment_list_data.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.id assessment.id 3 | json.title assessment.title 4 | json.tabTitle "#{category.title}: #{tab.title}" 5 | json.tabUrl course_assessments_path(course_id: course, category: category, tab: tab) 6 | -------------------------------------------------------------------------------- /app/views/course/assessment/question/programming/metadata/partials/_test_cases.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.set! type, test_cases.each do |test_case| 3 | json.expression test_case[:expression] 4 | json.expected test_case[:expected] 5 | json.hint test_case[:hint] 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/material/folders/breadcrumbs.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | json.breadcrumbs @folder.ancestors.reverse << @folder do |folder| 4 | json.id folder.id 5 | json.name folder.parent_id.nil? ? @settings.title || t('course.material.sidebar_title') : folder.name 6 | end 7 | -------------------------------------------------------------------------------- /app/views/course/statistics/assessments/_course_user.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.courseUser do 3 | json.id course_user.id 4 | json.name course_user.name 5 | json.role course_user.role 6 | json.isPhantom course_user.phantom? 7 | json.email course_user.user.email 8 | end 9 | -------------------------------------------------------------------------------- /app/views/course/survey/questions/_option.json.jbuilder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | json.(option, :id, :weight) 3 | json.option format_ckeditor_rich_text(option.option) 4 | unless option.attachment.nil? 5 | json.image_url option.attachment.url 6 | json.image_name option.attachment.name 7 | end 8 | -------------------------------------------------------------------------------- /client/app/api/system/index.js: -------------------------------------------------------------------------------- 1 | import AdminAPI from './Admin'; 2 | import InstanceAdminAPI from './InstanceAdmin'; 3 | 4 | const SystemAPI = { 5 | admin: new AdminAPI(), 6 | instance: new InstanceAdminAPI(), 7 | }; 8 | 9 | Object.freeze(SystemAPI); 10 | 11 | export default SystemAPI; 12 | -------------------------------------------------------------------------------- /config/locales/en/activerecord/course/group_user.yml: -------------------------------------------------------------------------------- 1 | en: 2 | activerecord: 3 | errors: 4 | models: 5 | course/group_user: 6 | not_enrolled: 'must be enrolled in same course as group' 7 | attributes: 8 | course/group_user: 9 | manager: 'Tutor' 10 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/filename_validator.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | messages: 5 | filename_validator: 6 | invalid_characters: '%{characters}는 허용되지 않습니다.' 7 | tailing_dots: '끝에 점이 올 수 없습니다.' 8 | whitespaces: '앞이나 뒤에 공백이 올 수 없습니다.' 9 | -------------------------------------------------------------------------------- /config/locales/ko/activerecord/instance.yml: -------------------------------------------------------------------------------- 1 | ko: 2 | activerecord: 3 | errors: 4 | models: 5 | instance/user_role_request: 6 | attributes: 7 | base: 8 | existing_pending_request: > 9 | '이미 존재하는 역할 요청이 있습니다. 페이지를 새로고침 해주세요.' 10 | -------------------------------------------------------------------------------- /config/locales/zh/activerecord/course/assessment/question/text_response_solution.yml: -------------------------------------------------------------------------------- 1 | zh: 2 | activerecord: 3 | errors: 4 | models: 5 | course/assessment/question/text_response_solution: 6 | attributes: 7 | grade: 8 | invalid_grade: '不能超过该问题的分数上限' 9 | --------------------------------------------------------------------------------