Vishwas1 commited on
Commit
02273e7
Β·
verified Β·
1 Parent(s): a834015

Fix: Deploy simplified working version that resolves JSON schema errors

Browse files
Files changed (1) hide show
  1. app.py +203 -351
app.py CHANGED
@@ -1,386 +1,238 @@
1
  import gradio as gr
2
  import pandas as pd
3
- import numpy as np
4
  from simple_salesforce import Salesforce
5
  import io
6
- import traceback
7
  from datetime import datetime
8
- import os
9
  import logging
10
 
11
  # Set up logging
12
  logging.basicConfig(level=logging.INFO)
13
  logger = logging.getLogger(__name__)
14
 
15
- class SalesforceDataLoader:
16
- def __init__(self):
17
- self.sf = None
18
- self.connected = False
19
- self.available_objects = []
20
-
21
- def connect_to_salesforce(self, username, password, security_token, sandbox=False):
22
- """Connect to Salesforce using credentials"""
23
- try:
24
- domain = 'test' if sandbox else None
25
- self.sf = Salesforce(
26
- username=username,
27
- password=password,
28
- security_token=security_token,
29
- domain=domain
30
- )
31
- self.connected = True
32
-
33
- # Get available objects
34
- self._get_available_objects()
35
-
36
- return f"βœ… Successfully connected to Salesforce as {username}", gr.update(visible=True), gr.update(choices=self.available_objects, value=None)
37
-
38
- except Exception as e:
39
- error_msg = str(e)
40
- logger.error(f"Connection failed: {error_msg}")
41
- self.connected = False
42
-
43
- # Provide more helpful error messages
44
- if "INVALID_LOGIN" in error_msg:
45
- return f"❌ Invalid credentials. Please check your username, password, and security token.", gr.update(visible=False), gr.update(choices=[], value=None)
46
- elif "API_DISABLED_FOR_ORG" in error_msg:
47
- return f"❌ API access is disabled for your organization. Please contact your Salesforce admin.", gr.update(visible=False), gr.update(choices=[], value=None)
48
- elif "LOGIN_MUST_USE_SECURITY_TOKEN" in error_msg:
49
- return f"❌ Security token required. Please append your security token to your password.", gr.update(visible=False), gr.update(choices=[], value=None)
50
- else:
51
- return f"❌ Connection failed: {error_msg}", gr.update(visible=False), gr.update(choices=[], value=None)
52
-
53
- def _get_available_objects(self):
54
- """Get list of available Salesforce objects"""
55
- try:
56
- # Get commonly used objects
57
- common_objects = ['Account', 'Contact', 'Lead', 'Opportunity', 'Case', 'Campaign', 'User', 'Product2']
58
- self.available_objects = []
59
-
60
- for obj_name in common_objects:
61
- try:
62
- # Test if object exists and is accessible
63
- obj = getattr(self.sf, obj_name)
64
- obj.describe()
65
- self.available_objects.append(obj_name)
66
- except Exception as e:
67
- logger.debug(f"Object {obj_name} not accessible: {str(e)}")
68
- continue
69
-
70
- except Exception as e:
71
- logger.error(f"Error getting objects: {str(e)}")
72
- self.available_objects = ['Account', 'Contact', 'Lead'] # Fallback
73
-
74
- def get_object_fields(self, object_name):
75
- """Get fields for selected Salesforce object"""
76
- if not self.connected or not object_name:
77
- return gr.update(choices=[], value=None), ""
78
-
79
- try:
80
- obj = getattr(self.sf, object_name)
81
- metadata = obj.describe()
82
-
83
- fields = []
84
- field_info = []
85
-
86
- for field in metadata['fields']:
87
- if field['createable'] or field['updateable']:
88
- field_name = field['name']
89
- field_type = field['type']
90
- required = "Required" if not field['nillable'] and not field['defaultedOnCreate'] else "Optional"
91
-
92
- fields.append(field_name)
93
- field_info.append(f"**{field_name}** ({field_type}) - {required}")
94
-
95
- field_info_text = "\n".join(field_info[:20]) # Show first 20 fields
96
- if len(field_info) > 20:
97
- field_info_text += f"\n... and {len(field_info) - 20} more fields"
98
-
99
- return gr.update(choices=fields, value=None), field_info_text
100
-
101
- except Exception as e:
102
- logger.error(f"Error getting fields: {str(e)}")
103
- return gr.update(choices=[], value=None), f"Error: {str(e)}"
104
-
105
- def upload_data_to_salesforce(self, file, object_name, operation, external_id_field=None):
106
- """Upload data to Salesforce"""
107
- if not self.connected:
108
- return "❌ Please connect to Salesforce first", None
109
-
110
- if not file or not object_name:
111
- return "❌ Please select a file and object", None
112
-
113
- try:
114
- # Read the uploaded file
115
- if file.name.endswith('.csv'):
116
- df = pd.read_csv(file.name)
117
- elif file.name.endswith(('.xlsx', '.xls')):
118
- df = pd.read_excel(file.name)
119
- else:
120
- return "❌ Please upload a CSV or Excel file", None
121
-
122
- if df.empty:
123
- return "❌ The uploaded file is empty", None
124
-
125
- # Get Salesforce object
126
- sf_object = getattr(self.sf, object_name)
127
-
128
- # Prepare data for upload
129
- records = df.to_dict('records')
130
-
131
- # Clean data - remove NaN values
132
- for record in records:
133
- record = {k: v for k, v in record.items() if pd.notna(v)}
134
-
135
- results = []
136
- errors = []
137
-
138
- # Perform bulk operation
139
- if operation == "Insert":
140
- try:
141
- result = sf_object.bulk.insert(records)
142
- results = result
143
- except Exception as e:
144
- return f"❌ Bulk insert failed: {str(e)}", None
145
-
146
- elif operation == "Update":
147
- try:
148
- result = sf_object.bulk.update(records)
149
- results = result
150
- except Exception as e:
151
- return f"❌ Bulk update failed: {str(e)}", None
152
-
153
- elif operation == "Upsert":
154
- if not external_id_field:
155
- return "❌ External ID field is required for upsert operation", None
156
- try:
157
- result = sf_object.bulk.upsert(records, external_id_field)
158
- results = result
159
- except Exception as e:
160
- return f"❌ Bulk upsert failed: {str(e)}", None
161
-
162
- # Process results
163
- success_count = 0
164
- error_count = 0
165
-
166
- for result in results:
167
- if result.get('success'):
168
- success_count += 1
169
- else:
170
- error_count += 1
171
- errors.append(result.get('errors', []))
172
-
173
- # Create results summary
174
- summary = f"βœ… Operation completed!\n"
175
- summary += f"πŸ“Š Total records: {len(records)}\n"
176
- summary += f"βœ… Successful: {success_count}\n"
177
- summary += f"❌ Failed: {error_count}\n"
178
-
179
- if errors:
180
- summary += f"\n**First few errors:**\n"
181
- for i, error in enumerate(errors[:5]):
182
- summary += f"{i+1}. {error}\n"
183
-
184
- # Create downloadable results file
185
- results_df = pd.DataFrame(results)
186
- results_csv = results_df.to_csv(index=False)
187
- results_file = f"salesforce_upload_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
188
-
189
- with open(results_file, 'w') as f:
190
- f.write(results_csv)
191
-
192
- return summary, results_file
193
-
194
- except Exception as e:
195
- logger.error(f"Upload error: {str(e)}")
196
- logger.error(traceback.format_exc())
197
- return f"❌ Error: {str(e)}", None
198
 
