- Lorem Ipsum is simply dummy text of the printing and typesetting industry.
- Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
- when an unknown printer took a galley of type and scrambled it to make a type specimen book.
- It has survived not only five centuries, but also the leap into electronic typesetting,
- remaining essentially unchanged. It was popularised in the 1960s with the release
- of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
- publishing software like Aldus PageMaker including versions of Lorem Ipsum.
-
-
-);
+import {
+ Button, Container, useMediaQuery, breakpoints, Card, ActionRow,
+} from '@openedx/paragon';
+import { getConfig } from '@edx/frontend-platform';
+import { useIntl } from '@edx/frontend-platform/i18n';
+import { getAuthenticatedUser } from '@edx/frontend-platform/auth';
+
+import messages from '../messages';
+import type { CourseOverviewProps } from './types';
+import { processOverviewContent } from './utils';
+
+export const CourseOverview = ({ overviewData, courseId }: CourseOverviewProps) => {
+ const intl = useIntl();
+ const authenticatedUser = getAuthenticatedUser();
+ const isGlobalStaff = authenticatedUser?.administrator || false;
+ const isExtraSmall = useMediaQuery({ maxWidth: breakpoints.extraSmall.maxWidth });
+
+ const processedOverviewData = processOverviewContent(overviewData, getConfig().LMS_BASE_URL);
+ const hasOverviewContent = processedOverviewData.trim().length > 0;
+
+ if (!hasOverviewContent) {
+ if (!isGlobalStaff) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+ {isGlobalStaff && (
+
+
+
+ )}
+ />
+ )}
+
+ {
+ /* eslint-disable-next-line react/no-danger */
+
+ }
+
+
+
+ );
+};
diff --git a/src/course-about/course-overview/types.ts b/src/course-about/course-overview/types.ts
new file mode 100644
index 0000000..f5c277f
--- /dev/null
+++ b/src/course-about/course-overview/types.ts
@@ -0,0 +1,4 @@
+export interface CourseOverviewProps {
+ overviewData: string;
+ courseId: string;
+}
diff --git a/src/course-about/course-overview/utils.ts b/src/course-about/course-overview/utils.ts
new file mode 100644
index 0000000..497f57b
--- /dev/null
+++ b/src/course-about/course-overview/utils.ts
@@ -0,0 +1,15 @@
+/**
+ * Processes overview content to replace image paths
+ * @param overview - The overview HTML content
+ * @returns Processed overview content with updated image paths
+ */
+export const processOverviewContent = (overview: string, lmsBaseUrl: string): string => {
+ if (!overview) {
+ return overview;
+ }
+
+ return overview.replace(
+ /src="\/(static\/images\/|asset)/g,
+ (_, path) => `src="${lmsBaseUrl}/${path}`,
+ );
+};
diff --git a/src/course-about/messages.ts b/src/course-about/messages.ts
index aff0839..0f7664a 100644
--- a/src/course-about/messages.ts
+++ b/src/course-about/messages.ts
@@ -6,6 +6,11 @@ const messages = defineMessages({
defaultMessage: 'If you experience repeated failures, please email support at {supportEmail}',
description: 'Error page message.',
},
+ viewAboutPageInStudio: {
+ id: 'catalog.course-about.view-about-page-in-studio',
+ defaultMessage: 'View About Page in Studio',
+ description: 'Link to view the Schedule and Details page in Studio.',
+ },
});
export default messages;
diff --git a/src/plugin-slots/CourseAboutOverviewSlot/README.md b/src/plugin-slots/CourseAboutOverviewSlot/README.md
new file mode 100644
index 0000000..c3e8afb
--- /dev/null
+++ b/src/plugin-slots/CourseAboutOverviewSlot/README.md
@@ -0,0 +1,119 @@
+# Course about overview slot
+
+### Slot ID: `org.openedx.frontend.catalog.course_about_page.overview`
+
+## Description
+
+This slot is used to replace/modify/hide the entire course about overview section on the Course about page.
+
+### Plugin Props:
+
+* `overviewData` - Object. HTML content of the course overview section.
+* `courseId` - String. The unique identifier of the course.
+
+## Examples
+
+### Default content
+
+
+
+### Replaced with custom component
+
+
+
+The following `env.config.tsx` will replace the Course About page overview slot entirely (in this case with a centered `h1` tag)
+
+```tsx
+import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
+
+const config = {
+ pluginSlots: {
+ 'org.openedx.frontend.catalog.course_about_page.overview': {
+ keepDefault: false,
+ plugins: [
+ {
+ op: PLUGIN_OPERATIONS.Insert,
+ widget: {
+ id: 'custom_about_page_overview_component',
+ type: DIRECT_PLUGIN,
+ RenderWidget: () => (
+
🦶
+ ),
+ },
+ },
+ ]
+ }
+ },
+}
+
+export default config;
+```
+
+### Custom component with plugin props
+
+**Default overview section:**
+
+
+**Custom button component:**
+
+
+**Modal dialog with course overview content:**
+
+
+The following `env.config.tsx` example demonstrates how to replace the Course About page overview slot with a custom component that uses the plugin props (`overviewData` and `courseId`). In this case, it creates a modal dialog that displays the course overview content when a button is clicked.
+
+```tsx
+import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
+import { useToggle, Button, ModalDialog } from '@openedx/paragon';
+
+const CourseOverviewModal = ({ overviewData, courseId }) => {
+ const [isOpen, open, close] = useToggle(false);
+
+ return (
+ <>
+
+
+
+
+ {courseId}
+
+
+
+
+
+
+ >
+ )
+}
+
+const config = {
+ pluginSlots: {
+ 'org.openedx.frontend.catalog.course_about_page.overview': {
+ keepDefault: false,
+ plugins: [
+ {
+ op: PLUGIN_OPERATIONS.Insert,
+ widget: {
+ id: 'custom_about_page_overview_component',
+ type: DIRECT_PLUGIN,
+ RenderWidget: ({ overviewData, courseId }) => (
+
+ ),
+ },
+ },
+ ]
+ }
+ },
+}
+
+export default config;
+```
diff --git a/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom.png b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom.png
new file mode 100644
index 0000000..8f30717
Binary files /dev/null and b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom.png differ
diff --git a/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom_button.png b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom_button.png
new file mode 100644
index 0000000..8fac217
Binary files /dev/null and b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom_button.png differ
diff --git a/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom_modal.png b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom_modal.png
new file mode 100644
index 0000000..8df69d9
Binary files /dev/null and b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_custom_modal.png differ
diff --git a/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_default.png b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_default.png
new file mode 100644
index 0000000..5dc7f87
Binary files /dev/null and b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_default.png differ
diff --git a/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_default_with_overview_contant.png b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_default_with_overview_contant.png
new file mode 100644
index 0000000..29e1d5a
Binary files /dev/null and b/src/plugin-slots/CourseAboutOverviewSlot/images/screenshot_default_with_overview_contant.png differ
diff --git a/src/plugin-slots/CourseAboutOverviewSlot/index.tsx b/src/plugin-slots/CourseAboutOverviewSlot/index.tsx
new file mode 100644
index 0000000..b0eda83
--- /dev/null
+++ b/src/plugin-slots/CourseAboutOverviewSlot/index.tsx
@@ -0,0 +1,18 @@
+import { PluginSlot } from '@openedx/frontend-plugin-framework';
+
+import { CourseOverview } from '@src/course-about/course-overview';
+import type { CourseOverviewProps } from '@src/course-about/course-overview/types';
+
+const CourseAboutOverviewSlot = ({ overviewData, courseId }: CourseOverviewProps) => (
+
+
+
+);
+
+export default CourseAboutOverviewSlot;