Skip to content

Commit

Permalink
Merge pull request #344 from NBISweden/develop
Browse files Browse the repository at this point in the history
Release pull for dataset version UI.
  • Loading branch information
kusalananda authored Oct 9, 2017
2 parents 4053b4a + cde4e4f commit 7b670e9
Show file tree
Hide file tree
Showing 26 changed files with 760 additions and 580 deletions.
118 changes: 101 additions & 17 deletions tornado/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from email.mime.text import MIMEText
import json
import logging
from datetime import datetime
import peewee
import smtplib
import tornado.web
Expand Down Expand Up @@ -29,7 +30,7 @@ def build_dataset_structure(dataset_version, user=None, dataset=None):
r = db.build_dict_from_row(dataset)

r['version'] = db.build_dict_from_row(dataset_version)
r['version']['available_from'] = r['version']['available_from'].strftime('%Y-%m-%d %H:%M')
r['version']['available_from'] = r['version']['available_from'].strftime('%Y-%m-%d')

r['has_image'] = dataset.has_image()

Expand All @@ -44,25 +45,120 @@ def build_dataset_structure(dataset_version, user=None, dataset=None):

return r


class ListDatasets(handlers.UnsafeHandler):
def get(self):
# List all datasets available to the current user, earliear than now OR
# versions that are available in the future that the user is admin of.
user = self.current_user

ret = []
if user:
futures = db.DatasetVersion.select(
).join(
db.Dataset
).join(
db.DatasetAccess
).where(
db.DatasetVersion.available_from > datetime.now(),
db.DatasetAccess.user == user,
db.DatasetAccess.is_admin
)
for f in futures:
dataset = build_dataset_structure(f, user)
dataset['future'] = True
ret.append( dataset )

for version in db.DatasetVersionCurrent.select():
ret.append( build_dataset_structure(version, user) )
dataset = build_dataset_structure(version, user)
dataset['current'] = True
ret.append( dataset )

self.finish({'data':ret})


class DatasetFiles(handlers.UnsafeHandler):
class GetDataset(handlers.UnsafeHandler):
def get(self, dataset, version=None, *args, **kwargs):
user = self.current_user

current_version = False
future_version = False
dataset = db.get_dataset(dataset)
if version:
version = db.DatasetVersion.select().where(
db.DatasetVersion.version == version,
db.DatasetVersion.dataset == dataset
).get()
else:
version = dataset.current_version.get()
current_version = True

if version.available_from > datetime.now():
# If it's not available yet, only return if user is admin.
if not (user and user.is_admin(dataset)):
self.send_error(status_code=403)
return
future_version = True
elif not current_version:
# Make another check on whether this is the current version
cv = dataset.current_version.get()
current_version = cv.version == version.version

ret = build_dataset_structure(version, user, dataset)
ret['current'] = current_version
ret['future'] = future_version

self.finish(ret)


class ListDatasetVersions(handlers.UnsafeHandler):
def get(self, dataset, *args, **kwargs):
user = self.current_user
dataset = db.get_dataset(dataset)

versions = db.DatasetVersion.select(
db.DatasetVersion.version, db.DatasetVersion.available_from
).where(
db.DatasetVersion.dataset == dataset
)
logging.info("ListDatasetVersions")

data = []
found_current = False
for v in reversed(versions):
current = False
future = False

# Skip future versions unless admin
if v.available_from > datetime.now():
if not (user and user.is_admin(dataset)):
continue
future = True

# Figure out if this is the current version
if not found_current and v.available_from < datetime.now():
found_current = True
current = True

data.insert(0, {
'name': v.version,
'available_from': v.available_from.strftime('%Y-%m-%d'),
'current': current,
'future': future,
})

self.finish({'data': data})


class DatasetFiles(handlers.AuthorizedHandler):
def get(self, dataset, version=None, *args, **kwargs):
dataset = db.get_dataset(dataset)
version = dataset.current_version.get()
if version:
dataset_version = dataset.versions.where(db.DatasetVersion.version==version).get()
else:
dataset_version = dataset.current_version.get()
ret = []
for f in version.files:
for f in dataset_version.files:
ret.append(db.build_dict_from_row(f))
self.finish({'files': ret})

Expand Down Expand Up @@ -93,18 +189,6 @@ def get(self, dataset, *args, **kwargs):
self.finish(ret)


class GetDataset(handlers.UnsafeHandler):
def get(self, dataset, *args, **kwargs):
user = self.current_user

dataset = db.get_dataset(dataset)
current_version = dataset.current_version.get()

ret = build_dataset_structure(current_version, user, dataset)

self.finish(ret)


class GetUser(handlers.UnsafeHandler):
def get(self, *args, **kwargs):
user = self.current_user
Expand Down
2 changes: 1 addition & 1 deletion tornado/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ class EnumField(Field):

def __init__(self, values=[], *args, **kwargs):
self.values = values
super(EnumField, self).__init__(*args, **kwargs)
super().__init__(*args, **kwargs)

def db_value(self, value):
if value not in self.values:
Expand Down
13 changes: 10 additions & 3 deletions tornado/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import peewee
import tornado.auth
import tornado.web
import tornado.template as template
import os.path

import db
Expand Down Expand Up @@ -71,7 +70,7 @@ def prepare(self):

class AuthorizedHandler(SafeHandler):
def prepare(self):
super(AuthorizedHandler, self).prepare()
super().prepare()

if self._finished:
return
Expand All @@ -84,7 +83,7 @@ def prepare(self):

class AdminHandler(SafeHandler):
def prepare(self):
super(AdminHandler, self).prepare()
super().prepare()

if self._finished:
return
Expand Down Expand Up @@ -193,3 +192,11 @@ def get(self, dataset, file):
self.set_header("X-Accel-Redirect", abspath)
self.set_header("Content-Disposition", "attachment")
self.finish()


class AngularTemplate(UnsafeHandler):
def initialize(self, path):
self.root = path

def get(self, path, *args, **kwargs):
self.render(self.root + path)
2 changes: 2 additions & 0 deletions tornado/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
appdirs==1.4.3
Jinja2==2.9.6
MarkupSafe==1.0
mysqlclient==1.3.10
packaging==16.8
peewee==2.9.2
Expand Down
63 changes: 38 additions & 25 deletions tornado/route.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import handlers
import settings
import beacon
import template


define("port", default=4000, help="run on the given port", type=int)
define("develop", default=False, help="Run in develop environment", type=bool)
Expand All @@ -24,44 +26,55 @@
},
"contact_person": '[email protected]',
"redirect_uri": redirect_uri,
"template_path": "templates/",
"xsrf_cookies": True,
"template_loader": template.Jinja2TemplateLoader('templates/'),
}

