Created
March 20, 2025 14:53
-
-
Save xitij2000/012417d3e84a1354e9733456c866fd53 to your computer and use it in GitHub Desktop.
Authoring MFE plugin for aspects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { DIRECT_PLUGIN, PLUGIN_OPERATIONS } from '@openedx/frontend-plugin-framework'; | |
import { | |
Button, | |
Card, | |
Dropdown, | |
DropdownButton, | |
Icon, | |
IconButton, | |
IconButtonWithTooltip | |
} from '@openedx/paragon'; | |
import { Analytics, ArrowBack, AvTimer, Close } from '@openedx/paragon/icons'; | |
import { getCourseUnit } from "CourseAuthoring/course-unit/data/selectors"; | |
import { useModel } from "CourseAuthoring/generic/model-store"; | |
import React, { useEffect } from 'react'; | |
import { useSelector } from "react-redux"; | |
import { useParams } from "react-router-dom"; | |
const AspectsSidebarContext = React.createContext({ | |
showSidebar: false, | |
location: null, | |
}); | |
const AspectsSidebarProvider = ({component}) => { | |
const [showSidebar, setShowSidebar] = React.useState(true); | |
const [location, setLocation] = React.useState(null); | |
return ( | |
<AspectsSidebarContext.Provider | |
value={{ | |
showSidebar, | |
location, | |
setShowSidebar, | |
setLocation | |
}} | |
> | |
{component} | |
</AspectsSidebarContext.Provider> | |
); | |
} | |
const CourseUnitButton = () => { | |
const {blockId} = useParams(); | |
const { | |
showSidebar, | |
setShowSidebar, | |
setLocation, | |
} = React.useContext(AspectsSidebarContext); | |
return ( | |
<Button | |
variant={ | |
showSidebar ? "primary":"outline-primary" | |
} | |
iconBefore={Analytics} | |
onClick={() => { | |
setShowSidebar(!showSidebar); | |
setLocation(blockId); | |
}} | |
> | |
Analytics | |
</Button> | |
); | |
}; | |
const CourseOutlineButton = () => { | |
const { | |
showSidebar, | |
setShowSidebar, | |
setLocation | |
} = React.useContext(AspectsSidebarContext); | |
return ( | |
<Button | |
variant={ | |
showSidebar ? "primary":"outline-primary" | |
} | |
iconBefore={Analytics} | |
onClick={() => { | |
setShowSidebar(!showSidebar); | |
setLocation(null) | |
}} | |
> | |
AnalyticsO | |
</Button> | |
); | |
}; | |
const UnitActionsButton = ({cardId, isVertical}) => { | |
const { | |
showSidebar, | |
location, | |
setShowSidebar, | |
setLocation | |
} = React.useContext(AspectsSidebarContext); | |
return isVertical && ( | |
<IconButton | |
isActive={showSidebar && location===cardId} | |
alt="Analytics" | |
src={Analytics} | |
iconAs={Icon} | |
variant="black" | |
onClick={() => { | |
if (location===cardId) { | |
setShowSidebar(false); | |
} else { | |
setLocation(cardId); | |
setShowSidebar(true); | |
} | |
}} | |
/> | |
); | |
} | |
const SidebarToggleWrapper = ({component}) => { | |
const { | |
showSidebar, | |
} = React.useContext(AspectsSidebarContext); | |
return !showSidebar && component; | |
} | |
const Sidebar = () => { | |
const { | |
showSidebar, | |
location, | |
setShowSidebar, | |
setLocation | |
} = React.useContext(AspectsSidebarContext); | |
const {courseId} = useParams(); | |
const courseDetails = useModel('courseDetails', courseId); | |
const unit = useSelector(getCourseUnit); | |
return showSidebar && ( | |
<Card className="bg-white rounded"> | |
<div className="sidebar-header d-flex flex-column shadow p-2 bg-light-200 "> | |
<div className="d-flex flex-row align-items-center justify-content-between"> | |
<span className="small sidebar-title d-flex"> | |
Analytics <Icon src={Analytics}/> | |
</span> | |
<IconButtonWithTooltip tooltipContent={"Close"} tooltipPlacement="top" | |
alt="Close" src={Close} iconAs={Icon} variant="black" | |
onClick={() => { | |
setShowSidebar(false); | |
}}/> | |
</div> | |
<div className="d-flex flex-row align-items-center justify-content-between"> | |
{location && | |
<IconButton alt="Back" src={ArrowBack} iconAs={Icon} variant="black" | |
onClick={() => setLocation(null)} size="inline"/>} | |
{location ? | |
unit?.unit?.displayName | |
:courseDetails?.name} | |
</div> | |
<DropdownButton variant="outline-primary" title={ | |
<span className="d-flex align-items-center mr-1 p-0"><Icon src={AvTimer}/>Dropdown button</span> | |
}> | |
<Dropdown.Item href="#/action-1">Action</Dropdown.Item> | |
<Dropdown.Item href="#/action-2">Another action</Dropdown.Item> | |
<Dropdown.Item href="#/action-3">Something else</Dropdown.Item> | |
</DropdownButton> | |
</div> | |
<iframe className="w-100" srcDoc="TEST"/> | |
</Card> | |
) | |
}; | |
const config = { | |
pluginSlots: { | |
course_outline_sidebar: { | |
keepDefault: true, | |
plugins: [ | |
{ | |
op: PLUGIN_OPERATIONS.Insert, | |
widget: { | |
id: 'outline-sidebar', | |
priority: 1, | |
type: DIRECT_PLUGIN, | |
RenderWidget: Sidebar, | |
}, | |
}, | |
{ | |
op: PLUGIN_OPERATIONS.Wrap, | |
widgetId: 'default_contents', | |
wrapper: SidebarToggleWrapper, | |
} | |
] | |
}, | |
course_unit_sidebar: { | |
keepDefault: true, | |
plugins: [ | |
{ | |
op: PLUGIN_OPERATIONS.Insert, | |
widget: { | |
id: 'course-unit-sidebar', | |
priority: 1, | |
type: DIRECT_PLUGIN, | |
RenderWidget: Sidebar, | |
}, | |
}, | |
{ | |
op: PLUGIN_OPERATIONS.Wrap, | |
widgetId: 'default_contents', | |
wrapper: SidebarToggleWrapper, | |
} | |
] | |
}, | |
course_unit_header_actions_slot: { | |
keepDefault: true, | |
plugins: [ | |
{ | |
op: PLUGIN_OPERATIONS.Insert, | |
widget: { | |
id: 'unit-header-aspects-button', | |
priority: 60, | |
type: DIRECT_PLUGIN, | |
RenderWidget: CourseUnitButton, | |
}, | |
}, | |
] | |
}, | |
course_outline_header_actions_slot: { | |
keepDefault: true, | |
plugins: [ | |
{ | |
op: PLUGIN_OPERATIONS.Insert, | |
widget: { | |
id: 'outline-header-aspects-button', | |
priority: 60, | |
type: DIRECT_PLUGIN, | |
RenderWidget: CourseOutlineButton, | |
}, | |
}, | |
] | |
}, | |
course_outline_header_slot: { | |
keepDefault: true, | |
plugins: [ | |
{ | |
op: PLUGIN_OPERATIONS.Insert, | |
widget: { | |
id: 'units-action-aspects-button', | |
priority: 60, | |
type: DIRECT_PLUGIN, | |
RenderWidget: UnitActionsButton, | |
}, | |
}, | |
] | |
}, | |
authoring_app_wrapper: { | |
keepDefault: true, | |
plugins: [ | |
{ | |
op: PLUGIN_OPERATIONS.Wrap, | |
widgetId: 'default_contents', | |
wrapper: AspectsSidebarProvider, | |
} | |
] | |
} | |
}, | |
} | |
export default config; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment