1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-09 07:45:22 +02:00

refactor(app): move react components to react codebase [EE-3179] (#6971)

This commit is contained in:
Chaim Lev-Ari 2022-06-17 19:18:42 +03:00 committed by GitHub
parent 212400c283
commit 18252ab854
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
346 changed files with 642 additions and 644 deletions

View file

@ -0,0 +1,54 @@
import userEvent from '@testing-library/user-event';
import { render } from '@/react-tools/test-utils';
import { CreateAccessToken } from './CreateAccessToken';
test('the button is disabled when description is missing and enabled when description is filled', async () => {
const queries = renderComponent();
const button = queries.getByRole('button', { name: 'Add access token' });
expect(button).toBeDisabled();
const descriptionField = queries.getByLabelText('Description');
userEvent.type(descriptionField, 'description');
expect(button).toBeEnabled();
userEvent.clear(descriptionField);
expect(button).toBeDisabled();
});
test('once the button is clicked, the access token is generated and displayed', async () => {
const token = 'a very long access token that should be displayed';
const onSubmit = jest.fn(() => Promise.resolve({ rawAPIKey: token }));
const queries = renderComponent(onSubmit);
const descriptionField = queries.getByLabelText('Description');
userEvent.type(descriptionField, 'description');
const button = queries.getByRole('button', { name: 'Add access token' });
userEvent.click(button);
expect(onSubmit).toHaveBeenCalledWith('description');
expect(onSubmit).toHaveBeenCalledTimes(1);
await expect(queries.findByText('New access token')).resolves.toBeVisible();
expect(queries.getByText(token)).toHaveTextContent(token);
});
function renderComponent(onSubmit = jest.fn()) {
const queries = render(
<CreateAccessToken onSubmit={onSubmit} onError={jest.fn()} />
);
expect(queries.getByLabelText('Description')).toBeVisible();
return queries;
}

View file

@ -0,0 +1,114 @@
import { PropsWithChildren, useEffect, useState } from 'react';
import { useRouter } from '@uirouter/react';
import { Trans, useTranslation } from 'react-i18next';
import { Widget, WidgetBody } from '@@/Widget';
import { FormControl } from '@@/form-components/FormControl';
import { Button } from '@@/buttons';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { TextTip } from '@@/Tip/TextTip';
import { Code } from '@@/Code';
import { CopyButton } from '@@/buttons/CopyButton';
import { Input } from '@@/form-components/Input';
interface AccessTokenResponse {
rawAPIKey: string;
}
export interface Props {
// onSubmit dispatches a successful matomo analytics event
onSubmit: (description: string) => Promise<AccessTokenResponse>;
// onError is called when an error occurs; this is a callback to Notifications.error
onError: (heading: string, err: unknown, message: string) => void;
}
export function CreateAccessToken({
onSubmit,
onError,
}: PropsWithChildren<Props>) {
const translationNS = 'account.accessTokens.create';
const { t } = useTranslation(translationNS);
const router = useRouter();
const [description, setDescription] = useState('');
const [errorText, setErrorText] = useState('');
const [isLoading, setIsLoading] = useState(false);
const [accessToken, setAccessToken] = useState('');
useEffect(() => {
if (description.length === 0) {
setErrorText(t('this field is required'));
} else setErrorText('');
}, [description, t]);
async function generateAccessToken() {
if (isLoading) {
return;
}
setIsLoading(true);
try {
const response = await onSubmit(description);
setAccessToken(response.rawAPIKey);
} catch (err) {
onError('Failure', err, 'Failed to generate access token');
} finally {
setIsLoading(false);
}
}
return (
<Widget>
<WidgetBody>
<div className="form-horizontal">
<FormControl
inputId="input"
label={t('Description')}
errors={errorText}
>
<Input
id="input"
onChange={(e) => setDescription(e.target.value)}
value={description}
/>
</FormControl>
<div className="row mt-5">
<div className="col-sm-12">
<Button
disabled={!!errorText || !!accessToken}
onClick={() => generateAccessToken()}
>
{t('Add access token')}
</Button>
</div>
</div>
</div>
{accessToken && (
<>
<FormSectionTitle>
<Trans ns={translationNS}>New access token</Trans>
</FormSectionTitle>
<TextTip>
<Trans ns={translationNS}>
Please copy the new access token. You won&#39;t be able to view
the token again.
</Trans>
</TextTip>
<Code>{accessToken}</Code>
<CopyButton copyText={accessToken}>
<Trans ns={translationNS}>Copy access token</Trans>
</CopyButton>
<hr />
<Button
type="button"
onClick={() => router.stateService.go('portainer.account')}
>
<Trans ns={translationNS}>Done</Trans>
</Button>
</>
)}
</WidgetBody>
</Widget>
);
}

View file

@ -0,0 +1 @@
export { CreateAccessToken } from './CreateAccessToken';

View file

@ -1,10 +1,10 @@
import { FormError } from '@/portainer/components/form-components/FormError';
import { Input } from '@/portainer/components/form-components/Input';
import { InputList } from '@/portainer/components/form-components/InputList';
import { FormError } from '@@/form-components/FormError';
import { Input } from '@@/form-components/Input';
import { InputList } from '@@/form-components/InputList';
import {
InputListError,
ItemProps,
} from '@/portainer/components/form-components/InputList/InputList';
} from '@@/form-components/InputList/InputList';
export interface VariableDefinition {
name: string;

View file

@ -1,6 +1,6 @@
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { FormSection } from '@/portainer/components/form-components/FormSection/FormSection';
import { Input } from '@/portainer/components/form-components/Input';
import { FormControl } from '@@/form-components/FormControl';
import { FormSection } from '@@/form-components/FormSection/FormSection';
import { Input } from '@@/form-components/Input';
import { VariableDefinition } from '../CustomTemplatesVariablesDefinitionField/CustomTemplatesVariablesDefinitionField';

View file

@ -2,11 +2,12 @@ import { useState } from 'react';
import { useRouter } from '@uirouter/react';
import _ from 'lodash';
import { Button } from '@/portainer/components/Button';
import { PageHeader } from '@/portainer/components/PageHeader';
import { Widget, WidgetBody, WidgetTitle } from '@/portainer/components/widget';
import { useAnalytics } from '@/angulartics.matomo/analytics-services';
import { Button } from '@@/buttons';
import { PageHeader } from '@@/PageHeader';
import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import {
EnvironmentSelector,
EnvironmentSelectorValue,

View file

@ -1,4 +1,4 @@
import { FormSection } from '@/portainer/components/form-components/FormSection';
import { FormSection } from '@@/form-components/FormSection';
import { Option } from '../components/Option';

View file

@ -3,14 +3,15 @@ import { useState } from 'react';
import _ from 'lodash';
import clsx from 'clsx';
import { Stepper } from '@/react/components/Stepper';
import { Widget, WidgetBody, WidgetTitle } from '@/portainer/components/widget';
import { notifyError } from '@/portainer/services/notifications';
import { PageHeader } from '@/portainer/components/PageHeader';
import { Button } from '@/portainer/components/Button';
import { Environment, EnvironmentId } from '@/portainer/environments/types';
import { useAnalytics } from '@/angulartics.matomo/analytics-services';
import { FormSection } from '@/portainer/components/form-components/FormSection';
import { Stepper } from '@@/Stepper';
import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import { PageHeader } from '@@/PageHeader';
import { Button } from '@@/buttons';
import { FormSection } from '@@/form-components/FormSection';
import { environmentTypes } from '../EnvironmentTypeSelectView/environment-types';
import { EnvironmentSelectorValue } from '../EnvironmentTypeSelectView/EnvironmentSelector';

View file

@ -2,15 +2,17 @@ import { Field, Form, Formik } from 'formik';
import { useReducer, useState } from 'react';
import { object, SchemaOf, string } from 'yup';
import { BoxSelector, buildOption } from '@/portainer/components/BoxSelector';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Input } from '@/portainer/components/form-components/Input';
import { LoadingButton } from '@/portainer/components/Button/LoadingButton';
import { buildOption } from '@/portainer/components/BoxSelector';
import { useCreateAzureEnvironmentMutation } from '@/portainer/environments/queries/useCreateEnvironmentMutation';
import { notifySuccess } from '@/portainer/services/notifications';
import { Environment } from '@/portainer/environments/types';
import { EnvironmentMetadata } from '@/portainer/environments/environment.service/create';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { Input } from '@@/form-components/Input';
import { FormControl } from '@@/form-components/FormControl';
import { BoxSelector } from '@@/BoxSelector';
import { NameField, nameValidation } from '../shared/NameField';
import { AnalyticsStateKey } from '../types';
import { metadataValidation } from '../shared/MetadataFieldset/validation';

View file

@ -1,16 +1,17 @@
import { Field, Form, Formik } from 'formik';
import { useReducer } from 'react';
import { LoadingButton } from '@/portainer/components/Button/LoadingButton';
import { useCreateRemoteEnvironmentMutation } from '@/portainer/environments/queries/useCreateEnvironmentMutation';
import { notifySuccess } from '@/portainer/services/notifications';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Input } from '@/portainer/components/form-components/Input';
import {
Environment,
EnvironmentCreationTypes,
} from '@/portainer/environments/types';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { FormControl } from '@@/form-components/FormControl';
import { Input } from '@@/form-components/Input';
import { NameField } from '../../shared/NameField';
import { MoreSettingsSection } from '../../shared/MoreSettingsSection';

