Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into issue-move-autocomp…
Browse files Browse the repository at this point in the history
…lete-to-unified-search
  • Loading branch information
nlatipov committed Apr 20, 2022
2 parents 158ca32 + 9d6aa99 commit 596caeb
Show file tree
Hide file tree
Showing 51 changed files with 1,647 additions and 7,499 deletions.
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ x-pack/plugins/security_solution/public/common/components/sessions_viewer @elast
/x-pack/plugins/osquery @elastic/security-asset-management

# Cloud Security Posture
/x-pack/plugins/cloud_security_posture/ @elastic/cloud-security-posture-control-plane
/x-pack/plugins/cloud_security_posture/ @elastic/kibana-cloud-security-posture

# Design (at the bottom for specificity of SASS files)
**/*.scss @elastic/kibana-design
Expand Down
4 changes: 2 additions & 2 deletions docs/user/reporting/index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ You access the options from the *Share* menu in the toolbar. The sharing options
* *Embed code* — Embed a fully interactive dashboard or visualization as an iframe on a web page.

[[reporting-on-cloud-resource-requirements]]
NOTE: On Elastic Cloud, Kibana requires a minimum of 2GB RAM to generate PDF or PNG reports. To edit Kibana deployments,
use {ess-console}[Cloud Management].
NOTE: For Elastic Cloud deployments, Kibana instances require a minimum of 2GB RAM to generate PDF or PNG reports. To
change Kibana sizing, {ess-console}[edit the deployment].

[float]
[[manually-generate-reports]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
EuiCallOut,
EuiFlexGroup,
EuiFlexItem,
EuiLink,
useEuiTheme,
} from '@elastic/eui';
import { css } from '@emotion/react';
Expand Down Expand Up @@ -60,40 +61,48 @@ export const DocumentExplorerUpdateCallout = () => {
<EuiCallOut
className="dscDocumentExplorerCallout"
title={<CalloutTitle onCloseCallout={onCloseCallout} />}
iconType="search"
iconType="tableDensityNormal"
heading="h3"
size="s"
>
<p>
<FormattedMessage
id="discover.docExplorerUpdateCallout.bodyMessage"
defaultMessage="Experience the new {documentExplorer}. Understand the shape of your data with {fieldStatistics}."
defaultMessage="Perform multi-column sorting, resize columns, set row height, and view data in fullscreen with the {documentExplorer}.
Learn more about the structure of your data with {fieldStatistics}."
values={{
fieldStatistics: (
<span css={semiBoldStyle}>
<FormattedMessage
id="discover.docExplorerUpdateCallout.fieldStatistics"
defaultMessage="Field Statistics"
/>
</span>
<EuiLink href={docLinks.links.discover.fieldStatistics} external>
<span css={semiBoldStyle}>
<FormattedMessage
id="discover.docExplorerUpdateCallout.fieldStatistics"
defaultMessage="field statistics"
/>
</span>
</EuiLink>
),
documentExplorer: (
<span css={semiBoldStyle}>
<FormattedMessage
id="discover.docExplorerUpdateCallout.documentExplorer"
defaultMessage="Document Explorer"
/>
</span>
<EuiLink href={docLinks.links.discover.documentExplorer} external>
<span css={semiBoldStyle}>
<FormattedMessage
id="discover.docExplorerUpdateCallout.documentExplorer"
defaultMessage="new document table"
/>
</span>
</EuiLink>
),
}}
/>
</p>
<EuiButton
iconType="tableDensityNormal"
data-test-subj="document-explorer-update-callout-dismiss-button"
iconType="check"
size="s"
href={docLinks.links.discover.documentExplorer}
onClick={onCloseCallout}
>
<FormattedMessage
id="discover.docExplorerUpdateCallout.learnMore"
defaultMessage="Learn more"
id="discover.docExplorerUpdateCallout.dismissButtonLabel"
defaultMessage="Got it"
/>
</EuiButton>
</EuiCallOut>
Expand All @@ -106,7 +115,7 @@ function CalloutTitle({ onCloseCallout }: { onCloseCallout: () => void }) {
<EuiFlexItem grow={false}>
<FormattedMessage
id="discover.docExplorerUpdateCallout.headerMessage"
defaultMessage="A better way to explore"
defaultMessage="Exploring your data just got better"
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export const ComboBoxField = ({ field, euiFieldProps = {}, idAria, ...rest }: Pr

const onCreateComboOption = (value: string) => {
// Note: for now, all validations for a comboBox array item have to be synchronous
// If there is a need to support asynchronous validation, we'll work on it (and will need to update the <EuiComboBox /> logic).
// If there is a need to support asynchronous validation, we'll need to update this handler and
// make the <EuiComboBox /> "onCreateOption" handler async).
const { isValid } = field.validate({
value,
validationType: VALIDATION_TYPES.ARRAY_ITEM,
Expand Down Expand Up @@ -84,7 +85,7 @@ export const ComboBoxField = ({ field, euiFieldProps = {}, idAria, ...rest }: Pr
placeholder={i18n.translate('esUi.forms.comboBoxField.placeHolderText', {
defaultMessage: 'Type and then hit "ENTER"',
})}
selectedOptions={(field.value as any[]).map((v) => ({ label: v }))}
selectedOptions={(field.value as string[]).map((v) => ({ label: v }))}
onCreateOption={onCreateComboOption}
onChange={onComboChange}
onSearchChange={onSearchComboChange}
Expand Down
19 changes: 19 additions & 0 deletions src/plugins/es_ui_shared/static/forms/docs/core/form_hook.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -212,3 +212,22 @@ Sets field errors imperatively.
```js
form.setFieldErrors('name', [{ message: 'There is an error in the field' }]);
```
### updateFieldValues()
**Arguments:** `updatedFormData: Partial<T>, options?: { runDeserializer?: boolean }`
Update multiple field values at once. You don't need to provide all the form fields, **partial** update is supported. This method is mainly useful to update an array of object fields or to avoid multiple `form.setFieldValue()` calls.
```js
// Update an array of object (e.g "myArray[0].foo", "myArray[0].baz"...)
form.updateFieldValues({
myArray: [
{ foo: 'bar', baz: true },
{ foo2: 'bar2', baz: false }
]
});

// or simply multiple fields at once
form.updateFieldValues({ foo: 'bar', baz: false })
```
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,7 @@ describe('<UseArray />', () => {
<>
{items.map(({ id, path }) => {
return (
<UseField
key={id}
path={`${path}.name`}
data-test-subj={`nameField__${id}`}
/>
<UseField key={id} path={`${path}.name`} data-test-subj={`${path}Name`} />
);
})}
</>
Expand All @@ -102,7 +98,7 @@ describe('<UseArray />', () => {
} = setup();

await act(async () => {
setInputValue('nameField__0', 'John');
setInputValue('users[0]Name', 'John');
});

const formData = onFormData.mock.calls[onFormData.mock.calls.length - 1][0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* Side Public License, v 1.
*/

