skyline/src/components/DetailCard/index.jsx
Jingwei.Zhang 9d438cdb77 fix: Fix copy volume id in backup detail page && error hint
1. Fix copy volume id in backup detail page
2. Fix error hint display

Change-Id: I6e6f482f13c891313a9ef853fb76699efffa1fea
2021-08-25 12:26:21 +08:00

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;