diff --git a/communicator/__init__.py b/communicator/__init__.py index e986a3d..c714cb8 100644 --- a/communicator/__init__.py +++ b/communicator/__init__.py @@ -14,6 +14,7 @@ from flask_sqlalchemy import SQLAlchemy from sentry_sdk.integrations.flask import FlaskIntegration from webassets import Bundle + logging.basicConfig(level=logging.INFO) # API, fully defined in api.yml @@ -80,7 +81,7 @@ if app.config['SENTRY_ENVIRONMENT']: BASE_HREF = app.config['APPLICATION_ROOT'].strip('/') -@app.route('/', methods=['GET', 'POST']) +@app.route('/', methods=['GET']) def index(): from communicator.models import Sample from communicator.tables import SampleTable @@ -117,6 +118,24 @@ def send_invitation(): base_href=BASE_HREF ) +@app.route('/imported_files', methods=['GET']) +def list_imported_files_from_ivy(): + from communicator.models.ivy_file import IvyFile + from communicator.tables import IvyFileTable + + # display results + page = request.args.get(get_page_parameter(), type=int, default=1) + files = db.session.query(IvyFile).order_by(IvyFile.date_added.desc()) + pagination = Pagination(page=page, total=files.count(), search=False, record_name='samples') + + table = IvyFileTable(files.paginate(page, 10, error_out=False).items) + return render_template( + 'imported_files.html', + table=table, + pagination=pagination, + base_href=BASE_HREF + ) + @app.route('/sso') def sso(): response = "" diff --git a/communicator/api/admin.py b/communicator/api/admin.py index 1015a7a..2e85eb2 100644 --- a/communicator/api/admin.py +++ b/communicator/api/admin.py @@ -28,7 +28,6 @@ def update_data(): """Updates the database based on local files placed by IVY. No longer attempts to pull files from the Firebase service.""" ivy_service = IvyService() - samples = ivy_service.load_directory() SampleService().add_or_update_records(samples) db.session.commit() diff --git a/communicator/models/ivy_file.py b/communicator/models/ivy_file.py index 5866a50..24f7bd7 100644 --- a/communicator/models/ivy_file.py +++ b/communicator/models/ivy_file.py @@ -6,3 +6,4 @@ from communicator import db class IvyFile(db.Model): file_name = db.Column(db.String, primary_key=True) date_added = db.Column(db.DateTime(timezone=True), default=func.now()) + sample_count = db.Column(db.Integer) diff --git a/communicator/services/ivy_service.py b/communicator/services/ivy_service.py index 6e73e26..39597c3 100644 --- a/communicator/services/ivy_service.py +++ b/communicator/services/ivy_service.py @@ -1,4 +1,5 @@ import csv +from datetime import datetime import globus_sdk from dateutil import parser @@ -23,18 +24,20 @@ class IvyService(object): self.GLOBUS_IVY_ENDPOINT = app.config['GLOBUS_IVY_ENDPOINT'] self.GLOBUS_DTN_ENDPOINT = app.config['GLOBUS_DTN_ENDPOINT'] - print("Client ID:" + self.GLOBUS_CLIENT_ID) - - self.client = globus_sdk.NativeAppAuthClient(self.GLOBUS_CLIENT_ID) - self.client.oauth2_start_flow(refresh_tokens=True) def load_directory(self): onlyfiles = [f for f in listdir(self.path) if isfile(join(self.path, f))] samples = [] for file_name in onlyfiles: samples = IvyService.samples_from_ivy_file(join(self.path, file_name)) - ivy_file = IvyFile(file_name=file_name) + ivy_file = db.session.query(IvyFile).filter(IvyFile.file_name == file_name).first() + if not ivy_file: + ivy_file = IvyFile(file_name=file_name, sample_count=len(samples)) + else: + ivy_file.date_added = datetime.now() + ivy_file.sample_count = len(samples) db.session.add(ivy_file) + db.session.commit() return samples @staticmethod @@ -105,6 +108,9 @@ class IvyService(object): def get_transfer_client(self): + self.client = globus_sdk.NativeAppAuthClient(self.GLOBUS_CLIENT_ID) + self.client.oauth2_start_flow(refresh_tokens=True) + authorizer = globus_sdk.RefreshTokenAuthorizer( self.GLOBUS_TRANSFER_RT, self.client, access_token=self.GLOBUS_TRANSFER_AT, expires_at=self.EXPIRES_AT) tc = globus_sdk.TransferClient(authorizer=authorizer) diff --git a/communicator/tables.py b/communicator/tables.py index a98a6b7..1d934e2 100644 --- a/communicator/tables.py +++ b/communicator/tables.py @@ -10,3 +10,11 @@ class SampleTable(Table): location = Col('Location') email_notified = BoolCol('Emailed?') text_notified = BoolCol('Texted?') + + +class IvyFileTable(Table): + def sort_url(self, col_id, reverse=False): + pass + file_name = Col('File Name') + date_added = DatetimeCol('Date', "medium") + sample_count = Col('Total Records') diff --git a/communicator/templates/imported_files.html b/communicator/templates/imported_files.html new file mode 100644 index 0000000..2b36d7e --- /dev/null +++ b/communicator/templates/imported_files.html @@ -0,0 +1,23 @@ + + + + UVA Be Safe Communicator + + + + + {% assets 'app_scss' %} + + {% endassets %} + + + +

UVA Be Safe Communicator

+ +

The following files were imported from IVY

+{{ pagination.info }} +{{ pagination.links }} +{{ table }} +{{ pagination.links }} + + diff --git a/tests/data/import_directory/file1.csv b/tests/data/import_directory/file1.csv new file mode 100644 index 0000000..d69463a --- /dev/null +++ b/tests/data/import_directory/file1.csv @@ -0,0 +1,2 @@ +Student ID|Student Cellphone|Student Email|Test Date Time|Test Kiosk Loc|Test Result Code +987654321|555/555-5555|rkc7h@virginia.edu|202009030809|4321|8726520277 diff --git a/tests/data/import_directory/file2.csv b/tests/data/import_directory/file2.csv new file mode 100644 index 0000000..619a7db --- /dev/null +++ b/tests/data/import_directory/file2.csv @@ -0,0 +1,3 @@ +Student ID|Student Cellphone|Student Email|Test Date Time|Test Kiosk Loc|Test Result Code +987655321|555/555-5558|testnegetive@virginia.edu|202009070719|4321|1142270225 + diff --git a/tests/data/import_directory/file3.csv b/tests/data/import_directory/file3.csv new file mode 100644 index 0000000..1a6122a --- /dev/null +++ b/tests/data/import_directory/file3.csv @@ -0,0 +1,3 @@ +Student ID|Student Cellphone|Student Email|Test Date Time|Test Kiosk Loc|Test Result Code +000000222|555/555-5556|testpositive@virginia.edu|202009091449|4321|8269722523 +000000333|555/555-5558|testnegetive@virginia.edu|202009091449|4321|1142270225 diff --git a/tests/data/import_directory/file4.csv b/tests/data/import_directory/file4.csv new file mode 100644 index 0000000..bab9396 --- /dev/null +++ b/tests/data/import_directory/file4.csv @@ -0,0 +1,4 @@ +Student ID|Student Cellphone|Student Email|Test Date Time|Test Kiosk Loc|Test Result Code +987654321|555/555-5555|rkc7h@virginia.edu|202009030809|4321|8726520277 +987654322|555/555-5556|testpositive@virginia.edu|202009060919|4321|8269722523 + diff --git a/tests/services/test_ivy_service.py b/tests/services/test_ivy_service.py index b2c950b..46b2242 100644 --- a/tests/services/test_ivy_service.py +++ b/tests/services/test_ivy_service.py @@ -1,9 +1,11 @@ +from tests.base_test import BaseTest import os import unittest import globus_sdk -from tests.base_test import BaseTest -from communicator import app +from communicator.models.ivy_file import IvyFile + +from communicator import app, db from communicator.errors import CommError from communicator.services.ivy_service import IvyService @@ -22,5 +24,11 @@ class IvyServiceTest(BaseTest): ivy_incorrect_file = os.path.join(app.root_path, '..', 'tests', 'data', 'incorrect.csv') IvyService.samples_from_ivy_file(ivy_incorrect_file) + def test_load_directory(self): + self.assertEquals(0, db.session.query(IvyFile).count()) + app.config['IVY_IMPORT_DIR'] = os.path.join(app.root_path, '..', 'tests', 'data', 'import_directory') + records = IvyService().load_directory() + files = db.session.query(IvyFile).all() + self.assertEquals(4, len(files))