Merge "feat: Show quota info when create server group"

This commit is contained in:
Zuul 2022-06-22 15:35:29 +00:00 committed by Gerrit Code Review
commit b8caadf202
6 changed files with 150 additions and 27 deletions

View File

@ -74,8 +74,8 @@ export default class BaseForm extends React.Component {
this.unMountActions && this.unMountActions();
}
get canSubmit() {
return true;
get disableSubmit() {
return false;
}
get name() {
@ -534,7 +534,7 @@ export default class BaseForm extends React.Component {
{t('Cancel')}
</Button>
<Button
disabled={!this.canSubmit}
disabled={this.disableSubmit}
type="primary"
className={styles.submit}
onClick={this.onClickSubmit}
@ -651,6 +651,9 @@ export default class BaseForm extends React.Component {
}
renderRightTopExtra() {
if (this.isModal) {
return null;
}
const content = this.renderQuota();
if (!content) {
return null;
@ -663,6 +666,17 @@ export default class BaseForm extends React.Component {
);
}
renderModalRightExtra() {
if (!this.isModal) {
return null;
}
const content = this.renderQuota();
if (!content) {
return null;
}
return <div className={styles['modal-right-extra-wrapper']}>{content}</div>;
}
render() {
const wrapperPadding =
this.listUrl || this.isStep || (this.isModal && this.tips)
@ -679,18 +693,31 @@ export default class BaseForm extends React.Component {
formStyle.height = `calc(100% - ${tipHeight}px)`;
}
}
const formDiv = (
<Spin spinning={this.isSubmitting} tip={this.renderSubmittingTip()}>
{tips}
{this.renderRightTopExtra()}
<div className={classnames(styles.form, 'sl-form')} style={formStyle}>
{this.renderForms()}
</div>
{this.renderFooter()}
</Spin>
);
const onlyForm = !this.isModal || (this.isModal && !this.showQuota);
const modalInner =
this.isModal && !onlyForm ? (
<Row justify="space-between" align="top">
<Col span={18}>{formDiv}</Col>
<Col span={6}>{this.renderModalRightExtra()}</Col>
</Row>
) : null;
return (
<div
className={classnames(styles.wrapper, wrapperPadding, this.className)}
>
<Spin spinning={this.isSubmitting} tip={this.renderSubmittingTip()}>
{tips}
{this.renderRightTopExtra()}
<div className={classnames(styles.form, 'sl-form')} style={formStyle}>
{this.renderForms()}
</div>
{this.renderFooter()}
</Spin>
{onlyForm && formDiv}
{modalInner}
</div>
);
}

View File

@ -139,3 +139,7 @@
}
}
}
.modal-right-extra-wrapper {
border-left: solid 2px @gray-2;
}

View File

