([]);
+ const goToList = () => {
+ return history.push('component_templates');
+ };
+
// Track component loaded
useEffect(() => {
trackMetric('loaded', UIM_COMPONENT_TEMPLATE_LIST_LOAD);
@@ -49,6 +64,7 @@ export const ComponentTemplateList: React.FunctionComponent = () => {
componentTemplates={data}
onReloadClick={sendRequest}
onDeleteClick={setComponentTemplatesToDelete}
+ history={history as ScopedHistory}
/>
);
} else if (error) {
@@ -58,18 +74,44 @@ export const ComponentTemplateList: React.FunctionComponent = () => {
return (
{content}
+
+ {/* delete modal */}
{componentTemplatesToDelete?.length > 0 ? (
{
if (deleteResponse?.hasDeletedComponentTemplates) {
// refetch the component templates
sendRequest();
+ // go back to list view (if deleted from details flyout)
+ goToList();
}
setComponentTemplatesToDelete([]);
}}
componentTemplatesToDelete={componentTemplatesToDelete}
/>
) : null}
+
+ {/* details flyout */}
+ {componentTemplateName && (
+
+ details._kbnMeta.usedBy.length > 0,
+ closePopoverOnClick: true,
+ handleActionClick: () => {
+ setComponentTemplatesToDelete([componentTemplateName]);
+ },
+ },
+ ]}
+ />
+ )}
);
};
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list_container.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list_container.tsx
index af8ab1b94c790..d0636da8cf93a 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list_container.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_template_list/component_template_list_container.tsx
@@ -5,16 +5,28 @@
*/
import React from 'react';
+import { RouteComponentProps } from 'react-router-dom';
import { ComponentTemplatesAuthProvider } from './auth_provider';
import { ComponentTemplatesWithPrivileges } from './with_privileges';
import { ComponentTemplateList } from './component_template_list';
-export const ComponentTemplateListContainer: React.FunctionComponent = () => {
+interface MatchParams {
+ componentTemplateName?: string;
+}
+
+export const ComponentTemplateListContainer: React.FunctionComponent> = ({
+ match: {
+ params: { componentTemplateName },
+ },
+ history,
+}) => {
return (
-
+
);
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 2d9557e64e6e7..b67a249ae6976 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
@@ -12,21 +12,30 @@ import {
EuiInMemoryTableProps,
EuiTextColor,
EuiIcon,
+ EuiLink,
} from '@elastic/eui';
+import { ScopedHistory } from 'kibana/public';
-import { ComponentTemplateListItem } from '../types';
+import { reactRouterNavigate } from '../../../../../../../../src/plugins/kibana_react/public';
+import { ComponentTemplateListItem } from '../shared_imports';
+import { UIM_COMPONENT_TEMPLATE_DETAILS } from '../constants';
+import { useComponentTemplatesContext } from '../component_templates_context';
export interface Props {
componentTemplates: ComponentTemplateListItem[];
onReloadClick: () => void;
onDeleteClick: (componentTemplateName: string[]) => void;
+ history: ScopedHistory;
}
export const ComponentTable: FunctionComponent = ({
componentTemplates,
onReloadClick,
onDeleteClick,
+ history,
}) => {
+ const { trackMetric } = useComponentTemplatesContext();
+
const [selection, setSelection] = useState([]);
const tableProps: EuiInMemoryTableProps = {
@@ -120,6 +129,21 @@ export const ComponentTable: FunctionComponent = ({
defaultMessage: 'Name',
}),
sortable: true,
+ render: (name: string) => (
+ /* eslint-disable-next-line @elastic/eui/href-or-on-click */
+ trackMetric('click', UIM_COMPONENT_TEMPLATE_DETAILS)
+ )}
+ data-test-subj="templateDetailsLink"
+ >
+ {name}
+
+ ),
},
{
field: 'usedBy',
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/component_templates_context.tsx b/x-pack/plugins/index_management/public/application/components/component_templates/component_templates_context.tsx
index 55f20ce21d417..e8116409def4b 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/component_templates_context.tsx
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/component_templates_context.tsx
@@ -14,7 +14,6 @@ const ComponentTemplatesContext = createContext(undefined);
interface Props {
httpClient: HttpSetup;
apiBasePath: string;
- appBasePath: string;
trackMetric: (type: 'loaded' | 'click' | 'count', eventName: string) => void;
docLinks: DocLinksSetup;
toasts: NotificationsSetup['toasts'];
@@ -27,7 +26,6 @@ interface Context {
documentation: ReturnType;
trackMetric: (type: 'loaded' | 'click' | 'count', eventName: string) => void;
toasts: NotificationsSetup['toasts'];
- appBasePath: string;
}
export const ComponentTemplatesProvider = ({
@@ -37,7 +35,7 @@ export const ComponentTemplatesProvider = ({
value: Props;
children: React.ReactNode;
}) => {
- const { httpClient, apiBasePath, trackMetric, docLinks, toasts, appBasePath } = value;
+ const { httpClient, apiBasePath, trackMetric, docLinks, toasts } = value;
const useRequest = getUseRequest(httpClient);
const sendRequest = getSendRequest(httpClient);
@@ -47,7 +45,7 @@ export const ComponentTemplatesProvider = ({
return (
{children}
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/constants.ts b/x-pack/plugins/index_management/public/application/components/component_templates/constants.ts
index 501acde07fc00..e9acfa8dcc56d 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/constants.ts
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/constants.ts
@@ -8,6 +8,7 @@
export const UIM_COMPONENT_TEMPLATE_LIST_LOAD = 'component_template_list_load';
export const UIM_COMPONENT_TEMPLATE_DELETE = 'component_template_delete';
export const UIM_COMPONENT_TEMPLATE_DELETE_MANY = 'component_template_delete_many';
+export const UIM_COMPONENT_TEMPLATE_DETAILS = 'component_template_details';
// privileges
export const APP_CLUSTER_REQUIRED_PRIVILEGES = ['manage_index_templates'];
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 e0219ec71787f..72e79a57ae413 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
@@ -8,4 +8,4 @@ export { ComponentTemplatesProvider } from './component_templates_context';
export { ComponentTemplateList } from './component_template_list';
-export * from './types';
+export { ComponentTemplateDetailsFlyout } from './component_template_details';
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/lib/api.ts b/x-pack/plugins/index_management/public/application/components/component_templates/lib/api.ts
index 351e83c6c0cb5..4a8cf965adfb9 100644
--- a/x-pack/plugins/index_management/public/application/components/component_templates/lib/api.ts
+++ b/x-pack/plugins/index_management/public/application/components/component_templates/lib/api.ts
@@ -4,9 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ComponentTemplateListItem } from '../types';
-import { UseRequestHook, SendRequestHook } from './request';
+import { ComponentTemplateListItem, ComponentTemplateDeserialized } from '../shared_imports';
import { UIM_COMPONENT_TEMPLATE_DELETE_MANY, UIM_COMPONENT_TEMPLATE_DELETE } from '../constants';
+import { UseRequestHook, SendRequestHook } from './request';
export const getApi = (
useRequest: UseRequestHook,
@@ -37,8 +37,16 @@ export const getApi = (
return result;
}
+ function useLoadComponentTemplate(name: string) {
+ return useRequest({
+ path: `${apiBasePath}/component_templates/${encodeURIComponent(name)}`,
+ method: 'get',
+ });
+ }
+
return {
useLoadComponentTemplates,
deleteComponentTemplates,
+ useLoadComponentTemplate,
};
};
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 049204f03c0c1..4e56f4a8c9818 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
@@ -19,3 +19,11 @@ export {
useAuthorizationContext,
NotAuthorizedSection,
} from '../../../../../../../src/plugins/es_ui_shared/public';
+
+export { TabMappings, TabSettings, TabAliases } from '../shared';
+
+export {
+ ComponentTemplateSerialized,
+ ComponentTemplateDeserialized,
+ ComponentTemplateListItem,
+} from '../../../../common';
diff --git a/x-pack/plugins/index_management/public/application/components/component_templates/types.ts b/x-pack/plugins/index_management/public/application/components/component_templates/types.ts
deleted file mode 100644
index 0aab3b6b0a94a..0000000000000
--- a/x-pack/plugins/index_management/public/application/components/component_templates/types.ts
+++ /dev/null
@@ -1,17 +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.
- */
-
-// Ideally, we shouldn't depend on anything in index management that is
-// outside of the components_templates directory
-// We could consider creating shared types or duplicating the types here if
-// the component_templates app were to move outside of index management
-import {
- ComponentTemplateSerialized,
- ComponentTemplateDeserialized,
- ComponentTemplateListItem,
-} from '../../../../common';
-
-export { ComponentTemplateSerialized, ComponentTemplateDeserialized, ComponentTemplateListItem };
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/index.ts b/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/index.ts
new file mode 100644
index 0000000000000..af5cd500a286a
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/index.ts
@@ -0,0 +1,9 @@
+/*
+ * 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 { TabAliases } from './tab_aliases';
+export { TabMappings } from './tab_mappings';
+export { TabSettings } from './tab_settings';
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_aliases.tsx b/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_aliases.tsx
new file mode 100644
index 0000000000000..bcf59fd13bad6
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_aliases.tsx
@@ -0,0 +1,39 @@
+/*
+ * 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 { FormattedMessage } from '@kbn/i18n/react';
+import { EuiCodeBlock, EuiCallOut } from '@elastic/eui';
+
+import { Aliases } from '../../../../../../common';
+
+interface Props {
+ aliases: Aliases | undefined;
+}
+
+export const TabAliases: React.FunctionComponent = ({ aliases }) => {
+ if (aliases && Object.keys(aliases).length) {
+ return (
+
+ {JSON.stringify(aliases, null, 2)}
+
+ );
+ }
+
+ return (
+
+ }
+ iconType="pin"
+ data-test-subj="noAliasesCallout"
+ size="s"
+ />
+ );
+};
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_mappings.tsx b/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_mappings.tsx
new file mode 100644
index 0000000000000..3c3d88345e5a1
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_mappings.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 { FormattedMessage } from '@kbn/i18n/react';
+import { EuiCodeBlock, EuiCallOut } from '@elastic/eui';
+import { Mappings } from '../../../../../../common';
+
+interface Props {
+ mappings: Mappings | undefined;
+}
+
+export const TabMappings: React.FunctionComponent = ({ mappings }) => {
+ if (mappings && Object.keys(mappings).length) {
+ return (
+
+ {JSON.stringify(mappings, null, 2)}
+
+ );
+ }
+
+ return (
+
+ }
+ iconType="pin"
+ data-test-subj="noMappingsCallout"
+ size="s"
+ />
+ );
+};
diff --git a/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_settings.tsx b/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_settings.tsx
new file mode 100644
index 0000000000000..6d5cf09588a1c
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/shared/components/details_panel/tab_settings.tsx
@@ -0,0 +1,38 @@
+/*
+ * 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 { FormattedMessage } from '@kbn/i18n/react';
+import { EuiCodeBlock, EuiCallOut } from '@elastic/eui';
+import { IndexSettings } from '../../../../../../common';
+
+interface Props {
+ settings: IndexSettings | undefined;
+}
+
+export const TabSettings: React.FunctionComponent = ({ settings }) => {
+ if (settings && Object.keys(settings).length) {
+ return (
+
+ {JSON.stringify(settings, null, 2)}
+
+ );
+ }
+
+ return (
+
+ }
+ iconType="pin"
+ data-test-subj="noSettingsCallout"
+ size="s"
+ />
+ );
+};
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
new file mode 100644
index 0000000000000..90d66bd1a5da4
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/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 { TabAliases, TabMappings, TabSettings } from './details_panel';
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
new file mode 100644
index 0000000000000..e015ef72e244f
--- /dev/null
+++ b/x-pack/plugins/index_management/public/application/components/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 { TabAliases, TabMappings, TabSettings } from './components';
diff --git a/x-pack/plugins/index_management/public/application/index.tsx b/x-pack/plugins/index_management/public/application/index.tsx
index 5d1096c9ee24e..ff54b4b1bfe35 100644
--- a/x-pack/plugins/index_management/public/application/index.tsx
+++ b/x-pack/plugins/index_management/public/application/index.tsx
@@ -10,7 +10,7 @@ import { render, unmountComponentAtNode } from 'react-dom';
import { CoreStart } from '../../../../../src/core/public';
-import { API_BASE_PATH, BASE_PATH } from '../../common';
+import { API_BASE_PATH } from '../../common';
import { AppContextProvider, AppDependencies } from './app_context';
import { App } from './app';
@@ -32,7 +32,6 @@ export const renderApp = (
const componentTemplateProviderValues = {
httpClient: services.httpService.httpClient,
apiBasePath: API_BASE_PATH,
- appBasePath: BASE_PATH,
trackMetric: services.uiMetricService.trackMetric.bind(services.uiMetricService),
docLinks,
toasts: notifications.toasts,
diff --git a/x-pack/plugins/index_management/public/application/sections/home/home.tsx b/x-pack/plugins/index_management/public/application/sections/home/home.tsx
index 51deaf42cc72c..7bd04cdbf0c91 100644
--- a/x-pack/plugins/index_management/public/application/sections/home/home.tsx
+++ b/x-pack/plugins/index_management/public/application/sections/home/home.tsx
@@ -150,7 +150,14 @@ export const IndexManagementHome: React.FunctionComponent
-
+