class Application(tornado.web.Application):
def __init__(self, settings):
self.declared_handlers = [
## Angular templates
(r"/static/js/ng-templates/(?P<path>.*)", handlers.AngularTemplate,
{"path": "ng-templates/"}),
## Static handlers
(r"/static/(.*)", tornado.web.StaticFileHandler, {"path": "static/"}),
(r'/(favicon.ico)', tornado.web.StaticFileHandler, {"path": "static/img/"}),
(r"/release/(?P<dataset>[^\/]+)/(?P<file>.*)", handlers.AuthorizedStaticNginxFileHanlder, {"path": "/release-files/"}),
(r"/static/(.*)", tornado.web.StaticFileHandler,
{"path": "static/"}),
(r'/(favicon.ico)', tornado.web.StaticFileHandler,
{"path": "static/img/"}),
(r"/release/(?P<dataset>[^\/]+)/(?P<file>.*)", handlers.AuthorizedStaticNginxFileHanlder,
{"path": "/release-files/"}),
## Authentication
("/login", handlers.LoginHandler),
("/logout", handlers.LogoutHandler),
("/login", handlers.LoginHandler),
("/logout", handlers.LogoutHandler),
## API Methods
("/api/countries", application.CountryList),
("/api/users/me", application.GetUser),
("/api/countries", application.CountryList),
("/api/users/me", application.GetUser),
### Dataset Api
("/api/datasets", application.ListDatasets),
("/api/datasets/(?P<dataset>[^\/]+)", application.GetDataset),
("/api/datasets/(?P<dataset>[^\/]+)/log/(?P<event>[^\/]+)", application.LogEvent),
("/api/datasets/(?P<dataset>[^\/]+)/logo", application.ServeLogo),
("/api/datasets/(?P<dataset>[^\/]+)/files", application.DatasetFiles),
("/api/datasets/(?P<dataset>[^\/]+)/collection", application.Collection),
("/api/datasets/(?P<dataset>[^\/]+)/users_current", application.DatasetUsersCurrent),
("/api/datasets/(?P<dataset>[^\/]+)/users_pending", application.DatasetUsersPending),
("/api/datasets/(?P<dataset>[^\/]+)/users/(?P<email>[^\/]+)/request", application.RequestAccess),
("/api/datasets/(?P<dataset>[^\/]+)/users/(?P<email>[^\/]+)/approve", application.ApproveUser),
("/api/datasets/(?P<dataset>[^\/]+)/users/(?P<email>[^\/]+)/revoke", application.RevokeUser),
("/api/datasets", application.ListDatasets),
("/api/datasets/(?P<dataset>[^\/]+)", application.GetDataset),
("/api/datasets/(?P<dataset>[^\/]+)/log/(?P<event>[^\/]+)", application.LogEvent),
("/api/datasets/(?P<dataset>[^\/]+)/logo", application.ServeLogo),
("/api/datasets/(?P<dataset>[^\/]+)/files", application.DatasetFiles),
("/api/datasets/(?P<dataset>[^\/]+)/collection", application.Collection),
("/api/datasets/(?P<dataset>[^\/]+)/users_current", application.DatasetUsersCurrent),
("/api/datasets/(?P<dataset>[^\/]+)/users_pending", application.DatasetUsersPending),
("/api/datasets/(?P<dataset>[^\/]+)/users/(?P<email>[^\/]+)/request", application.RequestAccess),
("/api/datasets/(?P<dataset>[^\/]+)/users/(?P<email>[^\/]+)/approve", application.ApproveUser),
("/api/datasets/(?P<dataset>[^\/]+)/users/(?P<email>[^\/]+)/revoke", application.RevokeUser),
("/api/datasets/(?P<dataset>[^\/]+)/versions", application.ListDatasetVersions),
("/api/datasets/(?P<dataset>[^\/]+)/versions/(?P<version>[^\/]+)", application.GetDataset),
("/api/datasets/(?P<dataset>[^\/]+)/versions/(?P<version>[^\/]+)/files", application.DatasetFiles),
### Beacon API
("/api/beacon/query", beacon.Query),
("/api/beacon/info", beacon.Info),
("/api/beacon/query", beacon.Query),
("/api/beacon/info", beacon.Info),
# # # # # Legacy beacon URIs # # # # #
("/query", beacon.Query),
("/info", tornado.web.RedirectHandler, {"url": "/api/beacon/info"}),
("/query", beacon.Query),
("/info", tornado.web.RedirectHandler,
{"url": "/api/beacon/info"}),
## Catch all
("/api/.*", tornado.web.ErrorHandler, {"status_code": 404} ),
(r'.*', application.Home),
("/api/.*", tornado.web.ErrorHandler,
{"status_code": 404} ),
(r'.*', application.Home),
]

# google oauth key
Expand Down
19 changes: 19 additions & 0 deletions tornado/static/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,25 @@ ul.samples li:first-child {
padding: 2px 0 2px 7px;
}

.dataset-future {
background-color: #BE8542;
}

.dataset-panel .future {
font-style: italic;
font-size: 90%;
color: #900;
}

li.future {
font-style: italic;
background-color: #f2dede;
}

.alert-future {
font-size: 200%;
}

.dataset-body {
overflow: hidden;
height: 100%;
Expand Down
Loading

0 comments on commit 7b670e9

Please sign in to comment.