diff --git a/src/pages/base/containers/Overview/components/QuotaOverview.jsx b/src/pages/base/containers/Overview/components/QuotaOverview.jsx
index 3f0a8d6a..c17bb5ef 100644
--- a/src/pages/base/containers/Overview/components/QuotaOverview.jsx
+++ b/src/pages/base/containers/Overview/components/QuotaOverview.jsx
@@ -34,8 +34,8 @@ export const quotaCardList = [
{ text: t('Instances'), key: 'instances' },
{ text: t('vCPUs'), key: 'cores' },
{ text: t('Memory'), key: 'ram' },
- { text: t('Server Group'), key: 'server_groups' },
{ text: t('Key Pair'), key: 'key_pairs' },
+ { text: t('Server Group'), key: 'server_groups' },
],
},
{
@@ -66,19 +66,46 @@ export const quotaCardList = [
},
{
text: t('Network'),
- type: '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('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);
@@ -117,30 +144,7 @@ export class QuotaOverview extends Component {
}
get volumeTypesQuota() {
- const volumeTypes = this.volumeTypeData.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: volumeTypes,
- };
+ return getVolumeTypeCards(this.volumeTypeData);
}
get quotaCardList() {
diff --git a/src/pages/identity/containers/Project/actions/QuotaManager.jsx b/src/pages/identity/containers/Project/actions/QuotaManager.jsx
index 93e4b018..67f5f95a 100644
--- a/src/pages/identity/containers/Project/actions/QuotaManager.jsx
+++ b/src/pages/identity/containers/Project/actions/QuotaManager.jsx
@@ -13,10 +13,14 @@
// limitations under the License.
import { inject, observer } from 'mobx-react';
-import globalProjectStore from 'stores/keystone/project';
+import globalProjectStore, { ProjectStore } from 'stores/keystone/project';
import React from 'react';
import { ModalAction } from 'containers/Action';
import { VolumeTypeStore } from 'stores/cinder/volume-type';
+import {
+ quotaCardList,
+ getVolumeTypeCards,
+} from 'pages/base/containers/Overview/components/QuotaOverview';
export class QuotaManager extends ModalAction {
static id = 'quota-management';
@@ -25,33 +29,29 @@ export class QuotaManager extends ModalAction {
init() {
this.store = globalProjectStore;
+ this.projectStore = new ProjectStore();
this.volumeTypeStore = new VolumeTypeStore();
- // this.getQuota();
+ this.getData();
}
get name() {
return t('Edit quota');
}
- componentDidMount() {
- this.getData();
+ async getData() {
+ const { id: project_id } = this.item;
+ await Promise.all([
+ this.projectStore.fetchProjectQuota({
+ project_id,
+ }),
+ this.volumeTypeStore.fetchProjectVolumeTypes(project_id),
+ ]);
+ this.updateDefaultValue();
}
- getData = async () => {
- const { id: project_id } = this.item;
- await this.store.fetchProjectQuota({
- project_id,
- });
- await this.volumeTypeStore.fetchProjectVolumeTypes(project_id);
- };
-
get tips() {
- return (
- <>
- {t(
- 'quota set to -1 means there is no quota limit on the current resource'
- )}
- >
+ return t(
+ 'quota set to -1 means there is no quota limit on the current resource'
);
}
@@ -62,99 +62,21 @@ export class QuotaManager extends ModalAction {
static allowed = () => Promise.resolve(true);
- get volumeTypesData() {
- const volumeTypes = [];
- const { projectVolumeTypes: data = [] } = this.volumeTypeStore;
- if (data[0] && this.formRef.current) {
- data.forEach((item) => {
- volumeTypes.push.apply(volumeTypes, [
- {
- 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 volumeTypes;
- }
-
get defaultValue() {
- const {
- quota: {
- instances,
- cores,
- security_group,
- ram,
- ipsecpolicy,
- key_pairs,
- security_group_rule,
- router,
- volumes,
- network,
- subnet,
- floatingip,
- vpnservice,
- vpntunnel,
- gigabytes,
- backups,
- port,
- backup_gigabytes,
- endpoint_group,
- loadbalancer,
- snapshots,
- server_groups,
- server_group_members,
- },
- } = this.store;
- if (instances && this.formRef.current) {
- const initData = {
- more: false,
- instances: (instances || {}).limit,
- cores: (cores || {}).limit,
- security_group: (security_group || {}).limit,
- ram: (ram || {}).limit,
- ipsecpolicy: (ipsecpolicy || {}).limit,
- key_pairs: (key_pairs || {}).limit,
- security_group_rule: (security_group_rule || {}).limit,
- router: (router || {}).limit,
- volumes: (volumes || {}).limit,
- network: (network || {}).limit,
- subnet: (subnet || {}).limit,
- floatingip: (floatingip || {}).limit,
- vpnservice: (vpnservice || {}).limit,
- vpntunnel: (vpntunnel || {}).limit,
- port: (port || {}).limit,
- gigabytes: (gigabytes || {}).limit,
- backup_gigabytes: (backup_gigabytes || {}).limit,
- backups: (backups || {}).limit,
- snapshots: (snapshots || {}).limit,
- server_groups: (server_groups || {}).limit,
- server_group_members: (server_group_members || {}).limit,
- endpoint_group: (endpoint_group || {}).limit,
- loadbalancer: (loadbalancer || {}).limit,
- };
- // eslint-disable-next-line no-return-assign
- this.volumeTypesData.forEach((i) => {
- initData[i.key] = this.store.quota[i.key].limit;
- });
- this.formRef.current.setFieldsValue(initData);
- }
- return {};
+ const { quota = {} } = this.projectStore;
+ const initData = {};
+ Object.keys(quota).forEach((key) => {
+ const item = this.formItems.find((it) => it.name === key);
+ if (item) {
+ const { limit } = quota[key] || {};
+ initData[key] = limit;
+ }
+ });
+ return initData;
}
- // static allowed = item => Promise.resolve(true);
-
checkMin = (rule, value) => {
- const { quota } = this.store;
+ const { quota } = this.projectStore;
const { field } = rule;
const { used } = quota[field];
const intNum = /^-?\d+$/;
@@ -169,205 +91,107 @@ export class QuotaManager extends ModalAction {
return Promise.resolve();
};
- get formItems() {
+ getTitleLabel = (name, title, hidden) => {
+ const content = (
+
{title}
+ );
+ return {
+ name,
+ label: '',
+ type: 'label',
+ content,
+ wrapperCol: { span: 24 },
+ hidden,
+ };
+ };
+
+ getInputItem(name, label, hidden) {
+ return {
+ name,
+ label,
+ type: 'input-number',
+ labelCol: { span: 12 },
+ colNum: 2,
+ validator: this.checkMin,
+ hidden,
+ };
+ }
+
+ get quotaCardList() {
+ return quotaCardList;
+ }
+
+ getFormItemsByCards(cardType) {
+ const card = this.quotaCardList.find((it) => it.type === cardType);
+ if (!card) {
+ return [];
+ }
+ const { type, text, value } = card;
+ const labelItem = this.getTitleLabel(type, text);
+ const items = value.map((it) => {
+ const { key, text: vText } = it;
+ return this.getInputItem(key, vText);
+ });
+ return [labelItem, ...items];
+ }
+
+ getComputeFormItems() {
+ const formItems = this.getFormItemsByCards('compute');
+ const memberItem = this.getInputItem(
+ 'server_group_members',
+ t('Server Group Member')
+ );
+ return [...formItems, memberItem];
+ }
+
+ get volumeTypeData() {
+ const { projectVolumeTypes: data = [] } = this.volumeTypeStore;
+ return data;
+ }
+
+ getVolumeTypeFormItems() {
const { more } = this.state;
+ const card = getVolumeTypeCards(this.volumeTypeData);
+ const { type, text, value } = card;
+ const newValue = [];
+ value.forEach((it) => newValue.push(...it.value));
+ const labelItem = this.getTitleLabel(type, text, !more);
+ const items = newValue.map((it) =>
+ this.getInputItem(it.key, it.text, !more)
+ );
+ return [labelItem, ...items];
+ }
+
+ get formItems() {
+ const computeFormItems = this.getComputeFormItems();
+ const cinderFormItems = this.getFormItemsByCards('storage');
+ const networkFormItems = this.getFormItemsByCards('networks');
+ const volumeTypeFormItems = this.getVolumeTypeFormItems();
const form = [
- {
- name: 'nova',
- label: t('Compute'),
- type: 'label',
- labelCol: { span: 12, offset: 6 },
- },
- {
- name: 'instances',
- label: t('instance'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'cores',
- label: t('vCPU'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'ram',
- label: t('RAM(GB)'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'key_pairs',
- label: t('keypair'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'server_groups',
- label: t('Server Group'),
- type: 'input-number',
- labelCol: { span: 6 },
- validator: this.checkMin,
- },
- {
- name: 'server_group_members',
- label: t('Server Group Member'),
- type: 'input-number',
- labelCol: { span: 6 },
- validator: this.checkMin,
- },
- {
- name: 'cinder',
- label: t('Storage'),
- type: 'label',
- labelCol: { span: 12, offset: 6 },
- colNum: 2,
- },
- {
- name: 'networks',
- label: t('Network'),
- type: 'label',
- labelCol: { span: 12, offset: 6 },
- colNum: 2,
- },
- {
- name: 'volumes',
- label: t('Volume'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'router',
- label: t('router'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'gigabytes',
- label: `${t('gigabytes')}(GB)`,
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'network',
- label: t('network'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'backups',
- label: t('Backup'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'subnet',
- label: t('subnet'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'backup_gigabytes',
- label: t('Backup Capacity'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'floatingip',
- label: t('floatingip'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'snapshots',
- label: t('Snapshot'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'port',
- label: t('Port'),
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- validator: this.checkMin,
- },
- {
- name: 'security_group',
- label: t('security_group'),
- type: 'input-number',
- labelCol: { span: 6, offset: 12 },
- validator: this.checkMin,
- },
- {
- name: 'security_group_rule',
- label: t('Security Group Rules'),
- type: 'input-number',
- labelCol: { span: 6, offset: 12 },
- validator: this.checkMin,
- },
+ ...computeFormItems,
+ ...cinderFormItems,
+ ...networkFormItems,
{
name: 'more',
label: t('Advanced Options'),
type: 'more',
},
- {
- name: 'cinder_types',
- label: t('Storage Types'),
- type: 'label',
- labelCol: { span: 21, offset: 3 },
- hidden: !more,
- },
+ ...volumeTypeFormItems,
];
-
- this.volumeTypesData.forEach((i) =>
- form.push({
- name: i.key,
- label: i.text,
- type: 'input-number',
- labelCol: { span: 12 },
- colNum: 2,
- hidden: !more,
- validator: this.checkMin,
- })
- );
return form;
}
- onSubmit = async (values) => {
+ getSubmitData(values) {
const { id: project_id } = this.item;
- const { more, cinder, networks, cinder_types, nova, security, ...others } =
- values;
- const results = this.store.updateProjectQuota({
+ const { more, compute, storage, networks, volumeTypes, ...others } = values;
+ return {
project_id,
data: others,
- });
+ };
+ }
+
+ onSubmit = async (body) => {
+ const results = this.store.updateProjectQuota(body);
return results;
};
}
diff --git a/src/stores/keystone/project.js b/src/stores/keystone/project.js
index 0b9ad33a..436c0389 100644
--- a/src/stores/keystone/project.js
+++ b/src/stores/keystone/project.js
@@ -62,18 +62,7 @@ export class ProjectStore extends Base {
return client.neutron.quotas;
}
- @action
- async fetchList({
- limit,
- page,
- sortKey,
- sortOrder,
- conditions,
- ...filters
- } = {}) {
- this.list.isLoading = true;
- // todo: no page, no limit, fetch all
- // const params = { ...filters };
+ async fetchProjects(filters) {
const { tags } = filters;
const [roleAssignmentsReault, projectsResult, roleResult] =
@@ -111,11 +100,25 @@ export class ProjectStore extends Base {
project.group_num = Object.keys(projectGroups).length;
return project;
});
- const items = projects.map(this.mapper);
- const newData = await this.listDidFetch(items);
+ return projects;
+ }
+
+ @action
+ async fetchList({
+ limit,
+ page,
+ sortKey,
+ sortOrder,
+ conditions,
+ ...filters
+ } = {}) {
+ this.list.isLoading = true;
+ const items = await this.fetchProjects(filters);
+ const data = await this.listDidFetch(items, true, filters);
+ const newData = data.map(this.mapper);
this.list.update({
data: newData,
- total: projects.length || 0,
+ total: newData.length || 0,
limit: Number(limit) || 10,
page: Number(page) || 1,
sortKey,
@@ -124,7 +127,7 @@ export class ProjectStore extends Base {
isLoading: false,
...(this.list.silent ? {} : { selectedRowKeys: [] }),
});
- return projects;
+ return items;
}
@action
@@ -212,11 +215,7 @@ export class ProjectStore extends Base {
return this.submitting(this.client.create(reqBody));
}
- @action
- async fetchDetail({ id, silent }) {
- if (!silent) {
- this.isLoading = true;
- }
+ async fetchProject(id) {
const [roleAssignmentsReault, projectResult, roleResult] =
await Promise.all([
this.roleAssignmentClient.list(),
@@ -250,11 +249,21 @@ export class ProjectStore extends Base {
project.user_num = Object.keys(userMapRole).length;
project.group_num = Object.keys(projectGroups).length;
const newItem = await this.detailDidFetch(project);
- this.detail = newItem;
- this.isLoading = false;
return newItem;
}
+ @action
+ async fetchDetail({ id, silent }) {
+ if (!silent) {
+ this.isLoading = true;
+ }
+ const item = await this.fetchProject(id);
+ const detail = this.mapper(item);
+ this.detail = detail;
+ this.isLoading = false;
+ return detail;
+ }
+
@action
async edit({ id, description, name }) {
const reqBody = {
@@ -287,6 +296,7 @@ export class ProjectStore extends Base {
}
});
this.quota = quota;
+ return quota;
}
omitNil = (obj) => {
@@ -298,30 +308,14 @@ export class ProjectStore extends Base {
}, {});
};
- @action
- async updateProjectQuota({ project_id, data }) {
- this.isSubmitting = true;
+ getNovaQuotaBody(data) {
const {
instances,
cores,
ram,
- volumes,
- gigabytes,
- firewall_group,
- security_group_rule,
server_groups,
- snapshots,
- backups,
- backup_gigabytes,
- network,
- router,
- subnet,
- floatingip,
- security_group,
- port,
server_group_members,
key_pairs,
- ...others
} = data;
let ramGb = ram;
if (ram && ram !== -1) {
@@ -337,17 +331,40 @@ export class ProjectStore extends Base {
key_pairs,
}),
};
+ return novaReqBody;
+ }
+
+ getCinderQuotaBody(data) {
+ const { backups, ...others } = data;
+ const rest = {};
+ Object.keys(others).forEach((key) => {
+ if (
+ key.includes('volumes') ||
+ key.includes('gigabytes') ||
+ key.includes('snapshots')
+ ) {
+ rest[key] = others[key];
+ }
+ });
const cinderReqBody = {
quota_set: this.omitNil({
- volumes,
- gigabytes,
- backup_gigabytes,
- snapshots,
backups,
- ...others,
+ ...rest,
}),
};
- const firewallValue = firewall_group ? { firewall_group } : {};
+ return cinderReqBody;
+ }
+
+ getNeutronQuotaBody(data) {
+ const {
+ security_group_rule,
+ network,
+ router,
+ subnet,
+ floatingip,
+ security_group,
+ port,
+ } = data;
const neutronReqBody = {
quota: this.omitNil({
network,
@@ -356,10 +373,16 @@ export class ProjectStore extends Base {
floatingip,
security_group,
security_group_rule,
- ...firewallValue,
port,
}),
};
+ return neutronReqBody;
+ }
+
+ async updateQuota(project_id, data) {
+ const novaReqBody = this.getNovaQuotaBody(data);
+ const cinderReqBody = this.getCinderQuotaBody(data);
+ const neutronReqBody = this.getNeutronQuotaBody(data);
const reqs = [];
if (!isEmpty(novaReqBody.quota_set)) {
reqs.push(client.nova.quotaSets.update(project_id, novaReqBody));
@@ -372,6 +395,13 @@ export class ProjectStore extends Base {
}
const result = await Promise.all(reqs);
+ return result;
+ }
+
+ @action
+ async updateProjectQuota({ project_id, data }) {
+ this.isSubmitting = true;
+ const result = await this.updateQuota(project_id, data);
this.isSubmitting = false;
return result;
}
@@ -461,7 +491,6 @@ export class ProjectStore extends Base {
}
groupResult.groups.forEach((group) => {
if (projectGroups[group.id]) {
- // const id = 3;
project.groupProjectRole = projectGroups[group.id].map(
(it) =>
`${roleResult.roles.filter((role) => role.id === it)[0].name}(${t(
@@ -470,8 +499,6 @@ export class ProjectStore extends Base {
);
}
});
- // const { id } = project;
- // this.getUserRoleList({ id, user_id: userId });
project.user_num = Object.keys(userMapRole).length;
project.group_num = Object.keys(projectGroups).length;
return project;