diff --git a/src/components/MagicInput/index.less b/src/components/MagicInput/index.less index 86330912..95ced803 100644 --- a/src/components/MagicInput/index.less +++ b/src/components/MagicInput/index.less @@ -166,7 +166,7 @@ } .magic-input-checks { - min-width: 120px; + min-width: 158px; margin-left: 8px; line-height: 32px; } diff --git a/src/pages/compute/containers/Flavor/actions/ManageAccess.jsx b/src/pages/compute/containers/Flavor/actions/ManageAccess.jsx index 442a1bad..7d4a54d0 100644 --- a/src/pages/compute/containers/Flavor/actions/ManageAccess.jsx +++ b/src/pages/compute/containers/Flavor/actions/ManageAccess.jsx @@ -56,7 +56,7 @@ export class ManageAccess extends ModalAction { } async getProjects() { - await this.projectStore.fetchList(); + await this.projectStore.fetchProjectsWithDomain(); this.updateDefaultValue(); } diff --git a/src/pages/compute/containers/Flavor/actions/StepCreate/AccessTypeSetting.jsx b/src/pages/compute/containers/Flavor/actions/StepCreate/AccessTypeSetting.jsx index 12a3685f..0177a810 100644 --- a/src/pages/compute/containers/Flavor/actions/StepCreate/AccessTypeSetting.jsx +++ b/src/pages/compute/containers/Flavor/actions/StepCreate/AccessTypeSetting.jsx @@ -48,8 +48,9 @@ export class AccessTypeSetting extends Base { ]; } - getProjects() { - this.projectStore.fetchList(); + async getProjects() { + this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); } get formItems() { diff --git a/src/pages/compute/containers/Image/actions/Create.jsx b/src/pages/compute/containers/Image/actions/Create.jsx index 8aa0f452..dd0bcb28 100644 --- a/src/pages/compute/containers/Image/actions/Create.jsx +++ b/src/pages/compute/containers/Image/actions/Create.jsx @@ -31,7 +31,7 @@ export class CreateForm extends FormAction { init() { this.store = globalImageStore; this.projectStore = new ProjectStore(); - this.getProjects(); + this.isAdminPage && this.getProjects(); } static id = 'image-create'; @@ -72,10 +72,9 @@ export class CreateForm extends FormAction { return Promise.resolve(true); } - getProjects() { - if (this.isAdminPage) { - this.projectStore.fetchList(); - } + async getProjects() { + await this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); } get projects() { diff --git a/src/pages/compute/containers/Image/actions/ManageAccess.jsx b/src/pages/compute/containers/Image/actions/ManageAccess.jsx index 7a7f96e2..f3aaa3af 100644 --- a/src/pages/compute/containers/Image/actions/ManageAccess.jsx +++ b/src/pages/compute/containers/Image/actions/ManageAccess.jsx @@ -53,7 +53,7 @@ export class ManageAccess extends ModalAction { } async getProjects() { - await this.projectStore.fetchList(); + await this.projectStore.fetchProjectsWithDomain(); this.updateDefaultValue(); } diff --git a/src/pages/compute/containers/Instance/index.jsx b/src/pages/compute/containers/Instance/index.jsx index 6e6f9023..729cd4de 100644 --- a/src/pages/compute/containers/Instance/index.jsx +++ b/src/pages/compute/containers/Instance/index.jsx @@ -257,6 +257,10 @@ export class Instance extends Base { label: t('Project Name'), name: 'project_name', }, + { + label: t('Project ID'), + name: 'project_id', + }, ] : []), ...(this.isAdminPage && !this.inHostDetailPage diff --git a/src/pages/identity/containers/Project/index.jsx b/src/pages/identity/containers/Project/index.jsx index fdae6995..b28a61ab 100644 --- a/src/pages/identity/containers/Project/index.jsx +++ b/src/pages/identity/containers/Project/index.jsx @@ -284,6 +284,10 @@ export class Projects extends Base { label: t('Project Name'), name: 'name', }, + { + label: t('Project ID'), + name: 'id', + }, { label: t('Enabled'), name: 'enabled', diff --git a/src/pages/identity/containers/User/actions/Edit.jsx b/src/pages/identity/containers/User/actions/Edit.jsx index 93d4c7d1..fa814edb 100644 --- a/src/pages/identity/containers/User/actions/Edit.jsx +++ b/src/pages/identity/containers/User/actions/Edit.jsx @@ -21,6 +21,10 @@ import parsePhoneNumberFromString from 'libphonenumber-js'; export class EditForm extends ModalAction { init() { this.store = globalUserStore; + const { + list: { data }, + } = this.store; + data.length === 0 && this.store.fetchList(); } static id = 'user-edit'; diff --git a/src/pages/network/containers/FloatingIp/actions/Allocate.jsx b/src/pages/network/containers/FloatingIp/actions/Allocate.jsx index 94d4cba0..f34ba1e4 100644 --- a/src/pages/network/containers/FloatingIp/actions/Allocate.jsx +++ b/src/pages/network/containers/FloatingIp/actions/Allocate.jsx @@ -22,6 +22,9 @@ import globalSubnetStore from 'stores/neutron/subnet'; import { QoSPolicyStore } from 'stores/neutron/qos-policy'; import { getQoSPolicyTabs } from 'resources/neutron/qos-policy'; import { qosEndpoint } from 'client/client/constants'; +import { projectTableOptions } from 'resources/keystone/project'; +import { isAdminPage } from 'utils'; +import { toJS } from 'mobx'; export class Allocate extends ModalAction { static id = 'allocate'; @@ -33,11 +36,12 @@ export class Allocate extends ModalAction { } static get modalSize() { - return qosEndpoint() ? 'large' : 'small'; + const { pathname } = window.location; + return qosEndpoint() || isAdminPage(pathname) ? 'large' : 'small'; } getModalSize() { - return qosEndpoint() ? 'large' : 'small'; + return qosEndpoint() || this.isAdminPage ? 'large' : 'small'; } get qosEndpoint() { @@ -63,10 +67,15 @@ export class Allocate extends ModalAction { maxCount: 2, }; this.getExternalNetworks(); - this.isAdminPage && globalProjectStore.fetchList(); + this.isAdminPage && this.fetchProjectList(); this.getQuota(); } + async fetchProjectList() { + await this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); + } + async getExternalNetworks() { const networks = await this.networkStore.pureFetchList({ 'router:external': true, @@ -80,6 +89,10 @@ export class Allocate extends ModalAction { return false; } + get projects() { + return toJS(this.projectStore.list.data) || []; + } + static policy = 'create_floatingip'; static allowed = () => Promise.resolve(true); @@ -151,10 +164,15 @@ export class Allocate extends ModalAction { } get defaultValue() { - return { - project_id: this.currentProjectId, + const values = { count: 2, }; + if (this.isAdminPage) { + values.project_id = { + selectedRowKeys: [this.currentProjectId], + }; + } + return values; } handleNetworkChange = async (networkId) => { @@ -181,7 +199,14 @@ export class Allocate extends ModalAction { }); }; - onSubmit = ({ subnet_id, batch_allocate, count, qos_policy_id, ...rest }) => { + onSubmit = ({ + subnet_id, + batch_allocate, + count, + qos_policy_id, + project_id, + ...rest + }) => { const data = rest; if (subnet_id) { data.subnet_id = subnet_id.value; @@ -197,7 +222,12 @@ export class Allocate extends ModalAction { } return Promise.all(promises); } - return this.store.create(data); + return this.store.create({ + ...data, + project_id: project_id + ? project_id.selectedRowKeys[0] + : this.currentProjectId, + }); }; onCountChange = (value) => { @@ -207,9 +237,10 @@ export class Allocate extends ModalAction { }; onProjectChange = (value) => { + const { selectedRowKeys } = value; this.setState( { - projectId: value, + projectId: selectedRowKeys[0], }, () => { this.getQuota(); @@ -230,10 +261,6 @@ export class Allocate extends ModalAction { label: item.name, value: item.id, })); - const projectOptions = globalProjectStore.list.data.map((project) => ({ - label: project.name, - value: project.id, - })); return [ { name: 'floating_network_id', @@ -246,12 +273,13 @@ export class Allocate extends ModalAction { { name: 'project_id', label: t('Project'), - type: 'select', - showSearch: true, + type: 'select-table', hidden: !this.isAdminPage, required: this.isAdminPage, - options: projectOptions, + isLoading: this.projectStore.list.isLoading, + data: this.projects, onChange: this.onProjectChange, + ...projectTableOptions, }, { name: 'subnet_id', diff --git a/src/pages/network/containers/Network/actions/CreateNetwork.jsx b/src/pages/network/containers/Network/actions/CreateNetwork.jsx index f44f4ee7..7fd2441a 100644 --- a/src/pages/network/containers/Network/actions/CreateNetwork.jsx +++ b/src/pages/network/containers/Network/actions/CreateNetwork.jsx @@ -22,6 +22,9 @@ import Notify from 'components/Notify'; import { checkSystemAdmin } from 'resources/skyline/policy'; import globalNeutronStore from 'stores/neutron/neutron'; import { subnetIpv6Tip } from 'resources/neutron/network'; +import { projectTableOptions } from 'resources/keystone/project'; +import { isAdminPage } from 'utils'; +import { toJS } from 'mobx'; import networkUtil from './networkUtil'; const { @@ -59,6 +62,15 @@ export class CreateNetwork extends ModalAction { return t('create network'); } + static get modalSize() { + const { pathname } = window.location; + return isAdminPage(pathname) ? 'large' : 'small'; + } + + getModalSize() { + return this.isAdminPage ? 'large' : 'small'; + } + init() { globalNetworkStore.updateCreateWithSubnet(false); this.state.networkQuota = {}; @@ -68,7 +80,7 @@ export class CreateNetwork extends ModalAction { this.state.projectId = this.currentProjectId; this.projectStore = globalProjectStore; globalNeutronStore.fetchAvailableZones(); - this.isAdminPage && globalProjectStore.fetchList(); + this.isAdminPage && this.fetchProjectList(); this.getQuota(); } @@ -89,6 +101,15 @@ export class CreateNetwork extends ModalAction { return true; } + async fetchProjectList() { + await this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); + } + + get projects() { + return toJS(this.projectStore.list.data) || []; + } + get showQuota() { return true; } @@ -136,8 +157,7 @@ export class CreateNetwork extends ModalAction { } get defaultValue() { - return { - project_id: this.currentProjectId, + const values = { enable_dhcp: true, provider_network_type: 'vxlan', ip_version: 'ipv4', @@ -147,6 +167,12 @@ export class CreateNetwork extends ModalAction { ipv6_ra_mode: 'slaac', ipv6_address_mode: 'slaac', }; + if (this.isAdminPage) { + values.project_id = { + selectedRowKeys: [this.currentProjectId], + }; + } + return values; } onSubmit = (values) => { @@ -188,7 +214,9 @@ export class CreateNetwork extends ModalAction { const networkAdminPageData = { 'router:external': external_network, - project_id, + project_id: project_id + ? project_id.selectedRowKeys[0] + : this.currentProjectId, 'provider:network_type': provider_network_type, 'provider:physical_network': provider_physical_network, 'provider:segmentation_id': provider_segmentation_id, @@ -314,9 +342,10 @@ export class CreateNetwork extends ModalAction { }; onProjectChange = (value) => { + const { selectedRowKeys } = value; this.setState( { - projectId: value, + projectId: selectedRowKeys[0], }, () => { this.getQuota(); @@ -339,10 +368,6 @@ export class CreateNetwork extends ModalAction { ip_version = 'ipv4', disable_gateway = false, } = this.state; - const projectOptions = globalProjectStore.list.data.map((project) => ({ - label: project.name, - value: project.id, - })); const hiddenPhysicalNetwork = this.isAdminPage && @@ -426,13 +451,13 @@ export class CreateNetwork extends ModalAction { { name: 'project_id', label: t('Project'), - type: 'select', - showSearch: true, + type: 'select-table', hidden: !this.isAdminPage, required: this.isAdminPage, - options: projectOptions, + isLoading: this.projectStore.list.isLoading, + data: this.projects, onChange: this.onProjectChange, - allowClear: false, + ...projectTableOptions, }, { name: 'provider_network_type', diff --git a/src/pages/network/containers/Network/actions/CreateSubnet.jsx b/src/pages/network/containers/Network/actions/CreateSubnet.jsx index 295f09e8..57e1dbdf 100644 --- a/src/pages/network/containers/Network/actions/CreateSubnet.jsx +++ b/src/pages/network/containers/Network/actions/CreateSubnet.jsx @@ -20,6 +20,8 @@ import { isEmpty } from 'lodash'; import globalProjectStore from 'stores/keystone/project'; import globalRootStore from 'stores/root'; import { subnetIpv6Tip } from 'resources/neutron/network'; +import { projectTableOptions } from 'resources/keystone/project'; +import { toJS } from 'mobx'; import networkUtil from './networkUtil'; const { @@ -43,6 +45,14 @@ export class CreateSubnet extends ModalAction { return t('Create Subnet'); } + static get modalSize() { + return globalRootStore.hasAdminRole ? 'large' : 'small'; + } + + getModalSize() { + return this.isSystemAdmin ? 'large' : 'small'; + } + get network() { return this.props.containerProps.detail || this.item || {}; } @@ -52,15 +62,20 @@ export class CreateSubnet extends ModalAction { } get defaultValue() { - return { + const values = { enable_dhcp: true, ip_version: 'ipv4', - project_id: this.currentProjectId, disable_gateway: false, more: false, ipv6_ra_mode: 'slaac', ipv6_address_mode: 'slaac', }; + if (this.isSystemAdmin) { + values.project_id = { + selectedRowKeys: [this.currentProjectId], + }; + } + return values; } init() { @@ -72,8 +87,13 @@ export class CreateSubnet extends ModalAction { this.getQuota(); } - getProjects() { - this.projectStore.fetchList(); + async getProjects() { + await this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); + } + + get projects() { + return toJS(this.projectStore.list.data) || []; } static get disableSubmit() { @@ -139,7 +159,7 @@ export class CreateSubnet extends ModalAction { }; onSubmit = (values) => { - const { allocation_pools, host_routes, ...rest } = values; + const { allocation_pools, host_routes, project_id, ...rest } = values; const allocationPools = getAllocationPools(allocation_pools); @@ -147,6 +167,9 @@ export class CreateSubnet extends ModalAction { return globalNetworkStore.createSubnet({ ...rest, + project_id: project_id + ? project_id.selectedRowKeys[0] + : this.currentProjectId, network_id: this.network.id, allocation_pools: allocationPools, host_routes: hostRouters, @@ -180,9 +203,10 @@ export class CreateSubnet extends ModalAction { }; onProjectChange = (value) => { + const { selectedRowKeys } = value; this.setState( { - projectId: value, + projectId: selectedRowKeys[0], }, () => { this.getQuota(); @@ -207,10 +231,6 @@ export class CreateSubnet extends ModalAction { projectId, } = this.state; const isIpv4 = ip_version === 'ipv4'; - const projectOptions = globalProjectStore.list.data.map((project) => ({ - label: project.name, - value: project.id, - })); return [ { @@ -223,17 +243,18 @@ export class CreateSubnet extends ModalAction { { name: 'project_id', label: t('Project'), - type: 'select', + type: 'select-table', required: true, hidden: !this.isSystemAdmin, - showSearch: true, extra: projectId !== this.networkProjectId && t( 'The selected project is different from the project to which the network belongs. That is, the subnet to be created is not under the same project as the network. Please do not continue unless you are quit sure what you are doing.' ), - options: projectOptions, + isLoading: this.projectStore.list.isLoading, + data: this.projects, onChange: this.onProjectChange, + ...projectTableOptions, }, { name: 'ip_version', diff --git a/src/pages/network/containers/QoSPolicy/actions/Create.jsx b/src/pages/network/containers/QoSPolicy/actions/Create.jsx index 8f8bac90..b89eb8da 100644 --- a/src/pages/network/containers/QoSPolicy/actions/Create.jsx +++ b/src/pages/network/containers/QoSPolicy/actions/Create.jsx @@ -16,6 +16,9 @@ import { inject, observer } from 'mobx-react'; import { ModalAction } from 'containers/Action'; import globalProjectStore from 'stores/keystone/project'; import { QoSPolicyStore } from 'stores/neutron/qos-policy'; +import { projectTableOptions } from 'resources/keystone/project'; +import { isAdminPage } from 'utils'; +import { toJS } from 'mobx'; export class Create extends ModalAction { static id = 'create_qos_policy'; @@ -26,6 +29,15 @@ export class Create extends ModalAction { return t('Create QoS Policy'); } + static get modalSize() { + const { pathname } = window.location; + return isAdminPage(pathname) ? 'large' : 'small'; + } + + getModalSize() { + return this.isAdminPage ? 'large' : 'small'; + } + static policy = 'create_policy'; static aliasPolicy = 'neutron:create_policy'; @@ -34,13 +46,28 @@ export class Create extends ModalAction { init() { this.store = new QoSPolicyStore(); - this.isAdminPage && globalProjectStore.fetchList(); + this.projectStore = globalProjectStore; + this.isAdminPage && this.fetchProjectList(); + } + + async fetchProjectList() { + await this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); + } + + get projects() { + return toJS(this.projectStore.list.data) || []; } get defaultValue() { - return { - project_id: this.props.rootStore.user.project.id, - }; + if (this.isAdminPage) { + return { + project_id: { + selectedRowKeys: [this.props.rootStore.user.project.id], + }, + }; + } + return {}; } onSubmit = (values) => { @@ -50,16 +77,13 @@ export class Create extends ModalAction { description, shared, is_default, - project_id, + project_id: project_id + ? project_id.selectedRowKeys[0] + : this.props.rootStore.user.project.id, }); }; get formItems() { - const projects = globalProjectStore.list.data.map((item) => ({ - label: item.name, - value: item.id, - })); - return [ { name: 'name', @@ -71,11 +95,12 @@ export class Create extends ModalAction { { name: 'project_id', label: t('Project'), - type: 'select', - showSearch: true, - required: true, - options: projects, + type: 'select-table', + required: this.isAdminPage, + isLoading: globalProjectStore.list.isLoading, + data: this.projects, hidden: !this.isAdminPage, + ...projectTableOptions, }, { name: 'description', diff --git a/src/pages/share/containers/ShareGroupType/actions/Create.jsx b/src/pages/share/containers/ShareGroupType/actions/Create.jsx index 8a3c9721..35993637 100644 --- a/src/pages/share/containers/ShareGroupType/actions/Create.jsx +++ b/src/pages/share/containers/ShareGroupType/actions/Create.jsx @@ -42,8 +42,9 @@ export class Create extends ModalAction { this.typeStore.fetchList({ is_public: 'all' }); } - getProjects() { - this.projectStore.fetchList(); + async getProjects() { + await this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); } get projects() { diff --git a/src/pages/share/containers/ShareGroupType/actions/ManageAccess.jsx b/src/pages/share/containers/ShareGroupType/actions/ManageAccess.jsx index d356ff14..865b8bc4 100644 --- a/src/pages/share/containers/ShareGroupType/actions/ManageAccess.jsx +++ b/src/pages/share/containers/ShareGroupType/actions/ManageAccess.jsx @@ -57,7 +57,7 @@ export class ManageAccess extends ModalAction { } async getProjects() { - await this.projectStore.fetchList(); + await this.projectStore.fetchProjectsWithDomain(); this.updateDefaultValue(); } diff --git a/src/pages/share/containers/ShareType/actions/Create.jsx b/src/pages/share/containers/ShareType/actions/Create.jsx index 413d8560..d435197d 100644 --- a/src/pages/share/containers/ShareType/actions/Create.jsx +++ b/src/pages/share/containers/ShareType/actions/Create.jsx @@ -60,8 +60,9 @@ export class Create extends ModalAction { this.getProjects(); } - getProjects() { - this.projectStore.fetchList(); + async getProjects() { + await this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); } get projects() { diff --git a/src/pages/share/containers/ShareType/actions/ManageAccess.jsx b/src/pages/share/containers/ShareType/actions/ManageAccess.jsx index 6baaea50..8328d6ef 100644 --- a/src/pages/share/containers/ShareType/actions/ManageAccess.jsx +++ b/src/pages/share/containers/ShareType/actions/ManageAccess.jsx @@ -55,7 +55,7 @@ export class ManageAccess extends ModalAction { } async getProjects() { - await this.projectStore.fetchList(); + await this.projectStore.fetchProjectsWithDomain(); this.updateDefaultValue(); } diff --git a/src/pages/storage/containers/VolumeType/VolumeType/actions/Create.jsx b/src/pages/storage/containers/VolumeType/VolumeType/actions/Create.jsx index 64ede08f..9a260998 100644 --- a/src/pages/storage/containers/VolumeType/VolumeType/actions/Create.jsx +++ b/src/pages/storage/containers/VolumeType/VolumeType/actions/Create.jsx @@ -38,8 +38,9 @@ export class Create extends ModalAction { // this.getServices(); } - getProjects() { - this.projectStore.fetchList(); + async getProjects() { + await this.projectStore.fetchProjectsWithDomain(); + this.updateDefaultValue(); } get projects() { diff --git a/src/pages/storage/containers/VolumeType/VolumeType/actions/ManageAccess.jsx b/src/pages/storage/containers/VolumeType/VolumeType/actions/ManageAccess.jsx index 88b8dd4a..73599c60 100644 --- a/src/pages/storage/containers/VolumeType/VolumeType/actions/ManageAccess.jsx +++ b/src/pages/storage/containers/VolumeType/VolumeType/actions/ManageAccess.jsx @@ -57,7 +57,7 @@ export class ManageAccess extends ModalAction { } async getProjects() { - await this.projectStore.fetchList(); + await this.projectStore.fetchProjectsWithDomain(); this.updateDefaultValue(); } diff --git a/src/resources/keystone/domain.jsx b/src/resources/keystone/domain.jsx index 54b93a76..f1edcdc5 100644 --- a/src/resources/keystone/domain.jsx +++ b/src/resources/keystone/domain.jsx @@ -1,5 +1,6 @@ import React from 'react'; import { Badge } from 'antd'; +import { getIdRender } from 'utils/table'; import globalDomainStore from 'stores/keystone/domain'; import globalRootStore from 'src/stores/root'; @@ -73,15 +74,35 @@ export const enabledColumn = { export const nameDomainColumns = [ { dataIndex: 'name', - title: t('Name'), + title: t('Project ID/Name'), + render: (value, record) => { + return ( + <> +
{getIdRender(record.id, true, false)}
+
{value}
+ + ); + }, }, { dataIndex: 'domainName', - title: t('Domain'), + title: t('Domain ID/Name'), + render: (value, record) => { + return ( + <> +
{getIdRender(record.domain_id, true, false)}
+
{value}
+ + ); + }, }, ]; export const transferFilterOption = (inputValue, record) => { - const { domainName, name } = record; - return name.includes(inputValue) || domainName.includes(inputValue); + const { domainName, name, id } = record; + return ( + id.includes(inputValue) || + name.includes(inputValue) || + domainName.includes(inputValue) + ); }; diff --git a/src/resources/keystone/project.js b/src/resources/keystone/project.jsx similarity index 60% rename from src/resources/keystone/project.js rename to src/resources/keystone/project.jsx index 2c8b4c62..4df181fd 100644 --- a/src/resources/keystone/project.js +++ b/src/resources/keystone/project.jsx @@ -12,13 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. +import React from 'react'; import { yesNoOptions } from 'utils/constants'; +import { getIdRender } from 'utils/table'; export const projectFilter = [ { label: t('Project Name'), name: 'name', }, + { + label: t('Project ID'), + name: 'id', + }, + { + label: t('Domain Name'), + name: 'domainName', + }, + { + label: t('Domain ID'), + name: 'domain_id', + }, { label: t('Enabled'), name: 'enabled', @@ -28,12 +42,30 @@ export const projectFilter = [ export const projectColumns = [ { - title: t('Project Name'), + title: t('Project ID/Name'), dataIndex: 'name', + render: (value, record) => { + const idRender = getIdRender(record.id, true, false); + return ( + <> +
{idRender}
+
{value}
+ + ); + }, }, { - title: t('User Num'), - dataIndex: 'userCount', + title: t('Domain ID/Name'), + dataIndex: 'domainName', + render: (value, record) => { + const idRender = getIdRender(record.domain_id, true, false); + return ( + <> +
{idRender}
+
{value}
+ + ); + }, }, { title: t('Enabled'), diff --git a/src/stores/keystone/project.js b/src/stores/keystone/project.js index 890fe394..4ef041c6 100644 --- a/src/stores/keystone/project.js +++ b/src/stores/keystone/project.js @@ -218,6 +218,24 @@ export class ProjectStore extends Base { ); } + async fetchProjectsWithDomain() { + this.list.isLoading = true; + const [{ projects = [] }, { domains = [] }] = await Promise.all([ + this.client.list(), + this.domainClient.list(), + ]); + const newProjects = projects.map((pro) => { + const domain = domains.find((it) => it.id === pro.domain_id); + pro.domainName = domain?.name; + return pro; + }); + this.list.update({ + data: newProjects, + total: newProjects.length || 0, + isLoading: false, + }); + } + get enableCinder() { return globalRootStore.checkEndpoint('cinder'); } diff --git a/test/e2e/integration/pages/identity/project.spec.js b/test/e2e/integration/pages/identity/project.spec.js index b42bfe8c..03edb4b9 100644 --- a/test/e2e/integration/pages/identity/project.spec.js +++ b/test/e2e/integration/pages/identity/project.spec.js @@ -50,6 +50,7 @@ describe('The Project Page', () => { it('successfully edit quota', () => { cy.tableSearchText(name) .clickActionInMore('Edit Quota') + .wait(5000) .formInput('instances', 11) .formButtonClick('more') .wait(2000) diff --git a/test/e2e/support/commands.js b/test/e2e/support/commands.js index 2d491916..15510310 100644 --- a/test/e2e/support/commands.js +++ b/test/e2e/support/commands.js @@ -153,7 +153,7 @@ Cypress.Commands.add('setLanguageByPage', () => { .find('.ant-col') .last() .find('button') - .trigger('mouseover'); + .trigger('mouseover', { force: true }); cy.get('.ant-dropdown-menu-light') .find('li') .eq(2) diff --git a/test/e2e/support/detail-commands.js b/test/e2e/support/detail-commands.js index dda72154..1a983d87 100644 --- a/test/e2e/support/detail-commands.js +++ b/test/e2e/support/detail-commands.js @@ -39,7 +39,7 @@ Cypress.Commands.add('clickDetailActionInMore', (title, waitTime = 2000) => { cy.get('.detail-main') .first() .find('.ant-dropdown-trigger') - .trigger('mouseover'); + .trigger('mouseover', { force: true }); const realTitle = getTitle(title); cy.get('ul.ant-dropdown-menu-light') .contains(realTitle) diff --git a/test/e2e/support/table-commands.js b/test/e2e/support/table-commands.js index 8fae5264..b0cfab05 100644 --- a/test/e2e/support/table-commands.js +++ b/test/e2e/support/table-commands.js @@ -56,7 +56,7 @@ Cypress.Commands.add( cy.get('.table-header-btns') .find('.ant-dropdown-trigger') .contains(moreTitle) - .trigger('mouseover'); + .trigger('mouseover', { force: true }); cy.get('ul.ant-dropdown-menu-light') .last() .find('button') @@ -95,7 +95,7 @@ Cypress.Commands.add('clickMoreActionButton', (buttonIndex) => { cy.get('.ant-table-row') .first() .find('.ant-dropdown-trigger') - .trigger('mouseover'); + .trigger('mouseover', { force: true }); cy.get('ul.ant-dropdown-menu-light') .find('li') .eq(buttonIndex) @@ -106,7 +106,7 @@ Cypress.Commands.add('clickActionInMore', (title, waitTime = 2000) => { cy.get('.ant-table-row') .first() .find('.ant-dropdown-trigger') - .trigger('mouseover'); + .trigger('mouseover', { force: true }); const realTitle = getTitle(title); cy.get('ul.ant-dropdown-menu-light') .contains(realTitle) @@ -118,12 +118,12 @@ Cypress.Commands.add('clickActionInMoreSub', (title, subMenu) => { cy.get('.ant-table-row') .first() .find('.ant-dropdown-trigger') - .trigger('mouseover'); + .trigger('mouseover', { force: true }); const realTitle = getTitle(title); const realMenu = getTitle(subMenu); cy.get('.ant-dropdown-menu-submenu-title') .contains(realMenu) - .trigger('mouseover'); + .trigger('mouseover', { force: true }); cy.get('.ant-dropdown-menu-submenu-popup') .last() .find('button') @@ -190,7 +190,7 @@ Cypress.Commands.add('checkActionDisabled', (title) => { cy.get('.ant-table-row') .first() .find('.ant-dropdown-trigger') - .trigger('mouseover'); + .trigger('mouseover', { force: true }); cy.get('ul.ant-dropdown-menu-light').contains(realTitle).should('not.exist'); }); @@ -204,7 +204,7 @@ Cypress.Commands.add('checkActionDisabledInFirstRow', (title, name) => { .get('.ant-table-row') .first() .find('.ant-dropdown-trigger') - .trigger('mouseover') + .trigger('mouseover', { force: true }) .get('ul.ant-dropdown-menu-light') .contains(realTitle) .should('not.exist'); @@ -228,7 +228,7 @@ Cypress.Commands.add('clickConfirmActionInMore', (title, waitTime) => { cy.get('.ant-table-row') .first() .find('.ant-dropdown-trigger') - .trigger('mouseover'); + .trigger('mouseover', { force: true }); const realTitle = getTitle(title); cy.get('ul.ant-dropdown-menu-light') .contains(realTitle) @@ -254,12 +254,12 @@ Cypress.Commands.add( cy.get('.ant-table-row') .first() .find('.ant-dropdown-trigger') - .trigger('mouseover'); + .trigger('mouseover', { force: true }); const realTitle = getTitle(title); const realMenu = getTitle(subMenu); cy.get('.ant-dropdown-menu-submenu-title') .contains(realMenu) - .trigger('mouseover'); + .trigger('mouseover', { force: true }); cy.get('.ant-dropdown-menu-submenu-popup') .last() .find('button')