199
- def export_data_from_salesforce(self, object_name, fields, record_limit=1000):
200
- """Export data from Salesforce"""
201
- if not self.connected:
202
- return "❌ Please connect to Salesforce first", None
203
-
204
- if not object_name:
205
- return "❌ Please select an object", None
206
-
207
- try:
208
- # Build SOQL query
209
- if not fields:
210
- # Get some default fields
211
- obj = getattr(self.sf, object_name)
212
- metadata = obj.describe()
213
- fields = [field['name'] for field in metadata['fields'][:10]] # First 10 fields
214
-
215
- fields_str = ', '.join(fields)
216
- query = f"SELECT {fields_str} FROM {object_name} LIMIT {record_limit}"
217
-
218
- # Execute query
219
- result = self.sf.query_all(query)
220
- records = result['records']
221
-
222
- if not records:
223
- return "❌ No records found", None
224
-
225
- # Convert to DataFrame
226
- df = pd.DataFrame(records)
227
-
228
- # Remove Salesforce metadata columns
229
- if 'attributes' in df.columns:
230
- df = df.drop('attributes', axis=1)
231
-
232
- # Create downloadable file
233
- export_file = f"salesforce_export_{object_name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
234
- df.to_csv(export_file, index=False)
235
-
236
- summary = f"βœ… Export completed!\n"
237
- summary += f"πŸ“Š Records exported: {len(records)}\n"
238
- summary += f"πŸ“‹ Fields: {', '.join(fields)}\n"
239
- summary += f"πŸ“ File: {export_file}"
240
-
241
- return summary, export_file
242
-
243
- except Exception as e:
244
- logger.error(f"Export error: {str(e)}")
245
- return f"❌ Error: {str(e)}", None
246
 
247
- # Initialize the Salesforce Data Loader
248
- sf_loader = SalesforceDataLoader()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
249
 
250
- # Create the Gradio interface
251
- def create_interface():
252
- with gr.Blocks(title="Salesforce Data Loader", theme=gr.themes.Soft()) as interface:
253
- gr.Markdown("""
254
- # πŸš€ Salesforce Data Loader
 
255
 
256
- A powerful tool to upload and download data from Salesforce. Connect with your credentials and start managing your data!
257
- """)
258
 
259
- with gr.Tab("πŸ” Connection"):
260
- gr.Markdown("### Connect to Salesforce")
261
- with gr.Row():
262
- with gr.Column():
263
- username = gr.Textbox(label="Username", placeholder="[email protected]")
264
- password = gr.Textbox(label="Password", type="password")
265
- security_token = gr.Textbox(label="Security Token", type="password",
266
- info="Get this from Salesforce Setup β†’ Personal Information β†’ Reset Security Token")
267
- with gr.Column():
268
- sandbox = gr.Checkbox(label="Sandbox Environment", info="Check if connecting to a sandbox")
269
- connect_btn = gr.Button("πŸ”— Connect to Salesforce", variant="primary")
270
-
271
- connection_status = gr.Markdown("")
272
-
273
- with gr.Tab("πŸ“€ Upload Data", visible=False) as upload_tab:
274
- gr.Markdown("### Upload CSV/Excel data to Salesforce")
275
-
276
- with gr.Row():
277
- with gr.Column():
278
- file_upload = gr.File(label="Upload CSV or Excel file", file_types=[".csv", ".xlsx", ".xls"])
279
- object_dropdown = gr.Dropdown(label="Select Salesforce Object", choices=[])
280
- operation_dropdown = gr.Dropdown(
281
- label="Operation Type",
282
- choices=["Insert", "Update", "Upsert"],
283
- value="Insert"
284
- )
285
- external_id_field = gr.Dropdown(label="External ID Field (for Upsert)", choices=[], visible=False)
286
-
287
- with gr.Column():
288
- object_fields_info = gr.Markdown("Select an object to see available fields")
289
-
290
- upload_btn = gr.Button("πŸ“€ Upload Data", variant="primary")
291
- upload_results = gr.Markdown("")
292
- download_results = gr.File(label="Download Results", visible=False)
293
-
294
- with gr.Tab("πŸ“₯ Export Data", visible=False) as export_tab:
295
- gr.Markdown("### Export data from Salesforce")
296
-
297
- with gr.Row():
298
- with gr.Column():
299
- export_object = gr.Dropdown(label="Select Object to Export", choices=[])
300
- export_fields = gr.CheckboxGroup(label="Select Fields to Export", choices=[])
301
- record_limit = gr.Slider(minimum=100, maximum=10000, value=1000, step=100,
302
- label="Record Limit")
303
-
304
- with gr.Column():
305
- export_fields_info = gr.Markdown("Select an object to see available fields")
306
-
307
- export_btn = gr.Button("πŸ“₯ Export Data", variant="primary")
308
- export_results = gr.Markdown("")
309
- download_export = gr.File(label="Download Export", visible=False)
310
 
311
- # Event handlers
312
- connect_btn.click(
313
- fn=sf_loader.connect_to_salesforce,
314
- inputs=[username, password, security_token, sandbox],
315
- outputs=[connection_status, upload_tab, object_dropdown]
316
- )
317
 
318
- # Update export object dropdown when connection is made
319
- def update_export_dropdown(status, visible, choices):
320
- if visible and choices:
321
- return gr.update(choices=choices, value=None)
322
- return gr.update(choices=[], value=None)
323
 
324
- connect_btn.click(
325
- fn=update_export_dropdown,
326
- inputs=[connection_status, upload_tab, object_dropdown],
327
- outputs=[export_object]
328
- )
329
 
330
- object_dropdown.change(
331
- fn=sf_loader.get_object_fields,
332
- inputs=[object_dropdown],
333
- outputs=[external_id_field, object_fields_info]
334
- )
335
 
336
- export_object.change(
337
- fn=sf_loader.get_object_fields,
338
- inputs=[export_object],
339
- outputs=[export_fields, export_fields_info]
340
- )
 
 
 
 
341
 
342
- def toggle_external_id(operation):
343
- return gr.update(visible=(operation == "Upsert"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
 
345
- operation_dropdown.change(
346
- fn=toggle_external_id,
347
- inputs=[operation_dropdown],
348
- outputs=[external_id_field]
 
 
 
 
 
 
 
 
 
349
  )
 
 
 
 
 
 
 
 
350
 
351
  upload_btn.click(
352
- fn=sf_loader.upload_data_to_salesforce,
353
- inputs=[file_upload, object_dropdown, operation_dropdown, external_id_field],
354
  outputs=[upload_results, download_results]
355
  )
356
-
357
- def show_download_results(file):
358
- return gr.update(visible=file is not None)
359
-
360
- download_results.change(
361
- fn=show_download_results,
362
- inputs=[download_results],
363
- outputs=[download_results]
 
 
 
 
 
 
364
  )
 
 
 
365
 
366
  export_btn.click(
367
- fn=sf_loader.export_data_from_salesforce,
368
- inputs=[export_object, export_fields, record_limit],
369
  outputs=[export_results, download_export]
370
  )
371
-
372
- def show_download_export(file):
373
- return gr.update(visible=file is not None)
374
-
375
- download_export.change(
376
- fn=show_download_export,
377
- inputs=[download_export],
378
- outputs=[download_export]
379
- )
380
-
381
- return interface
382
 
383
- # Launch the interface
384
  if __name__ == "__main__":
385
- interface = create_interface()
386
- interface.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import gradio as gr
2
  import pandas as pd
 
3
  from simple_salesforce import Salesforce
4
  import io
 
5
  from datetime import datetime
 
6
  import logging
7
 
8
  # Set up logging
9
  logging.basicConfig(level=logging.INFO)
10
  logger = logging.getLogger(__name__)
11
 
12
+ # Global variables to store connection
13
+ sf_connection = None
14
+ available_objects = []
15
+
16
+ def connect_to_salesforce(username, password, security_token, sandbox):
17
+ """Connect to Salesforce"""
18
+ global sf_connection, available_objects
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ try:
21
+ domain = 'test' if sandbox else None
22
+ sf_connection = Salesforce(
23
+ username=username,
24
+ password=password,
25
+ security_token=security_token,
26
+ domain=domain
27
+ )
28
+
29
+ # Test connection and get objects
30
+ common_objects = ['Account', 'Contact', 'Lead', 'Opportunity', 'Case']
31
+ available_objects = []
32
+
33
+ for obj_name in common_objects:
34
+ try:
35
+ obj = getattr(sf_connection, obj_name)
36
+ obj.describe()
37
+ available_objects.append(obj_name)
38
+ except:
39
+ continue
40
+
41
+ if not available_objects:
42
+ available_objects = ['Account', 'Contact', 'Lead']
43
+
44
+ return f"βœ… Successfully connected to Salesforce as {username}\nAvailable objects: {', '.join(available_objects)}"
45
+
46
+ except Exception as e:
47
+ sf_connection = None
48
+ available_objects = []
49
+ error_msg = str(e)
50
+
51
+ if "INVALID_LOGIN" in error_msg:
52
+ return "❌ Invalid credentials. Please check your username, password, and security token."
53
+ elif "API_DISABLED_FOR_ORG" in error_msg:
54
+ return "❌ API access is disabled for your organization. Please contact your Salesforce admin."
55
+ elif "LOGIN_MUST_USE_SECURITY_TOKEN" in error_msg:
56
+ return "❌ Security token required. Please append your security token to your password."
57
+ else:
58
+ return f"❌ Connection failed: {error_msg}"
 
 
 
 
 
 
 
 
59
 
60
+ def upload_data_to_salesforce(file, object_name, operation):
61
+ """Upload data to Salesforce"""
62
+ global sf_connection
63
+
64
+ if not sf_connection:
65
+ return "❌ Please connect to Salesforce first", None
66
+
67
+ if not file or not object_name:
68
+ return "❌ Please select a file and object", None
69
+
70
+ try:
71
+ # Read the uploaded file
72
+ if file.name.endswith('.csv'):
73
+ df = pd.read_csv(file.name)
74
+ elif file.name.endswith(('.xlsx', '.xls')):
75
+ df = pd.read_excel(file.name)
76
+ else:
77
+ return "❌ Please upload a CSV or Excel file", None
78
+
79
+ if df.empty:
80
+ return "❌ The uploaded file is empty", None
81
+
82
+ # Get Salesforce object
83
+ sf_object = getattr(sf_connection, object_name)
84
+
85
+ # Prepare data for upload
86
+ records = df.to_dict('records')
87
+
88
+ # Clean data - remove NaN values
89
+ cleaned_records = []
90
+ for record in records:
91
+ cleaned_record = {k: v for k, v in record.items() if pd.notna(v)}
92
+ cleaned_records.append(cleaned_record)
93
+
94
+ # Perform operation
95
+ if operation == "Insert":
96
+ result = sf_object.bulk.insert(cleaned_records)
97
+ elif operation == "Update":
98
+ result = sf_object.bulk.update(cleaned_records)
99
+ else: # Upsert
100
+ return "❌ Upsert operation requires additional configuration", None
101
+
102
+ # Process results
103
+ success_count = sum(1 for r in result if r.get('success'))
104
+ error_count = len(result) - success_count
105
+
106
+ summary = f"βœ… Operation completed!\n"
107
+ summary += f"πŸ“Š Total records: {len(records)}\n"
108
+ summary += f"βœ… Successful: {success_count}\n"
109
+ summary += f"❌ Failed: {error_count}\n"
110
+
111
+ # Create results file
112
+ results_df = pd.DataFrame(result)
113
+ results_file = f"salesforce_upload_results_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
114
+ results_df.to_csv(results_file, index=False)
115
+
116
+ return summary, results_file
117
+
118
+ except Exception as e:
119
+ logger.error(f"Upload error: {str(e)}")
120
+ return f"❌ Error: {str(e)}", None
121
 
122
+ def export_data_from_salesforce(object_name, record_limit):
123
+ """Export data from Salesforce"""
124
+ global sf_connection
125
+
126
+ if not sf_connection:
127
+ return "❌ Please connect to Salesforce first", None
128
 
129
+ if not object_name:
130
+ return "❌ Please select an object", None
131
 
132
+ try:
133
+ # Get object metadata to find some fields
134
+ obj = getattr(sf_connection, object_name)
135
+ metadata = obj.describe()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
 
137
+ # Get first 10 fields
138
+ fields = [field['name'] for field in metadata['fields'][:10]]
139
+ fields_str = ', '.join(fields)
 
 
 
140
 
141
+ # Build and execute query
142
+ query = f"SELECT {fields_str} FROM {object_name} LIMIT {record_limit}"
143
+ result = sf_connection.query_all(query)
144
+ records = result['records']
 
145
 
146
+ if not records:
147
+ return "❌ No records found", None
 
 
 
148
 
149
+ # Convert to DataFrame and clean
150
+ df = pd.DataFrame(records)
151
+ if 'attributes' in df.columns:
152
+ df = df.drop('attributes', axis=1)
 
153
 
154
+ # Create export file
155
+ export_file = f"salesforce_export_{object_name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv"
156
+ df.to_csv(export_file, index=False)
157
+
158
+ summary = f"βœ… Export completed!\n"
159
+ summary += f"πŸ“Š Records exported: {len(records)}\n"
160
+ summary += f"πŸ“‹ Fields: {', '.join(fields)}\n"
161
+
162
+ return summary, export_file
163
 
164
+ except Exception as e:
165
+ logger.error(f"Export error: {str(e)}")
166
+ return f"❌ Error: {str(e)}", None
167
+
168
+ # Create the Gradio interface
169
+ with gr.Blocks(title="Salesforce Data Loader", theme=gr.themes.Default()) as demo:
170
+ gr.Markdown("""
171
+ # πŸš€ Salesforce Data Loader
172
+ A simple tool to upload and download data from Salesforce.
173
+ """)
174
+
175
+ with gr.Tab("πŸ” Connect"):
176
+ gr.Markdown("### Connect to Salesforce")
177
+ username = gr.Textbox(label="Username", placeholder="[email protected]")
178
+ password = gr.Textbox(label="Password", type="password")
179
+ security_token = gr.Textbox(label="Security Token", type="password")
180
+ sandbox = gr.Checkbox(label="Sandbox Environment")
181
+ connect_btn = gr.Button("πŸ”— Connect", variant="primary")
182
+ connection_status = gr.Textbox(label="Connection Status", interactive=False)
183
 
184
+ connect_btn.click(
185
+ fn=connect_to_salesforce,
186
+ inputs=[username, password, security_token, sandbox],
187
+ outputs=[connection_status]
188
+ )
189
+
190
+ with gr.Tab("πŸ“€ Upload"):
191
+ gr.Markdown("### Upload CSV/Excel data to Salesforce")
192
+ file_upload = gr.File(label="Upload CSV or Excel file")
193
+ upload_object = gr.Dropdown(
194
+ label="Salesforce Object",
195
+ choices=["Account", "Contact", "Lead", "Opportunity", "Case"],
196
+ value="Contact"
197
  )
198
+ upload_operation = gr.Dropdown(
199
+ label="Operation",
200
+ choices=["Insert", "Update"],
201
+ value="Insert"
202
+ )
203
+ upload_btn = gr.Button("πŸ“€ Upload Data", variant="primary")
204
+ upload_results = gr.Textbox(label="Upload Results", interactive=False)
205
+ download_results = gr.File(label="Download Results")
206
 
207
  upload_btn.click(
208
+ fn=upload_data_to_salesforce,
209
+ inputs=[file_upload, upload_object, upload_operation],
210
  outputs=[upload_results, download_results]
211
  )
212
+
213
+ with gr.Tab("πŸ“₯ Export"):
214
+ gr.Markdown("### Export data from Salesforce")
215
+ export_object = gr.Dropdown(
216
+ label="Salesforce Object",
217
+ choices=["Account", "Contact", "Lead", "Opportunity", "Case"],
218
+ value="Account"
219
+ )
220
+ export_limit = gr.Slider(
221
+ label="Record Limit",
222
+ minimum=100,
223
+ maximum=10000,
224
+ value=1000,
225
+ step=100
226
  )
227
+ export_btn = gr.Button("πŸ“₯ Export Data", variant="primary")
228
+ export_results = gr.Textbox(label="Export Results", interactive=False)
229
+ download_export = gr.File(label="Download Export")
230
 
231
  export_btn.click(
232
+ fn=export_data_from_salesforce,
233
+ inputs=[export_object, export_limit],
234
  outputs=[export_results, download_export]
235
  )
 
 
 
 
 
 
 
 
 
 
 
236
 
 
237
  if __name__ == "__main__":
238
+ demo.launch(server_name="0.0.0.0", server_port=7860)