View file

@ -1,10 +1,11 @@
import { useState } from 'react';
import { CopyButton } from '@/portainer/components/Button/CopyButton';
import { Code } from '@/portainer/components/Code';
import { NavTabs } from '@/portainer/components/NavTabs/NavTabs';
import { useAgentDetails } from '@/portainer/environments/queries/useAgentDetails';
import { CopyButton } from '@@/buttons/CopyButton';
import { Code } from '@@/Code';
import { NavTabs } from '@@/NavTabs';
const deployments = [
{
id: 'linux',

View file

@ -1,14 +1,15 @@
import { useFormikContext } from 'formik';
import { FileUploadField } from '@/portainer/components/form-components/FileUpload';
import { SwitchField } from '@/portainer/components/form-components/SwitchField';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import {
file,
withFileSize,
withFileType,
} from '@/portainer/helpers/yup-file-validation';
import { FileUploadField } from '@@/form-components/FileUpload';
import { SwitchField } from '@@/form-components/SwitchField';
import { FormControl } from '@@/form-components/FormControl';
import { FormValues } from './types';
export function TLSFieldset() {

View file

@ -1,11 +1,12 @@
import { useState } from 'react';
import { CopyButton } from '@/portainer/components/Button/CopyButton';
import { Code } from '@/portainer/components/Code';
import { NavTabs } from '@/portainer/components/NavTabs/NavTabs';
import { getAgentShortVersion } from '@/portainer/views/endpoints/helpers';
import { useAgentDetails } from '@/portainer/environments/queries/useAgentDetails';
import { CopyButton } from '@@/buttons/CopyButton';
import { Code } from '@@/Code';
import { NavTabs } from '@@/NavTabs';
const deployments = [
{
id: 'linux',

View file

@ -1,14 +1,15 @@
import { Field, Form, Formik, useFormikContext } from 'formik';
import { useReducer } from 'react';
import { LoadingButton } from '@/portainer/components/Button/LoadingButton';
import { useCreateLocalDockerEnvironmentMutation } from '@/portainer/environments/queries/useCreateEnvironmentMutation';
import { notifySuccess } from '@/portainer/services/notifications';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Input } from '@/portainer/components/form-components/Input';
import { SwitchField } from '@/portainer/components/form-components/SwitchField';
import { Environment } from '@/portainer/environments/types';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { FormControl } from '@@/form-components/FormControl';
import { Input } from '@@/form-components/Input';
import { SwitchField } from '@@/form-components/SwitchField';
import { NameField } from '../../shared/NameField';
import { MoreSettingsSection } from '../../shared/MoreSettingsSection';

View file

@ -1,12 +1,10 @@
import { useState } from 'react';
import {
BoxSelector,
BoxSelectorOption,
} from '@/portainer/components/BoxSelector';
import { Environment } from '@/portainer/environments/types';
import { commandsTabs } from '@/react/edge/components/EdgeScriptForm/scripts';
import { BoxSelector, type BoxSelectorOption } from '@@/BoxSelector';
import { AnalyticsStateKey } from '../types';
import { EdgeAgentTab } from '../shared/EdgeAgentTab';

View file

@ -1,6 +1,5 @@
import clsx from 'clsx';
import { Widget, WidgetBody, WidgetTitle } from '@/portainer/components/widget';
import {
environmentTypeIcon,
endpointTypeName,
@ -17,6 +16,8 @@ import {
useEnvironmentList,
} from '@/portainer/environments/queries/useEnvironmentList';
import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import styles from './WizardEndpointsList.module.css';
interface Props {

View file

@ -1,12 +1,13 @@
import { useState } from 'react';
import { CopyButton } from '@/portainer/components/Button/CopyButton';
import { Code } from '@/portainer/components/Code';
import { FormSectionTitle } from '@/portainer/components/form-components/FormSectionTitle';
import { NavTabs } from '@/portainer/components/NavTabs/NavTabs';
import { getAgentShortVersion } from '@/portainer/views/endpoints/helpers';
import { useAgentDetails } from '@/portainer/environments/queries/useAgentDetails';
import { CopyButton } from '@@/buttons/CopyButton';
import { Code } from '@@/Code';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { NavTabs } from '@@/NavTabs';
const deployments = [
{
id: 'k8sLoadBalancer',

View file

@ -1,10 +1,10 @@
import { Field, Form, Formik } from 'formik';
import { LoadingButton } from '@/portainer/components/Button/LoadingButton';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { FormSectionTitle } from '@/portainer/components/form-components/FormSectionTitle';
import { Input } from '@/portainer/components/form-components/Input';
import { Button } from '@/portainer/components/Button';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { FormControl } from '@@/form-components/FormControl';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { Input } from '@@/form-components/Input';
import { Button } from '@@/buttons';
const initialValues = {
kubeConfig: '',

View file

@ -1,14 +1,15 @@
import { useState } from 'react';
import { BoxSelector } from '@/portainer/components/BoxSelector';
import {
Environment,
EnvironmentCreationTypes,
} from '@/portainer/environments/types';
import { BoxSelectorOption } from '@/portainer/components/BoxSelector/types';
import { commandsTabs } from '@/react/edge/components/EdgeScriptForm/scripts';
import { FeatureId } from '@/portainer/feature-flags/enums';
import { BEFeatureIndicator } from '@/portainer/components/BEFeatureIndicator';
import { BoxSelectorOption } from '@@/BoxSelector/types';
import { BoxSelector } from '@@/BoxSelector';
import { BEFeatureIndicator } from '@@/BEFeatureIndicator';
import { AnalyticsStateKey } from '../types';
import { EdgeAgentTab } from '../shared/EdgeAgentTab';

View file

@ -1,12 +1,13 @@
import { Form, Formik } from 'formik';
import { useReducer } from 'react';
import { LoadingButton } from '@/portainer/components/Button/LoadingButton';
import { useCreateAgentEnvironmentMutation } from '@/portainer/environments/queries/useCreateEnvironmentMutation';
import { notifySuccess } from '@/portainer/services/notifications';
import { Environment } from '@/portainer/environments/types';
import { CreateAgentEnvironmentValues } from '@/portainer/environments/environment.service/create';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { NameField } from '../NameField';
import { MoreSettingsSection } from '../MoreSettingsSection';

View file

@ -1,7 +1,7 @@
import { Field, useField } from 'formik';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Input } from '@/portainer/components/form-components/Input';
import { FormControl } from '@@/form-components/FormControl';
import { Input } from '@@/form-components/Input';
export function EnvironmentUrlField() {
const [, meta] = useField('environmentUrl');

View file

@ -1,12 +1,13 @@
import { Formik, Form } from 'formik';
import { LoadingButton } from '@/portainer/components/Button/LoadingButton';
import { Environment } from '@/portainer/environments/types';
import { useCreateEdgeAgentEnvironmentMutation } from '@/portainer/environments/queries/useCreateEnvironmentMutation';
import { baseHref } from '@/portainer/helpers/pathHelper';
import { FormSection } from '@/portainer/components/form-components/FormSection';
import { EdgeCheckinIntervalField } from '@/edge/components/EdgeCheckInIntervalField';
import { FormSection } from '@@/form-components/FormSection';
import { LoadingButton } from '@@/buttons/LoadingButton';
import { MoreSettingsSection } from '../../MoreSettingsSection';
import { EdgeAgentFieldset } from './EdgeAgentFieldset';

View file

@ -1,8 +1,8 @@
import { Field, useField } from 'formik';
import { string } from 'yup';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Input } from '@/portainer/components/form-components/Input';
import { FormControl } from '@@/form-components/FormControl';
import { Input } from '@@/form-components/Input';
interface Props {
fieldName: string;

View file

@ -1,12 +1,13 @@
import { v4 as uuid } from 'uuid';
import { useReducer, useState } from 'react';
import { Button } from '@/portainer/components/Button';
import { Environment } from '@/portainer/environments/types';
import { EdgeScriptForm } from '@/react/edge/components/EdgeScriptForm';
import { CommandTab } from '@/react/edge/components/EdgeScriptForm/scripts';
import { OS, EdgeInfo } from '@/react/edge/components/EdgeScriptForm/types';
import { Button } from '@@/buttons';
import { EdgeAgentForm } from './EdgeAgentForm';
interface Props {

View file

@ -1,10 +1,11 @@
import { useField } from 'formik';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Select } from '@/portainer/components/form-components/Input';
import { useGroups } from '@/portainer/environment-groups/queries';
import { EnvironmentGroupId } from '@/portainer/environment-groups/types';
import { FormControl } from '@@/form-components/FormControl';
import { Select } from '@@/form-components/Input';
export function GroupField() {
const [fieldProps, metaProps, helpers] =
useField<EnvironmentGroupId>('meta.groupId');

View file

@ -1,8 +1,9 @@
import { useField } from 'formik';
import { TagSelector } from '@/react/components/TagSelector';
import { useUser } from '@/portainer/hooks/useUser';
import { FormSection } from '@/portainer/components/form-components/FormSection';
import { TagSelector } from '@@/TagSelector';
import { FormSection } from '@@/form-components/FormSection';
import { GroupField } from './GroupsField';

View file

@ -1,6 +1,6 @@
import { PropsWithChildren } from 'react';
import { FormSection } from '@/portainer/components/form-components/FormSection';
import { FormSection } from '@@/form-components/FormSection';
import { MetadataFieldset } from './MetadataFieldset';

View file

@ -2,10 +2,11 @@ import { Field, useField } from 'formik';
import { string } from 'yup';
import { debounce } from 'lodash';
import { FormControl } from '@/portainer/components/form-components/FormControl';
import { Input } from '@/portainer/components/form-components/Input';
import { getEndpoints } from '@/portainer/environments/environment.service';
import { FormControl } from '@@/form-components/FormControl';
import { Input } from '@@/form-components/Input';
interface Props {
readonly?: boolean;
}

View file

@ -1,8 +1,9 @@
import { PageHeader } from '@/portainer/components/PageHeader';
import { Widget, WidgetBody, WidgetTitle } from '@/portainer/components/widget';
import { EnvironmentType } from '@/portainer/environments/types';
import { useAnalytics } from '@/angulartics.matomo/analytics-services';
import { Link } from '@/portainer/components/Link';
import { PageHeader } from '@@/PageHeader';
import { Widget, WidgetBody, WidgetTitle } from '@@/Widget';
import { Link } from '@@/Link';
import { Option } from '../components/Option';

View file

@ -1,10 +1,11 @@
import clsx from 'clsx';
import { ComponentType } from 'react';
import { BEFeatureIndicator } from '@/portainer/components/BEFeatureIndicator';
import { FeatureId } from '@/portainer/feature-flags/enums';
import { isLimitedToBE } from '@/portainer/feature-flags/feature-flags.service';
import { BEFeatureIndicator } from '@@/BEFeatureIndicator';
import styles from './Option.module.css';
export interface SelectorItemType {