[SR] Create and edit repositories UI#34020
[SR] Create and edit repositories UI#34020jen-huang merged 29 commits intoelastic:feature/snapshotsfrom
Conversation
…e/snapshots-create-repo
|
Pinging @elastic/es-ui |
This comment has been minimized.
This comment has been minimized.
|
|
||
| import Boom from 'boom'; | ||
|
|
||
| function extractCausedByChain(causedBy = {}, accumulator = []) { |
There was a problem hiding this comment.
the changes here are copied from the changes done in CCR to surface ES messages to UI:
https://github.com/elastic/kibana/blob/master/x-pack/plugins/cross_cluster_replication/server/lib/error_wrappers/wrap_es_error.js
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
💚 Build Succeeded |
|
@jen-huang I propose to remove the delegate combo and have a toggle for source (source only snapshots) |
|
Another comment - when additional custom settings are supported instead of |
sebelga
left a comment
There was a problem hiding this comment.
Amazing work @jen-huang ! I tested locally and works fine. I did not test any of the plugins as I did not manage to install them (azure, s3, ...).
In the review changes, I made mainly comments about style/personal preferences/reusability of code. Let me know if you agree with me.
There is a very small UI bug. When you click "edit" on a repository, then once in the form you click "cancel", you get back to the table list but with the detail, panel opened.
Note: I am a bit concerned about all the repeated logic in our forms I must say. We are constantly repeating the same pattern in all our apps (ccr, remote clusters, here) for our form rows:
- Title
- Description
- Input label
- type (text, number, toggle, select)
- validation
It would be so much simpler, consistent, more robust and faster to build those forms through a Schema. Maybe there is no time to do it now, but I had to mention it 😊 I'll see if I can investigate and find a solution for this ater the testing.
| import { | ||
| EuiButton, | ||
| EuiButtonEmpty, | ||
| // @ts-ignore |
There was a problem hiding this comment.
For the missing types from eui, it would be better to create the @elastic/eui folder inside the "typings" folder (from x-pack). And add a index.d.ts file there with
declare module '@elastic/eui' {
export const EuiDescribedFormGroup: React.SFC<any>;
}So that's the folder structure:
x-pack > typings > @elastic > eui > index.d.ts
So when eui will provide the type we can just delete our declaration here.
| EuiFormRow, | ||
| EuiSelect, | ||
| EuiSpacer, | ||
| // @ts-ignore |
There was a problem hiding this comment.
I think we can remove this, as EuiSuperSelect is not used
| repository: originalRepository, | ||
| isEditing, | ||
| isSaving, | ||
| saveError, |
There was a problem hiding this comment.
The naming is a bit misleading 😊 saveError sound like a method... to save the error! I prefer just error. If we had have multiple error type then
errors: {
save: <some error>,
delete: <some error>,
}| path: chrome.addBasePath(`${API_BASE_PATH}repository_types`), | ||
| method: 'get', | ||
| httpClient: http.getClient(), | ||
| }); |
There was a problem hiding this comment.
I think that the same way we had actions creators in Redux, we should have requests creators so we have a single place to modify and update them. I played a bit, this is what I came with:
// services/http/http_services.ts
class HttpService {
private client: any;
public addBasePath: (path: string) => string = () => '';
public init(httpClient: any, chrome: any) {
this.addBasePath = chrome.addBasePath.bind(chrome);
this.client = httpClient;
}
get httpClient() {
return this.client;
}
}
export const httpService = new HttpService();// we instantiate it in our main index.tsx file
...
import { httpService } from './services/http';
...
const {
i18n: { Context: I18nContext },
http,
chrome,
} = core;
const appDependencies: AppDependencies = {
core,
plugins,
};
DependenciesContext = createContext<AppDependencies>(appDependencies);
httpService.init(http.getClient(), chrome);
...// Our "requests" creators (./services/http/requests.ts)
import { API_BASE_PATH } from '../../../../common/constants';
import { httpService } from './http_service';
import { useRequest } from './use_request';
export const loadRepositoryTypes = () =>
useRequest({
path: httpService.addBasePath(`${API_BASE_PATH}repository_types`),
method: 'get',
httpClient: httpService.httpClient,
});// repository_form.tsx
...
import { loadRepositoryTypes } from '../../services/http';
// Then we simply have this here
const {
core: {
i18n: { FormattedMessage },
},
} = useAppDependencies();
const {
error: repositoryTypesError,
loading: repositoryTypesLoading,
data: repositoryTypes,
} = loadRepositoryTypes();What do you think?
There was a problem hiding this comment.
I like this idea, personally. Then we don't need to pass around chrome and http.
| () => { | ||
| const repositoryTypeOptions = [...repositoryTypes]; | ||
| const { type } = repository; | ||
| if (isEditing && REPOSITORY_PLUGINS_MAP[type] && !repositoryTypes.includes(type)) { |
There was a problem hiding this comment.
Curious to know why is this only executed on isEditing ?
There was a problem hiding this comment.
this is for an edge case like the following:
- user creates plugin-based repository like
s3 - user uninstalls plugin for some reason
- repository will still exist and show in the list, but the list of types available will not include
s3, so this logic pushes the repository into the list anyway
this scenario is not encountered for creation of a new repository, hence the isEditing check 🙂
| error, | ||
| loading, | ||
| data: { repository, verification }, | ||
| } = useRequest({ |
There was a problem hiding this comment.
To be changed if we go the "requests creator" path 😊
| setIsSaving(true); | ||
| setSaveError(null); | ||
| const { name } = newRepository; | ||
| const { error } = await sendRequest({ |
There was a problem hiding this comment.
Here too it'd be cleaner a request creator: await saveRepository(newRepository)
| /** | ||
| * Utility to remove empty fields ("") from repository settings | ||
| */ | ||
| export const cleanSettings = (settings: Repository['settings']) => |
There was a problem hiding this comment.
We might want to be able to use the same method for other forms object? What about naming it something like removeEmptyStringsFromObject(...). It could even do it deeply (with an optional parameter), but then you'd be passing the interview a second time 😄
There was a problem hiding this comment.
Just to play devil's advocate, I think there is a benefit to preserving this as specialized logic for cleaning the settings object, as opposed to generalizing it. In its current form it's really clear to me what its purpose is: empty strings have a special meaning in the context of the settings object, and this logic tells me that we don't want to keep them (for some reason). It's really simple to grok the intention behind this code. I understand that there's a business rule here and if we make changes to this code it will because we're adapting to changes in the business rule.
On the other hand, if we extract this out into a generalized utility, now the context has changed and we've invited new features (like the ability to clean an object deeply, which may not be necessary or even desired for our use case). If our business rules change then adapting the code is not as simple. As a contrived example, if we switch to using null instead of empty strings, then we'd need to either modify the generalized function and make sure we're not breaking anything for consumers, or write entirely new code.
Based on these pros and cons I really don't think we should bother generalizing this. :)
There was a problem hiding this comment.
The more I keep reading about functional programming the more we will have a discrepancy on this. 😊 In lean towards functions that do not have any business "specialized logic" baked in them. I believe in small functions that do 1 thing well and that are composable (especially utilities functions).
In the composition of those small function resides the business logic.
In the long run, it makes code cleaner, the webpage faster (no need to send the same JS over and over in differents .bundle.js), lower memory footprint, and I would even say more robust as the same piece of code is being executed hundreds of time (and thus fully tested).
And it goes without saying the fact that it saves in development time by not having to re-think, re-write and re-test the same exact code.
I mention it because.... I wrote a very similar function in CCR I think 😊 and the "empty strings have a special meaning in the context of the settings object" statement is not totally true. We need it in all those scenarios where we don't want the client to send form fields that haven't been modified.
|
|
||
| const unmountReactApp = (elem: Element | undefined | null): void => { | ||
| const unmountReactApp = (): void => { | ||
| const elem = document.getElementById(REACT_ROOT_ID); |
There was a problem hiding this comment.
Are you sure about this refactor? We kept the reference to the elem outside so we could unmount the react app without losing the reference to the dom node (as Angular was creating a new div in the DOM)...
Did you fully test this?
There was a problem hiding this comment.
yep. these changes were made due to the react app mounting twice when navigating away and coming back (React dev tools showed 2 apps)
There was a problem hiding this comment.
Ok.... then we might have the bug in our other apps as they are all using this pattern. I'll check.
| /** | ||
| * Utility to coerce ES boolean strings to actual booleans | ||
| */ | ||
| export const booleanizeSettings = (repository: Repository) => { |
There was a problem hiding this comment.
Same comment as above. I'd give it a generic name so it could be used and reused at will 😊
There was a problem hiding this comment.
Maybe as a compromise we can follow the rule of threes, and wait for multiple use cases to arise before generalizing?
There was a problem hiding this comment.
So here I was just saying to give it a generic name. By now we should have a common library of all those generic utils functions instead of re-writing them over and over.
…inition file for some EUI components to x-pack, rename saveError
cjcenizal
left a comment
There was a problem hiding this comment.
This is terrific! I had a few suggestions about UI/UX, but nothing that can't be addressed later. I will be able to hop onboard this week so I can even address them myself if you prefer.
Objects are misrendering in detail panel
Looks like object details are rendering as [object Object]. I didn't dig into it, but maybe we just need to do some JSON stringifying?
Type doclink needs grow={false}
Looks like this button is expanding to fill the container. I think we just need grow={false} on the EuiFlexItem that contains it.
Edit button could be a link
Can we make the "Edit" button a link so users can open it in a new tab?
Standardizing the detail panel
In the Rollup Jobs list, we have two columns in the detail panel and we make the value of each stat stand out more than the label. Can we tweak this detail panel to match this pattern?
| <div> | ||
| <Switch> | ||
| <Redirect exact from={`${BASE_PATH}`} to={`${BASE_PATH}/repositories`} /> | ||
| <Route exact path={`${BASE_PATH}/repositories/add`} component={RepositoryAdd} /> |
There was a problem hiding this comment.
I just found one limitation with encoding the name of the entity you're viewing in the URL, which is that you can't give it a name which conflicts with other routes. For example, if you name a repository "add" the router will never let you view its details.
I know this is kind of a silly corner case, but I think it's worth addressing. I can think of three solutions:
- Differentiate the "detail view" route from the others, e.g.
snapshot_restore/detail/:name. - Add validation in the form, so if someone tries to use the name "add", we disallow it. This of course doesn't prevent the user from doing this via direct API call so it's not really viable.
- Go back to putting the name in a query parameter. Blech!
| path: chrome.addBasePath(`${API_BASE_PATH}repository_types`), | ||
| method: 'get', | ||
| httpClient: http.getClient(), | ||
| }); |
There was a problem hiding this comment.
I like this idea, personally. Then we don't need to pass around chrome and http.
| () => { | ||
| const repositoryTypeOptions = [...repositoryTypes]; | ||
| const { type } = repository; | ||
| if (isEditing && REPOSITORY_PLUGINS_MAP[type] && !repositoryTypes.includes(type)) { |
There was a problem hiding this comment.
I tested this by removing the gcs plugin and going to edit a repo created for GCS. It looks like the option doesn't make it into the select:
It looks like the type is "gcs", but REPOSITORY_PLUGINS_MAP doesn't contain that key -- it's actually "repository-gcs". I didn't test the other plugins, but there's a chance the same applies to them as well.
| fullWidth | ||
| onChange={e => { | ||
| onRepositoryChange({ | ||
| ...repository, |
There was a problem hiding this comment.
I think this would be a nice improvement too, because it also makes it clear in the onRepositoryChange implementation that we're not accidentally mutating newRepository, which is how I originally interpreted the code since it's provided as an argument.
| renderLoadingRepositoryTypesError() | ||
| ) : ( | ||
| <EuiSelect | ||
| disabled={isEditing} |
There was a problem hiding this comment.
When we're in editing mode, how about rendering this as a read-only text field instead? That way the text is a bit easier to read and you don't have the "noise" of the select-dropdown caret and other styling.
<EuiFormRow
label={
<FormattedMessage
id="xpack.snapshotRestore.repositoryForm.fields.typeLabel"
defaultMessage="Type"
/>
}
describedByIds={['repositoryTypeDescription']}
fullWidth
>
{repositoryTypesError ? (
renderLoadingRepositoryTypesError()
) : isEditing ? (
<EuiFieldText
readOnly={true}
value={repository.type}
fullWidth
/>
) : (
<EuiSelect
isLoading={repositoryTypesLoading}
options={availableRepositoryTypes.map(type => {
return {
value: type,
text: ReactDOMServer.renderToString(<RepositoryTypeName type={type} />),
};
})}
value={
availableRepositoryTypes.includes(repository.type)
? repository.type
: REPOSITORY_TYPES.fs
}
onChange={e => {
onRepositoryChange({
...repository,
type: e.target.value,
settings: {},
});
}}
fullWidth
/>
)}
</EuiFormRow>There was a problem hiding this comment.
I like the idea but then we'd need to update the other apps to follow that pattern, no?
| fullWidth | ||
| describedByIds={['readonlyRepositoryURLDescription']} | ||
| > | ||
| <EuiFieldText |
There was a problem hiding this comment.
What do you think of using an inline select to list the available protocol options? That will make it easier for users to see what their options are, select one without a typo, and it will also reduce the amount of help text we need to show at one time, since we can just show the help text that matches whatever the user has selected. It will definitely add some complexity to the code though. :)
// just to convey the idea
<div>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem grow={false}>
<EuiFormRow
label={
<FormattedMessage
id="xpack.snapshotRestore.repositoryForm.typeReadonly.urlLabel"
defaultMessage="Protocol"
/>
}
fullWidth
describedByIds={['readonlyRepositoryURLDescription']}
>
<EuiSelect options={[{ value: 'http', text: 'http://' }]} value="http" />
</EuiFormRow>
</EuiFlexItem>
<EuiFlexItem>
<EuiFormRow
label={
<FormattedMessage
id="xpack.snapshotRestore.repositoryForm.typeReadonly.urlLabel"
defaultMessage="Path"
/>
}
fullWidth
describedByIds={['readonlyRepositoryURLDescription']}
>
<EuiFieldText
defaultValue={url || ''}
fullWidth
onChange={e => {
onSettingsChange({
...repository.settings,
url: e.target.value,
});
}}
/>
</EuiFormRow>
</EuiFlexItem>
</EuiFlexGroup>
{/* This will need some ARIA props to associate it with the above fields */}
<EuiFormHelpText>
<FormattedMessage
id="xpack.snapshotRestore.repositoryForm.typeReadonly.urlWhitelistDescription"
defaultMessage="URL repositories with {httpType} must be whitelisted as part of the {settingKey} Elasticsearch setting."
values={{
httpType: <EuiCode>http:</EuiCode>,
settingKey: <EuiCode>repositories.url.allowed_urls</EuiCode>,
}}
/>
</EuiFormHelpText>
</div>| }; | ||
|
|
||
| const renderTypeSettings = (repositoryType: RepositoryType) => { | ||
| switch (repositoryType) { |
There was a problem hiding this comment.
If you prefer I think you could also use the map pattern from repository_type_name.tsx instead of a switch.
| <EuiHealth color="success"> | ||
| <FormattedMessage | ||
| id="xpack.snapshotRestore.repositoryVerification.verificationSuccessfulValue" | ||
| defaultMessage="Success" |
There was a problem hiding this comment.
There was a problem hiding this comment.
to me, "Not verified" means "we didn't check this repository" rather than that there was an error with connecting to the repository. although ES uses the term "verification", I think "repository status" or "connection status" is more accurate. let's defer this until copywriting review, but maybe we can simply say "Status" instead, maybe with the values "Connected" or "Error"
| /** | ||
| * Utility to remove empty fields ("") from repository settings | ||
| */ | ||
| export const cleanSettings = (settings: Repository['settings']) => |
There was a problem hiding this comment.
Just to play devil's advocate, I think there is a benefit to preserving this as specialized logic for cleaning the settings object, as opposed to generalizing it. In its current form it's really clear to me what its purpose is: empty strings have a special meaning in the context of the settings object, and this logic tells me that we don't want to keep them (for some reason). It's really simple to grok the intention behind this code. I understand that there's a business rule here and if we make changes to this code it will because we're adapting to changes in the business rule.
On the other hand, if we extract this out into a generalized utility, now the context has changed and we've invited new features (like the ability to clean an object deeply, which may not be necessary or even desired for our use case). If our business rules change then adapting the code is not as simple. As a contrived example, if we switch to using null instead of empty strings, then we'd need to either modify the generalized function and make sure we're not breaking anything for consumers, or write entirely new code.
Based on these pros and cons I really don't think we should bother generalizing this. :)
| /** | ||
| * Utility to coerce ES boolean strings to actual booleans | ||
| */ | ||
| export const booleanizeSettings = (repository: Repository) => { |
There was a problem hiding this comment.
Maybe as a compromise we can follow the rule of threes, and wait for multiple use cases to arise before generalizing?
|
Thanks for the in-depth feedback, everyone! I've addressed most of them:
The major ones that I will defer are UI changes/improvements (as suggested by @yaronp68 and @cjcenizal) as these will take longer and I'd like to get this PR merged so that the upstream feature branch is in a good place to begin shared dev work 😄 |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
💚 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










Summary
This PR adds ability to create and edit repositories from the Snapshot and Restore app UI. All repository types are supported, including plugin-based repositories! Instructions for setting up repositories are below. After creating or editing a repository, the user will be redirected back to repository list with the newly created or edited repository details flyout open.
Note: The forms do not have client-side validation yet. I will add that next.
This PR also adds repository verification information to the UI, so that users can see which repositories are connected and which ones may potentially have configuration issues.
Instructions
Instructions for setting up repositories for testing
File system
or
locationsetting:settingsas necessary, all available settings can be found in docs:https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html#_shared_file_system_repository
Readonly
Readonly repositories only take
urlsetting. Documentation: https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html#_read_only_url_repositoryIt's easy to set up a
file:url:Source only
Source only repositories are special in that they are basically a wrapper around another repository type. Documentation: https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html#_source_only_repository
This means that the settings that are available depends on the
delegate_typeparameter. For example, this source only repository delegates tofs(file system) type, so all file system rules and available settings apply:Plugin-based repositories:
There are four official repository plugins available: S3, GCS, HDFS, Azure. Please refer to the meta ticket Developer notes section : https://github.com/elastic/elasticsearch-team/issues/118
Available plugin repository settings can be found in docs: https://www.elastic.co/guide/en/elasticsearch/plugins/master/repository.html
Screenshots
Verification status in repository list table:

Verification status and details in repository details:

Register (create) repository form:

The form changes based on repository type. Here's a

sourcerepository type that delegates toazure:Edit repository form, note that the

nameandtypefields are not editable: