// 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 { parse } from 'qs';
import classnames from 'classnames';
import { isEmpty, get } from 'lodash';
import { renderFilterMap, isAdminPage } from 'utils/index';
import { Button, Divider, Tabs, Typography } from 'antd';
import { UpOutlined, DownOutlined } from '@ant-design/icons';
import NotFound from 'components/Cards/NotFound';
import Infos from 'components/Infos';
import Notify from 'components/Notify';
import { toJS } from 'mobx';
import checkItemPolicy from 'resources/policy';
import ItemActionButtons from 'components/Tables/Base/ItemActionButtons';
import { emptyActionConfig } from 'utils/constants';
import styles from './index.less';
export default class DetailBase extends React.Component {
constructor(props, options = {}) {
super(props);
this.options = options;
this.state = {
notFound: false,
collapsed: false,
};
this.init();
}
componentDidMount() {
this.fetchDataWithPolicy();
}
get params() {
return this.props.match.params || {};
}
get id() {
return this.props.match.params.id;
}
get name() {
return '';
}
get routing() {
return this.props.rootStore.routing;
}
get isAdminPage() {
const { pathname } = this.props.location;
return isAdminPage(pathname);
}
getUrl(path, adminStr) {
return this.isAdminPage ? `${path}${adminStr || '-admin'}` : path;
}
get tabs() {
return [];
}
get tab() {
if (this.tabs.length === 0) {
return null;
}
const params = parse(this.routing.location.search.slice(1));
const { tab } = params;
const tabItem = this.tabs.find((it) => it.key === tab);
return tabItem || this.tabs[0];
}
get actionConfigs() {
return emptyActionConfig;
}
get rowActions() {
return [];
}
onCollapedCallback = () => {};
handleChangeTab = (tab) => {
// this.setState({
// tab
// });
this.handleFetch({ tab }, true);
};
handleFetch = (params, refresh) => {
this.routing.query(params, refresh);
};
get detailTabs() {
const tabs = [
{
title: 'tab1',
key: 'tab1',
component: null,
},
{
title: 'tab2',
key: 'tab2',
component: null,
},
];
return tabs;
}
get detailTitle() {
const { id } = this.params;
const { collapsed } = this.state;
const { Paragraph } = Typography;
const icon = collapsed ? : ;
return (
);
}
get className() {
return '';
}
get listUrl() {
return '/base/tmp';
}
get detailData() {
return toJS(this.store.detail) || {};
}
get isLoading() {
return this.store.isLoading;
}
get detailInfos() {
return [];
}
// After the operation, the refreshed Tab needs to be forced to load
get forceLoadingTabs() {
return [];
}
handleDetailInfo = () => {
const { collapsed } = this.state;
this.setState(
{
collapsed: !collapsed,
},
() => {
this.onCollapedCallback(!collapsed);
}
);
};
getDesc = (data, dataConf) => {
const { dataIndex, render, valueRender } = dataConf;
if (render) {
return render(data[dataIndex], data);
}
if (valueRender) {
const renderFunc = renderFilterMap[valueRender];
return renderFunc && renderFunc(data[dataIndex]);
}
const desc = get(data, dataIndex);
if (desc === undefined || desc === '') {
return '-';
}
return desc;
};
getActionData() {
return this.detailData;
}
fetchData = (params, silent) => {
if (this.store.fetchDetail) {
const newParams = {
...this.params,
...(params || {}),
all_projects: this.isAdminPage,
silent,
};
const realParams = this.updateFetchParams(newParams);
this.store.fetchDetail(realParams).catch(this.catch);
}
};
getRouteProps = () => ({});
fetchDataWithPolicy = (silent, params) => {
if (!checkItemPolicy({ policy: this.policy, actionName: this.name })) {
const error = {
message: t("You don't have access to get {name}.", {
name: this.name.toLowerCase(),
}),
status: 401,
};
Notify.errorWithDetail(
error,
t('Unable to get {name} detail.', { name: this.name.toLowerCase() })
);
return;
}
this.fetchData(params, silent);
};
refreshDetailByTab = () => {
this.fetchDataWithPolicy(true);
};
refreshDetailByAction = (silence) => {
this.fetchDataWithPolicy(silence);
};
catch = (e) => {
// eslint-disable-next-line no-console
console.log(e);
const { data, status } = (e || {}).response || e || {};
if (status === 404) {
this.setState({ notFound: true });
Notify.warn(
t('{name} {id} could not be found.', {
name: this.name.toLowerCase(),
id: this.id,
})
);
} else {
const error = {
message: data,
status,
};
Notify.errorWithDetail(
error,
t('Get {name} detail error.', { name: this.name.toLowerCase() })
);
}
};
goBack = () => {
this.routing.push(this.listUrl);
};
updateFetchParams = (params) => params;
onFinishAction = (success, fail, isDelete) => {
if (success && isDelete) {
this.goBack();
} else {
const silence = !this.forceLoadingTabs.includes(this.tab.key);
this.refreshDetailByAction(silence);
}
};
init() {
this.store = {
detail: {},
isLoading: true,
};
}
renderDetailInfos() {
const { Paragraph } = Typography;
const { collapsed } = this.state;
if (isEmpty(this.detailData)) {
return (
);
}
const descriptions = collapsed
? []
: this.detailInfos
.filter((it) => !it.hidden)
.map((it) => {
const { title, dataIndex, copyable } = it;
let desc;
if (
this.isLoading ||
!this.detailData ||
isEmpty(this.detailData)
) {
desc = '-';
} else {
desc = this.getDesc(this.detailData, it);
if (desc !== '-') {
if (
copyable ||
dataIndex.toLowerCase().indexOf('id') === 0 ||
dataIndex.toLowerCase().indexOf('_id') >= 0
) {
desc = (
{desc}
);
}
}
}
return {
label: title,
content: desc,
};
});
return (
);
}
renderTabComponent(tabItem) {
const { component, key } = tabItem;
return component ? (
) : (
{key}
);
}
renderTab(tabKey, tabItem) {
if (tabKey !== tabItem.key) {
return ;
}
return (
{this.renderTabComponent(tabItem)}
);
}
renderTabs() {
if (isEmpty(this.detailData) || this.isLoading) {
return null;
}
if (!this.tab) {
return null;
}
const tabPanes = this.tabs.map((it) => this.renderTab(this.tab.key, it));
return (
{tabPanes}
);
}
renderActions() {
const data = this.getActionData();
if (isEmpty(data)) {
return null;
}
return (
);
}
render() {
if (this.state.notFound) {
return ;
}
return (
{this.renderActions()}
{this.renderDetailInfos()}
{this.renderTabs()}
);
}
}