-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
migrate saved objects management edition view to react/typescript/eui #59490
migrate saved objects management edition view to react/typescript/eui #59490
Conversation
Pinging @elastic/kibana-platform (Team:Platform) |
$scope.$$postDigest(() => { | ||
const node = document.getElementById(REACT_OBJECTS_VIEW_DOM_ELEMENT_ID); | ||
if (!node) { | ||
return; | ||
} | ||
|
||
render( | ||
<I18nContext> |
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.
Not sure this $$postDigest
approach is the best, or even useful, but I copied the way it's already done in src/legacy/core_plugins/kibana/public/management/sections/objects/_objects.js
, and this angular->react bridge is meant to be temporary anyway.
uiRoutes.when('/management/kibana/objects/:service/:id', { | ||
template: objectViewHTML, | ||
k7Breadcrumbs: getViewBreadcrumbs, | ||
requireUICapability: 'management.kibana.objects', | ||
}); | ||
|
||
function createReactView($scope, $routeParams) { | ||
const { service: serviceName, id: objectId, notFound } = $routeParams; |
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.
TIL: src/legacy/ui/public/url/redirect_when_missing.js
for the notFound
undeclared route param.
if (confirmed) { | ||
await savedObjectsClient.delete(type, id); | ||
notifications.toasts.addSuccess(`Deleted '${object!.attributes.title}' ${type} object`); | ||
window.location.hash = '/management/kibana/objects'; |
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.
So, I did not like doing that, however
- I don't want any angular services here, so
$location
orkbnUrl
(which was used before) is not an option - We have no core APIs to do that
- The
management
kibana app is still using angular hash-based routing, meaning that even if core was exposing an API to change to url, this wouldn't work (we need to redirect to{basePath}/app/kibana#/management/kibana/objects
)
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.
Have you looked at using react-router-dom
to do the redirect? I think it will provide the right interface so that changes to the url structure won't break this.
edit - I think this is fine as an intermediate step but once this becomes a new platform management app we'll want to change this.
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.
if ((service as any).Class) { | ||
addFieldsFromClass((service as any).Class, fields); | ||
} |
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.
The js code was accessing the SavedObjectLoader.Class
property, but it's declared as private
in the TS definition.
const focusAndClickButton = async (buttonSubject: string) => { | ||
const button = await testSubjects.find(buttonSubject); | ||
await button.scrollIntoViewIfNecessary(); | ||
await delay(10); | ||
await button.focus(); | ||
await delay(10); | ||
await button.click(); | ||
}; |
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 don't know the exact cause, but only click
ing on the buttons was very flaky (it seems the texteditor are catching the focus / blocking the click during the driver auto-scrolling to the button). I had to use that to remove the flakyness...
For consistency, please use init caps for the field names: Name Also, use this capitalization for the button name: Save search object |
@elastic/kibana-design As said on slack
|
These are the exact field name from the saved object structure, not labels. Capitalizing that might not be a good idea, as copy/pasting the field name (to perform an ES query for example) would result in copying something wrong. WDYT? |
@pgayvallet Ah, I see. My preference would be to use capitalization for the labels because to me it makes the UI look more polished. We do use capitalization for the labels when editing a field in an index pattern. However, as this is for advanced users "with intimate knowledge of the code" and they might want to copy the field name for use in their queries, it's ok to leave as is. |
…gement-object-view-to-react
@elastic/kibana-design Do you want to take a pass at this? Not sure if it's important enough since it is a "advanced" screen, but thought I'd flag it just in case. |
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 made a design PR for you mainly just cleanup: pgayvallet#1
src/legacy/core_plugins/kibana/public/management/sections/objects/saved_object_view.tsx
Show resolved
Hide resolved
…object Wrapping whole view in page content panel and removing legacy classes
retest |
…gement-object-view-to-react
retest |
…gement-object-view-to-react
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's the testing plan for these changes? I see you added e2e tests which is great. Are we going to hold off on unit tests until later?
$location.path('/management/kibana/objects').search({ | ||
_a: rison.encode({ | ||
tab: serviceObj.title, | ||
}), | ||
}); |
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.
Is this URL state unneeded now? I don't see it in the new implementation
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.
From my understanding, it is. I think this was a forgotten thing from an older version, as the rison formatted search doesn't seems to be used (functionally or technically) in the SO management table view.
If we want to add UT, we should probably do it in this PR. What kind of unit test would you like to see added here? snapshot testing of the introduced lower-level react components ? |
@cchaos I think the asked changes are done. PTAL |
…gement-object-view-to-react
…gement-object-view-to-react
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 are still a few unnecessary legacy classes that need to be removed in favor of EUI components.
/> | ||
))} | ||
</div> | ||
<EuiFormRow fullWidth={true}> |
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.
You don't need a EuiFormRow
if you're not providing an input as a direct descendent or a label
. It will just cause extraneous wrappers.
const { name } = this.props; | ||
|
||
return ( | ||
<div className="kuiFormSection"> |
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 you remove these legacy kui
classes? Instead, you can just use the <EuiFormRow label="">
wrapper around the field.
defaultMessage="Proceed with caution!" | ||
/> | ||
} | ||
iconType="bolt" |
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.
iconType="bolt" | |
iconType="alert" |
@cchaos the remaning |
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!
@joshdover added UT for new components. Only skipped the high-level form component as it's more efficiently covered by the existing FTs. |
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. Left some suggestions for some improvements, but nothing blocking this for merging. I'll leave it up to you whether these optional suggestions are worth it on this page.
}); | ||
|
||
it('renders a EuiFieldText as fallback', () => { | ||
const mounted = mountField({ ...defaultProps, type: 'unkown' as any }); |
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.
super nit, doesn't really matter (could also make more obvious that it's supposed to be an unexpected value by making it blah
or something)
const mounted = mountField({ ...defaultProps, type: 'unkown' as any }); | |
const mounted = mountField({ ...defaultProps, type: 'unknown' as any }); |
!!currentValue ? ( | ||
<FormattedMessage id="kbn.management.objects.field.onLabel" defaultMessage="On" /> | ||
) : ( | ||
<FormattedMessage id="kbn.management.objects.field.offLabel" defaultMessage="Off" /> | ||
) |
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.
Untested
* @param {array} parents The parent keys to the field | ||
* @returns {array} | ||
*/ | ||
const recursiveCreateFields = (key: string, value: any, parents: string[] = []): ObjectField[] => { |
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 this have a max depth safety mechanism to avoid recursing deeply nested objects if one were to exist?
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.
Doesn't cost much to add. Also extracted the field generation logic and added tests
<Intro /> | ||
</> | ||
)} | ||
{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.
Should we use Suspense or show a spinner while this loads?
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.
Will keep this one as a later improvement
}, | ||
})} | ||
onClick={this.onSubmit} | ||
disabled={!isValid} |
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.
optional: Should this also be disabled while the save operation is running to avoid double-saves?
💛 Build succeeded, but was flaky
Test FailuresKibana Pipeline / kibana-xpack-agent / X-Pack OpenID Connect API Integration Tests (Implicit Flow).x-pack/test/oidc_api_integration/apis/implicit_flow/oidc_auth·ts.apis OpenID Connect Implicit Flow authentication finishing handshake should succeed if both the OpenID Connect response and the cookie are providedStandard Out
Stack Trace
History
To update your PR or re-run it, just comment with: |
…elastic#59490) * migrate so management edition view to react * fix bundle name + add forgotten data-test-subj * add FTR tests for edition page * EUIfy react components * wrap form with EuiPanel + caps btns labels * Wrapping whole view in page content panel and removing legacy classes * improve delete confirmation modal * update translations * improve delete popin * add unit test on view components * remove kui classes & address comments * extract createFieldList and add tests * disable form submit during submition Co-authored-by: cchaos <caroline.horn@elastic.co>
…pt/eui (#59490) (#60621) * migrate saved objects management edition view to react/typescript/eui (#59490) * migrate so management edition view to react * fix bundle name + add forgotten data-test-subj * add FTR tests for edition page * EUIfy react components * wrap form with EuiPanel + caps btns labels * Wrapping whole view in page content panel and removing legacy classes * improve delete confirmation modal * update translations * improve delete popin * add unit test on view components * remove kui classes & address comments * extract createFieldList and add tests * disable form submit during submition Co-authored-by: cchaos <caroline.horn@elastic.co> * update dataset and fix test description Co-authored-by: cchaos <caroline.horn@elastic.co>
* master: [ML] Use a new ML endpoint to estimate a model memory (elastic#60376) [Logs UI] Correctly update the expanded log rate table rows (elastic#60306) fixes drag and drop flakiness (elastic#60625) Removing isEmptyState from embeddable input (elastic#60511) [Cross Cluster Replication] NP Shim (elastic#60121) Clear changes when canceling an edit to an alert (elastic#60518) Update workflow syntax (elastic#60626) Updating project assigner workflows to v2.0.0 of the action and back to default tokens (elastic#60577) migrate saved objects management edition view to react/typescript/eui (elastic#59490)
Summary
Preliminary work for #50308, this converts the saved objects edition/view page to react, typescript, EUI, and new platform APIs.
Extracted from my #59110 sandbox
before
after
Checklist
Delete any items that are not applicable to this PR.