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
This commit is contained in:
Jingwei.Zhang 2022-08-17 09:19:54 +08:00
parent 07d6a51bf2
commit 5d457caf83
5 changed files with 148 additions and 63 deletions

View File

@ -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;

View File

@ -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'
);

View File

@ -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;

View File

@ -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}`,
}));

View File

@ -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) => (
<div key={`ip_address_${idx}`}>{d.ip_address}</div>
))}
</>
),
},
{
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}
<br />
{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) => (
<div key={`ip_address_${idx}`}>{d.ip_address}</div>
))}
</>
),
},
{
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',