saq1b commited on
Commit
98f4009
·
1 Parent(s): 66210a8

add image upload functionality to Cloudinary and remove temporary URL management

Browse files
Files changed (2) hide show
  1. .gitignore +22 -0
  2. src/App.jsx +35 -39
.gitignore ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # dependencies
2
+ /node_modules
3
+ /.pnp
4
+ .pnp.js
5
+
6
+ # testing
7
+ /coverage
8
+
9
+ # production
10
+ /build
11
+
12
+ # misc
13
+ .DS_Store
14
+ .env
15
+ .env.local
16
+ .env.development.local
17
+ .env.test.local
18
+ .env.production.local
19
+
20
+ npm-debug.log*
21
+ yarn-debug.log*
22
+ yarn-error.log*
src/App.jsx CHANGED
@@ -25,6 +25,14 @@ import axios from 'axios';
25
  import JSZip from 'jszip';
26
  import { saveAs } from 'file-saver';
27
 
 
 
 
 
 
 
 
 
28
  // Function to get file extension
29
  const getFileExtension = filename => {
30
  return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
@@ -35,6 +43,29 @@ const getFilenameWithoutExtension = filename => {
35
  return filename.substring(0, filename.lastIndexOf("."));
36
  }
37
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  const App = () => {
39
  const [apiKey, setApiKey] = useState('');
40
  const [uploadedImages, setUploadedImages] = useState([]);
@@ -43,7 +74,6 @@ const App = () => {
43
  const [progress, setProgress] = useState(0);
44
  const fileInputRef = useRef(null);
45
  const toast = useToast();
46
- const temporaryUrlsRef = useRef([]);
47
 
48
  const handleFileChange = async (e) => {
49
  const files = Array.from(e.target.files);
@@ -90,10 +120,6 @@ const App = () => {
90
  setProcessing(true);
91
  const pendingImages = uploadedImages.filter(img => img.status === 'pending');
92
 
93
- // Clean up any previous temporary URLs
94
- temporaryUrlsRef.current.forEach(url => URL.revokeObjectURL(url));
95
- temporaryUrlsRef.current = [];
96
-
97
  for (let i = 0; i < pendingImages.length; i++) {
98
  const image = pendingImages[i];
99
 
@@ -105,13 +131,12 @@ const App = () => {
105
  ));
106
 
107
  try {
108
- // Create a URL for the image file
109
- const imageUrl = URL.createObjectURL(image.file);
110
- temporaryUrlsRef.current.push(imageUrl);
111
 
112
- // Call the GLIF API with the image URL
113
  const response = await axios.post('https://simple-api.glif.app/cm7yya7850000la0ckalxpix2', {
114
- image: imageUrl
115
  }, {
116
  headers: {
117
  'Authorization': `Bearer ${apiKey}`,
@@ -142,10 +167,6 @@ const App = () => {
142
  }
143
  }
144
 
145
- // Clean up temporary URLs after processing is done
146
- temporaryUrlsRef.current.forEach(url => URL.revokeObjectURL(url));
147
- temporaryUrlsRef.current = [];
148
-
149
  setProgress(100);
150
  setProcessing(false);
151
 
@@ -212,39 +233,14 @@ const App = () => {
212
  };
213
 
214
  const removeImage = (id) => {
215
- // Find the image to remove
216
- const imageToRemove = uploadedImages.find(img => img.id === id);
217
- if (imageToRemove && imageToRemove.preview) {
218
- // Revoke the object URL to prevent memory leaks
219
- URL.revokeObjectURL(imageToRemove.preview);
220
- }
221
-
222
  setUploadedImages(prev => prev.filter(img => img.id !== id));
223
  };
224
 
225
  const clearAll = () => {
226
- // Revoke all preview URLs to prevent memory leaks
227
- uploadedImages.forEach(img => {
228
- if (img.preview) URL.revokeObjectURL(img.preview);
229
- });
230
-
231
  setUploadedImages([]);
232
  if (fileInputRef.current) fileInputRef.current.value = '';
233
  };
234
 
235
- // Clean up URLs when component unmounts
236
- React.useEffect(() => {
237
- return () => {
238
- // Clean up all preview URLs
239
- uploadedImages.forEach(img => {
240
- if (img.preview) URL.revokeObjectURL(img.preview);
241
- });
242
-
243
- // Clean up temporary URLs
244
- temporaryUrlsRef.current.forEach(url => URL.revokeObjectURL(url));
245
- };
246
- }, []);
247
-
248
  const getStatusBadge = (status) => {
249
  switch (status) {
250
  case 'pending':
 
25
  import JSZip from 'jszip';
26
  import { saveAs } from 'file-saver';
27
 
28
+ // Function to convert file to base64
29
+ const toBase64 = file => new Promise((resolve, reject) => {
30
+ const reader = new FileReader();
31
+ reader.readAsDataURL(file);
32
+ reader.onload = () => resolve(reader.result.split(',')[1]);
33
+ reader.onerror = error => reject(error);
34
+ });
35
+
36
  // Function to get file extension
37
  const getFileExtension = filename => {
38
  return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
 
43
  return filename.substring(0, filename.lastIndexOf("."));
44
  }
45
 
46
+ // Function to upload image to Cloudinary
47
+ const uploadToCloudinary = async (file) => {
48
+ const formData = new FormData();
49
+ formData.append('file', file);
50
+ formData.append('upload_preset', process.env.REACT_APP_CLOUDINARY_UPLOAD_PRESET);
51
+
52
+ try {
53
+ const response = await axios.post(
54
+ process.env.REACT_APP_CLOUDINARY_UPLOAD_URL,
55
+ formData
56
+ );
57
+
58
+ if (response.status === 200) {
59
+ return response.data.secure_url;
60
+ } else {
61
+ throw new Error('Failed to upload to Cloudinary');
62
+ }
63
+ } catch (error) {
64
+ console.error('Error uploading to Cloudinary:', error);
65
+ throw error;
66
+ }
67
+ };
68
+
69
  const App = () => {
70
  const [apiKey, setApiKey] = useState('');
71
  const [uploadedImages, setUploadedImages] = useState([]);
 
74
  const [progress, setProgress] = useState(0);
75
  const fileInputRef = useRef(null);
76
  const toast = useToast();
 
77
 
78
  const handleFileChange = async (e) => {
79
  const files = Array.from(e.target.files);
 
120
  setProcessing(true);
121
  const pendingImages = uploadedImages.filter(img => img.status === 'pending');
122
 
 
 
 
 
123
  for (let i = 0; i < pendingImages.length; i++) {
124
  const image = pendingImages[i];
125
 
 
131
  ));
132
 
133
  try {
134
+ // First upload image to Cloudinary
135
+ const cloudinaryUrl = await uploadToCloudinary(image.file);
 
136
 
137
+ // Call the GLIF API with the Cloudinary URL
138
  const response = await axios.post('https://simple-api.glif.app/cm7yya7850000la0ckalxpix2', {
139
+ image: cloudinaryUrl
140
  }, {
141
  headers: {
142
  'Authorization': `Bearer ${apiKey}`,
 
167
  }
168
  }
169
 
 
 
 
 
170
  setProgress(100);
171
  setProcessing(false);
172
 
 
233
  };
234
 
235
  const removeImage = (id) => {
 
 
 
 
 
 
 
236
  setUploadedImages(prev => prev.filter(img => img.id !== id));
237
  };
238
 
239
  const clearAll = () => {
 
 
 
 
 
240
  setUploadedImages([]);
241
  if (fileInputRef.current) fileInputRef.current.value = '';
242
  };
243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  const getStatusBadge = (status) => {
245
  switch (status) {
246
  case 'pending':