feat: standardize slot ids (#1854)

This commit is contained in:
Brian Smith
2025-04-24 07:27:04 -04:00
committed by GitHub
parent e7c22b1cbf
commit 7edb3528ba
30 changed files with 223 additions and 44 deletions

2
package-lock.json generated
View File

@@ -37,7 +37,7 @@
"@openedx-plugins/course-app-wiki": "file:plugins/course-apps/wiki",
"@openedx-plugins/course-app-xpert_unit_summary": "file:plugins/course-apps/xpert_unit_summary",
"@openedx/frontend-build": "^14.3.3",
"@openedx/frontend-plugin-framework": "^1.6.0",
"@openedx/frontend-plugin-framework": "^1.7.0",
"@openedx/frontend-slot-footer": "^1.2.0",
"@openedx/paragon": "^22.16.0",
"@redux-devtools/extension": "^3.3.0",

View File

@@ -61,7 +61,7 @@
"@openedx-plugins/course-app-wiki": "file:plugins/course-apps/wiki",
"@openedx-plugins/course-app-xpert_unit_summary": "file:plugins/course-apps/xpert_unit_summary",
"@openedx/frontend-build": "^14.3.3",
"@openedx/frontend-plugin-framework": "^1.6.0",
"@openedx/frontend-plugin-framework": "^1.7.0",
"@openedx/frontend-slot-footer": "^1.2.0",
"@openedx/paragon": "^22.16.0",
"@redux-devtools/extension": "^3.3.0",

View File

@@ -11,7 +11,7 @@ import {
TransitionReplace,
} from '@openedx/paragon';
import { ChevronLeft, ChevronRight, Close } from '@openedx/paragon/icons';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import { AdditionalTranslationsComponentSlot } from '../../../plugin-slots/AdditionalTranslationsComponentSlot';
import OrderTranscriptForm from './OrderTranscriptForm';
import messages from './messages';
import {
@@ -116,14 +116,12 @@ const TranscriptSettings = ({
)}
<TransitionReplace>
<div data-testid="translations-component">
<PluginSlot
id="additonal_translations_component_slot"
pluginProps={{
setIsAiTranslations,
closeTranscriptSettings,
courseId,
additionalProps: { transcriptType, isAiTranslationsEnabled },
}}
<AdditionalTranslationsComponentSlot
setIsAiTranslations={setIsAiTranslations}
closeTranscriptSettings={closeTranscriptSettings}
courseId={courseId}
transcriptType={transcriptType}
isAiTranslationsEnabled={isAiTranslationsEnabled}
/>
</div>
</TransitionReplace>

View File

@@ -20,6 +20,8 @@ import { RequestStatus } from '../data/constants';
import SettingsComponent from './SettingsComponent';
import PermissionDeniedAlert from '../generic/PermissionDeniedAlert';
import getPageHeadTitle from '../generic/utils';
import { AdditionalCoursePluginSlot } from '../plugin-slots/AdditionalCoursePluginSlot';
import { AdditionalCourseContentPluginSlot } from '../plugin-slots/AdditionalCourseContentPluginSlot';
const PagesAndResources = ({ courseId }) => {
const intl = useIntl();
@@ -90,7 +92,7 @@ const PagesAndResources = ({ courseId }) => {
<Route path=":appId/settings" element={<PageWrap><SettingsComponent url={redirectUrl} /></PageWrap>} />
</Routes>
<PageGrid pages={pages} pluginSlotId="additional_course_plugin" courseId={courseId} />
<PageGrid pages={pages} pluginSlotComponent={AdditionalCoursePluginSlot} courseId={courseId} />
{
(contentPermissionsPages.length > 0 || hasAdditionalCoursePlugin)
&& (
@@ -98,7 +100,7 @@ const PagesAndResources = ({ courseId }) => {
<div className="d-flex justify-content-between my-4 my-md-5 align-items-center">
<h3 className="m-0">{intl.formatMessage(messages.contentPermissions)}</h3>
</div>
<PageGrid pages={contentPermissionsPages} pluginSlotId="additional_course_content_plugin" />
<PageGrid pages={contentPermissionsPages} pluginSlotComponent={AdditionalCourseContentPluginSlot} />
</>
)
}

View File

@@ -1,10 +1,9 @@
import PropTypes from 'prop-types';
import React from 'react';
import { CardGrid } from '@openedx/paragon';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
import PageCard, { CoursePageShape } from './PageCard';
const PageGrid = ({ pages, pluginSlotId, courseId }) => (
const PageGrid = ({ pages, pluginSlotComponent, courseId }) => (
<CardGrid columnSizes={{
xs: 12,
sm: 6,
@@ -15,18 +14,18 @@ const PageGrid = ({ pages, pluginSlotId, courseId }) => (
{pages.map((page) => (
<PageCard page={page} key={page.id} courseId={courseId} />
))}
{pluginSlotId && <PluginSlot id={pluginSlotId} />}
{pluginSlotComponent}
</CardGrid>
);
PageGrid.defaultProps = {
pluginSlotId: null,
pluginSlotComponent: null,
courseId: null,
};
PageGrid.propTypes = {
pages: PropTypes.arrayOf(CoursePageShape.isRequired).isRequired,
pluginSlotId: PropTypes.string,
pluginSlotComponent: PropTypes.element,
courseId: PropTypes.string,
};

View File

@@ -0,0 +1,6 @@
# AdditionalCourseContentPluginSlot
### Slot ID: `org.openedx.frontend.authoring.additional_course_content_plugin.v1`
### Slot ID Aliases
* `additional_course_content_plugin`

View File

@@ -0,0 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AdditionalCourseContentPluginSlot renders 1`] = `
<PluginSlot
id="org.openedx.frontend.authoring.additional_course_content_plugin.v1"
idAliases={
[
"additional_course_content_plugin",
]
}
/>
`;

View File

@@ -0,0 +1,15 @@
import { shallow } from '@edx/react-unit-test-utils';
import { AdditionalCourseContentPluginSlot } from '.';
jest.mock('@openedx/frontend-plugin-framework', () => ({
PluginSlot: 'PluginSlot',
}));
describe('AdditionalCourseContentPluginSlot', () => {
beforeEach(() => jest.resetAllMocks());
it('renders', () => {
const wrapper = shallow(<AdditionalCourseContentPluginSlot />);
expect(wrapper.snapshot).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,9 @@
import { PluginSlot } from '@openedx/frontend-plugin-framework/dist';
import React from 'react';
export const AdditionalCourseContentPluginSlot = () => (
<PluginSlot
id="org.openedx.frontend.authoring.additional_course_content_plugin.v1"
idAliases={['additional_course_content_plugin']}
/>
);

View File

@@ -0,0 +1,6 @@
# AdditionalCoursePluginSlot
### Slot ID: `org.openedx.frontend.authoring.additional_course_plugin.v1`
### Slot ID Aliases
* `additional_course_plugin`

View File

@@ -0,0 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`AdditionalCoursePluginSlot renders 1`] = `
<PluginSlot
id="org.openedx.frontend.authoring.additional_course_plugin.v1"
idAliases={
[
"additional_course_plugin",
]
}
/>
`;

View File

@@ -0,0 +1,15 @@
import { shallow } from '@edx/react-unit-test-utils';
import { AdditionalCoursePluginSlot } from '.';
jest.mock('@openedx/frontend-plugin-framework', () => ({
PluginSlot: 'PluginSlot',
}));
describe('AdditionalCoursePluginSlot', () => {
beforeEach(() => jest.resetAllMocks());
it('renders', () => {
const wrapper = shallow(<AdditionalCoursePluginSlot />);
expect(wrapper.snapshot).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,9 @@
import { PluginSlot } from '@openedx/frontend-plugin-framework/dist';
import React from 'react';
export const AdditionalCoursePluginSlot = () => (
<PluginSlot
id="org.openedx.frontend.authoring.additional_course_plugin.v1"
idAliases={['additional_course_plugin']}
/>
);

View File

@@ -0,0 +1,15 @@
# AdditionalTranslationsComponentSlot
### Slot ID: `org.openedx.frontend.authoring.video_transcript_additional_translations_component.v1`
### Slot ID Aliases
* `additonal_translations_component_slot` (original misspelling)
* `additional_translations_component_slot`
### Plugin Props:
* `setIsAiTranslations` - Function (React SetState)
* `closeTranscriptSettings` - Function (Paragon useToggle)
* `courseId` - String
* `additionalProps` - Object
* `transcriptType` - String
* `isAiTranslationsEnabled` - Boolean

View File

@@ -0,0 +1,32 @@
import { PluginSlot } from '@openedx/frontend-plugin-framework/dist';
import React from 'react';
export const AdditionalTranslationsComponentSlot = ({
setIsAiTranslations,
closeTranscriptSettings,
courseId,
transcriptType,
isAiTranslationsEnabled,
}: AdditionalTranslationsComponentSlotProps) => (
<PluginSlot
id="org.openedx.frontend.authoring.video_transcript_additional_translations_component.v1"
idAliases={[
'additonal_translations_component_slot', // original misspelling
'additional_translations_component_slot',
]}
pluginProps={{
setIsAiTranslations,
closeTranscriptSettings,
courseId,
additionalProps: { transcriptType, isAiTranslationsEnabled },
}}
/>
);
interface AdditionalTranslationsComponentSlotProps {
setIsAiTranslations: React.Dispatch<React.SetStateAction<boolean>>;
closeTranscriptSettings: () => void;
courseId: string;
transcriptType: string;
isAiTranslationsEnabled: boolean;
}

View File

@@ -1,6 +1,9 @@
# CourseAuthoringOutlineSidebarSlot
### Slot ID: `course_authoring_outline_sidebar_slot`
### Slot ID: `org.openedx.frontend.authoring.course_outline_sidebar.v1`
### Slot ID Aliases
* `course_authoring_outline_sidebar_slot`
### Plugin Props:
@@ -24,7 +27,7 @@ import { PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const config = {
pluginSlots: {
course_authoring_outline_sidebar_slot: {
'org.openedx.frontend.authoring.course_outline_sidebar.v1': {
keepDefault: true,
plugins: [
{

View File

@@ -8,7 +8,8 @@ export const CourseAuthoringOutlineSidebarSlot = ({
sections,
}: CourseAuthoringOutlineSidebarSlotProps) => (
<PluginSlot
id="course_authoring_outline_sidebar_slot"
id="org.openedx.frontend.authoring.course_outline_sidebar.v1"
idAliases={['course_authoring_outline_sidebar_slot']}
pluginProps={{
courseId,
courseName,

View File

@@ -1,6 +1,9 @@
# CourseAuthoringUnitSidebarSlot
### Slot ID: `course_authoring_unit_sidebar_slot`
### Slot ID: `org.openedx.frontend.authoring.course_unit_sidebar.v1`
### Slot ID Aliases
* `course_authoring_unit_sidebar_slot`
### Plugin Props:
@@ -25,7 +28,7 @@ import { PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework';
const config = {
pluginSlots: {
course_authoring_unit_sidebar_slot: {
'org.openedx.frontend.authoring.course_unit_sidebar.v1': {
keepDefault: true,
plugins: [
{
@@ -63,7 +66,7 @@ const ProblemBlocks = ({unitTitle, xBlocks}) => (
const config = {
pluginSlots: {
course_authoring_unit_sidebar_slot: {
'org.openedx.frontend.authoring.course_unit_sidebar.v1': {
keepDefault: true,
plugins: [
{

View File

@@ -14,7 +14,8 @@ export const CourseAuthoringUnitSidebarSlot = (
}: CourseAuthoringUnitSidebarSlotProps,
) => (
<PluginSlot
id="course_authoring_unit_sidebar_slot"
id="org.openedx.frontend.authoring.course_unit_sidebar.v1"
idAliases={['course_authoring_unit_sidebar_slot']}
pluginProps={{
blockId, courseId, unitTitle, xBlocks,
}}

View File

@@ -1,6 +1,10 @@
# CourseOutlineHeaderActionsSlot
### Slot ID: `course_outline_header_actions_slot`
### Slot ID: `org.openedx.frontend.authoring.course_outline_header_actions.v1`
### Slot ID Aliases
* `course_outline_header_actions_slot`
### Plugin Props:
* `isReIndexShow` - Boolean.
@@ -33,7 +37,7 @@ const MyButton = () => (
const config = {
pluginSlots: {
course_outline_header_actions_slot: {
'org.openedx.frontend.authoring.course_outline_header_actions.v1': {
keepDefault: true,
plugins: [
{

View File

@@ -2,7 +2,12 @@
exports[`CourseOutlineHeaderActionsSlot pluginProps are set correctly 1`] = `
<PluginSlot
id="course_outline_header_actions_slot"
id="org.openedx.frontend.authoring.course_outline_header_actions.v1"
idAliases={
[
"course_outline_header_actions_slot",
]
}
pluginProps={
{
"courseActions": {

View File

@@ -15,7 +15,8 @@ const CourseOutlineHeaderActionsSlot = ({
sections,
}) => (
<PluginSlot
id="course_outline_header_actions_slot"
id="org.openedx.frontend.authoring.course_outline_header_actions.v1"
idAliases={['course_outline_header_actions_slot']}
pluginProps={{
isReIndexShow,
isSectionsExpanded,

View File

@@ -1,6 +1,10 @@
# CourseOutlineSubsectionCardExtraActionsSlot
### Slot ID: `course_outline_subsection_card_extra_actions_slot`
### Slot ID: `org.openedx.frontend.authoring.course_outline_subsection_card_extra_actions.v1`
### Slot ID Aliases
* `course_outline_subsection_card_extra_actions_slot`
### Plugin Props:
* `section` - object
@@ -36,7 +40,7 @@ const MyIconButton = () => (
const config = {
pluginSlots: {
course_outline_subsection_card_extra_actions_slot: {
'org.openedx.frontend.authoring.course_outline_subsection_card_extra_actions.v1': {
keepDefault: true,
plugins: [
{

View File

@@ -4,7 +4,11 @@ import PropTypes from 'prop-types';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
const CourseOutlineSubsectionCardExtraActionsSlot = ({ subsection, section }) => (
<PluginSlot id="course_outline_subsection_card_extra_actions_slot" pluginProps={{ subsection, section }} />
<PluginSlot
id="org.openedx.frontend.authoring.course_outline_subsection_card_extra_actions.v1"
idAliases={['course_outline_subsection_card_extra_actions_slot']}
pluginProps={{ subsection, section }}
/>
);
CourseOutlineSubsectionCardExtraActionsSlot.propTypes = {

View File

@@ -1,6 +1,10 @@
# CourseOutlineUnitCardExtraActionsSlot
### Slot ID: `course_outline_unit_card_extra_actions_slot`
### Slot ID: `org.openedx.frontend.authoring.course_outline_unit_card_extra_actions.v1`
### Slot ID Aliases
* `course_outline_unit_card_extra_actions_slot`
### Plugin Props:
* `unit` - object
@@ -37,7 +41,7 @@ const MyIconButton = () => (
const config = {
pluginSlots: {
course_outline_unit_card_extra_actions_slot: {
'org.openedx.frontend.authoring.course_outline_unit_card_extra_actions.v1': {
keepDefault: true,
plugins: [
{

View File

@@ -4,7 +4,11 @@ import PropTypes from 'prop-types';
import { PluginSlot } from '@openedx/frontend-plugin-framework';
const CourseOutlineUnitCardExtraActionsSlot = ({ unit, subsection, section }) => (
<PluginSlot id="course_outline_unit_card_extra_actions_slot" pluginProps={{ unit, subsection, section }} />
<PluginSlot
id="org.openedx.frontend.authoring.course_outline_unit_card_extra_actions.v1"
idAliases={['course_outline_unit_card_extra_actions_slot']}
pluginProps={{ unit, subsection, section }}
/>
);
CourseOutlineUnitCardExtraActionsSlot.propTypes = {

View File

@@ -1,6 +1,10 @@
# CourseUnitHeaderActionsSlot
### Slot ID: `course_unit_header_actions_slot`
### Slot ID: `org.openedx.frontend.authoring.course_unit_header_actions.v1`
### Slot ID Aliases
* `course_unit_header_actions_slot`
### Plugin Props:
* `headerNavigationsActions` - Object. See the prop-types definition in the component for details.
@@ -31,7 +35,7 @@ const MyButton = () => (
const config = {
pluginSlots: {
course_unit_header_actions_slot: {
'org.openedx.frontend.authoring.course_unit_header_actions.v1': {
keepDefault: true,
plugins: [
{

View File

@@ -2,7 +2,12 @@
exports[`CourseUnitHeaderActionsSlot pluginProps are set correctly 1`] = `
<PluginSlot
id="course_unit_header_actions_slot"
id="org.openedx.frontend.authoring.course_unit_header_actions.v1"
idAliases={
[
"course_unit_header_actions_slot",
]
}
pluginProps={
{
"category": "vertical",

View File

@@ -12,7 +12,8 @@ const CourseUnitHeaderActionsSlot = ({
const isUnitVerticalType = category === COURSE_BLOCK_NAMES.vertical.id;
return (
<PluginSlot
id="course_unit_header_actions_slot"
id="org.openedx.frontend.authoring.course_unit_header_actions.v1"
idAliases={['course_unit_header_actions_slot']}
pluginProps={{
headerNavigationsActions, category, unitTitle, isUnitVerticalType, verticalBlocks,
}}

View File

@@ -1,14 +1,19 @@
# `frontend-app-authoring` Plugin Slots
## Course Outline Page
* [`course_outline_header_actions_slot`](./CourseOutlineHeaderActionsSlot/)
* [`course_outline_subsection_card_extra_actions_slot`](./CourseOutlineSubsectionCardExtraActionsSlot)
* [`course_outline_unit_card_extra_actions_slot`](./CourseOutlineUnitCardExtraActionsSlot)
* [`org.openedx.frontend.authoring.course_outline_header_actions.v1`](./CourseOutlineHeaderActionsSlot/)
* [`org.openedx.frontend.authoring.course_outline_sidebar.v1`](./CourseAuthoringOutlineSidebarSlot/)
* [`org.openedx.frontend.authoring.course_outline_subsection_card_extra_actions.v1`](./CourseOutlineSubsectionCardExtraActionsSlot)
* [`org.openedx.frontend.authoring.course_outline_unit_card_extra_actions.v1`](./CourseOutlineUnitCardExtraActionsSlot)
## Course Unit page
* [`org.openedx.frontend.authoring.course_unit_header_actions.v1`](./CourseUnitHeaderActionsSlot/)
* [`org.openedx.frontend.authoring.course_unit_sidebar.v1`](./CourseAuthoringUnitSidebarSlot/)
* [`course_unit_header_actions_slot`](./CourseUnitHeaderActionsSlot/)
## Other Slots
* [`org.openedx.frontend.authoring.additional_course_content_plugin.v1`](./AdditionalCourseContentPluginSlot/)
* [`org.openedx.frontend.authoring.additional_course_plugin.v1`](./AdditionalCoursePluginSlot/)
* [`org.openedx.frontend.authoring.video_transcript_additional_translations_component.v1`](./AdditionalTranslationsComponentSlot/)
## Footer Slot
* [`studio_footer_slot`](./StudioFooterSlot/)