-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update user management page (#87133)
* Update user management page * Fixed i18n errors * Fix linting errors * Add ids required for accessability * Added suggestions from code review * Fix test errors * Fix types in fleet * fix translations * Fix i18n * Added suggestions from code review * Fix i18n errors * Fix linting errors * Update messaging * Updated unit tests * Updated functional tests * Fixed functional tests * Fix linting errors * Fix React warnings * Added suggestions from code review * Added tests and renamed routes * Fix functional tests * Simplified API integration tests * Updated copy based on writing suggestions * Fixed unit tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
- Loading branch information
1 parent
a5bb864
commit aeb6df3
Showing
57 changed files
with
3,242 additions
and
1,680 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
137 changes: 137 additions & 0 deletions
137
x-pack/plugins/security/public/components/breadcrumb.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React, { createContext, useEffect, useRef, useContext, FunctionComponent } from 'react'; | ||
import { EuiBreadcrumb } from '@elastic/eui'; | ||
import { useKibana } from '../../../../../src/plugins/kibana_react/public'; | ||
|
||
interface BreadcrumbsContext { | ||
parents: BreadcrumbProps[]; | ||
onMount(breadcrumbs: BreadcrumbProps[]): void; | ||
onUnmount(breadcrumbs: BreadcrumbProps[]): void; | ||
} | ||
|
||
const BreadcrumbsContext = createContext<BreadcrumbsContext | undefined>(undefined); | ||
|
||
export interface BreadcrumbProps extends EuiBreadcrumb { | ||
text: string; | ||
} | ||
|
||
/** | ||
* Component that automatically sets breadcrumbs and document title based on the render tree. | ||
* | ||
* @example | ||
* // Breadcrumbs will be set to: "Users > Create" | ||
* // Document title will be set to: "Create - Users" | ||
* | ||
* ```typescript | ||
* <Breadcrumb text="Users"> | ||
* <Table /> | ||
* {showForm && ( | ||
* <Breadcrumb text="Create"> | ||
* <Form /> | ||
* </Breadcrumb> | ||
* )} | ||
* </Breadcrumb> | ||
* ``` | ||
*/ | ||
export const Breadcrumb: FunctionComponent<BreadcrumbProps> = ({ children, ...breadcrumb }) => { | ||
const context = useContext(BreadcrumbsContext); | ||
const component = <InnerBreadcrumb breadcrumb={breadcrumb}>{children}</InnerBreadcrumb>; | ||
|
||
if (context) { | ||
return component; | ||
} | ||
|
||
return <BreadcrumbsProvider>{component}</BreadcrumbsProvider>; | ||
}; | ||
|
||
export interface BreadcrumbsProviderProps { | ||
onChange?: BreadcrumbsChangeHandler; | ||
} | ||
|
||
export type BreadcrumbsChangeHandler = (breadcrumbs: BreadcrumbProps[]) => void; | ||
|
||
/** | ||
* Component that can be used to define any side effects that should occur when breadcrumbs change. | ||
* | ||
* By default the breadcrumbs in application chrome are set and the document title is updated. | ||
* | ||
* @example | ||
* ```typescript | ||
* <Breadcrumbs onChange={(breadcrumbs) => setBreadcrumbs(breadcrumbs)}> | ||
* <Breadcrumb text="Users" /> | ||
* </Breadcrumbs> | ||
* ``` | ||
*/ | ||
export const BreadcrumbsProvider: FunctionComponent<BreadcrumbsProviderProps> = ({ | ||
children, | ||
onChange, | ||
}) => { | ||
const { services } = useKibana(); | ||
const breadcrumbsRef = useRef<BreadcrumbProps[]>([]); | ||
|
||
const handleChange = (breadcrumbs: BreadcrumbProps[]) => { | ||
if (onChange) { | ||
onChange(breadcrumbs); | ||
} else if (services.chrome) { | ||
services.chrome.setBreadcrumbs(breadcrumbs); | ||
services.chrome.docTitle.change(getDocTitle(breadcrumbs)); | ||
} | ||
}; | ||
|
||
return ( | ||
<BreadcrumbsContext.Provider | ||
value={{ | ||
parents: [], | ||
onMount: (breadcrumbs) => { | ||
if (breadcrumbs.length > breadcrumbsRef.current.length) { | ||
breadcrumbsRef.current = breadcrumbs; | ||
handleChange(breadcrumbs); | ||
} | ||
}, | ||
onUnmount: (breadcrumbs) => { | ||
if (breadcrumbs.length < breadcrumbsRef.current.length) { | ||
breadcrumbsRef.current = breadcrumbs; | ||
handleChange(breadcrumbs); | ||
} | ||
}, | ||
}} | ||
> | ||
{children} | ||
</BreadcrumbsContext.Provider> | ||
); | ||
}; | ||
|
||
export interface InnerBreadcrumbProps { | ||
breadcrumb: BreadcrumbProps; | ||
} | ||
|
||
export const InnerBreadcrumb: FunctionComponent<InnerBreadcrumbProps> = ({ | ||
breadcrumb, | ||
children, | ||
}) => { | ||
const { parents, onMount, onUnmount } = useContext(BreadcrumbsContext)!; | ||
const nextParents = [...parents, breadcrumb]; | ||
|
||
useEffect(() => { | ||
onMount(nextParents); | ||
return () => onUnmount(parents); | ||
}, [breadcrumb.text, breadcrumb.href]); // eslint-disable-line react-hooks/exhaustive-deps | ||
|
||
return ( | ||
<BreadcrumbsContext.Provider value={{ parents: nextParents, onMount, onUnmount }}> | ||
{children} | ||
</BreadcrumbsContext.Provider> | ||
); | ||
}; | ||
|
||
export function getDocTitle(breadcrumbs: BreadcrumbProps[], maxBreadcrumbs = 2) { | ||
return breadcrumbs | ||
.slice(0, maxBreadcrumbs) | ||
.reverse() | ||
.map(({ text }) => text); | ||
} |
94 changes: 94 additions & 0 deletions
94
x-pack/plugins/security/public/components/confirm_modal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React, { FunctionComponent } from 'react'; | ||
import { | ||
EuiButton, | ||
EuiButtonProps, | ||
EuiButtonEmpty, | ||
EuiFlexGroup, | ||
EuiFlexItem, | ||
EuiModal, | ||
EuiModalBody, | ||
EuiModalFooter, | ||
EuiModalHeader, | ||
EuiModalHeaderTitle, | ||
EuiModalProps, | ||
EuiOverlayMask, | ||
} from '@elastic/eui'; | ||
import { FormattedMessage } from '@kbn/i18n/react'; | ||
|
||
export interface ConfirmModalProps extends Omit<EuiModalProps, 'onClose' | 'initialFocus'> { | ||
confirmButtonText: string; | ||
confirmButtonColor?: EuiButtonProps['color']; | ||
isLoading?: EuiButtonProps['isLoading']; | ||
isDisabled?: EuiButtonProps['isDisabled']; | ||
onCancel(): void; | ||
onConfirm(): void; | ||
ownFocus?: boolean; | ||
} | ||
|
||
/** | ||
* Component that renders a confirmation modal similar to `EuiConfirmModal`, except that | ||
* it adds `isLoading` prop, which renders a loading spinner and disables action buttons, | ||
* and `ownFocus` prop to render overlay mask. | ||
*/ | ||
export const ConfirmModal: FunctionComponent<ConfirmModalProps> = ({ | ||
children, | ||
confirmButtonColor: buttonColor, | ||
confirmButtonText, | ||
isLoading, | ||
isDisabled, | ||
onCancel, | ||
onConfirm, | ||
ownFocus = true, | ||
title, | ||
...rest | ||
}) => { | ||
const modal = ( | ||
<EuiModal role="dialog" title={title} onClose={onCancel} {...rest}> | ||
<EuiModalHeader> | ||
<EuiModalHeaderTitle>{title}</EuiModalHeaderTitle> | ||
</EuiModalHeader> | ||
<EuiModalBody data-test-subj="confirmModalBodyText">{children}</EuiModalBody> | ||
<EuiModalFooter> | ||
<EuiFlexGroup justifyContent="flexEnd"> | ||
<EuiFlexItem grow={false}> | ||
<EuiButtonEmpty | ||
data-test-subj="confirmModalCancelButton" | ||
flush="right" | ||
isDisabled={isLoading} | ||
onClick={onCancel} | ||
> | ||
<FormattedMessage | ||
id="xpack.security.confirmModal.cancelButton" | ||
defaultMessage="Cancel" | ||
/> | ||
</EuiButtonEmpty> | ||
</EuiFlexItem> | ||
<EuiFlexItem grow={false}> | ||
<EuiButton | ||
data-test-subj="confirmModalConfirmButton" | ||
color={buttonColor} | ||
fill | ||
isLoading={isLoading} | ||
isDisabled={isDisabled} | ||
onClick={onConfirm} | ||
> | ||
{confirmButtonText} | ||
</EuiButton> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiModalFooter> | ||
</EuiModal> | ||
); | ||
|
||
return ownFocus ? ( | ||
<EuiOverlayMask onClick={!isLoading ? onCancel : undefined}>{modal}</EuiOverlayMask> | ||
) : ( | ||
modal | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import React, { useCallback, FunctionComponent } from 'react'; | ||
import { EuiLink } from '@elastic/eui'; | ||
import { useKibana } from '../../../../../src/plugins/kibana_react/public'; | ||
import { CoreStart } from '../../../../../src/core/public'; | ||
|
||
export type DocLinks = CoreStart['docLinks']['links']; | ||
export type GetDocLinkFunction = (app: string, doc: string) => string; | ||
|
||
/** | ||
* Creates links to the documentation. | ||
* | ||
* @see {@link DocLink} for a component that creates a link to the docs. | ||
* | ||
* @example | ||
* ```typescript | ||
* <DocLink app="elasticsearch" doc="built-in-roles.html"> | ||
* Learn what privileges individual roles grant. | ||
* </DocLink> | ||
* ``` | ||
* | ||
* @example | ||
* ```typescript | ||
* const [docs] = useDocLinks(); | ||
* | ||
* <EuiLink href={docs.dashboard.guide} target="_blank" external> | ||
* Learn how to get started with dashboards. | ||
* </EuiLink> | ||
* ``` | ||
*/ | ||
export function useDocLinks(): [DocLinks, GetDocLinkFunction] { | ||
const { services } = useKibana(); | ||
const { links, ELASTIC_WEBSITE_URL, DOC_LINK_VERSION } = services.docLinks!; | ||
const getDocLink = useCallback<GetDocLinkFunction>( | ||
(app, doc) => { | ||
return `${ELASTIC_WEBSITE_URL}guide/en/${app}/reference/${DOC_LINK_VERSION}/${doc}`; | ||
}, | ||
[ELASTIC_WEBSITE_URL, DOC_LINK_VERSION] | ||
); | ||
return [links, getDocLink]; | ||
} | ||
|
||
export interface DocLinkProps { | ||
app: string; | ||
doc: string; | ||
} | ||
|
||
export const DocLink: FunctionComponent<DocLinkProps> = ({ app, doc, children }) => { | ||
const [, getDocLink] = useDocLinks(); | ||
return ( | ||
<EuiLink href={getDocLink(app, doc)} target="_blank" external> | ||
{children} | ||
</EuiLink> | ||
); | ||
}; |
Oops, something went wrong.