skyline/src/pages/storage/containers/Container/Detail/index.jsx
Jingwei.Zhang ce0042945f refactor: Update style
1. Support style check: stylelint
2. Add stylelint check in lint-staged husky
2. Update styles

Change-Id: Id793b0936e4c3ea27ddef0df794d5b711880599f
2022-03-02 11:04:01 +08:00

308 lines
7.4 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, { useEffect, useState } from 'react';
import { observer, inject } from 'mobx-react';
import { Popover, Col, Row, Skeleton } from 'antd';
import Base from 'containers/List';
import globalObjectStore, { ObjectStore } from 'stores/swift/object';
import { bytesFilter } from 'utils/index';
import { allCanReadPolicy } from 'resources/policy';
import { toJS } from 'mobx';
import { isEqual } from 'lodash';
import { isFolder } from 'resources/container';
import { getStrFromTimestamp } from 'utils/time';
import styles from './index.less';
import actionConfigs from './actions';
function PopUpContent({ item }) {
const { container, name, shortName } = item;
const [data, setData] = useState([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
let timeout = null;
(async function () {
setLoading(true);
const cb = await new ObjectStore().fetchDetail({ container, name });
timeout = setTimeout(() => {
setLoading(false);
setData(cb);
}, 200);
})();
return () => {
clearTimeout(timeout);
};
}, []);
const content = loading ? (
<Skeleton loading={loading} />
) : (
<>
<Row>
<Col span={8}>{t('Name')}</Col>
<Col span={12} style={{ wordBreak: 'break-all' }}>
{shortName}
</Col>
</Row>
{data.etag && (
<Row>
<Col span={8}>{t('Hash')}</Col>
<Col span={12}>{data.etag}</Col>
</Row>
)}
<Row>
<Col span={8}>{t('Content Type')}</Col>
<Col span={12} style={{ wordBreak: 'break-all' }}>
{data.contentType}
</Col>
</Row>
<Row>
<Col span={8}>{t('Created At')}</Col>
<Col span={12}>{getStrFromTimestamp(data.timestamp)}</Col>
</Row>
<Row>
<Col span={8}>{t('Size')}</Col>
<Col span={12}>{bytesFilter(data.size || item.bytes)}</Col>
</Row>
{!isFolder(item) && (
<Row>
<Col span={8}>{t('Origin File Name')}</Col>
<Col span={12} style={{ wordBreak: 'break-all' }}>
{decodeURIComponent(data.originFileName)}
</Col>
</Row>
)}
</>
);
return (
<div key={`object_${name}`} style={{ width: 300 }}>
{content}
</div>
);
}
@inject('rootStore')
@observer
export default class ContainerObject extends Base {
init() {
this.store = globalObjectStore;
}
get policy() {
return allCanReadPolicy;
}
get name() {
return t('container objects');
}
get rowKey() {
return 'name';
}
get actionConfigs() {
return actionConfigs;
}
get clearListUnmount() {
return true;
}
get hasTab() {
return true;
}
get hideDownload() {
return true;
}
get isInFolder() {
const { folder } = this.params;
return !!folder;
}
get ableAutoFresh() {
return false;
}
get primaryActionsExtra() {
const { hasCopy, container } = this.store;
return {
hasCopy,
container,
};
}
getCheckboxProps(record) {
if (isFolder(record)) {
return {
disabled: true,
name: record.shortName,
};
}
}
componentDidUpdate(prevProps) {
if (!isEqual(this.props.match.params, prevProps.match.params)) {
this.handleRefresh(true);
}
}
getRequestFolder = (folder) => {
if (!folder) {
return '';
}
const str = decodeURIComponent(folder);
if (str[str.length - 1] !== '/') {
return `${str}/`;
}
return str;
};
updateFetchParams = (params) => {
const { folder } = this.params;
return {
...params,
folder: this.getRequestFolder(folder),
};
};
getColumns = () => [
{
title: t('Name'),
dataIndex: 'shortName',
render: (name, record) => {
const { type, container } = record;
if (type === 'folder') {
const str = encodeURIComponent(record.name);
return this.getLinkRender('folderDetail', name, {
container,
folder: str,
});
}
return name;
},
},
{
title: t('Size'),
dataIndex: 'bytes',
isHideable: true,
valueRender: 'formatSize',
render: (value, data) => {
if (data.type === 'folder') {
return '-';
}
return bytesFilter(value);
},
},
{
title: t('Last Updated'),
dataIndex: 'last_modified',
isHideable: true,
valueRender: 'sinceTime',
},
{
title: t('Detail Info'),
dataIndex: 'detail',
isHideable: true,
render: (_, data) => {
const content = <PopUpContent item={data} />;
return (
<Popover content={content} destroyTooltipOnHide trigger="click">
<span className="link-class">{t('Detail Info')}</span>
</Popover>
);
},
},
];
get searchFilters() {
return [
{
label: t('Name'),
name: 'shortName',
},
];
}
handleRefresh = (force) => {
const { inAction, inSelect } = this;
if (inAction || (inSelect && !force)) {
return;
}
if (!force && this.autoRefreshCount >= this.autoRefreshCountMax) {
return;
}
if (force) {
this.autoRefreshCount = 0;
}
const { page, limit, sortKey, sortOrder, filters } = this.list;
const params = {
page,
limit,
sortKey,
sortOrder,
...toJS(filters),
silent: !force,
};
if (force) {
params.page = 1;
}
this.handleFetch(params, true);
if (this.inDetailPage && force && this.shouldRefreshDetail) {
this.refreshDetailData();
}
};
renderHeader() {
const { container = '', folder = '' } = this.params || {};
const folders = decodeURIComponent(folder)
.split('/')
.filter((it) => !!it);
const containerLink = {
path: this.getRoutePath('containerDetail', { id: container }),
link: this.getLinkRender('containerDetail', container, { id: container }),
};
const items = [containerLink];
const folderLinks = folders.map((it, index) => {
const path = folders.slice(0, index + 1).join('/');
return {
path: this.getRoutePath('folderDetail', {
container,
folder: encodeURIComponent(path),
}),
link: this.getLinkRender('folderDetail', it, {
container,
folder: encodeURIComponent(path),
}),
};
});
items.push(...folderLinks);
const next = <span className={styles['item-next']}>&gt;</span>;
const itemLinks = items.map((it, index) => {
return (
<span key={it.path}>
{it.link} {index < items.length - 1 && next}
</span>
);
});
return (
<div className={styles['link-header']}>
<span className={styles['link-title']}>{t('Current Path: ')}</span>
{itemLinks}
</div>
);
}
}