Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support merging base component props, custom props, and pluginProps via slotOptions.mergeProps #84

Conversation

adamstankiewicz
Copy link
Member

@adamstankiewicz adamstankiewicz commented Aug 23, 2024

CHANGELOG

This PR introduces several key improvements, bug fixes, and new features to the frontend-plugin-framework. The following changes have been made:

Slot Options for PluginSlot

  • Consumers can now pass the slotOptions prop to the PluginSlot component.
  • The current slotOptions allow opting into merging props, rather than exposing prop modifications solely within content to the widget.
  • This prop merging functionality supports both custom widgets and the default_contents widget, and handles special cases such as className, style, and event handlers (i.e., functions).

Validation of PluginSlot Children

  • Prop merging for the default_contents widget now only works when PluginSlot contains a single React element as its children, but you may still pass all types of children, including plain text (strings), multiple elements, etc.

Parity in Widget Prop Handling

  • Ensured that pluginProps are passed to the default_contents widget, achieving consistency across all widgets.
  • This removes the need for PluginSlot to pass some widget props both in pluginProps and directly to the default children element, as is done in a few existing usages.

React Key Warning Fix

  • Resolved an issue where React's key warning was triggered when a widget was wrapped via a plugin.

Default Value Adjustment for className

  • The default value for the className prop has been changed to undefined. This ensures that an empty class attribute isn't rendered in the DOM.

Automated TOC and PluginSlot Examples in Example App

  • The ExamplePage in the example app now automates the generation of a Table of Contents (TOC) and PluginSlot examples.
  • Skip links have been added to improve the discoverability of specific examples.

New PluginOperations.Modify Example

  • Added a new example of PluginOperations.Modify applied to the "default_contents" widget in the example app's ExamplePage.

NPM Script Updates

  • Updated the start NPM script to exclude test files by removing the --copy-files flag.
  • Introduced a new test:watch NPM script to streamline the testing process.

Test Enhancements

  • Updated the test suite to include new cases covering the prop merging functionality.

Minor Syntax Cleanup

  • Performed minor syntax improvements for code consistency and readability.

These changes improve the overall robustness of the framework, provide better customization options for consumers, and address some existing issues with the current implementation.

Examples

Enabling merged props within PluginSlot via slotOptions

<PluginSlot
  id="slot_name"
  // Default slotOptions
  slotOptions={{
    mergeProps: true,
  }}
>
  <span>Hello, world</span>
</PluginSlot>

@adamstankiewicz adamstankiewicz force-pushed the ags/modify-default-contents-props branch from f8aca45 to e068ebd Compare August 23, 2024 19:32
Copy link

codecov bot commented Aug 23, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.80%. Comparing base (bf8705b) to head (751831b).
Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master      #84      +/-   ##
==========================================
+ Coverage   96.79%   97.80%   +1.01%     
==========================================
  Files          10       10              
  Lines         187      228      +41     
  Branches       41       58      +17     
==========================================
+ Hits          181      223      +42     
+ Misses          5        4       -1     
  Partials        1        1              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@adamstankiewicz adamstankiewicz force-pushed the ags/modify-default-contents-props branch 2 times, most recently from 716ba3e to 3702c58 Compare August 23, 2024 20:09
@@ -18,12 +17,28 @@ const modifyWidget = (widget) => {
return modifiedWidget;
};

