/* * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ import React, { forwardRef, useCallback, useRef, useImperativeHandle } from "react"; import { EuiIcon, EuiFlexGroup, EuiFlexItem, EuiFormRow, EuiToolTip, EuiBadge, EuiText, EuiContextMenu, EuiFormRowProps, } from "@elastic/eui"; import { set, pick, isEqual } from "lodash"; import { MappingsProperties } from "../../../models/interfaces"; import { AllBuiltInComponents } from "../FormGenerator"; import useField, { transformNameToString } from "../../lib/field"; import { INDEX_MAPPING_TYPES, INDEX_MAPPING_TYPES_WITH_CHILDREN } from "../../utils/constants"; import SimplePopover from "../SimplePopover"; import { useEffect } from "react"; interface IMappingLabel { value: MappingsProperties[number]; onChange: (val: IMappingLabel["value"], key: string, value: string) => void | string; onFieldNameCheck: (val: string) => string; onAddSubField: () => void; onAddSubObject: () => void; onDeleteField: () => void; readonly?: boolean; id: string; shouldShowLabel?: boolean; } export interface IMappingLabelRef { validate: () => Promise; } const FormRow = (props: EuiFormRowProps & Pick) => { const { shouldShowLabel, label, ...others } = props; return ; }; export const MappingLabel = forwardRef((props: IMappingLabel, forwardedRef: React.Ref) => { const { onFieldNameCheck, onAddSubField, onAddSubObject, onDeleteField, id, readonly, shouldShowLabel } = props; const propsRef = useRef(props); propsRef.current = props; const onFieldChange = useCallback( (k, v) => { let newValue = { ...propsRef.current.value }; set(newValue, k, v); if (k === "type") { newValue = pick(newValue, ["fieldName", "type"]); const findItem = INDEX_MAPPING_TYPES.find((item) => item.label === v); const initValues = (findItem?.options?.fields || []).reduce((total, current) => { if (current && current.initValue !== undefined) { return { ...total, [transformNameToString(current.name)]: current.initValue, }; } return total; }, {}); newValue = { ...newValue, ...initValues, }; field.setValues(newValue); } return propsRef.current.onChange(newValue, k, v); }, [propsRef.current.value, propsRef.current.onChange] ); const field = useField({ values: { ...propsRef.current.value, type: propsRef.current.value.type || "object", }, onChange: onFieldChange, unmountComponent: true, }); useEffect(() => { if (!isEqual(propsRef.current.value, field.getValues())) { field.resetValues(propsRef.current.value); } }, [propsRef.current.value]); const value = field.getValues(); const type = value.type; useImperativeHandle(forwardedRef, () => ({ validate: async () => { const { errors } = await field.validatePromise(); if (errors) { return "Validate Error"; } else { return ""; } }, })); const findItem = INDEX_MAPPING_TYPES.find((item) => item.label === type); const moreFields = findItem?.options?.fields || []; if (readonly) { return (
  • {field.getValue("fieldName")} {type} {moreFields.map((extraField) => ( {extraField.label}: {field.getValue(extraField.name)} ))}
  • ); } return ( e.stopPropagation()}> { const checkResult = onFieldNameCheck(value); if (checkResult) { return Promise.reject(checkResult); } return Promise.resolve(""); }, }, ], })} compressed data-test-subj={`${id}-field-name`} /> { const allOptions = INDEX_MAPPING_TYPES.map((item) => ({ text: item.label, value: item.label })); const typeValue = field.getValue("type"); if (!allOptions.find((item) => item.value === typeValue)) { allOptions.push({ text: typeValue, value: typeValue, }); } return allOptions; })()} /> {moreFields.map((item) => { const { label, type, ...others } = item; const RenderComponent = AllBuiltInComponents[type]; return ( ); })} {readonly ? null : (
    { e.stopPropagation(); }} > {INDEX_MAPPING_TYPES_WITH_CHILDREN.includes(type) ? ( } > ) : null}
    )}
    ); }); export default MappingLabel;