1. Fix copy volume id in backup detail page 2. Fix error hint display Change-Id: I6e6f482f13c891313a9ef853fb76699efffa1fea
161 lines
4.3 KiB
JavaScript
161 lines
4.3 KiB
JavaScript
// Copyright 2021 99cloud
|
|
//
|
|
// Licensed 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 React from 'react';
|
|
import { Row, Col, Skeleton, Tooltip, Typography, Popover } from 'antd';
|
|
import { InfoCircleOutlined } from '@ant-design/icons';
|
|
import { has, get, isNumber, isBoolean } from 'lodash';
|
|
import PropTypes from 'prop-types';
|
|
import classnames from 'classnames';
|
|
import { renderFilterMap } from 'utils/index';
|
|
import Status from 'components/Status';
|
|
import styles from './index.less';
|
|
|
|
const { Paragraph } = Typography;
|
|
|
|
const getContentValue = (value, dataIndex, data, copyable) => {
|
|
const status = get(data, dataIndex);
|
|
// get status
|
|
if (
|
|
dataIndex.toLowerCase().indexOf('status') >= 0 ||
|
|
dataIndex.toLowerCase().indexOf('state') >= 0
|
|
) {
|
|
return <Status status={status} text={value} />;
|
|
}
|
|
// get copyable
|
|
if (value !== '-') {
|
|
if (
|
|
(/_?id/g.test(dataIndex.toLowerCase()) && copyable !== false) ||
|
|
copyable
|
|
) {
|
|
if (isBoolean(copyable)) {
|
|
return <Paragraph copyable>{value}</Paragraph>;
|
|
}
|
|
return <Paragraph copyable={copyable}>{value}</Paragraph>;
|
|
}
|
|
}
|
|
return value || '-';
|
|
};
|
|
|
|
const getContent = (data, option) => {
|
|
const { content, dataIndex, render, valueRender, copyable } = option;
|
|
if (has(option, 'content')) {
|
|
return copyable ? <Paragraph copyable>{content}</Paragraph> : content;
|
|
}
|
|
let value = get(data, dataIndex);
|
|
if (!render) {
|
|
if (valueRender) {
|
|
const renderFunc = renderFilterMap[valueRender];
|
|
value = renderFunc && renderFunc(value);
|
|
}
|
|
} else {
|
|
value = render(value, data);
|
|
}
|
|
if (!isNumber(value)) {
|
|
value = value || '-';
|
|
}
|
|
return getContentValue(value, dataIndex, data, copyable);
|
|
};
|
|
|
|
const renderLabel = (option) => {
|
|
const { label, tooltip = '' } = option;
|
|
if (!tooltip) {
|
|
return label;
|
|
}
|
|
return (
|
|
<Tooltip title={tooltip}>
|
|
<span>{label}</span>
|
|
</Tooltip>
|
|
);
|
|
};
|
|
|
|
const renderOptions = (options, data, loading, labelCol, contentCol) =>
|
|
options.map((option, index) => (
|
|
<Skeleton loading={loading} key={`detail-row-${index}`}>
|
|
<Row className={classnames(styles['card-item'], 'sl-card-item')}>
|
|
<Col span={labelCol}>{renderLabel(option)}</Col>
|
|
<Col span={contentCol}>{getContent(data, option)}</Col>
|
|
</Row>
|
|
</Skeleton>
|
|
));
|
|
|
|
const DetailCard = ({
|
|
title,
|
|
titleHelp,
|
|
loading,
|
|
options,
|
|
data,
|
|
labelCol,
|
|
contentCol,
|
|
className,
|
|
button,
|
|
}) => {
|
|
let titleHelpValue;
|
|
if (titleHelp) {
|
|
titleHelpValue = (
|
|
<Popover
|
|
arrowPointAtCenter="true"
|
|
placement="rightTop"
|
|
content={titleHelp}
|
|
>
|
|
<InfoCircleOutlined className={styles['title-help']} />
|
|
</Popover>
|
|
);
|
|
}
|
|
return (
|
|
<div className={classnames(styles.card, className)}>
|
|
<div className={styles['card-content']}>
|
|
<Skeleton loading={loading}>
|
|
<Row className={classnames(styles['card-item'], 'sl-card-item')}>
|
|
<h3> {title} </h3>
|
|
{titleHelpValue}
|
|
{button}
|
|
</Row>
|
|
</Skeleton>
|
|
{renderOptions(options, data, loading, labelCol, contentCol)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const detailProps = PropTypes.shape({
|
|
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
content: PropTypes.any,
|
|
tooltip: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
dataIndex: PropTypes.string,
|
|
valueRender: PropTypes.string,
|
|
});
|
|
|
|
DetailCard.defaultProps = {
|
|
labelCol: 8,
|
|
contentCol: 16,
|
|
options: [],
|
|
title: '',
|
|
titleHelp: '',
|
|
loading: false,
|
|
data: {},
|
|
};
|
|
|
|
DetailCard.propTypes = {
|
|
title: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
titleHelp: PropTypes.any,
|
|
options: PropTypes.arrayOf(detailProps),
|
|
loading: PropTypes.bool,
|
|
data: PropTypes.object,
|
|
labelCol: PropTypes.number,
|
|
contentCol: PropTypes.number,
|
|
};
|
|
|
|
export default DetailCard;
|