Skip to content

Commit

Permalink
[Index template] Add filters to simulate preview (#74497)
Browse files Browse the repository at this point in the history
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
sebelga and elasticmachine authored Aug 19, 2020
1 parent 87414ad commit 53c765e
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ $heightHeader: $euiSizeL * 2;

.componentTemplates {
border: $euiBorderThin;
border-radius: $euiBorderRadius;
border-top: none;
height: 100%;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,31 @@

&__selection {
border: $euiBorderThin;
border-radius: $euiBorderRadius;

padding: 0 $euiSize $euiSize;
color: $euiColorDarkShade;
padding: 0 $euiSize $euiSize;
color: $euiColorDarkShade;

&--is-empty {
align-items: center;
justify-content: center;
}
&--is-empty {
align-items: center;
justify-content: center;
}

&__header {
background-color: $euiColorLightestShade;
border-bottom: $euiBorderThin;
color: $euiColorInk;
height: $euiSizeXXL; // [1]
line-height: $euiSizeXXL; // [1]
font-size: $euiSizeM;
margin-bottom: $euiSizeS;
margin-left: $euiSize * -1;
margin-right: $euiSize * -1;
padding-left: $euiSize;
&__header {
background-color: $euiColorLightestShade;
border-bottom: $euiBorderThin;
color: $euiColorInk;
height: $euiSizeXXL; // [1]
line-height: $euiSizeXXL; // [1]
font-size: $euiSizeM;
margin-bottom: $euiSizeS;
margin-left: $euiSize * -1;
margin-right: $euiSize * -1;
padding-left: $euiSize;

&__count {
font-weight: 600;
}
&__count {
font-weight: 600;
}
}

&__content {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,12 +200,19 @@ export const ComponentTemplatesSelector = ({
</div>
</>
) : (
<div>
<FormattedMessage
id="xpack.idxMgmt.componentTemplatesSelector.noComponentSelectedLabel"
defaultMessage="No component template selected."
/>
</div>
<EuiText textAlign="center">
<p>
<FormattedMessage
id="xpack.idxMgmt.componentTemplatesSelector.noComponentSelectedLabel-1"
defaultMessage="Add component template building blocks to this template."
/>
<br />
<FormattedMessage
id="xpack.idxMgmt.componentTemplatesSelector.noComponentSelectedLabel-2"
defaultMessage="Component templates are applied in the order specified."
/>
</p>
</EuiText>
)}
</EuiFlexItem>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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.
*/
export {
useForm,
Form,
getUseField,
FormDataProvider,
} from '../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';

export { CheckBoxField } from '../../../../../../../src/plugins/es_ui_shared/static/forms/components';
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ export {
Props as SimulateTemplateProps,
} from './simulate_template_flyout';

export { SimulateTemplate } from './simulate_template';
export { SimulateTemplate, Filters as SimulateTemplateFilters } from './simulate_template';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
*/
import React, { useState, useCallback, useEffect } from 'react';
import uuid from 'uuid';
import { EuiCodeBlock } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiCodeBlock, EuiCallOut } from '@elastic/eui';

import { serializers } from '../../../../shared_imports';
import { TemplateDeserialized } from '../../../../../common';
Expand All @@ -14,12 +15,18 @@ import { simulateIndexTemplate } from '../../../services';

const { stripEmptyFields } = serializers;

export interface Filters {
mappings: boolean;
settings: boolean;
aliases: boolean;
}

interface Props {
template: { [key: string]: any };
minHeightCodeBlock?: string;
filters?: Filters;
}

export const SimulateTemplate = React.memo(({ template, minHeightCodeBlock }: Props) => {
export const SimulateTemplate = React.memo(({ template, filters }: Props) => {
const [templatePreview, setTemplatePreview] = useState('{}');

const updatePreview = useCallback(async () => {
Expand All @@ -34,26 +41,60 @@ export const SimulateTemplate = React.memo(({ template, minHeightCodeBlock }: Pr
indexTemplate.index_patterns = [uuid.v4()];

const { data, error } = await simulateIndexTemplate(indexTemplate);
let filteredTemplate = data;

if (data) {
// "Overlapping" info is only useful when simulating against an index
// which we don't do here.
delete data.overlapping;

if (data.template && data.template.mappings === undefined) {
// Adding some extra logic to return an empty object for "mappings" as ES does not
// return one in that case (empty objects _are_ returned for "settings" and "aliases")
// Issue: https://github.com/elastic/elasticsearch/issues/60968
data.template.mappings = {};
}

if (filters) {
filteredTemplate = Object.entries(filters).reduce(
(acc, [key, value]) => {
if (!value) {
delete acc[key];
}
return acc;
},
{ ...data.template } as any
);
}
}

setTemplatePreview(JSON.stringify(data ?? error, null, 2));
}, [template]);
setTemplatePreview(JSON.stringify(filteredTemplate ?? error, null, 2));
}, [template, filters]);

useEffect(() => {
updatePreview();
}, [updatePreview]);

return templatePreview === '{}' ? null : (
<EuiCodeBlock
style={{ minHeight: minHeightCodeBlock }}
lang="json"
data-test-subj="simulateTemplatePreview"
>
const isEmpty = templatePreview === '{}';
const hasFilters = Boolean(filters);

if (isEmpty && hasFilters) {
return (
<EuiCallOut
title={
<FormattedMessage
id="xpack.idxMgmt.simulateTemplate.noFilterSelected"
defaultMessage="Select at least one option to preview."
/>
}
iconType="pin"
size="s"
/>
);
}

return isEmpty ? null : (
<EuiCodeBlock lang="json" data-test-subj="simulateTemplatePreview">
{templatePreview}
</EuiCodeBlock>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
import React, { useState, useCallback, useEffect, useRef } from 'react';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import {
EuiFlyoutHeader,
EuiTitle,
Expand All @@ -19,28 +20,56 @@ import {
EuiSpacer,
} from '@elastic/eui';

import { SimulateTemplate } from './simulate_template';
import { useForm, Form, getUseField, CheckBoxField, FormDataProvider } from '../shared_imports';
import { SimulateTemplate, Filters } from './simulate_template';

const CheckBox = getUseField({ component: CheckBoxField });

export interface Props {
onClose(): void;
getTemplate: () => { [key: string]: any };
filters: Filters;
onFiltersChange: (filters: Filters) => void;
}

export const defaultFlyoutProps = {
'data-test-subj': 'simulateTemplateFlyout',
'aria-labelledby': 'simulateTemplateFlyoutTitle',
};

export const SimulateTemplateFlyoutContent = ({ onClose, getTemplate }: Props) => {
const i18nTexts = {
filters: {
label: i18n.translate('xpack.idxMgmt.simulateTemplate.filters.label', {
defaultMessage: 'Include:',
}),
mappings: i18n.translate('xpack.idxMgmt.simulateTemplate.filters.mappings', {
defaultMessage: 'Mappings',
}),
indexSettings: i18n.translate('xpack.idxMgmt.simulateTemplate.filters.indexSettings', {
defaultMessage: 'Index settings',
}),
aliases: i18n.translate('xpack.idxMgmt.simulateTemplate.filters.aliases', {
defaultMessage: 'Aliases',
}),
},
};

export const SimulateTemplateFlyoutContent = ({
onClose,
getTemplate,
filters,
onFiltersChange,
}: Props) => {
const isMounted = useRef(false);
const [heightCodeBlock, setHeightCodeBlock] = useState(0);
const [template, setTemplate] = useState<{ [key: string]: any }>({});
const { form } = useForm<Filters>({ defaultValue: filters });
const { subscribe } = form;

useEffect(() => {
setHeightCodeBlock(
document.getElementsByClassName('euiFlyoutBody__overflow')[0].clientHeight - 96
);
}, []);
subscribe((formState) => {
onFiltersChange(formState.data.format());
});
}, [subscribe, onFiltersChange]);

const updatePreview = useCallback(async () => {
const indexTemplate = await getTemplate();
Expand Down Expand Up @@ -71,16 +100,37 @@ export const SimulateTemplateFlyoutContent = ({ onClose, getTemplate }: Props) =
<p>
<FormattedMessage
id="xpack.idxMgmt.simulateTemplate.descriptionText"
defaultMessage="This is the final template that will be applied to your indices based on the
components templates you have selected and any overrides you've added."
defaultMessage="This is the final template that will be applied to matching indices based on the
component templates you have selected and any overrides you've added."
/>
</p>
</EuiText>
</EuiTextColor>
</EuiFlyoutHeader>

<EuiFlyoutBody data-test-subj="content">
<SimulateTemplate template={template} minHeightCodeBlock={`${heightCodeBlock}px`} />
<Form form={form}>
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={false}>{i18nTexts.filters.label}</EuiFlexItem>
<EuiFlexItem grow={false}>
<CheckBox path="mappings" config={{ label: i18nTexts.filters.mappings }} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<CheckBox path="settings" config={{ label: i18nTexts.filters.indexSettings }} />
</EuiFlexItem>
<EuiFlexItem grow={false}>
<CheckBox path="aliases" config={{ label: i18nTexts.filters.aliases }} />
</EuiFlexItem>
</EuiFlexGroup>

<EuiSpacer />

<FormDataProvider>
{(formData) => {
return <SimulateTemplate template={template} filters={formData as Filters} />;
}}
</FormDataProvider>
</Form>
</EuiFlyoutBody>

<EuiFlyoutFooter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const i18nTexts = {
description: (
<FormattedMessage
id="xpack.idxMgmt.formWizard.stepComponents.componentsDescription"
defaultMessage="Components templates let you save index settings, mappings and aliases and inherit from them in index templates."
defaultMessage="Component templates let you save index settings, mappings and aliases and inherit from them in index templates."
/>
),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const PreviewTab = ({ template }: { template: { [key: string]: any } }) => {
<p>
<FormattedMessage
id="xpack.idxMgmt.templateForm.stepReview.previewTab.descriptionText"
defaultMessage="This is the final template that will be applied to your indices."
defaultMessage="This is the final template that will be applied to matching indices. Component templates are applied in the order specified. Explicit mappings, settings, and aliases override the component templates."
/>
</p>
</EuiText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* 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, { useState, useCallback } from 'react';
import React, { useState, useCallback, useRef } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiSpacer, EuiButton } from '@elastic/eui';
Expand All @@ -15,6 +15,7 @@ import {
SimulateTemplateFlyoutContent,
SimulateTemplateProps,
simulateTemplateFlyoutProps,
SimulateTemplateFilters,
} from '../index_templates';
import { StepLogisticsContainer, StepComponentContainer, StepReviewContainer } from './steps';
import {
Expand Down Expand Up @@ -98,6 +99,11 @@ export const TemplateForm = ({
}: Props) => {
const [wizardContent, setWizardContent] = useState<Forms.Content<WizardContent> | null>(null);
const { addContent: addContentToGlobalFlyout, closeFlyout } = useGlobalFlyout();
const simulateTemplateFilters = useRef<SimulateTemplateFilters>({
mappings: true,
settings: true,
aliases: true,
});

const indexTemplate = defaultValue ?? {
name: '',
Expand Down Expand Up @@ -234,13 +240,19 @@ export const TemplateForm = ({
return template;
}, [buildTemplateObject, indexTemplate, wizardContent]);

const onSimulateTemplateFiltersChange = useCallback((filters: SimulateTemplateFilters) => {
simulateTemplateFilters.current = filters;
}, []);

const showPreviewFlyout = () => {
addContentToGlobalFlyout<SimulateTemplateProps>({
id: 'simulateTemplate',
Component: SimulateTemplateFlyoutContent,
props: {
getTemplate: getSimulateTemplate,
onClose: closeFlyout,
filters: simulateTemplateFilters.current,
onFiltersChange: onSimulateTemplateFiltersChange,
},
flyoutProps: simulateTemplateFlyoutProps,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const TabPreview = ({ templateDetails }: Props) => {
<p>
<FormattedMessage
id="xpack.idxMgmt.templateDetails.previewTab.descriptionText"
defaultMessage="This is the final template that will be applied to your indices."
defaultMessage="This is the final template that will be applied to matching indices."
/>
</p>
</EuiText>
Expand Down
Loading

0 comments on commit 53c765e

Please sign in to comment.