From cd83f7a22f20f6941e07993b4d4cf090c62298e3 Mon Sep 17 00:00:00 2001
From: Alison Goryachev
Date: Tue, 23 Jun 2020 14:28:48 -0400
Subject: [PATCH 01/20] init commit: component template wizard
---
.../lib/component_template_serialization.ts | 14 ++
.../index_management/common/lib/index.ts | 1 +
.../public/application/app.tsx | 2 +
.../component_template_create.tsx | 65 ++++++
.../component_template_create/index.ts | 7 +
.../component_template_list/empty_prompt.tsx | 11 +-
.../component_template_list/table.tsx | 11 +
.../components/component_templates/index.ts | 2 +
.../component_template_form.tsx | 201 +++++++++++++++++
.../component_template_form/index.ts | 7 +
.../component_template_form/steps/index.ts | 8 +
.../steps/step_logistics.tsx | 151 +++++++++++++
.../steps/step_logistics_container.tsx} | 17 +-
.../steps/step_review.tsx | 205 ++++++++++++++++++
.../steps/step_review_container.tsx | 26 +++
.../shared/components/index.ts | 7 +
.../component_templates/shared/index.ts | 7 +
.../component_templates/shared_imports.ts | 23 ++
.../components/shared/components/index.ts | 7 +-
.../shared/components/wizard_steps/index.ts | 8 +-
.../wizard_steps/step_aliases_container.tsx | 22 ++
.../wizard_steps}/step_mappings_container.tsx | 17 +-
.../wizard_steps/step_settings_container.tsx | 22 ++
.../shared/components/wizard_steps/types.ts | 13 ++
.../application/components/shared/index.ts | 7 +-
.../components/template_form/steps/index.ts | 3 -
.../steps/step_settings_container.tsx | 23 --
.../template_form/template_form.tsx | 18 +-
28 files changed, 845 insertions(+), 60 deletions(-)
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_template_create/component_template_create.tsx
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/component_template_create/index.ts
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/component_template_form.tsx
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/index.ts
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/index.ts
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics.tsx
rename x-pack/plugins/index_management/public/application/components/{template_form/steps/step_aliases_container.tsx => component_templates/shared/components/component_template_form/steps/step_logistics_container.tsx} (59%)
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_review.tsx
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_review_container.tsx
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/components/index.ts
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/index.ts
create mode 100644 x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_aliases_container.tsx
rename x-pack/plugins/index_management/public/application/components/{template_form/steps => shared/components/wizard_steps}/step_mappings_container.tsx (57%)
create mode 100644 x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_settings_container.tsx
create mode 100644 x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/types.ts
delete mode 100644 x-pack/plugins/index_management/public/application/components/template_form/steps/step_settings_container.tsx
diff --git a/x-pack/plugins/index_management/common/lib/component_template_serialization.ts b/x-pack/plugins/index_management/common/lib/component_template_serialization.ts
index 0db81bf81d3002..03ddacd473c5e0 100644
--- a/x-pack/plugins/index_management/common/lib/component_template_serialization.ts
+++ b/x-pack/plugins/index_management/common/lib/component_template_serialization.ts
@@ -8,6 +8,7 @@ import {
ComponentTemplateFromEs,
ComponentTemplateDeserialized,
ComponentTemplateListItem,
+ ComponentTemplateSerialized,
} from '../types';
const hasEntries = (data: object = {}) => Object.entries(data).length > 0;
@@ -84,3 +85,16 @@ export function deserializeComponenTemplateList(
return componentTemplateListItem;
}
+
+// TODO add test
+export function serializeComponentTemplate(
+ componentTemplateDeserialized: ComponentTemplateDeserialized
+): ComponentTemplateSerialized {
+ const { version, template, _meta } = componentTemplateDeserialized;
+
+ return {
+ version,
+ template,
+ _meta,
+ };
+}
diff --git a/x-pack/plugins/index_management/common/lib/index.ts b/x-pack/plugins/index_management/common/lib/index.ts
index fce4d8ccc2502b..efd79bf2afcf23 100644
--- a/x-pack/plugins/index_management/common/lib/index.ts
+++ b/x-pack/plugins/index_management/common/lib/index.ts
@@ -18,4 +18,5 @@ export { getTemplateParameter } from './utils';
export {
deserializeComponentTemplate,
deserializeComponenTemplateList,
+ serializeComponentTemplate,
} from './component_template_serialization';
diff --git a/x-pack/plugins/index_management/public/application/app.tsx b/x-pack/plugins/index_management/public/application/app.tsx
index 92197bee30c88f..3bb8343ea77101 100644
--- a/x-pack/plugins/index_management/public/application/app.tsx
+++ b/x-pack/plugins/index_management/public/application/app.tsx
@@ -16,6 +16,7 @@ import { TemplateClone } from './sections/template_clone';
import { TemplateEdit } from './sections/template_edit';
import { useServices } from './app_context';
+import { ComponentTemplateCreate } from './components';
export const App = ({ history }: { history: ScopedHistory }) => {
const { uiMetricService } = useServices();
@@ -32,6 +33,7 @@ export const App = ({ history }: { history: ScopedHistory }) => {
export const AppWithoutRouter = () => (
+
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_create/component_template_create.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_create/component_template_create.tsx
new file mode 100644
index 00000000000000..21a3c95c214019
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_create/component_template_create.tsx
@@ -0,0 +1,65 @@
+/*
+ * 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, { useState } from 'react';
+import { RouteComponentProps } from 'react-router-dom';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiPageBody, EuiPageContent, EuiSpacer, EuiTitle } from '@elastic/eui';
+import { ComponentTemplateDeserialized } from '../shared_imports';
+import { ComponentTemplateForm } from '../shared';
+
+export const ComponentTemplateCreate: React.FunctionComponent = ({
+ history,
+}) => {
+ const [isSaving, setIsSaving] = useState(false);
+ const [saveError, setSaveError] = useState(null);
+
+ // TODO implement
+ const onSave = async (template: ComponentTemplateDeserialized) => {
+ // const { name } = template;
+ // setIsSaving(true);
+ // setSaveError(null);
+ // const { error } = await saveTemplate(template);
+ // setIsSaving(false);
+ // if (error) {
+ // setSaveError(error);
+ // return;
+ // }
+ // history.push(getTemplateDetailsLink(name, template._kbnMeta.isLegacy));
+ };
+
+ const clearSaveError = () => {
+ setSaveError(null);
+ };
+
+ // TODO implement breadcrumb
+ // useEffect(() => {
+ // breadcrumbService.setBreadcrumbs('templateCreate');
+ // }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_create/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_create/index.ts
new file mode 100644
index 00000000000000..6b0e02317888b5
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_create/index.ts
@@ -0,0 +1,7 @@
+/*
+ * 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 { ComponentTemplateCreate } from './component_template_create';
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/empty_prompt.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/empty_prompt.tsx
index edd9f77cbf635d..c4db16cd16f715 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/empty_prompt.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/empty_prompt.tsx
@@ -6,8 +6,9 @@
import React, { FunctionComponent } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
-import { EuiEmptyPrompt, EuiLink } from '@elastic/eui';
+import { EuiEmptyPrompt, EuiLink, EuiButton } from '@elastic/eui';
+// import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public';
import { useComponentTemplatesContext } from '../component_templates_context';
export const EmptyPrompt: FunctionComponent = () => {
@@ -38,6 +39,14 @@ export const EmptyPrompt: FunctionComponent = () => {
}
+ // TODO implement
+ // actions={
+ //
+ // {i18n.translate('xpack.idxMgmt.home.componentTemplates.emptyPromptButtonLabel', {
+ // defaultMessage: 'Create a component template',
+ // })}
+ //
+ // }
/>
);
};
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/table.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/table.tsx
index b67a249ae69765..bbe510f217f1f4 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/table.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/table.tsx
@@ -85,6 +85,17 @@ export const ComponentTable: FunctionComponent = ({
defaultMessage: 'Reload',
})}
,
+
+ {i18n.translate('xpack.idxMgmt.componentTemplatesList.table.createButtonLabel', {
+ defaultMessage: 'Create a component template',
+ })}
+ ,
],
box: {
incremental: true,
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/index.ts
index 72e79a57ae4136..80570f4a443cde 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/index.ts
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/index.ts
@@ -9,3 +9,5 @@ export { ComponentTemplatesProvider } from './component_templates_context';
export { ComponentTemplateList } from './component_template_list';
export { ComponentTemplateDetailsFlyout } from './component_template_details';
+
+export { ComponentTemplateCreate } from './component_template_create';
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/component_template_form.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/component_template_form.tsx
new file mode 100644
index 00000000000000..8ec405fc5d23db
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/component_template_form.tsx
@@ -0,0 +1,201 @@
+/*
+ * 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 } from 'react';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { EuiSpacer } from '@elastic/eui';
+
+import { serializers, Forms, ComponentTemplateDeserialized } from '../../../shared_imports';
+// import { SectionError } from '../section_error';
+import { StepLogisticsContainer, StepReviewContainer } from './steps';
+import {
+ CommonWizardSteps,
+ StepSettingsContainer,
+ StepMappingsContainer,
+ StepAliasesContainer,
+} from '../../../../shared';
+
+const { stripEmptyFields } = serializers;
+const { FormWizard, FormWizardStep } = Forms;
+
+interface Props {
+ onSave: (componentTemplate: ComponentTemplateDeserialized) => void;
+ clearSaveError: () => void;
+ isSaving: boolean;
+ saveError: any;
+ defaultValue?: ComponentTemplateDeserialized;
+ isEditing?: boolean;
+}
+
+export interface WizardContent extends CommonWizardSteps {
+ logistics: Omit;
+}
+
+export type WizardSection = keyof WizardContent | 'review';
+
+const wizardSections: { [id: string]: { id: WizardSection; label: string } } = {
+ logistics: {
+ id: 'logistics',
+ label: i18n.translate('xpack.idxMgmt.componentTemplateForm.steps.logisticsStepName', {
+ defaultMessage: 'Logistics',
+ }),
+ },
+ settings: {
+ id: 'settings',
+ label: i18n.translate('xpack.idxMgmt.componentTemplateForm.steps.settingsStepName', {
+ defaultMessage: 'Index settings',
+ }),
+ },
+ mappings: {
+ id: 'mappings',
+ label: i18n.translate('xpack.idxMgmt.componentTemplateForm.steps.mappingsStepName', {
+ defaultMessage: 'Mappings',
+ }),
+ },
+ aliases: {
+ id: 'aliases',
+ label: i18n.translate('xpack.idxMgmt.componentTemplateForm.steps.aliasesStepName', {
+ defaultMessage: 'Aliases',
+ }),
+ },
+ review: {
+ id: 'review',
+ label: i18n.translate('xpack.idxMgmt.componentTemplateForm.steps.summaryStepName', {
+ defaultMessage: 'Review component template',
+ }),
+ },
+};
+
+export const ComponentTemplateForm = ({
+ defaultValue = {
+ name: '',
+ _meta: {},
+ template: {
+ settings: {},
+ mappings: {},
+ aliases: {},
+ },
+ _kbnMeta: {
+ // TODO
+ usedBy: [],
+ },
+ },
+ isEditing,
+ isSaving,
+ saveError,
+ clearSaveError,
+ onSave,
+}: Props) => {
+ const {
+ template: { settings, mappings, aliases },
+ ...logistics
+ } = defaultValue;
+
+ const wizardDefaultValue: WizardContent = {
+ logistics,
+ settings,
+ mappings,
+ aliases,
+ };
+
+ const i18nTexts = {
+ save: isEditing ? (
+
+ ) : (
+
+ ),
+ };
+
+ // TODO implement
+ const apiError = saveError ? (
+ <>
+ {/*
+ }
+ error={saveError}
+ data-test-subj="saveComponentTemplateError"
+ /> */}
+
+ >
+ ) : null;
+
+ const buildTemplateObject = (initialTemplate: ComponentTemplateDeserialized) => (
+ wizardData: WizardContent
+ ): ComponentTemplateDeserialized => ({
+ ...initialTemplate,
+ ...wizardData.logistics,
+ template: {
+ settings: wizardData.settings,
+ mappings: wizardData.mappings,
+ aliases: wizardData.aliases,
+ },
+ });
+
+ const onSaveTemplate = useCallback(
+ async (wizardData: WizardContent) => {
+ const template = buildTemplateObject(defaultValue)(wizardData);
+
+ // We need to strip empty strings, otherwise if the "version" is not set,
+ // it will be an empty string and ES expects a number.
+ onSave(
+ stripEmptyFields(template, {
+ types: ['string'],
+ }) as ComponentTemplateDeserialized
+ );
+
+ clearSaveError();
+ },
+ [defaultValue, onSave, clearSaveError]
+ );
+
+ return (
+
+ defaultValue={wizardDefaultValue}
+ onSave={onSaveTemplate}
+ isEditing={isEditing}
+ isSaving={isSaving}
+ apiError={apiError}
+ texts={i18nTexts}
+ >
+
+
+
+
+ {/* TODO fix doc link */}
+
+
+
+
+ {/* TODO fix doc link */}
+
+
+
+
+ {/* TODO fix doc link */}
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/index.ts
new file mode 100644
index 00000000000000..84d9a2795ee2c0
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/index.ts
@@ -0,0 +1,7 @@
+/*
+ * 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 { ComponentTemplateForm } from './component_template_form';
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/index.ts
new file mode 100644
index 00000000000000..b7e3e36e61814d
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/index.ts
@@ -0,0 +1,8 @@
+/*
+ * 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 { StepLogisticsContainer } from './step_logistics_container';
+export { StepReviewContainer } from './step_review_container';
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics.tsx
new file mode 100644
index 00000000000000..e0287054b0c474
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics.tsx
@@ -0,0 +1,151 @@
+/*
+ * 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, { useEffect } from 'react';
+import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiButtonEmpty, EuiSpacer } from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@kbn/i18n';
+import {
+ useForm,
+ Form,
+ getUseField,
+ getFormRow,
+ Field,
+ Forms,
+ FieldConfig,
+ FIELD_TYPES,
+ fieldValidators,
+} from '../../../../shared_imports';
+
+const UseField = getUseField({ component: Field });
+const FormRow = getFormRow({ titleTag: 'h3' });
+
+const { emptyField } = fieldValidators;
+
+const fieldsMeta = {
+ name: {
+ title: i18n.translate('xpack.idxMgmt.componentTemplateForm.stepLogistics.nameTitle', {
+ defaultMessage: 'Name',
+ }),
+ description: i18n.translate(
+ 'xpack.idxMgmt.componentTemplateForm.stepLogistics.nameDescription',
+ {
+ defaultMessage: 'A unique identifier for this component template.',
+ }
+ ),
+ testSubject: 'nameField',
+ },
+ version: {
+ title: i18n.translate('xpack.idxMgmt.componentTemplateForm.stepLogistics.versionTitle', {
+ defaultMessage: 'Version',
+ }),
+ description: i18n.translate(
+ 'xpack.idxMgmt.componentTemplateForm.stepLogistics.versionDescription',
+ {
+ defaultMessage: 'A number that identifies the template to external management systems.',
+ }
+ ),
+ testSubject: 'versionField',
+ },
+};
+
+const nameConfig: FieldConfig = {
+ defaultValue: undefined,
+ label: i18n.translate('xpack.idxMgmt.componentTemplateForm.stepLogistics.nameFieldLabel', {
+ defaultMessage: 'Name',
+ }),
+ type: FIELD_TYPES.TEXT,
+ validations: [
+ {
+ validator: emptyField(
+ i18n.translate('xpack.idxMgmt.componentTemplateForm.validation.nameRequiredError', {
+ defaultMessage: 'A component template name is required.',
+ })
+ ),
+ },
+ ],
+};
+
+interface Props {
+ defaultValue: { [key: string]: any };
+ onChange: (content: Forms.Content) => void;
+ isEditing?: boolean;
+}
+
+export const StepLogistics: React.FunctionComponent = React.memo(
+ ({ defaultValue, isEditing, onChange }) => {
+ const { form } = useForm({
+ defaultValue,
+ options: { stripEmptyFields: false },
+ });
+
+ useEffect(() => {
+ const validate = async () => {
+ return (await form.submit()).isValid;
+ };
+ onChange({
+ isValid: form.isValid,
+ validate,
+ getData: form.getFormData,
+ });
+ }, [form.isValid, onChange]); // eslint-disable-line react-hooks/exhaustive-deps
+
+ const { name, version } = fieldsMeta;
+
+ return (
+
+ );
+ }
+);
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_aliases_container.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics_container.tsx
similarity index 59%
rename from x-pack/plugins/index_management/public/application/components/template_form/steps/step_aliases_container.tsx
rename to x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics_container.tsx
index a0e0c59be6622e..867ecff799858d 100644
--- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_aliases_container.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics_container.tsx
@@ -6,18 +6,17 @@
import React from 'react';
import { Forms } from '../../../../shared_imports';
-import { documentationService } from '../../../services/documentation';
-import { StepAliases } from '../../shared';
import { WizardContent } from '../template_form';
+import { StepLogistics } from './step_logistics';
-export const StepAliasesContainer = () => {
- const { defaultValue, updateContent } = Forms.useContent('aliases');
+interface Props {
+ isEditing?: boolean;
+}
+
+export const StepLogisticsContainer = ({ isEditing = false }: Props) => {
+ const { defaultValue, updateContent } = Forms.useContent('logistics');
return (
-
+
);
};
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_review.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_review.tsx
new file mode 100644
index 00000000000000..2e18edd6783711
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_review.tsx
@@ -0,0 +1,205 @@
+/*
+ * 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 {
+ EuiFlexGroup,
+ EuiTitle,
+ EuiFlexItem,
+ EuiSpacer,
+ EuiTabbedContent,
+ EuiDescriptionList,
+ EuiDescriptionListTitle,
+ EuiDescriptionListDescription,
+ EuiText,
+ EuiCodeBlock,
+} from '@elastic/eui';
+import { FormattedMessage } from '@kbn/i18n/react';
+
+import { WizardSection } from '../component_template_form';
+import {
+ ComponentTemplateDeserialized,
+ serializers,
+ serializeComponentTemplate,
+} from '../../../../shared_imports';
+
+const { stripEmptyFields } = serializers;
+
+const NoneDescriptionText = () => (
+
+);
+
+const getDescriptionText = (data: any) => {
+ const hasEntries = data && Object.entries(data).length > 0;
+
+ return hasEntries ? (
+
+ ) : (
+
+ );
+};
+
+interface Props {
+ template: ComponentTemplateDeserialized;
+ navigateToStep: (stepId: WizardSection) => void;
+}
+
+export const StepReview: React.FunctionComponent = React.memo(
+ ({ template, navigateToStep }) => {
+ const { name, version } = template!;
+
+ const serializedComponentTemplate = serializeComponentTemplate(
+ stripEmptyFields(template!, {
+ types: ['string'],
+ }) as ComponentTemplateDeserialized
+ );
+
+ const {
+ template: {
+ mappings: serializedMappings,
+ settings: serializedSettings,
+ aliases: serializedAliases,
+ },
+ } = serializedComponentTemplate;
+
+ const SummaryTab = () => (
+
+
+
+
+
+
+ {/* Version */}
+
+
+
+
+ {version ? version : }
+
+
+
+
+
+
+
+
+
+
+ {getDescriptionText(serializedSettings)}
+
+
+
+
+
+ {getDescriptionText(serializedMappings)}
+
+
+
+
+
+ {getDescriptionText(serializedAliases)}
+
+
+
+
+
+ );
+
+ const RequestTab = () => {
+ const endpoint = `PUT _component_template/${name || ''}`;
+ const templateString = JSON.stringify(serializedComponentTemplate, null, 2);
+ const request = `${endpoint}\n${templateString}`;
+
+ // Beyond a certain point, highlighting the syntax will bog down performance to unacceptable
+ // levels. This way we prevent that happening for very large requests.
+ const language = request.length < 60000 ? 'json' : undefined;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {request}
+
+
+ );
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+ ,
+ },
+ {
+ id: 'request',
+ name: i18n.translate(
+ 'xpack.idxMgmt.componentTemplateForm.stepReview.requestTabTitle',
+ {
+ defaultMessage: 'Request',
+ }
+ ),
+ content: ,
+ },
+ ]}
+ />
+
+ );
+ }
+);
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_review_container.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_review_container.tsx
new file mode 100644
index 00000000000000..cafa8660b11503
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_review_container.tsx
@@ -0,0 +1,26 @@
+/*
+ * 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 { TemplateDeserialized } from '../../../../../common';
+import { Forms } from '../../../../shared_imports';
+import { WizardContent, WizardSection } from '../template_form';
+import { StepReview } from './step_review';
+
+interface Props {
+ getTemplateData: (wizardContent: WizardContent) => TemplateDeserialized;
+}
+
+export const StepReviewContainer = React.memo(({ getTemplateData }: Props) => {
+ const { navigateToStep } = Forms.useFormWizardContext();
+ const { getData } = Forms.useMultiContentContext();
+
+ const wizardContent = getData();
+ // Build the final template object, providing the wizard content data
+ const template = getTemplateData(wizardContent);
+
+ return ;
+});
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/index.ts
new file mode 100644
index 00000000000000..84d9a2795ee2c0
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/index.ts
@@ -0,0 +1,7 @@
+/*
+ * 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 { ComponentTemplateForm } from './component_template_form';
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/index.ts b/x-pack/plugins/index_management/public/application/components/component_templates/shared/index.ts
new file mode 100644
index 00000000000000..a81d0dcd900a0b
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/index.ts
@@ -0,0 +1,7 @@
+/*
+ * 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 { ComponentTemplateForm } from './components/component_template_form';
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts b/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts
index 4e56f4a8c98189..f57a432f003e71 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared_imports.ts
@@ -18,8 +18,29 @@ export {
Error,
useAuthorizationContext,
NotAuthorizedSection,
+ Forms,
} from '../../../../../../../src/plugins/es_ui_shared/public';
+export {
+ serializers,
+ fieldValidators,
+} from '../../../../../../../src/plugins/es_ui_shared/static/forms/helpers';
+
+export {
+ FormSchema,
+ FIELD_TYPES,
+ VALIDATION_TYPES,
+ FieldConfig,
+ useForm,
+ Form,
+ getUseField,
+} from '../../../../../../../src/plugins/es_ui_shared/static/forms/hook_form_lib';
+
+export {
+ getFormRow,
+ Field,
+} from '../../../../../../../src/plugins/es_ui_shared/static/forms/components';
+
export { TabMappings, TabSettings, TabAliases } from '../shared';
export {
@@ -27,3 +48,5 @@ export {
ComponentTemplateDeserialized,
ComponentTemplateListItem,
} from '../../../../common';
+
+export { serializeComponentTemplate } from '../../../../common/lib';
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/index.ts b/x-pack/plugins/index_management/public/application/components/shared/components/index.ts
index e1700ad6a632d2..b67a9c355e723d 100644
--- a/x-pack/plugins/index_management/public/application/components/shared/components/index.ts
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/index.ts
@@ -6,4 +6,9 @@
export { TabAliases, TabMappings, TabSettings } from './details_panel';
-export { StepAliases, StepMappings, StepSettings } from './wizard_steps';
+export {
+ StepAliasesContainer,
+ StepMappingsContainer,
+ StepSettingsContainer,
+ CommonWizardSteps,
+} from './wizard_steps';
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/index.ts b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/index.ts
index 90ce6227c09c88..ea554ca269d8bd 100644
--- a/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/index.ts
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/index.ts
@@ -4,6 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
-export { StepAliases } from './step_aliases';
-export { StepMappings } from './step_mappings';
-export { StepSettings } from './step_settings';
+export { StepAliasesContainer } from './step_aliases_container';
+export { StepMappingsContainer } from './step_mappings_container';
+export { StepSettingsContainer } from './step_settings_container';
+
+export { CommonWizardSteps } from './types';
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_aliases_container.tsx b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_aliases_container.tsx
new file mode 100644
index 00000000000000..a5953ea00a1063
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_aliases_container.tsx
@@ -0,0 +1,22 @@
+/*
+ * 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 { Forms } from '../../../../../shared_imports';
+import { CommonWizardSteps } from './types';
+import { StepAliases } from './step_aliases';
+
+interface Props {
+ esDocsBase: string;
+}
+
+export const StepAliasesContainer: React.FunctionComponent = ({ esDocsBase }) => {
+ const { defaultValue, updateContent } = Forms.useContent('aliases');
+
+ return (
+
+ );
+};
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_mappings_container.tsx b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_mappings_container.tsx
similarity index 57%
rename from x-pack/plugins/index_management/public/application/components/template_form/steps/step_mappings_container.tsx
rename to x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_mappings_container.tsx
index 80c0d1d4df4890..34e05d88c651d7 100644
--- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_mappings_container.tsx
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_mappings_container.tsx
@@ -5,20 +5,23 @@
*/
import React from 'react';
-import { Forms } from '../../../../shared_imports';
-import { documentationService } from '../../../services/documentation';
-import { StepMappings } from '../../shared';
-import { WizardContent } from '../template_form';
+import { Forms } from '../../../../../shared_imports';
+import { CommonWizardSteps } from './types';
+import { StepMappings } from './step_mappings';
-export const StepMappingsContainer = () => {
- const { defaultValue, updateContent, getData } = Forms.useContent('mappings');
+interface Props {
+ esDocsBase: string;
+}
+
+export const StepMappingsContainer: React.FunctionComponent = ({ esDocsBase }) => {
+ const { defaultValue, updateContent, getData } = Forms.useContent('mappings');
return (
);
};
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_settings_container.tsx b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_settings_container.tsx
new file mode 100644
index 00000000000000..c540ddceb95c2f
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/step_settings_container.tsx
@@ -0,0 +1,22 @@
+/*
+ * 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 { Forms } from '../../../../../shared_imports';
+import { CommonWizardSteps } from './types';
+import { StepSettings } from './step_settings';
+
+interface Props {
+ esDocsBase: string;
+}
+
+export const StepSettingsContainer = React.memo(({ esDocsBase }: Props) => {
+ const { defaultValue, updateContent } = Forms.useContent('settings');
+
+ return (
+
+ );
+});
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/types.ts b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/types.ts
new file mode 100644
index 00000000000000..f8088e2b6e058b
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/wizard_steps/types.ts
@@ -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.
+ */
+
+import { Mappings, IndexSettings, Aliases } from '../../../../../../common';
+
+export interface CommonWizardSteps {
+ settings?: IndexSettings;
+ mappings?: Mappings;
+ aliases?: Aliases;
+}
diff --git a/x-pack/plugins/index_management/public/application/components/shared/index.ts b/x-pack/plugins/index_management/public/application/components/shared/index.ts
index 5ec1f717102709..897e86c99eca0b 100644
--- a/x-pack/plugins/index_management/public/application/components/shared/index.ts
+++ b/x-pack/plugins/index_management/public/application/components/shared/index.ts
@@ -8,7 +8,8 @@ export {
TabAliases,
TabMappings,
TabSettings,
- StepAliases,
- StepMappings,
- StepSettings,
+ StepAliasesContainer,
+ StepMappingsContainer,
+ StepSettingsContainer,
+ CommonWizardSteps,
} from './components';
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/index.ts b/x-pack/plugins/index_management/public/application/components/template_form/steps/index.ts
index 95d1222ad2cc9a..b7e3e36e61814d 100644
--- a/x-pack/plugins/index_management/public/application/components/template_form/steps/index.ts
+++ b/x-pack/plugins/index_management/public/application/components/template_form/steps/index.ts
@@ -5,7 +5,4 @@
*/
export { StepLogisticsContainer } from './step_logistics_container';
-export { StepAliasesContainer } from './step_aliases_container';
-export { StepMappingsContainer } from './step_mappings_container';
-export { StepSettingsContainer } from './step_settings_container';
export { StepReviewContainer } from './step_review_container';
diff --git a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_settings_container.tsx b/x-pack/plugins/index_management/public/application/components/template_form/steps/step_settings_container.tsx
deleted file mode 100644
index b79c6804d382b3..00000000000000
--- a/x-pack/plugins/index_management/public/application/components/template_form/steps/step_settings_container.tsx
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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 { Forms } from '../../../../shared_imports';
-import { documentationService } from '../../../services/documentation';
-import { StepSettings } from '../../shared';
-import { WizardContent } from '../template_form';
-
-export const StepSettingsContainer = React.memo(() => {
- const { defaultValue, updateContent } = Forms.useContent('settings');
-
- return (
-
- );
-});
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 9e6d49faac5630..8a2c991aea8d07 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
@@ -11,13 +11,14 @@ import { EuiSpacer } from '@elastic/eui';
import { TemplateDeserialized, CREATE_LEGACY_TEMPLATE_BY_DEFAULT } from '../../../../common';
import { serializers, Forms } from '../../../shared_imports';
import { SectionError } from '../section_error';
+import { StepLogisticsContainer, StepReviewContainer } from './steps';
import {
- StepLogisticsContainer,
+ CommonWizardSteps,
StepSettingsContainer,
StepMappingsContainer,
StepAliasesContainer,
- StepReviewContainer,
-} from './steps';
+} from '../shared';
+import { documentationService } from '../../services/documentation';
const { stripEmptyFields } = serializers;
const { FormWizard, FormWizardStep } = Forms;
@@ -31,11 +32,8 @@ interface Props {
isEditing?: boolean;
}
-export interface WizardContent {
+export interface WizardContent extends CommonWizardSteps {
logistics: Omit;
- settings: TemplateDeserialized['template']['settings'];
- mappings: TemplateDeserialized['template']['mappings'];
- aliases: TemplateDeserialized['template']['aliases'];
}
export type WizardSection = keyof WizardContent | 'review';
@@ -183,15 +181,15 @@ export const TemplateForm = ({
-
+
-
+
-
+
From 6ea26f56b39f97ed36ae86bac68bbaaa294097d1 Mon Sep 17 00:00:00 2001
From: Alison Goryachev
Date: Tue, 23 Jun 2020 21:36:33 -0400
Subject: [PATCH 02/20] build out logistics form
---
.../component_templates/lib/documentation.ts | 1 +
.../steps/step_logistics.tsx | 201 ++++++++++++------
.../steps/step_logistics_container.tsx | 2 +-
.../steps/step_logistics_schema.tsx | 111 ++++++++++
.../steps/step_review_container.tsx | 7 +-
.../component_templates/shared_imports.ts | 4 +
6 files changed, 252 insertions(+), 74 deletions(-)
create mode 100644 x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics_schema.tsx
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/lib/documentation.ts b/x-pack/plugins/index_management/public/application/components/component_templates/lib/documentation.ts
index dc27dadf0b8073..b2a6c94d339ef7 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/lib/documentation.ts
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/lib/documentation.ts
@@ -12,5 +12,6 @@ export const getDocumentation = ({ ELASTIC_WEBSITE_URL, DOC_LINK_VERSION }: DocL
return {
componentTemplates: `${esDocsBase}/indices-component-template.html`,
+ componentTemplatesMetadata: `${esDocsBase}/indices-component-template.html#component-templates-metadata`,
};
};
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics.tsx
index e0287054b0c474..f72dc0519cb444 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/shared/components/component_template_form/steps/step_logistics.tsx
@@ -3,8 +3,16 @@
* 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, { useEffect } from 'react';
-import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiButtonEmpty, EuiSpacer } from '@elastic/eui';
+import React, { useEffect, useState } from 'react';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiTitle,
+ EuiButtonEmpty,
+ EuiSpacer,
+ EuiSwitch,
+ EuiLink,
+} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import {
@@ -14,60 +22,15 @@ import {
getFormRow,
Field,
Forms,
- FieldConfig,
- FIELD_TYPES,
- fieldValidators,
+ JsonEditorField,
} from '../../../../shared_imports';
+import { logisticsFormSchema } from './step_logistics_schema';
+import { useComponentTemplatesContext } from '../../../../component_templates_context';
+
const UseField = getUseField({ component: Field });
const FormRow = getFormRow({ titleTag: 'h3' });
-const { emptyField } = fieldValidators;
-
-const fieldsMeta = {
- name: {
- title: i18n.translate('xpack.idxMgmt.componentTemplateForm.stepLogistics.nameTitle', {
- defaultMessage: 'Name',
- }),
- description: i18n.translate(
- 'xpack.idxMgmt.componentTemplateForm.stepLogistics.nameDescription',
- {
- defaultMessage: 'A unique identifier for this component template.',
- }
- ),
- testSubject: 'nameField',
- },
- version: {
- title: i18n.translate('xpack.idxMgmt.componentTemplateForm.stepLogistics.versionTitle', {
- defaultMessage: 'Version',
- }),
- description: i18n.translate(
- 'xpack.idxMgmt.componentTemplateForm.stepLogistics.versionDescription',
- {
- defaultMessage: 'A number that identifies the template to external management systems.',
- }
- ),
- testSubject: 'versionField',
- },
-};
-
-const nameConfig: FieldConfig = {
- defaultValue: undefined,
- label: i18n.translate('xpack.idxMgmt.componentTemplateForm.stepLogistics.nameFieldLabel', {
- defaultMessage: 'Name',
- }),
- type: FIELD_TYPES.TEXT,
- validations: [
- {
- validator: emptyField(
- i18n.translate('xpack.idxMgmt.componentTemplateForm.validation.nameRequiredError', {
- defaultMessage: 'A component template name is required.',
- })
- ),
- },
- ],
-};
-
interface Props {
defaultValue: { [key: string]: any };
onChange: (content: Forms.Content) => void;
@@ -77,10 +40,21 @@ interface Props {
export const StepLogistics: React.FunctionComponent = React.memo(
({ defaultValue, isEditing, onChange }) => {
const { form } = useForm({
+ schema: logisticsFormSchema,
defaultValue,
options: { stripEmptyFields: false },
});
+ const { documentation } = useComponentTemplatesContext();
+
+ const [isVersionVisible, setIsVersionVisible] = useState(
+ Boolean(defaultValue.version)
+ );
+
+ const [isMetaVisible, setIsMetaVisible] = useState(
+ Boolean(Object.keys(defaultValue._meta).length)
+ );
+
useEffect(() => {
const validate = async () => {
return (await form.submit()).isValid;
@@ -92,8 +66,6 @@ export const StepLogistics: React.FunctionComponent = React.memo(
});
}, [form.isValid, onChange]); // eslint-disable-line react-hooks/exhaustive-deps
- const { name, version } = fieldsMeta;
-
return (