import React, { useEffect, useCallback } from "react";
import type {
WrappedFieldArrayProps,
WrappedFieldMetaProps,
WrappedFieldInputProps,
} from "redux-form";
import { Field, FieldArray } from "redux-form";
import styled from "styled-components";
import type { ControlProps, ControlData } from "./BaseControl";
import BaseControl from "./BaseControl";
import type { ControlType } from "constants/PropertyControlConstants";
import DynamicTextField from "components/editorComponents/form/fields/DynamicTextField";
import type { InputProps } from "design-system";
import { setDefaultKeyValPairFlag } from "actions/datasourceActions";
import { useDispatch } from "react-redux";
import { Button, Input } from "design-system";
export interface KeyValueArrayControlProps extends ControlProps {
name: string;
label: string;
maxLen?: number;
description?: string;
actionConfig?: any;
extraData?: ControlData[];
isRequired?: boolean;
}
const FormRowWithLabel = styled.div`
display: flex;
flex: 1;
flex-direction: row;
align-items: start;
margin-bottom: 5px;
& svg {
cursor: pointer;
}
.form-input-field {
width: 270px;
+ .form-input-field {
margin-left: 5px;
}
}
`;
const StyledInput = styled(Input)`
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
margin: 0px;
}
`;
const StyledButton = styled(Button)`
margin-left: 5px;
`;
const AddMoreButton = styled(Button)``;
function KeyValueRow(
props: KeyValueArrayControlProps & WrappedFieldArrayProps,
) {
const { extraData = [] } = props;
const keyName = getFieldName(extraData[0]?.configProperty);
const valueName = getFieldName(extraData[1]?.configProperty);
const keyFieldProps = extraData[0];
const dispatch = useDispatch();
const addRow = useCallback(() => {
if (keyName && valueName) {
props.fields.push({ [keyName[1]]: "", [valueName[1]]: "" });
} else {
props.fields.push({ key: "", value: "" });
}
}, [keyName, valueName]);
useEffect(() => {
// Always maintain 1 row
if (props.fields.length < 1) {
for (let i = props.fields.length; i < 1; i += 1) {
addRow();
// Since we are initializing one default key value pair, it needs to stored in redux store
// so that it can be used to initilize datasource config form as well
dispatch(setDefaultKeyValPairFlag(props.configProperty));
}
}
}, [props.fields, keyName, valueName]);
useEffect(() => {
if (typeof props.fields.getAll() === "string") {
const fieldsValue: any[] = JSON.parse(`${props.fields.getAll()}`);
props.fields.removeAll();
fieldsValue.forEach((value, index) => {
props.fields.insert(index, value);
});
}
}, [props.fields]);
const isKeyFieldValid = useCallback(
(value: string) => {
if (value && keyFieldProps?.validationRegex) {
const regex = new RegExp(keyFieldProps?.validationRegex);
return regex.test(value)
? { isValid: true }
: { isValid: false, message: keyFieldProps.validationMessage };
}
return { isValid: true };
},
[keyFieldProps?.validationRegex, keyFieldProps?.validationMessage],
);
return typeof props.fields.getAll() === "object" ? (
<>
{props.fields.map((field: any, index: number) => {
let keyTextFieldName = `${field}.key`;
let valueTextFieldName = `${field}.value`;
if (keyName && Array.isArray(keyName) && keyName?.length)
keyTextFieldName = `${field}.${keyName[1]}`;
if (valueName && Array.isArray(valueName) && valueName?.length)
valueTextFieldName = `${field}.${valueName[1]}`;
return (
{!props.actionConfig && (
)}
{!props.actionConfig && (
props.fields.remove(index)}
size="md"
startIcon="delete"
/>
)}
{props.actionConfig && (
)}
);
})}
Add more
>
) : null;
}
class KeyValueArrayControl extends BaseControl {
render() {
const name = getFieldName(this.props.configProperty);
return (
);
}
getControlType(): ControlType {
return "KEYVALUE_ARRAY";
}
}
const getFieldName = (configProperty: string): string[] | undefined => {
if (configProperty) return configProperty.split("[*].");
};
const getType = (dataType: string | undefined) => {
switch (dataType) {
case "PASSWORD":
return "password";
case "NUMBER":
return "number";
default:
return "text";
}
};
function renderInput(
props: InputProps & {
dataType?: "text" | "number" | "password";
placeholder?: string;
defaultValue: string | number;
isRequired: boolean;
isKeyFieldValid?: (value: string) => { isValid: boolean; message: string };
helperText?: string;
} & {
meta: Partial;
input: Partial;
},
): JSX.Element {
return (
);
}
export default KeyValueArrayControl;