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

[App Search] Updated Search UI to new URL #101320

Merged
merged 5 commits into from
Jun 8, 2021

Conversation

JasonStoltz
Copy link
Member

Summary

This PR does 2 things:

  • Changes Search UI to POST to the new authentication-not-required search experience page in ent-search, including a valid public search key.
  • Changes Search UI to show an error message if no valid public search key is available.

When testing:

  • Be sure to run this against the latest master version of ent-search, in an incognito window, so you are signed out of everything. Ensure that you are not prompted to log into ent-search when clicking on "Generate search experience".
  • Verify that there is no way to copy/paste a url for the generated search experience in a way that would expose a user's search key unintentionally.

latest

screencapture-localhost-5601-app-enterprise-search-app-search-engines-national-parks-demo-search-ui-2021-06-03-15_01_02

Checklist

Delete any items that are not applicable to this PR.

For maintainers

@JasonStoltz JasonStoltz requested a review from a team June 3, 2021 19:08
@JasonStoltz JasonStoltz added v7.14.0 auto-backport Deprecated - use backport:version if exact versions are needed release_note:skip Skip the PR/issue when compiling release notes labels Jun 3, 2021
@JasonStoltz
Copy link
Member Author

@elasticmachine merge upstream

@@ -87,6 +90,14 @@ export const EngineLogic = kea<MakeLogicType<EngineValues, EngineActions>>({
() => [selectors.engine],
(engine) => engine?.unconfirmedFields?.length > 0,
],
searchKey: [
Copy link
Member Author

Choose a reason for hiding this comment

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

We need to POST the search key to the new search experience URL from the Search UI form. Since all keys that are valid for a particular engine are already available on engine.apiTokens from state, I added a selector to easily access the first available search token.

Since tokens that do not have access to the current engine are not returned in this object, I do not have to check their access level, as we already know it has access to the current engine.

Copy link
Member

Choose a reason for hiding this comment

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

I really like this added logic/selector. Feels elegant and makes sense.

const { engineName } = EngineLogic.values;
const { searchKey, engineName } = EngineLogic.values;

if (!searchKey) {
Copy link
Member Author

Choose a reason for hiding this comment

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

We make a call to fetch all the data that the Search UI form needs below. As part of this API call, the API will actualy return an "errors" field that will return the message "It looks like you don't have any Public Search Keys with access to the 'engine1' engine. Please visit the Credentials page to set one up." In ent-search, we simply printed the error from that field to the screen.

In this UI, I opted to explicitly check for that condition and add that error message to an i18n string, so that it can be translated.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if I agree with this approach. It's seems strange to add this to listener that largely does an http call. I think I would have kept this as a static part of the SearchUiForm with useValues(EngineLogic)

Copy link
Member Author

Choose a reason for hiding this comment

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

True. I think I chose to put it in this logic file because I wanted to use our flash messaging system, which is stateful and requires a call to something like setErrorMessage to use.

I could have done that in like a useEffect in SearchUiForm but that seems clunkier. I like it here because we can short circuit the API call and all flash messages are generated from the logic file.

It could also be a stateless check where we just do like !searchKey && <EuiCallout..., but then that conflicts with the flash messaging system we use. Like it gets hairy having them both exist on the page together.

Copy link
Member

@cee-chen cee-chen Jun 8, 2021

Choose a reason for hiding this comment

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

Ah, I think I see Byron's point - it does seem odd to skip loading fieldData entirely just because a searchKey is missing. I don't think this is overly clunky to put in a useEffect personally - would you be cool with making that change?

const { searchKey, engineName } = useValues(EngineLogic);

useEffect(() => {
  if (!searchKey) setErrorMessage(NO_SEARCH_KEY_ERROR(engineName));
}, [searchKey]);

3 or so lines doesn't feel so bad to me, and I do think it makes more sense (conceptually) in the view than this specific listener.

Definitely ++ to keeping this using our flash messages + i18n though!

@@ -33,7 +33,7 @@ describe('generatePreviewUrl', () => {
empty2: [''], // Empty fields should be stripped
})
).toEqual(
'http://localhost:3002/as/engines/national-parks-demo/reference_application/preview?facets[]=baz&facets[]=qux&sortFields[]=quux&sortFields[]=quuz&titleField=foo&urlField=bar'
'http://localhost:3002/as/engines/national-parks-demo/search_experience/preview?facets[]=baz&facets[]=qux&sortFields[]=quux&sortFields[]=quuz&titleField=foo&urlField=bar'
Copy link
Member Author

Choose a reason for hiding this comment

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

This is a new route that was set up specifically for this form, which accepts a search token in order to render the search experience preview, rather than authenticating like the former route.

@@ -119,8 +127,8 @@ export const SearchUIForm: React.FC = () => {
/>
</EuiFormRow>
<EuiButton
Copy link
Member Author

Choose a reason for hiding this comment

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

Rather than being a link as before, this is not a form with a submit button so that we can POST to the new route.

Copy link
Contributor

@byronhulcher byronhulcher left a comment

Choose a reason for hiding this comment

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

Code looks good, I had two question-that-is-really-more-of-a-comments. I'm going to QA now

searchKey: [
() => [selectors.engine],
(engine: Partial<EngineDetails>) => {
const isSearchKey = (token: ApiToken) => token.type === ApiTokenTypes.Search;
Copy link
Contributor

Choose a reason for hiding this comment

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

You could pull this function out instead of declaring it in here every time (idk if its worth writing a test for it)

Copy link
Member

Choose a reason for hiding this comment

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

Going completely the opposite direction, I would have just left it as an inline fn in .find() :trollface: But it doesn't bother me either way personally

Copy link
Member Author

Choose a reason for hiding this comment

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

Haha, quite the array of opinions! I just pulled this out for readability. It was long in the tooth inline in the find.

const { engineName } = EngineLogic.values;
const { searchKey, engineName } = EngineLogic.values;

if (!searchKey) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if I agree with this approach. It's seems strange to add this to listener that largely does an http call. I think I would have kept this as a static part of the SearchUiForm with useValues(EngineLogic)

@JasonStoltz
Copy link
Member Author

@elasticmachine merge upstream

@JasonStoltz
Copy link
Member Author

@elasticmachine merge upstream

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
enterpriseSearch 2.1MB 2.1MB +3.6KB

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@JasonStoltz
Copy link
Member Author

@byronhulcher Are you looking for any changes in particular before approving?

titleField: 'bar',
facets: ['baz'],
sortFields: ['qux'],
it('should disable everything while data is loading', () => {
Copy link
Member

Choose a reason for hiding this comment

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

Thanks for adding this piece of UX + test - love it! 🎉

@cee-chen
Copy link
Member

cee-chen commented Jun 8, 2021

This LGTM - I think I'm +1 to Byron on #101320 (comment), and moving the error display to a view useEffect is my only real change request. If you feel strongly otherwise though lmk

@JasonStoltz
Copy link
Member Author

Ok. I'll make the change, though TBH, I'm really medium on it and don't really feel like expending the cycles.

@JasonStoltz
Copy link
Member Author

Just keep an eye on it so we can get this approved and merged please.

@cee-chen
Copy link
Member

cee-chen commented Jun 8, 2021

@JasonStoltz if you're feeling medium on it but wouldn't mind it happening, I'd be cool pushing up the change in your stead to save you some effort. Totally up to you though!

@JasonStoltz
Copy link
Member Author

Actually, I do feel strongly about this. I want the fields to be disabled if there is no search key, there's no way you can generate a UI without one. So it's pointless to fetch the fields. I am also relying on the dataLoading field to disable all of the fields. So if there's any kind of error here... whether it's an error on the server, or the error is is that there is no search key, it all fits into the same flow right now. It also has the advantage of being written and tested. I don't think there is a compelling enough reason for any of us to spend cycles changing this.

@cee-chen
Copy link
Member

cee-chen commented Jun 8, 2021

Ahhh that's a solid point about disabling fields that I missed! I think that's a good enough argument to not block this PR and I'm fine with merging this in as-is 👍

@JasonStoltz
Copy link
Member Author

🙇‍♂️ 🙏

@JasonStoltz JasonStoltz merged commit a9e64ab into elastic:master Jun 8, 2021
@JasonStoltz JasonStoltz deleted the new-search-experience-url branch June 8, 2021 16:42
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Jun 8, 2021
@kibanamachine
Copy link
Contributor

💚 Backport successful

Status Branch Result
7.x

This backport PR will be merged automatically after passing CI.

kibanamachine added a commit that referenced this pull request Jun 8, 2021
Co-authored-by: Jason Stoltzfus <jastoltz24@gmail.com>
gmmorris added a commit to gmmorris/kibana that referenced this pull request Jun 9, 2021
* master: (54 commits)
  Implement "select all" rules feature (elastic#100554)
  [ML] Remove script fields from the Anomaly detection alerting rule executor  (elastic#101607)
  [Security solutions][Endpoint] Update event filtering texts (elastic#101563)
  [Enterprise Search] Mocks/tests tech debt - avoid hungry mocking (elastic#101107)
  [FTR] Updates esArchive paths
  [FTR] Updates esArchive paths
  [Security Solution][Detection Engine] Adds runtime field tests (elastic#101664)
  Added APM PHP agent to the list of agent names (elastic#101062)
  [CI] Restore old version_info behavior when .git directory is present (elastic#101642)
  [Fleet] Add fleet server telemetry (elastic#101400)
  [APM] Syncs agent config settings to APM Fleet policies (elastic#100744)
  [esArchiver] drop support for --dir, use repo-relative paths instead (elastic#101345)
  Revert "[xpack/test] restore incremental: false in ts project"
  [Security Solution] Remove Host Isolation feature flag (elastic#101655)
  [xpack/test] restore incremental: false in ts project
  [DOCS] Adds link to video landing page (elastic#101413)
  [ML] Move Index Data Visualizer into separate plugin (Part 1) (elastic#100922)
  Improve security plugin return types (elastic#101492)
  [ts] migrate `x-pack/test` to composite ts project (elastic#101441)
  [App Search] Updated Search UI to new URL (elastic#101320)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-backport Deprecated - use backport:version if exact versions are needed release_note:skip Skip the PR/issue when compiling release notes v7.14.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants