Skip to content

Commit

Permalink
Reorganizes files for consistency between repos. Completely refactors…
Browse files Browse the repository at this point in the history
… Dockerfile to install from wheel.
  • Loading branch information
ajlouie committed May 24, 2020
1 parent 8fa36b9 commit a633cc7
Show file tree
Hide file tree
Showing 14 changed files with 353 additions and 163 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
__pycache__/
app.db
static/.webassets-cache*
static/*.css
pb/static/*.css
78 changes: 48 additions & 30 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,30 +1,48 @@
FROM python:3.7

ENV PATH=/root/.local/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

# install node and yarn
RUN apt-get update
RUN apt-get -y install postgresql-client libpcre3 libpcre3-dev

# config project dir
RUN mkdir /protocol-builder-mock
WORKDIR /protocol-builder-mock

# install python requirements
RUN pip install pipenv
ADD Pipfile /protocol-builder-mock/
ADD Pipfile.lock /protocol-builder-mock/
RUN pipenv install --dev

# include rejoiner code (gets overriden by local changes)
COPY . /protocol-builder-mock/

ENV FLASK_APP=/protocol-builder-mock/app.py

# run webserver by default
CMD ["pipenv", "run", "python", "/protocol-builder-mock/run.py"]

# expose ports
EXPOSE 5001


#
# https://medium.com/@greut/building-a-python-package-a-docker-image-using-pipenv-233d8793b6cc
# https://github.com/greut/pipenv-to-wheel
#
FROM kennethreitz/pipenv as pipenv

ADD . /app
WORKDIR /app

RUN pipenv install --dev \
&& pipenv lock -r > requirements.txt \
&& pipenv run python setup.py bdist_wheel

# ----------------------------------------------------------------------------
FROM ubuntu:bionic

ARG DEBIAN_FRONTEND=noninteractive

COPY --from=pipenv /app/dist/*.whl .

RUN set -xe \
&& apt-get update -q \
&& apt-get install -y -q \
python3-minimal \
python3-wheel \
python3-pip \
gunicorn3 \
postgresql-client \
&& python3 -m pip install *.whl \
&& apt-get remove -y python3-pip python3-wheel \
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -f *.whl \
&& rm -rf /root/.cache \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir -p /app \
&& useradd _gunicorn --no-create-home --user-group

USER _gunicorn

COPY ./static /app/static
COPY ./docker_run.sh /app/
COPY ./wait-for-it.sh /app/
WORKDIR /app

CMD ["gunicorn3", \
"--bind", "0.0.0.0:8000", \
"pb:app"]
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]
pbr = "*"

[packages]
flask = "*"
Expand Down
257 changes: 146 additions & 111 deletions Pipfile.lock

Large diffs are not rendered by default.

10 changes: 4 additions & 6 deletions app.py → pb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from sqlalchemy import func

from wtforms.ext.appengine.db import model_form

PROTOCOLS = {}
Expand Down Expand Up @@ -40,8 +39,7 @@ def get_study_details(studyid):
def get_form(id, requirement_code):
return


conn = connexion.App('Protocol Builder', specification_dir='./')
conn = connexion.App('Protocol Builder', specification_dir='pb')

app = conn.app

Expand All @@ -66,7 +64,7 @@ def get_form(id, requirement_code):

# Loads all the descriptions from the API so we can display them in the editor.
description_map = {}
with open(r'api.yml') as file:
with open(r'pb/api.yml') as file:
api_config = yaml.load(file, Loader=yaml.FullLoader)
study_detail_properties = api_config['components']['schemas']['StudyDetail']['properties']
for schema in api_config['components']['schemas']:
Expand Down Expand Up @@ -98,8 +96,8 @@ def site_map():
# **************************
# WEB FORMS
# **************************
from forms import StudyForm, StudyTable, InvestigatorForm, StudyDetailsForm
from models import Study, RequiredDocument, Investigator, StudySchema, RequiredDocumentSchema, InvestigatorSchema, \
from pb.forms import StudyForm, StudyTable, InvestigatorForm, StudyDetailsForm
from pb.models import Study, RequiredDocument, Investigator, StudySchema, RequiredDocumentSchema, InvestigatorSchema, \
StudyDetails, StudyDetailsSchema


Expand Down
8 changes: 4 additions & 4 deletions api.yml → pb/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ paths:
tags:
- CR-Connect
summary: A list of all studies related to a given UVA ID
operationId: app.get_user_studies
operationId: pb.get_user_studies
description: "By passing in a valid UVA Id (ex: dhf8r) it will return a list of all studies that exist for that user in Protocol Builder"
parameters:
- in: query
Expand Down Expand Up @@ -49,7 +49,7 @@ paths:
tags:
- CR-Connect
summary: Required documents
operationId: app.required_docs
operationId: pb.required_docs
description: A list of all documents Protocol Builder considers required, given input from the PI
parameters:
- in: query
Expand All @@ -72,7 +72,7 @@ paths:
tags:
- CR-Connect
summary: Personnel associated with this study.
operationId: app.investigators
operationId: pb.investigators
description: A list of everyone that is associated with the study, including the PI, Study Coordinator, etc... This is currently returned on the "study" endpoint with other information.
parameters:
- in: query
Expand Down Expand Up @@ -101,7 +101,7 @@ paths:
get:
tags:
- CR-Connect
operationId: app.get_study_details
operationId: pb.get_study_details
summary: Details about a specific protocol.
responses:
200:
Expand Down
9 changes: 3 additions & 6 deletions forms.py → pb/forms.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import sys

from flask_table import Table, Col, DateCol, LinkCol, BoolCol, DatetimeCol, NestedTableCol
from flask_table import Table, Col, LinkCol, BoolCol, DatetimeCol, NestedTableCol
from flask_wtf import FlaskForm
from wtforms import SelectMultipleField, SubmitField, StringField, IntegerField, BooleanField, DateField, widgets, \
SelectField, validators, HiddenField
from wtforms import SelectMultipleField, StringField, BooleanField, SelectField, validators, HiddenField
from wtforms_alchemy import ModelForm

from models import RequiredDocument, Investigator, StudyDetails
from pb.models import RequiredDocument, Investigator, StudyDetails


class StudyForm(FlaskForm):
Expand Down
2 changes: 1 addition & 1 deletion models.py → pb/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from sqlalchemy import func
from app import db, ma
from pb import db, ma


class Study(db.Model):
Expand Down
2 changes: 1 addition & 1 deletion run.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from app import app
from pb import app
if __name__ == "__main__":
flask_port = app.config['FLASK_PORT']
app.run(host='0.0.0.0', port=flask_port)
5 changes: 5 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[metadata]
name = pb

[files]
packages = pb
3 changes: 3 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from setuptools import setup

setup(setup_requires=["pbr"], pbr=True)
133 changes: 133 additions & 0 deletions static/app.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
.mat-icon {
font-family: 'Material Icons', sans-serif;
font-size: 24px; }

.text-center {
text-align: center; }

html, body {
padding: 1em;
margin: 0;
font-family: Arial, sans-serif;
font-size: 16px; }

table {
border: 1px solid #cacaca;
background-color: white;
width: 100%;
text-align: left;
border-collapse: collapse; }
table th, table td {
padding: 0.5em; }
table td, table.blueTable th {
border: 1px solid #cacaca; }
table tbody td {
font-size: 14px; }
table tr:nth-child(even) {
background: #ededed; }
table thead {
background-color: #495e9d; }
table thead th {
font-size: 16px;
font-weight: bold;
color: white;
border-left: 1px solid #cacaca; }
table thead th:first-child {
border-left: none; }
table tfoot {
font-size: 16px;
font-weight: bold;
color: white;
background-color: #cacaca; }
table tfoot td {
font-size: 16px; }
table tfoot .links {
text-align: right; }
table tfoot .links a {
display: inline-block;
background: #495e9d;
color: white;
padding: 2px 8px;
border-radius: 5px; }

.btn {
font-size: 16px;
padding: 0.5em 1em;
border-radius: 5px;
text-decoration: none;
color: white;
white-space: nowrap;
border: none; }
.btn:hover {
text-decoration: none; }
.btn.btn-icon {
font-family: 'Material Icons', sans-serif;
font-size: 24px;
border: none; }
.btn.btn-icon.btn-default {
color: #4e4e4e;
background-color: transparent;
border: none; }
.btn.btn-icon.btn-default:hover {
color: #373737;
background-color: transparent; }
.btn.btn-icon.btn-primary {
color: #232D4B;
background-color: transparent; }
.btn.btn-icon.btn-primary:hover {
color: #191f34;
background-color: transparent; }
.btn.btn-icon.btn-accent {
color: #E57200;
background-color: transparent; }
.btn.btn-icon.btn-accent:hover {
color: #a05000;
background-color: transparent; }
.btn.btn-icon.btn-warn {
color: #DF1E43;
background-color: transparent; }
.btn.btn-icon.btn-warn:hover {
color: #9c152f;
background-color: transparent; }
.btn.btn-default {
color: #373737;
background-color: white;
border: 1px solid #cacaca; }
.btn.btn-default:hover {
background-color: #ededed; }
.btn.btn-primary {
background-color: #232D4B; }
.btn.btn-primary:hover {
background-color: #191f34; }
.btn.btn-warn {
background-color: #DF1E43; }
.btn.btn-warn:hover {
background-color: #9c152f; }
.btn.btn-accent {
background-color: #E57200; }
.btn.btn-accent:hover {
background-color: #a05000; }

select.multi {
height: 600px; }

.form-field {
display: flex;
width: 100%;
margin-bottom: 40px;
padding: 2em; }
.form-field:nth-child(even) {
background-color: #ededed; }
.form-field .form-field-label, .form-field .form-field-help,
.form-field .form-field-input {
width: 30%;
text-align: left;
margin-right: 40px; }
.form-field .form-field-label {
font-weight: bold; }
.form-field .form-field-input input {
width: 100%; }
.form-field .form-field-help {
font-style: italic; }
.form-field .form-field-error {
color: #DF1E43; }
Empty file added tests/__init__.py
Empty file.
6 changes: 3 additions & 3 deletions test_sanity.py → tests/test_sanity.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
os.environ["TESTING"] = "true"

import unittest
from app import app, db
from forms import StudyForm
from models import Study, RequiredDocument
from pb import app, db
from pb.forms import StudyForm
from pb.models import Study, RequiredDocument


class Sanity_Check_Test(unittest.TestCase):
Expand Down

0 comments on commit a633cc7

Please sign in to comment.