-
Notifications
You must be signed in to change notification settings - Fork 1
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
UI-7229 - Option to remove widgets of a given type in the CLI #21
UI-7229 - Option to remove widgets of a given type in the CLI #21
Conversation
@@ -2128,6 +2249,18 @@ Object { | |||
], | |||
}, | |||
}, | |||
"organization_permissions": Object { |
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.
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.
A few suggestions. Also, have you been able to try it for real and make sure that the migrated dashboards work as expected? I am thinking in particular about edge cases where a page contains a single widget, which is removed. Or even worse: a dashboard contains a single page, which contains a single widget, which is removed.
Asking to know whether I should invest the time to do it on my side.
src/migrateDashboard.test.ts
Outdated
|
||
const { content, layout } = dashboard.pages["p-0"]; | ||
const widgetPluginKeys = _map(content, ({ widgetKey }) => widgetKey); | ||
expect( |
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.
It would be nice to add another assertion here with the legacy dashboard state:
expect(
_intersection(widgetKeysInLegacyDashboard, keysOfWidgetPluginsToRemove)
).toHaveLength(1);
This way, we are guaranteed that this test will remain useful, even if future devs change the content of mocks.
src/migrateDashboard.ts
Outdated
|
||
const deserializedDashboard = deserializeDashboardState(dashboard); | ||
|
||
const dashboardWithWidgetsRemoved = _reduce( |
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 try to avoid reduce
because it tends to be less legible than other methods to people who didn't write them (and the future-self of people who wrote them). I am not the only one feeling this way. See eslint-plugin-unicorn/no-array-reduce.md.
In this case, I believe we could do:
const dashboardWithWidgetsRemoved = produce(deserializedDashboard, draft => {
for (let i = 0; i < draft.pages.length; i++) {
keysOfLeavesToRemove.forEach(leafKey => {
// the call to getLayoutPath could even be internalized within removeWidget
draft.pages[i] = removeWidget(draft.pages[i], layoutPath);
});
)
})
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.
That would be ideal, but this is not the signature of removeWidget
:
removeWidget({
dashboardState,
pageKey,
leafKey,
layoutPath,
});
And since removeWidget
can modify the layout of a given page, then when calling several removeWidget
in a row, one has to get the latest dashboardState
at each iteration (rather than the initial dashboardState
before any removal).
So typically I feel this is a good use case for reduce: you want to feed the intermediate result to the next iteration step.
An alternative would be to refactor things a bit in the SDK and export a removeWidgetFromPage
function that mutates its input page, but that would mean:
- making the API surface bigger
- requiring to bump the SDK dependency to 5.0.11 in
activeui-migration
before proceeding with this dev
This does not seem very appealing to me.
Or am I missing another way to write it ?
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 am pushing an attempt. Let me know what you think.
src/migrateUIFolder.test.ts
Outdated
const widgetPluginKeys = _map(content, ({ widgetKey }) => widgetKey); | ||
expect( | ||
_intersection(widgetPluginKeys, keysOfWidgetPluginsToRemove) | ||
).toHaveLength(0); |
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 remark 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.
Don't forget this one either 🙏
I have tested that
works well with the attached input aui4 folder (GitHub does not support attaching JSONs, so you'll have to change the extension if you want to open it in an IDE and have it formatted properly)
While I agree that it would be nice to do end-to-end tests for edge cases, here I feel this is almost out of scope: the removal job is the responsability 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.
I cannot build the repo. I get 40 instances of the following error:
ERROR in ./node_modules/katex/dist/fonts/KaTeX_Typewriter-Regular.woff 1:4
Module parse failed: Unexpected character '' (1:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
@ ./node_modules/css-loader/dist/cjs.js!./node_modules/katex/dist/katex.css 62:0-83 123:74-104
@ ./node_modules/katex/dist/katex.css 2:26-79
@ ./node_modules/@activeviam/plugin-widget-text-editor/dist/esm/DangerousMarkdownPreview-0f2462ba.js 5:0-30
@ ./node_modules/@activeviam/plugin-widget-text-editor/dist/esm/index.js 19:45-93
@ ./node_modules/@activeviam/activeui-sdk/dist/esm/index.js 81:0-79 81:0-79
@ ./src/migrateDashboard.ts 8:23-58
@ ./src/index.ts 5:25-54
Can you build the repo?
src/migrateDashboard.ts
Outdated
/** | ||
* Returns the layout path to the leaf uniquely identified by `leafKey`, or `undefined` if no leaf has this key. | ||
*/ | ||
function findPathToLeaf(layout: Layout, leafKey: string): number[] | undefined { |
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.
Can this be removed in favor of getLayoutPath
from @activeviam/activeui-sdk
?
src/migrateUIFolder.test.ts
Outdated
); | ||
const { content, layout } = migratedDashboard.pages["p-0"]; | ||
const widgetPluginKeys = _map(content, ({ widgetKey }) => widgetKey); | ||
expect( |
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 seems like a simpler way of testing the same thing:
expect( | |
expect(widgetPluginKeysInLegacyDashboard).toContain("filters"); |
If you agree, same suggestion below.
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 forget this comment 🙏
src/migrateDashboard.ts
Outdated
|
||
const deserializedDashboard = deserializeDashboardState(dashboard); | ||
|
||
const dashboardWithWidgetsRemoved = _reduce( |
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 am pushing an attempt. Let me know what you think.
I get the same errors but it's only for fonts. |
Co-authored-by: Benjamin Amelot <[email protected]>
Thanks for the commit, it works 👍 |
src/migrateUIFolder.test.ts
Outdated
); | ||
const { content, layout } = migratedDashboard.pages["p-0"]; | ||
const widgetPluginKeys = _map(content, ({ widgetKey }) => widgetKey); | ||
expect( |
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 forget this comment 🙏
src/migrateUIFolder.test.ts
Outdated
const widgetPluginKeys = _map(content, ({ widgetKey }) => widgetKey); | ||
expect( | ||
_intersection(widgetPluginKeys, keysOfWidgetPluginsToRemove) | ||
).toHaveLength(0); |
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 forget this one either 🙏
Co-authored-by: Benjamin Amelot <[email protected]>
I would like to keep the abstraction of "output plugin keys do (not) contain the plugins keys to remove", rather than projecting it on "filters". |
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.
Looks good 👍
The rationale is explained in UI-7229, which comes from a client request at CIBC: NAS-3463
You can review commit by commit.