const wrapWidget = ({ component, idx }) => (
<div className="bg-warning" data-testid={`wrapper${idx + 1}`} key={idx}>
Copy link
Member Author

Choose a reason for hiding this comment

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

[inform/context] Passing the key here does not resolve the React console warning; The key needs to be applied to the parent wrapWidget function as opposed to a node within wrapWidget, given its acting as a component (e.g., wrapWidget is the display name of the rendered component).

import PluginSlotWithInsert from './pluginSlots/PluginSlotWithInsert';
import PluginSlotWithModifyWrapHide from './pluginSlots/PluginSlotWithModifyWrapHide';
import PluginSlotWithModularPlugins from './pluginSlots/PluginSlotWithModularPlugins';
import PluginSlotWithoutDefault from './pluginSlots/PluginSlotWithoutDefault';

const pluginExamples = [
Copy link
Member Author

Choose a reason for hiding this comment

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

[inform/context] Refactored ExamplePage to iterate through pluginExamples to ensure the generated Table of Content links (below) are created in the same order as the plugin examples themselves.

Comment on lines +58 to +64
<ul>
{pluginExamples.map(({ id, label }) => (
<li key={id}>
<a href={`#${id}`}>{label}</a>
</li>
))}
</ul>
Copy link
Member Author

Choose a reason for hiding this comment

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

[inform/context] Includes a small list of skip links to navigate to specific example(s), without necessarily needing to scroll to find a specific example.

@@ -16,9 +16,10 @@
"lint": "fedx-scripts eslint --ext .js --ext .jsx .",
"lint:fix": "fedx-scripts eslint --fix --ext .js --ext .jsx .",
"snapshot": "fedx-scripts jest --updateSnapshot",
"start": "./node_modules/.bin/fedx-scripts babel src --watch --out-dir dist --source-maps --ignore **/*.test.jsx,**/*.test.js,**/setupTest.js --copy-files",
"start": "fedx-scripts babel src --watch --out-dir dist --source-maps --ignore **/*.test.jsx,**/*.test.js,**/setupTest.js",
Copy link
Member Author

Choose a reason for hiding this comment

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

  1. ./node_modules/.bin/ isn't needed to call fedx-scripts (per other NPM scripts above).
  2. --copy-files seems to copy test files into dist, even though they are ignored through --ignore. When running tests, it runs tests against the dist and src directories, instead of just src. Without --copy-files, npm run test will only work against src as intended.

"start:example": "npm --prefix example start & npm --prefix example-plugin-app start",
"test": "fedx-scripts jest --coverage --passWithNoTests"
"test": "fedx-scripts jest --coverage --passWithNoTests",
"test:watch": "npm run test -- --watch"
Copy link
Member Author

Choose a reason for hiding this comment

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

[inform/context] Exposes a "test:watch" command; same behavior as npm run test, but uses a watcher to re-run tests on file saves.

@adamstankiewicz adamstankiewicz force-pushed the ags/modify-default-contents-props branch 3 times, most recently from 5cb8851 to e1a762b Compare August 27, 2024 21:19
@adamstankiewicz adamstankiewicz changed the title feat: ensure default_contents widgets support merging props with PluginOperations.Modify feat: support merging props with PluginOperations.Modify Aug 27, 2024
@adamstankiewicz adamstankiewicz changed the title feat: support merging props with PluginOperations.Modify feat: support merging props with PluginOperations.Modify Aug 27, 2024
@adamstankiewicz adamstankiewicz force-pushed the ags/modify-default-contents-props branch 5 times, most recently from 6b5dde7 to 208a3a4 Compare August 28, 2024 00:22
@adamstankiewicz adamstankiewicz changed the title feat: support merging props with PluginOperations.Modify feat: support merging base component props, custom props, and pluginProps via slotOptions.mergeProps Aug 28, 2024
@adamstankiewicz adamstankiewicz force-pushed the ags/modify-default-contents-props branch 3 times, most recently from 1931be1 to 1886404 Compare August 28, 2024 00:54
Copy link
Contributor

@brian-smith-tcril brian-smith-tcril left a comment

Choose a reason for hiding this comment

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

Overall this is looking great! Awesome cleanup and the new feature works beautifully (as I've found out by using it in openedx/frontend-component-header#528)

I left a couple small comments about naming, and a couple questions about default slotOptions. From what I can tell existing PluginSlots used without setting slotOptions should still be fine and there are just a couple places where comments aren't making that clear, but if I'm mistaken about that then I'd like to discuss what can be done to make sure that is the case and this can land as a non-breaking change!

example/env.config.jsx Outdated Show resolved Hide resolved
example/env.config.jsx Outdated Show resolved Hide resolved
Copy link
Contributor

@brian-smith-tcril brian-smith-tcril left a comment

Choose a reason for hiding this comment

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

Super exciting to see this all come together!

:shipit:

Copy link
Member

@MaxFrank13 MaxFrank13 left a comment

Choose a reason for hiding this comment

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

Just one nit pick on a comment. Feel free to disregard if you think it's unnecessary.

Thanks for adding this feature as well as cleaning up the areas around it! 😄

@davidjoy
Copy link

davidjoy commented Sep 5, 2024

Oof, I'm going to have to figure out how to merge this into frontend-base, where I've been Typescript-ifying the frontend-plugin-framework code. 😬

@brian-smith-tcril brian-smith-tcril merged commit f34f4df into openedx:master Sep 6, 2024
7 checks passed
@openedx-semantic-release-bot

🎉 This PR is included in version 1.3.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants