Skip to content

Conversation

@ahtesham-quraish
Copy link
Contributor

What are the relevant tickets?

In refernce to https://github.com/mitodl/hq/issues/9314

Description (What does it do?)

Want to provide content creators with the ability to insert course card inside the Tiptap editor.
The custom plugin should support adding course card inside the tiptap editor

Screenshots (if appropriate):

image Screenshot 2025-11-20 at 1 31 58 PM Screenshot 2025-11-20 at 1 32 10 PM

How can this be tested?

  • Hit the following url '/articles/new'
  • You would see the course embed icon in toolbar, click on that
  • A modal will open where you paste the url of the course, e.g ( http://open.odl.local:8062/search?resource=297 )
  • then give title of the article
  • click save, after that saving the content you will be redirecting to detail page of the article

@github-actions
Copy link

github-actions bot commented Nov 20, 2025

OpenAPI Changes

Show/hide No detectable change.

Unexpected changes? Ensure your branch is up-to-date with main (consider rebasing).

@ahtesham-quraish ahtesham-quraish changed the title Ahtesham/course plugin feat: course embedding plugin Nov 20, 2025
@ahtesham-quraish ahtesham-quraish changed the title feat: course embedding plugin feat: course card embedding plugin Nov 20, 2025
@@ -0,0 +1,10 @@
.simple-editor-content .tiptap.ProseMirror .node-learningResource {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we style using @emotion/styled. The Sass files should be for vendor code only.

In ./components/TiptapEditor/components/tiptap-node/learning-resource-node/LearningResourceListCard.tsx you should be able to do:

const StyledLearningResourceListCard = styled(LearningResourceListCard)({
  color: "inherit",
  textDecoration: "none",
  span:{
    textDecoration: "none"
  }
})

We may want to apply reset styles though if these are to override TipTap's css.

For styling elements other than our own components we can create a styled editor and target with nested selectors, e.g.

const StyledEditor = styled(TiptapEditor)({
  ".target-classname": {
    ...
  }
})

Copy link
Contributor

@jonkafton jonkafton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works nicely. Can you please take a look at moving the styles and let's start separating vendor code from our own. We need to make sure it's very clear which code we've written and which has been provided by library templates. We'll be moving the TipTap simple template code into ./components/TipTap/vendor (please feel free to make this change).

One suggestion looks like this, though let's catch up with @ChristopherChudzicki and agree on the approach:

  • Move code ejected from the tiptap simple editor into TipTapEditor/vendor/SimpleTemplate/
  • Run the simple template again to ensure that code is untouched.
  • The extension(s) we have added are moved to TipTapEditor/components.
  • Agree a strict rule that vendor code cannot be changed. Extensions must be extended from existing or created fresh.
  • Add a native git hook (works without pre-commit) that prevents changes to vendor files at their version.

if (!url) return

// Extract `resource=XYZ`
const match = url.match(/resource=(\d+)/)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also allow just the resource ID to be entered. It would be good to provide a resource search here, though we can leave that for a later iteration if others agree.

console.log("URL received from modal:", url)
if (!url) return

// Extract `resource=XYZ`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Extract `resource=XYZ`
// Extract `resource=123`


const handleEmbed = useCallback(async () => {
const url: string = await NiceModal.show(CourseUrlInputDialog)
console.log("URL received from modal:", url)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove

isVisible,
canInsert,
label,
Icon, // SVG icon (same as your media embed pattern)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment not needed here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants