From 691c91c4b5f17e5a3fc824d76a5b6cdec6b7ca6c Mon Sep 17 00:00:00 2001
From: dw927 <dw927@drexel.edu>
Date: Sun, 26 Feb 2023 21:19:50 +0000
Subject: [PATCH] Removed test hardcoding from images. Images are now populated
 from api...

---
 diagnosis_service/svc/database_connection.py  |  18 +++
 diagnosis_service/svc/run.py                  |  18 +--
 front_end/dpath.py                            |  30 +++--
 front_end/static/js/popup.js                  |  40 +++++++
 front_end/static/styles/style.css             | 109 ++++++++++++++++++
 front_end/templates/home.html                 |  11 +-
 front_end/templates/includes/imageList.html   |  12 ++
 front_end/templates/includes/imagePopup.html  |   3 +
 front_end/templates/includes/navbar.html      |   4 +-
 .../templates/includes/reportDetail.html      |  60 +++++-----
 front_end/templates/includes/reports.html     |  16 +--
 front_end/templates/includes/scriptsload.html |   1 +
 front_end/templates/reportDetail.html         |  10 +-
 front_end/templates/reports.html              |   2 +-
 upload_service/app.py                         |  33 ++++--
 upload_service/diagnosis_provider.py          |  40 +++++++
 16 files changed, 335 insertions(+), 72 deletions(-)
 create mode 100644 front_end/static/js/popup.js
 create mode 100644 front_end/templates/includes/imageList.html
 create mode 100644 front_end/templates/includes/imagePopup.html
 create mode 100644 front_end/templates/includes/scriptsload.html
 create mode 100644 upload_service/diagnosis_provider.py

diff --git a/diagnosis_service/svc/database_connection.py b/diagnosis_service/svc/database_connection.py
index 4b64b94..d35f338 100644
--- a/diagnosis_service/svc/database_connection.py
+++ b/diagnosis_service/svc/database_connection.py
@@ -143,3 +143,21 @@ class DigpathDatabase:
         }
 
         return results
+    
+    def get_requests(self):
+        cursor = self._db.cursor().execute('SELECT * FROM requests')
+        results = []
+        for i in cursor.fetchall():
+            item = {
+                'request_id': i[0],
+                'file': i[1],
+                'diagnosis': i[2],
+                'total_chips': i[3],
+                'mild': i[4],
+                'moderate': i[5],
+                'severe': i[6],
+                'status': i[7],
+                'timestamp': i[8]
+            }
+            results.append(item)
+        return results
diff --git a/diagnosis_service/svc/run.py b/diagnosis_service/svc/run.py
index af895e4..6c9a168 100644
--- a/diagnosis_service/svc/run.py
+++ b/diagnosis_service/svc/run.py
@@ -2,7 +2,6 @@ import json
 import uuid
 
 import boto3
-import mysql.connector
 from flask import Flask, request, jsonify
 from database_connection import DigpathDatabase
 
@@ -40,7 +39,7 @@ def get_slice_percentage(slice_num):
 
     return start, stop
 
-@app.route('/diagnose')
+@app.route('/diagnose', methods=['POST'])
 def diagnoseEndpoint():
     request_id = str(uuid.uuid4())
 
@@ -73,14 +72,15 @@ def diagnoseEndpoint():
     }
     return jsonify(response)
 
-@app.route('/request_info')
-def getDiagnosisEndpoint():
-
-    content = request.json
-    print(f"Getting info for: {content}")
+@app.route('/request_info/<string:request_id>')
+def getDiagnosisEndpoint(request_id):
+    request_info = DIGPATH_DB.get_request_info(request_id)
+    return jsonify(request_info)
 
-    request_info = DIGPATH_DB.get_request_info(content['request_id'])
+@app.route('/request_info')
+def getDiagnoses():
+    request_info = DIGPATH_DB.get_requests()
     return jsonify(request_info)
 
 if __name__ == '__main__':
-    app.run(host='0.0.0.0')
+    app.run(host='0.0.0.0', debug=True)
diff --git a/front_end/dpath.py b/front_end/dpath.py
index d3957ea..86907dd 100644
--- a/front_end/dpath.py
+++ b/front_end/dpath.py
@@ -1,4 +1,4 @@
-from flask import Flask, render_template, url_for, flash, redirect, request
+from flask import Flask, render_template, url_for, flash, redirect, request, send_file
 import requests
 from werkzeug.utils import secure_filename
 
@@ -6,7 +6,7 @@ from werkzeug.utils import secure_filename
 app = Flask(__name__)
 
 UPLOAD_FOLDER = 'static/uploads/'
