1
0
Fork 0
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:
Chaim Lev-Ari 2023-09-26 13:54:45 +03:00 committed by GitHub
parent b4b44e6fa4
commit 7acde18930
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 159 additions and 67 deletions

View 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>
);
}

View file

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

View 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,
};

View file

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

View file

@ -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 [];
}

View file

@ -0,0 +1,6 @@
export interface Label {
name: string;
value: string;
}
export type Values = Array<Label>;

View file

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