######################################################### IMPORTS ################################################################################################################################# from __future__ import print_function from flask import Flask, render_template,request,flash , json, url_for,g , redirect , jsonify , send_file ,make_response import json import fitz from PIL import Image import cv2 import numpy as np import pilecaps_adr import base64 from db import dropbox_connect import cv2 import pandas as pd import time from io import BytesIO, StringIO import urllib import tempfile from flask import Flask, Response from werkzeug.wsgi import wrap_file import tameem3_2 import pypdfium2 as pdfium from urllib.parse import urlparse import re import pixelconversion import tameem2_1 import io from urllib.parse import unquote import API import MC_Templates_API import tsadropboxretrieval import doc_search import google_sheet_Legend import dxf__omar3_2 import requests import google_sheet_to_xml from threading import Thread import mainDBAlaa import datetime import doors_fasterrcnn import deploying_3_3 import Doors_Schedule import Code_2_7 import Counting_Columns_2_1 # import Find_Hyperlinking_text import ezdxf import Azure_api from flask import Flask, render_template, session, redirect, url_for from flask_session import Session # Capital "S" import os, traceback from werkzeug.utils import secure_filename import Legend_Detection ######################################################### FLASK APP ################################################################################################################################# app = Flask(__name__) # Configure Flask-Session for server-side session storage app.config["SESSION_TYPE"] = "filesystem" app.config["SESSION_PERMANENT"] = False app.config["SESSION_FILE_DIR"] = "./flask_session_files" app.secret_key = "your_secret_key" # Initialize Flask-Session sess = Session() sess.init_app(app) ######################################################### GLOBAL VARIABLES ################################################################################################################################# global colorsused global pdflink # Global cache to store last known tables cached_tables = { "projects": None, "parts": None, "sections": None } global hatched_areas2_7 # For 2.7 ######################################################### MAIN ERROR MESSAGE FUNCTION ################################################################################################################################# def log_error(message, issue_type="backend"): filename = os.path.basename(__file__) # Assign contact based on filename if filename.startswith(('2.6', '2.8', '2.1')): contactName = 'Tameem' elif filename.startswith(('2.7', '3.2', '3.3')): contactName = 'Omar' else: contactName = 'Marthe' # Define issue category if issue_type == "connection": issue_msg = "Connection issue detected" elif issue_type == "frontend": issue_msg = "Frontend issue detected" else: issue_msg = "Backend error detected" error_msg = f"{issue_msg}. {message}. Please contact {contactName} from the ADR Team." print(error_msg) return error_msg ######################################################### GUI RENDER ################################################################################################################################# @app.route("/", methods=["GET", "POST"]) def getInfotoMeasure(): try: return render_template("gui2.html") except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 ######################################################### PASSWORD REDIRECTION ################################################################################################################################# @app.route("/password", methods=["GET", "POST"]) def password_page(): try: return render_template("gui2.html") except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 @app.route("/check_password", methods=["POST"]) def check_password(): try: password = request.form.get("password") correct_password = "c900" if password == correct_password: session["authenticated"] = True return jsonify({"authenticated": True}), 200 else: return jsonify({"authenticated": False}), 200 except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 ######################################################### MAIN GUI PAGE ################################################################################################################################# @app.route("/mainGUI", methods=["GET", "POST"]) def main_gui(): try: if "authenticated" not in session or not session["authenticated"]: return redirect(url_for("password_page")) return render_template("proposed-GUI.html") except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 @app.route("/measurementConsole",methods=["GET", "POST"]) def measurementConsoleFn(): try: return render_template("proposed-GUI.html") except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 ######################################################### WORD SEARCH ################################################################################################################################# @app.route('/WordSearch',methods=["GET", "POST"]) def searchDocument(): return render_template('wordSearch.html') @app.route("/WordSearch",methods=["GET", "POST"]) def getInfo2toMeasure(): try: # API.AppendtablestoSheets() return render_template("wordSearch.html") except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 @app.route('/searchInDocs',methods=["GET", "POST"]) def getSearchinDocs(): try: arr=[] values = request.get_json() keyword=values.get('keyword') listpfProjs=values.get('listofprojs') print(keyword,listpfProjs) df,img_list=doc_search.search_docs(keyword,listpfProjs) for img in img_list: _, buffer = cv2.imencode('.png', img) arr.append(base64.b64encode(buffer).decode('utf-8')) return jsonify([df.to_html(index=False, escape=False),arr]) except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 @app.route('/searchInFolder',methods=["GET", "POST"]) def getSearchinFolder(): try: arr=[] values = request.get_json() keyword=values.get('keyword') projname=values.get('ProjectName') df,img_list=doc_search.slow_search(keyword=keyword,project=projname) for img in img_list: _, buffer = cv2.imencode('.png', img) arr.append(base64.b64encode(buffer).decode('utf-8')) return jsonify([df.to_html(index=False, escape=False),arr]) except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 #get sunburst from doc_search - NOT USED @app.route('/getsunburst',methods=["GET", "POST"]) def getSunburst(): try: # df=tsadropboxretrieval.GetParquetDF() tree=doc_search.prepare_sunburst() return jsonify(tree.to_dict()) except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 ######################################################### TESTING ROUTE ################################################################################################################################# @app.route('/test') def test_route(): try: # simulate an error x = 10 / 0 return jsonify({"result": x}) except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 ######################################################### PROJECT NAMES RETRIEVAL ################################################################################################################################# @app.route('/getprojectnames/', methods=['GET']) def getprjnamesfromTestAPI(): try: prjnames, prjids = API.getPrjNames() # Save in memory global cached_tables cached_tables["projects"] = pd.DataFrame({ "ProjectName": prjnames, "ProjectId": prjids }) return jsonify([prjnames, prjids]) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 # return Response(generate_progressPrjnames(), content_type='text/event-stream') ######################################################### PROJECT PARTS RETRIEVAL ################################################################################################################################# @app.route('/getprojectparts/', methods=['GET']) def getprjpartsfromTestAPI(jsdata): try: prjparts, partsIds = API.getprjParts(jsdata) global cached_tables df = pd.DataFrame({"ProjectPart": prjparts, "ProjectPartId": partsIds, "ProjectId": [int(jsdata)] * len(prjparts)}) cached_tables["parts"] = df return jsonify([prjparts, partsIds]) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### PROJECT SECTIONS RETRIEVAL ################################################################################################################################# @app.route('/getprojectsections/', methods=['GET']) def getprjSectionsfromTestAPI(jsdata): try: data = json.loads(jsdata) if data[0] == 'testing': sections = API.getprjSections() project_id = data[0] project_part_id = None # No second parameter in this case else: # Expecting 2 values project_id = data[0] project_part_id = data[1] if len(data) > 1 else None sections = API.getprjSections(project_id, project_part_id) global cached_tables df = pd.DataFrame({ "ProjectSection": sections, "ProjectId": [project_id] * len(sections), "ProjectPartId": [project_part_id] * len(sections) }) cached_tables["sections"] = df return jsonify(sections) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### PROJECT PDF NAMES RETRIEVAL ################################################################################################################################# @app.route('/getmethod/', methods=['GET']) def get_javascript_data(jsdata): progress_updates = [] # Shared list to store progress def generate_progress(): try: # raise ConnectionError("Failed to reach external service") yield f"data: 5\n\n" # Initial progress yield f"data: 10\n\n" # Initial progress # Call retrieveProjects and pass a callback to update the shared list documentsToMeasure, RelevantDocuments, extracted_path = tsadropboxretrieval.retrieveProjects( jsdata, progress_callback=lambda p: progress_updates.append(p) ) # Continuously yield progress updates from the shared list while progress_updates: progress = progress_updates.pop(0) # Get the next progress value yield f"data: {progress}\n\n" # Final progress and result yield f"data: 100\n\n" result = json.dumps([documentsToMeasure, RelevantDocuments, extracted_path]) yield f"data: {result}\n\n" except (ConnectionError, TimeoutError) as e: # Use your log_error function for connection issues error_msg = log_error(str(e), issue_type="connection") # Send it as SSE custom event yield f"event:error\ndata:{json.dumps({'error': error_msg})}\n\n" except Exception: # Any other backend error error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") # Send it as SSE custom event yield f"event:error\ndata:{json.dumps({'error': error_msg})}\n\n" return Response(generate_progress(), content_type='text/event-stream') #--------------------------------------------------------------- ######################################################### TABLE DETECTION ################################################################################################################################# @app.route('/tableDetection',methods=["GET", "POST"]) def TableDetection(): try: return render_template('tableDetection.html') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #####################not added in gui yettt @app.route('/savedetectedtables/',methods=["POST"]) def table(): try: # 1. Get PDF bytes from Dropbox tt = eval(request.form.get('answers')) # consider json.loads instead of eval print("Value of tt = ",tt) print("Value of tt[0] = ",tt[0]) pdflist=[] pdfnames=[] if tt[0].startswith('http'): pdf_path=tt[0] if pdf_path and ('http' in pdf_path or 'dropbox' in pdf_path): pdf_path = pdf_path.replace('dl=0', 'dl=1') response = requests.get(pdf_path) pdf_content = BytesIO(response.content) if not pdf_content: raise ValueError("No valid PDF content found.") excel_io = Azure_api.detect_tables([response.content],['pdfname.pdf']) else: for i in range(len(tt[0])): print("Value of tt[0][i] = ",tt[0][i]) pdfpath, _ = tsadropboxretrieval.getPathtoPDF_File(nameofPDF=tt[0][i]) dbx = tsadropboxretrieval.ADR_Access_DropboxTeam('user') _, res = dbx.files_download(path=pdfpath) pdf_bytes = res.content pdflist.append(pdf_bytes) pdfnames.append(pdfpath) # 2. Generate in-memory Excel print("pdflist = ",pdflist) excel_io = Azure_api.detect_tables(pdflist,pdfnames) # 3. Send it as a downloadable .xlsx if excel_io is None: # No tables → return a JSON error (or another response of your choice) return ('', 204) return send_file( excel_io, as_attachment=True, download_name='detected_tables.xlsx', mimetype='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### TESTING MEASUREMENT USING LINKS ################################################################################################################################# @app.route('/TestingMeasurement',methods=["GET", "POST"]) def TestingMeasurement(): try: return render_template('TestingMeasurement.html') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### FIND FUNCTIONS ################################################################################################################################# #####################not added in gui yettt @app.route('/FindInitialMarkups',methods=["GET", "POST"]) def FindInitialMarkups(): try: return render_template('FindInitialMarkups.html') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 pdf_content = None pageNumTextFound = 0 BASE_URL = "https://marthee-nbslink.hf.space" # Hugging Face Spaces base URL # @app.route("/", methods=["GET", "POST"]) # def thismain(): # print('ayhaga') # return render_template("gui.html") @app.route('/view-pdf', methods=['GET']) def download_pdf(): try: # Manually parse the query parameters full_query_string = request.query_string.decode() # Get raw query string parsed_params = urllib.parse.parse_qs(full_query_string) # Parse it # Extract pdfLink and keyword manually pdf_link = parsed_params.get('pdfLink', [None])[0] keyword = parsed_params.get('keyword', [None])[0] if not pdf_link or not keyword: return "Missing required parameters.", 400 # Decode the extracted values pdf_link = urllib.parse.unquote(pdf_link) keyword = urllib.parse.unquote(keyword) # If the keyword is a JSON string, convert it back to a list try: keyword = json.loads(keyword) except json.JSONDecodeError: keyword = [keyword] # Treat it as a single keyword if not JSON print("Extracted PDF Link:", pdf_link) print("Extracted Keywords:", keyword) createDF=False pdf_content = Find_Hyperlinking_text.annotate_text_from_pdf([pdf_link], keyword)[0] if pdf_content is None: return "PDF content not found.", 404 pdf_bytes = BytesIO(pdf_content) return send_file( pdf_bytes, mimetype='application/pdf', as_attachment=False, download_name=f"annotated_page_{pageNumTextFound}.pdf" ) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route('/api/process-data', methods=['POST']) def receive_pdf_data(): try: global pdf_content, pageNumTextFound # Get PDF link and keyword from finddata() pdfLink, keyword = finddata() if not pdfLink or not keyword: return jsonify({"error": "Both 'pdfLink' and 'keyword' must be provided."}), 400 try: print(pdfLink, keyword) pdfbytes, pdf_document , df ,tablepdfoutput= Find_Hyperlinking_text.annotate_text_from_pdf([pdfLink], keyword) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') # Get metadata using the shared link metadata = dbxTeam.sharing_get_shared_link_metadata(pdfLink) dbPath='/TSA JOBS/ADR Test/FIND/' pdflink= tsadropboxretrieval.uploadanyFile(doc=pdf_document,path=dbPath,pdfname=metadata.name) #doc=doc,pdfname=path,pdfpath=pdfpath+'Measured Plan/ print('LINKS0',pdflink) dbPath='/TSA JOBS/ADR Test/FIND/' tablepdfLink=tsadropboxretrieval.uploadanyFile(doc=tablepdfoutput,path=dbPath,pdfname=metadata.name.rsplit(".pdf", 1)[0] +' Markup Summary'+'.pdf') print(f"PDF successfully uploaded to Dropbox at") print('LINKS1',tablepdfLink) return jsonify({ "message": "PDF processed successfully.", "PDF_MarkedUp": pdflink, 'Table_PDF_Markup_Summary': tablepdfLink }) except Exception as e: return jsonify({"error": str(e)}), 500 except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 def finddata(): pdfLink = 'https://www.dropbox.com/scl/fi/hnp4mqigb51a5kp89kgfa/00801-ARC-20-ZZ-S-A-0002.pdf?rlkey=45abeoebzqw4qwnslnei6dkd6&st=m4yrcjm2&dl=1' keyword = ['115 INTEGRATED MRI ROOM LININGS', '310 ACCURACY'] return pdfLink, keyword ######################################################### LEGEND DIRECTORY ################################################################################################################################# @app.route('/legends',methods=["GET", "POST"]) def legendDirectory(): try: return render_template('legendDirectory.html') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #Google sheet links #####################not added in gui yettt @app.route('/getdrivelinks/',methods=["GET", "POST"]) def getlinkscreated(jsdata): try: spreadsheet_service,drive_service,gc= google_sheet_Legend.authorizeLegend() ids=gc.spreadsheet_ids() titles=gc.spreadsheet_titles() allpaths=[] print('HEREEEEEEEEEE') # for title in titles: for i in range(0,len(titles)): print('titles',titles[i]) if not (titles[i].startswith('API') or (titles[i].startswith('Dropbox')) ) : ws=gc.open(titles[i]) path_metadata = ws.get_developer_metadata('path') print(path_metadata) allpaths.append([titles[i], ws.get_developer_metadata('path')[0].value , drive_service.files().get(fileId=ids[i],fields="createdTime, modifiedTime").execute() ,ids[i] ]) return jsonify(allpaths) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### MC NAMES RETRIEVAL ################################################################################################################################# @app.route('/RetrieveMCTNames/',methods=['GET']) def CallAPIforMCTNames(): # print(jsdata) try: DictionaryOfTemplates=MC_Templates_API.RetrieveMC_Templates_API() # jsdata=jsdata.replace('"', '') print('here') return jsonify(DictionaryOfTemplates) #[str(jsdata).lower()] except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ ######################################################### HELPER FUNCTIONS: MARTHE (1.0) ################################################################################################################################# #Hex value to RGB value def hexRGB(color): try: color=color.lstrip('#') color= tuple(int(color[i:i+2], 16) for i in (0, 2, 4)) #hex to rgb color=list(color) #rgb to bgr return color except Exception as e: # capture traceback for more detail error_details = traceback.format_exc() error_msg = log_error(error_details) return jsonify({"error": error_msg}), 500 #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ ######################################################### GUI: UPDATE IMAGE PREVIEW ################################################################################################################################# @app.route('/updatepreviewimg/',methods=["GET", "POST"]) def getfromdropboxImg(jsdata): try: # vv = eval(request.form.get('pdflink')) pdfpath='' # jsdata=jsdata.replace('"', '') jsdata=eval(jsdata) print('pdfnameeee==',jsdata) dbPath='/TSA JOBS/ADR Test/'+jsdata[0][0]+'/'+jsdata[0][1]+'/'+jsdata[0][2]+'/Measured Plan/'+jsdata[1] print(dbPath) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=dbPath) data = res.content doc = fitz.open("pdf",data) page=doc[0] pix = page.get_pixmap() # render page to an image pl=Image.frombytes('RGB', [pix.width,pix.height],pix.samples) img=np.array(pl) img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) _, buffer = cv2.imencode('.png', img) return base64.b64encode(buffer).decode('utf-8') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### MAIN FUNCTION WHEN USER CLICKS MEASURE BUTTON ################################################################################################################################# @app.route('/savebase64Img/',methods=["POST"]) def stringToRGB(): try: vv = eval(request.form.get('answers')) # vv = json.loads(answers) # JSON null -> Python None, true->True, false->False # print("vv for 2.7=", vv) if type(vv[0]) == list: vv[0] = vv[0][0] if vv[0].startswith('http'): if ( vv[5].startswith('3.2') or vv[5].startswith('3.3') or vv[5].startswith('2.7')) : print('3.2 section') # pdflink=vv[0] # encoded_url = request.args.get('url') link = urllib.parse.unquote(vv[0].strip('"')) if link and ('http' in link or 'dropbox' in link): if 'dl=0' in link: link = link.replace('dl=0', 'dl=1') elif 'www.dropbox.com' in link and '?dl=1' not in link: link += '?dl=1' response = requests.get(link) pdf_content = BytesIO(response.content) if not pdf_content: raise ValueError("No valid PDF content found.") if 'file' not in request.files: print('error, No file part in the request') else: file = request.files['file'] print('file done, measuring') arr=measureproject(result=vv,dxffile=file,pdf_content=pdf_content) return jsonify(arr) if vv[5].startswith('2.8') or vv[5].startswith('2.6'): # or vv[5].startswith('2.1') #print(f"el mawgood fe vv[0]: {vv[0]}") # arr_s = [] # dataDocs = [] # pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF= str(v)) link = urllib.parse.unquote(vv[0].strip('"')) if link and ('http' in link or 'dropbox' in link): if 'dl=0' in link: link = link.replace('dl=0', 'dl=1') elif 'www.dropbox.com' in link and '?dl=1' not in link: link += '?dl=1' response = requests.get(link) pdf_content = BytesIO(response.content) doc = fitz.open(stream=pdf_content, filetype="pdf") # doc = fitz.open("pdf",dataDoc) page=doc[0] if page.rotation!=0: page.set_rotation(0) pix = page.get_pixmap(dpi=300) # render page to an image pl=Image.frombytes('RGB', [pix.width,pix.height],pix.samples) if 'file' not in request.files: print('error, No file part in the request') else: csvfile = request.files['csvfile'] print('csvfile done, measuring') arr=measureproject(result=vv,img=pl,pdf_content=pdf_content,csvfile=csvfile) else: if ( vv[5][2].startswith('3.2') or vv[5][2].startswith('3.3') or vv[5][2].startswith('2.7')) : print('3.2 section') pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF=vv[0]) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=pdfpath) dataDoc = res.content if 'file' not in request.files: print('error, No file part in the request') else: file = request.files['file'] print('file done, measuring') arr=measureproject(vv,dataDoc,0,file) return jsonify(arr) if vv[5][2].startswith('1.0'): opencv_img,dataDoc = plan2img( str(vv[0]) ) if vv[1]==220: imgdata = base64.b64decode(vv[6]) img=Image.open(io.BytesIO(imgdata)) opencv_img= cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) arr=measureproject(vv,dataDoc,opencv_img) if vv[5][2].startswith('2.1'): #vv = eval(request.form.get('answers')) #print(f"el mawgood fe vv[0] fe 2.1: {vv[0]}") #print(f"el mawgood fe vv[6] fe 2.1: {vv[6]}") #print(f"el mawgood fe vv fe 2.1: {vv}") #answers = json.loads(request.form['answers']) data_url = vv[6] # "data:image/png;base64,..." header, b64 = data_url.split(',', 1) segmented_img_bytes = base64.b64decode(b64) pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF= str(vv[0])) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=pdfpath) dataDoc = res.content opencv_img,_ = convert2img2_1(str(vv[0])) #imgdata = base64.b64decode(vv[6]) #img=Image.open(io.BytesIO(imgdata)) # opencv_img= cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) arr=measureproject(vv,dataDoc,segmented_img_bytes) if vv[5][2].startswith('2.8') or vv[5][2].startswith('2.6'): vv = eval(request.form.get('answers')) print(f"el mawgood fe vv[0]: {vv[0]}") arr_s = [] dataDocs = [] pls = [] for v in vv[0]: pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF= str(v)) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=pdfpath) dataDoc = res.content dataDocs.append(dataDoc) doc = fitz.open("pdf",dataDoc) page=doc[0] if page.rotation!=0: page.set_rotation(0) pix = page.get_pixmap(dpi=300) # render page to an image pl=Image.frombytes('RGB', [pix.width,pix.height],pix.samples) pls.append(pl) arr=measureproject(vv,dataDocs,pls) # ---- CSV FILE ----# #if 'file' not in request.files: # print('error, No file part in the request') # arr=measureproject(vv,dataDocs,pls) #else: # csvfile = request.files['csvfile'] # print('csvfile done, measuring') #arr=measureproject(vv,dataDocs,pls,csvfile=csvfile) #pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF= str(vv[0])) #dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') #md, res =dbxTeam.files_download(path=pdfpath) #dataDoc = res.content #doc = fitz.open("pdf",dataDoc) #page=doc[0] #if page.rotation!=0: # page.set_rotation(0) #pix = page.get_pixmap(dpi=300) # render page to an image #pl=Image.frombytes('RGB', [pix.width,pix.height],pix.samples) #arr=measureproject(vv,dataDoc,pl) return jsonify(arr) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route('/2.1Trial/',methods=["POST"]) def measure2_1(): try: name = request.get_json() result=name.get('allvalues') arr=measureproject(result) return arr except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #MAIN FUNCTION -- calls python code to measure the chosen plan from the interface # @app.route('/projecttomeasure/',methods=["GET","POST"]) def measureproject(result,dataDoc=0,img=0,dxffile=0,pdf_content=0,csvfile=0): try: colorarr=[] global pdflink pdfpath='/' # result = json.loads(jsdata) if pdf_content: section=result[5] pdfpath+='testinglink/' else: section=result[5][2] for word in result[5]: pdfpath+=word +'/' ################################# -1.0- ################################# arr=[] if section.startswith('1.0'): #section value - 1.0 substructure- pile caps for item in result[2]: # item1 ='#'+item c=hexRGB(item) colorarr.append(c) print('RATIOS=',result[3], result[4]) # cv2.imwrite(img,'imgg.png') # global pdflink imgPerimeter1,image_new1,SimilarAreaDictionary , colorsUsed,spreadsheet_url, spreadsheetId,list1, pdflink, areas_Perimeters, namepathArr =pilecaps_adr.drawAllContours(dataDoc,img,result[1],colorarr, result[3], result[4], result[0],pdfpath) _, buffer = cv2.imencode('.png', image_new1) arr=[base64.b64encode(buffer).decode('utf-8'),SimilarAreaDictionary.to_dict(),spreadsheet_url , spreadsheetId,colorsUsed,list1.to_dict(), pdflink, areas_Perimeters, namepathArr] ################################# -3.2- ################################# # elif result[5][2].startswith('3.2'): #section value - 3.2 floor finishes # print('IN HEREEEE 3.2') # dxfpath=dxffile.read() # with tempfile.NamedTemporaryFile(suffix='.dxf', delete=False) as temp_file: # temp_file.write(dxfpath) # temp_filename = temp_file.name # print(temp_filename) # doc,outputimg, SimilarAreaDictionary ,spreadsheetId, spreadsheet_url , namepathArr , list1,hatched_areas=dxf__omar3_2.mainFunctionDrawImgPdf(dataDoc,temp_filename,result[4] , pdfpath,result[0]) # dbPath='/TSA JOBS/ADR Test'+pdfpath+'Measured Plan/' # pdflink= tsadropboxretrieval.uploadanyFile(doc=doc,path=dbPath,pdfname=result[0]) #doc=doc,pdfname=path,pdfpath=pdfpath+'Measured Plan/' # _, buffer = cv2.imencode('.png', outputimg) # arr=[ base64.b64encode(buffer).decode('utf-8'),SimilarAreaDictionary.to_dict(), spreadsheet_url,spreadsheetId,[],list1.to_dict(),pdflink,hatched_areas,namepathArr]# , spreadsheetId, spreadsheet_url , list1.to_dict()] ################################# -3.3 or 3.2- ################################# elif section.startswith('3.3') or section.startswith('3.2'): #section value - 3.2 floor finishes print('code of 3.3 and 3.2') dxfpath=dxffile.read() with tempfile.NamedTemporaryFile(suffix='.dxf', delete=False) as temp_file: temp_file.write(dxfpath) temp_filename = temp_file.name print(temp_filename) CorrectionRatio=result[8] print("result = ",result) SearchArray=result[6] parsed_url = urlparse(result[0]) filename = parsed_url.path.split('/')[-1] print(filename) nameofpdf=filename points_Of_drawing_Canvas=drawonpdf(nameofpdf,result[7]) ########################## points of manual drawing hereee if pdf_content: if section.startswith('3.3'): doc,outputimg, SimilarAreaDictionary ,spreadsheetId, spreadsheet_url , namepathArr , list1,hatched_areas , bax_pretty_xml, column_xml=deploying_3_3.mainFunctionDrawImgPdf(dataDoc,temp_filename,result[4] ,SearchArray,CorrectionRatio,points_Of_drawing_Canvas,pdfpath,result[0],pdf_content) else: doc,outputimg, SimilarAreaDictionary ,spreadsheetId, spreadsheet_url , namepathArr , list1,hatched_areas, bax_pretty_xml, column_xml=dxf__omar3_2.mainFunctionDrawImgPdf(dataDoc,temp_filename,result[4] ,SearchArray,CorrectionRatio,points_Of_drawing_Canvas,pdfpath,result[0],pdf_content) else: if section.startswith('3.3'): doc,outputimg, SimilarAreaDictionary ,spreadsheetId, spreadsheet_url , namepathArr , list1,hatched_areas , bax_pretty_xml, column_xml=deploying_3_3.mainFunctionDrawImgPdf(dataDoc,temp_filename,result[4] ,SearchArray,CorrectionRatio,points_Of_drawing_Canvas,pdfpath,result[0]) else: doc,outputimg, SimilarAreaDictionary ,spreadsheetId, spreadsheet_url , namepathArr , list1,hatched_areas, bax_pretty_xml, column_xml=dxf__omar3_2.mainFunctionDrawImgPdf(dataDoc,temp_filename,result[4] ,SearchArray,CorrectionRatio,points_Of_drawing_Canvas,pdfpath,result[0]) global colorsused colorsused=list(SimilarAreaDictionary['Color']) dbPath='/TSA JOBS/ADR Test'+pdfpath+'Measured Plan/' print(dbPath,result[0]) pdflink= tsadropboxretrieval.uploadanyFile(doc=doc,path=dbPath,pdfname=nameofpdf) _, buffer = cv2.imencode('.png', outputimg) # if section.startswith('3.3'): # arr=[ base64.b64encode(buffer).decode('utf-8'),SimilarAreaDictionary.to_dict(), spreadsheet_url,spreadsheetId,[],list1.to_dict(),pdflink,hatched_areas,namepathArr]#,hatched_areas,namepathArr]# , spreadsheetId, spreadsheet_url , list1.to_dict()] # else: bax_b64 = base64.b64encode(bax_pretty_xml.encode("utf-8")).decode("ascii") #base64.b64encode(bax_pretty_xml).decode("ascii") xml_b64 = base64.b64encode(column_xml.encode("utf-8")).decode("ascii") bax_link= tsadropboxretrieval.upload_string_file(content_str=bax_pretty_xml,filename="baxfile.bax",path=dbPath) xml_link= tsadropboxretrieval.upload_string_file(content_str=column_xml,filename="customCols.xml",path=dbPath) arr=[ base64.b64encode(buffer).decode('utf-8'),SimilarAreaDictionary.to_dict(), spreadsheet_url,spreadsheetId,[],list1.to_dict(),pdflink,hatched_areas,namepathArr ,bax_b64,xml_b64, bax_link,xml_link] ################################# 2.7- ################################# elif section.startswith('2.7') : #section value - 2.7 floor finishes print('code of 2.7') dxfpath=dxffile.read() with tempfile.NamedTemporaryFile(suffix='.dxf', delete=False) as temp_file: temp_file.write(dxfpath) temp_filename = temp_file.name print(temp_filename) CorrectionRatio=result[10] SearchArray=result[6] CollectedColors=result[7] print("CollectedColors in app.py = ",CollectedColors) Thickness=result[8] print("result[9] = ",result[9]) parsed_url = urlparse(result[0]) filename = parsed_url.path.split('/')[-1] print(filename) nameofpdf=filename points_Of_drawing_Canvas=drawonpdf(nameofpdf,result[9]) ########################## points of manual drawing hereee print("result for 2.7 = ",result) print("SearchArray = ",SearchArray) global hatched_areas2_7 if pdf_content: doc,outputimg, SimilarAreaDictionary ,spreadsheetId, spreadsheet_url , namepathArr , list1,hatched_areas,bax_pretty_xml,column_xml=Code_2_7.mainFunctionDrawImgPdf(dataDoc,temp_filename,result[4],SearchArray,CorrectionRatio,CollectedColors,points_Of_drawing_Canvas,Thickness, pdfpath,result[0],pdf_content) else: doc,outputimg, SimilarAreaDictionary ,spreadsheetId, spreadsheet_url , namepathArr , list1,hatched_areas,bax_pretty_xml,column_xml=Code_2_7.mainFunctionDrawImgPdf(dataDoc,temp_filename,result[4],SearchArray,CorrectionRatio,CollectedColors,points_Of_drawing_Canvas,Thickness, pdfpath,result[0]) # global colorsused hatched_areas2_7=hatched_areas colorsused=list(SimilarAreaDictionary['Color']) dbPath='/TSA JOBS/ADR Test'+pdfpath+'Measured Plan/' print(dbPath,result[0]) pdflink= tsadropboxretrieval.uploadanyFile(doc=doc,path=dbPath,pdfname=nameofpdf) #doc=doc,pdfname=path,pdfpath=pdfpath+'Measured Plan/' _, buffer = cv2.imencode('.png', outputimg) bax_b64 = base64.b64encode(bax_pretty_xml.encode("utf-8")).decode("ascii") #base64.b64encode(bax_pretty_xml).decode("ascii") xml_b64 = base64.b64encode(column_xml.encode("utf-8")).decode("ascii") bax_link= tsadropboxretrieval.upload_string_file(content_str=bax_pretty_xml,filename="baxfile.bax",path=dbPath) xml_link= tsadropboxretrieval.upload_string_file(content_str=column_xml,filename="customCols.xml",path=dbPath) arr=[ base64.b64encode(buffer).decode('utf-8'),SimilarAreaDictionary.to_dict(), spreadsheet_url,spreadsheetId,[],list1.to_dict(),pdflink,[],namepathArr,bax_b64,xml_b64, bax_link,xml_link]#,hatched_areas,namepathArr]# , spreadsheetId, spreadsheet_url , list1.to_dict()] # arr=[ base64.b64encode(buffer).decode('utf-8'),SimilarAreaDictionary.to_dict(), spreadsheet_url,spreadsheetId,[],list1.to_dict(),pdflink,hatched_areas,namepathArr]#,hatched_areas,namepathArr]# , spreadsheetId, spreadsheet_url , list1.to_dict()] ################################# -2.8- ################################# elif section.startswith('2.8') or section.startswith('2.6'): #section value - 2.8 floor finishes #vv[0] array of pdf names imgss=[] dpxlinks=[] legendLinks=[] listofmarkups=[] SearchArray=result[7] print('searchhh:',SearchArray) print('csv',csvfile) CSV_UPLOAD_DIR = os.path.join(os.path.dirname(__file__), "uploaded_csv") # annotatedimg,pdf_document,spreadsheet_url, list1 , df_doors=doors_fasterrcnn.main_run(img,dataDoc,'separated_classes_all.pth',result[0],pdfpath, result[4]) #single_double.pth if pdf_content: link = urllib.parse.unquote(result[6].strip('"')) if link and ('http' in link or 'dropbox' in link): if 'dl=0' in link: link = link.replace('dl=0', 'dl=1') elif 'www.dropbox.com' in link and '?dl=1' not in link: link += '?dl=1' response = requests.get(link) pdf_contentSched = BytesIO(response.content) # pdf_contentSched = fitz.open(stream=pdf_contentSched, filetype="pdf") annotatedimgs, pdf_document , list1, repeated_labels , not_found, bax_pretty_xml, column_xml =Doors_Schedule.mainRun(pdf_contentSched, dataDoc, SearchArray,pdf_content,pdf_contentSched) else: sch_csv_pdf = False file_names = result[6] # ["7376....csv", "something.csv"] in CSV mode or PDF names in PDF mode if not file_names: raise ValueError("No schedule files provided in result[6].") first_name = str(file_names[0]).lower() if first_name.endswith(".csv"): # 🔹 CSV MODE # Ensure folder exists os.makedirs(CSV_UPLOAD_DIR, exist_ok=True) # Grab uploaded CSV files from the request # name="csvFilename" from your uploaded_csvs = request.files.getlist("csvFilename") saved_paths = [] for f in uploaded_csvs: if not f.filename: continue safe_name = secure_filename(f.filename) save_path = os.path.join(CSV_UPLOAD_DIR, safe_name) f.save(save_path) saved_paths.append(save_path) annotatedimgs, pdf_document, list1, repeated_labels, not_found, bax_pretty_xml, column_xml = Doors_Schedule.mainRun( saved_paths, # 👉 ["file1.csv", "file2.csv"] dataDoc, SearchArray, sch_csv_pdf ) else: dataDocDoorsSchedule = [] sch_csv_pdf = True for r in result[6]: pdfpathDoors,_=tsadropboxretrieval.getPathtoPDF_File(nameofPDF= r) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, resDoors =dbxTeam.files_download(path=pdfpathDoors) dataDocDoorsSchedule.append(resDoors.content) annotatedimgs, pdf_document , list1, repeated_labels , not_found, bax_pretty_xml, column_xml =Doors_Schedule.mainRun(dataDocDoorsSchedule, dataDoc, SearchArray, sch_csv_pdf) dbPath='/TSA JOBS/ADR Test'+pdfpath+'Measured Plan/' pdflink= tsadropboxretrieval.uploadanyFile(doc=pdf_document,path=dbPath,pdfname="combined_output.pdf") #doc=doc,pdfname=path,pdfpath=pdfpath+'Measured Plan/ repeatedLabelsReturn='' NotFoundReturn='' if len(repeated_labels)>0: repeatedLabelsReturn=repeated_labels if len(not_found)>0: NotFoundReturn=not_found # , spreadsheetId, spreadsheet_url , list1.to_dict()] annotatedimgsBuffered=[] for b in annotatedimgs: _, buffer = cv2.imencode('.png', b) # Convert buffer (ndarray) to bytes and then base64 string b64_str = base64.b64encode(buffer).decode('utf-8') annotatedimgsBuffered.append(b64_str) bax_b64 = base64.b64encode(bax_pretty_xml.encode("utf-8")).decode("ascii") #base64.b64encode(bax_pretty_xml).decode("ascii") xml_b64 = base64.b64encode(column_xml.encode("utf-8")).decode("ascii") dbPath='/TSA JOBS/ADR Test'+pdfpath+'Measured Plan/' bax_link= tsadropboxretrieval.upload_string_file(content_str=bax_pretty_xml,filename="baxfile.bax",path=dbPath) xml_link= tsadropboxretrieval.upload_string_file(content_str=column_xml,filename="customCols.xml",path=dbPath) arr = [ annotatedimgsBuffered, pdflink, list1.to_dict(), str(repeatedLabelsReturn), str(NotFoundReturn), bax_b64, xml_b64, bax_link, xml_link ] ################################# -2.1- ################################# elif section.startswith('2.1'): #section value - 2.8 floor finishes #vv[0] array of pdf names imgss=[] dpxlinks=[] legendLinks=[] listofmarkups=[] data_url = result[6] # "data:image/png;base64,..." header, b64 = data_url.split(',', 1) segmented_img_bytes = base64.b64decode(b64) #annotatedimg,pdf_document,spreadsheet_url, list1 , df_doors = Counting_Columns_2_1.mainfun(dataDoc, segmented_img_bytes) # dbPath='/TSA JOBS/ADR Test'+pdfpath+'Measured Plan/' # pdflink= tsadropboxretrieval.uploadanyFile(doc=pdf_document,path=dbPath,pdfname=result[0]) #doc=doc,pdfname=path,pdfpath=pdfpath+'Measured Plan/ # _, buffer = cv2.imencode('.png', annotatedimg) #arr=[base64.b64encode(buffer).decode('utf-8') ,pdflink,spreadsheet_url,list1.to_dict(), df_doors.to_dict()]# , spreadsheetId, spreadsheet_url , list1.to_dict()] output_dict = Counting_Columns_2_1.mainfun(dataDoc, segmented_img_bytes) arr = output_dict ################################# -2.2- ################################# # elif result[5][2].startswith('2.2'): #section value - 2.2 rc slabs #add here python code # #link (add this to ur code) # pdflink= db.dropbox_upload_file(doc=doc,pdfname=path,pdfpath=pdfpath) # gc,spreadsheet_service,spreadsheetId, spreadsheet_url , namepathArr= pilecaps_adr.legendGoogleSheets(df,plan ,pdfpath) #output img # _, buffer = cv2.imencode('.png', outputimg) #let first result to be the img #return results in arr=[base64.b64encode(buffer).decode('utf-8'),pdflink,spreadsheetId,spreadsheet_url] like the previous sections in the above lines # elif result[5][2].startswith('2.1'): #section value - 2.1 frames # url = tameem2_1.mainfun( result[0], pdfpath) # return jsonify([url]) return arr except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ ######################################################### HELPER FUNCTIONS: MARTHE/OMAR ################################################################################################################################# def drawonpdf(nameofpdf,coords): try: pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF=nameofpdf) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=pdfpath) data = res.content doc = fitz.open("pdf",data) page=doc[0] for shape in coords: if not isinstance(shape, dict): continue points_list = shape.get("coordinates", []) if not isinstance(points_list, list) or len(points_list) < 2: continue # Extract coordinates vertices = [(p["x"], p["y"]) for p in points_list if "x" in p and "y" in p] # Convert to fitz.Point objects and apply derotation points = [fitz.Point(x, y) * page.derotation_matrix for x, y in vertices] # --- 🟢 Use polygon annotation --- if len(points) > 2: annot = page.add_polygon_annot(points) else: annot = page.add_polyline_annot(points) # Style annotation annot.set_colors(stroke=(1, 0, 0)) # red border annot.set_border(width=1) annot.update() # doc.save("output.pdf") return points except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route("/wallsLegend/", methods=["POST"]) def callOmarLegend(): # TEXT DATA nameofPDF = request.form.get("nameofPDF") print('nameofPDF',nameofPDF) groupedValues = json.loads(request.form.get("groupedValues")) print('groupedValues',groupedValues) # FILE (DXF) if "file" not in request.files: return jsonify({"error": "No file received"}), 400 file = request.files["file"] with tempfile.NamedTemporaryFile(suffix=".dxf", delete=False) as temp_file: temp_file.write(file.read()) temp_filename = temp_file.name # Get PDF from Dropbox pdfpath, pdflink = tsadropboxretrieval.getPathtoPDF_File(nameofPDF=nameofPDF) dbxTeam = tsadropboxretrieval.ADR_Access_DropboxTeam("user") md, res = dbxTeam.files_download(path=pdfpath) dataDoc = res.content # Run your legend detection colorsArray = Legend_Detection.Legend_Detection(dataDoc,temp_filename,groupedValues) print('colorsArray',colorsArray) return jsonify(colorsArray) ######################################################### GUI: CANVAS ################################################################################################################################# @app.route("/canvaspdftoimgBackground/",methods=["GET", "POST"]) def pdftoimgCanvas(jsdata): try: img=plan2img(jsdata)[0] _, buffer = cv2.imencode('.png', img) arr=[base64.b64encode(buffer).decode('utf-8') , img.shape[0],img.shape[1]] return jsonify(arr) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route("/canvaspdftoimg/",methods=["GET", "POST"]) def pdftoimgCanvas2(jsdata): try: img=convert2img2_1(jsdata)[0] _, buffer = cv2.imencode('.png', img) arr=[base64.b64encode(buffer).decode('utf-8') , img.shape[0],img.shape[1]] return jsonify(arr) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #pdf to img ######################################################### HELPER FUNCTIONS: MARTHE ################################################################################################################################# def plan2img(nameofpdf): try: pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF=nameofpdf) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=pdfpath) data = res.content doc = fitz.open("pdf",data) page=doc[0] # if page.rotation!=0: # page.set_rotation(0) pix = page.get_pixmap() # render page to an image pl=Image.frombytes('RGB', [pix.width,pix.height],pix.samples) img=np.array(pl) img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) return img ,data except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ ######################################################### HELPER FUNCTIONS: TAMEEM ################################################################################################################################# img_cv2 = None segmented_img = None current_hsv = { 'h_min': 0, 'h_max': 179, 's_min': 0, 's_max': 255, 'v_min': 0, 'v_max': 255 } def convert2img2_1(nameofpdf): try: global img_cv2 pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF=nameofpdf) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=pdfpath) data = res.content pdf = pdfium.PdfDocument(data) page = pdf.get_page(0) pil_image = page.render().to_pil() pl1=np.array(pil_image) img = cv2.cvtColor(pl1, cv2.COLOR_RGB2BGR) img_cv2 = img return img, data except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 def convert2img(path): try: pdf = pdfium.PdfDocument(path) page = pdf.get_page(0) pil_image = page.render().to_pil() pl1=np.array(pil_image) img = cv2.cvtColor(pl1, cv2.COLOR_RGB2BGR) return img except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### FRONTEND ROUTES: TAMEEM ################################################################################################################################# @app.route('/click', methods=['POST']) def click(): try: global img_cv2, current_hsv if img_cv2 is None: return jsonify({'error': 'No image loaded'}), 400 data = request.json x, y = int(data['x']), int(data['y']) b, g, r = img_cv2[y, x] hsv = cv2.cvtColor(np.uint8([[[b, g, r]]]), cv2.COLOR_BGR2HSV)[0][0] h, s, v = hsv.tolist() current_hsv = { 'h_min': h, 'h_max': h, 's_min': s, 's_max':s, 'v_min': v, 'v_max': v } return jsonify({ 'info': f'RGB: ({r}, {g}, {b}) - HSV: ({h}, {s}, {v})', 'hMin': current_hsv['h_min'], 'hMax': current_hsv['h_max'], 'sMin': current_hsv['s_min'], 'sMax': current_hsv['s_max'], 'vMin': current_hsv['v_min'], 'vMax': current_hsv['v_max'] }) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### FRONTEND ROUTES: TAMEEM ################################################################################################################################# @app.route('/update_mask', methods=['POST']) def update_mask(): try: global img_cv2, segmented_img, current_hsv if img_cv2 is None: return jsonify({'error': 'No image uploaded yet'}), 400 data = request.get_json(force=True) or {} current_hsv = { 'h_min': int(data.get('hMin', 0)), 'h_max': int(data.get('hMax', 179)), 's_min': int(data.get('sMin', 0)), 's_max': int(data.get('sMax', 255)), 'v_min': int(data.get('vMin', 0)), 'v_max': int(data.get('vMax', 255)), } hsv = cv2.cvtColor(img_cv2, cv2.COLOR_BGR2HSV) lower = np.array([current_hsv['h_min'], current_hsv['s_min'], current_hsv['v_min']], dtype=np.uint8) upper = np.array([current_hsv['h_max'], current_hsv['s_max'], current_hsv['v_max']], dtype=np.uint8) mask = cv2.inRange(hsv, lower, upper) segmented_img = cv2.bitwise_and(img_cv2, img_cv2, mask=mask) # Encode segmented image to PNG -> base64 ok, buf = cv2.imencode('.png', segmented_img) if not ok: return jsonify({'error': 'PNG encode failed'}), 500 b64 = base64.b64encode(buf).decode('utf-8') data_url = 'data:image/png;base64,' + b64 return jsonify({ 'image_data': data_url }) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### FRONTEND ROUTES: TAMEEM ################################################################################################################################# @app.route('/img_to_click', methods=['POST']) def img_to_click(blob): try: pdf = fitz.open("pdf", blob) page = pdf.get_page(0) pil_image = page.render().to_pil() pl1=np.array(pil_image) img = cv2.cvtColor(pl1, cv2.COLOR_RGB2BGR) _, buffer = cv2.imencode('.png', img) return base64.b64encode(buffer).decode('utf-8') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### FRONTEND ROUTES: MARTHE ################################################################################################################################# #User-made MC-T NAME - in the second part of the interface @app.route("/mctnametoGoogleSheet/",methods=["GET", "POST"]) def sendmctnametoLegend(jsdata): try: result = json.loads(jsdata) print(result) global pdflink summaryid=google_sheet_Legend.mapnametoLegend(result,colorsused,pdflink) allreturns=[summaryid] return jsonify(allreturns) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route("/getguessednamepath/",methods=["GET", "POST"]) def getguessedNames(): try: guessednamesDrpdwn=google_sheet_Legend.getallguessednames() return jsonify(guessednamesDrpdwn) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ ######################################################### HELPER FUNCTIONS: TAMEEM - NOT USED ################################################################################################################################# #NOT USED (pixel conversion instead) def calcRef(img): try: blk = np.ones(img.shape, dtype="uint8") * [[[np.uint8(0), np.uint8(0), np.uint8(0)]]] start_point = (50, 100) end_point = (120, 200) color = (255, 255, 255) # white BGR thickness = -1 # Thickness of -1 will fill the entire shape blk = cv2.rectangle(blk, start_point, end_point, color, thickness) blk = cv2.cvtColor(blk, cv2.COLOR_BGR2GRAY) contourzz, hierarchy = cv2.findContours(image=blk, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE) for i, cnt3 in enumerate(contourzz): M = cv2.moments(cnt3) if M['m00'] != 0.0: x2 = int(M['m10']/M['m00']) y2 = int(M['m01']/M['m00']) area = cv2.contourArea(cnt3) perimeter = cv2.arcLength(cnt3, True) return area,perimeter , blk except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #NOT USED (pixel conversion instead) def modifyingcalcRefDynamic(img): try: imgcopy = img.copy() blk = np.ones(img.shape, dtype="uint8") * [[[np.uint8(0), np.uint8(0), np.uint8(0)]]] x = 50 y = 100 xD = int(img.shape[1] * 0.10) yD = int(img.shape[0] * 0.10) start_point = (x, y) end_point = (x+xD, y+yD) blue = (255, 0, 0) # BGR white = (255, 255, 255) # BGR thickness = -1 # Thickness of -1 will fill the entire shape imgcopy = cv2.rectangle(imgcopy, start_point, end_point, blue, thickness) blk = cv2.rectangle(blk, start_point, end_point, white, thickness) blk = cv2.cvtColor(blk, cv2.COLOR_BGR2GRAY) contourzz, hierarchy = cv2.findContours(image=blk, mode=cv2.RETR_EXTERNAL, method=cv2.CHAIN_APPROX_NONE) for i, cnt3 in enumerate(contourzz): M = cv2.moments(cnt3) if M['m00'] != 0.0: x2 = int(M['m10']/M['m00']) y2 = int(M['m01']/M['m00']) area = cv2.contourArea(cnt3) perimeter = cv2.arcLength(cnt3, True) return area, perimeter, blk , imgcopy except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ ######################################################### DROPBOX CODES ################################################################################################################################# @app.route('/downloadPDFfromLink') def downloadPDFfromLinkFunc(): try: encoded_url = request.args.get('url') link = urllib.parse.unquote(encoded_url) if link and ('http' in link or 'dropbox' in link): if 'dl=0' in link: link = link.replace('dl=0', 'dl=1') elif 'www.dropbox.com' in link and '?dl=1' not in link: link += '?dl=1' try: res = requests.get(link) res.raise_for_status() except Exception as e: return f"Error downloading PDF from link: {e}", 400 pdf_data = res.content filename = link.split("/")[-1].split("?")[0] or "downloaded.pdf" response = make_response(io.BytesIO(pdf_data).getvalue()) response.headers.set('Content-Type', 'application/pdf') response.headers.set('Content-Disposition', f'attachment; filename="{filename}"') return response except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #get pdf dropbox url after measurement is done @app.route('/getdropboxurl/',methods=["GET", "POST"]) def calldropboxurl(jsdata): try: print('jsdata',jsdata) pdfurl=tsadropboxretrieval.getPathtoPDF_File(nameofPDF=jsdata)[1] print('urll',pdfurl) if pdfurl and ('http' in pdfurl or 'dropbox' in pdfurl): if 'dl=0' in pdfurl: pdfurl = pdfurl.replace('dl=0', 'dl=1') print('urll1',pdfurl) # Download the PDF content from the shareable link response = requests.get(pdfurl) pdf_content = BytesIO(response.content) # Store the content in memory if pdf_content is None: raise ValueError("No valid PDF content found.") # Open the PDF using PyMuPDF pdf_document = fitz.open(stream=pdf_content, filetype="pdf") pdf_bytes = BytesIO() pdf_document.save(pdf_bytes) return Response(pdf_bytes.getvalue(), content_type='application/pdf') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route('/refreshDropbox',methods=["GET", "POST"]) def checkdropbox(): try: print('checkingggdf') dfFromDropbox=tsadropboxretrieval.DropboxItemstoDF("/TSA JOBS")[0] dfParquet=tsadropboxretrieval.GetParquetDF() dfParquet1 = dfParquet[['name', 'path_display', 'client_modified', 'server_modified']] deletedrows = pd.concat([dfFromDropbox, dfParquet1]).drop_duplicates(keep=False) deletedrows = deletedrows.reset_index(drop=True) deletedrows.columns = ['name', 'path_display', 'client_modified', 'server_modified'] differences = deletedrows[~deletedrows.isin(dfFromDropbox)].dropna() if (len(differences)>0): print(differences) dbxTeam=tsadropboxretrieval.dropbox_upload_file(dfFromDropbox) stringReturned= 'Updated Sucessfully.' else: stringReturned= 'Nothing to update.' return 'stringReturned' except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 def refreshDropboxRetrievals(extractedPath): try: dfFromDropbox = tsadropboxretrieval.DropboxItemstoDF(extractedPath)[0] dfParquet = tsadropboxretrieval.GetParquetDF() # print("Original Parquet size:", len(dfParquet)) # Keep only relevant columns dfParquet = dfParquet[['name', 'path_display', 'client_modified', 'server_modified']] dfFromDropbox = dfFromDropbox[['name', 'path_display', 'client_modified', 'server_modified']] # **Drop rows that start with extractedPath** dfParquetUpdated = dfParquet[~dfParquet['path_display'].str.startswith(extractedPath)] # **Append new data from Dropbox** dfParquetUpdated = pd.concat([dfParquetUpdated, dfFromDropbox], ignore_index=True) # print("Updated Parquet size:", len(dfParquetUpdated),dfParquetUpdated) # **Save the updated Parquet file** tsadropboxretrieval.dropbox_upload_file(dfParquetUpdated) if len(dfFromDropbox) > 0: print("Updated entries:", dfFromDropbox) return 'Updated Successfully.' else: return 'Nothing to update.' except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route('/postdropboxprojects/') def handle_path(encoded_path): try: decoded_path = urllib.parse.unquote(encoded_path) # Decode URL encoding extracted_path = json.loads(decoded_path) # Convert back to Python object print('path to refresh',extracted_path) stringReturned=refreshDropboxRetrievals(extracted_path) print(stringReturned) return stringReturned except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### GET PATH OF PDF ################################################################################################################################# @app.route('/get-pdf/') def get_pdf(jsdata): try: print('pdfname',jsdata) # Download PDF from Dropbox pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF=jsdata) print('pdfpath',pdfpath) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=pdfpath) pdf_data = res.content # Ensure this is your correct PDF data from Dropbox response = make_response(io.BytesIO(pdf_data).getvalue()) response.headers.set('Content-Type', 'application/pdf') response.headers.set('Content-Disposition', 'attachment', filename='filename.pdf') # Replace with your desired file name # return response return response except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### PIXEL CONVERSION ################################################################################################################################# @app.route('/pixeltestingimg') def pixeltesting(): try: encoded_url = request.args.get('url') link = urllib.parse.unquote(encoded_url.strip('"')) if link and ('http' in link or 'dropbox' in link): if 'dl=0' in link: link = link.replace('dl=0', 'dl=1') elif 'www.dropbox.com' in link and '?dl=1' not in link: link += '?dl=1' pdf_path=link response = requests.get(pdf_path) pdf_content = BytesIO(response.content) if not pdf_content: raise ValueError("No valid PDF content found.") progress_updates = [] # Shared list to store progress def generate_progressPixel(): yield f"data: 10\n\n" # Initial progress doc,areaPixel,perimeterPixel=pixelconversion.drawisrotated(pdf_content=pdf_content) # .openDrawPDF(data) yield f"data: 20\n\n" # Initial progress dbPath='/TSA JOBS/ADR Test/'+'TestingLinks'+'/'+'Scale Document' +'/' dburl=tsadropboxretrieval.uploadanyFile(doc=doc,pdfname=str('testinglink') ,path=dbPath) #PixelConv_ # areaPixel,perimeterPixel= pixelconversion.getAreaPerimeter(dbPath, str(jsdata[3])) yield f"data: 40\n\n" # Initial progress outputs=[areaPixel,perimeterPixel , dburl] while progress_updates: progress = progress_updates.pop(0) # Get the next progress value yield f"data: {progress}\n\n" # Final progress and result yield f"data: 80\n\n" yield f"data: 100\n\n" result = json.dumps(outputs) yield f"data: {result}\n\n" return Response(generate_progressPixel(), content_type='text/event-stream') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #PIXEL CONVERSION METHOD -- SAVES DOC ON DROPBOX TO BE MEASURED BY USER @app.route("/pixelimg/",methods=["GET", "POST"]) def getimg(jsdata): try: progress_updates = [] # Shared list to store progress jsdata=eval(jsdata) print('piexxxeell',jsdata) def generate_progressPixel(): yield f"data: 10\n\n" # Initial progress pdfpath,pdflink=tsadropboxretrieval.getPathtoPDF_File(nameofPDF=jsdata[3], progress_callback=lambda p: progress_updates.append(p)) dbxTeam= tsadropboxretrieval.ADR_Access_DropboxTeam('user') md, res =dbxTeam.files_download(path=pdfpath) data = res.content if str(jsdata[2]).startswith('1.0'): doc,areaPixel,perimeterPixel=pixelconversion.drawisrotated(data=data,dpi=300) # .openDrawPDF(data) else: doc,areaPixel,perimeterPixel=pixelconversion.drawisrotated(data=data) # .openDrawPDF(data) yield f"data: 20\n\n" # Initial progress dbPath='/TSA JOBS/ADR Test/'+jsdata[0]+'/'+jsdata[1]+'/'+jsdata[2]+'/'+'Scale Document' +'/' dburl=tsadropboxretrieval.uploadanyFile(doc=doc,pdfname=str(jsdata[3]) ,path=dbPath) #PixelConv_ # areaPixel,perimeterPixel= pixelconversion.getAreaPerimeter(dbPath, str(jsdata[3])) yield f"data: 40\n\n" # Initial progress outputs=[areaPixel,perimeterPixel , dburl] while progress_updates: progress = progress_updates.pop(0) # Get the next progress value yield f"data: {progress}\n\n" # Final progress and result yield f"data: 80\n\n" yield f"data: 100\n\n" result = json.dumps(outputs) yield f"data: {result}\n\n" return Response(generate_progressPixel(), content_type='text/event-stream') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ ######################################################### DELETE MARKUPS ################################################################################################################################# #DELETE MARKUPS (for comparison) @app.route('/_submission',methods=["GET", "POST"]) def getnewlegend(): try: pdfpth='' alljson = request.get_json() list1=alljson.get('dict1') print('list1',list1) # list1 = request.args.get('dict1') path=alljson.get('path') # path = request.args.get('path') spreadsheetId=alljson.get('spreadsheetId') # spreadsheetId =request.args.get('spreadsheetId') pdfpathpath=alljson.get('pdfpathpath') # pdfpathpath=request.args.get('pdfpathpath') print(pdfpathpath,type(pdfpathpath)) pdfname=request.args.get('pdfname') for word in eval(pdfpathpath): pdfpth+='/' +word pdfpth+='/' dbPath='/TSA JOBS/ADR Test'+pdfpth+'Measured Plan/' print(pdfpth) deletedrows1=google_sheet_Legend.deletemarkups(list1=list1,dbPath=dbPath,path=path) arr1=[deletedrows1.to_dict()] print('arr,',arr1) return jsonify(arr1) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 #--------------------------------------------------------------------------- #if user wishes to delete @app.route('/deletemarkupsroute',methods=["GET", "POST"]) def dltmarkupslegend(): try: print('IN deletemarkupsroute') pdfpth='' alljson = request.get_json() SimilarAreaDictionary=alljson.get('dict') # SimilarAreaDictionary = request.args.get('dict') deletedrows=alljson.get('deletedrows') print('deletedrowsssssssssssssssssssssssssssssss',deletedrows) # deletedrows = request.args.get('deletedrows') path=alljson.get('path') # path = request.args.get('path') spreadsheetId=alljson.get('spreadsheetId') # spreadsheetId =request.args.get('spreadsheetId') areaPermArr=alljson.get('areaPermArr') print('aaaaaaaaaaaaa',areaPermArr) # areaPermArr=request.args.get('areaPermArr') section=alljson.get('section') # section=request.args.get('section') pdfpathpath=alljson.get('pdfpathpath') # pdfpathpath=request.args.get('pdfpathpath') for word in eval(pdfpathpath): pdfpth+='/' +word pdfpth+='/' # myDict=eval(deletedrows) deletedrows=pd.DataFrame(deletedrows) print('deletedrows',deletedrows) if section.startswith('2.7'): areaPermArr=hatched_areas2_7 if section.startswith('1.0') or section.startswith('3.2') or section.startswith('3.3'): newlgnd=google_sheet_Legend.deletefromlegend(deletedrows=deletedrows,SimilarAreaDictionarycopy=SimilarAreaDictionary, section=section,areaPermArr=areaPermArr) elif section.startswith('2.8') or section.startswith('2.6'): newlgnd=google_sheet_Legend.deletedoors(deletedrows,SimilarAreaDictionary) print('done wit 2.8 in deleting, didnt append yet ') else: newlgnd=google_sheet_Legend.deletefromlegend(deletedrows=deletedrows,SimilarAreaDictionarycopy=SimilarAreaDictionary, section=section) try: newlgnd=google_sheet_Legend.legendGoogleSheets(SimilarAreaDictionary=newlgnd,path=path,spreadsheetId=spreadsheetId ,pdfpath=pdfpth) #new legend except: print("An exception occurred") time.sleep(20) newlgnd=google_sheet_Legend.legendGoogleSheets(SimilarAreaDictionary=newlgnd,path=path,spreadsheetId=spreadsheetId,pdfpath=pdfpth) return jsonify('donee') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### API ################################################################################################################################# #_________________________________________________________________________________________________________________________ #_________________________________________________________________________________________________________________________ @app.route('/getAPITables/',methods=["GET", "POST"]) def returnAPITables(): try: # API.update_df() table1,table2,table3=API.GenerateTables() return jsonify([table1.to_dict(),table2.to_dict(),table3.to_dict()]) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route('/refreshAPI', methods=["GET", "POST"]) def checktables(): try: projectname = request.args.get('prjname') projectpart = request.args.get('prjpart') projectpartid = request.args.get('prjpartid') global cached_tables # ✅ Fix: check properly for missing/empty DataFrame if cached_tables["projects"] is None or cached_tables["projects"].empty: return jsonify(["No cached data available yet. Please fetch projects first."]) # Get fresh values from API new_projects, new_parts, new_sections = API.GenerateTables() returnString = None # 1) Compare project names old_names = cached_tables["projects"]["ProjectName"].tolist() new_names = new_projects["ProjectName"].tolist() if set(old_names) != set(new_names): added = list(set(new_names) - set(old_names)) removed = list(set(old_names) - set(new_names)) returnString = ["Changes in Projects", "project", {"added": added, "removed": removed}] # 2) Compare parts elif projectname and cached_tables["parts"] is not None and not cached_tables["parts"].empty: prjid = new_projects.loc[new_projects['ProjectName'] == projectname, 'ProjectId'].values[0] old_parts = cached_tables["parts"].loc[cached_tables["parts"]["ProjectId"] == prjid, "ProjectPart"].tolist() new_parts_list = new_parts.loc[new_parts["ProjectId"] == prjid, "ProjectPart"].tolist() if set(old_parts) != set(new_parts_list): added = list(set(new_parts_list) - set(old_parts)) removed = list(set(old_parts) - set(new_parts_list)) returnString = ["Changes in Parts", "part", {"added": added, "removed": removed}] # 3) Compare sections elif projectname and projectpart and projectpartid and cached_tables["sections"] is not None and not cached_tables["sections"].empty: prjid = new_projects.loc[new_projects['ProjectName'] == projectname, 'ProjectId'].values[0] old_sections = cached_tables["sections"]["ProjectSection"].tolist() new_sections_list = new_sections[ (new_sections["ProjectId"] == prjid) & (new_sections["ProjectPartId"] == int(projectpartid)) ]["ProjectSection"].tolist() if set(old_sections) != set(new_sections_list): added = list(set(new_sections_list) - set(old_sections)) removed = list(set(old_sections) - set(new_sections_list)) returnString = ["Changes in Sections", "section", {"added": added, "removed": removed}] if not returnString: returnString = ["No changes detected"] # ✅ update cache cached_tables["projects"] = new_projects cached_tables["parts"] = new_parts cached_tables["sections"] = new_sections return jsonify(returnString) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 @app.route('/refreshAPIAppendNewTables',methods=["GET", "POST"]) def appendNewTables(): try:# value = request.args.get('keyword') # print(value) API.AppendtablestoSheets() return jsonify('appended') except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ######################################################### XML SUMMARY ################################################################################################################################# @app.route('/summarytoXML/',methods=["GET", "POST"]) def cvtSummarytoXML(jsdata): try: path='/TSA JOBS/ADR Test/' result = json.loads(jsdata) for word in result[0]: path+=word +'/' print(path) path=path+'XML/' # print(result[0]) # print(result[1]) xmllink=google_sheet_to_xml.create_xml(documentname=result[1],dbPath=path) return jsonify(xmllink) except (ConnectionError, TimeoutError) as e: # Use app context when logging from flask import current_app with current_app.app_context(): error_msg = log_error(str(e), issue_type="connection") return jsonify({"error": error_msg}), 500 except Exception: from flask import current_app with current_app.app_context(): error_details = traceback.format_exc() error_msg = log_error(error_details, issue_type="backend") return jsonify({"error": error_msg}), 500 ################################################################################################################################################################################################ ######################################################### MAIN ################################################################################################################################# ################################################################################################################################################################################################ def runn(): # app.run(host="127.0.0.1") from gevent.pywsgi import WSGIServer http_server = WSGIServer(("0.0.0.0", 7860), app) http_server.serve_forever() # serve(app, host="127.0.0.1", port=8080) def keep_alive(): t=Thread(target=runn) t.start() dtn = datetime.datetime.now(datetime.timezone.utc) print(dtn) next_start = datetime.datetime(dtn.year, dtn.month, dtn.day, 21, 0, 0).astimezone(datetime.timezone.utc) #us - 2 = utc time (21 utc is 19:00 our time and 9 is 7 our time , it needs to run 9 utc time ____ ) print(next_start) keep_alive() # active_path = "/TSA Team Folder/ADR Test/Test/" while 1: dtnNow = datetime.datetime.now(datetime.timezone.utc) print(dtnNow) if dtnNow >= next_start: next_start += datetime.timedelta(hours=12) # 1 day print(next_start) checkdropbox() time.sleep(1800) if __name__ == "__main__": runn()