-REPORTS_SERVICE_URL = 'http://127.0.0.1:5000'
+REPORTS_SERVICE_URL = 'http://127.0.0.1:5001'
 
 app.secret_key = "secret key"
 app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
@@ -16,10 +16,6 @@ ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif', 'tif'])
 BASE_URL = 'dpath'
 
 
-def allowed_file(filename):
-    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
-
-
 @app.route(f'/{BASE_URL}/')
 def home():
     return render_template('home.html')
@@ -34,13 +30,14 @@ def term2():
 @app.route(f'/{BASE_URL}/reports')
 def reports():
     reports = requests.get(f'{REPORTS_SERVICE_URL}/dpath/report').json()
+    print(reports)
     return render_template('reports.html', reports=reports)
 
 @app.route(f'/{BASE_URL}/reports/<string:report_id>')
 def get_report(report_id):
     report = requests.get(f'{REPORTS_SERVICE_URL}/dpath/report/{report_id}').json()
-    return render_template('reportDetail.html', report=report)
-
+    images  = requests.get(f'{REPORTS_SERVICE_URL}/dpath/report/{report_id}/images').json()
+    return render_template('reportDetail.html', report=report, images=images, image_name=image_name, upload_service_url=upload_service_url)
 
 @app.route('/', methods=['GET', "POST"])
 def upload_image():
@@ -54,17 +51,28 @@ def upload_image():
     if file and allowed_file(file.filename):
         filename = secure_filename(file.filename)
         report = post_file(request)
-        return render_template('reportDetail.html', report=report)
+        return get_report(report['request_id'])
     else:
         flash('Allowed image types are - png, jpg, jpeg, gif, tif')
         return redirect(request.url)
 
-
 @app.route('/display/<filename>')
 def display_image(filename):
     return redirect(url_for('static', filename='uploads/' + filename), code=301)
 
 
+def allowed_file(filename):
+    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
+
+
 def post_file(request) :
     response = requests.post(f'{REPORTS_SERVICE_URL}/{BASE_URL}/report/image', files=request.files).json()
