initial version of json file upload component (#75)
This commit is contained in:
parent
c59a7198c9
commit
082682e6d3
7 changed files with 690 additions and 88 deletions
|
@ -1,5 +1,6 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
...require("@snowpack/app-scripts-react/jest.config.js")(),
|
...require("@snowpack/app-scripts-react/jest.config.js")(),
|
||||||
|
"snapshotSerializers": ["enzyme-to-json/serializer"],
|
||||||
"moduleNameMapper": {
|
"moduleNameMapper": {
|
||||||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/src/__mocks__/fileMock.js",
|
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/src/__mocks__/fileMock.js",
|
||||||
"\\.(css|less)$": "<rootDir>/src/__mocks__/styleMock.js"
|
"\\.(css|less)$": "<rootDir>/src/__mocks__/styleMock.js"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Button, AlertVariant } from "@patternfly/react-core";
|
import { Button, AlertVariant } from "@patternfly/react-core";
|
||||||
import { mount } from "enzyme";
|
import { mount } from "enzyme";
|
||||||
import EnzymeToJson from "enzyme-to-json";
|
|
||||||
import { act } from "react-dom/test-utils";
|
import { act } from "react-dom/test-utils";
|
||||||
|
|
||||||
import { AlertPanel } from "./AlertPanel";
|
import { AlertPanel } from "./AlertPanel";
|
||||||
|
@ -20,9 +19,7 @@ const WithButton = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
it("renders global alerts", () => {
|
it("renders global alerts", () => {
|
||||||
const empty = EnzymeToJson(
|
const empty = mount(<AlertPanel alerts={[]} onCloseAlert={() => {}} />);
|
||||||
mount(<AlertPanel alerts={[]} onCloseAlert={() => {}} />)
|
|
||||||
);
|
|
||||||
expect(empty).toMatchSnapshot();
|
expect(empty).toMatchSnapshot();
|
||||||
|
|
||||||
const tree = mount(<WithButton />);
|
const tree = mount(<WithButton />);
|
||||||
|
@ -32,10 +29,10 @@ it("renders global alerts", () => {
|
||||||
act(() => {
|
act(() => {
|
||||||
button!.simulate("click");
|
button!.simulate("click");
|
||||||
});
|
});
|
||||||
expect(EnzymeToJson(tree)).toMatchSnapshot();
|
expect(tree).toMatchSnapshot();
|
||||||
|
|
||||||
act(() => {
|
act(() => {
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
});
|
});
|
||||||
expect(EnzymeToJson(tree)).toMatchSnapshot();
|
expect(tree).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
35
src/components/json-file-upload/JsonFileUpload.test.tsx
Normal file
35
src/components/json-file-upload/JsonFileUpload.test.tsx
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import React from "react";
|
||||||
|
import { mount } from "enzyme";
|
||||||
|
|
||||||
|
import { JsonFileUpload } from "./JsonFileUpload";
|
||||||
|
|
||||||
|
describe("<JsonFileUpload />", () => {
|
||||||
|
it("render", () => {
|
||||||
|
const comp = mount(<JsonFileUpload id="test" onChange={jest.fn()} />);
|
||||||
|
expect(comp).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("upload file", async () => {
|
||||||
|
const onChange = jest.fn((value) => value);
|
||||||
|
const comp = mount(<JsonFileUpload id="upload" onChange={onChange} />);
|
||||||
|
|
||||||
|
const fileInput = comp.find('[type="file"]');
|
||||||
|
expect(fileInput.length).toBe(1);
|
||||||
|
|
||||||
|
const json = '{"bla": "test"}';
|
||||||
|
const file = new File([json], "test.json");
|
||||||
|
|
||||||
|
const dummyFileReader = {
|
||||||
|
onload: jest.fn(),
|
||||||
|
readAsText: () => Promise.resolve(json),
|
||||||
|
};
|
||||||
|
(window as any).FileReader = jest.fn(() => dummyFileReader);
|
||||||
|
|
||||||
|
fileInput.simulate("change", {
|
||||||
|
target: {
|
||||||
|
files: [file],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(comp).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
118
src/components/json-file-upload/JsonFileUpload.tsx
Normal file
118
src/components/json-file-upload/JsonFileUpload.tsx
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import {
|
||||||
|
FormGroup,
|
||||||
|
FileUpload,
|
||||||
|
Modal,
|
||||||
|
ModalVariant,
|
||||||
|
Button,
|
||||||
|
} from "@patternfly/react-core";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
type FileUpload = {
|
||||||
|
value: string | File;
|
||||||
|
filename: string;
|
||||||
|
isLoading: boolean;
|
||||||
|
modal: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type JsonFileUploadProps = {
|
||||||
|
id: string;
|
||||||
|
onChange: (
|
||||||
|
value: string | File,
|
||||||
|
filename: string,
|
||||||
|
event:
|
||||||
|
| React.DragEvent<HTMLElement> // User dragged/dropped a file
|
||||||
|
| React.ChangeEvent<HTMLTextAreaElement> // User typed in the TextArea
|
||||||
|
| React.MouseEvent<HTMLButtonElement, MouseEvent> // User clicked Clear button
|
||||||
|
) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const JsonFileUpload = ({
|
||||||
|
id,
|
||||||
|
onChange,
|
||||||
|
...rest
|
||||||
|
}: JsonFileUploadProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const defaultUpload = {
|
||||||
|
value: "",
|
||||||
|
filename: "",
|
||||||
|
isLoading: false,
|
||||||
|
modal: false,
|
||||||
|
};
|
||||||
|
const [fileUpload, setFileUpload] = useState<FileUpload>(defaultUpload);
|
||||||
|
const removeDialog = () => setFileUpload({ ...fileUpload, modal: false });
|
||||||
|
const handleChange = (
|
||||||
|
value: string | File,
|
||||||
|
filename: string,
|
||||||
|
event:
|
||||||
|
| React.DragEvent<HTMLElement>
|
||||||
|
| React.ChangeEvent<HTMLTextAreaElement>
|
||||||
|
| React.MouseEvent<HTMLButtonElement, MouseEvent>
|
||||||
|
): void => {
|
||||||
|
if (event.nativeEvent instanceof MouseEvent) {
|
||||||
|
setFileUpload({ ...fileUpload, modal: true });
|
||||||
|
} else {
|
||||||
|
setFileUpload({
|
||||||
|
...fileUpload,
|
||||||
|
value,
|
||||||
|
filename,
|
||||||
|
});
|
||||||
|
onChange(value, filename, event);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{fileUpload.modal && (
|
||||||
|
<Modal
|
||||||
|
variant={ModalVariant.small}
|
||||||
|
title={t("Clear this file")}
|
||||||
|
isOpen
|
||||||
|
onClose={removeDialog}
|
||||||
|
actions={[
|
||||||
|
<Button
|
||||||
|
key="confirm"
|
||||||
|
variant="primary"
|
||||||
|
onClick={(event) => {
|
||||||
|
setFileUpload(defaultUpload);
|
||||||
|
onChange("", "", event);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("Clear")}
|
||||||
|
</Button>,
|
||||||
|
<Button key="cancel" variant="link" onClick={removeDialog}>
|
||||||
|
{t("Cancel")}
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{t("confirmImportClear")}
|
||||||
|
</Modal>
|
||||||
|
)}
|
||||||
|
<FormGroup
|
||||||
|
label={t("Resource file")}
|
||||||
|
fieldId={id}
|
||||||
|
helperText="Upload a JSON file"
|
||||||
|
>
|
||||||
|
<FileUpload
|
||||||
|
id={id}
|
||||||
|
{...rest}
|
||||||
|
type="text"
|
||||||
|
value={fileUpload.value}
|
||||||
|
filename={fileUpload.filename}
|
||||||
|
onChange={handleChange}
|
||||||
|
allowEditingUploadedText
|
||||||
|
onReadStarted={() =>
|
||||||
|
setFileUpload({ ...fileUpload, isLoading: true })
|
||||||
|
}
|
||||||
|
onReadFinished={() =>
|
||||||
|
setFileUpload({ ...fileUpload, isLoading: false })
|
||||||
|
}
|
||||||
|
isLoading={fileUpload.isLoading}
|
||||||
|
dropzoneProps={{
|
||||||
|
accept: ".json",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</FormGroup>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,504 @@
|
||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`<JsonFileUpload /> render 1`] = `
|
||||||
|
<JsonFileUpload
|
||||||
|
id="test"
|
||||||
|
onChange={[MockFunction]}
|
||||||
|
>
|
||||||
|
<FormGroup
|
||||||
|
fieldId="test"
|
||||||
|
helperText="Upload a JSON file"
|
||||||
|
label="Resource file"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="pf-c-form__group"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="pf-c-form__group-label"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="pf-c-form__label"
|
||||||
|
htmlFor="test"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="pf-c-form__label-text"
|
||||||
|
>
|
||||||
|
Resource file
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="pf-c-form__group-control"
|
||||||
|
>
|
||||||
|
<FileUpload
|
||||||
|
allowEditingUploadedText={true}
|
||||||
|
dropzoneProps={
|
||||||
|
Object {
|
||||||
|
"accept": ".json",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filename=""
|
||||||
|
id="test"
|
||||||
|
isLoading={false}
|
||||||
|
onChange={[Function]}
|
||||||
|
onReadFinished={[Function]}
|
||||||
|
onReadStarted={[Function]}
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<t
|
||||||
|
accept=".json"
|
||||||
|
disabled={false}
|
||||||
|
getDataTransferItems={[Function]}
|
||||||
|
maxSize={Infinity}
|
||||||
|
minSize={0}
|
||||||
|
multiple={false}
|
||||||
|
onDropAccepted={[Function]}
|
||||||
|
onDropRejected={[Function]}
|
||||||
|
preventDropOnDocument={true}
|
||||||
|
>
|
||||||
|
<FileUploadField
|
||||||
|
allowEditingUploadedText={true}
|
||||||
|
containerRef={[Function]}
|
||||||
|
filename=""
|
||||||
|
id="test"
|
||||||
|
isLoading={false}
|
||||||
|
onBlur={[Function]}
|
||||||
|
onBrowseButtonClick={[Function]}
|
||||||
|
onChange={[Function]}
|
||||||
|
onClearButtonClick={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
onDragEnter={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onDragOver={[Function]}
|
||||||
|
onDragStart={[Function]}
|
||||||
|
onDrop={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
tabIndex={null}
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="pf-c-file-upload"
|
||||||
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
onDragEnter={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onDragOver={[Function]}
|
||||||
|
onDragStart={[Function]}
|
||||||
|
onDrop={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
tabIndex={null}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="pf-c-file-upload__file-select"
|
||||||
|
>
|
||||||
|
<InputGroup>
|
||||||
|
<div
|
||||||
|
className="pf-c-input-group"
|
||||||
|
>
|
||||||
|
<ForwardRef
|
||||||
|
aria-describedby="test-browse-button"
|
||||||
|
aria-label="Drag a file here or browse to upload"
|
||||||
|
id="test-filename"
|
||||||
|
isDisabled={false}
|
||||||
|
isReadOnly={true}
|
||||||
|
key=".0"
|
||||||
|
name="test-filename"
|
||||||
|
placeholder="Drag a file here or browse to upload"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<TextInputBase
|
||||||
|
aria-describedby="test-browse-button"
|
||||||
|
aria-label="Drag a file here or browse to upload"
|
||||||
|
className=""
|
||||||
|
id="test-filename"
|
||||||
|
innerRef={null}
|
||||||
|
isDisabled={false}
|
||||||
|
isReadOnly={true}
|
||||||
|
isRequired={false}
|
||||||
|
name="test-filename"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="Drag a file here or browse to upload"
|
||||||
|
type="text"
|
||||||
|
validated="default"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-describedby="test-browse-button"
|
||||||
|
aria-invalid={false}
|
||||||
|
aria-label="Drag a file here or browse to upload"
|
||||||
|
className="pf-c-form-control"
|
||||||
|
disabled={false}
|
||||||
|
id="test-filename"
|
||||||
|
name="test-filename"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="Drag a file here or browse to upload"
|
||||||
|
readOnly={true}
|
||||||
|
required={false}
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</TextInputBase>
|
||||||
|
</ForwardRef>
|
||||||
|
<Button
|
||||||
|
id="test-browse-button"
|
||||||
|
isDisabled={false}
|
||||||
|
key=".1"
|
||||||
|
onClick={[Function]}
|
||||||
|
variant="control"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
aria-disabled={false}
|
||||||
|
aria-label={null}
|
||||||
|
className="pf-c-button pf-m-control"
|
||||||
|
data-ouia-component-id={0}
|
||||||
|
data-ouia-component-type="PF4/Button"
|
||||||
|
data-ouia-safe={true}
|
||||||
|
disabled={false}
|
||||||
|
id="test-browse-button"
|
||||||
|
onClick={[Function]}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Browse...
|
||||||
|
</button>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
isDisabled={true}
|
||||||
|
key=".2"
|
||||||
|
onClick={[Function]}
|
||||||
|
variant="control"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
aria-disabled={true}
|
||||||
|
aria-label={null}
|
||||||
|
className="pf-c-button pf-m-control pf-m-disabled"
|
||||||
|
data-ouia-component-id={1}
|
||||||
|
data-ouia-component-type="PF4/Button"
|
||||||
|
data-ouia-safe={true}
|
||||||
|
disabled={true}
|
||||||
|
onClick={[Function]}
|
||||||
|
tabIndex={null}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</InputGroup>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="pf-c-file-upload__file-details"
|
||||||
|
>
|
||||||
|
<TextArea
|
||||||
|
aria-label="File upload"
|
||||||
|
className=""
|
||||||
|
disabled={false}
|
||||||
|
id="test"
|
||||||
|
isRequired={false}
|
||||||
|
name="test"
|
||||||
|
onChange={[Function]}
|
||||||
|
readOnly={false}
|
||||||
|
resizeOrientation="vertical"
|
||||||
|
validated="default"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
aria-invalid={false}
|
||||||
|
aria-label="File upload"
|
||||||
|
className="pf-c-form-control pf-m-resize-vertical"
|
||||||
|
disabled={false}
|
||||||
|
id="test"
|
||||||
|
name="test"
|
||||||
|
onChange={[Function]}
|
||||||
|
readOnly={false}
|
||||||
|
required={false}
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</TextArea>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
accept=".json"
|
||||||
|
autoComplete="off"
|
||||||
|
multiple={false}
|
||||||
|
onChange={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"display": "none",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabIndex={-1}
|
||||||
|
type="file"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FileUploadField>
|
||||||
|
</t>
|
||||||
|
</FileUpload>
|
||||||
|
<div
|
||||||
|
aria-live="polite"
|
||||||
|
className="pf-c-form__helper-text"
|
||||||
|
id="test-helper"
|
||||||
|
>
|
||||||
|
Upload a JSON file
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FormGroup>
|
||||||
|
</JsonFileUpload>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`<JsonFileUpload /> upload file 1`] = `
|
||||||
|
<JsonFileUpload
|
||||||
|
id="upload"
|
||||||
|
onChange={[MockFunction]}
|
||||||
|
>
|
||||||
|
<FormGroup
|
||||||
|
fieldId="upload"
|
||||||
|
helperText="Upload a JSON file"
|
||||||
|
label="Resource file"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="pf-c-form__group"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="pf-c-form__group-label"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
className="pf-c-form__label"
|
||||||
|
htmlFor="upload"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="pf-c-form__label-text"
|
||||||
|
>
|
||||||
|
Resource file
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="pf-c-form__group-control"
|
||||||
|
>
|
||||||
|
<FileUpload
|
||||||
|
allowEditingUploadedText={true}
|
||||||
|
dropzoneProps={
|
||||||
|
Object {
|
||||||
|
"accept": ".json",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filename=""
|
||||||
|
id="upload"
|
||||||
|
isLoading={false}
|
||||||
|
onChange={[Function]}
|
||||||
|
onReadFinished={[Function]}
|
||||||
|
onReadStarted={[Function]}
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<t
|
||||||
|
accept=".json"
|
||||||
|
disabled={false}
|
||||||
|
getDataTransferItems={[Function]}
|
||||||
|
maxSize={Infinity}
|
||||||
|
minSize={0}
|
||||||
|
multiple={false}
|
||||||
|
onDropAccepted={[Function]}
|
||||||
|
onDropRejected={[Function]}
|
||||||
|
preventDropOnDocument={true}
|
||||||
|
>
|
||||||
|
<FileUploadField
|
||||||
|
allowEditingUploadedText={true}
|
||||||
|
containerRef={[Function]}
|
||||||
|
filename=""
|
||||||
|
id="upload"
|
||||||
|
isDragActive={false}
|
||||||
|
isLoading={false}
|
||||||
|
onBlur={[Function]}
|
||||||
|
onBrowseButtonClick={[Function]}
|
||||||
|
onChange={[Function]}
|
||||||
|
onClearButtonClick={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
onDragEnter={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onDragOver={[Function]}
|
||||||
|
onDragStart={[Function]}
|
||||||
|
onDrop={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
tabIndex={null}
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="pf-c-file-upload"
|
||||||
|
onBlur={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
onDragEnter={[Function]}
|
||||||
|
onDragLeave={[Function]}
|
||||||
|
onDragOver={[Function]}
|
||||||
|
onDragStart={[Function]}
|
||||||
|
onDrop={[Function]}
|
||||||
|
onFocus={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
tabIndex={null}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="pf-c-file-upload__file-select"
|
||||||
|
>
|
||||||
|
<InputGroup>
|
||||||
|
<div
|
||||||
|
className="pf-c-input-group"
|
||||||
|
>
|
||||||
|
<ForwardRef
|
||||||
|
aria-describedby="upload-browse-button"
|
||||||
|
aria-label="Drag a file here or browse to upload"
|
||||||
|
id="upload-filename"
|
||||||
|
isDisabled={false}
|
||||||
|
isReadOnly={true}
|
||||||
|
key=".0"
|
||||||
|
name="upload-filename"
|
||||||
|
placeholder="Drag a file here or browse to upload"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<TextInputBase
|
||||||
|
aria-describedby="upload-browse-button"
|
||||||
|
aria-label="Drag a file here or browse to upload"
|
||||||
|
className=""
|
||||||
|
id="upload-filename"
|
||||||
|
innerRef={null}
|
||||||
|
isDisabled={false}
|
||||||
|
isReadOnly={true}
|
||||||
|
isRequired={false}
|
||||||
|
name="upload-filename"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="Drag a file here or browse to upload"
|
||||||
|
type="text"
|
||||||
|
validated="default"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
aria-describedby="upload-browse-button"
|
||||||
|
aria-invalid={false}
|
||||||
|
aria-label="Drag a file here or browse to upload"
|
||||||
|
className="pf-c-form-control"
|
||||||
|
disabled={false}
|
||||||
|
id="upload-filename"
|
||||||
|
name="upload-filename"
|
||||||
|
onChange={[Function]}
|
||||||
|
placeholder="Drag a file here or browse to upload"
|
||||||
|
readOnly={true}
|
||||||
|
required={false}
|
||||||
|
type="text"
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</TextInputBase>
|
||||||
|
</ForwardRef>
|
||||||
|
<Button
|
||||||
|
id="upload-browse-button"
|
||||||
|
isDisabled={false}
|
||||||
|
key=".1"
|
||||||
|
onClick={[Function]}
|
||||||
|
variant="control"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
aria-disabled={false}
|
||||||
|
aria-label={null}
|
||||||
|
className="pf-c-button pf-m-control"
|
||||||
|
data-ouia-component-id={4}
|
||||||
|
data-ouia-component-type="PF4/Button"
|
||||||
|
data-ouia-safe={true}
|
||||||
|
disabled={false}
|
||||||
|
id="upload-browse-button"
|
||||||
|
onClick={[Function]}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Browse...
|
||||||
|
</button>
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
isDisabled={true}
|
||||||
|
key=".2"
|
||||||
|
onClick={[Function]}
|
||||||
|
variant="control"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
aria-disabled={true}
|
||||||
|
aria-label={null}
|
||||||
|
className="pf-c-button pf-m-control pf-m-disabled"
|
||||||
|
data-ouia-component-id={5}
|
||||||
|
data-ouia-component-type="PF4/Button"
|
||||||
|
data-ouia-safe={true}
|
||||||
|
disabled={true}
|
||||||
|
onClick={[Function]}
|
||||||
|
tabIndex={null}
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</InputGroup>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="pf-c-file-upload__file-details"
|
||||||
|
>
|
||||||
|
<TextArea
|
||||||
|
aria-label="File upload"
|
||||||
|
className=""
|
||||||
|
disabled={false}
|
||||||
|
id="upload"
|
||||||
|
isRequired={false}
|
||||||
|
name="upload"
|
||||||
|
onChange={[Function]}
|
||||||
|
readOnly={false}
|
||||||
|
resizeOrientation="vertical"
|
||||||
|
validated="default"
|
||||||
|
value=""
|
||||||
|
>
|
||||||
|
<textarea
|
||||||
|
aria-invalid={false}
|
||||||
|
aria-label="File upload"
|
||||||
|
className="pf-c-form-control pf-m-resize-vertical"
|
||||||
|
disabled={false}
|
||||||
|
id="upload"
|
||||||
|
name="upload"
|
||||||
|
onChange={[Function]}
|
||||||
|
readOnly={false}
|
||||||
|
required={false}
|
||||||
|
value=""
|
||||||
|
/>
|
||||||
|
</TextArea>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
accept=".json"
|
||||||
|
autoComplete="off"
|
||||||
|
multiple={false}
|
||||||
|
onChange={[Function]}
|
||||||
|
onClick={[Function]}
|
||||||
|
style={
|
||||||
|
Object {
|
||||||
|
"display": "none",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tabIndex={-1}
|
||||||
|
type="file"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FileUploadField>
|
||||||
|
</t>
|
||||||
|
</FileUpload>
|
||||||
|
<div
|
||||||
|
aria-live="polite"
|
||||||
|
className="pf-c-form__helper-text"
|
||||||
|
id="upload-helper"
|
||||||
|
>
|
||||||
|
Upload a JSON file
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FormGroup>
|
||||||
|
</JsonFileUpload>
|
||||||
|
`;
|
|
@ -6,41 +6,25 @@ import {
|
||||||
Divider,
|
Divider,
|
||||||
Form,
|
Form,
|
||||||
FormGroup,
|
FormGroup,
|
||||||
FileUpload,
|
|
||||||
TextInput,
|
TextInput,
|
||||||
ActionGroup,
|
ActionGroup,
|
||||||
Button,
|
Button,
|
||||||
AlertVariant,
|
AlertVariant,
|
||||||
Modal,
|
|
||||||
ModalVariant,
|
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
import { ClientRepresentation } from "../../model/client-model";
|
import { ClientRepresentation } from "../../model/client-model";
|
||||||
import { ClientDescription } from "./ClientDescription";
|
import { ClientDescription } from "./ClientDescription";
|
||||||
import { HttpClientContext } from "../../http-service/HttpClientContext";
|
import { HttpClientContext } from "../../http-service/HttpClientContext";
|
||||||
|
import { JsonFileUpload } from "../../components/json-file-upload/JsonFileUpload";
|
||||||
import { useAlerts } from "../../components/alert/Alerts";
|
import { useAlerts } from "../../components/alert/Alerts";
|
||||||
import { AlertPanel } from "../../components/alert/AlertPanel";
|
import { AlertPanel } from "../../components/alert/AlertPanel";
|
||||||
|
|
||||||
type FileUpload = {
|
|
||||||
value: string | File;
|
|
||||||
filename: string;
|
|
||||||
isLoading: boolean;
|
|
||||||
modal: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ImportForm = () => {
|
export const ImportForm = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const httpClient = useContext(HttpClientContext)!;
|
const httpClient = useContext(HttpClientContext)!;
|
||||||
|
|
||||||
const [add, alerts, hide] = useAlerts();
|
const [add, alerts, hide] = useAlerts();
|
||||||
const defaultUpload = {
|
|
||||||
value: "",
|
|
||||||
filename: "",
|
|
||||||
isLoading: false,
|
|
||||||
modal: false,
|
|
||||||
};
|
|
||||||
const [fileUpload, setFileUpload] = useState<FileUpload>(defaultUpload);
|
|
||||||
const defaultClient = {
|
const defaultClient = {
|
||||||
protocol: "",
|
protocol: "",
|
||||||
clientId: "",
|
clientId: "",
|
||||||
|
@ -49,21 +33,11 @@ export const ImportForm = () => {
|
||||||
};
|
};
|
||||||
const [client, setClient] = useState<ClientRepresentation>(defaultClient);
|
const [client, setClient] = useState<ClientRepresentation>(defaultClient);
|
||||||
|
|
||||||
const handleFileChange = (value: string | File, filename: string) => {
|
const handleFileChange = (value: string | File) => {
|
||||||
if (value === "" && client.protocol !== "") {
|
setClient({
|
||||||
// clear clicked
|
...client,
|
||||||
setFileUpload({ ...fileUpload, modal: true });
|
...(value ? JSON.parse(value as string) : defaultClient),
|
||||||
} else {
|
});
|
||||||
setFileUpload({
|
|
||||||
...fileUpload,
|
|
||||||
value,
|
|
||||||
filename,
|
|
||||||
});
|
|
||||||
setClient({
|
|
||||||
...client,
|
|
||||||
...(value ? JSON.parse(value as string) : defaultClient),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const handleDescriptionChange = (
|
const handleDescriptionChange = (
|
||||||
value: string,
|
value: string,
|
||||||
|
@ -72,7 +46,6 @@ export const ImportForm = () => {
|
||||||
const name = (event.target as HTMLInputElement).name;
|
const name = (event.target as HTMLInputElement).name;
|
||||||
setClient({ ...client, [name]: value });
|
setClient({ ...client, [name]: value });
|
||||||
};
|
};
|
||||||
const removeDialog = () => setFileUpload({ ...fileUpload, modal: false });
|
|
||||||
|
|
||||||
const save = async () => {
|
const save = async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -95,56 +68,8 @@ export const ImportForm = () => {
|
||||||
</PageSection>
|
</PageSection>
|
||||||
<Divider />
|
<Divider />
|
||||||
<PageSection variant="light">
|
<PageSection variant="light">
|
||||||
{fileUpload.modal && (
|
|
||||||
<Modal
|
|
||||||
variant={ModalVariant.small}
|
|
||||||
title={t("Clear this file")}
|
|
||||||
isOpen
|
|
||||||
onClose={removeDialog}
|
|
||||||
actions={[
|
|
||||||
<Button
|
|
||||||
key="confirm"
|
|
||||||
variant="primary"
|
|
||||||
onClick={() => {
|
|
||||||
setClient(defaultClient);
|
|
||||||
setFileUpload(defaultUpload);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("Clear")}
|
|
||||||
</Button>,
|
|
||||||
<Button key="cancel" variant="link" onClick={removeDialog}>
|
|
||||||
{t("Cancel")}
|
|
||||||
</Button>,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
{t("confirmImportClear")}
|
|
||||||
</Modal>
|
|
||||||
)}
|
|
||||||
<Form isHorizontal>
|
<Form isHorizontal>
|
||||||
<FormGroup
|
<JsonFileUpload id="realm-file" onChange={handleFileChange} />
|
||||||
label={t("Resource file")}
|
|
||||||
fieldId="realm-file"
|
|
||||||
helperText="Upload a JSON file"
|
|
||||||
>
|
|
||||||
<FileUpload
|
|
||||||
id="realm-file"
|
|
||||||
type="text"
|
|
||||||
value={fileUpload.value}
|
|
||||||
filename={fileUpload.filename}
|
|
||||||
onChange={handleFileChange}
|
|
||||||
allowEditingUploadedText
|
|
||||||
onReadStarted={() =>
|
|
||||||
setFileUpload({ ...fileUpload, isLoading: true })
|
|
||||||
}
|
|
||||||
onReadFinished={() =>
|
|
||||||
setFileUpload({ ...fileUpload, isLoading: false })
|
|
||||||
}
|
|
||||||
isLoading={fileUpload.isLoading}
|
|
||||||
dropzoneProps={{
|
|
||||||
accept: ".json",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</FormGroup>
|
|
||||||
<ClientDescription
|
<ClientDescription
|
||||||
onChange={handleDescriptionChange}
|
onChange={handleDescriptionChange}
|
||||||
client={client}
|
client={client}
|
||||||
|
|
22
src/stories/JsonFileUpload.stories.tsx
Normal file
22
src/stories/JsonFileUpload.stories.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import React from "react";
|
||||||
|
import { Meta, Story } from "@storybook/react";
|
||||||
|
|
||||||
|
import {
|
||||||
|
JsonFileUpload,
|
||||||
|
JsonFileUploadProps,
|
||||||
|
} from "../components/json-file-upload/JsonFileUpload";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Json file upload dailog",
|
||||||
|
component: JsonFileUpload,
|
||||||
|
parameters: { actions: { argTypesRegex: "^on.*" } },
|
||||||
|
} as Meta;
|
||||||
|
|
||||||
|
const Template: Story<JsonFileUploadProps> = (args) => (
|
||||||
|
<JsonFileUpload {...args} />
|
||||||
|
);
|
||||||
|
|
||||||
|
export const Dialog = Template.bind({});
|
||||||
|
Dialog.args = {
|
||||||
|
id: "jsonFile",
|
||||||
|
};
|
Loading…
Reference in a new issue