@ -429,16 +429,18 @@ export class ActionButton extends Component {
callback();
};
getModalWidth = (size) => {
getModalWidth = (action) => {
const { modalSize: size, showQuota = false } = action;
const multi = showQuota ? 1.25 : 1;
switch (size) {
case 'small':
return 520;
return 520 * multi;
case 'middle':
return 720;
return 720 * multi;
case 'large':
return 1200;
return 1200 * multi;
default:
return 520;
return 520 * multi;
}
};
@ -455,8 +457,15 @@ export class ActionButton extends Component {
}
const { title, action, item, containerProps, items } = this.props;
const ActionComponent = action;
const { modalSize, okText, cancelText, id, className, readOnly } = action;
const width = this.getModalWidth(modalSize);
const {
okText,
cancelText,
id,
className,
readOnly,
disableSubmit = false,
} = action;
const width = this.getModalWidth(action);
const modalProps = {
title,
visible,
@ -464,6 +473,9 @@ export class ActionButton extends Component {
width,
onOk: () => this.onClickModalActionOk(),
onCancel: this.onClickModalActionCancel,
okButtonProps: {
disabled: disableSubmit,
},
confirmLoading: submitLoading,
okText,
cancelText,

View File

@ -42,6 +42,14 @@ export default class ModalAction extends BaseForm {
return 'small';
}
static get showQuota() {
return false;
}
get showQuota() {
return false;
}
get labelCol() {
const size = this.getModalSize();
if (size === 'large') {

View File

@ -17,6 +17,7 @@ import { inject, observer } from 'mobx-react';
import globalServerGroupStore from 'stores/nova/server-group';
import { ModalAction } from 'containers/Action';
import policyType from 'resources/nova/server-group';
import globalProjectStore from 'src/stores/keystone/project';
export class Create extends ModalAction {
static id = 'create';
@ -24,7 +25,11 @@ export class Create extends ModalAction {
static title = t('Create Server Group');
init() {
this.state.quota = {};
this.state.quotaLoading = true;
this.store = globalServerGroupStore;
this.projectStore = globalProjectStore;
this.getQuota();
}
get name() {
@ -35,6 +40,45 @@ export class Create extends ModalAction {
static allowed = () => Promise.resolve(true);
static get disableSubmit() {
const { novaQuota: { server_groups: { left = 0 } = {} } = {} } =
globalProjectStore;
return left === 0;
}
static get showQuota() {
return true;
}
get showQuota() {
return true;
}
async getQuota() {
const result = await this.projectStore.fetchProjectNovaQuota();
const { server_groups: quota = {} } = result || {};
this.setState({
quota,
quotaLoading: false,
});
}
get quotaInfo() {
const { quota = {}, quotaLoading } = this.state;
if (quotaLoading) {
return [];
}
const { left = 0 } = quota;
const add = left === 0 ? 0 : 1;
const data = {
...quota,
add,
name: 'server_groups',
title: t('Server Group'),
};
return [data];
}
get formItems() {
const policies = Object.keys(policyType).map((it) => ({
value: it,

View File

@ -14,7 +14,7 @@
import { action, observable } from 'mobx';
import { getGiBValue } from 'utils/index';
import { isNil, isEmpty } from 'lodash';
import { isNil, isEmpty, isObject } from 'lodash';
import client from 'client';
import Base from 'stores/base';
import globalRootStore from 'stores/root';
@ -23,6 +23,9 @@ export class ProjectStore extends Base {
@observable
quota = {};
@observable
novaQuota = {};
@observable
groupRoleList = [];
@ -261,14 +264,9 @@ export class ProjectStore extends Base {
...neutronQuota,
...renameShareQuota,
};
const quotaKey = Object.keys(quota);
quotaKey.forEach((it) => {
if (quota[it].in_use !== undefined) {
quota[it].used = quota[it].in_use;
}
});
this.quota = quota;
return quota;
const newQuota = this.updateQuotaData(quota);
this.quota = newQuota;
return newQuota;
}
omitNil = (obj) => {
@ -437,6 +435,36 @@ export class ProjectStore extends Base {
const result = await this.client.groups.roles.delete(id, groupId, roleId);
return result;
}
getLeftQuotaData = (data) => {
const { used = 0, limit = 0, reserved = 0 } = data;
if (limit === -1) {
return -1;
}
return limit - used - reserved;
};
updateQuotaData = (quota) => {
const newData = JSON.parse(JSON.stringify(quota));
Object.keys(newData).forEach((it) => {
if (isObject(newData[it])) {
if (newData[it].in_use !== undefined) {
newData[it].used = newData[it].in_use;
}
newData[it].left = this.getLeftQuotaData(newData[it]);
}
});
return newData;
};
@action
async fetchProjectNovaQuota() {
const result = await this.novaQuotaClient.detail(this.currentProjectId);
const { quota_set: quota } = result;
const novaQuota = this.updateQuotaData(quota);
this.novaQuota = novaQuota;
return novaQuota;
}
}
const globalProjectStore = new ProjectStore();