-
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
[SR] Snapshot and restore plugin boilerplate #32276
[SR] Snapshot and restore plugin boilerplate #32276
Conversation
Pinging @elastic/es-ui |
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 is so 🔥. Thanks for leading the way on this! This will make building plugins compatible with the new platform so much easier (and converting existing ones). I think the AppContext mechanism you've created for sharing injected dependencies is a terrific solution. My initial idea was a service locator, but this is much more elegant!
I think it would make sense to move the repository_list
and snapshot_list
directories into home
. This localizes these components with the page which will consume them, and the resulting tree-like folder structure will mirror the structure of the DOM and UI. This will also declutter the sections
directory as we add more pages.
x-pack/server/lib/constants.js
Outdated
@@ -7,6 +7,7 @@ | |||
export const XPACK_DEFAULT_ADMIN_EMAIL_UI_SETTING = 'xPack:defaultAdminEmail'; | |||
export const XPACK_INFO_API_DEFAULT_POLL_FREQUENCY_IN_MILLIS = 30001; // 30 seconds | |||
export const RANKED_LICENSE_TYPES = [ | |||
'oss', |
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 we consume license type constants exported from common
instead of hardcoding strings?
export const PLUGIN = { | ||
ID: 'snapshot_restore', | ||
NAME: 'Snapshot and Restore', | ||
MINIMUM_LICENSE_REQUIRED: 'basic', |
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.
Could this refer to a constant instead of using a hardcoded string?
|
||
export const PLUGIN = { | ||
ID: 'snapshot_restore', | ||
NAME: 'Snapshot and Restore', |
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 we internationalize 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.
This one was tricky since I'm trying to avoid calling i18n
outside of shim.ts
. In the end, I changed this to be a function, getI18nName(), which is called when the plugin is initialized.
Also, this is called in the legacy world rather than plugin.ts
to avoid the plugin knowing about server
, which is needed by registerLicenseChecker
.
@epixa, any thoughts on accessing i18n
, or other core/plugin modules from constant files like this case?
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
export const getAll = { |
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 always get a little concerned about creating config objects because I need to understand how they're consumed in order to understand how they "work". For example in this case I need to also read register_routes.ts
to gain that context and understand how these objects work. But if we keep these as functions then I would have enough context to understand them on their own (theoretically we could also unit test, but in this case I guess that test wouldn't be very valuable 😄). What are your thoughts on this?
export const registerGetAll = router => {
router.get('repositories', async (req: any, callWithRequest: any, responseToolkit: any) => {
const repositoriesByName = await callWithRequest('snapshot.getRepository', {
repository: '_all',
});
const repositories = Object.keys(repositoriesByName).map(name => {
return {
name,
...repositoriesByName[name],
};
});
return repositories;
});
}
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 adjusted this to something similar to your suggestion - each handler is broken out into it's own named function, and registered registerRepositoriesRoutes(). I also added additional typings to enforce the signature of each handler function
export const getAll = { | ||
path: 'repositories', | ||
method: 'get', | ||
handler: async (req: any, callWithRequest: any, responseToolkit: 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.
From looking at how some other plugins do it, I think we can use a few types here:
import { Legacy } from 'kibana';
import { Request, ResponseToolkit } from 'hapi';
import { CallClusterWithRequest } from 'src/legacy/core_plugins/elasticsearch';
handler: async (req: Legacy.Request, callWithRequest: CallClusterWithRequest, responseToolkit: ResponseToolkit) => {
// or this one... not sure why we have both Legacy.Request and Request
handler: async (req:Request, callWithRequest: CallClusterWithRequest, responseToolkit: ResponseToolkit) => {
patch: RouterRoute; | ||
} | ||
|
||
export declare function createRouter(server: any, pluginId: string, apiBasePath: string): Router; |
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.
We can type server
:
import { Server } from 'hapi';
export declare function createRouter(server: Server, pluginId: string, apiBasePath: string): Router;
|
||
import { Request, ResponseObject, ResponseToolkit } from 'hapi'; | ||
|
||
type CallWithRequest = (request: any, action: string, params: any) => 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.
I believe we can type request
per my comment above.
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 think the legacy ES call stuff is all typed now: https://github.com/elastic/kibana/blob/master/src/legacy/core_plugins/elasticsearch/index.d.ts
import { LicenseType } from '../../../common/constants'; | ||
|
||
export declare function registerLicenseChecker( | ||
server: 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.
We can type server
, per my comment above.
|
||
public start(): void { | ||
const server = this.server; | ||
const { core, plugins } = createShim(server, PLUGIN.ID); |
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 recommend pulling the shimming logic into snapshot_restore/index.ts
, so plugin.ts
doesn't appear coupled to the legacy stuff at all. So you'd call createShim
from the legacy init()
and pass core
and plugins
as arguments to this start()
.
Over time you'll convert more of the shim stuff over to new platform services directly, and then eventually you'll just delete the legacy plugin definition entirely, and your new plugin definition won't really change along the way.
The react context approach makes a lot of sense in this case, I think. You might want to be more selective in passing down the features you want to use though, rather than just passing the whole arguments through. It forces developers to make an explicit decision to take advantage of a new plugin or core feature somewhere deep within your code, which can help increase scrutiny around increased levels of coupling. At least this is all TypeScript so it's easy to manage even if you do pass them through. |
|
||
export class Plugin { | ||
public start(): void { | ||
const shim = createShim(); |
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.
Like in my comment on the server, I think you should pull the shim logic out of the Plugin
class and into the code that instantiates this and calls .start(). Keep the new code as pristine as possible, and let the legacy code handle the hackery.
}); | ||
|
||
// Register react root | ||
routing.registerAngularRoute(`${CLIENT_BASE_PATH}/:section?/:subsection?/:view?/:id`, { |
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 explain why this needs to be an angular route/controller rather than just being react like the rest of the plugin?
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.
since the Kibana chrome is using Angular routing, we need to register the initial base path with Angular so it's accessible from the management menu. we then mount the React app inside it which handles the rest of internal stuff in 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.
So if the management app itself was built using something like react router rather angular router, this wouldn't be necessary here, is that correct?
This is really awesome! I left a few comments, but overall this nailed the spirit of the migration guide, and I think it turned out well. |
Thanks for the reviews @cjcenizal and @epixa! I've addressed your feedback. I've fleshed out the typings to what I believe is a comprehensive enough point. I will add tests in the next pass when building out the actual features, so this PR is ready for another review by you two, or anyone else I have tagged. 😄 |
💚 Build Succeeded |
import { unmountComponentAtNode } from 'react-dom'; | ||
import { HashRouter } from 'react-router-dom'; | ||
|
||
export interface AppCore { |
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.
when this PR or #32746 finished we need to update typings here and 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.
thanks for the heads up 😄 I am happy to update these typings when that PR is merged. work with continue for this feature in subsequent PRs into the main feature branch, so it will be easy to update since there won't be any conflicts with master
|
||
// Snapshot and restore plugin styles | ||
|
||
// Prefix all styles with "snapshot" to avoid conflicts. |
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 know there aren't any actual styles in here (yet) but prefixes should just be 3 letters. I would change it now so its correct if people start adding styles.
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 that info, I've updated this to be ssr
prefix instead
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.
Looking pretty great Jen, nice work. I left a few comments, but nothing major.
import { HashRouter } from 'react-router-dom'; | ||
|
||
import { App } from './app'; | ||
// import { srStore } from './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.
leftover commented out code
export { BASE_PATH as CLIENT_BASE_PATH } from './constants'; | ||
|
||
export const renderReact = async ( | ||
elem: Element | null, |
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 the or null here? seems like it should always be an Element.
|
||
render( | ||
<I18nContext> | ||
{/*<Provider store={srStore}>*/} |
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.
more commented out code
export class SnapshotRestoreHome extends PureComponent<Props, State> { | ||
public static contextType = AppContext; | ||
|
||
public static getDerivedStateFromProps(nextProps: Props) { |
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.
wondering if maybe we want to start using function components + hooks instead of class ones.
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'd like to address this with the next pass when actual features start getting built out, it's hard for me to formulate an opinion for function components with hooks instead of lifecycles when the components don't do much yet 😁 I'll try function components + hooks for new components, and refactor these class ones if it goes well!
$scope.$$postDigest(() => { | ||
elem = document.getElementById(REACT_ROOT_ID); | ||
renderReact( | ||
elem, |
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.
we should check elem for null and only render if not null I think, then elem above can remove | null
|
||
export class Plugin { | ||
public start(core: Core, plugins: Plugins): void { | ||
const { i18n, routing, http, chrome, notification } = core; |
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.
routing
seems like maybe not the best name for this function, since it has unmount logic, which seems unrelated to routing, more like rendering to me.
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.
good point, I'll move unmounting logic out of shim, and keep routing
for just routing
export interface Core extends AppCore { | ||
routing: { | ||
registerAngularRoute(path: string, config: object): void; | ||
unmountReactApp(elem: Element | undefined | null): void; |
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.
wondering if this should be broken out into rendering
export function createShim(): { core: Core; plugins: Plugins } { | ||
// This is an Angular service, which is why we use this provider pattern | ||
// to access it within our React app. | ||
let httpClient: 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.
there's a type for $http ng.IHttpService
Thanks for the feedback, all! I've addressed the latest batch of em. |
💚 Build Succeeded |
One detail that I don't think is obvious is that all code originating from the plugin shim "hack" file will be bundled globally into all application bundles. That's the nature of hacks - they are global across all applications. The consequence of this is potential for rapid bloat of our common bundle size as more plugins shim more stuff. This is in contrast to most other uiExport-based functionality, which is only included in bundles when it is actually used by that application. In otherwords, your snapshot code will be loaded by users even when they're accessing things like timelion, ml, and apm. This will also be true of plugin definitions in the new platform, so it was an intentional design decision. The way we combat this problem is by having plugin developers use async imports to lazy load code only when it is necessary. This can technically be done in any extension point that allows your plugin to register an async function, and as a plugin author you should carefully consider where it makes the most sense. Too many async imports will result in poor performance as the browser has to load a ton of JavaScript files. Poorly placed async imports can potentially result in poor performance as the browser might load a bunch of JavaScript files one at a time. Registering management sections is a great place for using an async import, and I would expect this to be the expectation of all management sections in the future. Each section potentially has a ton of code powering it, but you only need to load that code when you actually navigate to that section. Any time we see this sort of situation, an async import is probably a good idea. Taking advantage of this requires an understanding of the problem from both sides. The management app itself must provide an extension point that allows an async function to load the section. Then the downstream plugin needs to put all of its section loading logic behind an async import. It would be pretty easy for you to do the latter in this pull request, but I'm not familiar with how management handles registering of sections, and I'm not sure if it would support an async function in its current form. In my mind, I'd expect this to look something like: // inside start() of plugin.js
management.getCategory('elasticsearch').registerSection({
id: 'snapshots',
name: 'Snapshots',
async render(domElement) {
const { loadSection } = await import('./section');
return loadSection(domElement, /* any core/plugin stuff you need in the section itself */);
}
});
// section.js
// most of the logic and imports related to the snapshots section in management
// would originate here, which ensures they aren't loaded until a user navigates here
export function loadSection(domElement, ...) {
// would render the section into the domElement container
return function unloadSection() {
// invoked by management app when navigating away from section
// would destroy/cleanup anything in the section that wouldn't automatically be
// cleaned up when the management app killed the dom element
}
} I know that's not how it looks today, but perhaps the chief goal of hiding the bulk of the section logic behind an async import is technically possible with the existing API? I don't know enough about the existing API to say for sure. |
Thanks for the insights, @epixa. I agree that it would be great to use async imports for management apps. Unfortunately, the management section registry right now is not that sophisticated with regards to rendering/mounting apps; it really only maintains a list of links with a few config options. Not hearing any other objections, I'm going to merge this into the feature branch 🙂 |
3c49317
to
358dfa8
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.
Wow, so many types! Code LGTM. Awesome work.
💚 Build Succeeded |
* [SR] Snapshot and restore plugin boilerplate (#32276) * Initial plugin set up * Set up client shell * Add initial repository list routes * Fix merge issues and some typings * Decouple server from plugin.ts files, tighten up typings * Use exported constant for required license * Translate plugin name, more typings * Fix more types, move list components under /home * Remove unused var * Change scss prefix * Uncouple unmount logic from routing shim, and some other PR feedback * [SR] Repository list and details UI (#33367) * Initial pass at repositories list UI * Add detail panel for file system repositories, and a generic detail panel with json settings view * Add detail components for other types * Add detail panel footer, rename `useStateValue` to `useAppState` * Fix detail panel footer * Fix unused vars * PR feedback * PR feedback * [SR] Refactor proposal (#33690) * Move app dependencies to its own context provider * Add index.ts barrel file for common types * Move Enums to constants.ts file * Refactor function component using `React.FunctionComponent<Props>` * Refactor service folder structure * Fix type import * Move REPOSITORY_DOC_PATHS from common to public constants * Move AppCore and AppPlugins interfaces back to shim and re-export them from app types * [SR] Create and edit repositories UI (#34020) * Add routing and placeholder form * Fix typings * Set up edit repository route, and basic form UI * Add typings for wrapCustomError, and copy extractCausedByChain from CCR wrapEsError * Throw errors that are already boomified * Create and edit for basic repository types (fs, url, source) * Add repository verification UI to table and details * Create and edit for plugin repository types (hdfs, azure, s3, gcs) * Fix linting * Fix test * Fix test * Remove unused import * Fix duplicate i18n key * Fix details opening on cancel edit, remove unnecessary Fragments, definition file for some EUI components to x-pack, rename saveError * Remove breaks * Adjust add and edit repo routes so they don't conflict with list route * Add repo plugin and types doc links to form * Bootstrap documentation service * Bootstrap text service and replace RepositoryTypeName component with it * Bootstrap breadcrumb service and replace usages * Bootstrap httpService, remove chrome and http from app dependencies(!) * Add request creator and replace all instances of useRequest and sendRequest with it * Fix typo * Simplify update repository and update repository setting methods * Adjust copy * Lint * Remove unused var * Remove unused import * [SR] Add API for retrieving snapshots. (#34598) * [SR] Single and multiple repository delete (#34593) * Add single/multi repository delete API and UI * Address PR feedback * [SR] Add SnapshotTable and SnapshotDetails. (#34837) * Remove associations between multiple repositories with a single snapshot. * Retrieve complete snapshot details in getAllHandler. * Fix cleanup function bug in useRequest hook. * Fix bug in useRequest which prevented old data from being cleared when subsequent requests returned errors. * Add initialValue config option to useRequest. * Add formatDate service to text module. * [SR] Fix linting and add (de)serialization for repositories (#35031) * Fix eslint issues and add (de)serialization for repositories * Add comment about flattening settings * [SR] Surface repository errors and index failures more prominently (#35042) * Add links to repositories from Snapshot Table and Snapshot Details. - Rename services/breadcrumbs to services/navigation and add linkToRepository function. - Refactor home component to update active tab when URL was changed. * Add warning callout to let user know when their repositories contain errors. * Sort failures by shard and add test for snapshot serialization. * Sort failures and indices. * Add filter for filtering snapshots by their repository. * Surface states with humanized text, icons, and tooltips where necessary. * Fix pluralization of seconds. * Surface failures tab even if there are none. - Display a '-' for missing times and durations. - Create DataPlaceholder component. * [SR] Polish repositories UX (#35123) * Refactor repository detail panel to load repository based directly on route param. * Display repository detail panel while table is loading. * Make 'Edit repository' table action a link instead of a button. * Render disabled EuiSelect as a readonly EuiFieldText. * Prepend HDFS URI with hdfs:// protocol. * Present scheme options for Read-Only URL repository as a select. * [SR] Add client-side validation to repository form and link to snapshots from details (#35238) * Add client side repository form validation, extract `flatten` into common lib * Add snapshot count to repository details and link to snapshot list * Reset validation when changing repository type * Fix snapshot list filter deep linking for repository names with slashes and spaces * Fix imports * PR feedback * [SR] Design and copywriting fixes (#35591) * Split repository form into two steps; move `clean_settings.ts` to server * Default to snapshots tab, adjust snapshot empty prompt, add app description * Add minimum timeout to list view requests to avoid flicker, use EuiEmptyPrompt for loading screen, add doc link to settings step * Add information about snapshots to delete repository behavior, add doc link for source only toggle, add size notation help text * Add main doc link * Copywriting and i18n fixes, and add some common settings to third party repo types * Add fields to third party repo detail panel * More copywriting fixes * Use spinner for duration and end time if snapshotting is still in progress * Show all repository type options, mark missing plugins * Revert "Show all repository type options, mark missing plugins" This reverts commit e34ee47. * Fix space * [SR] Add permissions UI and Cloud-specific repository type UI branch (#35833) * Add missing permissions UI and cloud-specific repository type UI branch * Add ES UI as owners of /snapshot_restore directory * Add no repository types callout for Cloud edge case * Redirect invalid section param to repositories * Add warning empty prompt if all repositories have errrors * Replace repository cards with EuiCard * Add snapshot doc link to repository error empty prompt * Remove auto-verification from list and get routes, add separate verification route, add manual verification to repository detail panel * Update copy and remove obsolete test * Remove unused scss files * Final changes to repository cards
* [SR] Snapshot and restore plugin boilerplate (elastic#32276) * Initial plugin set up * Set up client shell * Add initial repository list routes * Fix merge issues and some typings * Decouple server from plugin.ts files, tighten up typings * Use exported constant for required license * Translate plugin name, more typings * Fix more types, move list components under /home * Remove unused var * Change scss prefix * Uncouple unmount logic from routing shim, and some other PR feedback * [SR] Repository list and details UI (elastic#33367) * Initial pass at repositories list UI * Add detail panel for file system repositories, and a generic detail panel with json settings view * Add detail components for other types * Add detail panel footer, rename `useStateValue` to `useAppState` * Fix detail panel footer * Fix unused vars * PR feedback * PR feedback * [SR] Refactor proposal (elastic#33690) * Move app dependencies to its own context provider * Add index.ts barrel file for common types * Move Enums to constants.ts file * Refactor function component using `React.FunctionComponent<Props>` * Refactor service folder structure * Fix type import * Move REPOSITORY_DOC_PATHS from common to public constants * Move AppCore and AppPlugins interfaces back to shim and re-export them from app types * [SR] Create and edit repositories UI (elastic#34020) * Add routing and placeholder form * Fix typings * Set up edit repository route, and basic form UI * Add typings for wrapCustomError, and copy extractCausedByChain from CCR wrapEsError * Throw errors that are already boomified * Create and edit for basic repository types (fs, url, source) * Add repository verification UI to table and details * Create and edit for plugin repository types (hdfs, azure, s3, gcs) * Fix linting * Fix test * Fix test * Remove unused import * Fix duplicate i18n key * Fix details opening on cancel edit, remove unnecessary Fragments, definition file for some EUI components to x-pack, rename saveError * Remove breaks * Adjust add and edit repo routes so they don't conflict with list route * Add repo plugin and types doc links to form * Bootstrap documentation service * Bootstrap text service and replace RepositoryTypeName component with it * Bootstrap breadcrumb service and replace usages * Bootstrap httpService, remove chrome and http from app dependencies(!) * Add request creator and replace all instances of useRequest and sendRequest with it * Fix typo * Simplify update repository and update repository setting methods * Adjust copy * Lint * Remove unused var * Remove unused import * [SR] Add API for retrieving snapshots. (elastic#34598) * [SR] Single and multiple repository delete (elastic#34593) * Add single/multi repository delete API and UI * Address PR feedback * [SR] Add SnapshotTable and SnapshotDetails. (elastic#34837) * Remove associations between multiple repositories with a single snapshot. * Retrieve complete snapshot details in getAllHandler. * Fix cleanup function bug in useRequest hook. * Fix bug in useRequest which prevented old data from being cleared when subsequent requests returned errors. * Add initialValue config option to useRequest. * Add formatDate service to text module. * [SR] Fix linting and add (de)serialization for repositories (elastic#35031) * Fix eslint issues and add (de)serialization for repositories * Add comment about flattening settings * [SR] Surface repository errors and index failures more prominently (elastic#35042) * Add links to repositories from Snapshot Table and Snapshot Details. - Rename services/breadcrumbs to services/navigation and add linkToRepository function. - Refactor home component to update active tab when URL was changed. * Add warning callout to let user know when their repositories contain errors. * Sort failures by shard and add test for snapshot serialization. * Sort failures and indices. * Add filter for filtering snapshots by their repository. * Surface states with humanized text, icons, and tooltips where necessary. * Fix pluralization of seconds. * Surface failures tab even if there are none. - Display a '-' for missing times and durations. - Create DataPlaceholder component. * [SR] Polish repositories UX (elastic#35123) * Refactor repository detail panel to load repository based directly on route param. * Display repository detail panel while table is loading. * Make 'Edit repository' table action a link instead of a button. * Render disabled EuiSelect as a readonly EuiFieldText. * Prepend HDFS URI with hdfs:// protocol. * Present scheme options for Read-Only URL repository as a select. * [SR] Add client-side validation to repository form and link to snapshots from details (elastic#35238) * Add client side repository form validation, extract `flatten` into common lib * Add snapshot count to repository details and link to snapshot list * Reset validation when changing repository type * Fix snapshot list filter deep linking for repository names with slashes and spaces * Fix imports * PR feedback * [SR] Design and copywriting fixes (elastic#35591) * Split repository form into two steps; move `clean_settings.ts` to server * Default to snapshots tab, adjust snapshot empty prompt, add app description * Add minimum timeout to list view requests to avoid flicker, use EuiEmptyPrompt for loading screen, add doc link to settings step * Add information about snapshots to delete repository behavior, add doc link for source only toggle, add size notation help text * Add main doc link * Copywriting and i18n fixes, and add some common settings to third party repo types * Add fields to third party repo detail panel * More copywriting fixes * Use spinner for duration and end time if snapshotting is still in progress * Show all repository type options, mark missing plugins * Revert "Show all repository type options, mark missing plugins" This reverts commit e34ee47. * Fix space * [SR] Add permissions UI and Cloud-specific repository type UI branch (elastic#35833) * Add missing permissions UI and cloud-specific repository type UI branch * Add ES UI as owners of /snapshot_restore directory * Add no repository types callout for Cloud edge case * Redirect invalid section param to repositories * Add warning empty prompt if all repositories have errrors * Replace repository cards with EuiCard * Add snapshot doc link to repository error empty prompt * Remove auto-verification from list and get routes, add separate verification route, add manual verification to repository detail panel * Update copy and remove obsolete test * Remove unused scss files * Final changes to repository cards
* [SR] Snapshot and restore plugin boilerplate (#32276) * Initial plugin set up * Set up client shell * Add initial repository list routes * Fix merge issues and some typings * Decouple server from plugin.ts files, tighten up typings * Use exported constant for required license * Translate plugin name, more typings * Fix more types, move list components under /home * Remove unused var * Change scss prefix * Uncouple unmount logic from routing shim, and some other PR feedback * [SR] Repository list and details UI (#33367) * Initial pass at repositories list UI * Add detail panel for file system repositories, and a generic detail panel with json settings view * Add detail components for other types * Add detail panel footer, rename `useStateValue` to `useAppState` * Fix detail panel footer * Fix unused vars * PR feedback * PR feedback * [SR] Refactor proposal (#33690) * Move app dependencies to its own context provider * Add index.ts barrel file for common types * Move Enums to constants.ts file * Refactor function component using `React.FunctionComponent<Props>` * Refactor service folder structure * Fix type import * Move REPOSITORY_DOC_PATHS from common to public constants * Move AppCore and AppPlugins interfaces back to shim and re-export them from app types * [SR] Create and edit repositories UI (#34020) * Add routing and placeholder form * Fix typings * Set up edit repository route, and basic form UI * Add typings for wrapCustomError, and copy extractCausedByChain from CCR wrapEsError * Throw errors that are already boomified * Create and edit for basic repository types (fs, url, source) * Add repository verification UI to table and details * Create and edit for plugin repository types (hdfs, azure, s3, gcs) * Fix linting * Fix test * Fix test * Remove unused import * Fix duplicate i18n key * Fix details opening on cancel edit, remove unnecessary Fragments, definition file for some EUI components to x-pack, rename saveError * Remove breaks * Adjust add and edit repo routes so they don't conflict with list route * Add repo plugin and types doc links to form * Bootstrap documentation service * Bootstrap text service and replace RepositoryTypeName component with it * Bootstrap breadcrumb service and replace usages * Bootstrap httpService, remove chrome and http from app dependencies(!) * Add request creator and replace all instances of useRequest and sendRequest with it * Fix typo * Simplify update repository and update repository setting methods * Adjust copy * Lint * Remove unused var * Remove unused import * [SR] Add API for retrieving snapshots. (#34598) * [SR] Single and multiple repository delete (#34593) * Add single/multi repository delete API and UI * Address PR feedback * [SR] Add SnapshotTable and SnapshotDetails. (#34837) * Remove associations between multiple repositories with a single snapshot. * Retrieve complete snapshot details in getAllHandler. * Fix cleanup function bug in useRequest hook. * Fix bug in useRequest which prevented old data from being cleared when subsequent requests returned errors. * Add initialValue config option to useRequest. * Add formatDate service to text module. * [SR] Fix linting and add (de)serialization for repositories (#35031) * Fix eslint issues and add (de)serialization for repositories * Add comment about flattening settings * [SR] Surface repository errors and index failures more prominently (#35042) * Add links to repositories from Snapshot Table and Snapshot Details. - Rename services/breadcrumbs to services/navigation and add linkToRepository function. - Refactor home component to update active tab when URL was changed. * Add warning callout to let user know when their repositories contain errors. * Sort failures by shard and add test for snapshot serialization. * Sort failures and indices. * Add filter for filtering snapshots by their repository. * Surface states with humanized text, icons, and tooltips where necessary. * Fix pluralization of seconds. * Surface failures tab even if there are none. - Display a '-' for missing times and durations. - Create DataPlaceholder component. * [SR] Polish repositories UX (#35123) * Refactor repository detail panel to load repository based directly on route param. * Display repository detail panel while table is loading. * Make 'Edit repository' table action a link instead of a button. * Render disabled EuiSelect as a readonly EuiFieldText. * Prepend HDFS URI with hdfs:// protocol. * Present scheme options for Read-Only URL repository as a select. * [SR] Add client-side validation to repository form and link to snapshots from details (#35238) * Add client side repository form validation, extract `flatten` into common lib * Add snapshot count to repository details and link to snapshot list * Reset validation when changing repository type * Fix snapshot list filter deep linking for repository names with slashes and spaces * Fix imports * PR feedback * [SR] Design and copywriting fixes (#35591) * Split repository form into two steps; move `clean_settings.ts` to server * Default to snapshots tab, adjust snapshot empty prompt, add app description * Add minimum timeout to list view requests to avoid flicker, use EuiEmptyPrompt for loading screen, add doc link to settings step * Add information about snapshots to delete repository behavior, add doc link for source only toggle, add size notation help text * Add main doc link * Copywriting and i18n fixes, and add some common settings to third party repo types * Add fields to third party repo detail panel * More copywriting fixes * Use spinner for duration and end time if snapshotting is still in progress * Show all repository type options, mark missing plugins * Revert "Show all repository type options, mark missing plugins" This reverts commit e34ee47. * Fix space * [SR] Add permissions UI and Cloud-specific repository type UI branch (#35833) * Add missing permissions UI and cloud-specific repository type UI branch * Add ES UI as owners of /snapshot_restore directory * Add no repository types callout for Cloud edge case * Redirect invalid section param to repositories * Add warning empty prompt if all repositories have errrors * Replace repository cards with EuiCard * Add snapshot doc link to repository error empty prompt * Remove auto-verification from list and get routes, add separate verification route, add manual verification to repository detail panel * Update copy and remove obsolete test * Remove unused scss files * Final changes to repository cards
The beginning of snapshot and restore GUI!
This PR sets up the new plugin and includes some boilerplate client-side and server-side code. Since this plugin was created with new Kibana platform principles in mind, I am primarily looking for feedback with regards to that. You'll notice two sets of
shim.ts
andplugin.ts
files, one used by client and the other for server.@epixa, I ran into some difficulties with accessing
core
andplugins
from child React components. I ended up creating a React context,AppContext
, which is initialized when parent component is mounted, and referenced by child components usingcontextType
so thatcore
andplugins
can be used in lifecycle methods. Feedback and/or suggestions for this would be super appreciated.