feat: support quota info when create share

1. Support quota info when create share
2. Disable click submit button when left quota is not enough to create

Change-Id: I6af7cb3c29cad89dbceffb3c33d93eb46d0f963d
This commit is contained in:
Jingwei.Zhang 2022-06-30 17:34:15 +08:00
parent 26df0cefe1
commit a82cd5883d
4 changed files with 181 additions and 18 deletions

View File

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { toJS } from 'mobx';
import { inject, observer } from 'mobx-react';
import { FormAction } from 'containers/Action';
import globalShareStore, { ShareStore } from 'stores/manila/share';
@ -33,13 +32,28 @@ import {
getShareNetworkColumns,
shareNetworkFilters,
} from 'resources/manila/share-network';
import { shareProtocol } from 'resources/manila/share';
import { cloneDeep } from 'lodash';
import {
shareProtocol,
getQuota,
getQuotaInfo,
fetchShareQuota,
checkQuotaDisable,
getShareSizeInStore,
setCreateShareSize,
onShareSizeChange,
} from 'resources/manila/share';
import { cloneDeep, isEmpty } from 'lodash';
import { idNameColumn } from 'utils/table';
import { extraFormItem } from 'pages/share/containers/ShareType/actions/Create';
import { updateAddSelectValueToObj, getOptions } from 'utils/index';
import { checkPolicyRule } from 'resources/skyline/policy';
const quotaKeys = ['shares', 'gigabytes'];
const getWishes = () => {
return [1, getShareSizeInStore() || 1];
};
export class Create extends FormAction {
static id = 'create';
@ -68,16 +82,48 @@ export class Create extends FormAction {
this.shareStore.fetchAvailableZones();
this.state.showNetworks = false;
this.state.shareGroups = [];
this.getQuota();
}
static policy = 'manila:share:create';
static allowed = () => Promise.resolve(true);
get defaultValue() {
async getQuota() {
await fetchShareQuota(this);
setCreateShareSize(this.defaultSize);
this.updateDefaultValue();
}
get disableSubmit() {
const { quota, quotaLoading } = this.state;
if (isEmpty(quota) || quotaLoading) {
return true;
}
return checkQuotaDisable(quotaKeys, getWishes());
}
get showQuota() {
return true;
}
getShareQuota() {
const { quota = {} } = this.state;
return getQuota(quota, quotaKeys);
}
get quotaInfo() {
return getQuotaInfo(this, quotaKeys, getWishes());
}
get defaultSize() {
const size = this.quotaIsLimit && this.maxSize < 10 ? this.maxSize : 10;
return size;
}
get defaultValue() {
const values = {
size,
size: this.defaultSize,
project: this.currentProjectName,
};
return values;
@ -101,24 +147,14 @@ export class Create extends FormAction {
});
};
get quota() {
const { shares: { limit = 10, in_use = 0, reserved = 0 } = {} } =
toJS(this.shareStore.quotaSet) || {};
if (limit === -1) {
return Infinity;
}
return limit - in_use - reserved;
}
get quotaIsLimit() {
const { gigabytes: { limit } = {} } = toJS(this.shareStore.quotaSet) || {};
const { gigabytes: { limit } = {} } = this.getShareQuota();
return limit !== -1;
}
get maxSize() {
const { gigabytes: { limit = 10, in_use = 0, reserved = 0 } = {} } =
toJS(this.shareStore.quotaSet) || {};
return limit - in_use - reserved;
const { gigabytes: { left = 0 } = {} } = this.getShareQuota();
return left === -1 ? 1000 : left || 1;
}
get shareTypeColumns() {
@ -195,6 +231,7 @@ export class Create extends FormAction {
description: `${minSize}GiB-${this.maxSize}GiB`,
required: this.quotaIsLimit,
display: this.quotaIsLimit,
onChange: onShareSizeChange,
},
{
name: 'size',
@ -203,6 +240,7 @@ export class Create extends FormAction {
min: minSize,
display: !this.quotaIsLimit,
required: !this.quotaIsLimit,
onChange: onShareSizeChange,
},
{
name: 'is_public',

View File

@ -1,3 +1,7 @@
import globalProjectStore from 'stores/keystone/project';
import { isEmpty } from 'lodash';
import globalShareStore from 'src/stores/manila/share';
export const shareStatus = {
creating: t('Creating'),
creating_from_snapshot: t('Creating From Snapshot'),
@ -72,3 +76,102 @@ export const shareAccessType = {
user: t('User'),
cephx: t('Cephx'),
};
// deal with quota
export function setCreateShareSize(value) {
globalShareStore.setCreateShareSize(value);
}
export async function fetchShareQuota(self) {
self.setState({
quota: {},
quotaLoading: true,
});
const result = await globalProjectStore.fetchProjectShareQuota();
self.setState({
quota: result,
quotaLoading: false,
});
}
export const getQuota = (shareQuota, quotaKeys = ['shares', 'gigabytes']) => {
if (isEmpty(shareQuota)) {
return {};
}
return quotaKeys.reduce((pre, cur) => {
pre[cur] = shareQuota[cur] || {};
return pre;
}, {});
};
export const getAdd = (
shareQuota,
quotaKeys = ['shares', 'gigabytes'],
wishes = [1, 1]
) => {
if (isEmpty(shareQuota)) {
return [];
}
const info = getQuota(shareQuota, quotaKeys);
let hasError = false;
quotaKeys.forEach((key, index) => {
if (!hasError) {
const quotaDetail = info[key];
const { left = 0 } = quotaDetail || {};
const wish = wishes[index];
if (left !== -1 && left < wish) {
hasError = true;
}
}
});
if (!hasError) {
return wishes;
}
return new Array(quotaKeys.length).fill(0);
};
const titleMap = {
shares: t('Share'),
gigabytes: t('Share Gigabytes(GiB)'),
share_networks: t('Share Network'),
share_groups: t('Share group'),
};
export const getQuotaInfo = (
self,
quotaKeys = ['shares', 'gigabytes'],
wishes = [1, 1]
) => {
const { quota = {}, quotaLoading } = self.state;
if (quotaLoading || isEmpty(quota)) {
return [];
}
const adds = getAdd(quota, quotaKeys, wishes);
const infos = getQuota(quota, quotaKeys);
return quotaKeys.map((key, index) => {
const type = index === 0 ? 'ring' : 'line';
const title = titleMap[key];
const info = infos[key] || {};
return {
...info,
add: adds[index],
name: key,
title,
type,
};
});
};
export const checkQuotaDisable = (quotaKeys, wishes) => {
const { shareQuota = {} } = globalProjectStore;
const adds = getAdd(shareQuota, quotaKeys, wishes);
return adds[0] === 0;
};
export const onShareSizeChange = (value) => {
setCreateShareSize(value);
};
export const getShareSizeInStore = () => {
return globalShareStore.shareSizeForCreate;
};

View File

@ -33,6 +33,9 @@ export class ProjectStore extends Base {
@observable
cinderQuota = {};
@observable
shareQuota = {};
@observable
groupRoleList = [];
@ -503,6 +506,17 @@ export class ProjectStore extends Base {
this.cinderQuota = cinderQuota;
return cinderQuota;
}
@action
async fetchProjectShareQuota(projectId) {
const result = await this.shareQuotaClient.showDetail(
projectId || this.currentProjectId
);
const { quota_set: quota } = result;
const shareQuota = this.updateQuotaData(quota);
this.shareQuota = shareQuota;
return shareQuota;
}
}
const globalProjectStore = new ProjectStore();

View File

@ -26,6 +26,9 @@ export class ShareStore extends Base {
@observable
quotaSet = {};
@observable
shareSizeForCreate = 0;
get client() {
return client.manila.shares;
}
@ -168,6 +171,11 @@ export class ShareStore extends Base {
@action
delete = (data) => this.submitting(this.deleteItem(data));
@action
setCreateShareSize(size = 0) {
this.shareSizeForCreate = size;
}
}
const globalShareStore = new ShareStore();