-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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: Dynamically imported viz plugins #10288
Conversation
d5ebb30
to
42f97e7
Compare
@suddjian I'm happy to help out here |
Thanks for the offer @amitNielsen! I won't have a chance to get back on this until next week, but if we can address the CI errors I think it should be just about ready for review. Just needs one last pass to make sure that every part of the app knows how to wait for the async plugins. If you make some fixes I can merge your branch 🙂 |
@suddjian I tried solving the issue in the explore page where controlsPanel section / row is not re-rendering the exiting parameters of the query like group by and metrics. Can we maybe do some knowledge transfer on how what exactly should be done there and maybe do some refactoring in those areas you can also have a look at my PR that solves few of the issues already |
Codecov Report
@@ Coverage Diff @@
## master #10288 +/- ##
==========================================
- Coverage 64.76% 58.59% -6.17%
==========================================
Files 789 762 -27
Lines 37091 36142 -949
Branches 3555 3315 -240
==========================================
- Hits 24021 21177 -2844
- Misses 12963 14774 +1811
- Partials 107 191 +84
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
@suddjian I've fix the pre-commit issues for re configuring 3rd party and then re running sort here is my branch with the fix : https://github.com/amitnielsen/incubator-superset/tree/dynamic-plugin-import ================ update ================= |
@suddjian I suggest we also write an E2E cypress test for the explore page and dashboard page that loads a dynamic plugin stable currently with the https://github.com/apache-superset/dynamic-import-demo-plugin we should also stabalize the demo plugin to be aligned with the latest yeo generated plugin, which is what all community plugins are starting from |
A cypress test sounds like a good idea to me. I have the example plugin working locally, maybe I can help there? I think dynamic plugins in the long run will have a different set of requirements than static plugins. I'm thinking about adding some kind of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the awesome work! I think exposing @superset-ui
packages as globals is the right way to go. In the future, there will only be one package so it should become more or less more manageable. For security reasons, we want to limit what methods are exposed in the superset-ui
package available to plugins, but that's another story.
'@superset-ui/style': import('@superset-ui/style'), | ||
'@superset-ui/translation': import('@superset-ui/translation'), | ||
'@superset-ui/validator': import('@superset-ui/validator'), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should defineSharedModules
be called outside of fetchAll
or in a separate setup
function? It would also be nice to make DynamicProviderProvider
load only specific plugins on demand instead of all together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to do loading on demand, but the way I got the example plugin's webpack to work is it references global variables on the window
. I intend to define a superset-plugin.json
manifest file for dynamic plugins in the future, which would be a good place to put dependency info. For now I'd like to keep this minimal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This design is also not ideal for third-party plugins that may want to add libraries for other plugins to depend on. Definitely should be improved.
superset-frontend/src/components/DynamicPlugins/DynamicPluginProvider.tsx
Outdated
Show resolved
Hide resolved
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. For admin, please label this issue |
Really bot, no! this would be super useful |
@@ -167,53 +170,59 @@ export function getControlState(controlKey, vizType, state, value) { | |||
); | |||
} | |||
|
|||
const getMemoizedSectionsToRender = memoizeOne( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
} | ||
}); | ||
Object.keys(controlsState) | ||
.concat(Object.keys(inputFormData)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dynamically imported plugins don't have any controls state available until after the plugin has loaded. This change makes it so that we use the fields from the chart's form data instead of only using the controls.
@@ -21,26 +21,29 @@ import memoize from 'lodash/memoize'; | |||
import { getChartControlPanelRegistry } from '@superset-ui/core'; | |||
import { controls } from '../explore/controls'; | |||
|
|||
const getControlsForVizType = memoize(vizType => { | |||
const memoizedControls = memoize((vizType, controlPanel) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
had to change memoization again here
@@ -15,7 +15,7 @@ | |||
# specific language governing permissions and limitations | |||
# under the License. | |||
# pylint: disable=too-few-public-methods,invalid-name | |||
from dataclasses import dataclass | |||
from dataclasses import dataclass # pylint: disable=wrong-import-order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't know why but every linter decided to lose its shit here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What version of Python are you on? I'm guessing the ordering fails due to dataclasses being built-in on 3.7 but an addon in previous versions. But no need to fix here, I can clean this up later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm on 3.7
@@ -122,138 +127,110 @@ const Styles = styled.div` | |||
} | |||
`; | |||
|
|||
class ExploreViewContainer extends React.Component { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Converted this to a function component out of frustration with trying to change behavior. Didn't have the stamina to go all the way and convert it to typescript.
"DatabaseAsync", | ||
"DatabaseView", | ||
"DruidClusterModelView", | ||
"DynamicPlugin", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this makes it so that only admins can write to dynamic plugins endpoints
if (title) { | ||
document.title = title; | ||
useEffect(() => { | ||
if (wasDynamicPluginLoading && !isDynamicPluginLoading) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this effect is the only functionality in this file that's actually new
521dccf
to
c0e0847
Compare
c0e0847
to
7e637ab
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Super excited to see this within superset!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
// jest.spyOn(ReactAll, 'useContext').mockImplementation(() => { | ||
// return { | ||
// store, | ||
// subscription: new Subscription(store), | ||
// }; | ||
// }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I prefer /* */
for multi-line comments
@@ -15,7 +15,7 @@ | |||
# specific language governing permissions and limitations | |||
# under the License. | |||
# pylint: disable=too-few-public-methods,invalid-name | |||
from dataclasses import dataclass | |||
from dataclasses import dataclass # pylint: disable=wrong-import-order |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What version of Python are you on? I'm guessing the ordering fails due to dataclasses being built-in on 3.7 but an addon in previous versions. But no need to fix here, I can clean this up later.
@@ -107,11 +113,12 @@ describe('chart card view', () => { | |||
cy.get('[data-test="modal-cancel-button"]').click(); | |||
}); | |||
|
|||
it('should edit correctly', () => { | |||
// flaky | |||
xit('should edit correctly', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did we nix so many tests? Were they causing problems in other PRs, too? If yes, I think it would be better if they were turned off in a separate PR so we can keep better track of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these tests failed and passed at various times, as well as on other PRs. We did a little investigation but haven't found the cause of flakiness yet.
Migration is failing on MySQL with:
|
@betodealmeida That's very strange... Any idea why? It passed CI. |
@betodealmeida what version of MySQL are you seeing this on? |
Indicates that it could be related to the charset or a non InnoDB engine. Maybe? |
SUMMARY
Adds functionality to import plugins dynamically. A corresponding plugin can be found here: https://github.com/apache-superset/dynamic-import-demo-plugin
Goals:
How it works:
serve
command to help with local development.Various hacks were necessary to build a PoC, but I believe they can all be solved with some kind of arcane webpack incantation:
I'd greatly appreciate any help addressing these issues, or any feedback on the code that anyone has!
TEST PLAN
ADDITIONAL INFORMATION