mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 07:49:41 +02:00
refactor(templates): migrate list view to react [EE-2296] (#10999)
This commit is contained in:
parent
d38085a560
commit
6ff4fd3db2
103 changed files with 2628 additions and 1315 deletions
|
@ -11,9 +11,7 @@ import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
|
|||
import { isAgentEnvironment } from '@/react/portainer/environments/utils';
|
||||
import { FeatureId } from '@/react/portainer/feature-flags/enums';
|
||||
|
||||
import { FormControl } from '@@/form-components/FormControl';
|
||||
import { FormSection } from '@@/form-components/FormSection';
|
||||
import { Input } from '@@/form-components/Input';
|
||||
import { SwitchField } from '@@/form-components/SwitchField';
|
||||
import { ImageConfigFieldset, ImageConfigValues } from '@@/ImageConfigFieldset';
|
||||
import { LoadingButton } from '@@/buttons';
|
||||
|
@ -23,6 +21,7 @@ import {
|
|||
PortsMappingField,
|
||||
Values as PortMappingValue,
|
||||
} from './PortsMappingField';
|
||||
import { NameField } from './NameField';
|
||||
|
||||
export interface Values {
|
||||
name: string;
|
||||
|
@ -74,19 +73,14 @@ export function BaseForm({
|
|||
return (
|
||||
<Widget>
|
||||
<Widget.Body>
|
||||
<FormControl label="Name" inputId="name-input" errors={errors?.name}>
|
||||
<Input
|
||||
id="name-input"
|
||||
value={values.name}
|
||||
onChange={(e) => {
|
||||
const name = e.target.value;
|
||||
onChangeName(name);
|
||||
setFieldValue('name', name);
|
||||
}}
|
||||
placeholder="e.g. myContainer"
|
||||
data-cy="container-name-input"
|
||||
/>
|
||||
</FormControl>
|
||||
<NameField
|
||||
value={values.name}
|
||||
onChange={(name) => {
|
||||
setFieldValue('name', name);
|
||||
onChangeName(name);
|
||||
}}
|
||||
error={errors?.name}
|
||||
/>
|
||||
|
||||
<FormSection title="Image Configuration">
|
||||
<ImageConfigFieldset
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { string } from 'yup';
|
||||
|
||||
import { FormControl } from '@@/form-components/FormControl';
|
||||
import { Input } from '@@/form-components/Input';
|
||||
|
||||
export function NameField({
|
||||
value,
|
||||
error,
|
||||
onChange,
|
||||
}: {
|
||||
value: string;
|
||||
error?: string;
|
||||
onChange: (value: string) => void;
|
||||
}) {
|
||||
return (
|
||||
<FormControl label="Name" inputId="name-input" errors={error}>
|
||||
<Input
|
||||
id="name-input"
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
placeholder="e.g. myContainer"
|
||||
data-cy="container-name-input"
|
||||
/>
|
||||
</FormControl>
|
||||
);
|
||||
}
|
||||
|
||||
export function nameValidation() {
|
||||
return string().default('');
|
||||
}
|
|
@ -9,7 +9,7 @@ type PortKey = `${string}/${Protocol}`;
|
|||
export function parsePortBindingRequest(portBindings: Values): PortMap {
|
||||
const bindings: Record<
|
||||
PortKey,
|
||||
Array<{ HostIp: string; HostPort: string }>
|
||||
Array<{ HostIp?: string; HostPort?: string }>
|
||||
> = {};
|
||||
_.forEach(portBindings, (portBinding) => {
|
||||
if (!portBinding.containerPort) {
|
||||
|
@ -17,9 +17,6 @@ export function parsePortBindingRequest(portBindings: Values): PortMap {
|
|||
}
|
||||
|
||||
const portInfo = extractPortInfo(portBinding);
|
||||
if (!portInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { hostPort } = portBinding;
|
||||
const { endHostPort, endPort, hostIp, startHostPort, startPort } = portInfo;
|
||||
|
@ -36,7 +33,9 @@ export function parsePortBindingRequest(portBindings: Values): PortMap {
|
|||
hostPort += `-${endHostPort.toString()}`;
|
||||
}
|
||||
|
||||
bindings[bindKey].push({ HostIp: hostIp, HostPort: hostPort });
|
||||
bindings[bindKey].push(
|
||||
hostIp || hostPort ? { HostIp: hostIp, HostPort: hostPort } : {}
|
||||
);
|
||||
});
|
||||
});
|
||||
return bindings;
|
||||
|
@ -71,7 +70,13 @@ function parsePort(port: string) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
function extractPortInfo(portBinding: PortMapping) {
|
||||
function extractPortInfo(portBinding: PortMapping): {
|
||||
startPort: number;
|
||||
endPort: number;
|
||||
hostIp: string;
|
||||
startHostPort: number;
|
||||
endHostPort: number;
|
||||
} {
|
||||
const containerPortRange = parsePortRange(portBinding.containerPort);
|
||||
if (!isValidPortRange(containerPortRange)) {
|
||||
throw new Error(`Invalid port specification: ${portBinding.containerPort}`);
|
||||
|
@ -82,7 +87,13 @@ function extractPortInfo(portBinding: PortMapping) {
|
|||
let hostIp = '';
|
||||
let { hostPort } = portBinding;
|
||||
if (!hostPort) {
|
||||
return null;
|
||||
return {
|
||||
startPort,
|
||||
endPort,
|
||||
hostIp: '',
|
||||
startHostPort: 0,
|
||||
endHostPort: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (hostPort.includes('[')) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Values } from './PortsMappingField';
|
|||
export function validationSchema(): SchemaOf<Values> {
|
||||
return array(
|
||||
object({
|
||||
hostPort: string().required('host is required'),
|
||||
hostPort: string().default(''),
|
||||
containerPort: string().required('container is required'),
|
||||
protocol: mixed().oneOf(['tcp', 'udp']),
|
||||
})
|
||||
|
|
|
@ -6,6 +6,7 @@ import { imageConfigValidation } from '@@/ImageConfigFieldset';
|
|||
|
||||
import { Values } from './BaseForm';
|
||||
import { validationSchema as portsSchema } from './PortsMappingField.validation';
|
||||
import { nameValidation } from './NameField';
|
||||
|
||||
export function validation(
|
||||
{
|
||||
|
@ -26,9 +27,10 @@ export function validation(
|
|||
}
|
||||
): SchemaOf<Values> {
|
||||
return object({
|
||||
name: string()
|
||||
.default('')
|
||||
.test('not-duplicate-portainer', () => !isDuplicatingPortainer),
|
||||
name: nameValidation().test(
|
||||
'not-duplicate-portainer',
|
||||
() => !isDuplicatingPortainer
|
||||
),
|
||||
alwaysPull: boolean()
|
||||
.default(true)
|
||||
.test('rate-limits', 'Rate limit exceeded', (alwaysPull: boolean) =>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue