aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/ui/imageUpload/index.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/ui/imageUpload/index.tsx')
-rw-r--r--src/components/ui/imageUpload/index.tsx167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/components/ui/imageUpload/index.tsx b/src/components/ui/imageUpload/index.tsx
new file mode 100644
index 000000000..7a2ca747f
--- /dev/null
+++ b/src/components/ui/imageUpload/index.tsx
@@ -0,0 +1,167 @@
1import { Component, InputHTMLAttributes } from 'react';
2import { observer } from 'mobx-react';
3import classnames from 'classnames';
4import Dropzone from 'react-dropzone';
5import { mdiDelete, mdiFileImage } from '@mdi/js';
6import prettyBytes from 'pretty-bytes';
7import { noop } from 'lodash';
8import { isWindows } from '../../../environment';
9import Icon from '../icon';
10import { IFormField } from '../typings/generic';
11
12interface IProps extends InputHTMLAttributes<HTMLInputElement>, IFormField {
13 className: string;
14 multiple: boolean;
15 textDelete: string;
16 textUpload: string;
17 textMaxFileSize: string;
18 textMaxFileSizeError: string;
19 maxSize?: number;
20 maxFiles?: number;
21 messages: any;
22 set?: (value: string) => void;
23}
24
25interface IState {
26 path: string | null;
27 errorState: boolean;
28 errorMessage: { message: string };
29}
30
31// TODO - drag and drop image for recipe add/edit not working from 6.2.0 need to look at it
32@observer
33class ImageUpload extends Component<IProps, IState> {
34 constructor(props: IProps) {
35 super(props);
36
37 this.state = {
38 path: null,
39 errorState: false,
40 errorMessage: {
41 message: '',
42 },
43 };
44 }
45
46 onDropAccepted(acceptedFiles): void {
47 const { onDrop = noop, set = noop } = this.props;
48 this.setState({ errorState: false });
49
50 for (const file of acceptedFiles) {
51 const imgPath: string = isWindows
52 ? file.path.replace(/\\/g, '/')
53 : file.path;
54 this.setState({ path: imgPath });
55 onDrop(file);
56 }
57
58 set('');
59 }
60
61 onDropRejected(rejectedFiles): void {
62 for (const file of rejectedFiles) {
63 for (const error of file.errors) {
64 if (error.code === 'file-too-large') {
65 this.setState({ errorState: true });
66 this.setState({
67 errorMessage: {
68 message: this.props.textMaxFileSizeError,
69 },
70 });
71 }
72 }
73 }
74 }
75
76 render() {
77 const {
78 className,
79 multiple = false,
80 textDelete,
81 textUpload,
82 textMaxFileSize,
83 value,
84 maxSize = Number.POSITIVE_INFINITY,
85 maxFiles = 0,
86 label = '',
87 set = noop,
88 } = this.props;
89
90 const cssClasses = classnames({
91 'image-upload__dropzone': true,
92 [`${className}`]: className,
93 });
94
95 const maxSizeParse: number =
96 maxSize === undefined || maxSize === Number.POSITIVE_INFINITY
97 ? 0
98 : maxSize;
99
100 return (
101 <div className="image-upload-wrapper">
102 <label className="franz-form__label" htmlFor="iconUpload">
103 {label}
104 </label>
105 <div className="image-upload">
106 {(value && value !== 'delete') || this.state.path ? (
107 <>
108 <div
109 className="image-upload__preview"
110 style={{
111 backgroundImage: `url("${this.state.path || value}")`,
112 }}
113 />
114 <div className="image-upload__action">
115 <button
116 type="button"
117 onClick={() => {
118 if (value) {
119 set('delete');
120 } else {
121 this.setState({ path: null });
122 }
123 }}
124 >
125 <Icon icon={mdiDelete} />
126 <p>{textDelete}</p>
127 </button>
128 <div className="image-upload__action-background" />
129 </div>
130 </>
131 ) : (
132 <Dropzone
133 onDropAccepted={this.onDropAccepted.bind(this)}
134 onDropRejected={this.onDropRejected.bind(this)}
135 multiple={multiple}
136 accept="image/jpeg, image/png, image/svg+xml"
137 minSize={0}
138 maxSize={maxSize}
139 maxFiles={maxFiles}
140 >
141 {({ getRootProps, getInputProps }) => (
142 <div {...getRootProps()} className={cssClasses}>
143 <Icon icon={mdiFileImage} />
144 <p>{textUpload}</p>
145 <input {...getInputProps()} />
146 </div>
147 )}
148 </Dropzone>
149 )}
150 </div>
151 {maxSizeParse !== 0 && (
152 <span className="image-upload-wrapper__file-size">
153 {textMaxFileSize}{' '}
154 {prettyBytes(maxSizeParse, { maximumFractionDigits: 1 })}
155 </span>
156 )}
157 {this.state.errorState && (
158 <span className="image-upload-wrapper__file-size-error">
159 {this.state.errorMessage.message}
160 </span>
161 )}
162 </div>
163 );
164 }
165}
166
167export default ImageUpload;