Skip to content

Commit

Permalink
Merge branch 'master' into fleet-sort-imports
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Mar 1, 2021
2 parents 05d51bf + 31041af commit 30fba48
Show file tree
Hide file tree
Showing 293 changed files with 3,098 additions and 1,775 deletions.
4 changes: 2 additions & 2 deletions docs/user/dashboard/drilldowns.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ that shows a single data center or server.
[[url-drilldowns]]
==== URL drilldowns

beta[] URL drilldowns enable you to navigate from a dashboard to internal or external URLs.
URL drilldowns enable you to navigate from a dashboard to internal or external URLs.
Destination URLs can be dynamic, depending on the dashboard context or user interaction with a panel.
For example, if you have a dashboard that shows data from a Github repository, you can create a URL drilldown
that opens Github from the dashboard.
Expand Down Expand Up @@ -226,7 +226,7 @@ and date range are carried over.
[[create-a-url-drilldown]]
=== Try it: Create a URL drilldown

beta[] To create URL drilldowns, you add <<variables,variables>> to a URL template, which configures the bahavior of the drilldown.
To create URL drilldowns, you add <<variables,variables>> to a URL template, which configures the behavior of the drilldown.

image:images/url_drilldown_go_to_github.gif[Drilldown on pie chart that navigates to Github]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,20 @@ import { Query } from '@elastic/eui';
import { parse } from 'query-string';
import { i18n } from '@kbn/i18n';
import { CoreStart, ChromeBreadcrumb } from 'src/core/public';
import type {
SpacesAvailableStartContract,
SpacesContextProps,
} from 'src/plugins/spaces_oss/public';
import { DataPublicPluginStart } from '../../../data/public';
import { SavedObjectsTaggingApi } from '../../../saved_objects_tagging_oss/public';
import type { SpacesAvailableStartContract } from '../../../spaces_oss/public';
import {
ISavedObjectsManagementServiceRegistry,
SavedObjectsManagementActionServiceStart,
SavedObjectsManagementColumnServiceStart,
} from '../services';
import { SavedObjectsTable } from './objects_table';

const EmptyFunctionComponent: React.FC = ({ children }) => <>{children}</>;
const getEmptyFunctionComponent: React.FC<SpacesContextProps> = ({ children }) => <>{children}</>;

