if the editor is not visible
-
)}
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_form/steps/step_logistics_schema.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_form/steps/step_logistics_schema.tsx
index 0c52037abde45..c577957339487 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_form/steps/step_logistics_schema.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_wizard/component_template_form/steps/step_logistics_schema.tsx
@@ -65,7 +65,7 @@ export const logisticsFormSchema: FormSchema = {
},
_meta: {
label: i18n.translate('xpack.idxMgmt.componentTemplateForm.stepLogistics.metaFieldLabel', {
- defaultMessage: 'Metadata (optional)',
+ defaultMessage: '_meta field data (optional)',
}),
helpText: (
- Object.keys(json).length ? JSON.stringify(json, null, 2) : '{\n\n}';
-
const formSerializer: SerializerFunc = (formData) => {
const {
dynamicMapping: {
@@ -40,22 +37,17 @@ const formSerializer: SerializerFunc = (formData) => {
const dynamic = dynamicMappingsEnabled ? true : throwErrorsForUnmappedFields ? 'strict' : false;
- let parsedMeta;
- try {
- parsedMeta = JSON.parse(metaField);
- } catch {
- parsedMeta = {};
- }
-
- return {
+ const serialized = {
dynamic,
numeric_detection,
date_detection,
dynamic_date_formats,
- _source: { ...sourceField },
- _meta: parsedMeta,
+ _source: sourceField,
+ _meta: metaField,
_routing,
};
+
+ return serialized;
};
const formDeserializer = (formData: GenericObject) => {
@@ -64,7 +56,11 @@ const formDeserializer = (formData: GenericObject) => {
numeric_detection,
date_detection,
dynamic_date_formats,
- _source: { enabled, includes, excludes },
+ _source: { enabled, includes, excludes } = {} as {
+ enabled?: boolean;
+ includes?: string[];
+ excludes?: string[];
+ },
_meta,
_routing,
} = formData;
@@ -82,7 +78,7 @@ const formDeserializer = (formData: GenericObject) => {
includes,
excludes,
},
- metaField: stringifyJson(_meta),
+ metaField: _meta ?? {},
_routing,
};
};
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx
index c06340fd9ae14..6e80f8b813ec2 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/configuration_form/configuration_form_schema.tsx
@@ -48,10 +48,30 @@ export const configurationFormSchema: FormSchema = {
validator: isJsonField(
i18n.translate('xpack.idxMgmt.mappingsEditor.configuration.metaFieldEditorJsonError', {
defaultMessage: 'The _meta field JSON is not valid.',
- })
+ }),
+ { allowEmptyString: true }
),
},
],
+ deserializer: (value: any) => {
+ if (value === '') {
+ return value;
+ }
+ return JSON.stringify(value, null, 2);
+ },
+ serializer: (value: string) => {
+ try {
+ const parsed = JSON.parse(value);
+ // If an empty object was passed, strip out this value entirely.
+ if (!Object.keys(parsed).length) {
+ return undefined;
+ }
+ return parsed;
+ } catch (error) {
+ // swallow error and return non-parsed value;
+ return value;
+ }
+ },
},
sourceField: {
enabled: {
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form.tsx
index 80937e7da1192..79685d46b6bdd 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/components/templates_form/templates_form.tsx
@@ -22,7 +22,7 @@ interface Props {
const stringifyJson = (json: { [key: string]: any }) =>
Array.isArray(json) ? JSON.stringify(json, null, 2) : '[\n\n]';
-const formSerializer: SerializerFunc = (formData) => {
+const formSerializer: SerializerFunc = (formData) => {
const { dynamicTemplates } = formData;
let parsedTemplates;
@@ -34,12 +34,14 @@ const formSerializer: SerializerFunc = (formData) => {
parsedTemplates = [parsedTemplates];
}
} catch {
- parsedTemplates = [];
+ // Silently swallow errors
}
- return {
- dynamic_templates: parsedTemplates,
- };
+ return Array.isArray(parsedTemplates) && parsedTemplates.length > 0
+ ? {
+ dynamic_templates: parsedTemplates,
+ }
+ : undefined;
};
const formDeserializer = (formData: { [key: string]: any }) => {
@@ -53,7 +55,7 @@ const formDeserializer = (formData: { [key: string]: any }) => {
export const TemplatesForm = React.memo(({ value }: Props) => {
const isMounted = useRef(undefined);
- const { form } = useForm({
+ const { form } = useForm({
schema: templatesFormSchema,
serializer: formSerializer,
deserializer: formDeserializer,
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts
index e7c27cb413b53..2633dbfc0e40d 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/lib/utils.ts
@@ -198,7 +198,7 @@ export const getTypeMetaFromSource = (
*
* @param fieldsToNormalize The "properties" object from the mappings (or "fields" object for `text` and `keyword` types)
*/
-export const normalize = (fieldsToNormalize: Fields): NormalizedFields => {
+export const normalize = (fieldsToNormalize: Fields = {}): NormalizedFields => {
let maxNestedDepth = 0;
const normalizeFields = (
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx
index 077f839ee1cdf..d03b6949bf0a2 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_editor.tsx
@@ -39,14 +39,14 @@ export const MappingsEditor = React.memo(({ onChange, value, indexSettings }: Pr
}
const {
- _source = {},
- _meta = {},
+ _source,
+ _meta,
_routing,
dynamic,
numeric_detection,
date_detection,
dynamic_date_formats,
- properties = {},
+ properties,
dynamic_templates,
} = mappingsDefinition.mappings;
diff --git a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_state.tsx b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_state.tsx
index 5b899a341652d..f9d9e50f38756 100644
--- a/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_state.tsx
+++ b/x-pack/plugins/index_management/public/application/components/mappings_editor/mappings_state.tsx
@@ -19,7 +19,7 @@ import { normalize, deNormalize, stripUndefinedValues } from './lib';
type Mappings = MappingsTemplates &
MappingsConfiguration & {
- properties: MappingsFields;
+ properties?: MappingsFields;
};
export interface Types {
@@ -31,7 +31,7 @@ export interface Types {
export interface OnUpdateHandlerArg {
isValid?: boolean;
- getData: () => Mappings | { [key: string]: Mappings };
+ getData: () => Mappings | { [key: string]: Mappings } | undefined;
validate: () => Promise;
}
@@ -115,19 +115,26 @@ export const MappingsState = React.memo(({ children, onChange, value, mappingsTy
const configurationData = state.configuration.data.format();
const templatesData = state.templates.data.format();
- const mappings = {
+ const output = {
...stripUndefinedValues({
...configurationData,
...templatesData,
}),
- properties: fields,
- } as Mappings;
-
- return mappingsType === undefined
- ? mappings
- : {
- [mappingsType]: mappings,
- };
+ };
+
+ if (fields && Object.keys(fields).length > 0) {
+ output.properties = fields;
+ }
+
+ if (Object.keys(output).length > 0) {
+ return mappingsType === undefined
+ ? (output as Mappings)
+ : {
+ [mappingsType]: output as Mappings,
+ };
+ }
+
+ return undefined;
},
validate: async () => {
const configurationFormValidator =
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_components.tsx b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_components.tsx
index 01771f40f89ea..df0cc791384fe 100644
--- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_components.tsx
+++ b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_components.tsx
@@ -25,6 +25,12 @@ interface Props {
}
const i18nTexts = {
+ title: (
+
+ ),
description: (
{
- onChange({ isValid: true, validate: async () => true, getData: () => components });
+ onChange({
+ isValid: true,
+ validate: async () => true,
+ getData: () => (components.length > 0 ? components : undefined),
+ });
},
[onChange]
);
@@ -63,12 +73,7 @@ export const StepComponents = ({ defaultValue = [], onChange, esDocsBase }: Prop
-
-
-
+ {i18nTexts.title}
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx
index 44ec4db0873f3..2777941175429 100644
--- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx
+++ b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_logistics.tsx
@@ -4,7 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React, { useEffect } from 'react';
-import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiButtonEmpty, EuiSpacer } from '@elastic/eui';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiButtonEmpty,
+ EuiSpacer,
+ EuiLink,
+} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
@@ -16,6 +23,7 @@ import {
Field,
Forms,
JsonEditorField,
+ FormDataProvider,
} from '../../../../shared_imports';
import { documentationService } from '../../../services/documentation';
import { schemas, nameConfig, nameConfigWithoutValidations } from '../template_form_schemas';
@@ -24,70 +32,125 @@ import { schemas, nameConfig, nameConfigWithoutValidations } from '../template_f
const UseField = getUseField({ component: Field });
const FormRow = getFormRow({ titleTag: 'h3' });
-const fieldsMeta = {
- name: {
- title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.nameTitle', {
- defaultMessage: 'Name',
- }),
- description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.nameDescription', {
- defaultMessage: 'A unique identifier for this template.',
- }),
- testSubject: 'nameField',
- },
- indexPatterns: {
- title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.indexPatternsTitle', {
- defaultMessage: 'Index patterns',
- }),
- description: i18n.translate(
- 'xpack.idxMgmt.templateForm.stepLogistics.indexPatternsDescription',
- {
- defaultMessage: 'The index patterns to apply to the template.',
- }
- ),
- testSubject: 'indexPatternsField',
- },
- order: {
- title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.orderTitle', {
- defaultMessage: 'Merge order',
- }),
- description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.orderDescription', {
- defaultMessage: 'The merge order when multiple templates match an index.',
- }),
- testSubject: 'orderField',
- },
- priority: {
- title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.priorityTitle', {
- defaultMessage: 'Merge priority',
- }),
- description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.priorityDescription', {
- defaultMessage: 'The merge priority when multiple templates match an index.',
- }),
- testSubject: 'priorityField',
- },
- version: {
- title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.versionTitle', {
- defaultMessage: 'Version',
- }),
- description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.versionDescription', {
- defaultMessage: 'A number that identifies the template to external management systems.',
- }),
- testSubject: 'versionField',
- },
-};
+function getFieldsMeta(esDocsBase: string) {
+ return {
+ name: {
+ title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.nameTitle', {
+ defaultMessage: 'Name',
+ }),
+ description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.nameDescription', {
+ defaultMessage: 'A unique identifier for this template.',
+ }),
+ testSubject: 'nameField',
+ },
+ indexPatterns: {
+ title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.indexPatternsTitle', {
+ defaultMessage: 'Index patterns',
+ }),
+ description: i18n.translate(
+ 'xpack.idxMgmt.templateForm.stepLogistics.indexPatternsDescription',
+ {
+ defaultMessage: 'The index patterns to apply to the template.',
+ }
+ ),
+ testSubject: 'indexPatternsField',
+ },
+ dataStream: {
+ title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.dataStreamTitle', {
+ defaultMessage: 'Data stream',
+ }),
+ description: (
+
+
+
+ {i18n.translate(
+ 'xpack.idxMgmt.templateForm.stepLogistics.dataStreamDocumentionLink',
+ {
+ defaultMessage: 'Learn more about data streams.',
+ }
+ )}
+
+ >
+ ),
+ }}
+ />
+ ),
+ testSubject: 'dataStreamField',
+ },
+ order: {
+ title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.orderTitle', {
+ defaultMessage: 'Merge order',
+ }),
+ description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.orderDescription', {
+ defaultMessage: 'The merge order when multiple templates match an index.',
+ }),
+ testSubject: 'orderField',
+ },
+ priority: {
+ title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.priorityTitle', {
+ defaultMessage: 'Priority',
+ }),
+ description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.priorityDescription', {
+ defaultMessage: 'Only the highest priority template will be applied.',
+ }),
+ testSubject: 'priorityField',
+ },
+ version: {
+ title: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.versionTitle', {
+ defaultMessage: 'Version',
+ }),
+ description: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.versionDescription', {
+ defaultMessage: 'A number that identifies the template to external management systems.',
+ }),
+ testSubject: 'versionField',
+ },
+ };
+}
+
+interface LogisticsForm {
+ [key: string]: any;
+}
+
+interface LogisticsFormInternal extends LogisticsForm {
+ __internal__: {
+ addMeta: boolean;
+ };
+}
interface Props {
- defaultValue: { [key: string]: any };
+ defaultValue: LogisticsForm;
onChange: (content: Forms.Content) => void;
isEditing?: boolean;
isLegacy?: boolean;
}
+function formDeserializer(formData: LogisticsForm): LogisticsFormInternal {
+ return {
+ ...formData,
+ __internal__: {
+ addMeta: Boolean(formData._meta && Object.keys(formData._meta).length),
+ },
+ };
+}
+
+function formSerializer(formData: LogisticsFormInternal): LogisticsForm {
+ const { __internal__, ...rest } = formData;
+ return rest;
+}
+
export const StepLogistics: React.FunctionComponent = React.memo(
({ defaultValue, isEditing = false, onChange, isLegacy = false }) => {
const { form } = useForm({
schema: schemas.logistics,
defaultValue,
options: { stripEmptyFields: false },
+ serializer: formSerializer,
+ deserializer: formDeserializer,
});
/**
@@ -117,7 +180,9 @@ export const StepLogistics: React.FunctionComponent = React.memo(
return subscription.unsubscribe;
}, [onChange]); // eslint-disable-line react-hooks/exhaustive-deps
- const { name, indexPatterns, order, priority, version } = fieldsMeta;
+ const { name, indexPatterns, dataStream, order, priority, version } = getFieldsMeta(
+ documentationService.getEsDocsBase()
+ );
return (
<>
@@ -180,6 +245,16 @@ export const StepLogistics: React.FunctionComponent = React.memo(
/>
+ {/* Create data stream */}
+ {isLegacy !== true && (
+
+
+
+ )}
+
{/* Order */}
{isLegacy && (
@@ -226,25 +301,35 @@ export const StepLogistics: React.FunctionComponent = React.memo(
id="xpack.idxMgmt.templateForm.stepLogistics.metaFieldDescription"
defaultMessage="Use the _meta field to store any metadata you want."
/>
+
+
>
}
>
-
+ {({ '__internal__.addMeta': addMeta }) => {
+ return (
+ addMeta && (
+
+ )
+ );
}}
- />
+
)}
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_review.tsx b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_review.tsx
index 5d0eab93c4f02..d36f249e8ff0f 100644
--- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_review.tsx
+++ b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_review.tsx
@@ -169,7 +169,7 @@ export const StepReview: React.FunctionComponent = React.memo(
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/template_form.tsx b/x-pack/plugins/index_management/public/application/components/template_form/template_form.tsx
index 6310ac09488e5..f5c9be9292cd0 100644
--- a/x-pack/plugins/index_management/public/application/components/template_form/template_form.tsx
+++ b/x-pack/plugins/index_management/public/application/components/template_form/template_form.tsx
@@ -50,7 +50,7 @@ const wizardSections: { [id: string]: { id: WizardSection; label: string } } = {
components: {
id: 'components',
label: i18n.translate('xpack.idxMgmt.templateForm.steps.componentsStepName', {
- defaultMessage: 'Components',
+ defaultMessage: 'Component templates',
}),
},
settings: {
@@ -91,15 +91,9 @@ export const TemplateForm = ({
const indexTemplate = defaultValue ?? {
name: '',
indexPatterns: [],
- composedOf: [],
- template: {
- settings: {},
- mappings: {},
- aliases: {},
- },
+ template: {},
_kbnMeta: {
- isManaged: false,
- isCloudManaged: false,
+ type: 'default',
hasDatastream: false,
isLegacy,
},
@@ -150,18 +144,50 @@ export const TemplateForm = ({
>
) : null;
- const buildTemplateObject = (initialTemplate: TemplateDeserialized) => (
- wizardData: WizardContent
- ): TemplateDeserialized => ({
- ...initialTemplate,
- ...wizardData.logistics,
- composedOf: wizardData.components,
- template: {
- settings: wizardData.settings,
- mappings: wizardData.mappings,
- aliases: wizardData.aliases,
+ /**
+ * If no mappings, settings or aliases are defined, it is better to not send empty
+ * object for those values.
+ * This method takes care of that and other cleanup of empty fields.
+ * @param template The template object to clean up
+ */
+ const cleanupTemplateObject = (template: TemplateDeserialized) => {
+ const outputTemplate = { ...template };
+
+ if (outputTemplate.template.settings === undefined) {
+ delete outputTemplate.template.settings;
+ }
+ if (outputTemplate.template.mappings === undefined) {
+ delete outputTemplate.template.mappings;
+ }
+ if (outputTemplate.template.aliases === undefined) {
+ delete outputTemplate.template.aliases;
+ }
+ if (Object.keys(outputTemplate.template).length === 0) {
+ delete outputTemplate.template;
+ }
+
+ return outputTemplate;
+ };
+
+ const buildTemplateObject = useCallback(
+ (initialTemplate: TemplateDeserialized) => (
+ wizardData: WizardContent
+ ): TemplateDeserialized => {
+ const outputTemplate = {
+ ...initialTemplate,
+ ...wizardData.logistics,
+ composedOf: wizardData.components,
+ template: {
+ settings: wizardData.settings,
+ mappings: wizardData.mappings,
+ aliases: wizardData.aliases,
+ },
+ };
+
+ return cleanupTemplateObject(outputTemplate);
},
- });
+ []
+ );
const onSaveTemplate = useCallback(
async (wizardData: WizardContent) => {
@@ -177,7 +203,7 @@ export const TemplateForm = ({
clearSaveError();
},
- [indexTemplate, onSave, clearSaveError]
+ [indexTemplate, buildTemplateObject, onSave, clearSaveError]
);
return (
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx b/x-pack/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx
index 5af3b4dd00c4f..d8c3ad8c259fc 100644
--- a/x-pack/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx
+++ b/x-pack/plugins/index_management/public/application/components/template_form/template_form_schemas.tsx
@@ -128,6 +128,32 @@ export const schemas: Record = {
},
],
},
+ dataStream: {
+ type: FIELD_TYPES.TOGGLE,
+ label: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.datastreamLabel', {
+ defaultMessage: 'Create data stream',
+ }),
+ defaultValue: false,
+ serializer: (value) => {
+ if (value === true) {
+ return {
+ timestamp_field: '@timestamp',
+ };
+ }
+ },
+ deserializer: (value) => {
+ if (typeof value === 'boolean') {
+ return value;
+ }
+
+ /**
+ * For now, it is enough to have a "data_stream" declared on the index template
+ * to assume that the template creates a data stream. In the future, this condition
+ * might change
+ */
+ return value !== undefined;
+ },
+ },
order: {
type: FIELD_TYPES.NUMBER,
label: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.fieldOrderLabel', {
@@ -187,5 +213,13 @@ export const schemas: Record = {
}
},
},
+ __internal__: {
+ addMeta: {
+ type: FIELD_TYPES.TOGGLE,
+ label: i18n.translate('xpack.idxMgmt.templateForm.stepLogistics.addMetadataLabel', {
+ defaultMessage: 'Add metadata',
+ }),
+ },
+ },
},
};
diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/components/index.ts b/x-pack/plugins/index_management/public/application/sections/home/template_list/components/index.ts
index 156d792c26f1d..3954ce04ca0b5 100644
--- a/x-pack/plugins/index_management/public/application/sections/home/template_list/components/index.ts
+++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/components/index.ts
@@ -5,3 +5,5 @@
*/
export * from './filter_list_button';
+
+export * from './template_type_indicator';
diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/components/template_type_indicator.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/components/template_type_indicator.tsx
new file mode 100644
index 0000000000000..c6b0e21ebfdc1
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/components/template_type_indicator.tsx
@@ -0,0 +1,37 @@
+/*
+ * 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 from 'react';
+import { i18n } from '@kbn/i18n';
+import { EuiBadge } from '@elastic/eui';
+
+import { TemplateType } from '../../../../../../common';
+
+interface Props {
+ templateType: TemplateType;
+}
+
+const i18nTexts = {
+ managed: i18n.translate('xpack.idxMgmt.templateBadgeType.managed', {
+ defaultMessage: 'Managed',
+ }),
+ cloudManaged: i18n.translate('xpack.idxMgmt.templateBadgeType.cloudManaged', {
+ defaultMessage: 'Cloud-managed',
+ }),
+ system: i18n.translate('xpack.idxMgmt.templateBadgeType.system', { defaultMessage: 'System' }),
+};
+
+export const TemplateTypeIndicator = ({ templateType }: Props) => {
+ if (templateType === 'default') {
+ return null;
+ }
+
+ return (
+
+ {i18nTexts[templateType]}
+
+ );
+};
diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx
index b470bcfd7660e..9203e76fce787 100644
--- a/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/legacy_templates/template_table/template_table.tsx
@@ -7,7 +7,7 @@
import React, { useState, Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiInMemoryTable, EuiIcon, EuiButton, EuiLink, EuiBasicTableColumn } from '@elastic/eui';
+import { EuiInMemoryTable, EuiButton, EuiLink, EuiBasicTableColumn } from '@elastic/eui';
import { ScopedHistory } from 'kibana/public';
import { SendRequestResponse, reactRouterNavigate } from '../../../../../../shared_imports';
import { TemplateListItem } from '../../../../../../../common';
@@ -15,6 +15,8 @@ import { UIM_TEMPLATE_SHOW_DETAILS_CLICK } from '../../../../../../../common/con
import { TemplateDeleteModal } from '../../../../../components';
import { encodePathForReactRouter } from '../../../../../services/routing';
import { useServices } from '../../../../../app_context';
+import { TemplateContentIndicator } from '../../../../../components/shared';
+import { TemplateTypeIndicator } from '../../components';
interface Props {
templates: TemplateListItem[];
@@ -47,20 +49,23 @@ export const LegacyTemplateTable: React.FunctionComponent = ({
sortable: true,
render: (name: TemplateListItem['name'], item: TemplateListItem) => {
return (
- /* eslint-disable-next-line @elastic/eui/href-or-on-click */
- uiMetricService.trackMetric('click', UIM_TEMPLATE_SHOW_DETAILS_CLICK)
- )}
- data-test-subj="templateDetailsLink"
- >
- {name}
-
+ <>
+ uiMetricService.trackMetric('click', UIM_TEMPLATE_SHOW_DETAILS_CLICK)
+ )}
+ data-test-subj="templateDetailsLink"
+ >
+ {name}
+
+
+
+ >
);
},
},
@@ -98,44 +103,30 @@ export const LegacyTemplateTable: React.FunctionComponent = ({
) : null,
},
{
- field: 'order',
- name: i18n.translate('xpack.idxMgmt.templateList.legacyTable.orderColumnTitle', {
- defaultMessage: 'Order',
- }),
- truncateText: true,
- sortable: true,
- },
- {
- field: 'hasMappings',
- name: i18n.translate('xpack.idxMgmt.templateList.legacyTable.mappingsColumnTitle', {
- defaultMessage: 'Mappings',
+ name: i18n.translate('xpack.idxMgmt.templateList.legacyTable.contentColumnTitle', {
+ defaultMessage: 'Content',
}),
- truncateText: true,
- sortable: true,
- render: (hasMappings: boolean) => (hasMappings ? : null),
- },
- {
- field: 'hasSettings',
- name: i18n.translate('xpack.idxMgmt.templateList.legacyTable.settingsColumnTitle', {
- defaultMessage: 'Settings',
- }),
- truncateText: true,
- sortable: true,
- render: (hasSettings: boolean) => (hasSettings ? : null),
- },
- {
- field: 'hasAliases',
- name: i18n.translate('xpack.idxMgmt.templateList.legacyTable.aliasesColumnTitle', {
- defaultMessage: 'Aliases',
- }),
- truncateText: true,
- sortable: true,
- render: (hasAliases: boolean) => (hasAliases ? : null),
+ width: '120px',
+ render: (item: TemplateListItem) => (
+
+ {i18n.translate('xpack.idxMgmt.templateList.table.noneDescriptionText', {
+ defaultMessage: 'None',
+ })}
+
+ }
+ />
+ ),
},
{
name: i18n.translate('xpack.idxMgmt.templateList.legacyTable.actionColumnTitle', {
defaultMessage: 'Actions',
}),
+ width: '120px',
actions: [
{
name: i18n.translate('xpack.idxMgmt.templateList.legacyTable.actionEditText', {
@@ -153,7 +144,7 @@ export const LegacyTemplateTable: React.FunctionComponent = ({
onClick: ({ name }: TemplateListItem) => {
editTemplate(name, true);
},
- enabled: ({ _kbnMeta: { isCloudManaged } }: TemplateListItem) => !isCloudManaged,
+ enabled: ({ _kbnMeta: { type } }: TemplateListItem) => type !== 'cloudManaged',
},
{
type: 'icon',
@@ -188,7 +179,7 @@ export const LegacyTemplateTable: React.FunctionComponent = ({
setTemplatesToDelete([{ name, isLegacy }]);
},
isPrimary: true,
- enabled: ({ _kbnMeta: { isCloudManaged } }: TemplateListItem) => !isCloudManaged,
+ enabled: ({ _kbnMeta: { type } }: TemplateListItem) => type !== 'cloudManaged',
},
],
},
@@ -208,13 +199,13 @@ export const LegacyTemplateTable: React.FunctionComponent = ({
const selectionConfig = {
onSelectionChange: setSelection,
- selectable: ({ _kbnMeta: { isCloudManaged } }: TemplateListItem) => !isCloudManaged,
+ selectable: ({ _kbnMeta: { type } }: TemplateListItem) => type !== 'cloudManaged',
selectableMessage: (selectable: boolean) => {
if (!selectable) {
return i18n.translate(
- 'xpack.idxMgmt.templateList.legacyTable.deleteManagedTemplateTooltip',
+ 'xpack.idxMgmt.templateList.legacyTable.deleteCloudManagedTemplateTooltip',
{
- defaultMessage: 'You cannot delete a managed template.',
+ defaultMessage: 'You cannot delete a cloud-managed template.',
}
);
}
diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx
index de2fc29ec8543..0c403e69d2e76 100644
--- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/tabs/tab_summary.tsx
@@ -17,6 +17,7 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiCodeBlock,
+ EuiSpacer,
} from '@elastic/eui';
import { useAppContext } from '../../../../../app_context';
import { TemplateDeserialized } from '../../../../../../../common';
@@ -57,163 +58,169 @@ export const TabSummary: React.FunctionComponent = ({ templateDetails })
} = useAppContext();
return (
-
-
-
- {/* Index patterns */}
-
-
-
-
- {numIndexPatterns > 1 ? (
-
-
- {indexPatterns.map((indexName: string, i: number) => {
- return (
- -
-
- {indexName}
-
-
- );
- })}
-
-
+ <>
+
+
+
+ {/* Index patterns */}
+
+
+
+
+ {numIndexPatterns > 1 ? (
+
+
+ {indexPatterns.map((indexName: string, i: number) => {
+ return (
+ -
+
+ {indexName}
+
+
+ );
+ })}
+
+
+ ) : (
+ indexPatterns.toString()
+ )}
+
+
+ {/* Priority / Order */}
+ {isLegacy !== true ? (
+ <>
+
+
+
+
+ {priority || priority === 0 ? priority : i18nTexts.none}
+
+ >
) : (
- indexPatterns.toString()
+ <>
+
+
+
+
+ {order || order === 0 ? order : i18nTexts.none}
+
+ >
)}
-
-
- {/* Priority / Order */}
- {isLegacy !== true ? (
- <>
-
-
-
-
- {priority || priority === 0 ? priority : i18nTexts.none}
-
- >
- ) : (
- <>
-
-
-
-
- {order || order === 0 ? order : i18nTexts.none}
-
- >
- )}
- {/* Components */}
- {isLegacy !== true && (
- <>
-
-
-
-
- {composedOf && composedOf.length > 0 ? (
-
- {composedOf.map((component) => (
- -
-
- {component}
-
-
- ))}
-
- ) : (
- i18nTexts.none
- )}
-
- >
- )}
-
-
+ {/* Components */}
+ {isLegacy !== true && (
+ <>
+
+
+
+
+ {composedOf && composedOf.length > 0 ? (
+
+ {composedOf.map((component) => (
+ -
+
+ {component}
+
+
+ ))}
+
+ ) : (
+ i18nTexts.none
+ )}
+
+ >
+ )}
+
+
-
-
- {/* ILM Policy (only for legacy as composable template could have ILM policy
+
+
+ {/* ILM Policy (only for legacy as composable template could have ILM policy
inside one of their components) */}
- {isLegacy && (
- <>
-
-
-
-
- {ilmPolicy && ilmPolicy.name ? (
-
- {ilmPolicy.name}
-
- ) : (
- i18nTexts.none
- )}
-
- >
- )}
+ {isLegacy && (
+ <>
+
+
+
+
+ {ilmPolicy && ilmPolicy.name ? (
+
+ {ilmPolicy.name}
+
+ ) : (
+ i18nTexts.none
+ )}
+
+ >
+ )}
+
+ {/* Has data stream? (only for composable template) */}
+ {isLegacy !== true && (
+ <>
+
+
+
+
+ {hasDatastream ? i18nTexts.yes : i18nTexts.no}
+
+ >
+ )}
- {/* Has data stream? (only for composable template) */}
- {isLegacy !== true && (
- <>
-
-
-
-
- {hasDatastream ? i18nTexts.yes : i18nTexts.no}
-
- >
- )}
+ {/* Version */}
+
+
+
+
+ {version || version === 0 ? version : i18nTexts.none}
+
+
+
+
- {/* Version */}
-
-
-
-
- {version || version === 0 ? version : i18nTexts.none}
-
+
- {/* Metadata (optional) */}
- {isLegacy !== true && _meta && (
- <>
-
-
-
-
- {JSON.stringify(_meta, null, 2)}
-
- >
- )}
-
-
-
+
+ {/* Metadata (optional) */}
+ {isLegacy !== true && _meta && (
+ <>
+
+
+
+
+ {JSON.stringify(_meta, null, 2)}
+
+ >
+ )}
+
+ >
);
};
diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx
index 34e90aef51701..5b726013a1d92 100644
--- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_details/template_details_content.tsx
@@ -36,6 +36,7 @@ import { useLoadIndexTemplate } from '../../../../services/api';
import { decodePathFromReactRouter } from '../../../../services/routing';
import { useServices } from '../../../../app_context';
import { TabAliases, TabMappings, TabSettings } from '../../../../components/shared';
+import { TemplateTypeIndicator } from '../components';
import { TabSummary } from './tabs';
const SUMMARY_TAB_ID = 'summary';
@@ -98,7 +99,7 @@ export const TemplateDetailsContent = ({
decodedTemplateName,
isLegacy
);
- const isCloudManaged = templateDetails?._kbnMeta.isCloudManaged ?? false;
+ const isCloudManaged = templateDetails?._kbnMeta.type === 'cloudManaged';
const [templateToDelete, setTemplateToDelete] = useState<
Array<{ name: string; isLegacy?: boolean }>
>([]);
@@ -111,6 +112,12 @@ export const TemplateDetailsContent = ({
{decodedTemplateName}
+ {templateDetails && (
+ <>
+
+
+ >
+ )}
@@ -163,16 +170,16 @@ export const TemplateDetailsContent = ({
}
color="primary"
size="s"
>
diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx
index 18a65407ee20d..f421bc5d87a54 100644
--- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_list.tsx
@@ -37,13 +37,19 @@ import { TemplateDetails } from './template_details';
import { LegacyTemplateTable } from './legacy_templates/template_table';
import { FilterListButton, Filters } from './components';
-type FilterName = 'composable' | 'system';
+type FilterName = 'managed' | 'cloudManaged' | 'system';
interface MatchParams {
templateName?: string;
}
-const stripOutSystemTemplates = (templates: TemplateListItem[]): TemplateListItem[] =>
- templates.filter((template) => !template.name.startsWith('.'));
+function filterTemplates(templates: TemplateListItem[], types: string[]): TemplateListItem[] {
+ return templates.filter((template) => {
+ if (template._kbnMeta.type === 'default') {
+ return true;
+ }
+ return types.includes(template._kbnMeta.type);
+ });
+}
export const TemplateList: React.FunctionComponent> = ({
match: {
@@ -56,12 +62,18 @@ export const TemplateList: React.FunctionComponent>({
- composable: {
- name: i18n.translate('xpack.idxMgmt.indexTemplatesList.viewComposableTemplateLabel', {
- defaultMessage: 'Composable templates',
+ managed: {
+ name: i18n.translate('xpack.idxMgmt.indexTemplatesList.viewManagedTemplateLabel', {
+ defaultMessage: 'Managed templates',
}),
checked: 'on',
},
+ cloudManaged: {
+ name: i18n.translate('xpack.idxMgmt.indexTemplatesList.viewCloudManagedTemplateLabel', {
+ defaultMessage: 'Cloud-managed templates',
+ }),
+ checked: 'off',
+ },
system: {
name: i18n.translate('xpack.idxMgmt.indexTemplatesList.viewSystemTemplateLabel', {
defaultMessage: 'System templates',
@@ -72,18 +84,19 @@ export const TemplateList: React.FunctionComponent {
if (!allTemplates) {
+ // If templates are not fetched, return empty arrays.
return { templates: [], legacyTemplates: [] };
}
- return filters.system.checked === 'on'
- ? allTemplates
- : {
- templates: stripOutSystemTemplates(allTemplates.templates),
- legacyTemplates: stripOutSystemTemplates(allTemplates.legacyTemplates),
- };
- }, [allTemplates, filters.system.checked]);
+ const visibleTemplateTypes = Object.entries(filters)
+ .filter(([name, _filter]) => _filter.checked === 'on')
+ .map(([name]) => name);
- const showComposableTemplateTable = filters.composable.checked === 'on';
+ return {
+ templates: filterTemplates(allTemplates.templates, visibleTemplateTypes),
+ legacyTemplates: filterTemplates(allTemplates.legacyTemplates, visibleTemplateTypes),
+ };
+ }, [allTemplates, filters]);
const selectedTemplate = Boolean(templateName)
? {
@@ -154,8 +167,8 @@ export const TemplateList: React.FunctionComponent
);
- const renderTemplatesTable = () =>
- showComposableTemplateTable ? (
+ const renderTemplatesTable = () => {
+ return (
<>
>
- ) : null;
+ );
+ };
const renderLegacyTemplatesTable = () => (
<>
diff --git a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx
index 55a777363d06f..3dffdcde160f1 100644
--- a/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/home/template_list/template_table/template_table.tsx
@@ -7,14 +7,7 @@
import React, { useState, Fragment } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import {
- EuiInMemoryTable,
- EuiBasicTableColumn,
- EuiButton,
- EuiLink,
- EuiBadge,
- EuiIcon,
-} from '@elastic/eui';
+import { EuiInMemoryTable, EuiBasicTableColumn, EuiButton, EuiLink, EuiIcon } from '@elastic/eui';
import { ScopedHistory } from 'kibana/public';
import { TemplateListItem } from '../../../../../../common';
@@ -24,6 +17,7 @@ import { encodePathForReactRouter } from '../../../../services/routing';
import { useServices } from '../../../../app_context';
import { TemplateDeleteModal } from '../../../../components';
import { TemplateContentIndicator } from '../../../../components/shared';
+import { TemplateTypeIndicator } from '../components';
interface Props {
templates: TemplateListItem[];
@@ -70,13 +64,7 @@ export const TemplateTable: React.FunctionComponent = ({
{name}
- {item._kbnMeta.isManaged ? (
-
- Managed
-
- ) : (
- ''
- )}
+
>
);
},
@@ -99,14 +87,6 @@ export const TemplateTable: React.FunctionComponent = ({
sortable: true,
render: (composedOf: string[] = []) => {composedOf.join(', ')},
},
- {
- field: 'priority',
- name: i18n.translate('xpack.idxMgmt.templateList.table.priorityColumnTitle', {
- defaultMessage: 'Priority',
- }),
- truncateText: true,
- sortable: true,
- },
{
name: i18n.translate('xpack.idxMgmt.templateList.table.dataStreamColumnTitle', {
defaultMessage: 'Data stream',
@@ -119,7 +99,7 @@ export const TemplateTable: React.FunctionComponent = ({
name: i18n.translate('xpack.idxMgmt.templateList.table.contentColumnTitle', {
defaultMessage: 'Content',
}),
- truncateText: true,
+ width: '120px',
render: (item: TemplateListItem) => (
= ({
name: i18n.translate('xpack.idxMgmt.templateList.table.actionColumnTitle', {
defaultMessage: 'Actions',
}),
+ width: '120px',
actions: [
{
name: i18n.translate('xpack.idxMgmt.templateList.table.actionEditText', {
@@ -153,7 +134,7 @@ export const TemplateTable: React.FunctionComponent = ({
onClick: ({ name }: TemplateListItem) => {
editTemplate(name);
},
- enabled: ({ _kbnMeta: { isCloudManaged } }: TemplateListItem) => !isCloudManaged,
+ enabled: ({ _kbnMeta: { type } }: TemplateListItem) => type !== 'cloudManaged',
},
{
type: 'icon',
@@ -182,7 +163,7 @@ export const TemplateTable: React.FunctionComponent = ({
setTemplatesToDelete([{ name, isLegacy }]);
},
isPrimary: true,
- enabled: ({ _kbnMeta: { isCloudManaged } }: TemplateListItem) => !isCloudManaged,
+ enabled: ({ _kbnMeta: { type } }: TemplateListItem) => type !== 'cloudManaged',
},
],
},
@@ -202,13 +183,13 @@ export const TemplateTable: React.FunctionComponent = ({
const selectionConfig = {
onSelectionChange: setSelection,
- selectable: ({ _kbnMeta: { isCloudManaged } }: TemplateListItem) => !isCloudManaged,
+ selectable: ({ _kbnMeta: { type } }: TemplateListItem) => type !== 'cloudManaged',
selectableMessage: (selectable: boolean) => {
if (!selectable) {
return i18n.translate(
- 'xpack.idxMgmt.templateList.legacyTable.deleteManagedTemplateTooltip',
+ 'xpack.idxMgmt.templateList.table.deleteCloudManagedTemplateTooltip',
{
- defaultMessage: 'You cannot delete a managed template.',
+ defaultMessage: 'You cannot delete a cloud-managed template.',
}
);
}
diff --git a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx
index 6ecefe18b1a61..29fd2e02120fc 100644
--- a/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/template_edit/template_edit.tsx
@@ -85,11 +85,11 @@ export const TemplateEdit: React.FunctionComponent): boolean => {
+ return obj === undefined || Object.keys(obj).length === 0 ? false : true;
+};
export const getTemplate = ({
name = getRandomString(),
@@ -13,31 +17,35 @@ export const getTemplate = ({
order = getRandomNumber(),
indexPatterns = [],
template: { settings, aliases, mappings } = {},
- isManaged = false,
- isCloudManaged = false,
hasDatastream = false,
isLegacy = false,
+ type = 'default',
}: Partial<
TemplateDeserialized & {
isLegacy?: boolean;
- isManaged: boolean;
- isCloudManaged: boolean;
+ type?: TemplateType;
hasDatastream: boolean;
}
-> = {}): TemplateDeserialized => ({
- name,
- version,
- order,
- indexPatterns,
- template: {
- aliases,
- mappings,
- settings,
- },
- _kbnMeta: {
- isManaged,
- isCloudManaged,
- hasDatastream,
- isLegacy,
- },
-});
+> = {}): TemplateDeserialized & TemplateListItem => {
+ const indexTemplate = {
+ name,
+ version,
+ order,
+ indexPatterns,
+ template: {
+ aliases,
+ mappings,
+ settings,
+ },
+ hasSettings: objHasProperties(settings),
+ hasMappings: objHasProperties(mappings),
+ hasAliases: objHasProperties(aliases),
+ _kbnMeta: {
+ type,
+ hasDatastream,
+ isLegacy,
+ },
+ };
+
+ return indexTemplate;
+};
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index d5d7b1648e47f..451483ad5db5b 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -7041,8 +7041,6 @@
"xpack.idxMgmt.templateDetails.loadingIndexTemplateErrorMessage": "テンプレートの読み込み中にエラーが発生",
"xpack.idxMgmt.templateDetails.manageButtonLabel": "管理",
"xpack.idxMgmt.templateDetails.manageContextMenuPanelTitle": "テンプレートオプション",
- "xpack.idxMgmt.templateDetails.managedTemplateInfoDescription": "マネージドテンプレートは内部オペレーションに不可欠です。",
- "xpack.idxMgmt.templateDetails.managedTemplateInfoTitle": "マネジドテンプレートの編集は許可されていません。",
"xpack.idxMgmt.templateDetails.mappingsTabTitle": "マッピング",
"xpack.idxMgmt.templateDetails.settingsTabTitle": "設定",
"xpack.idxMgmt.templateDetails.summaryTab.ilmPolicyDescriptionListTitle": "ILM ポリシー",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index b22b89a40a774..9e31a053a9a56 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -7045,8 +7045,6 @@
"xpack.idxMgmt.templateDetails.loadingIndexTemplateErrorMessage": "加载模板时出错",
"xpack.idxMgmt.templateDetails.manageButtonLabel": "管理",
"xpack.idxMgmt.templateDetails.manageContextMenuPanelTitle": "模板选项",
- "xpack.idxMgmt.templateDetails.managedTemplateInfoDescription": "托管模板对内部操作至关重要。",
- "xpack.idxMgmt.templateDetails.managedTemplateInfoTitle": "不允许编辑托管模板",
"xpack.idxMgmt.templateDetails.mappingsTabTitle": "映射",
"xpack.idxMgmt.templateDetails.settingsTabTitle": "设置",
"xpack.idxMgmt.templateDetails.summaryTab.ilmPolicyDescriptionListTitle": "ILM 策略",
diff --git a/x-pack/test/api_integration/apis/management/index_management/templates.helpers.js b/x-pack/test/api_integration/apis/management/index_management/templates.helpers.js
index a563b956df344..d24a856399f10 100644
--- a/x-pack/test/api_integration/apis/management/index_management/templates.helpers.js
+++ b/x-pack/test/api_integration/apis/management/index_management/templates.helpers.js
@@ -14,7 +14,12 @@ export const registerHelpers = ({ supertest }) => {
const getOneTemplate = (name, isLegacy = false) =>
supertest.get(`${API_BASE_PATH}/index_templates/${name}?legacy=${isLegacy}`);
- const getTemplatePayload = (name, indexPatterns = INDEX_PATTERNS, isLegacy = false) => {
+ const getTemplatePayload = (
+ name,
+ indexPatterns = INDEX_PATTERNS,
+ isLegacy = false,
+ type = 'default'
+ ) => {
const baseTemplate = {
name,
indexPatterns,
@@ -48,6 +53,7 @@ export const registerHelpers = ({ supertest }) => {
},
_kbnMeta: {
isLegacy,
+ type,
},
};