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:
parent
07d6a51bf2
commit
5d457caf83
@ -17,8 +17,12 @@ import { inject, observer } from 'mobx-react';
|
|||||||
import { ModalAction } from 'containers/Action';
|
import { ModalAction } from 'containers/Action';
|
||||||
import { isNull, isObject } from 'lodash';
|
import { isNull, isObject } from 'lodash';
|
||||||
import { getCanReachSubnetIdsWithRouterIdInComponent } from 'resources/neutron/router';
|
import { getCanReachSubnetIdsWithRouterIdInComponent } from 'resources/neutron/router';
|
||||||
import { PortStore } from 'stores/neutron/port';
|
import { PortStore } from 'stores/neutron/port-extension';
|
||||||
import { getPortFormItem, getPortsAndReasons } from 'resources/neutron/port';
|
import {
|
||||||
|
getPortFormItem,
|
||||||
|
getPortsAndReasons,
|
||||||
|
getPortsForPortFormItem,
|
||||||
|
} from 'resources/neutron/port';
|
||||||
import { getInterfaceWithReason } from 'resources/neutron/floatingip';
|
import { getInterfaceWithReason } from 'resources/neutron/floatingip';
|
||||||
import globalPortForwardingStore from 'stores/neutron/port-forwarding';
|
import globalPortForwardingStore from 'stores/neutron/port-forwarding';
|
||||||
import { enablePFW } from 'resources/neutron/neutron';
|
import { enablePFW } from 'resources/neutron/neutron';
|
||||||
@ -53,6 +57,7 @@ export class CreatePortForwarding extends ModalAction {
|
|||||||
routerIdWithExternalNetworkInfo: [],
|
routerIdWithExternalNetworkInfo: [],
|
||||||
supportRange: true,
|
supportRange: true,
|
||||||
};
|
};
|
||||||
|
this.getPorts();
|
||||||
this.getRangeSupport();
|
this.getRangeSupport();
|
||||||
this.getFipAlreadyUsedPorts();
|
this.getFipAlreadyUsedPorts();
|
||||||
getCanReachSubnetIdsWithRouterIdInComponent.call(this, (router) => {
|
getCanReachSubnetIdsWithRouterIdInComponent.call(this, (router) => {
|
||||||
@ -155,6 +160,14 @@ export class CreatePortForwarding extends ModalAction {
|
|||||||
return ['protocol'];
|
return ['protocol'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get portDeviceOwner() {
|
||||||
|
return ['compute:nova', ''];
|
||||||
|
}
|
||||||
|
|
||||||
|
getPorts() {
|
||||||
|
getPortsForPortFormItem.call(this, this.portDeviceOwner);
|
||||||
|
}
|
||||||
|
|
||||||
async getRangeSupport() {
|
async getRangeSupport() {
|
||||||
try {
|
try {
|
||||||
await globalPortForwardingStore.fetchListByPage({
|
await globalPortForwardingStore.fetchListByPage({
|
||||||
@ -565,10 +578,7 @@ export class CreatePortForwarding extends ModalAction {
|
|||||||
extra: internalPortExtra,
|
extra: internalPortExtra,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const [virtualAdapterItem, fixedIpItem] = getPortFormItem.call(this, [
|
const [virtualAdapterItem, fixedIpItem] = getPortFormItem.call(this);
|
||||||
'compute:nova',
|
|
||||||
'',
|
|
||||||
]);
|
|
||||||
virtualAdapterItem.label = t('Target Port');
|
virtualAdapterItem.label = t('Target Port');
|
||||||
fixedIpItem.label = t('Target IP Address');
|
fixedIpItem.label = t('Target IP Address');
|
||||||
fixedIpItem.onChange = this.onFixedIpChange;
|
fixedIpItem.onChange = this.onFixedIpChange;
|
||||||
|
@ -14,10 +14,14 @@
|
|||||||
|
|
||||||
import { inject, observer } from 'mobx-react';
|
import { inject, observer } from 'mobx-react';
|
||||||
import globalPortForwardingStore from 'stores/neutron/port-forwarding';
|
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 { getCanReachSubnetIdsWithRouterIdInComponent } from 'resources/neutron/router';
|
||||||
import { getInterfaceWithReason } from 'resources/neutron/floatingip';
|
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';
|
import { ModalAction } from 'containers/Action';
|
||||||
|
|
||||||
export class Edit extends ModalAction {
|
export class Edit extends ModalAction {
|
||||||
@ -45,6 +49,7 @@ export class Edit extends ModalAction {
|
|||||||
this.getInitialPortFixedIPs();
|
this.getInitialPortFixedIPs();
|
||||||
});
|
});
|
||||||
this.getFipAlreadyUsedPorts();
|
this.getFipAlreadyUsedPorts();
|
||||||
|
this.getPorts();
|
||||||
this.state = {
|
this.state = {
|
||||||
alreadyUsedPorts: [],
|
alreadyUsedPorts: [],
|
||||||
instanceFixedIPs: [],
|
instanceFixedIPs: [],
|
||||||
@ -54,6 +59,14 @@ export class Edit extends ModalAction {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get portDeviceOwner() {
|
||||||
|
return ['compute:nova', ''];
|
||||||
|
}
|
||||||
|
|
||||||
|
getPorts() {
|
||||||
|
getPortsForPortFormItem.call(this, this.portDeviceOwner);
|
||||||
|
}
|
||||||
|
|
||||||
async getFipAlreadyUsedPorts() {
|
async getFipAlreadyUsedPorts() {
|
||||||
const detail = await globalPortForwardingStore.fetchList({
|
const detail = await globalPortForwardingStore.fetchList({
|
||||||
fipId: this.item.fip.id,
|
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(
|
const portIndex = extraColumn.findIndex(
|
||||||
(i) => i.name === 'virtual_adapter'
|
(i) => i.name === 'virtual_adapter'
|
||||||
);
|
);
|
||||||
|
@ -26,7 +26,11 @@ import {
|
|||||||
import globalFloatingIpsStore from 'stores/neutron/floatingIp';
|
import globalFloatingIpsStore from 'stores/neutron/floatingIp';
|
||||||
import { PortStore } from 'stores/neutron/port';
|
import { PortStore } from 'stores/neutron/port';
|
||||||
import { instanceSelectTablePropsBackend } from 'resources/nova/instance';
|
import { instanceSelectTablePropsBackend } from 'resources/nova/instance';
|
||||||
import { getPortFormItem, getPortsAndReasons } from 'resources/neutron/port';
|
import {
|
||||||
|
getPortFormItem,
|
||||||
|
getPortsAndReasons,
|
||||||
|
getPortsForPortFormItem,
|
||||||
|
} from 'resources/neutron/port';
|
||||||
import {
|
import {
|
||||||
getInterfaceWithReason,
|
getInterfaceWithReason,
|
||||||
disableFIPAssociate,
|
disableFIPAssociate,
|
||||||
@ -58,6 +62,7 @@ export class Associate extends ModalAction {
|
|||||||
canReachSubnetIdsWithRouterId: [],
|
canReachSubnetIdsWithRouterId: [],
|
||||||
routerIdWithExternalNetworkInfo: [],
|
routerIdWithExternalNetworkInfo: [],
|
||||||
};
|
};
|
||||||
|
this.getPorts();
|
||||||
}
|
}
|
||||||
|
|
||||||
get instanceName() {
|
get instanceName() {
|
||||||
@ -106,6 +111,14 @@ export class Associate extends ModalAction {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get portDeviceOwner() {
|
||||||
|
return [''];
|
||||||
|
}
|
||||||
|
|
||||||
|
getPorts() {
|
||||||
|
getPortsForPortFormItem.call(this, this.portDeviceOwner);
|
||||||
|
}
|
||||||
|
|
||||||
onValuesChange = (changedFields) => {
|
onValuesChange = (changedFields) => {
|
||||||
if (has(changedFields, 'resourceType')) {
|
if (has(changedFields, 'resourceType')) {
|
||||||
const { resourceType } = changedFields;
|
const { resourceType } = changedFields;
|
||||||
@ -391,7 +404,7 @@ export class Associate extends ModalAction {
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'port':
|
case 'port':
|
||||||
ret.push(...getPortFormItem.call(this, ['']));
|
ret.push(...getPortFormItem.call(this, false));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -183,8 +183,7 @@ export class FloatingIps extends Base {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const pageSize = 10;
|
const pageSize = 10;
|
||||||
const zeroLength =
|
const zeroLength = length > pageSize ? pageSize - (length % pageSize) : 0;
|
||||||
length > pageSize ? pageSize - (length % pageSize) : pageSize;
|
|
||||||
const zeroData = Array.from({ length: zeroLength }, (i) => ({
|
const zeroData = Array.from({ length: zeroLength }, (i) => ({
|
||||||
key: `zero-${i}`,
|
key: `zero-${i}`,
|
||||||
}));
|
}));
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ipValidate } from 'utils/validate';
|
import { ipValidate } from 'utils/validate';
|
||||||
|
import { getOptions } from 'utils/index';
|
||||||
|
|
||||||
const { isIPv4 } = ipValidate;
|
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 { 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 [
|
return [
|
||||||
{
|
{
|
||||||
name: 'virtual_adapter',
|
name: 'virtual_adapter',
|
||||||
@ -92,58 +187,13 @@ export function getPortFormItem(device_owner) {
|
|||||||
type: 'select-table',
|
type: 'select-table',
|
||||||
required: true,
|
required: true,
|
||||||
rowKey: 'id',
|
rowKey: 'id',
|
||||||
backendPageStore: this.portStore,
|
data: this.portStore.list.data || [],
|
||||||
|
isLoading: this.portStore.list.isLoading,
|
||||||
disabledFunc: this.portsDisableFunc,
|
disabledFunc: this.portsDisableFunc,
|
||||||
onChange: this.handlePortSelect,
|
onChange: this.handlePortSelect,
|
||||||
extraParams: { device_owner, project_id: this.currentProjectId },
|
|
||||||
isMulti: false,
|
isMulti: false,
|
||||||
...portSortProps,
|
filterParams: portFilters,
|
||||||
filterParams: [
|
columns: portColumns,
|
||||||
{
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'fixed_ip_address',
|
name: 'fixed_ip_address',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user