diff --git a/backend/score.py b/backend/score.py index b2117d455..1175ac554 100644 --- a/backend/score.py +++ b/backend/score.py @@ -115,7 +115,8 @@ async def create_source_knowledge_graph_url( gcs_bucket_folder=Form(None), source_type=Form(None), gcs_project_id=Form(None), - access_token=Form(None) + access_token=Form(None), + email=Form() ): try: @@ -149,7 +150,7 @@ async def create_source_knowledge_graph_url( elapsed_time = end - start json_obj = {'api_name':'url_scan','db_url':uri,'url_scanned_file':lst_file_name, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','userName':userName, 'database':database, 'aws_access_key_id':aws_access_key_id, 'model':model, 'gcs_bucket_name':gcs_bucket_name, 'gcs_bucket_folder':gcs_bucket_folder, 'source_type':source_type, - 'gcs_project_id':gcs_project_id, 'logging_time': formatted_time(datetime.now(timezone.utc))} + 'gcs_project_id':gcs_project_id, 'logging_time': formatted_time(datetime.now(timezone.utc)),'email':email} logger.log_struct(json_obj, "INFO") result ={'elapsed_api_time' : f'{elapsed_time:.2f}'} return create_api_response("Success",message=message,success_count=success_count,failed_count=failed_count,file_name=lst_file_name,data=result) @@ -157,13 +158,13 @@ async def create_source_knowledge_graph_url( error_message = str(e) message = f" Unable to create source node for source type: {source_type} and source: {source}" # Set the status "Success" becuase we are treating these error already handled by application as like custom errors. - json_obj = {'error_message':error_message, 'status':'Success','db_url':uri, 'userName':userName, 'database':database,'success_count':1, 'source_type': source_type, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc))} + json_obj = {'error_message':error_message, 'status':'Success','db_url':uri, 'userName':userName, 'database':database,'success_count':1, 'source_type': source_type, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc)),'email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Failed',message=message + error_message[:80],error=error_message,file_source=source_type) except Exception as e: error_message = str(e) message = f" Unable to create source node for source type: {source_type} and source: {source}" - json_obj = {'error_message':error_message, 'status':'Failed','db_url':uri, 'userName':userName, 'database':database,'failed_count':1, 'source_type': source_type, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc))} + json_obj = {'error_message':error_message, 'status':'Failed','db_url':uri, 'userName':userName, 'database':database,'failed_count':1, 'source_type': source_type, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc)),'email':email} logger.log_struct(json_obj, "ERROR") logging.exception(f'Exception Stack trace:') return create_api_response('Failed',message=message + error_message[:80],error=error_message,file_source=source_type) @@ -192,7 +193,8 @@ async def extract_knowledge_graph_from_file( language=Form(None), access_token=Form(None), retry_condition=Form(None), - additional_instructions=Form(None) + additional_instructions=Form(None), + email=Form() ): """ Calls 'extract_graph_from_file' in a new thread to create Neo4jGraph from a @@ -266,6 +268,7 @@ async def extract_knowledge_graph_from_file( result['gcs_project_id'] = gcs_project_id result['language'] = language result['retry_condition'] = retry_condition + result['email'] = email logger.log_struct(result, "INFO") result.update(uri_latency) logging.info(f"extraction completed in {extract_api_time:.2f} seconds for file name {file_name}") @@ -277,7 +280,7 @@ async def extract_knowledge_graph_from_file( node_detail = graphDb_data_Access.get_current_status_document_node(file_name) # Set the status "Completed" in logging becuase we are treating these error already handled by application as like custom errors. json_obj = {'api_name':'extract','message':error_message,'file_created_at':node_detail[0]['created_time'],'error_message':error_message, 'file_name': file_name,'status':'Completed', - 'db_url':uri, 'userName':userName, 'database':database,'success_count':1, 'source_type': source_type, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc))} + 'db_url':uri, 'userName':userName, 'database':database,'success_count':1, 'source_type': source_type, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc)),'email':email} logger.log_struct(json_obj, "INFO") return create_api_response("Failed", message = error_message, error=error_message, file_name=file_name) except Exception as e: @@ -288,14 +291,14 @@ async def extract_knowledge_graph_from_file( node_detail = graphDb_data_Access.get_current_status_document_node(file_name) json_obj = {'api_name':'extract','message':message,'file_created_at':node_detail[0]['created_time'],'error_message':error_message, 'file_name': file_name,'status':'Failed', - 'db_url':uri, 'userName':userName, 'database':database,'failed_count':1, 'source_type': source_type, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc))} + 'db_url':uri, 'userName':userName, 'database':database,'failed_count':1, 'source_type': source_type, 'source_url':source_url, 'wiki_query':wiki_query, 'logging_time': formatted_time(datetime.now(timezone.utc)),'email':email} logger.log_struct(json_obj, "ERROR") return create_api_response('Failed', message=message + error_message[:100], error=error_message, file_name = file_name) finally: gc.collect() @app.get("/sources_list") -async def get_source_list(uri:str, userName:str, password:str, database:str=None): +async def get_source_list(uri:str, userName:str, password:str, email:str, database:str=None): """ Calls 'get_source_list_from_graph' which returns list of sources which already exist in databse """ @@ -307,7 +310,7 @@ async def get_source_list(uri:str, userName:str, password:str, database:str=None result = await asyncio.to_thread(get_source_list_from_graph,uri,userName,decoded_password,database) end = time.time() elapsed_time = end - start - json_obj = {'api_name':'sources_list','db_url':uri, 'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'sources_list','db_url':uri, 'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response("Success",data=result, message=f"Total elapsed API time {elapsed_time:.2f}") except Exception as e: @@ -318,7 +321,7 @@ async def get_source_list(uri:str, userName:str, password:str, database:str=None return create_api_response(job_status, message=message, error=error_message) @app.post("/post_processing") -async def post_processing(uri=Form(), userName=Form(), password=Form(), database=Form(), tasks=Form(None)): +async def post_processing(uri=Form(), userName=Form(), password=Form(), database=Form(), tasks=Form(None), email=Form()): try: graph = create_graph_database_connection(uri, userName, password, database) tasks = set(map(str.strip, json.loads(tasks))) @@ -362,7 +365,7 @@ async def post_processing(uri=Form(), userName=Form(), password=Form(), database end = time.time() elapsed_time = end - start - json_obj = {'api_name': api_name, 'db_url': uri, 'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name': api_name, 'db_url': uri, 'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj) return create_api_response('Success', data=count_response, message='All tasks completed successfully') @@ -377,7 +380,7 @@ async def post_processing(uri=Form(), userName=Form(), password=Form(), database gc.collect() @app.post("/chat_bot") -async def chat_bot(uri=Form(),model=Form(None),userName=Form(), password=Form(), database=Form(),question=Form(None), document_names=Form(None),session_id=Form(None),mode=Form(None)): +async def chat_bot(uri=Form(),model=Form(None),userName=Form(), password=Form(), database=Form(),question=Form(None), document_names=Form(None),session_id=Form(None),mode=Form(None),email=Form()): logging.info(f"QA_RAG called at {datetime.now()}") qa_rag_start_time = time.time() try: @@ -395,7 +398,7 @@ async def chat_bot(uri=Form(),model=Form(None),userName=Form(), password=Form(), result["info"]["response_time"] = round(total_call_time, 2) json_obj = {'api_name':'chat_bot','db_url':uri, 'userName':userName, 'database':database, 'question':question,'document_names':document_names, - 'session_id':session_id, 'mode':mode, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{total_call_time:.2f}'} + 'session_id':session_id, 'mode':mode, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{total_call_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=result) @@ -409,14 +412,14 @@ async def chat_bot(uri=Form(),model=Form(None),userName=Form(), password=Form(), gc.collect() @app.post("/chunk_entities") -async def chunk_entities(uri=Form(),userName=Form(), password=Form(), database=Form(), nodedetails=Form(None),entities=Form(),mode=Form()): +async def chunk_entities(uri=Form(),userName=Form(), password=Form(), database=Form(), nodedetails=Form(None),entities=Form(),mode=Form(),email=Form()): try: start = time.time() result = await asyncio.to_thread(get_entities_from_chunkids,uri=uri, username=userName, password=password, database=database,nodedetails=nodedetails,entities=entities,mode=mode) end = time.time() elapsed_time = end - start json_obj = {'api_name':'chunk_entities','db_url':uri, 'userName':userName, 'database':database, 'nodedetails':nodedetails,'entities':entities, - 'mode':mode, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + 'mode':mode, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=result,message=f"Total elapsed API time {elapsed_time:.2f}") except Exception as e: @@ -429,13 +432,13 @@ async def chunk_entities(uri=Form(),userName=Form(), password=Form(), database=F gc.collect() @app.post("/get_neighbours") -async def get_neighbours(uri=Form(),userName=Form(), password=Form(), database=Form(), elementId=Form(None)): +async def get_neighbours(uri=Form(),userName=Form(), password=Form(), database=Form(), elementId=Form(None),email=Form()): try: start = time.time() result = await asyncio.to_thread(get_neighbour_nodes,uri=uri, username=userName, password=password,database=database, element_id=elementId) end = time.time() elapsed_time = end - start - json_obj = {'api_name':'get_neighbours', 'userName':userName, 'database':database,'db_url':uri, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'get_neighbours', 'userName':userName, 'database':database,'db_url':uri, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=result,message=f"Total elapsed API time {elapsed_time:.2f}") except Exception as e: @@ -454,6 +457,7 @@ async def graph_query( userName: str = Form(), password: str = Form(), document_names: str = Form(None), + email=Form() ): try: start = time.time() @@ -467,7 +471,7 @@ async def graph_query( ) end = time.time() elapsed_time = end - start - json_obj = {'api_name':'graph_query','db_url':uri, 'userName':userName, 'database':database, 'document_names':document_names, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'graph_query','db_url':uri, 'userName':userName, 'database':database, 'document_names':document_names, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success', data=result,message=f"Total elapsed API time {elapsed_time:.2f}") except Exception as e: @@ -481,14 +485,14 @@ async def graph_query( @app.post("/clear_chat_bot") -async def clear_chat_bot(uri=Form(),userName=Form(), password=Form(), database=Form(), session_id=Form(None)): +async def clear_chat_bot(uri=Form(),userName=Form(), password=Form(), database=Form(), session_id=Form(None),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) result = await asyncio.to_thread(clear_chat_history,graph=graph,session_id=session_id) end = time.time() elapsed_time = end - start - json_obj = {'api_name':'clear_chat_bot', 'db_url':uri, 'userName':userName, 'database':database, 'session_id':session_id, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'clear_chat_bot', 'db_url':uri, 'userName':userName, 'database':database, 'session_id':session_id, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=result) except Exception as e: @@ -501,7 +505,7 @@ async def clear_chat_bot(uri=Form(),userName=Form(), password=Form(), database=F gc.collect() @app.post("/connect") -async def connect(uri=Form(), userName=Form(), password=Form(), database=Form()): +async def connect(uri=Form(), userName=Form(), password=Form(), database=Form(),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -510,7 +514,7 @@ async def connect(uri=Form(), userName=Form(), password=Form(), database=Form()) chunk_to_be_created = int(os.environ.get('CHUNKS_TO_BE_CREATED', '50')) end = time.time() elapsed_time = end - start - json_obj = {'api_name':'connect','db_url':uri, 'userName':userName, 'database':database, 'count':1, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'connect','db_url':uri, 'userName':userName, 'database':database, 'count':1, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") result['elapsed_api_time'] = f'{elapsed_time:.2f}' result['gcs_file_cache'] = gcs_file_cache @@ -526,7 +530,7 @@ async def connect(uri=Form(), userName=Form(), password=Form(), database=Form()) @app.post("/upload") async def upload_large_file_into_chunks(file:UploadFile = File(...), chunkNumber=Form(None), totalChunks=Form(None), originalname=Form(None), model=Form(None), uri=Form(), userName=Form(), - password=Form(), database=Form()): + password=Form(), database=Form(),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -534,7 +538,7 @@ async def upload_large_file_into_chunks(file:UploadFile = File(...), chunkNumber end = time.time() elapsed_time = end - start json_obj = {'api_name':'upload','db_url':uri,'userName':userName, 'database':database, 'chunkNumber':chunkNumber,'totalChunks':totalChunks, - 'original_file_name':originalname,'model':model, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + 'original_file_name':originalname,'model':model, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") if int(chunkNumber) == int(totalChunks): return create_api_response('Success',data=result, message='Source Node Created Successfully') @@ -550,7 +554,7 @@ async def upload_large_file_into_chunks(file:UploadFile = File(...), chunkNumber gc.collect() @app.post("/schema") -async def get_structured_schema(uri=Form(), userName=Form(), password=Form(), database=Form()): +async def get_structured_schema(uri=Form(), userName=Form(), password=Form(), database=Form(),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -558,7 +562,7 @@ async def get_structured_schema(uri=Form(), userName=Form(), password=Form(), da end = time.time() elapsed_time = end - start logging.info(f'Schema result from DB: {result}') - json_obj = {'api_name':'schema','db_url':uri, 'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'schema','db_url':uri, 'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success', data=result,message=f"Total elapsed API time {elapsed_time:.2f}") except Exception as e: @@ -630,7 +634,8 @@ async def delete_document_and_entities(uri=Form(), database=Form(), filenames=Form(), source_types=Form(), - deleteEntities=Form()): + deleteEntities=Form(), + email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -640,7 +645,7 @@ async def delete_document_and_entities(uri=Form(), end = time.time() elapsed_time = end - start json_obj = {'api_name':'delete_document_and_entities','db_url':uri, 'userName':userName, 'database':database, 'filenames':filenames,'deleteEntities':deleteEntities, - 'source_types':source_types, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + 'source_types':source_types, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',message=message) except Exception as e: @@ -693,7 +698,7 @@ async def get_document_status(file_name, url, userName, password, database): return create_api_response('Failed',message=message) @app.post("/cancelled_job") -async def cancelled_job(uri=Form(), userName=Form(), password=Form(), database=Form(), filenames=Form(None), source_types=Form(None)): +async def cancelled_job(uri=Form(), userName=Form(), password=Form(), database=Form(), filenames=Form(None), source_types=Form(None),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -701,7 +706,7 @@ async def cancelled_job(uri=Form(), userName=Form(), password=Form(), database=F end = time.time() elapsed_time = end - start json_obj = {'api_name':'cancelled_job','db_url':uri, 'userName':userName, 'database':database, 'filenames':filenames, - 'source_types':source_types, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + 'source_types':source_types, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',message=result) except Exception as e: @@ -714,13 +719,13 @@ async def cancelled_job(uri=Form(), userName=Form(), password=Form(), database=F gc.collect() @app.post("/populate_graph_schema") -async def populate_graph_schema(input_text=Form(None), model=Form(None), is_schema_description_checked=Form(None)): +async def populate_graph_schema(input_text=Form(None), model=Form(None), is_schema_description_checked=Form(None),email=Form()): try: start = time.time() result = populate_graph_schema_from_text(input_text, model, is_schema_description_checked) end = time.time() elapsed_time = end - start - json_obj = {'api_name':'populate_graph_schema', 'model':model, 'is_schema_description_checked':is_schema_description_checked, 'input_text':input_text, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'populate_graph_schema', 'model':model, 'is_schema_description_checked':is_schema_description_checked, 'input_text':input_text, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=result) except Exception as e: @@ -733,7 +738,7 @@ async def populate_graph_schema(input_text=Form(None), model=Form(None), is_sche gc.collect() @app.post("/get_unconnected_nodes_list") -async def get_unconnected_nodes_list(uri=Form(), userName=Form(), password=Form(), database=Form()): +async def get_unconnected_nodes_list(uri=Form(), userName=Form(), password=Form(), database=Form(),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -741,7 +746,7 @@ async def get_unconnected_nodes_list(uri=Form(), userName=Form(), password=Form( nodes_list, total_nodes = graphDb_data_Access.list_unconnected_nodes() end = time.time() elapsed_time = end - start - json_obj = {'api_name':'get_unconnected_nodes_list','db_url':uri, 'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'get_unconnected_nodes_list','db_url':uri, 'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=nodes_list,message=total_nodes) except Exception as e: @@ -754,7 +759,7 @@ async def get_unconnected_nodes_list(uri=Form(), userName=Form(), password=Form( gc.collect() @app.post("/delete_unconnected_nodes") -async def delete_orphan_nodes(uri=Form(), userName=Form(), password=Form(), database=Form(),unconnected_entities_list=Form()): +async def delete_orphan_nodes(uri=Form(), userName=Form(), password=Form(), database=Form(),unconnected_entities_list=Form(),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -762,7 +767,7 @@ async def delete_orphan_nodes(uri=Form(), userName=Form(), password=Form(), data result = graphDb_data_Access.delete_unconnected_nodes(unconnected_entities_list) end = time.time() elapsed_time = end - start - json_obj = {'api_name':'delete_unconnected_nodes','db_url':uri, 'userName':userName, 'database':database,'unconnected_entities_list':unconnected_entities_list, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'delete_unconnected_nodes','db_url':uri, 'userName':userName, 'database':database,'unconnected_entities_list':unconnected_entities_list, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=result,message="Unconnected entities delete successfully") except Exception as e: @@ -775,7 +780,7 @@ async def delete_orphan_nodes(uri=Form(), userName=Form(), password=Form(), data gc.collect() @app.post("/get_duplicate_nodes") -async def get_duplicate_nodes(uri=Form(), userName=Form(), password=Form(), database=Form()): +async def get_duplicate_nodes(uri=Form(), userName=Form(), password=Form(), database=Form(),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -783,7 +788,7 @@ async def get_duplicate_nodes(uri=Form(), userName=Form(), password=Form(), data nodes_list, total_nodes = graphDb_data_Access.get_duplicate_nodes_list() end = time.time() elapsed_time = end - start - json_obj = {'api_name':'get_duplicate_nodes','db_url':uri,'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + json_obj = {'api_name':'get_duplicate_nodes','db_url':uri,'userName':userName, 'database':database, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=nodes_list, message=total_nodes) except Exception as e: @@ -796,7 +801,7 @@ async def get_duplicate_nodes(uri=Form(), userName=Form(), password=Form(), data gc.collect() @app.post("/merge_duplicate_nodes") -async def merge_duplicate_nodes(uri=Form(), userName=Form(), password=Form(), database=Form(),duplicate_nodes_list=Form()): +async def merge_duplicate_nodes(uri=Form(), userName=Form(), password=Form(), database=Form(),duplicate_nodes_list=Form(),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -805,7 +810,7 @@ async def merge_duplicate_nodes(uri=Form(), userName=Form(), password=Form(), da end = time.time() elapsed_time = end - start json_obj = {'api_name':'merge_duplicate_nodes','db_url':uri, 'userName':userName, 'database':database, - 'duplicate_nodes_list':duplicate_nodes_list, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + 'duplicate_nodes_list':duplicate_nodes_list, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',data=result,message="Duplicate entities merged successfully") except Exception as e: @@ -818,7 +823,7 @@ async def merge_duplicate_nodes(uri=Form(), userName=Form(), password=Form(), da gc.collect() @app.post("/drop_create_vector_index") -async def drop_create_vector_index(uri=Form(), userName=Form(), password=Form(), database=Form(), isVectorIndexExist=Form()): +async def drop_create_vector_index(uri=Form(), userName=Form(), password=Form(), database=Form(), isVectorIndexExist=Form(),email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -827,7 +832,7 @@ async def drop_create_vector_index(uri=Form(), userName=Form(), password=Form(), end = time.time() elapsed_time = end - start json_obj = {'api_name':'drop_create_vector_index', 'db_url':uri, 'userName':userName, 'database':database, - 'isVectorIndexExist':isVectorIndexExist, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + 'isVectorIndexExist':isVectorIndexExist, 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") return create_api_response('Success',message=result) except Exception as e: @@ -840,7 +845,7 @@ async def drop_create_vector_index(uri=Form(), userName=Form(), password=Form(), gc.collect() @app.post("/retry_processing") -async def retry_processing(uri=Form(), userName=Form(), password=Form(), database=Form(), file_name=Form(), retry_condition=Form()): +async def retry_processing(uri=Form(), userName=Form(), password=Form(), database=Form(), file_name=Form(), retry_condition=Form(), email=Form()): try: start = time.time() graph = create_graph_database_connection(uri, userName, password, database) @@ -848,7 +853,7 @@ async def retry_processing(uri=Form(), userName=Form(), password=Form(), databas end = time.time() elapsed_time = end - start json_obj = {'api_name':'retry_processing', 'db_url':uri, 'userName':userName, 'database':database, 'file_name':file_name,'retry_condition':retry_condition, - 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}'} + 'logging_time': formatted_time(datetime.now(timezone.utc)), 'elapsed_api_time':f'{elapsed_time:.2f}','email':email} logger.log_struct(json_obj, "INFO") if chunks[0]['text'] is None or chunks[0]['text']=="" or not chunks : return create_api_response('Success',message=f"Chunks are not created for the file{file_name}. Please upload again the file to re-process.",data=chunks) @@ -941,7 +946,8 @@ async def fetch_chunktext( userName: str = Form(), password: str = Form(), document_name: str = Form(), - page_no: int = Form(1) + page_no: int = Form(1), + email=Form() ): try: start = time.time() @@ -964,7 +970,8 @@ async def fetch_chunktext( 'document_name': document_name, 'page_no': page_no, 'logging_time': formatted_time(datetime.now(timezone.utc)), - 'elapsed_api_time': f'{elapsed_time:.2f}' + 'elapsed_api_time': f'{elapsed_time:.2f}', + 'email': email } logger.log_struct(json_obj, "INFO") return create_api_response('Success', data=result, message=f"Total elapsed API time {elapsed_time:.2f}") diff --git a/frontend/src/API/Index.ts b/frontend/src/API/Index.ts index f4ad15cbe..b89924221 100644 --- a/frontend/src/API/Index.ts +++ b/frontend/src/API/Index.ts @@ -1,7 +1,45 @@ import axios from 'axios'; import { url } from '../utils/Utils'; +import { UserCredentials } from '../types'; const api = axios.create({ baseURL: url(), + data: {}, }); + +export const createDefaultFormData = (userCredentials: UserCredentials) => { + const formData = new FormData(); + formData.append('uri', userCredentials?.uri ?? ''); + formData.append('database', userCredentials?.database ?? ''); + formData.append('userName', userCredentials?.userName ?? ''); + formData.append('password', userCredentials?.password ?? ''); + formData.append('email', userCredentials?.email ?? ''); + api.interceptors.request.use( + (config) => { + if (config.data instanceof FormData) { + for (const [key, value] of formData.entries()) { + if (!config.data.has(key)) { + config.data.append(key, value); + } + } + } else { + const formData = new FormData(); + for (const [key, value] of formData.entries()) { + formData.append(key, value); + } + for (const [key, value] of Object.entries(config.data || {})) { + formData.append(key, value as any); + } + config.data = formData; + } + + return config; + }, + (error) => { + return Promise.reject(error); + } + ); + return formData; +}; + export default api; diff --git a/frontend/src/components/ChatBot/ChatOnlyComponent.tsx b/frontend/src/components/ChatBot/ChatOnlyComponent.tsx index 3ab088a1b..7a3236a97 100644 --- a/frontend/src/components/ChatBot/ChatOnlyComponent.tsx +++ b/frontend/src/components/ChatBot/ChatOnlyComponent.tsx @@ -32,6 +32,7 @@ const ChatContent: React.FC = ({ chatMessages }) => { const encodedPassword = urlParams.get('password'); const database = urlParams.get('database'); const port = urlParams.get('port'); + const email = urlParams.get('email'); const openModal = urlParams.get('open') === 'true'; if (openModal || !(uri && user && encodedPassword && database && port)) { setOpenConnection((prev) => ({ ...prev, openPopUp: true })); @@ -42,6 +43,7 @@ const ChatContent: React.FC = ({ chatMessages }) => { password: atob(atob(encodedPassword)), database, port, + email: email ?? '', }; setShowBackButton(); setUserCredentials(credentialsForAPI); diff --git a/frontend/src/components/ChatBot/Chatbot.tsx b/frontend/src/components/ChatBot/Chatbot.tsx index 9a96fbb4c..e6b6a321a 100644 --- a/frontend/src/components/ChatBot/Chatbot.tsx +++ b/frontend/src/components/ChatBot/Chatbot.tsx @@ -23,12 +23,10 @@ import { ExtendedRelationship, Messages, ResponseMode, - UserCredentials, metricstate, multimodelmetric, nodeDetailsProps, } from '../../types'; -import { useCredentials } from '../../context/UserCredentials'; import { chatBotAPI } from '../../services/QnaAPI'; import { v4 as uuidv4 } from 'uuid'; import { useFileContext } from '../../context/UsersFiles'; @@ -63,7 +61,6 @@ const Chatbot: FC = (props) => { } = props; const [inputMessage, setInputMessage] = useState(''); const [loading, setLoading] = useState(isLoading); - const { userCredentials } = useCredentials(); const { model, chatModes, selectedRows, filesData } = useFileContext(); const messagesEndRef = useRef(null); const [showInfoModal, setShowInfoModal] = useState(false); @@ -215,7 +212,6 @@ const Chatbot: FC = (props) => { try { const apiCalls = chatModes.map((mode) => chatBotAPI( - userCredentials as UserCredentials, inputMessage, sessionId, model, diff --git a/frontend/src/components/ChatBot/ChunkInfo.tsx b/frontend/src/components/ChatBot/ChunkInfo.tsx index 2db5a2cbd..1f91cec77 100644 --- a/frontend/src/components/ChatBot/ChunkInfo.tsx +++ b/frontend/src/components/ChatBot/ChunkInfo.tsx @@ -1,5 +1,5 @@ import { FC, useContext, useState } from 'react'; -import { ChunkProps, UserCredentials } from '../../types'; +import { ChunkProps } from '../../types'; import { LoadingSpinner, TextLink, Typography } from '@neo4j-ndl/react'; import { DocumentTextIconOutline, GlobeAltIconOutline } from '@neo4j-ndl/react/icons'; import wikipedialogo from '../../assets/images/wikipedia.svg'; @@ -10,13 +10,11 @@ import ReactMarkdown from 'react-markdown'; import { generateYouTubeLink, getLogo, isAllowedHost } from '../../utils/Utils'; import { ThemeWrapperContext } from '../../context/ThemeWrapper'; import { chatModeLables } from '../../utils/Constants'; -import { useCredentials } from '../../context/UserCredentials'; import GraphViewModal from '../Graph/GraphViewModal'; import { handleGraphNodeClick } from './chatInfo'; const ChunkInfo: FC = ({ loading, chunks, mode }) => { const themeUtils = useContext(ThemeWrapperContext); - const { userCredentials } = useCredentials(); const [neoNodes, setNeoNodes] = useState([]); const [neoRels, setNeoRels] = useState([]); const [openGraphView, setOpenGraphView] = useState(false); @@ -25,7 +23,6 @@ const ChunkInfo: FC = ({ loading, chunks, mode }) => { const handleChunkClick = (elementId: string, viewMode: string) => { handleGraphNodeClick( - userCredentials as UserCredentials, elementId, viewMode, setNeoNodes, diff --git a/frontend/src/components/ChatBot/CommunitiesInfo.tsx b/frontend/src/components/ChatBot/CommunitiesInfo.tsx index 48a72b86c..afecdcefb 100644 --- a/frontend/src/components/ChatBot/CommunitiesInfo.tsx +++ b/frontend/src/components/ChatBot/CommunitiesInfo.tsx @@ -1,14 +1,12 @@ import { LoadingSpinner, Flex, Typography, TextLink } from '@neo4j-ndl/react'; import { FC, useState } from 'react'; import ReactMarkdown from 'react-markdown'; -import { CommunitiesProps, UserCredentials } from '../../types'; +import { CommunitiesProps } from '../../types'; import { chatModeLables } from '../../utils/Constants'; -import { useCredentials } from '../../context/UserCredentials'; import GraphViewModal from '../Graph/GraphViewModal'; import { handleGraphNodeClick } from './chatInfo'; const CommunitiesInfo: FC = ({ loading, communities, mode }) => { - const { userCredentials } = useCredentials(); const [neoNodes, setNeoNodes] = useState([]); const [neoRels, setNeoRels] = useState([]); const [openGraphView, setOpenGraphView] = useState(false); @@ -17,7 +15,6 @@ const CommunitiesInfo: FC = ({ loading, communities, mode }) = const handleCommunityClick = (elementId: string, viewMode: string) => { handleGraphNodeClick( - userCredentials as UserCredentials, elementId, viewMode, setNeoNodes, diff --git a/frontend/src/components/ChatBot/EntitiesInfo.tsx b/frontend/src/components/ChatBot/EntitiesInfo.tsx index 3c1626cef..489fb9d03 100644 --- a/frontend/src/components/ChatBot/EntitiesInfo.tsx +++ b/frontend/src/components/ChatBot/EntitiesInfo.tsx @@ -1,15 +1,13 @@ import { GraphLabel, LoadingSpinner, TextLink, Typography } from '@neo4j-ndl/react'; import { FC, useMemo, useState } from 'react'; -import { EntitiesProps, GroupedEntity, UserCredentials } from '../../types'; +import { EntitiesProps, GroupedEntity } from '../../types'; import { calcWordColor } from '@neo4j-devtools/word-color'; import { graphLabels } from '../../utils/Constants'; import { parseEntity } from '../../utils/Utils'; -import { useCredentials } from '../../context/UserCredentials'; import GraphViewModal from '../Graph/GraphViewModal'; import { handleGraphNodeClick } from './chatInfo'; const EntitiesInfo: FC = ({ loading, mode, graphonly_entities, infoEntities }) => { - const { userCredentials } = useCredentials(); const [neoNodes, setNeoNodes] = useState([]); const [neoRels, setNeoRels] = useState([]); const [openGraphView, setOpenGraphView] = useState(false); @@ -45,7 +43,6 @@ const EntitiesInfo: FC = ({ loading, mode, graphonly_entities, in const handleEntityClick = (elementId: string, viewMode: string) => { handleGraphNodeClick( - userCredentials as UserCredentials, elementId, viewMode, setNeoNodes, diff --git a/frontend/src/components/ChatBot/chatInfo.ts b/frontend/src/components/ChatBot/chatInfo.ts index 26f2e765c..7a545a817 100644 --- a/frontend/src/components/ChatBot/chatInfo.ts +++ b/frontend/src/components/ChatBot/chatInfo.ts @@ -1,9 +1,8 @@ import { getNeighbors } from '../../services/GraphQuery'; -import { NeoNode, NeoRelationship, UserCredentials } from '../../types'; +import { NeoNode, NeoRelationship } from '../../types'; import { showNormalToast } from '../../utils/toasts'; export const handleGraphNodeClick = async ( - userCredentials: UserCredentials, elementId: string, viewMode: string, setNeoNodes: React.Dispatch>, @@ -16,7 +15,7 @@ export const handleGraphNodeClick = async ( setLoadingGraphView(true); } try { - const result = await getNeighbors(userCredentials, elementId); + const result = await getNeighbors(elementId); if (result && result.data.data.nodes.length > 0) { let { nodes } = result.data.data; if (viewMode === 'Chunk') { diff --git a/frontend/src/components/Content.tsx b/frontend/src/components/Content.tsx index 302f0e381..e9b3f3fc1 100644 --- a/frontend/src/components/Content.tsx +++ b/frontend/src/components/Content.tsx @@ -4,15 +4,7 @@ import { Button, Typography, Flex, StatusIndicator, useMediaQuery } from '@neo4j import { useCredentials } from '../context/UserCredentials'; import { useFileContext } from '../context/UsersFiles'; import { extractAPI } from '../utils/FileAPI'; -import { - BannerAlertProps, - ContentProps, - CustomFile, - OptionType, - UserCredentials, - chunkdata, - FileTableHandle, -} from '../types'; +import { BannerAlertProps, ContentProps, CustomFile, OptionType, chunkdata, FileTableHandle } from '../types'; import deleteAPI from '../services/DeleteFiles'; import { postProcessing } from '../services/PostProcessing'; import { triggerStatusUpdateAPI } from '../services/ServerSideStatusUpdateAPI'; @@ -157,34 +149,36 @@ const Content: React.FC = ({ (task) => task !== 'graph_schema_consolidation' && task !== 'enable_communities' ) : postProcessingTasks.filter((task) => task !== 'enable_communities'); - const response = await postProcessing(userCredentials as UserCredentials, payload); - if (response.data.status === 'Success') { - const communityfiles = response.data?.data; - if (Array.isArray(communityfiles) && communityfiles.length) { - communityfiles?.forEach((c: any) => { - setFilesData((prev) => { - return prev.map((f) => { - if (f.name === c.filename) { - return { - ...f, - chunkNodeCount: c.chunkNodeCount ?? 0, - entityNodeCount: c.entityNodeCount ?? 0, - communityNodeCount: c.communityNodeCount ?? 0, - chunkRelCount: c.chunkRelCount ?? 0, - entityEntityRelCount: c.entityEntityRelCount ?? 0, - communityRelCount: c.communityRelCount ?? 0, - nodesCount: c.nodeCount, - relationshipsCount: c.relationshipCount, - }; - } - return f; + if (payload.length) { + const response = await postProcessing(payload); + if (response.data.status === 'Success') { + const communityfiles = response.data?.data; + if (Array.isArray(communityfiles) && communityfiles.length) { + communityfiles?.forEach((c: any) => { + setFilesData((prev) => { + return prev.map((f) => { + if (f.name === c.filename) { + return { + ...f, + chunkNodeCount: c.chunkNodeCount ?? 0, + entityNodeCount: c.entityNodeCount ?? 0, + communityNodeCount: c.communityNodeCount ?? 0, + chunkRelCount: c.chunkRelCount ?? 0, + entityEntityRelCount: c.entityEntityRelCount ?? 0, + communityRelCount: c.communityRelCount ?? 0, + nodesCount: c.nodeCount, + relationshipsCount: c.relationshipCount, + }; + } + return f; + }); }); }); - }); + } + showSuccessToast('All Q&A functionality is available now.'); + } else { + throw new Error(response.data.error); } - showSuccessToast('All Q&A functionality is available now.'); - } else { - throw new Error(response.data.error); } } catch (error) { if (error instanceof Error) { @@ -220,7 +214,7 @@ const Content: React.FC = ({ }; const getChunks = async (name: string, pageNo: number) => { toggleChunksLoading(); - const response = await getChunkText(userCredentials as UserCredentials, name, pageNo); + const response = await getChunkText(name, pageNo); setTextChunks(response.data.data.pageitems); if (!totalPageCount) { setTotalPageCount(response.data.data.total_pages); @@ -281,7 +275,6 @@ const Content: React.FC = ({ const apiResponse = await extractAPI( fileItem.model, - userCredentials as UserCredentials, fileItem.fileSource, fileItem.retryOption ?? '', fileItem.sourceUrl, @@ -384,7 +377,7 @@ const Content: React.FC = ({ }; const addFilesToQueue = async (remainingFiles: CustomFile[]) => { - if (!remainingFiles.length) { + if (!remainingFiles.length && postProcessingTasks.length) { showNormalToast( = ({ /> ); try { - const response = await postProcessing(userCredentials as UserCredentials, postProcessingTasks); + const response = await postProcessing(postProcessingTasks); if (response.data.status === 'Success') { const communityfiles = response.data?.data; if (Array.isArray(communityfiles) && communityfiles.length) { @@ -561,7 +554,7 @@ const Content: React.FC = ({ setConnectionStatus(false); localStorage.removeItem('password'); localStorage.removeItem('selectedModel'); - setUserCredentials({ uri: '', password: '', userName: '', database: '' }); + setUserCredentials({ uri: '', password: '', userName: '', database: '', email: '' }); setSelectedNodes([]); setSelectedRels([]); localStorage.removeItem('instructions'); @@ -586,7 +579,7 @@ const Content: React.FC = ({ const retryHandler = async (filename: string, retryoption: string) => { try { setRetryLoading(true); - const response = await retry(userCredentials as UserCredentials, filename, retryoption); + const response = await retry(filename, retryoption); setRetryLoading(false); if (response.data.status === 'Failure') { throw new Error(response.data.error); @@ -677,11 +670,7 @@ const Content: React.FC = ({ const handleDeleteFiles = async (deleteEntities: boolean) => { try { setIsDeleteLoading(true); - const response = await deleteAPI( - userCredentials as UserCredentials, - childRef.current?.getSelectedRows() as CustomFile[], - deleteEntities - ); + const response = await deleteAPI(childRef.current?.getSelectedRows() as CustomFile[], deleteEntities); queue.clear(); setProcessedCount(0); setRowSelection({}); @@ -716,7 +705,7 @@ const Content: React.FC = ({ const selectedRows = childRef.current?.getSelectedRows(); if (selectedRows?.length) { const expiredFilesExists = selectedRows.some( - (c) => c.status !== 'Ready to Reprocess' && isExpired((c?.createdAt as Date) ?? new Date()) + (c) => isFileReadyToProcess(c, true) && isExpired((c?.createdAt as Date) ?? new Date()) ); const largeFileExists = selectedRows.some( (c) => isFileReadyToProcess(c, true) && typeof c.size === 'number' && c.size > largeFileSize @@ -729,7 +718,7 @@ const Content: React.FC = ({ handleGenerateGraph(selectedRows.filter((f) => isFileReadyToProcess(f, false))); } } else if (filesData.length) { - const expiredFileExists = filesData.some((c) => isExpired(c?.createdAt as Date)); + const expiredFileExists = filesData.some((c) => isFileReadyToProcess(c, true) && isExpired(c?.createdAt as Date)); const largeFileExists = filesData.some( (c) => isFileReadyToProcess(c, true) && typeof c.size === 'number' && c.size > largeFileSize ); diff --git a/frontend/src/components/DataSources/AWS/S3Modal.tsx b/frontend/src/components/DataSources/AWS/S3Modal.tsx index 2ab89e2a9..30f07e65b 100644 --- a/frontend/src/components/DataSources/AWS/S3Modal.tsx +++ b/frontend/src/components/DataSources/AWS/S3Modal.tsx @@ -1,8 +1,7 @@ import { TextInput } from '@neo4j-ndl/react'; import React, { useState } from 'react'; -import { CustomFile, CustomFileBase, S3File, S3ModalProps, UserCredentials } from '../../../types'; +import { CustomFile, CustomFileBase, S3File, S3ModalProps } from '../../../types'; import { urlScanAPI } from '../../../services/URLScan'; -import { useCredentials } from '../../../context/UserCredentials'; import { validation } from '../../../utils/Utils'; import { useFileContext } from '../../../context/UsersFiles'; import { v4 as uuidv4 } from 'uuid'; @@ -17,7 +16,6 @@ const S3Modal: React.FC = ({ hideModal, open }) => { const [statusMessage, setStatusMessage] = useState(''); const [isFocused, setIsFocused] = useState(false); const [isValid, setValid] = useState(false); - const { userCredentials } = useCredentials(); const { setFilesData, model, filesData } = useFileContext(); const reset = () => { @@ -62,7 +60,6 @@ const S3Modal: React.FC = ({ hideModal, open }) => { setStatusMessage('Scanning...'); const apiResponse = await urlScanAPI({ urlParam: url.trim(), - userCredentials: userCredentials as UserCredentials, model: model, accessKey: accessKey.trim(), secretKey: secretKey.trim(), diff --git a/frontend/src/components/DataSources/GCS/GCSModal.tsx b/frontend/src/components/DataSources/GCS/GCSModal.tsx index b8b735735..a0a406ceb 100644 --- a/frontend/src/components/DataSources/GCS/GCSModal.tsx +++ b/frontend/src/components/DataSources/GCS/GCSModal.tsx @@ -1,6 +1,5 @@ import { TextInput } from '@neo4j-ndl/react'; import { useCallback, useState } from 'react'; -import { useCredentials } from '../../../context/UserCredentials'; import { useFileContext } from '../../../context/UsersFiles'; import { urlScanAPI } from '../../../services/URLScan'; import { CustomFileBase, GCSModalProps, fileName, nonoautherror } from '../../../types'; @@ -17,7 +16,6 @@ const GCSModal: React.FC = ({ hideModal, open, openGCSModal }) => const [projectId, setProjectId] = useState(''); const [status, setStatus] = useState<'unknown' | 'success' | 'info' | 'warning' | 'danger'>('unknown'); const [statusMessage, setStatusMessage] = useState(''); - const { userCredentials } = useCredentials(); const { showAlert } = useAlertContext(); const { setFilesData, model, filesData } = useFileContext(); @@ -54,7 +52,6 @@ const GCSModal: React.FC = ({ hideModal, open, openGCSModal }) => setStatusMessage('Loading...'); openGCSModal(); const apiResponse = await urlScanAPI({ - userCredentials, model, accessKey: '', secretKey: '', diff --git a/frontend/src/components/DataSources/Local/DropZone.tsx b/frontend/src/components/DataSources/Local/DropZone.tsx index 4a5d92efe..53f8962f4 100644 --- a/frontend/src/components/DataSources/Local/DropZone.tsx +++ b/frontend/src/components/DataSources/Local/DropZone.tsx @@ -4,7 +4,7 @@ import Loader from '../../../utils/Loader'; import { v4 as uuidv4 } from 'uuid'; import { useCredentials } from '../../../context/UserCredentials'; import { useFileContext } from '../../../context/UsersFiles'; -import { CustomFile, CustomFileBase, UserCredentials } from '../../../types'; +import { CustomFile, CustomFileBase } from '../../../types'; import { buttonCaptions, chunkSize } from '../../../utils/Constants'; import { InformationCircleIconOutline } from '@neo4j-ndl/react/icons'; import { IconButtonWithToolTip } from '../../UI/IconButtonToolTip'; @@ -117,14 +117,7 @@ const DropZone: FunctionComponent = () => { }) ); try { - const apiResponse = await uploadAPI( - chunk, - userCredentials as UserCredentials, - model, - chunkNumber, - totalChunks, - file.name - ); + const apiResponse = await uploadAPI(chunk, model, chunkNumber, totalChunks, file.name); if (apiResponse?.status === 'Failed') { throw new Error(`message:${apiResponse.data.message},fileName:${apiResponse.data.file_name}`); } else { diff --git a/frontend/src/components/DataSources/Local/DropZoneForSmallLayouts.tsx b/frontend/src/components/DataSources/Local/DropZoneForSmallLayouts.tsx index 2305a614e..16dc55335 100644 --- a/frontend/src/components/DataSources/Local/DropZoneForSmallLayouts.tsx +++ b/frontend/src/components/DataSources/Local/DropZoneForSmallLayouts.tsx @@ -3,7 +3,7 @@ import { useDropzone } from 'react-dropzone'; import { useFileContext } from '../../../context/UsersFiles'; import { useEffect, useState } from 'react'; import { useCredentials } from '../../../context/UserCredentials'; -import { CustomFile, CustomFileBase, UserCredentials } from '../../../types'; +import { CustomFile, CustomFileBase } from '../../../types'; import { chunkSize } from '../../../utils/Constants'; import { uploadAPI } from '../../../utils/FileAPI'; import { v4 as uuidv4 } from 'uuid'; @@ -48,14 +48,7 @@ export default function DropZoneForSmallLayouts() { }) ); try { - const apiResponse = await uploadAPI( - chunk, - userCredentials as UserCredentials, - model, - chunkNumber, - totalChunks, - file.name - ); + const apiResponse = await uploadAPI(chunk, model, chunkNumber, totalChunks, file.name); if (apiResponse?.status === 'Failed') { throw new Error(`message:${apiResponse.data.message},fileName:${apiResponse.data.file_name}`); } else { diff --git a/frontend/src/components/Graph/GraphViewModal.tsx b/frontend/src/components/Graph/GraphViewModal.tsx index 97a55144b..3ea256be7 100644 --- a/frontend/src/components/Graph/GraphViewModal.tsx +++ b/frontend/src/components/Graph/GraphViewModal.tsx @@ -9,7 +9,6 @@ import { GraphType, GraphViewModalProps, Scheme, - UserCredentials, } from '../../types'; import { InteractiveNvlWrapper } from '@neo4j-nvl/react'; import NVL from '@neo4j-nvl/base'; @@ -114,11 +113,10 @@ const GraphViewModal: React.FunctionComponent = ({ const nodeRelationshipData = viewPoint === graphLabels.showGraphView ? await graphQueryAPI( - userCredentials as UserCredentials, graphQuery, selectedRows?.map((f) => f.name) ) - : await graphQueryAPI(userCredentials as UserCredentials, graphQuery, [inspectedName ?? '']); + : await graphQueryAPI(graphQuery, [inspectedName ?? '']); return nodeRelationshipData; } catch (error: any) { console.log(error); diff --git a/frontend/src/components/Layout/PageLayout.tsx b/frontend/src/components/Layout/PageLayout.tsx index 4c2f1c1e8..f92ddc77c 100644 --- a/frontend/src/components/Layout/PageLayout.tsx +++ b/frontend/src/components/Layout/PageLayout.tsx @@ -15,6 +15,8 @@ import FallBackDialog from '../UI/FallBackDialog'; import { envConnectionAPI } from '../../services/ConnectAPI'; import { healthStatus } from '../../services/HealthStatus'; import { useNavigate } from 'react-router'; +import { useAuth0 } from '@auth0/auth0-react'; +import { createDefaultFormData } from '../../API/Index'; const ConnectionModal = lazy(() => import('../Popups/ConnectionModal/ConnectionModal')); @@ -35,6 +37,8 @@ const PageLayout: React.FC = () => { const [shows3Modal, toggleS3Modal] = useReducer((s) => !s, false); const [showGCSModal, toggleGCSModal] = useReducer((s) => !s, false); const [showGenericModal, toggleGenericModal] = useReducer((s) => !s, false); + const { user, isAuthenticated } = useAuth0(); + const navigate = useNavigate(); const toggleLeftDrawer = () => { if (isLargeDesktop) { @@ -83,6 +87,7 @@ const PageLayout: React.FC = () => { }; const setUserCredentialsLocally = (credentials: any) => { setUserCredentials(credentials); + createDefaultFormData(credentials); setIsGCSActive(credentials.isGCSActive ?? false); setGdsActive(credentials.isgdsActive); setIsReadOnlyUser(credentials.isReadonlyUser); @@ -99,6 +104,7 @@ const PageLayout: React.FC = () => { isgdsActive: credentials.isgdsActive, isGCSActive: credentials.isGCSActive, chunksTobeProcess: credentials.chunksTobeProcess, + email: credentials.email, }) ); }; @@ -111,12 +117,15 @@ const PageLayout: React.FC = () => { try { const parsedConnection = JSON.parse(neo4jConnection); if (parsedConnection.uri && parsedConnection.user && parsedConnection.password && parsedConnection.database) { - setUserCredentials({ + const credentials = { uri: parsedConnection.uri, userName: parsedConnection.user, password: atob(parsedConnection.password), database: parsedConnection.database, - }); + email: parsedConnection.email, + }; + setUserCredentials(credentials); + createDefaultFormData(credentials); setGdsActive(parsedConnection.isgdsActive); setIsReadOnlyUser(parsedConnection.isReadOnlyUser); setIsGCSActive(parsedConnection.isGCSActive); @@ -162,6 +171,7 @@ const PageLayout: React.FC = () => { isgdsActive: connectionData.data.gds_status, isGCSActive: connectionData?.data?.gcs_file_cache === 'True', chunksTobeProcess: parseInt(connectionData.data.chunk_to_be_created), + email: user?.email ?? '', }; setChunksToBeProces(envCredentials.chunksTobeProcess); setIsGCSActive(envCredentials.isGCSActive); @@ -200,7 +210,7 @@ const PageLayout: React.FC = () => { } } initializeConnection(); - }, []); + }, [isAuthenticated]); const deleteOnClick = async () => { try { diff --git a/frontend/src/components/Popups/ConnectionModal/ConnectionModal.tsx b/frontend/src/components/Popups/ConnectionModal/ConnectionModal.tsx index 92241d8bc..27078f307 100644 --- a/frontend/src/components/Popups/ConnectionModal/ConnectionModal.tsx +++ b/frontend/src/components/Popups/ConnectionModal/ConnectionModal.tsx @@ -7,6 +7,8 @@ import { buttonCaptions } from '../../../utils/Constants'; import { createVectorIndex } from '../../../services/vectorIndexCreation'; import { ConnectionModalProps, Message, UserCredentials } from '../../../types'; import VectorIndexMisMatchAlert from './VectorIndexMisMatchAlert'; +import { useAuth0 } from '@auth0/auth0-react'; +import { createDefaultFormData } from '../../../API/Index'; export default function ConnectionModal({ open, @@ -41,6 +43,8 @@ export default function ConnectionModal({ const [username, setUsername] = useState(initialusername ?? 'neo4j'); const [password, setPassword] = useState(''); const [connectionMessage, setMessage] = useState({ type: 'unknown', content: '' }); + const { user } = useAuth0(); + const { setUserCredentials, userCredentials, @@ -79,7 +83,7 @@ export default function ConnectionModal({ if (usercredential != null && Object.values(usercredential).length) { try { setVectorIndexLoading(true); - const response = await createVectorIndex(usercredential as UserCredentials, isNewVectorIndex); + const response = await createVectorIndex(isNewVectorIndex); setVectorIndexLoading(false); if (response.data.status === 'Failed') { throw new Error(response.data.error); @@ -212,13 +216,21 @@ export default function ConnectionModal({ setIsLoading(false); }; - const submitConnection = async () => { + const submitConnection = async (email: string) => { const connectionURI = `${protocol}://${URI}${URI.split(':')[1] ? '' : `:${port}`}`; - const credential = { uri: connectionURI, userName: username, password: password, database: database, port: port }; + const credential = { + uri: connectionURI, + userName: username, + password: password, + database: database, + port: port, + email, + }; setUserCredentials(credential); + createDefaultFormData(credential); setIsLoading(true); try { - const response = await connectAPI(connectionURI, username, password, database); + const response = await connectAPI(); setIsLoading(false); if (response?.data?.status !== 'Success') { throw new Error(response.data.error); @@ -243,6 +255,7 @@ export default function ConnectionModal({ isReadOnlyUser, isGCSActive, chunksTobeProcess, + email: user?.email ?? '', }) ); setUserDbVectorIndex(response.data.data.db_vector_dimension); @@ -310,23 +323,24 @@ export default function ConnectionModal({ setMessage({ type: 'unknown', content: '' }); }, []); - const handleKeyPress = (e: React.KeyboardEvent, nextRef?: React.RefObject) => { - if (e.code === 'Enter') { - e.preventDefault(); - // @ts-ignore - const { form } = e.target; - if (form) { - const index = Array.prototype.indexOf.call(form, e.target); - if (index + 1 < form.elements.length) { - form.elements[index + 1].focus(); + const handleKeyPress = + (email: string) => (e: React.KeyboardEvent, nextRef?: React.RefObject) => { + if (e.code === 'Enter') { + e.preventDefault(); + // @ts-ignore + const { form } = e.target; + if (form) { + const index = Array.prototype.indexOf.call(form, e.target); + if (index + 1 < form.elements.length) { + form.elements[index + 1].focus(); + } else { + submitConnection(email); + } } else { - submitConnection(); + nextRef?.current?.focus(); } - } else { - nextRef?.current?.focus(); } - } - }; + }; const isDisabled = useMemo(() => !username || !URI || !password, [username, URI, password]); @@ -413,7 +427,7 @@ export default function ConnectionModal({ id: 'url', autoFocus: true, onPaste: (e) => handleHostPasteChange(e), - onKeyDown: (e) => handleKeyPress(e, databaseRef), + onKeyDown: (e) => handleKeyPress(user?.email ?? '')(e, databaseRef), 'aria-label': 'Connection URI', }} value={URI} @@ -429,7 +443,7 @@ export default function ConnectionModal({ ref={databaseRef} htmlAttributes={{ id: 'database', - onKeyDown: handleKeyPress, + onKeyDown: handleKeyPress(user?.email ?? ''), 'aria-label': 'Database', placeholder: 'neo4j', }} @@ -447,7 +461,7 @@ export default function ConnectionModal({ ref={userNameRef} htmlAttributes={{ id: 'username', - onKeyDown: handleKeyPress, + onKeyDown: handleKeyPress(user?.email ?? ''), 'aria-label': 'Username', placeholder: 'neo4j', }} @@ -463,7 +477,7 @@ export default function ConnectionModal({ ref={passwordRef} htmlAttributes={{ id: 'password', - onKeyDown: handleKeyPress, + onKeyDown: handleKeyPress(user?.email ?? ''), type: 'password', 'aria-label': 'Password', placeholder: 'password', @@ -482,12 +496,12 @@ export default function ConnectionModal({