-    return response
\ No newline at end of file
+    return response
+
+def image_name(image_url) :
+    image_name = image_url.split('/')[-1]
+    return image_name
+
+def upload_service_url(image_url) :
+    return image_url.replace('..', REPORTS_SERVICE_URL)
+     
\ No newline at end of file
diff --git a/front_end/static/js/popup.js b/front_end/static/js/popup.js
new file mode 100644
index 0000000..a372452
--- /dev/null
+++ b/front_end/static/js/popup.js
@@ -0,0 +1,40 @@
+function showImage(imageUrl) {
+    dialog = document.getElementById("imageDialog");
+    image = createImage(imageUrl);
+    dialog.appendChild(image);
+    buttonWrapper = document.createElement("div");
+    buttonWrapper.classList.add('dialog-button-wrapper');
+    buttonWrapper.appendChild(createCloseButton());
+    buttonWrapper.appendChild(createNewTabLink(imageUrl));
+    dialog.appendChild(buttonWrapper);
+    dialog.showModal();
+}
+
+function createImage(imageUrl) {
+    image = document.createElement('img');
+    image.src = imageUrl;
+    return image
+}
+
+function createCloseButton() {
+    closeButton = document.createElement('button');
+    closeButton.classList.add("dialog-button");
+    closeButton.onclick = function() {
+        dialog.close();
+        while (dialog.hasChildNodes()) {
+            dialog.removeChild(dialog.firstChild);
+        }
+    }
+    closeButton.textContent = 'Close';
+    return closeButton;
+}
+
+function createNewTabLink(imageUrl) {
+    button = document.createElement('button');
+    button.onclick = function() {
+        window.open(imageUrl);
+    }
+    button.textContent = 'View in New Tab';
+    button.classList.add('dialog-button');
+    return button;
+}
\ No newline at end of file
diff --git a/front_end/static/styles/style.css b/front_end/static/styles/style.css
index 5bc2f3b..0dbd5e3 100644
--- a/front_end/static/styles/style.css
+++ b/front_end/static/styles/style.css
@@ -1,10 +1,42 @@
 body {
     width: 100%;
+    background-color: #FAF9F6;
+}
+
+title {
+    display: block;
+}
+
+.title-wrapper {
+    width: 100%;
+    text-align: center;
+    display:block;
 }
 
 .container {
     width: 100%;
     text-align: center;
+    margin-top: 20px;
+    display: flex;
+}
+
+.nav-link {
+    color: white;
+    font-weight: bold;
+}
+
+.navbar-brand {
+    color: white;
+    font-weight: bold;
+}
+
+.bg-primary {
+    color: white;
+}
+
+.navbar {
+    background-color: #e3f2fd;
+    padding-left: 10px;
 }
 
 .report-table {
@@ -17,10 +49,15 @@ th {
     background-color: lightskyblue;
 }
 
+tr {
+    transition-duration: .2s;
+}
+
 tr:hover {
     background-color: lightgray;
 }
 
+
 td {
     padding-left: 5px;
     padding-right: 5px;
@@ -32,4 +69,76 @@ td {
 
 .right {
     text-align: right;
+}
+
+.table-link {
+    text-decoration: none;
+}
+
+#imageDisplay {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    background-color: blue;
+    text-align: center;
+    top: 0;
+}
+
+img {
+    max-width: 100%;
+    max-height: 100%;
+}
+
+.hidden {
+    display: none;
+}
+
+.dialog-button {
+    border: 2px solid white;
+    border-color: white;
+    border-radius: 15px;
+    box-shadow: none;
+    background-color: #0d6efd;
+    color: white;
+    font-weight: bold;
+    padding: 10px;
+}
+
+.dialog-button-wrapper {
+    width: 100%;
+    margin-top: 20px;
+    display: flex;
+    text-align: center;
+}
+
+dialog {
+    text-align: center;
+    margin-left: auto;
+    margin-right: auto;
+    border-radius: 15px;
+    border-color: lightgray;
+}
+
+.left-panel {
+    width: 40%;
+}
+
+.right-panel {
+    width: 60%;
+}
+
+.image-table {
+    margin-left: 30px;
+}
+
+.report-detail-table {
+    width: 100%;
+}
+
+.detail-left {
+    width: 30%;
+}
+
+.detail-right {
+    width: 70%;
 }
\ No newline at end of file
diff --git a/front_end/templates/home.html b/front_end/templates/home.html
index e40bed6..3c1259c 100644
--- a/front_end/templates/home.html
+++ b/front_end/templates/home.html
@@ -1,14 +1,16 @@
 <!doctype html>
 <html lang="en">
-<center>
+
   <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Slide Analyzer</title>
-    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
+    {% include 'includes/stylesload.html' %}
   </head>
+<center>
   <body>
     {% include 'includes/navbar.html' %}
+    <div class="">
     <h1>Welcome to the Digital Pathology Slide Analyzer.</h1>
     <br>
     <h2>Please select a file to upload.</h2>
@@ -32,7 +34,7 @@
         <button type="submit" class="btn btn-primary">Submit</button>
       </div>
   </form>
-      <br>
+      <!-- <br>
       <h2>
         Sample id: c1471950-71a5-11ed-9ddb-1267f16e00ed
       </h2>
@@ -46,8 +48,9 @@
             Chip Predictions:
             Mild: 806
             Severe: 846
-      </h2>
+      </h2> -->
     <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
+  </div>
   </body>
 </center>
 </html>
\ No newline at end of file
diff --git a/front_end/templates/includes/imageList.html b/front_end/templates/includes/imageList.html
new file mode 100644
index 0000000..0f5dac2
--- /dev/null
+++ b/front_end/templates/includes/imageList.html
@@ -0,0 +1,12 @@
+<div>
+    <table class="image-table">
+        <th class="left bg-primary">Chips</th>
+        {% for image in images %}
+        <tr>
+            <td class="left">
+                <a class="table-link" href="javascript:showImage('{{ upload_service_url(image) }}')" name="{{ image }}">{{ image_name(image) }}</a>
+            </td>
+        </tr>
+        {% endfor %}
+    </table>
+</div>
\ No newline at end of file
diff --git a/front_end/templates/includes/imagePopup.html b/front_end/templates/includes/imagePopup.html
new file mode 100644
index 0000000..eeefd35
--- /dev/null
+++ b/front_end/templates/includes/imagePopup.html
@@ -0,0 +1,3 @@
+<div id="imageDisplay" class="hidden">
+    <img src="http://127.0.0.1:5001/dpath/report/1939b367-0c4d-4689-8f39-8fdad55226c4/image/reportimage123.png">
+</div>
\ No newline at end of file
diff --git a/front_end/templates/includes/navbar.html b/front_end/templates/includes/navbar.html
index a9474cc..08f0526 100644
--- a/front_end/templates/includes/navbar.html
+++ b/front_end/templates/includes/navbar.html
@@ -1,8 +1,8 @@
-<nav class="navbar navbar-expand-lg navbar-light bg-light">
+<nav class="navbar navbar-expand-lg bg-primary">
     <a class="navbar-brand" href="#">Digital Pathology</a>
     <ul class="navbar-nav mr-auto">
         <li class="nav-item">
-            <a class="nav-link" href="{{ url_for('home')}}">Home</a>
+            <a class="nav-link" href="{{ url_for('home')}}">Upload</a>
         </li>
         <li class="nav-item">
             <a class="nav-link" href="{{ url_for('reports')}}">Reports</a>
diff --git a/front_end/templates/includes/reportDetail.html b/front_end/templates/includes/reportDetail.html
index a1e0ffb..99b2467 100644
--- a/front_end/templates/includes/reportDetail.html
+++ b/front_end/templates/includes/reportDetail.html
@@ -1,28 +1,36 @@
 {% block content %}
-<table class="report-detail-table">
-    <th class="left">Details</th>
-    <tr>
-        <td>Id</td>
-        <td>{{ report.id }}</td>
-    </tr>
-    <tr>
-        <td>Report Date</td>
-        <td>{{ report.report.runDate }}</td>
-    </tr>
-    <tr>
-        <td>Report Status</td>
-        <td>Todo</td>
-    </tr>
-    <tr>
-        <td>Diagnosis</td>
-        <td>{{ report.report.diagnosis }}</td>
-    </tr>
-    <tr>
-        <td>Mild Chips</td>
-        <td>{{ report.report.chipPredictions.mild}}</td>
-    </tr>
-    <tr>
-        <td>Severe Chips</td>
-        <td>{{ report.report.chipPredictions.severe}}</td>
-    </tr>
+<div class="panel panel-default">
+    <table class="report-detail-table ">
+        <th class="left bg-primary detail-left">Details</th>
+        <th class="left bg-primary detail-right"></th>
+        <tr>
+            <td>Id</td>
+            <td>{{ report.request_id }}</td>
+        </tr>
+        <tr>
+            <td>Report Date</td>
+            <td>{{ report.timestamp }}</td>
+        </tr>
+        <tr>
+            <td>Report Status</td>
+            <td>{{ report.status }}</td>
+        </tr>
+        <tr>
+            <td>Diagnosis</td>
+            <td>{{ report.diagnosis }}</td>
+        </tr>
+        <tr>
+            <td>Mild Chips</td>
+            <td>{{ report.mild}}</td>
+        </tr>
+        <tr>
+            <td>Moderate Chips</td>
+            <td>{{ report.moderate}}</td>
+        </tr>
+        <tr>
+            <td>Severe Chips</td>
+            <td>{{ report.severe}}</td>
+        </tr>
+    </table>
+</div>
 {% endblock %}
\ No newline at end of file
diff --git a/front_end/templates/includes/reports.html b/front_end/templates/includes/reports.html
index 2186ea1..7a798f3 100644
--- a/front_end/templates/includes/reports.html
+++ b/front_end/templates/includes/reports.html
@@ -1,17 +1,19 @@
 {% block content %}
-<h1>{% block title %} Reports {% endblock %}</h1>
+<!-- <div class="title-wrapper">
+  <h1>Reports</h1>
+</div> -->
 <table class="report-table">
-  <th class="left">Id</th>
-  <th class="left">Status</th>
-  <th class="right">Run Date</th>
+  <th class="left bg-primary">Id</th>
+  <th class="left bg-primary">Status</th>
+  <th class="right bg-primary">Run Date</th>
   {% for report in reports %}
   <tr>
 
     <td class="left">
-      <a href="{{ url_for('get_report', report_id=report.id)}}">{{ report.id }}</a>
+      <a class="table-link" href="{{ url_for('get_report', report_id=report.request_id)}}">{{ report.request_id }}</a>
     </td>
-    <td class="left">Completed</td>
-    <td class="right">{{ report.report.runDate }}</td>
+    <td class="left">{{ report.status }}</td>
+    <td class="right">{{ report.timestamp }}</td>
   </tr>
   {% endfor %}
 </table>
diff --git a/front_end/templates/includes/scriptsload.html b/front_end/templates/includes/scriptsload.html
new file mode 100644
index 0000000..830e21f
--- /dev/null
+++ b/front_end/templates/includes/scriptsload.html
@@ -0,0 +1 @@
+<script src="{{ url_for('static', filename='js/popup.js') }}"></script>
\ No newline at end of file
diff --git a/front_end/templates/reportDetail.html b/front_end/templates/reportDetail.html
index cbe840b..c3cad10 100644
--- a/front_end/templates/reportDetail.html
+++ b/front_end/templates/reportDetail.html
@@ -5,9 +5,17 @@
     {% include 'includes/stylesload.html' %}
 </head>
 
+{% include 'includes/scriptsload.html' %}
+
 <body>
     {% include 'includes/navbar.html' %}
     <div class="container">
-        {% include 'includes/reportDetail.html' %}
+        <div class="left-panel">
+            {% include 'includes/reportDetail.html' %}
+        </div>
+        <div class="right-panel">
+            {% include 'includes/imageList.html' %}
+        </div>
+        <dialog id="imageDialog"></dialog>
     </div>
 </body>
\ No newline at end of file
diff --git a/front_end/templates/reports.html b/front_end/templates/reports.html
index b579b6b..d45f0a3 100644
--- a/front_end/templates/reports.html
+++ b/front_end/templates/reports.html
@@ -3,7 +3,7 @@
 <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <title>Reports</title>
+        <title>Reports</title>
     {% include 'includes/stylesload.html' %}
 </head>
 
diff --git a/upload_service/app.py b/upload_service/app.py
index c1e3521..136f07f 100644
--- a/upload_service/app.py
+++ b/upload_service/app.py
@@ -1,8 +1,9 @@
 from flask import Flask
 from flask import jsonify
 from flask import request
+from flask import send_file
 # from s3_provider import Provider
-from test_report_provider import Provider
+from diagnosis_provider import Provider
 from fake_model import LearningModel as Model
 import uuid
 
@@ -30,19 +31,32 @@ def get_reports() :
 	response.status_code = 200
 	return response
 
+@app.route(f'/{PREFIX}/report/<string:report_id>/images', methods=['GET'])
+def get_images(report_id) :
+	provider = Provider()
+	response = jsonify(provider.get_images(report_id))
+	response.status_code = 200
+	return response
+
+@app.route(f'/{PREFIX}/report/<string:report_id>/image/<string:file_name>', methods=['GET'])
+def get_image(report_id, file_name) :
+	provider = Provider()
+	path = provider.get_image_path(file_name)
+	return send_file(
+		path,
+		download_name=file_name,
+		mimetype='image/png'
+	)
+
 @app.route(f'/{PREFIX}/report/image', methods=['POST'])
 def upload_image():
-	print("reached")
 	response = validate_request(request)
 	if response.status_code == 400:
 		return response
 
 	provider = Provider()
 	id = uuid.uuid1()
-	response = jsonify(provider.create_report(""))
-	# response = jsonify(Model(id).start())
-	response.status_code = 201
-	return response
+	return jsonify(provider.save_binary(request.files['file']))	
 
 def validate_request(request):
 	response = jsonify({'message' : 'File successfully uploaded'})
@@ -52,12 +66,9 @@ def validate_request(request):
 		response = jsonify({'message' : 'No file part in the request'})
 		response.status_code = 400
 		return response
+	
+	file = request.files['file']
 
-	file = file = request.files['file']
-	# if invalid_extension(file.filename.rsplit('.', 1)[1].lower()):
-	# 	response = jsonify({'message' : 'Allowed file types are png, tiff'})
-	# 	response.status_code = 400
-	# 	return response	
 	if invalid_filename(file):
 		response = jsonify({'message' : 'No file selected for uploading'})
 		response.status_code = 400
diff --git a/upload_service/diagnosis_provider.py b/upload_service/diagnosis_provider.py
new file mode 100644
index 0000000..2c37d44
--- /dev/null
+++ b/upload_service/diagnosis_provider.py
@@ -0,0 +1,40 @@
+import requests
+from PIL import Image
+import os
+from base64 import b64encode
+
+BASE_URL = 'http://127.0.0.1:5000'
+SAVE_DIRECTORY = 'C:\\Users\\Dave\\OneDrive\\Documents\\Capstone\\data\\'
+
+
+class Provider:
+    
+    def save_binary(self, data):
+        url = BASE_URL + '/diagnose'
+        file_name = self.__save_local_file(data)
+        request = {'file': file_name}
+        return requests.post(url, json=request).json()
+    
+    def get_report(self, id):
+        url = BASE_URL + '/request_info/' + id
+        return requests.get(url).json()
+
+    def get_reports(self):
+        url = BASE_URL + '/request_info'
+        return requests.get(url).json()
+    
+    def get_images(self, report_id):
+        response = []
+        for _ in range(50) :
+            response.append(f'../dpath/report/{report_id}/image/reportimage123.png')
+        return response
+    
+    def get_image_path(self, image_name):
+        return SAVE_DIRECTORY + image_name
+    
+    def __save_local_file(self, file):
+        file_name = 'reportimage123.png'
+        new_file = open(SAVE_DIRECTORY + file_name, 'wb')
+        new_file.write(file.stream.read())
+        new_file.close()
+        return file_name
\ No newline at end of file
-- 
GitLab