// 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, { Component } from 'react'; import { Badge, Card, Col, List, Progress, Row, Spin, Tooltip } from 'antd'; import { inject, observer } from 'mobx-react'; import globalVolumeTypeStore from 'stores/cinder/volume-type'; import globalProjectStore from 'stores/keystone/project'; import globalRootStore from 'stores/root'; import { isNumber } from 'lodash'; import styles from '../style.less'; const colors = { normal: { color: '#4CC9F0', text: t('Normal') }, danger: { color: '#4361EE', text: t('Danger') }, full: { color: '#E8684A', text: t('Full') }, }; export const quotaCardList = [ { text: t('Compute'), type: 'compute', value: [ { text: t('Instances'), key: 'instances' }, { text: t('vCPUs'), key: 'cores' }, { text: t('Memory'), key: 'ram' }, { text: t('Key Pair'), key: 'key_pairs' }, { text: t('Server Group'), key: 'server_groups' }, ], }, { text: t('Storage'), type: 'storage', value: [ { text: t('volumes'), key: 'volumes', }, { text: t('Gigabytes(GB)'), key: 'gigabytes', }, { text: t('Snapshots'), key: 'snapshots', }, { text: t('backups'), key: 'backups', }, { text: t('backup gigabytes (GiB)'), key: 'backup_gigabytes', }, ], }, { text: t('Network'), type: 'networks', value: [ { text: t('Router'), key: 'router' }, { text: t('Network'), key: 'network' }, { text: t('Subnet'), key: 'subnet' }, { text: t('Floating IP'), key: 'floatingip' }, { text: t('Port'), key: 'port' }, { text: t('Security Group'), key: 'security_group' }, { text: t('Security Group Rule'), key: 'security_group_rule' }, ], }, ]; export const getVolumeTypeCards = (data) => { const value = data.map((item, index) => { return { index, value: [ { text: t('{name} type', { name: item.name }), key: `volumes_${item.name}`, }, { text: t('{name} type gigabytes(GB)', { name: item.name }), key: `gigabytes_${item.name}`, }, { text: t('{name} type snapshots', { name: item.name }), key: `snapshots_${item.name}`, }, ], }; }); return { text: t('Storage Types'), type: 'volumeTypes', value, }; }; export class QuotaOverview extends Component { constructor(props) { super(props); this.state = { isLoading: true, }; const { projectStore, volumeTypeStore } = props; this.projectStore = projectStore || globalProjectStore; this.volumeTypeStore = volumeTypeStore || globalVolumeTypeStore; } componentDidMount() { this.getData(); } async getData() { const { getData } = this.props; if (getData) { await getData(); } else { const { user } = this.props.rootStore; const { project: { id: projectId = '' } = {} } = user; const promiseArr = [ this.projectStore.fetchProjectQuota({ project_id: projectId }), ]; if (this.enableCinder) { promiseArr.push(this.volumeTypeStore.fetchList()); } await Promise.all(promiseArr); } this.setState({ isLoading: false, }); } get enableCinder() { return globalRootStore.checkEndpoint('cinder'); } get volumeTypeData() { const { volumeTypeData } = this.props; return volumeTypeData || this.volumeTypeStore.list.data; } get volumeTypesQuota() { return getVolumeTypeCards(this.volumeTypeData); } get quotaCardList() { const list = this.props.quotaCardList || quotaCardList; if (!this.enableCinder) { return list.filter((it) => it.type !== 'storage'); } return list; } get quotaAction() { return this.props.quotaAction; } getFilteredValue = (value) => value.filter((it) => !it.hidden); getItemInfo = (data, i) => { let percent = 0; if (data[i.key] && isNumber(data[i.key].used) && data[i.key].limit !== -1) { percent = (data[i.key].used / data[i.key].limit) * 100; } let used = '-'; if (data[i.key] && isNumber(data[i.key].used)) { used = `${data[i.key].used} / ${ data[i.key].limit === -1 ? t('Unlimit') : data[i.key].limit }`; } const strokeColor = (percent >= 90 && colors.full.color) || (percent >= 80 && colors.danger.color) || colors.normal.color; let title = `${i.text} : ${used}`; const { server_group_members } = data; if (i.key === 'server_groups' && server_group_members) { title = `${title} (${t('Member in group')} : ${ server_group_members.limit === -1 ? t('Unlimit') : server_group_members.limit })`; } return ( <>
{title}
); }; renderQuotaCardList = () => { const { isLoading } = this.state; return ( {this.quotaCardList.map((item) => ( {this.renderQuotaCardContent(item)} ))} {this.enableCinder ? ( {this.renderVolumeTypes()} ) : null} ); }; renderQuotaCardContent(item) { const { isLoading } = this.state; if (isLoading) { return ; } return this.renderQuotaCart( this.projectStore.quota, this.getFilteredValue(item.value) ); } renderQuotaCart = (data, item = []) => item.map((i) =>
{this.getItemInfo(data, i)}
); renderVolumeTypes = () => { const { isLoading } = this.state; if (isLoading) { return ; } return ( ( {item.value.map((i) => ( {this.getItemInfo(this.projectStore.quota, i)} ))} )} /> ); }; render() { const { isLoading } = this.state; return ( {t('Quota Overview')} {Object.keys(colors).map((key) => ( ))} } extra={this.quotaAction} > {this.renderQuotaCardList()} ); } } export default inject('rootStore')(observer(QuotaOverview));