From 5d457caf8391dc6f18e6cb2278940015b9370de0 Mon Sep 17 00:00:00 2001 From: "Jingwei.Zhang" Date: Wed, 17 Aug 2022 09:19:54 +0800 Subject: [PATCH] feat: support fuzzy query port when create port forwarding 1. Support fuzzy query port by name/fixed ip/server name when create/edit port forwarding and floating ip associate port: the API filtering method is used to filter data precisely. It is changed to: After the front-end obtains all data, it filters data based on the input content. 2. Add port status filter when create/edit port forwarding 3. Fix the port forwarding display in the floating ip list page: when the number of port forwardings is less than the page size(10), the list will not show the pagination. Change-Id: Iea0d19db42de2557167c444ad9454d6b8300795e --- .../Detail/PortForwarding/actions/Create.jsx | 22 ++- .../Detail/PortForwarding/actions/Edit.jsx | 19 ++- .../FloatingIp/actions/Associate.jsx | 17 +- .../network/containers/FloatingIp/index.jsx | 3 +- src/resources/neutron/port.jsx | 150 ++++++++++++------ 5 files changed, 148 insertions(+), 63 deletions(-) diff --git a/src/pages/network/containers/FloatingIp/Detail/PortForwarding/actions/Create.jsx b/src/pages/network/containers/FloatingIp/Detail/PortForwarding/actions/Create.jsx index aa328c80..55e350af 100644 --- a/src/pages/network/containers/FloatingIp/Detail/PortForwarding/actions/Create.jsx +++ b/src/pages/network/containers/FloatingIp/Detail/PortForwarding/actions/Create.jsx @@ -17,8 +17,12 @@ import { inject, observer } from 'mobx-react'; import { ModalAction } from 'containers/Action'; import { isNull, isObject } from 'lodash'; import { getCanReachSubnetIdsWithRouterIdInComponent } from 'resources/neutron/router'; -import { PortStore } from 'stores/neutron/port'; -import { getPortFormItem, getPortsAndReasons } from 'resources/neutron/port'; +import { PortStore } from 'stores/neutron/port-extension'; +import { + getPortFormItem, + getPortsAndReasons, + getPortsForPortFormItem, +} from 'resources/neutron/port'; import { getInterfaceWithReason } from 'resources/neutron/floatingip'; import globalPortForwardingStore from 'stores/neutron/port-forwarding'; import { enablePFW } from 'resources/neutron/neutron'; @@ -53,6 +57,7 @@ export class CreatePortForwarding extends ModalAction { routerIdWithExternalNetworkInfo: [], supportRange: true, }; + this.getPorts(); this.getRangeSupport(); this.getFipAlreadyUsedPorts(); getCanReachSubnetIdsWithRouterIdInComponent.call(this, (router) => { @@ -155,6 +160,14 @@ export class CreatePortForwarding extends ModalAction { return ['protocol']; } + get portDeviceOwner() { + return ['compute:nova', '']; + } + + getPorts() { + getPortsForPortFormItem.call(this, this.portDeviceOwner); + } + async getRangeSupport() { try { await globalPortForwardingStore.fetchListByPage({ @@ -565,10 +578,7 @@ export class CreatePortForwarding extends ModalAction { extra: internalPortExtra, }, ]; - const [virtualAdapterItem, fixedIpItem] = getPortFormItem.call(this, [ - 'compute:nova', - '', - ]); + const [virtualAdapterItem, fixedIpItem] = getPortFormItem.call(this); virtualAdapterItem.label = t('Target Port'); fixedIpItem.label = t('Target IP Address'); fixedIpItem.onChange = this.onFixedIpChange; diff --git a/src/pages/network/containers/FloatingIp/Detail/PortForwarding/actions/Edit.jsx b/src/pages/network/containers/FloatingIp/Detail/PortForwarding/actions/Edit.jsx index 43acf434..5b714810 100644 --- a/src/pages/network/containers/FloatingIp/Detail/PortForwarding/actions/Edit.jsx +++ b/src/pages/network/containers/FloatingIp/Detail/PortForwarding/actions/Edit.jsx @@ -14,10 +14,14 @@ import { inject, observer } from 'mobx-react'; import globalPortForwardingStore from 'stores/neutron/port-forwarding'; -import globalPortStore, { PortStore } from 'stores/neutron/port'; +import globalPortStore, { PortStore } from 'stores/neutron/port-extension'; import { getCanReachSubnetIdsWithRouterIdInComponent } from 'resources/neutron/router'; import { getInterfaceWithReason } from 'resources/neutron/floatingip'; -import { getPortFormItem, getPortsAndReasons } from 'resources/neutron/port'; +import { + getPortFormItem, + getPortsAndReasons, + getPortsForPortFormItem, +} from 'resources/neutron/port'; import { ModalAction } from 'containers/Action'; export class Edit extends ModalAction { @@ -45,6 +49,7 @@ export class Edit extends ModalAction { this.getInitialPortFixedIPs(); }); this.getFipAlreadyUsedPorts(); + this.getPorts(); this.state = { alreadyUsedPorts: [], instanceFixedIPs: [], @@ -54,6 +59,14 @@ export class Edit extends ModalAction { }; } + get portDeviceOwner() { + return ['compute:nova', '']; + } + + getPorts() { + getPortsForPortFormItem.call(this, this.portDeviceOwner); + } + async getFipAlreadyUsedPorts() { const detail = await globalPortForwardingStore.fetchList({ fipId: this.item.fip.id, @@ -296,7 +309,7 @@ export class Edit extends ModalAction { }, }, ]; - const extraColumn = getPortFormItem.call(this, ['compute:nova', '']); + const extraColumn = getPortFormItem.call(this); const portIndex = extraColumn.findIndex( (i) => i.name === 'virtual_adapter' ); diff --git a/src/pages/network/containers/FloatingIp/actions/Associate.jsx b/src/pages/network/containers/FloatingIp/actions/Associate.jsx index 46e1d077..1fef583a 100644 --- a/src/pages/network/containers/FloatingIp/actions/Associate.jsx +++ b/src/pages/network/containers/FloatingIp/actions/Associate.jsx @@ -26,7 +26,11 @@ import { import globalFloatingIpsStore from 'stores/neutron/floatingIp'; import { PortStore } from 'stores/neutron/port'; import { instanceSelectTablePropsBackend } from 'resources/nova/instance'; -import { getPortFormItem, getPortsAndReasons } from 'resources/neutron/port'; +import { + getPortFormItem, + getPortsAndReasons, + getPortsForPortFormItem, +} from 'resources/neutron/port'; import { getInterfaceWithReason, disableFIPAssociate, @@ -58,6 +62,7 @@ export class Associate extends ModalAction { canReachSubnetIdsWithRouterId: [], routerIdWithExternalNetworkInfo: [], }; + this.getPorts(); } get instanceName() { @@ -106,6 +111,14 @@ export class Associate extends ModalAction { return value; } + get portDeviceOwner() { + return ['']; + } + + getPorts() { + getPortsForPortFormItem.call(this, this.portDeviceOwner); + } + onValuesChange = (changedFields) => { if (has(changedFields, 'resourceType')) { const { resourceType } = changedFields; @@ -391,7 +404,7 @@ export class Associate extends ModalAction { ); break; case 'port': - ret.push(...getPortFormItem.call(this, [''])); + ret.push(...getPortFormItem.call(this, false)); break; default: break; diff --git a/src/pages/network/containers/FloatingIp/index.jsx b/src/pages/network/containers/FloatingIp/index.jsx index 49280822..285a8e7e 100644 --- a/src/pages/network/containers/FloatingIp/index.jsx +++ b/src/pages/network/containers/FloatingIp/index.jsx @@ -183,8 +183,7 @@ export class FloatingIps extends Base { return null; } const pageSize = 10; - const zeroLength = - length > pageSize ? pageSize - (length % pageSize) : pageSize; + const zeroLength = length > pageSize ? pageSize - (length % pageSize) : 0; const zeroData = Array.from({ length: zeroLength }, (i) => ({ key: `zero-${i}`, })); diff --git a/src/resources/neutron/port.jsx b/src/resources/neutron/port.jsx index 06199f31..bb6c320c 100644 --- a/src/resources/neutron/port.jsx +++ b/src/resources/neutron/port.jsx @@ -14,6 +14,7 @@ import React from 'react'; import { ipValidate } from 'utils/validate'; +import { getOptions } from 'utils/index'; const { isIPv4 } = ipValidate; @@ -83,8 +84,102 @@ export function getPortsAndReasons( }); } -export function getPortFormItem(device_owner) { +export function getPortsForPortFormItem(device_owner) { + this.portStore.fetchList({ device_owner, project_id: this.currentProjectId }); +} + +export function getPortFormItem(withResourceNameAndStatusFilter = true) { const { portFixedIPs, fixedIpLoading } = this.state; + const portFilters = [ + { + label: t('Name'), + name: 'name', + }, + { + label: t('Fixed IP'), + name: 'fixed_ips', + filterFunc: (record, val) => { + return (record || []).some((it) => it.ip_address.includes(val)); + }, + }, + ]; + if (withResourceNameAndStatusFilter) { + portFilters.push( + ...[ + { + label: t('Bind Resource Name'), + name: 'server_name', + }, + { + label: t('Status'), + name: 'status', + options: getOptions(portStatus).filter((it) => + ['ACTIVE', 'DOWN'].includes(it.key) + ), + }, + ] + ); + } + const portColumns = [ + { + title: t('ID/Name'), + dataIndex: 'name', + routeName: this.getRouteName('portDetail'), + }, + { + title: t('Description'), + dataIndex: 'description', + }, + { + title: t('Fixed IPs'), + dataIndex: 'fixed_ips', + render: (data) => ( + <> + {data.map((d, idx) => ( +
{d.ip_address}
+ ))} + + ), + }, + { + title: t('Created At'), + dataIndex: 'created_at', + valueRender: 'sinceTime', + }, + ]; + if (withResourceNameAndStatusFilter) { + const extraColumns = [ + { + title: t('Status'), + dataIndex: 'status', + render: (value) => portStatus[value] || value, + }, + { + title: t('Bind Resource'), + dataIndex: 'server_name', + render: (server_name, item) => { + const { device_id } = item; + if (!device_id) { + return '-'; + } + const link = this.getLinkRender( + 'instanceDetail', + device_id, + { id: device_id }, + { tab: 'interface' } + ); + return ( + <> + {link} +
+ {server_name || '-'} + + ); + }, + }, + ]; + portColumns.splice(4, 0, ...extraColumns); + } return [ { name: 'virtual_adapter', @@ -92,58 +187,13 @@ export function getPortFormItem(device_owner) { type: 'select-table', required: true, rowKey: 'id', - backendPageStore: this.portStore, + data: this.portStore.list.data || [], + isLoading: this.portStore.list.isLoading, disabledFunc: this.portsDisableFunc, onChange: this.handlePortSelect, - extraParams: { device_owner, project_id: this.currentProjectId }, isMulti: false, - ...portSortProps, - filterParams: [ - { - label: t('Name'), - name: 'name', - }, - { - label: t('Fixed IP'), - name: 'fixedIP', - }, - ], - columns: [ - { - title: t('ID/Name'), - dataIndex: 'name', - routeName: this.getRouteName('portDetail'), - }, - { - title: t('Description'), - dataIndex: 'description', - sorter: false, - }, - { - title: t('Fixed IPs'), - dataIndex: 'fixed_ips', - sorter: false, - render: (data) => ( - <> - {data.map((d, idx) => ( -
{d.ip_address}
- ))} - - ), - }, - { - title: t('Status'), - dataIndex: 'status', - render: (value) => portStatus[value] || value, - }, - { - title: t('Created At'), - dataIndex: 'created_at', - valueRender: 'sinceTime', - isHideable: true, - sorter: false, - }, - ], + filterParams: portFilters, + columns: portColumns, }, { name: 'fixed_ip_address',