const SavedObjectsTablePage = ({
coreStart,
Expand Down Expand Up @@ -71,7 +74,8 @@ const SavedObjectsTablePage = ({
}, [setBreadcrumbs]);

const ContextWrapper = useMemo(
() => spacesApi?.ui.components.SpacesContext || EmptyFunctionComponent,
() =>
spacesApi ? spacesApi.ui.components.getSpacesContextProvider : getEmptyFunctionComponent,
[spacesApi]
);

Expand Down
9 changes: 5 additions & 4 deletions src/plugins/spaces_oss/public/api.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,11 @@ type SpacesApiUiComponentMock = jest.Mocked<SpacesApiUiComponent>;

const createApiUiComponentsMock = () => {
const mock: SpacesApiUiComponentMock = {
SpacesContext: jest.fn(),
ShareToSpaceFlyout: jest.fn(),
SpaceList: jest.fn(),
LegacyUrlConflict: jest.fn(),
getSpacesContextProvider: jest.fn(),
getShareToSpaceFlyout: jest.fn(),
getSpaceList: jest.fn(),
getLegacyUrlConflict: jest.fn(),
getSpaceAvatar: jest.fn(),
};

return mock;
Expand Down
38 changes: 32 additions & 6 deletions src/plugins/spaces_oss/public/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import { Observable } from 'rxjs';
import type { FunctionComponent } from 'react';
import type { ReactElement } from 'react';
import { Space } from '../common';

/**
Expand All @@ -22,12 +22,19 @@ export interface SpacesApi {
ui: SpacesApiUi;
}

/**
* Function that returns a promise for a lazy-loadable component.
*
* @public
*/
export type LazyComponentFn<T> = (props: T) => ReactElement;

/**
* @public
*/
export interface SpacesApiUi {
/**
* {@link SpacesApiUiComponent | React components} to support the spaces feature.
* Lazy-loadable {@link SpacesApiUiComponent | React components} to support the spaces feature.
*/
components: SpacesApiUiComponent;
/**
Expand Down Expand Up @@ -62,13 +69,13 @@ export interface SpacesApiUiComponent {
/**
* Provides a context that is required to render some Spaces components.
*/
SpacesContext: FunctionComponent<SpacesContextProps>;
getSpacesContextProvider: LazyComponentFn<SpacesContextProps>;
/**
* Displays a flyout to edit the spaces that an object is shared to.
*
* Note: must be rendered inside of a SpacesContext.
*/
ShareToSpaceFlyout: FunctionComponent<ShareToSpaceFlyoutProps>;
getShareToSpaceFlyout: LazyComponentFn<ShareToSpaceFlyoutProps>;
/**
* Displays a corresponding list of spaces for a given list of saved object namespaces. It shows up to five spaces (and an indicator for
* any number of spaces that the user is not authorized to see) by default. If more than five named spaces would be displayed, the extras
Expand All @@ -77,7 +84,7 @@ export interface SpacesApiUiComponent {
*
* Note: must be rendered inside of a SpacesContext.
*/
SpaceList: FunctionComponent<SpaceListProps>;
getSpaceList: LazyComponentFn<SpaceListProps>;
/**
* Displays a callout that needs to be used if a call to `SavedObjectsClient.resolve()` results in an `"conflict"` outcome, which
* indicates that the user has loaded the page which is associated directly with one object (A), *and* with a legacy URL that points to a
Expand All @@ -95,7 +102,11 @@ export interface SpacesApiUiComponent {
*
* New URL path: `#/workpad/workpad-e08b9bdb-ec14-4339-94c4-063bddfd610e/page/1`
*/
LegacyUrlConflict: FunctionComponent<LegacyUrlConflictProps>;
getLegacyUrlConflict: LazyComponentFn<LegacyUrlConflictProps>;
/**
* Displays an avatar for the given space.
*/
getSpaceAvatar: LazyComponentFn<SpaceAvatarProps>;
}

/**
Expand Down Expand Up @@ -251,3 +262,18 @@ export interface LegacyUrlConflictProps {
*/
otherObjectPath: string;
}

/**
* @public
*/
export interface SpaceAvatarProps {
space: Partial<Space>;
size?: 's' | 'm' | 'l' | 'xl';
className?: string;
/**
* When enabled, allows EUI to provide an aria-label for this component, which is announced on screen readers.
*
* Default value is true.
*/
announceSpaceName?: boolean;
}
2 changes: 2 additions & 0 deletions src/plugins/spaces_oss/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export {
} from './types';

export {
LazyComponentFn,
SpacesApi,
SpacesApiUi,
SpacesApiUiComponent,
Expand All @@ -24,6 +25,7 @@ export {
ShareToSpaceSavedObjectTarget,
SpaceListProps,
LegacyUrlConflictProps,
SpaceAvatarProps,
} from './api';

export const plugin = () => new SpacesOssPlugin();
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export { NumberInputOption } from './number_input';
export { RangeOption } from './range';
export { RequiredNumberInputOption } from './required_number_input';
export { TextInputOption } from './text_input';
export { PercentageModeOption } from './percentage_mode';
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { mountWithIntl } from '@kbn/test/jest';
import { PercentageModeOption, PercentageModeOptionProps } from './percentage_mode';
import { EuiFieldText } from '@elastic/eui';

describe('PercentageModeOption', () => {
let props: PercentageModeOptionProps;
let component;
beforeAll(() => {
props = {
percentageMode: true,
setValue: jest.fn(),
};
});

it('renders the EuiFieldText', () => {
component = mountWithIntl(<PercentageModeOption {...props} />);
expect(component.find(EuiFieldText).length).toBe(1);
});

it('should call setValue when value was putted in fieldText', () => {
component = mountWithIntl(<PercentageModeOption {...props} />);
const fieldText = component.find(EuiFieldText);
fieldText.props().onChange!({
target: {
value: '0.0%',
},
} as React.ChangeEvent<HTMLInputElement>);

expect(props.setValue).toHaveBeenCalledWith('percentageFormatPattern', '0.0%');
});

it('fieldText should be disabled when percentageMode is false', () => {
props.percentageMode = false;
component = mountWithIntl(<PercentageModeOption {...props} />);
const fieldText = component.find(EuiFieldText);

expect(fieldText.props().disabled).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import React from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiFieldText, EuiFormRow, EuiLink } from '@elastic/eui';
import { SwitchOption } from './switch';
import { useKibana } from '../../../../kibana_react/public';
import { UI_SETTINGS } from '../../../../data/public';

export interface PercentageModeOptionProps {
setValue: (
paramName: 'percentageMode' | 'percentageFormatPattern',
value: boolean | string | undefined
) => void;
percentageMode: boolean;
formatPattern?: string;
'data-test-subj'?: string;
}

function PercentageModeOption({
'data-test-subj': dataTestSubj,
setValue,
percentageMode,
formatPattern,
}: PercentageModeOptionProps) {
const { services } = useKibana();
const defaultPattern = services.uiSettings?.get(UI_SETTINGS.FORMAT_PERCENT_DEFAULT_PATTERN);

return (
<>
<SwitchOption
data-test-subj={dataTestSubj}
label={i18n.translate('visDefaultEditor.options.percentageMode.percentageModeLabel', {
defaultMessage: 'Percentage mode',
})}
paramName="percentageMode"
value={percentageMode}
setValue={setValue}
/>
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="visDefaultEditor.options.percentageMode.numeralLabel"
defaultMessage="Format pattern"
/>
}
helpText={
<EuiLink target="_blank" href="https://adamwdraper.github.io/Numeral-js/">
<FormattedMessage
id="visDefaultEditor.options.percentageMode.documentationLabel"
defaultMessage="Numeral.js documentation"
/>
</EuiLink>
}
>
<EuiFieldText
fullWidth
compressed
data-test-subj={`${dataTestSubj}FormatPattern`}
value={formatPattern || ''}
placeholder={defaultPattern}
onChange={(e) => {
setValue('percentageFormatPattern', e.target.value ? e.target.value : undefined);
}}
disabled={!percentageMode}
/>
</EuiFormRow>
</>
);
}

export { PercentageModeOption };
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
SetColorSchemaOptionsValue,
ColorSchemaOptions,
RangeOption,
PercentageModeOption,
} from '../../../vis_default_editor/public';
import { ColorMode, colorSchemas } from '../../../charts/public';
import { MetricVisParam, VisParams } from '../types';
Expand Down Expand Up @@ -113,12 +114,10 @@ function MetricVisOptions({
</EuiTitle>
<EuiSpacer size="s" />

<SwitchOption
label={i18n.translate('visTypeMetric.params.percentageModeLabel', {
defaultMessage: 'Percentage mode',
})}
paramName="percentageMode"
value={stateParams.metric.percentageMode}
<PercentageModeOption
data-test-subj="metricPercentageMode"
percentageMode={stateParams.metric.percentageMode}
formatPattern={stateParams.metric.percentageFormatPattern}
setValue={setMetricValue}
/>

Expand Down
6 changes: 5 additions & 1 deletion src/plugins/vis_type_metric/public/to_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const toExpressionAst: VisToExpressionAst<VisParams> = (vis, params) => {

const {
percentageMode,
percentageFormatPattern,
useRanges,
colorSchema,
metricColorMode,
Expand All @@ -55,7 +56,10 @@ export const toExpressionAst: VisToExpressionAst<VisParams> = (vis, params) => {
// fix formatter for percentage mode
if (get(vis.params, 'metric.percentageMode') === true) {
schemas.metric.forEach((metric: SchemaConfig) => {
metric.format = { id: 'percent' };
metric.format = {
id: 'percent',
params: { pattern: percentageFormatPattern },
};
});
}

Expand Down
1 change: 1 addition & 0 deletions src/plugins/vis_type_metric/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface DimensionsVisParam {

export interface MetricVisParam {
percentageMode: boolean;
percentageFormatPattern?: string;
useRanges: boolean;
colorSchema: ColorSchemas;
metricColorMode: ColorMode;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
SetColorRangeValue,
SwitchOption,
ColorSchemaOptions,
PercentageModeOption,
} from '../../../../../vis_default_editor/public';
import { ColorSchemaParams, ColorSchemas, colorSchemas } from '../../../../../charts/public';
import { GaugeOptionsInternalProps } from '../gauge';
Expand Down Expand Up @@ -77,13 +78,10 @@ function RangesPanel({
setValue={setGaugeValue}
/>

<SwitchOption
<PercentageModeOption
data-test-subj="gaugePercentageMode"
label={i18n.translate('visTypeVislib.controls.gaugeOptions.percentageModeLabel', {
defaultMessage: 'Percentage mode',
})}
paramName="percentageMode"
value={stateParams.gauge.percentageMode}
percentageMode={stateParams.gauge.percentageMode}
formatPattern={stateParams.gauge.percentageFormatPattern}
setValue={setGaugeValue}
/>

Expand Down
Loading

0 comments on commit 30fba48

Please sign in to comment.