1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-19 13:29:41 +02:00

fix(ui): apply controlled input to field [EE-6411] (#10738)

This commit is contained in:
Chaim Lev-Ari 2024-01-08 12:11:31 +07:00 committed by GitHub
parent 98157350b6
commit e142939929
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 41 additions and 50 deletions

View file

@ -15,7 +15,7 @@ import { AssociatedEdgeEnvironmentsSelector } from '@/react/edge/components/Asso
import { EnvironmentsDatatable } from '@/react/edge/edge-stacks/ItemView/EnvironmentsDatatable'; import { EnvironmentsDatatable } from '@/react/edge/edge-stacks/ItemView/EnvironmentsDatatable';
import { TemplateFieldset } from '@/react/edge/edge-stacks/CreateView/TemplateFieldset'; import { TemplateFieldset } from '@/react/edge/edge-stacks/CreateView/TemplateFieldset';
export const componentsModule = angular const ngModule = angular
.module('portainer.edge.react.components', []) .module('portainer.edge.react.components', [])
.component( .component(
'edgeStackEnvironmentsDatatable', 'edgeStackEnvironmentsDatatable',
@ -104,4 +104,6 @@ export const componentsModule = angular
.component( .component(
'edgeStackCreateTemplateFieldset', 'edgeStackCreateTemplateFieldset',
r2a(withReactQuery(TemplateFieldset), ['setValues', 'values', 'errors']) r2a(withReactQuery(TemplateFieldset), ['setValues', 'values', 'errors'])
).name; );
export const componentsModule = ngModule.name;

View file

@ -0,0 +1,6 @@
import angular from 'angular';
export const applicationsModule = angular.module(
'portainer.kubernetes.react.components.applications',
[]
).name;

View file

@ -3,7 +3,6 @@ import angular from 'angular';
import { r2a } from '@/react-tools/react2angular'; import { r2a } from '@/react-tools/react2angular';
import { IngressClassDatatableAngular } from '@/react/kubernetes/cluster/ingressClass/IngressClassDatatable/IngressClassDatatableAngular'; import { IngressClassDatatableAngular } from '@/react/kubernetes/cluster/ingressClass/IngressClassDatatable/IngressClassDatatableAngular';
import { NamespacesSelector } from '@/react/kubernetes/cluster/RegistryAccessView/NamespacesSelector'; import { NamespacesSelector } from '@/react/kubernetes/cluster/RegistryAccessView/NamespacesSelector';
import { StorageAccessModeSelector } from '@/react/kubernetes/cluster/ConfigureView/ConfigureForm/StorageAccessModeSelector';
import { NamespaceAccessUsersSelector } from '@/react/kubernetes/namespaces/AccessView/NamespaceAccessUsersSelector'; import { NamespaceAccessUsersSelector } from '@/react/kubernetes/namespaces/AccessView/NamespaceAccessUsersSelector';
import { RegistriesSelector } from '@/react/kubernetes/namespaces/components/RegistriesFormSection/RegistriesSelector'; import { RegistriesSelector } from '@/react/kubernetes/namespaces/components/RegistriesFormSection/RegistriesSelector';
import { KubeServicesForm } from '@/react/kubernetes/applications/CreateView/application-services/KubeServicesForm'; import { KubeServicesForm } from '@/react/kubernetes/applications/CreateView/application-services/KubeServicesForm';
@ -51,8 +50,10 @@ import { withControlledInput } from '@/react-tools/withControlledInput';
import { EnvironmentVariablesFieldset } from '@@/form-components/EnvironmentVariablesFieldset'; import { EnvironmentVariablesFieldset } from '@@/form-components/EnvironmentVariablesFieldset';
import { applicationsModule } from './applications';
export const ngModule = angular export const ngModule = angular
.module('portainer.kubernetes.react.components', []) .module('portainer.kubernetes.react.components', [applicationsModule])
.component( .component(
'ingressClassDatatable', 'ingressClassDatatable',
r2a(IngressClassDatatableAngular, [ r2a(IngressClassDatatableAngular, [
@ -78,16 +79,6 @@ export const ngModule = angular
'value', 'value',
]) ])
) )
.component(
'storageAccessModeSelector',
r2a(StorageAccessModeSelector, [
'inputId',
'onChange',
'options',
'value',
'storageClassName',
])
)
.component( .component(
'namespaceAccessUsersSelector', 'namespaceAccessUsersSelector',
r2a(NamespaceAccessUsersSelector, [ r2a(NamespaceAccessUsersSelector, [
@ -140,11 +131,12 @@ export const ngModule = angular
) )
.component( .component(
'kubeStackName', 'kubeStackName',
r2a(withUIRouter(withReactQuery(withCurrentUser(StackName))), [ r2a(
'setStackName', withUIRouter(
'isAdmin', withReactQuery(withCurrentUser(withControlledInput(StackName)))
'stackName', ),
]) ['setStackName', 'isAdmin', 'stackName']
)
) )
.component( .component(
'applicationSummaryWidget', 'applicationSummaryWidget',
@ -202,8 +194,12 @@ export const componentsModule = ngModule.name;
withFormValidation( withFormValidation(
ngModule, ngModule,
withControlledInput( withUIRouter(
withUIRouter(withCurrentUser(withReactQuery(KubeServicesForm))) withCurrentUser(
withReactQuery(
withControlledInput(KubeServicesForm, { values: 'onChange' })
)
)
), ),
'kubeServicesForm', 'kubeServicesForm',
['values', 'onChange', 'appName', 'selector', 'isEditMode', 'namespace'], ['values', 'onChange', 'appName', 'selector', 'isEditMode', 'namespace'],

View file

@ -1,13 +0,0 @@
import angular from 'angular';
import { r2a } from '@/react-tools/react2angular';
import { ImportFdoDeviceButton } from '@/react/portainer/environments/ListView/ImportFdoDeviceButton';
import { withUIRouter } from '@/react-tools/withUIRouter';
import { withReactQuery } from '@/react-tools/withReactQuery';
export const envListModule = angular
.module('portainer.app.react.components.environments.list-view', [])
.component(
'importFdoDeviceButton',
r2a(withUIRouter(withReactQuery(ImportFdoDeviceButton)), [])
).name;

View file

@ -9,6 +9,7 @@ import { withFormValidation } from '@/react-tools/withFormValidation';
import { GroupAssociationTable } from '@/react/portainer/environments/environment-groups/components/GroupAssociationTable'; import { GroupAssociationTable } from '@/react/portainer/environments/environment-groups/components/GroupAssociationTable';
import { AssociatedEnvironmentsSelector } from '@/react/portainer/environments/environment-groups/components/AssociatedEnvironmentsSelector'; import { AssociatedEnvironmentsSelector } from '@/react/portainer/environments/environment-groups/components/AssociatedEnvironmentsSelector';
import { HelmRepositoryDatatable } from '@/react/portainer/account/AccountView/HelmRepositoryDatatable'; import { HelmRepositoryDatatable } from '@/react/portainer/account/AccountView/HelmRepositoryDatatable';
import { withControlledInput } from '@/react-tools/withControlledInput';
import { import {
EnvironmentVariablesFieldset, EnvironmentVariablesFieldset,
@ -21,7 +22,6 @@ import { PageHeader } from '@@/PageHeader';
import { TagSelector } from '@@/TagSelector'; import { TagSelector } from '@@/TagSelector';
import { Loading } from '@@/Widget/Loading'; import { Loading } from '@@/Widget/Loading';
import { PasswordCheckHint } from '@@/PasswordCheckHint'; import { PasswordCheckHint } from '@@/PasswordCheckHint';
import { ViewLoading } from '@@/ViewLoading';
import { Tooltip } from '@@/Tip/Tooltip'; import { Tooltip } from '@@/Tip/Tooltip';
import { Badge } from '@@/Badge'; import { Badge } from '@@/Badge';
import { TableColumnHeaderAngular } from '@@/datatables/TableHeaderCell'; import { TableColumnHeaderAngular } from '@@/datatables/TableHeaderCell';
@ -43,7 +43,6 @@ import { gitFormModule } from './git-form';
import { settingsModule } from './settings'; import { settingsModule } from './settings';
import { accessControlModule } from './access-control'; import { accessControlModule } from './access-control';
import { environmentsModule } from './environments'; import { environmentsModule } from './environments';
import { envListModule } from './environments-list-view-components';
import { registriesModule } from './registries'; import { registriesModule } from './registries';
import { accountModule } from './account'; import { accountModule } from './account';
@ -51,7 +50,6 @@ export const ngModule = angular
.module('portainer.app.react.components', [ .module('portainer.app.react.components', [
accessControlModule, accessControlModule,
customTemplatesModule, customTemplatesModule,
envListModule,
environmentsModule, environmentsModule,
gitFormModule, gitFormModule,
registriesModule, registriesModule,
@ -106,7 +104,6 @@ export const ngModule = angular
'isSortedDesc', 'isSortedDesc',
]) ])
) )
.component('viewLoading', r2a(ViewLoading, ['message']))
.component( .component(
'pageHeader', 'pageHeader',
r2a(withUIRouter(withReactQuery(withCurrentUser(PageHeader))), [ r2a(withUIRouter(withReactQuery(withCurrentUser(PageHeader))), [
@ -198,7 +195,6 @@ export const ngModule = angular
'dataCy', 'dataCy',
]) ])
) )
.component( .component(
'reactCodeEditor', 'reactCodeEditor',
r2a(CodeEditor, [ r2a(CodeEditor, [
@ -240,7 +236,7 @@ export const componentsModule = ngModule.name;
withFormValidation( withFormValidation(
ngModule, ngModule,
EnvironmentVariablesFieldset, withControlledInput(EnvironmentVariablesFieldset, { values: 'onChange' }),
'environmentVariablesFieldset', 'environmentVariablesFieldset',
['canUndoDelete'], ['canUndoDelete'],
envVarValidation envVarValidation
@ -248,7 +244,7 @@ withFormValidation(
withFormValidation( withFormValidation(
ngModule, ngModule,
EnvironmentVariablesPanel, withControlledInput(EnvironmentVariablesPanel, { values: 'onChange' }),
'environmentVariablesPanel', 'environmentVariablesPanel',
['explanation', 'showHelpMessage', 'isFoldable'], ['explanation', 'showHelpMessage', 'isFoldable'],
envVarValidation envVarValidation

View file

@ -1,11 +1,12 @@
import { ComponentProps } from 'react';
import { FormSection } from '@@/form-components/FormSection'; import { FormSection } from '@@/form-components/FormSection';
import { TextTip } from '@@/Tip/TextTip'; import { TextTip } from '@@/Tip/TextTip';
import { ArrayError } from '../InputList/InputList';
import { Values } from './types';
import { EnvironmentVariablesFieldset } from './EnvironmentVariablesFieldset'; import { EnvironmentVariablesFieldset } from './EnvironmentVariablesFieldset';
type FieldsetProps = ComponentProps<typeof EnvironmentVariablesFieldset>;
export function EnvironmentVariablesPanel({ export function EnvironmentVariablesPanel({
explanation, explanation,
onChange, onChange,
@ -15,12 +16,9 @@ export function EnvironmentVariablesPanel({
isFoldable = false, isFoldable = false,
}: { }: {
explanation?: string; explanation?: string;
values: Values;
onChange(value: Values): void;
showHelpMessage?: boolean; showHelpMessage?: boolean;
errors?: ArrayError<Values>;
isFoldable?: boolean; isFoldable?: boolean;
}) { } & FieldsetProps) {
return ( return (
<FormSection <FormSection
title="Environment variables" title="Environment variables"

View file

@ -1,5 +1,6 @@
import { FormikErrors } from 'formik'; import { FormikErrors } from 'formik';
import { boolean, number, object, SchemaOf, string } from 'yup'; import { boolean, number, object, SchemaOf, string } from 'yup';
import { useState } from 'react';
import { GitAuthModel } from '@/react/portainer/gitops/types'; import { GitAuthModel } from '@/react/portainer/gitops/types';
import { useDebounce } from '@/react/hooks/useDebounce'; import { useDebounce } from '@/react/hooks/useDebounce';
@ -23,11 +24,12 @@ interface Props {
} }
export function AuthFieldset({ export function AuthFieldset({
value, value: initialValue,
onChange, onChange,
isAuthExplanationVisible, isAuthExplanationVisible,
errors, errors,
}: Props) { }: Props) {
const [value, setValue] = useState(initialValue); // TODO: remove this state when form is not inside angularjs
const [username, setUsername] = useDebounce( const [username, setUsername] = useDebounce(
value.RepositoryUsername || '', value.RepositoryUsername || '',
(username) => handleChange({ RepositoryUsername: username }) (username) => handleChange({ RepositoryUsername: username })
@ -139,6 +141,7 @@ export function AuthFieldset({
function handleChange(partialValue: Partial<GitAuthModel>) { function handleChange(partialValue: Partial<GitAuthModel>) {
onChange(partialValue); onChange(partialValue);
setValue((value) => ({ ...value, ...partialValue }));
} }
} }

View file

@ -1,5 +1,6 @@
import { array, boolean, object, SchemaOf, string } from 'yup'; import { array, boolean, object, SchemaOf, string } from 'yup';
import { FormikErrors } from 'formik'; import { FormikErrors } from 'formik';
import { useState } from 'react';
import { ComposePathField } from '@/react/portainer/gitops/ComposePathField'; import { ComposePathField } from '@/react/portainer/gitops/ComposePathField';
import { RefField } from '@/react/portainer/gitops/RefField'; import { RefField } from '@/react/portainer/gitops/RefField';
@ -35,7 +36,7 @@ interface Props {
} }
export function GitForm({ export function GitForm({
value, value: initialValue,
onChange, onChange,
environmentType = 'DOCKER', environmentType = 'DOCKER',
deployMethod = 'compose', deployMethod = 'compose',
@ -48,6 +49,7 @@ export function GitForm({
webhookId, webhookId,
webhooksDocs, webhooksDocs,
}: Props) { }: Props) {
const [value, setValue] = useState(initialValue); // TODO: remove this state when form is not inside angularjs
return ( return (
<FormSection title="Git repository"> <FormSection title="Git repository">
<AuthFieldset <AuthFieldset
@ -126,6 +128,7 @@ export function GitForm({
function handleChange(partialValue: Partial<GitFormModel>) { function handleChange(partialValue: Partial<GitFormModel>) {
onChange(partialValue); onChange(partialValue);
setValue((value) => ({ ...value, ...partialValue }));
} }
} }