Skip to content

Commit

Permalink
Merge pull request #149 from akash314/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
PFWhite committed May 2, 2017
2 parents 8812630 + 413c20d commit 937d23f
Show file tree
Hide file tree
Showing 15 changed files with 158 additions and 17 deletions.
2 changes: 2 additions & 0 deletions app/db/005/downgrade.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- remove file type column
ALTER TABLE SubjectFile DROP sfFileType;
3 changes: 3 additions & 0 deletions app/db/005/upgrade.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- ensure there will be no duplicates user / user role pairs
ALTER TABLE SubjectFile
ADD sfFileType varchar(255) NOT NULL;
6 changes: 4 additions & 2 deletions app/deploy/fabfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,8 @@ def mysql_create_tables():
'002/upgrade.sql',
'002/data.sql',
'003/upgrade.sql',
'004/upgrade.sql']
'004/upgrade.sql',
'005/upgrade.sql' ]

with lcd('../db/'):
for sql in files:
Expand All @@ -377,7 +378,8 @@ def mysql_drop_tables():
abort(colors.red("Unable to drop tables in database '%(db_name)s'."
"The database does not exist" % env))

files = ['004/downgrade.sql',
files = ['005/downgrade.sql',
'004/downgrade.sql',
'003/downgrade.sql',
'002/downgrade.sql',
'001/downgrade.sql']
Expand Down
2 changes: 2 additions & 0 deletions app/fabfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def init_db():
local('sudo mysql ctsi_dropper_s < db/002/data.sql')
local('sudo mysql ctsi_dropper_s < db/003/upgrade.sql')
local('sudo mysql ctsi_dropper_s < db/004/upgrade.sql')
local('sudo mysql ctsi_dropper_s < db/005/upgrade.sql')


@task
Expand All @@ -82,6 +83,7 @@ def reset_db():
local('sudo mysql ctsi_dropper_s < db/002/data.sql')
local('sudo mysql ctsi_dropper_s < db/003/upgrade.sql')
local('sudo mysql ctsi_dropper_s < db/004/upgrade.sql')
local('sudo mysql ctsi_dropper_s < db/005/upgrade.sql')


@task
Expand Down
7 changes: 3 additions & 4 deletions app/redidropper/models/subject_file_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class SubjectFileEntity(db.Model, CRUDMixin):
file_name = db.Column("sfFileName", db.String(255), nullable=False)
file_check_sum = db.Column("sfFileCheckSum", db.String(32), nullable=False)
file_size = db.Column("sfFileSize", db.String(255), nullable=False)
file_type = db.Column("sfFileType", db.String(255), nullable=False)
uploaded_at = db.Column("sfUploadedAt", db.DateTime, nullable=False,
server_default='0000-00-00 00:00:00')
user_id = db.Column("usrID", db.Integer, db.ForeignKey('User.usrID'),
Expand Down Expand Up @@ -100,12 +101,10 @@ def serialize(self):
'file_name': self.file_name,
'file_check_sum': self.file_check_sum,
'file_size': self.file_size,
'file_type': self.file_type,
'uploaded_at': utils.localize_est_datetime(self.uploaded_at),
'subject_id': self.subject_id,
'event_id': self.event_id,
'user_id': self.user_id,
'user_name': self.user.get_name(),
# 'subject': self.subject.serialize(),
# 'event': self.event.serialize(),
# 'user': self.user.serialize(),
'user_name': self.user.get_name()
}
33 changes: 33 additions & 0 deletions app/redidropper/routes/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Goal: Delegate requests to the `/api` path to the appropriate controller
@authors:
Akash Agarwal <agarwala989@gmail.com
Andrei Sura <sura.andrei@gmail.com>
Ruchi Vivek Desai <ruchivdesai@gmail.com>
Sanath Pasumarthy <sanath@ufl.edu>
Expand Down Expand Up @@ -182,7 +183,23 @@ def api_delete_file():
response = utils.jsonify_error({"exception": ret_value})

return response

@app.route('/api/update_fileType', methods=['POST'])
@login_required
def api_update_fileType():
""" Updates the file type """
#get the file from the response
subject_file_id = request.form.get('file_id')
subject_file_type = request.form.get('file_type')
try:
ret_value = file_manager.update_filetype(subject_file_id, subject_file_type)
#app.logger.debug("updated file id: {}".format(subject_file_id))
response = utils.jsonify_success({"file_id": ret_value[0], "file_type": ret_value[1]})

except:
response = utils.jsonify_error({"exception": ret_value})

return response

@app.route("/api/download_file", methods=['POST'])
@login_required
Expand All @@ -200,6 +217,22 @@ def download_file():
LogEntity.file_downloaded(session['uuid'], file_path)
return send_file(file_path, as_attachment=True)

@app.route("/api/all_files_info", methods=['GET'])
@login_required
def all_files_info():
""" Get the list of all uploaded files and their path """
all_files = db.session.query(SubjectFileEntity,EventEntity.redcap_event,SubjectEntity.redcap_id).join(EventEntity).join(SubjectEntity)
return_list = [__build_files_info_json(subject_file,event,subject) for subject_file,event,subject in all_files]
return utils.jsonify_success({'list_of_files' : return_list})

def __build_files_info_json(subject_file,event,subject):
path = subject_file.get_full_path(app.config['REDIDROPPER_UPLOAD_SAVED_DIR'])
file_json = subject_file.serialize()
file_json['path'] = path
file_json['redcap_id'] = subject
file_json['redcap_event'] = event
return file_json

def __extract_user_information(request):
return {
"email": request.form.get('email'),
Expand Down
9 changes: 9 additions & 0 deletions app/redidropper/routes/file_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def init_from_request(cls):
self.total_size = int(request.form['resumableTotalSize'])
self.uniqueid = request.form['resumableIdentifier']
self.file_name = secure_filename(request.form['resumableFilename'])
self.file_type = request.form['resumableFileType']
self.afile = request.files['file']
self.total_parts = int(request.form['resumableTotalChunks'])
self.redcap_id = request.form['subject_id'] # @TODO: rename
Expand Down Expand Up @@ -73,6 +74,7 @@ def save_file_metadata(fchunk):
file_name=fchunk.file_name,
file_check_sum='pending',
file_size=fchunk.total_size,
file_type=fchunk.file_type,
uploaded_at=added_date,
user_id=current_user.id)
logger.debug("Saved metadata to the db: ".format(subject_file))
Expand Down Expand Up @@ -217,3 +219,10 @@ def delete_file(subject_file_id):
file_entity.delete()
db.session.commit()
return (subject_file_id, file_path)

def update_filetype(subject_file_id, subject_file_type):
""" Updates the type field of the file """
file_entity = SubjectFileEntity.query.filter_by(id=subject_file_id).one()
file_entity.update(file_type=subject_file_type)
db.session.commit()
return (subject_file_id, subject_file_type)
5 changes: 5 additions & 0 deletions app/redidropper/static/css/dashboard.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.dash_drop{
width:75px;
height:30px;
padding: 30px 0 0 0;
}
35 changes: 27 additions & 8 deletions app/redidropper/static/js/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,11 @@ var FilesList = React.createClass({
},

deleteFile: function(file_id) {
var confirmed = confirm("Are you sure you want to delete the file?");
if(confirmed == false){
return;
}

var request = Utils.api_post_json("/api/delete_file", {file_id: file_id}),
self = this;

Expand Down Expand Up @@ -303,6 +308,20 @@ var FilesList = React.createClass({
});
},

changeType: function(fileId){
var request = Utils.api_post_json("/api/update_fileType", {file_id: fileId, file_type: event.target.value}),
self = this;

request.success((json) => {
obj = self.state.list_of_files.find(function(ele){return ele.id==json.data.file_id})
obj.file_type=json.data.file_type
self.setState({
list_of_files: self.state.list_of_files
});
});

},

render: function() {
return (
<div className="table-responsive" >
Expand All @@ -313,7 +332,7 @@ var FilesList = React.createClass({
<th className="text-center"> File Size (MB)</th>
<th className="text-center"> Uploaded </th>
<th className="text-center"> Uploaded By </th>
<th className="text-center"></th>
<th className="text-center"> Image Type </th>
</tr>
</thead>
<tbody id="technician-table-body">
Expand All @@ -324,6 +343,13 @@ var FilesList = React.createClass({
<td>{(record.file_size / (1024 * 1024)).toFixed(2)}</td>
<td>{record.uploaded_at}</td>
<td>{record.user_name}</td>
<td>
<select className="dash_drop" value={record.file_type} onChange={this.changeType.bind(this,record.id)}>
<option value="MRI">MRI</option>
<option value="PET">PET</option>
<option value="N/A">N/A</option>
</select>
</td>
<td>
<form method="POST" action="/api/download_file">
<input type="hidden" name="file_id" value={record.id} />
Expand All @@ -333,15 +359,8 @@ var FilesList = React.createClass({
<td>
<button
onClick={this.deleteFile.bind(this, record.id)}
disabled={!record.canDelete}
className="btn btn-primary">Delete File</button>
</td>
<td>
Enable delete file? <input type="checkbox"
checked={!!record.canDelete}
onChange={this.toggleCanDelete.bind(this, record.id)}
></input>
</td>
</tr>);
})}
</tbody>
Expand Down
3 changes: 3 additions & 0 deletions app/redidropper/static/js/resumable.js
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,7 @@
$.file = file;
$.fileName = file.fileName||file.name; // Some confusion in different versions of Firefox
$.size = file.size;
$.fileType = 'N/A';
$.relativePath = file.webkitRelativePath || file.relativePath || $.fileName;
$.uniqueIdentifier = $h.generateUniqueIdentifier(file);
$._pause = false;
Expand Down Expand Up @@ -680,6 +681,7 @@
params.push(['resumableType', encodeURIComponent($.fileObjType)].join('='));
params.push(['resumableIdentifier', encodeURIComponent($.fileObj.uniqueIdentifier)].join('='));
params.push(['resumableFilename', encodeURIComponent($.fileObj.fileName)].join('='));
params.push(['resumableFileType', encodeURIComponent($.fileObj.fileType)].join('='));
params.push(['resumableRelativePath', encodeURIComponent($.fileObj.relativePath)].join('='));
params.push(['resumableTotalChunks', encodeURIComponent($.fileObj.chunks.length)].join('='));

Expand Down Expand Up @@ -767,6 +769,7 @@
resumableType: $.fileObjType,
resumableIdentifier: $.fileObj.uniqueIdentifier,
resumableFilename: $.fileObj.fileName,
resumableFileType: $.fileObj.fileType,
resumableRelativePath: $.fileObj.relativePath,
resumableTotalChunks: $.fileObj.chunks.length
};
Expand Down
1 change: 1 addition & 0 deletions app/redidropper/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<link href="{{ url_for('static', filename='css/layout.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/start_upload.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/parallax.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/dashboard.css') }}" rel="stylesheet">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">


Expand Down
2 changes: 2 additions & 0 deletions app/tests/base_test_with_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Goal: Extend the base test class by inserting samle rows in the database
Authors:
Akash Agarwal <agarwala989@gmail.com
Andrei Sura <sura.andrei@gmail.com>
"""
Expand Down Expand Up @@ -116,6 +117,7 @@ def create_sample_data(self):
subject_id=subject.id,
event_id=fdata['event'],
file_name=fdata['name'],
file_type="N/A",
file_check_sum=utils.compute_text_md5(fdata['name']),
file_size=fdata['size'],
uploaded_at=added_date,
Expand Down
55 changes: 55 additions & 0 deletions app/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Goal: Simulate api calls
Authors:
Akash Agarwal <agarwala989@gmail.com
Patrick White <pfwhite9@gmail.com> <pfwhite@ufl.edu>
"""
Expand All @@ -12,8 +13,14 @@
from .base_test_with_data import BaseTestCaseWithData
from redidropper.main import app
from redidropper.main import db
from datetime import datetime

from redidropper import utils
from redidropper.models.user_entity import UserEntity
from redidropper.models.event_entity import EventEntity
from redidropper.models.subject_entity import SubjectEntity
from redidropper.models.subject_file_entity import SubjectFileEntity
import json

class TestAPI(BaseTestCaseWithData):

Expand Down Expand Up @@ -84,6 +91,54 @@ def test_edit_user(self):
self.fail('user not existing')
print('edit user test')

def test_update_fileType(self):
""" Verify that we can change file type"""
res_login = self.__login("admin@example.com")

added_date = datetime.today()
subject = SubjectEntity.create(
redcap_id="002",
added_at=added_date,
last_checked_at=added_date,
was_deleted=0)

# == Create events
evt = EventEntity.create(redcap_arm='Arm 2',
redcap_event='Event 2',
day_offset=1,
added_at=added_date)

files = [
{'name': 'x.png', 'size': '123', 'event': evt.id},
{'name': 'y.png', 'size': '1234', 'event': evt.id}
]

for fdata in files:
subject_file = SubjectFileEntity.create(
subject_id=subject.id,
event_id=fdata['event'],
file_name=fdata['name'],
file_type="N/A",
file_check_sum=utils.compute_text_md5(fdata['name']),
file_size=fdata['size'],
uploaded_at=added_date,
user_id='1')

file_entity = SubjectFileEntity.query.filter_by(file_name='x.png').one()
postdata = {'file_id': file_entity.id, 'file_type': 'MRI'}
response = self.client.post("/api/update_fileType", data=postdata)
self.assertEqual(response._status_code, 200)

after_edit_file = SubjectFileEntity.query.filter_by(file_name='x.png').one()
self.assertEqual(after_edit_file.file_type, "MRI")
print('update file test')

def test_all_files_info(self):
response = self.client.get("/api/all_files_info")
self.assertEqual(response._status_code, 200)
jsondata = json.loads(response.data)
self.assertGreater(len(jsondata['data']['list_of_files']),1)

def __get_file_list_data(self, response):
d = Decoder()
data = d.decode(response.data)
Expand Down
7 changes: 5 additions & 2 deletions app/tests/test_subject_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Goal: test insert/search subject, subject file
Authors:
Akash Agarwal <agarwala989@gmail.com
Andrei Sura <sura.andrei@gmail.com>
"""
Expand Down Expand Up @@ -47,7 +48,7 @@ def test_subject(self):
evt = EventEntity.create(redcap_arm='Arm 1', redcap_event='Event 1',
added_at=added_date)

fdata = {'name': 'a.png', 'size': '1MB', 'event': evt.id}
fdata = {'name': 'a.png', 'size': '1MB', 'event': evt.id, 'file_type': 'MRI'}
user = UserEntity.create(email="admin@example.com",
first="",
last="",
Expand All @@ -62,6 +63,7 @@ def test_subject(self):
file_name=fdata['name'],
file_check_sum=utils.compute_text_md5(fdata['name']),
file_size=fdata['size'],
file_type=fdata['file_type'],
uploaded_at=added_date,
user_id=user.get_id())
self.assertIsNotNone(subject_file.id)
Expand All @@ -74,4 +76,5 @@ def test_subject(self):
self.assertEqual(1, actual_count)

sfile = SubjectFileEntity.query.first()
self.assertEqual(user.id, sfile.user_id)
self.assertEqual(user.id, sfile.user_id)
self.assertEqual('MRI', sfile.file_type)
5 changes: 4 additions & 1 deletion vagrant/bootstrap_functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ function install_dropper() {
mysql ctsi_dropper_s < db/003/upgrade.sql
log "Execute sql: db/004/upgrade.sql"
mysql ctsi_dropper_s < db/004/upgrade.sql

log "Execute sql: db/005/upgrade.sql"
mysql ctsi_dropper_s < db/005/upgrade.sql


log "Stop apache in order to disable the default site"
service apache2 stop
a2dissite 000-default
Expand Down

0 comments on commit 937d23f

Please sign in to comment.