From 75e18408dc643722dcba26ed1c03980f36ca895b Mon Sep 17 00:00:00 2001 From: ihor-romaniuk Date: Tue, 9 Jan 2024 15:31:18 +0100 Subject: [PATCH 1/4] feat: Course unit - add new component section --- src/course-unit/CourseUnit.jsx | 5 +- src/course-unit/CourseUnit.scss | 1 + src/course-unit/CourseUnit.test.jsx | 7 + .../__mocks__/courseSectionVertical.js | 1418 +++++++++++++++++ src/course-unit/__mocks__/index.js | 2 +- .../add-component/AddComponent.jsx | 35 + .../add-component/AddComponent.scss | 12 + .../add-component/AddComponent.test.jsx | 59 + .../add-component/ComponentIcon.jsx | 17 + src/course-unit/add-component/messages.js | 14 + src/course-unit/constants.js | 19 + src/i18n/messages/ar.json | 4 +- src/i18n/messages/de.json | 4 +- src/i18n/messages/de_DE.json | 4 +- src/i18n/messages/es_419.json | 4 +- src/i18n/messages/fa_IR.json | 4 +- src/i18n/messages/fr.json | 4 +- src/i18n/messages/fr_CA.json | 4 +- src/i18n/messages/hi.json | 4 +- src/i18n/messages/it.json | 4 +- src/i18n/messages/it_IT.json | 4 +- src/i18n/messages/pt.json | 4 +- src/i18n/messages/pt_PT.json | 4 +- src/i18n/messages/ru.json | 4 +- src/i18n/messages/uk.json | 4 +- src/i18n/messages/zh_CN.json | 4 +- 26 files changed, 1631 insertions(+), 18 deletions(-) create mode 100644 src/course-unit/__mocks__/courseSectionVertical.js create mode 100644 src/course-unit/add-component/AddComponent.jsx create mode 100644 src/course-unit/add-component/AddComponent.scss create mode 100644 src/course-unit/add-component/AddComponent.test.jsx create mode 100644 src/course-unit/add-component/ComponentIcon.jsx create mode 100644 src/course-unit/add-component/messages.js diff --git a/src/course-unit/CourseUnit.jsx b/src/course-unit/CourseUnit.jsx index e7a09a2d02..bbe3ba0241 100644 --- a/src/course-unit/CourseUnit.jsx +++ b/src/course-unit/CourseUnit.jsx @@ -12,6 +12,7 @@ import getPageHeadTitle from '../generic/utils'; import ProcessingNotification from '../generic/processing-notification'; import InternetConnectionAlert from '../generic/internet-connection-alert'; import Loading from '../generic/Loading'; +import AddComponent from './add-component/AddComponent'; import HeaderTitle from './header-title/HeaderTitle'; import Breadcrumbs from './breadcrumbs/Breadcrumbs'; import HeaderNavigations from './header-navigations/HeaderNavigations'; @@ -87,9 +88,9 @@ const CourseUnit = ({ courseId }) => { xl={[{ span: 9 }, { span: 3 }]} > - {/* TODO: Unit content will be added in the following tasks. */} - Unit content + + diff --git a/src/course-unit/CourseUnit.scss b/src/course-unit/CourseUnit.scss index 954bbbdacc..d3264d89f2 100644 --- a/src/course-unit/CourseUnit.scss +++ b/src/course-unit/CourseUnit.scss @@ -1,2 +1,3 @@ @import "./breadcrumbs/Breadcrumbs"; @import "./course-sequence/CourseSequence"; +@import "./add-component/AddComponent"; diff --git a/src/course-unit/CourseUnit.test.jsx b/src/course-unit/CourseUnit.test.jsx index bc4e1ad9a6..7af46666fe 100644 --- a/src/course-unit/CourseUnit.test.jsx +++ b/src/course-unit/CourseUnit.test.jsx @@ -9,14 +9,17 @@ import { getConfig, initializeMockApp } from '@edx/frontend-platform'; import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; import { + getCourseSectionVerticalApiUrl, getCourseUnitApiUrl, getXBlockBaseApiUrl, } from './data/api'; import { + fetchCourseSectionVerticalData, fetchCourseUnitQuery, } from './data/thunk'; import initializeStore from '../store'; import { + courseSectionVerticalMock, courseUnitIndexMock, } from './__mocks__'; import { executeThunk } from '../utils'; @@ -63,6 +66,10 @@ describe('', () => { .onGet(getCourseUnitApiUrl(courseId)) .reply(200, courseUnitIndexMock); await executeThunk(fetchCourseUnitQuery(courseId), store.dispatch); + axiosMock + .onGet(getCourseSectionVerticalApiUrl(blockId)) + .reply(200, courseSectionVerticalMock); + await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch); }); it('render CourseUnit component correctly', async () => { diff --git a/src/course-unit/__mocks__/courseSectionVertical.js b/src/course-unit/__mocks__/courseSectionVertical.js new file mode 100644 index 0000000000..fdae7cdd56 --- /dev/null +++ b/src/course-unit/__mocks__/courseSectionVertical.js @@ -0,0 +1,1418 @@ +module.exports = { + language_code: 'en', + action: 'view', + xblock: { + display_name: 'Getting Started', + display_type: 'Unit', + category: 'vertical', + }, + is_unit_page: true, + is_collapsible: false, + position: 1, + prev_url: '%2Fcontainer%2Fblock-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40vertical%2Bblock%40vertical_0270f6de40fc', + next_url: '%2Fcontainer%2Fblock-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40vertical%2Bblock%404f6c1b4e316a419ab5b6bf30e6c708e9', + new_unit_category: 'vertical', + outline_url: '/course/course-v1:edX+DemoX+Demo_Course?format=concise', + ancestor_xblocks: [ + { + children: [ + { + url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40d8a6192ade314473a78242dfeedfbf5b', + display_name: 'Introduction 2', + }, + { + url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40interactive_demonstrations', + display_name: 'Example Week 1: Getting Started', + }, + { + url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40graded_interactions', + display_name: 'Example Week 2: Get Interactive', + }, + { + url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40social_integration', + display_name: 'Example Week 3: Be Social', + }, + { + url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%401414ffd5143b4b508f739b563ab468b7', + display_name: 'About Exams and Certificates', + }, + ], + title: 'Example Week 1: Getting Started', + is_last: false, + }, + { + children: [ + { + url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%4019a30717eff543078a5d94ae9d6c18a5', + display_name: 'Lesson 1 - Getting Started', + }, + { + url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%40basic_questions', + display_name: 'Homework - Question Styles', + }, + ], + title: 'Lesson 1 - Getting Started', + is_last: true, + }, + ], + component_templates: [ + { + type: 'advanced', + templates: [ + { + display_name: 'Annotation', + category: 'annotatable', + boilerplate_name: null, + hinted: false, + tab: 'common', + support_level: true, + }, + { + display_name: 'Video', + category: 'videoalpha', + boilerplate_name: null, + hinted: false, + tab: 'common', + support_level: true, + }, + ], + display_name: 'Advanced', + support_legend: { + show_legend: false, + allow_unsupported_xblocks: false, + documentation_label: 'Your Platform Name Here Support Levels:', + }, + }, + { + type: 'discussion', + templates: [ + { + display_name: 'Discussion', + category: 'discussion', + boilerplate_name: null, + hinted: false, + tab: 'advanced', + support_level: true, + }, + ], + display_name: 'Discussion', + support_legend: { + show_legend: false, + allow_unsupported_xblocks: false, + documentation_label: 'Your Platform Name Here Support Levels:', + }, + }, + { + type: 'library', + templates: [ + { + display_name: 'Randomized Content Block', + category: 'library_content', + boilerplate_name: null, + hinted: false, + tab: 'common', + support_level: true, + }, + ], + display_name: 'Library Content', + support_legend: { + show_legend: false, + allow_unsupported_xblocks: false, + documentation_label: 'Your Platform Name Here Support Levels:', + }, + }, + { + type: 'html', + templates: [ + { + display_name: 'Text', + category: 'html', + boilerplate_name: null, + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'Raw HTML', + category: 'html', + boilerplate_name: 'raw.yaml', + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'Zooming Image Tool', + category: 'html', + boilerplate_name: 'zooming_image.yaml', + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'IFrame Tool', + category: 'html', + boilerplate_name: 'iframe.yaml', + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'Anonymous User ID', + category: 'html', + boilerplate_name: 'anon_user_id.yaml', + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'Announcement', + category: 'html', + boilerplate_name: 'announcement.yaml', + hinted: false, + tab: 'advanced', + support_level: true, + }, + ], + display_name: 'Text', + support_legend: { + show_legend: false, + allow_unsupported_xblocks: false, + documentation_label: 'Your Platform Name Here Support Levels:', + }, + }, + { + type: 'openassessment', + templates: [ + { + display_name: 'Peer Assessment Only', + category: 'openassessment', + boilerplate_name: 'peer-assessment', + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'Self Assessment Only', + category: 'openassessment', + boilerplate_name: 'self-assessment', + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'Staff Assessment Only', + category: 'openassessment', + boilerplate_name: 'staff-assessment', + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'Self Assessment to Peer Assessment', + category: 'openassessment', + boilerplate_name: 'self-to-peer', + hinted: false, + tab: 'advanced', + support_level: true, + }, + { + display_name: 'Self Assessment to Staff Assessment', + category: 'openassessment', + boilerplate_name: 'self-to-staff', + hinted: false, + tab: 'advanced', + support_level: true, + }, + ], + display_name: 'Open Response', + support_legend: { + show_legend: false, + allow_unsupported_xblocks: false, + documentation_label: 'Your Platform Name Here Support Levels:', + }, + }, + { + type: 'problem', + templates: [ + { + display_name: 'Blank Common Problem', + category: 'problem', + boilerplate_name: 'blank_common.yaml', + hinted: false, + tab: 'common', + support_level: true, + }, + ], + display_name: 'Problem', + support_legend: { + show_legend: false, + allow_unsupported_xblocks: false, + documentation_label: 'Your Platform Name Here Support Levels:', + }, + }, + { + type: 'video', + templates: [ + { + display_name: 'Video', + category: 'video', + boilerplate_name: null, + hinted: false, + tab: 'advanced', + support_level: true, + }, + ], + display_name: 'Video', + support_legend: { + show_legend: false, + allow_unsupported_xblocks: false, + documentation_label: 'Your Platform Name Here Support Levels:', + }, + }, + { + type: 'drag-and-drop-v2', + templates: [ + { + display_name: 'Drag and Drop', + category: 'drag-and-drop-v2', + boilerplate_name: null, + hinted: false, + tab: 'advanced', + support_level: true, + }, + ], + display_name: 'Drag and Drop', + support_legend: { + show_legend: false, + allow_unsupported_xblocks: false, + documentation_label: 'Your Platform Name Here Support Levels:', + }, + }, + ], + xblock_info: { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec', + display_name: 'Getting Started', + category: 'vertical', + has_children: true, + edited_on: 'Jan 04, 2024 at 10:32 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'needs_attention', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: true, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_info: { + ancestors: [ + { + id: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5', + display_name: 'Lesson 1 - Getting Started', + category: 'sequential', + has_children: true, + edited_on: 'Jan 04, 2024 at 10:32 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40sequential%2Bblock%4019a30717eff543078a5d94ae9d6c18a5', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'needs_attention', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: null, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + hide_after_due: false, + is_proctored_exam: false, + was_exam_ever_linked_with_external: false, + online_proctoring_rules: '', + is_practice_exam: false, + is_onboarding_exam: false, + is_time_limited: false, + exam_review_rules: '', + default_time_limit_minutes: null, + proctoring_exam_configuration_link: null, + supports_onboarding: false, + show_review_rules: true, + child_info: { + category: 'vertical', + display_name: 'Unit', + children: [ + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec', + display_name: 'Getting Started', + category: 'vertical', + has_children: true, + edited_on: 'Jan 04, 2024 at 10:32 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'needs_attention', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: true, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@4f6c1b4e316a419ab5b6bf30e6c708e9', + display_name: 'Working with Videos', + category: 'vertical', + has_children: true, + edited_on: 'Dec 28, 2023 at 10:00 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@4f6c1b4e316a419ab5b6bf30e6c708e9', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: false, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@3dc16db8d14842e38324e95d4030b8a0', + display_name: 'Videos on edX', + category: 'vertical', + has_children: true, + edited_on: 'Dec 28, 2023 at 10:00 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@3dc16db8d14842e38324e95d4030b8a0', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: false, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@4a1bba2a403f40bca5ec245e945b0d76', + display_name: 'Video Demonstrations', + category: 'vertical', + has_children: true, + edited_on: 'Dec 28, 2023 at 10:00 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@4a1bba2a403f40bca5ec245e945b0d76', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: false, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@256f17a44983429fb1a60802203ee4e0', + display_name: 'Video Presentation Styles', + category: 'vertical', + has_children: true, + edited_on: 'Dec 28, 2023 at 10:00 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@256f17a44983429fb1a60802203ee4e0', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: false, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@e3601c0abee6427d8c17e6d6f8fdddd1', + display_name: 'Interactive Questions', + category: 'vertical', + has_children: true, + edited_on: 'Dec 28, 2023 at 10:00 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@e3601c0abee6427d8c17e6d6f8fdddd1', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: false, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@a79d59cd72034188a71d388f4954a606', + display_name: 'Exciting Labs and Tools', + category: 'vertical', + has_children: true, + edited_on: 'Dec 28, 2023 at 10:00 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@a79d59cd72034188a71d388f4954a606', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: false, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@134df56c516a4a0dbb24dd5facef746e', + display_name: 'Reading Assignments', + category: 'vertical', + has_children: true, + edited_on: 'Dec 28, 2023 at 10:00 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@134df56c516a4a0dbb24dd5facef746e', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: false, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@vertical+block@d91b9e5d8bc64d57a1332d06bf2f2193', + display_name: 'When Are Your Exams? ', + category: 'vertical', + has_children: true, + edited_on: 'Dec 28, 2023 at 10:00 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/container/block-v1:edX+DemoX+Demo_Course+type@vertical+block@d91b9e5d8bc64d57a1332d06bf2f2193', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: false, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + discussion_enabled: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + }, + ], + }, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@chapter+block@interactive_demonstrations', + display_name: 'Example Week 1: Getting Started', + category: 'chapter', + has_children: true, + edited_on: 'Jan 04, 2024 at 10:32 UTC', + published: true, + published_on: 'Dec 28, 2023 at 10:00 UTC', + studio_url: '/course/course-v1:edX+DemoX+Demo_Course?show=block-v1%3AedX%2BDemoX%2BDemo_Course%2Btype%40chapter%2Bblock%40interactive_demonstrations', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: 'live', + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: null, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + highlights: [], + highlights_enabled: true, + highlights_preview_only: false, + highlights_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/latest/developing_course/course_sections.html#set-section-highlights-for-weekly-course-highlight-messages', + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + }, + { + id: 'block-v1:edX+DemoX+Demo_Course+type@course+block@course', + display_name: 'Demonstration Course', + category: 'course', + has_children: true, + unit_level_discussions: false, + edited_on: 'Jan 08, 2024 at 16:39 UTC', + published: true, + published_on: 'Jan 08, 2024 at 16:39 UTC', + studio_url: '/course/course-v1:edX+DemoX+Demo_Course', + released_to_students: true, + release_date: 'Feb 05, 2013 at 05:00 UTC', + visibility_state: null, + has_explicit_staff_lock: false, + start: '2013-02-05T05:00:00Z', + graded: false, + due_date: '', + due: null, + relative_weeks_due: null, + format: null, + course_graders: [ + 'Homework', + 'Exam', + ], + has_changes: null, + actions: { + deletable: true, + draggable: true, + childAddable: true, + duplicable: true, + }, + explanatory_message: null, + group_access: {}, + user_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + show_correctness: 'always', + highlights_enabled_for_messaging: false, + highlights_enabled: true, + highlights_preview_only: false, + highlights_doc_url: 'http://edx.readthedocs.io/projects/open-edx-building-and-running-a-course/en/latest/developing_course/course_sections.html#set-section-highlights-for-weekly-course-highlight-messages', + enable_proctored_exams: false, + create_zendesk_tickets: true, + enable_timed_exams: true, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + }, + ], + }, + ancestor_has_staff_lock: false, + user_partition_info: { + selectable_partitions: [ + { + id: 50, + name: 'Enrollment Track Groups', + scheme: 'enrollment_track', + groups: [ + { + id: 2, + name: 'Verified Certificate', + selected: false, + deleted: false, + }, + { + id: 1, + name: 'Audit', + selected: false, + deleted: false, + }, + ], + }, + ], + selected_partition_index: -1, + selected_groups_label: '', + }, + enable_copy_paste_units: false, + edited_by: 'edx', + published_by: null, + currently_visible_to_students: true, + has_partition_group_components: false, + release_date_from: 'Section "Example Week 1: Getting Started"', + staff_lock_from: null, + }, + draft_preview_link: '//preview.localhost:18000/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec', + published_preview_link: '//localhost:18000/courses/course-v1:edX+DemoX+Demo_Course/jump_to/block-v1:edX+DemoX+Demo_Course+type@vertical+block@867dddb6f55d410caaa9c1eb9c6743ec', + show_unit_tags: false, + user_clipboard: { + content: null, + source_usage_key: '', + source_context_title: '', + source_edit_url: '', + }, + is_fullwidth_content: false, + assets_url: '/assets/course-v1:edX+DemoX+Demo_Course/', + unit_block_id: '867dddb6f55d410caaa9c1eb9c6743ec', + subsection_location: 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5', +}; diff --git a/src/course-unit/__mocks__/index.js b/src/course-unit/__mocks__/index.js index ebf5206845..dbf4d113b3 100644 --- a/src/course-unit/__mocks__/index.js +++ b/src/course-unit/__mocks__/index.js @@ -1,2 +1,2 @@ -/* eslint-disable import/prefer-default-export */ export { default as courseUnitIndexMock } from './courseUnitIndex'; +export { default as courseSectionVerticalMock } from './courseSectionVertical'; diff --git a/src/course-unit/add-component/AddComponent.jsx b/src/course-unit/add-component/AddComponent.jsx new file mode 100644 index 0000000000..5a03e2e874 --- /dev/null +++ b/src/course-unit/add-component/AddComponent.jsx @@ -0,0 +1,35 @@ +import { useSelector } from 'react-redux'; +import { useIntl } from '@edx/frontend-platform/i18n'; +import { Button } from '@edx/paragon'; + +import { getCourseSectionVertical } from '../data/selectors'; +import ComponentIcon from './ComponentIcon'; +import messages from './messages'; + +const AddComponent = () => { + const intl = useIntl(); + const { componentTemplates } = useSelector(getCourseSectionVertical); + + if (!Object.keys(componentTemplates).length) { + return null; + } + + return ( +
+
{intl.formatMessage(messages.title)}
+
    + {Object.keys(componentTemplates).map((component) => ( +
  • + +
  • + ))} +
+
+ ); +}; + +export default AddComponent; diff --git a/src/course-unit/add-component/AddComponent.scss b/src/course-unit/add-component/AddComponent.scss new file mode 100644 index 0000000000..aba0a04e1c --- /dev/null +++ b/src/course-unit/add-component/AddComponent.scss @@ -0,0 +1,12 @@ +.course-unit { + .new-component-type { + gap: .75rem; + } + + .add-component-button { + @include pgn-box-shadow(1, "down"); + + width: 11.63rem; + height: 6.875rem; + } +} diff --git a/src/course-unit/add-component/AddComponent.test.jsx b/src/course-unit/add-component/AddComponent.test.jsx new file mode 100644 index 0000000000..eaff9da870 --- /dev/null +++ b/src/course-unit/add-component/AddComponent.test.jsx @@ -0,0 +1,59 @@ +import MockAdapter from 'axios-mock-adapter'; +import { render } from '@testing-library/react'; + +import { initializeMockApp } from '@edx/frontend-platform'; +import { AppProvider } from '@edx/frontend-platform/react'; +import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; + +import initializeStore from '../../store'; +import { executeThunk } from '../../utils'; +import { fetchCourseSectionVerticalData } from '../data/thunk'; +import { getCourseSectionVerticalApiUrl } from '../data/api'; +import { courseSectionVerticalMock } from '../__mocks__'; +import AddComponent from './AddComponent'; +import messages from './messages'; + +let store; +let axiosMock; +const blockId = '123'; + +const renderComponent = (props) => render( + + + + + , +); + +describe('', () => { + beforeEach(async () => { + initializeMockApp({ + authenticatedUser: { + userId: 3, + username: 'abc123', + administrator: true, + roles: [], + }, + }); + + store = initializeStore(); + axiosMock = new MockAdapter(getAuthenticatedHttpClient()); + axiosMock + .onGet(getCourseSectionVerticalApiUrl(blockId)) + .reply(200, courseSectionVerticalMock); + await executeThunk(fetchCourseSectionVerticalData(blockId), store.dispatch); + }); + + it('render AddComponent component correctly', () => { + const { getByRole } = renderComponent(); + const componentTemplates = courseSectionVerticalMock.component_templates; + + expect(getByRole('heading', { name: messages.title.defaultMessage })).toBeInTheDocument(); + Object.keys(componentTemplates).map((component) => ( + expect(getByRole('button', { + name: new RegExp(`${messages.buttonText.defaultMessage} ${componentTemplates[component].display_name}`, 'i'), + })).toBeInTheDocument() + )); + }); +}); diff --git a/src/course-unit/add-component/ComponentIcon.jsx b/src/course-unit/add-component/ComponentIcon.jsx new file mode 100644 index 0000000000..0fe9321334 --- /dev/null +++ b/src/course-unit/add-component/ComponentIcon.jsx @@ -0,0 +1,17 @@ +import PropTypes from 'prop-types'; +import { Icon } from '@edx/paragon'; +import { EditNote as EditNoteIcon } from '@edx/paragon/icons'; + +import { COMPONENT_TYPE_ICON_MAP, COMPONENT_ICON_TYPES } from '../constants'; + +const ComponentIcon = ({ type }) => { + const icon = COMPONENT_TYPE_ICON_MAP[type] || EditNoteIcon; + + return ; +}; + +ComponentIcon.propTypes = { + type: PropTypes.oneOf(COMPONENT_ICON_TYPES).isRequired, +}; + +export default ComponentIcon; diff --git a/src/course-unit/add-component/messages.js b/src/course-unit/add-component/messages.js new file mode 100644 index 0000000000..94e6bf4833 --- /dev/null +++ b/src/course-unit/add-component/messages.js @@ -0,0 +1,14 @@ +import { defineMessages } from '@edx/frontend-platform/i18n'; + +const messages = defineMessages({ + title: { + id: 'course-authoring.course-unit.add.component.title', + defaultMessage: 'Add a new component', + }, + buttonText: { + id: 'course-authoring.course-unit.add.component.button.text', + defaultMessage: 'Add Component:', + }, +}); + +export default messages; diff --git a/src/course-unit/constants.js b/src/course-unit/constants.js index c35d980d1b..c2fbe49add 100644 --- a/src/course-unit/constants.js +++ b/src/course-unit/constants.js @@ -1,13 +1,21 @@ import { + BackHand as BackHandIcon, BookOpen as BookOpenIcon, Edit as EditIcon, FormatListBulleted as FormatListBulletedIcon, + HelpOutline as HelpOutlineIcon, + LibraryAdd as LibraryIcon, Lock as LockIcon, + QuestionAnswerOutline as QuestionAnswerOutlineIcon, + Science as ScienceIcon, + TextFields as TextFieldsIcon, VideoCamera as VideoCameraIcon, } from '@edx/paragon/icons'; export const UNIT_ICON_TYPES = ['video', 'other', 'vertical', 'problem', 'lock']; +export const COMPONENT_ICON_TYPES = ['advanced', 'discussion', 'library', 'openassessment', 'problem', 'video', 'drag-and-drop-v2']; + export const TYPE_ICONS_MAP = { video: VideoCameraIcon, other: BookOpenIcon, @@ -15,3 +23,14 @@ export const TYPE_ICONS_MAP = { problem: EditIcon, lock: LockIcon, }; + +export const COMPONENT_TYPE_ICON_MAP = { + advanced: ScienceIcon, + discussion: QuestionAnswerOutlineIcon, + library: LibraryIcon, + html: TextFieldsIcon, + openassessment: EditIcon, + problem: HelpOutlineIcon, + video: VideoCameraIcon, + 'drag-and-drop-v2': BackHandIcon, +}; diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index 393a9019a3..0c24ccbd7f 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index 09c7da1eb7..2500a14407 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/de_DE.json b/src/i18n/messages/de_DE.json index 0286fe7a06..de185d7071 100644 --- a/src/i18n/messages/de_DE.json +++ b/src/i18n/messages/de_DE.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/es_419.json b/src/i18n/messages/es_419.json index c59fa68499..7999fe94ae 100644 --- a/src/i18n/messages/es_419.json +++ b/src/i18n/messages/es_419.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/fa_IR.json b/src/i18n/messages/fa_IR.json index a8ef072f6d..bafa9a9fb7 100644 --- a/src/i18n/messages/fa_IR.json +++ b/src/i18n/messages/fa_IR.json @@ -12,5 +12,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index e91037042e..da68eb6719 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/fr_CA.json b/src/i18n/messages/fr_CA.json index f3251fbbb0..ca1e8b4152 100644 --- a/src/i18n/messages/fr_CA.json +++ b/src/i18n/messages/fr_CA.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json index 09c7da1eb7..2500a14407 100644 --- a/src/i18n/messages/hi.json +++ b/src/i18n/messages/hi.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json index 09c7da1eb7..2500a14407 100644 --- a/src/i18n/messages/it.json +++ b/src/i18n/messages/it.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/it_IT.json b/src/i18n/messages/it_IT.json index 21f4b2660f..333f18723d 100644 --- a/src/i18n/messages/it_IT.json +++ b/src/i18n/messages/it_IT.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index 09c7da1eb7..2500a14407 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/pt_PT.json b/src/i18n/messages/pt_PT.json index b447c987fd..c281896c81 100644 --- a/src/i18n/messages/pt_PT.json +++ b/src/i18n/messages/pt_PT.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index 09c7da1eb7..2500a14407 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/uk.json b/src/i18n/messages/uk.json index 09c7da1eb7..2500a14407 100644 --- a/src/i18n/messages/uk.json +++ b/src/i18n/messages/uk.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } diff --git a/src/i18n/messages/zh_CN.json b/src/i18n/messages/zh_CN.json index 09c7da1eb7..2500a14407 100644 --- a/src/i18n/messages/zh_CN.json +++ b/src/i18n/messages/zh_CN.json @@ -989,5 +989,7 @@ "course-authoring.course-unit.sequence-nav-label-text": "Sequence navigation", "course-authoring.course-unit.sequence.load.failure": "There was an error loading this course.", "course-authoring.course-unit.sequence.no.content": "There is no content here.", - "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}" + "course-authoring.course-unit.sequence.navigation.menu": "{current} of {total}", + "course-authoring.course-unit.add.component.title": "Add a new component", + "course-authoring.course-unit.add.component.button.text": "Add Component:" } From 5e2d93b5bb804e03968dc861bd40c97862d7074b Mon Sep 17 00:00:00 2001 From: Ihor Romaniuk Date: Thu, 11 Jan 2024 13:36:59 +0100 Subject: [PATCH 2/4] feat: Course unit - make Discussion and Drag-and-Drop button functional --- src/constants.js | 1 + src/course-unit/CourseUnit.jsx | 6 ++- .../add-component/AddComponent.jsx | 25 +++++++++++- .../add-component/AddComponent.test.jsx | 38 ++++++++++++++++++- .../add-component/ComponentIcon.jsx | 2 +- src/course-unit/constants.js | 28 +++++++++----- src/course-unit/data/api.js | 13 +++++++ src/course-unit/data/slice.js | 7 ++++ src/course-unit/data/thunk.js | 29 +++++++++++++- src/course-unit/hooks.jsx | 6 +++ 10 files changed, 140 insertions(+), 15 deletions(-) diff --git a/src/constants.js b/src/constants.js index 2b2d394c0d..eb1b17b372 100644 --- a/src/constants.js +++ b/src/constants.js @@ -20,6 +20,7 @@ export const BADGE_STATES = { }; export const NOTIFICATION_MESSAGES = { + adding: 'Adding', saving: 'Saving', duplicating: 'Duplicating', deleting: 'Deleting', diff --git a/src/course-unit/CourseUnit.jsx b/src/course-unit/CourseUnit.jsx index bbe3ba0241..b532fe0be2 100644 --- a/src/course-unit/CourseUnit.jsx +++ b/src/course-unit/CourseUnit.jsx @@ -34,6 +34,7 @@ const CourseUnit = ({ courseId }) => { headerNavigationsActions, handleTitleEdit, handleInternetConnectionFailed, + handleCreateNewCourseXblock, } = useCourseUnit({ courseId, blockId }); document.title = getPageHeadTitle('', unitTitle); @@ -88,7 +89,10 @@ const CourseUnit = ({ courseId }) => { xl={[{ span: 9 }, { span: 3 }]} > - + diff --git a/src/course-unit/add-component/AddComponent.jsx b/src/course-unit/add-component/AddComponent.jsx index 5a03e2e874..c4a8f844c0 100644 --- a/src/course-unit/add-component/AddComponent.jsx +++ b/src/course-unit/add-component/AddComponent.jsx @@ -1,15 +1,27 @@ +import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; import { useIntl } from '@edx/frontend-platform/i18n'; import { Button } from '@edx/paragon'; import { getCourseSectionVertical } from '../data/selectors'; +import { COMPONENT_ICON_TYPES } from '../constants'; import ComponentIcon from './ComponentIcon'; import messages from './messages'; -const AddComponent = () => { +const AddComponent = ({ blockId, handleCreateNewCourseXblock }) => { const intl = useIntl(); const { componentTemplates } = useSelector(getCourseSectionVertical); + const handleCreateNewXblock = (type) => () => { + switch (type) { + case COMPONENT_ICON_TYPES.discussion: + case COMPONENT_ICON_TYPES.dragAndDrop: + handleCreateNewCourseXblock({ type, parentLocator: blockId }); + break; + default: + } + }; + if (!Object.keys(componentTemplates).length) { return null; } @@ -20,7 +32,11 @@ const AddComponent = () => {
    {Object.keys(componentTemplates).map((component) => (
  • -