/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import React, { useContext, useRef, useState, useEffect, useMemo } from "react"; import { EuiButton, EuiButtonIcon, EuiDragDropContext, EuiDraggable, EuiDroppable, EuiFlexGroup, EuiFlexItem, EuiHighlight, EuiIcon, EuiLink, EuiPanel, EuiSelectable, EuiSpacer, EuiText, EuiTitle, euiDragDropReorder, } from "@elastic/eui"; import { ContentPanel } from "../../../../components/ContentPanel"; import CustomFormRow from "../../../../components/CustomFormRow"; import { ServicesContext } from "../../../../services"; import { BrowserServices } from "../../../../models/interfaces"; import { SubDetailProps } from "../../interface"; import { TemplateItem } from "../../../../../models/interfaces"; import { Modal } from "../../../../components/Modal"; import { ICatComposableTemplate } from "../../../ComposableTemplates/interface"; import { IndicesUpdateMode, ROUTES } from "../../../../utils/constants"; import ComponentTemplateBadge from "../../../../components/ComponentTemplateBadge"; import ComponentTemplateDetail, { IComponentTemplateDetailInstance } from "../../../CreateComposableTemplate/containers/TemplateDetail"; import { CoreServicesContext } from "../../../../components/core_services"; import { CoreStart } from "opensearch-dashboards/public"; import FilterGroup from "../../../../components/FilterGroup"; export default function ComposableTemplate(props: SubDetailProps) { const { field, readonly, history } = props; const [dialogVisible, setDialogVisible] = useState(false); const [selectedTypes, setSelectedTypes] = useState([]); const [selectedComposableTemplates, setSelectedComposableTemplates] = useState([]); const [allComposableTemplates, setAllComposableTemplates] = useState([]); const [createComponentVisible, setCreateComponentVisible] = useState(false); const values: TemplateItem = field.getValues(); const services = useContext(ServicesContext) as BrowserServices; const coreServices = useContext(CoreServicesContext) as CoreStart; const componentCreateRef = useRef(null); const reloadAllComposableTemplates = () => services.commonService .apiCaller<{ component_templates?: ICatComposableTemplate[]; }>({ endpoint: "transport.request", data: { method: "GET", path: `/_component_template/*`, }, hideLog: true, }) .then((res) => { if (res && res.ok) { setAllComposableTemplates(res.response.component_templates || []); } }); useEffect(() => { reloadAllComposableTemplates(); }, []); const finalOptions = useMemo( () => allComposableTemplates.filter((item) => { if (!selectedTypes.length) { return true; } return selectedTypes.every((type) => !!item.component_template.template[type as IndicesUpdateMode]); }), [selectedTypes, allComposableTemplates] ); if (readonly) { return null; } return (
Component template
} helpText={ <> Define an index template by combining component templates containing index configurations. Associate existing component templates or create one. You can arrange the priority of the component templates by dragging them. The component template placed on bottom has the highest priority.{" "} Learn more } > <>
} titleSize="s" > {values.composed_of && values.composed_of.length && allComposableTemplates.length ? ( { if (source && destination) { const items = euiDragDropReorder(values.composed_of || [], source.index, destination.index); field.setValue("composed_of", items); } }} > {values.composed_of.map((item, index) => { const findItem = allComposableTemplates.find((template) => template.name === item); if (!findItem) { return
; } return ( {(provided) => (
{findItem.name}
{readonly ? null : ( { const newValue = [...(values.composed_of || [])]; newValue.splice(index, 1); field.setValue("composed_of", newValue); }} iconType="trash" color="danger" aria-label="delete" /> )} window.open(`#${ROUTES.CREATE_COMPOSABLE_TEMPLATE}/${item}`)} style={{ marginLeft: 12 }} iconType="inspect" color="primary" aria-label="see detail" />
)}
); })} ) : ( No component templates associated )} {readonly ? null : (
setDialogVisible(true)}>Associate component templates setCreateComponentVisible(true)}> Create component template
)} { field.setValue("composed_of", [...(field.getValue("composed_of") || []), ...selectedComposableTemplates]); setSelectedComposableTemplates([]); }} onClose={() => setDialogVisible(false)} content={ ({ value: item, label: item.name, checked: [...(values.composed_of || []), ...selectedComposableTemplates].includes(item.name) ? "on" : undefined, disabled: (values.composed_of || []).includes(item.name), }))} onChange={(val) => { setSelectedComposableTemplates(val.filter((item) => item.checked === "on" && !item.disabled).map((item) => item.label)); }} searchProps={{ placeholder: "Search", }} listProps={{ rowHeight: 40, bordered: true, }} renderOption={(option, searchValue) => ( {option.label} )} height={480} > {(list, search) => ( <> {search} setSelectedTypes(val || [])} value={selectedTypes} options={[ { label: IndicesUpdateMode.alias, }, { label: IndicesUpdateMode.mappings, }, { label: IndicesUpdateMode.settings, }, ]} /> {list} )} } /> {createComponentVisible ? ( setCreateComponentVisible(false)} locale={{ confirm: "Create", }} footer={["cancel", "confirm"]} onOk={() => { componentCreateRef.current?.submit(); // return a reject promise to keep it from closing return Promise.reject("no error"); }} onClose={() => setCreateComponentVisible(false)} content={ { reloadAllComposableTemplates(); field.setValue("composed_of", [...(field.getValue("composed_of") || []), name]); setCreateComponentVisible(false); }} ref={componentCreateRef} history={history} /> } /> ) : null} ); }