blob: 63c07d195519f9f3fde29f92a0712bfb6b192736 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { AutoComplete, Button, Col, Drawer, Form, notification, Row } from 'antd';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useIntl } from 'umi';
import { transformLabelValueToKeyValue } from '../../helpers';
type Props = {
title?: string;
actionName: string;
dataSource: string[];
filterList?: string[];
fetchLabelList: any;
disabled: boolean;
onClose: () => void;
} & Pick<RouteModule.Step1PassProps, 'onChange'>;
const LabelList = (disabled: boolean, labelList: LabelList, filterList: string[] = []) => {
const { formatMessage } = useIntl();
const keyOptions = useMemo(
() =>
Object.keys(labelList || {})
.filter((item) => !filterList.includes(item))
.map((item) => ({ value: item })),
[labelList, filterList],
);
return (
<Form.List name="labels">
{(fields, { add, remove }) => {
return (
<>
{fields.map((field, index) => (
<Form.Item
key={field.key}
label={index === 0 && 'Label'}
labelCol={{ span: index === 0 ? 3 : 0 }}
wrapperCol={{ offset: index === 0 ? 0 : 3 }}
>
<Row style={{ marginBottom: 10 }} gutter={16}>
<Col>
<Form.Item
style={{ marginBottom: 0 }}
name={[field.name, 'labelKey']}
rules={[
{
required: true,
message: 'Please input key',
},
]}
>
<AutoComplete options={keyOptions} style={{ width: 100 }} />
</Form.Item>
</Col>
<Col>
<Form.Item shouldUpdate noStyle>
{({ getFieldValue }) => {
const key = getFieldValue(['labels', field.name, 'labelKey']);
let valueOptions = [{ value: '' }];
if (labelList) {
valueOptions = (labelList[key] || []).map((item) => ({ value: item }));
}
return (
<Form.Item
noStyle
name={[field.name, 'labelValue']}
fieldKey={[field.fieldKey, 'labelValue']}
rules={[
{
required: true,
message: 'Please input value',
},
]}
>
<AutoComplete options={valueOptions} style={{ width: 100 }} />
</Form.Item>
);
}}
</Form.Item>
</Col>
<Col>
{!disabled && <MinusCircleOutlined onClick={() => remove(field.name)} />}
</Col>
</Row>
</Form.Item>
))}
{!disabled && (
<Form.Item wrapperCol={{ offset: 3 }}>
<Button type="dashed" onClick={add}>
<PlusOutlined />
{formatMessage({ id: 'component.global.add' })}
</Button>
</Form.Item>
)}
</>
);
}}
</Form.List>
);
};
const LabelsDrawer: React.FC<Props> = ({
title = '',
actionName = '',
disabled = false,
dataSource = [],
filterList = [],
fetchLabelList,
onClose,
onChange = () => {},
}) => {
const { formatMessage } = useIntl();
const [form] = Form.useForm();
const [labelList, setLabelList] = useState<LabelList>();
useEffect(() => {
fetchLabelList().then(setLabelList);
}, []);
useEffect(() => {
const transformLabel = transformLabelValueToKeyValue(dataSource);
form.setFieldsValue({ labels: transformLabel });
}, [form.setFieldsValue, dataSource]);
const onClick: React.MouseEventHandler<HTMLElement> = useCallback(
function onClick(e) {
e.persist();
form.validateFields().then(({ labels }) => {
const data = labels.map((item: any) => `${item.labelKey}:${item.labelValue}`);
// check for duplicates
if (new Set(data).size !== data.length) {
notification.warning({
message: `Config Error`,
description: 'Please do not enter duplicate labels',
});
return;
}
onChange({
action: actionName,
data,
});
onClose();
});
},
[form, actionName, onChange, onClose],
);
return (
<Drawer
title={title || formatMessage({ id: 'component.label-manager' })}
placement="right"
width={512}
visible
closable
onClose={onClose}
maskClosable={false}
footer={
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Button onClick={onClose}>{formatMessage({ id: 'component.global.cancel' })}</Button>
<Button type="primary" style={{ marginRight: 8, marginLeft: 8 }} onClick={onClick}>
{formatMessage({ id: 'component.global.confirm' })}
</Button>
</div>
}
>
<Form form={form} layout="horizontal">
{LabelList(disabled, labelList || {}, filterList)}
</Form>
</Drawer>
);
};
export default LabelsDrawer;