import uuid from 'uuid';
import { useEffect, useRef, useCallback, useMemo } from 'react';

import { FormHook, FieldConfig } from '../types';
Expand Down Expand Up @@ -37,6 +36,25 @@ export interface FormArrayField {
form: FormHook;
}

let uniqueId = 0;

export const createArrayItem = (path: string, index: number, isNew = true): ArrayItem => ({
id: uniqueId++,
path: `${path}[${index}]`,
isNew,
});

/**
* We create an internal field to represent the Array items. This field is not returned
* as part as the form data but is used internally to run validation on the array items.
* It is this internal field value (ArrayItem[]) that we then map to actual form fields
* (in the children func <UseArray>{({ items }) => (...)}</UseArray>)
*
* @param path The array path in the form data
* @returns The internal array field path
*/
export const getInternalArrayFieldPath = (path: string): string => `${path}__array__`;

/**
* Use UseArray to dynamically add fields to your form.
*
Expand All @@ -60,41 +78,26 @@ export const UseArray = ({
children,
}: Props) => {
const isMounted = useRef(false);
const uniqueId = useRef(0);

const form = useFormContext();
const { getFieldDefaultValue } = form;

const getNewItemAtIndex = useCallback(
(index: number): ArrayItem => ({
id: uniqueId.current++,
path: `${path}[${index}]`,
isNew: true,
}),
[path]
);

const fieldDefaultValue = useMemo<ArrayItem[]>(() => {
const defaultValues = readDefaultValueOnForm
? getFieldDefaultValue<unknown[]>(path)
: undefined;

if (defaultValues) {
return defaultValues.map((_, index) => ({
id: uniqueId.current++,
path: `${path}[${index}]`,
isNew: false,
}));
return defaultValues.map((_, index) => createArrayItem(path, index, false));
}

return new Array(initialNumberOfItems).fill('').map((_, i) => getNewItemAtIndex(i));
}, [path, initialNumberOfItems, readDefaultValueOnForm, getFieldDefaultValue, getNewItemAtIndex]);
return new Array(initialNumberOfItems).fill('').map((_, i) => createArrayItem(path, i));
}, [path, initialNumberOfItems, readDefaultValueOnForm, getFieldDefaultValue]);

// Create an internal hook field which behaves like any other form field except that it is not
// outputed in the form data (when calling form.submit() or form.getFormData())
// This allow us to run custom validations (passed to the props) on the Array items

const internalFieldPath = useMemo(() => `${path}__${uuid.v4()}`, [path]);
const internalFieldPath = useMemo(() => getInternalArrayFieldPath(path), [path]);

const fieldConfigBase: FieldConfig<ArrayItem[]> & InternalFieldConfig<ArrayItem[]> = {
defaultValue: fieldDefaultValue,
Expand Down Expand Up @@ -132,9 +135,9 @@ export const UseArray = ({
const addItem = useCallback(() => {
setValue((previousItems) => {
const itemIndex = previousItems.length;
return [...previousItems, getNewItemAtIndex(itemIndex)];
return [...previousItems, createArrayItem(path, itemIndex)];
});
}, [setValue, getNewItemAtIndex]);
}, [setValue, path]);

const removeItem = useCallback(
(id: number) => {
Expand Down
Loading

0 comments on commit 596caeb

Please sign in to comment.