mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 07:49:41 +02:00
feat(containers): migrate labels tab to react [EE-5212] (#10348)
This commit is contained in:
parent
b4b44e6fa4
commit
7acde18930
11 changed files with 159 additions and 67 deletions
31
app/react/docker/containers/CreateView/LabelsTab/Item.tsx
Normal file
31
app/react/docker/containers/CreateView/LabelsTab/Item.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { FormError } from '@@/form-components/FormError';
|
||||
import { InputGroup } from '@@/form-components/InputGroup';
|
||||
import { ItemProps } from '@@/form-components/InputList';
|
||||
|
||||
import { Label } from './types';
|
||||
|
||||
export function Item({ item, onChange, error }: ItemProps<Label>) {
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="flex w-full gap-4">
|
||||
<InputGroup className="w-1/2">
|
||||
<InputGroup.Addon>name</InputGroup.Addon>
|
||||
<InputGroup.Input
|
||||
value={item.name}
|
||||
onChange={(e) => onChange({ ...item, name: e.target.value })}
|
||||
placeholder="e.g. com.example.foo"
|
||||
/>
|
||||
</InputGroup>
|
||||
<InputGroup className="w-1/2">
|
||||
<InputGroup.Addon>value</InputGroup.Addon>
|
||||
<InputGroup.Input
|
||||
value={item.value}
|
||||
onChange={(e) => onChange({ ...item, value: e.target.value })}
|
||||
placeholder="e.g. bar"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
{error && <FormError>{Object.values(error)[0]}</FormError>}
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import { useState } from 'react';
|
||||
|
||||
import { InputList } from '@@/form-components/InputList';
|
||||
import { ArrayError } from '@@/form-components/InputList/InputList';
|
||||
|
||||
import { Item } from './Item';
|
||||
import { Values } from './types';
|
||||
|
||||
export function LabelsTab({
|
||||
values: initialValues,
|
||||
onChange,
|
||||
errors,
|
||||
}: {
|
||||
values: Values;
|
||||
onChange: (values: Values) => void;
|
||||
errors?: ArrayError<Values>;
|
||||
}) {
|
||||
const [values, setControlledValues] = useState(initialValues);
|
||||
|
||||
return (
|
||||
<InputList
|
||||
label="Labels"
|
||||
onChange={handleChange}
|
||||
errors={errors}
|
||||
value={values}
|
||||
item={Item}
|
||||
itemBuilder={() => ({ name: '', value: '' })}
|
||||
/>
|
||||
);
|
||||
|
||||
function handleChange(values: Values) {
|
||||
setControlledValues(values);
|
||||
onChange(values);
|
||||
}
|
||||
}
|
14
app/react/docker/containers/CreateView/LabelsTab/index.ts
Normal file
14
app/react/docker/containers/CreateView/LabelsTab/index.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { validation } from './validation';
|
||||
import { toRequest } from './toRequest';
|
||||
import { toViewModel, getDefaultViewModel } from './toViewModel';
|
||||
|
||||
export { LabelsTab } from './LabelsTab';
|
||||
|
||||
export { type Values as LabelsTabValues } from './types';
|
||||
|
||||
export const labelsTabUtils = {
|
||||
toRequest,
|
||||
toViewModel,
|
||||
validation,
|
||||
getDefaultViewModel,
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
import { CreateContainerRequest } from '../types';
|
||||
|
||||
import { Values } from './types';
|
||||
|
||||
export function toRequest(
|
||||
oldConfig: CreateContainerRequest,
|
||||
values: Values
|
||||
): CreateContainerRequest {
|
||||
return {
|
||||
...oldConfig,
|
||||
Labels: Object.fromEntries(
|
||||
values
|
||||
.filter((label) => label.name)
|
||||
.map((label) => [label.name, label.value])
|
||||
),
|
||||
};
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import { ContainerJSON } from '../../queries/container';
|
||||
|
||||
import { Values } from './types';
|
||||
|
||||
export function toViewModel(config: ContainerJSON): Values {
|
||||
if (!config || !config.Config || !config.Config.Labels) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return Object.entries(config.Config.Labels).map(([name, value]) => ({
|
||||
name,
|
||||
value,
|
||||
}));
|
||||
}
|
||||
|
||||
export function getDefaultViewModel(): Values {
|
||||
return [];
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export interface Label {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
export type Values = Array<Label>;
|
|
@ -0,0 +1,12 @@
|
|||
import { array, object, SchemaOf, string } from 'yup';
|
||||
|
||||
import { Values } from './types';
|
||||
|
||||
export function validation(): SchemaOf<Values> {
|
||||
return array(
|
||||
object({
|
||||
name: string().required('Name is required'),
|
||||
value: string().default(''),
|
||||
})
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue