1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-04 13:25:26 +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,7 @@
.file-input {
display: none !important;
}
.file-button {
margin-left: 0 !important;
}

View file

@ -0,0 +1,33 @@
import { Meta } from '@storybook/react';
import { useState } from 'react';
import { FileUploadField } from './FileUploadField';
export default {
component: FileUploadField,
title: 'Components/Buttons/FileUploadField',
} as Meta;
interface Args {
title: string;
}
export { Example };
function Example({ title }: Args) {
const [value, setValue] = useState<File>();
function onChange(value: File) {
if (value) {
setValue(value);
}
}
return (
<FileUploadField
onChange={onChange}
value={value}
title={title}
inputId="file-field"
/>
);
}

View file

@ -0,0 +1,28 @@
import { fireEvent, render } from '@/react-tools/test-utils';
import { FileUploadField } from './FileUploadField';
test('render should make the file button clickable and fire onChange event after click', async () => {
const onClick = jest.fn();
const { findByText, findByLabelText } = render(
<FileUploadField
title="test button"
onChange={onClick}
inputId="file-field"
/>
);
const button = await findByText('test button');
expect(button).toBeVisible();
const input = await findByLabelText('file-input');
expect(input).not.toBeNull();
const mockFile = new File([], 'file.txt');
if (input) {
fireEvent.change(input, {
target: { files: [mockFile] },
});
}
expect(onClick).toHaveBeenCalledWith(mockFile);
});

View file

@ -0,0 +1,68 @@
import { ChangeEvent, createRef } from 'react';
import { Button } from '@@/buttons';
import styles from './FileUploadField.module.css';
export interface Props {
onChange(value: File): void;
value?: File;
accept?: string;
title?: string;
required?: boolean;
inputId: string;
}
export function FileUploadField({
onChange,
value,
accept,
title = 'Select a file',
required = false,
inputId,
}: Props) {
const fileRef = createRef<HTMLInputElement>();
return (
<div className="file-upload-field">
<input
id={inputId}
ref={fileRef}
type="file"
accept={accept}
required={required}
className={styles.fileInput}
onChange={changeHandler}
aria-label="file-input"
/>
<Button
size="small"
color="primary"
onClick={handleButtonClick}
className={styles.fileButton}
>
{title}
</Button>
<span className="space-left">
{value ? (
value.name
) : (
<i className="fa fa-times red-icon" aria-hidden="true" />
)}
</span>
</div>
);
function handleButtonClick() {
if (fileRef && fileRef.current) {
fileRef.current.click();
}
}
function changeHandler(event: ChangeEvent<HTMLInputElement>) {
if (event.target && event.target.files && event.target.files.length > 0) {
onChange(event.target.files[0]);
}
}
}

View file

@ -0,0 +1,37 @@
import { Meta } from '@storybook/react';
import { useState } from 'react';
import { FileUploadForm } from './FileUploadForm';
export default {
component: FileUploadForm,
title: 'Components/Form/FileUploadForm',
} as Meta;
interface Args {
title: string;
}
export { Example };
function Example({ title }: Args) {
const [value, setValue] = useState<File>();
function onChange(value: File) {
if (value) {
setValue(value);
}
}
return (
<div className="form-horizontal">
<FileUploadForm
onChange={onChange}
value={value}
title={title}
description={
<span>You can upload a Compose file from your computer.</span>
}
/>
</div>
);
}

View file

@ -0,0 +1,20 @@
import { render } from '@/react-tools/test-utils';
import { FileUploadForm } from './FileUploadForm';
test('render should include description', async () => {
const onClick = jest.fn();
const { findByText } = render(
<FileUploadForm
title="test button"
onChange={onClick}
description={<span>test description</span>}
/>
);
const button = await findByText('test button');
expect(button).toBeVisible();
const description = await findByText('test description');
expect(description).toBeVisible();
});

View file

@ -0,0 +1,40 @@
import { PropsWithChildren, ReactNode } from 'react';
import { FormSectionTitle } from '@@/form-components/FormSectionTitle';
import { FileUploadField } from '@@/form-components/FileUpload/FileUploadField';
export interface Props {
onChange(value: unknown): void;
value?: File;
title?: string;
required?: boolean;
description: ReactNode;
}
export function FileUploadForm({
onChange,
value,
title = 'Select a file',
required = false,
description,
}: PropsWithChildren<Props>) {
return (
<div className="file-upload-form">
<FormSectionTitle>Upload</FormSectionTitle>
<div className="form-group">
<span className="col-sm-12 text-muted small">{description}</span>
</div>
<div className="form-group">
<div className="col-sm-12">
<FileUploadField
inputId="file-upload-field"
onChange={onChange}
value={value}
title={title}
required={required}
/>
</div>
</div>
</div>
);
}

View file

@ -0,0 +1,2 @@
export { FileUploadField } from './FileUploadField';
export { FileUploadForm } from './FileUploadForm';