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

[index patterns] Index pattern creation modal API #99876

Closed
mattkime opened this issue May 12, 2021 · 13 comments
Closed

[index patterns] Index pattern creation modal API #99876

mattkime opened this issue May 12, 2021 · 13 comments
Labels
impact:high Addressing this issue will have a high level of impact on the quality/strength of our product. loe:small Small Level of Effort

Comments

@mattkime
Copy link
Contributor

mattkime commented May 12, 2021

Some new text

Parent issue for index pattern creation modal - [https://github.com//issues/84725|https://github.com//issues/84725]

A new IndexPatternEditor plugin will be created which will expose an interface for an index pattern creation flyout. It will be loaded asynchronously to be mindful of bundle size. It will initially be used by Index Pattern Management.

Note - this API is heavily based on the IndexPatternFieldEditor API - [https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_field_editor|https://github.com/elastic/kibana/tree/master/src/plugins/index_pattern_field_editor].

const MyComponent = () => \{
// Access the plugin through context
const \{ indexPatternEditor } = useAppPlugins();

// Ref of the handler to close the editor
const closeIndexPatternEditor = useRef(() => \{});

const saveIndexPattern = (indexPattern: IndexPattern) => \{
// Respond to new index pattern
};

const openIndexPatternEditor = async() => \{
// Lazy load the editor
const \{ openEditor } = await indexPatternEditor.loadEditor();

closeIndexPatternEditor.current = openEditor(\{
defaults?: \{
title?: string;
timestampField?: string;
isRollup?: boolean;
},
config?: \{
requireTimestampField?: boolean;
},
onSave: saveIndexPattern
});
};

useEffect(() => \{
return () => \{
// Remove the editor when the component unmounts
closeIndexPatternEditor?.current();
};
}, \[]);

return (
<button onClick=\{openIndexPatternEditor}>Add index pattern</button>
)
}

A convenience function will also be provided for checking permissions -

const canCreateIndexPattern = indexPatternEditor.userPermissions.editIndexPattern();
@botelastic botelastic bot added the needs-team Issues missing a team label label May 12, 2021
@elasticmachine
Copy link
Contributor

Pinging @elastic/kibana-app-services (Team:AppServices)

@botelastic botelastic bot removed the needs-team Issues missing a team label label May 12, 2021
@mattkime
Copy link
Contributor Author

In particular, I'd like feedback from @weltenwort @flash1293 @timroes

@streamich
Copy link
Contributor

streamich commented May 12, 2021

I believe we are doing flyouts not in the best way in many places in Kibana. In particular, it would be great to open flyouts in declerative way, same as it is provided by EUI library. For example:

const MyComponent = () => {
 const { indexPatternEditor } = useAppPlugins();
 const [open, setOpen] = React.useState(false);
 
 return (
   <>
     <button onClick={() => setOpen(true)}>Add index pattern</button>
     {open && <indexPatternEditor.Flyout onSave={() => {}} />}
   </>
 )
}

It would be great to implement the <indexPatternEditor.Flyout> component as the basis. And then if some app still needs to open the flyout in an imperative way, construction on top of it can be created by index patterns or the app itself to open the flyout in an imperative way. Maybe it is even better to leave that up to the app, to encourage good patterns.

@flash1293
Copy link
Contributor

I think an imperative API should be provided because it's also usable outside of React which can sometimes become necessary (e.g. inside of an action handler). While it's possible to use the react api in this situation as well, it's cumbersome and IMHO we shouldn't push this to the consumer. If we feel strongly about the "manual" flyout reference management (I agree it can lead to unclosed flyouts leaking out of the app which is also not great), I would vote for providing two APIs (imperative and declarative). This is also consistent what we are doing for the field deletion modal:

DeleteRuntimeFieldProvider: getDeleteFieldProvider(openDeleteModal),

Besides that I'm pretty happy with this API. Didn't discuss this with design or anything, but we could add a pre-set for the index pattern name to the context:

openEditor({
  onSave,
  initalPatternString,
});

This could be used for a user flow like this:

  • User is opening the index pattern chooser in Lens and starts searching for a pattern
  • Notices there's no index pattern for this name yet
  • There's an option in the chooser "create this index pattern" (which will open the editor with the string the user typed so far)

@streamich
Copy link
Contributor

streamich commented May 12, 2021

If you go for imperative approach maybe worth creating a helper, say useIndexPatternFlyout, so every user of the flyout does not need to write the boilerplate code:

const MyComponent = () => {
 const { indexPatternEditor } = useAppPlugins();
 const { open } = useIndexPatternFlyout(indexPatternEditor, {
   onSave: () => {},
 });
 
 return (
   <button onClick={open}>Add index pattern</button>
 )
}

@mattkime
Copy link
Contributor Author

As best I can tell, we have specific use cases that need the imperative API. Do we have specific use cases that need the declarative api? Otherwise I'm tempted to stick with imperative until its unsuitable for a given situation. What do you think @streamich @flash1293 ?

@mattkime
Copy link
Contributor Author

Besides that I'm pretty happy with this API. Didn't discuss this with design or anything, but we could add a pre-set for the index pattern name to the context:

@flash1293

Yes, this could be added easily. We can add it when its needed.

@weltenwort
Copy link
Member

Thanks for working on this, @mattkime! The ability to prepopulate an index pattern name would be pretty useful to provide guidance to the user. Similarly, it would be useful to require the timestamp field because many observability use-cases depend on such a field. Would that be possible?

@mattkime
Copy link
Contributor Author

@weltenwort I updated the code example with some type interfaces. Let me know what you think.

@weltenwort
Copy link
Member

That looks like it should cover the requirements I can anticipate. 👍

💭 On a side-note, I wonder if you perceive the requireTimestampField as being too specific? Alternatively the consumer could pass a generic validation function? Just thinking loudly. 🤷

@flash1293
Copy link
Contributor

Alternatively the consumer could pass a generic validation function

My 2 cents - a generic validation function is more flexible, but the UX is definitely worse because the creation dialog can't prevent the problem from happening (e.g. by simply omitting "No default time field" option in the dropdown) nor highlight the problematic field in the form.

@weltenwort
Copy link
Member

[...] the UX is definitely worse because the creation dialog can't prevent the problem from happening (e.g. by simply omitting "No default time field" option in the dropdown) nor highlight the problematic field in the form.

Very good point, thank you!

@exalate-issue-sync exalate-issue-sync bot added impact:low Addressing this issue will have a low level of impact on the quality/strength of our product. loe:small Small Level of Effort impact:high Addressing this issue will have a high level of impact on the quality/strength of our product. and removed impact:low Addressing this issue will have a low level of impact on the quality/strength of our product. labels Jun 21, 2021
@mattkime
Copy link
Contributor Author

implemented by #84725

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
impact:high Addressing this issue will have a high level of impact on the quality/strength of our product. loe:small Small Level of Effort
Projects
None yet
Development

No branches or pull requests

5 participants