mirror of
https://github.com/sartography/protocol-builder-mock.git
synced 2025-02-11 15:16:44 +00:00
Merge branch 'master' of github.com:sartography/protocol-builder-mock
This commit is contained in:
commit
085fee7f31
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
.idea
|
||||
__pycache__/
|
||||
app.db
|
||||
app.db
|
||||
static/.webassets-cache*
|
||||
static/*.css
|
||||
|
2
Pipfile
2
Pipfile
@ -12,6 +12,7 @@ gevent = "*"
|
||||
flask-wtf = "*"
|
||||
sqlalchemy = "*"
|
||||
flask-sqlalchemy = "*"
|
||||
flask-assets = "*"
|
||||
flask-table = "*"
|
||||
flask-migrate = "*"
|
||||
flask-marshmallow = "*"
|
||||
@ -19,6 +20,7 @@ ma = "*"
|
||||
marshmallow-sqlalchemy = "*"
|
||||
wtforms-alchemy = "*"
|
||||
psycopg2-binary = "*"
|
||||
pyscss = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.7"
|
||||
|
139
Pipfile.lock
generated
139
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "b6f0cb3d5c8381e79ffc0d4cab429cf5cc449f17bbebed93f9066e88fb2480f5"
|
||||
"sha256": "d08ffb3e7cd1b35e9acf7581587157d4f9577b937b3f4a0289ac7ab7a0b2134e"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@ -18,9 +18,9 @@
|
||||
"default": {
|
||||
"alembic": {
|
||||
"hashes": [
|
||||
"sha256:035ab00497217628bf5d0be82d664d8713ab13d37b630084da8e1f98facf4dbf"
|
||||
"sha256:2df2519a5b002f881517693b95626905a39c5faf4b5a1f94de4f1441095d1d26"
|
||||
],
|
||||
"version": "==1.4.2"
|
||||
"version": "==1.4.0"
|
||||
},
|
||||
"attrs": {
|
||||
"hashes": [
|
||||
@ -52,10 +52,10 @@
|
||||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
|
||||
"sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
|
||||
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
|
||||
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
|
||||
],
|
||||
"version": "==7.1.1"
|
||||
"version": "==7.0"
|
||||
},
|
||||
"clickclick": {
|
||||
"hashes": [
|
||||
@ -77,10 +77,10 @@
|
||||
},
|
||||
"decorator": {
|
||||
"hashes": [
|
||||
"sha256:41fa54c2a0cc4ba648be4fd43cff00aedf5b9465c9bf18d64325bc225f08f760",
|
||||
"sha256:e3a62f0520172440ca0dcc823749319382e377f37f140a0b99ef45fecb84bfe7"
|
||||
"sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce",
|
||||
"sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"
|
||||
],
|
||||
"version": "==4.4.2"
|
||||
"version": "==4.4.1"
|
||||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
@ -90,6 +90,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"flask-assets": {
|
||||
"hashes": [
|
||||
"sha256:1dfdea35e40744d46aada72831f7613d67bf38e8b20ccaaa9e91fdc37aa3b8c2",
|
||||
"sha256:2845bd3b479be9db8556801e7ebc2746ce2d9edb4e7b64a1c786ecbfc1e5867b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.0"
|
||||
},
|
||||
"flask-babel": {
|
||||
"hashes": [
|
||||
"sha256:247f4ec34cf605d03781f480bccb1a5acb719df1d1a2a743c091ab3db5d5fde2",
|
||||
@ -107,11 +115,11 @@
|
||||
},
|
||||
"flask-migrate": {
|
||||
"hashes": [
|
||||
"sha256:4dc4a5cce8cbbb06b8dc963fd86cf8136bd7d875aabe2d840302ea739b243732",
|
||||
"sha256:a69d508c2e09d289f6e55a417b3b8c7bfe70e640f53d2d9deb0d056a384f37ee"
|
||||
"sha256:6fb038be63d4c60727d5dfa5f581a6189af5b4e2925bc378697b4f0a40cfb4e1",
|
||||
"sha256:a96ff1875a49a40bd3e8ac04fce73fdb0870b9211e6168608cbafa4eb839d502"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.5.3"
|
||||
"version": "==2.5.2"
|
||||
},
|
||||
"flask-sqlalchemy": {
|
||||
"hashes": [
|
||||
@ -262,10 +270,9 @@
|
||||
},
|
||||
"mako": {
|
||||
"hashes": [
|
||||
"sha256:3139c5d64aa5d175dbafb95027057128b5fbd05a40c53999f3905ceb53366d9d",
|
||||
"sha256:8e8b53c71c7e59f3de716b6832c4e401d903af574f6962edbbbf6ecc2a5fe6c9"
|
||||
"sha256:2984a6733e1d472796ceef37ad48c26f4a984bb18119bb2dbc37a44d8f6e75a4"
|
||||
],
|
||||
"version": "==1.1.2"
|
||||
"version": "==1.1.1"
|
||||
},
|
||||
"markupsafe": {
|
||||
"hashes": [
|
||||
@ -307,18 +314,18 @@
|
||||
},
|
||||
"marshmallow": {
|
||||
"hashes": [
|
||||
"sha256:90854221bbb1498d003a0c3cc9d8390259137551917961c8b5258c64026b2f85",
|
||||
"sha256:ac2e13b30165501b7d41fc0371b8df35944f5849769d136f20e2c5f6cdc6e665"
|
||||
"sha256:3a94945a7461f2ab4df9576e51c97d66bee2c86155d3d3933fab752b31effab8",
|
||||
"sha256:4b95c7735f93eb781dfdc4dded028108998cad759dda8dd9d4b5b4ac574cbf13"
|
||||
],
|
||||
"version": "==3.5.1"
|
||||
"version": "==3.5.0"
|
||||
},
|
||||
"marshmallow-sqlalchemy": {
|
||||
"hashes": [
|
||||
"sha256:9301c6fd197bd97337820ea1417aa1233d0ee3e22748ebd5821799bc841a57e8",
|
||||
"sha256:dde9e20bcb710e9e59f765a38e3d6d17f1b2d6b4320cbdc2cea0f6b57f70d08c"
|
||||
"sha256:a370e247216e1a005277d92079d2f0d8d5b0a70fba68ee645730f6a1200991d1",
|
||||
"sha256:f3155e87717e3a52def3a177b4022fd0500e71f626cbb0672adcb95588a99aa3"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.22.3"
|
||||
"version": "==0.22.2"
|
||||
},
|
||||
"openapi-spec-validator": {
|
||||
"hashes": [
|
||||
@ -328,50 +335,19 @@
|
||||
],
|
||||
"version": "==0.2.8"
|
||||
},
|
||||
"psycopg2-binary": {
|
||||
"hashes": [
|
||||
"sha256:040234f8a4a8dfd692662a8308d78f63f31a97e1c42d2480e5e6810c48966a29",
|
||||
"sha256:086f7e89ec85a6704db51f68f0dcae432eff9300809723a6e8782c41c2f48e03",
|
||||
"sha256:18ca813fdb17bc1db73fe61b196b05dd1ca2165b884dd5ec5568877cabf9b039",
|
||||
"sha256:19dc39616850342a2a6db70559af55b22955f86667b5f652f40c0e99253d9881",
|
||||
"sha256:2166e770cb98f02ed5ee2b0b569d40db26788e0bf2ec3ae1a0d864ea6f1d8309",
|
||||
"sha256:3a2522b1d9178575acee4adf8fd9f979f9c0449b00b4164bb63c3475ea6528ed",
|
||||
"sha256:3aa773580f85a28ffdf6f862e59cb5a3cc7ef6885121f2de3fca8d6ada4dbf3b",
|
||||
"sha256:3b5deaa3ee7180585a296af33e14c9b18c218d148e735c7accf78130765a47e3",
|
||||
"sha256:407af6d7e46593415f216c7f56ba087a9a42bd6dc2ecb86028760aa45b802bd7",
|
||||
"sha256:4c3c09fb674401f630626310bcaf6cd6285daf0d5e4c26d6e55ca26a2734e39b",
|
||||
"sha256:4c6717962247445b4f9e21c962ea61d2e884fc17df5ddf5e35863b016f8a1f03",
|
||||
"sha256:50446fae5681fc99f87e505d4e77c9407e683ab60c555ec302f9ac9bffa61103",
|
||||
"sha256:5057669b6a66aa9ca118a2a860159f0ee3acf837eda937bdd2a64f3431361a2d",
|
||||
"sha256:5dd90c5438b4f935c9d01fcbad3620253da89d19c1f5fca9158646407ed7df35",
|
||||
"sha256:659c815b5b8e2a55193ede2795c1e2349b8011497310bb936da7d4745652823b",
|
||||
"sha256:69b13fdf12878b10dc6003acc8d0abf3ad93e79813fd5f3812497c1c9fb9be49",
|
||||
"sha256:7a1cb80e35e1ccea3e11a48afe65d38744a0e0bde88795cc56a4d05b6e4f9d70",
|
||||
"sha256:7e6e3c52e6732c219c07bd97fff6c088f8df4dae3b79752ee3a817e6f32e177e",
|
||||
"sha256:7f42a8490c4fe854325504ce7a6e4796b207960dabb2cbafe3c3959cb00d1d7e",
|
||||
"sha256:84156313f258eafff716b2961644a4483a9be44a5d43551d554844d15d4d224e",
|
||||
"sha256:8578d6b8192e4c805e85f187bc530d0f52ba86c39172e61cd51f68fddd648103",
|
||||
"sha256:890167d5091279a27e2505ff0e1fb273f8c48c41d35c5b92adbf4af80e6b2ed6",
|
||||
"sha256:98e10634792ac0e9e7a92a76b4991b44c2325d3e7798270a808407355e7bb0a1",
|
||||
"sha256:9aadff9032e967865f9778485571e93908d27dab21d0fdfdec0ca779bb6f8ad9",
|
||||
"sha256:9f24f383a298a0c0f9b3113b982e21751a8ecde6615494a3f1470eb4a9d70e9e",
|
||||
"sha256:a73021b44813b5c84eda4a3af5826dd72356a900bac9bd9dd1f0f81ee1c22c2f",
|
||||
"sha256:afd96845e12638d2c44d213d4810a08f4dc4a563f9a98204b7428e567014b1cd",
|
||||
"sha256:b73ddf033d8cd4cc9dfed6324b1ad2a89ba52c410ef6877998422fcb9c23e3a8",
|
||||
"sha256:b8f490f5fad1767a1331df1259763b3bad7d7af12a75b950c2843ba319b2415f",
|
||||
"sha256:dbc5cd56fff1a6152ca59445178652756f4e509f672e49ccdf3d79c1043113a4",
|
||||
"sha256:eac8a3499754790187bb00574ab980df13e754777d346f85e0ff6df929bcd964",
|
||||
"sha256:eaed1c65f461a959284649e37b5051224f4db6ebdc84e40b5e65f2986f101a08"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.8.4"
|
||||
},
|
||||
"pyrsistent": {
|
||||
"hashes": [
|
||||
"sha256:cdc7b5e3ed77bed61270a47d35434a30617b9becdf2478af76ad2c6ade307280"
|
||||
],
|
||||
"version": "==0.15.7"
|
||||
},
|
||||
"pyscss": {
|
||||
"hashes": [
|
||||
"sha256:14a25c33c221a66bb1f000a6a067f376528d3df2f9333cee9c95709a9280cdb0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.3.5"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
|
||||
@ -396,19 +372,19 @@
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
"sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97",
|
||||
"sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76",
|
||||
"sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2",
|
||||
"sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648",
|
||||
"sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf",
|
||||
"sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f",
|
||||
"sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2",
|
||||
"sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee",
|
||||
"sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d",
|
||||
"sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c",
|
||||
"sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"
|
||||
"sha256:059b2ee3194d718896c0ad077dd8c043e5e909d9180f387ce42012662a4946d6",
|
||||
"sha256:1cf708e2ac57f3aabc87405f04b86354f66799c8e62c28c5fc5f88b5521b2dbf",
|
||||
"sha256:24521fa2890642614558b492b473bee0ac1f8057a7263156b02e8b14c88ce6f5",
|
||||
"sha256:4fee71aa5bc6ed9d5f116327c04273e25ae31a3020386916905767ec4fc5317e",
|
||||
"sha256:70024e02197337533eef7b85b068212420f950319cc8c580261963aefc75f811",
|
||||
"sha256:74782fbd4d4f87ff04159e986886931456a1894c61229be9eaf4de6f6e44b99e",
|
||||
"sha256:940532b111b1952befd7db542c370887a8611660d2b9becff75d39355303d82d",
|
||||
"sha256:cb1f2f5e426dc9f07a7681419fe39cee823bb74f723f36f70399123f439e9b20",
|
||||
"sha256:dbbb2379c19ed6042e8f11f2a2c66d39cceb8aeace421bfc29d085d93eda3689",
|
||||
"sha256:e3a057b7a64f1222b56e47bcff5e4b94c4f61faac04c7c4ecb1985e18caa3994",
|
||||
"sha256:e9f45bd5b92c7974e59bcd2dcc8631a6b6cc380a904725fce7bc08872e691615"
|
||||
],
|
||||
"version": "==5.3.1"
|
||||
"version": "==5.3"
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
@ -426,16 +402,16 @@
|
||||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
"sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"
|
||||
"sha256:64a7b71846db6423807e96820993fa12a03b89127d278290ca25c0b11ed7b4fb"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.3.15"
|
||||
"version": "==1.3.13"
|
||||
},
|
||||
"sqlalchemy-utils": {
|
||||
"hashes": [
|
||||
"sha256:f268af5bc03597fe7690d60df3e5f1193254a83e07e4686f720f61587ec4493a"
|
||||
"sha256:4e637c88bf3ac5f99b7d72342092a1f636bea1287b2e3e17d441b0413771f86e"
|
||||
],
|
||||
"version": "==0.36.3"
|
||||
"version": "==0.36.1"
|
||||
},
|
||||
"swagger-ui-bundle": {
|
||||
"hashes": [
|
||||
@ -458,6 +434,13 @@
|
||||
],
|
||||
"version": "==0.14.2"
|
||||
},
|
||||
"webassets": {
|
||||
"hashes": [
|
||||
"sha256:167132337677c8cedc9705090f6d48da3fb262c8e0b2773b29f3352f050181cd",
|
||||
"sha256:a31a55147752ba1b3dc07dee0ad8c8efff274464e08bbdb88c1fd59ffd552724"
|
||||
],
|
||||
"version": "==2.0"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
|
||||
@ -487,10 +470,10 @@
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
"sha256:aa36550ff0c0b7ef7fa639055d797116ee891440eac1a56f378e2d3179e0320b",
|
||||
"sha256:c599e4d75c98f6798c509911d08a22e6c021d074469042177c8c86fb92eefd96"
|
||||
"sha256:12248a63bbdf7548f89cb4c7cda4681e537031eda29c02ea29674bc6854460c2",
|
||||
"sha256:7c0f8e91abc0dc07a5068f315c52cb30c66bfbc581e5b50704c8a2f6ebae794a"
|
||||
],
|
||||
"version": "==3.1.0"
|
||||
"version": "==3.0.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
|
19
app.py
19
app.py
@ -5,6 +5,7 @@ from datetime import date
|
||||
import connexion
|
||||
import yaml
|
||||
from flask import url_for, json, redirect, render_template, request, flash
|
||||
from flask_assets import Environment, Bundle
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
from flask_marshmallow import Marshmallow
|
||||
from flask_migrate import Migrate
|
||||
@ -58,6 +59,10 @@ else:
|
||||
db = SQLAlchemy(app)
|
||||
migrate = Migrate(app, db)
|
||||
ma = Marshmallow(app)
|
||||
assets = Environment(app)
|
||||
assets.url = app.static_url_path
|
||||
scss = Bundle('scss/app.scss', filters='pyscss', output='app.css')
|
||||
assets.register('app_scss', scss)
|
||||
|
||||
# Loads all the descriptions from the API so we can display them in the editor.
|
||||
description_map = {}
|
||||
@ -184,15 +189,19 @@ def del_study(study_id):
|
||||
def _update_study(study, form):
|
||||
if study.STUDYID:
|
||||
db.session.query(RequiredDocument).filter(RequiredDocument.STUDYID == study.STUDYID).delete()
|
||||
for r in form.requirements:
|
||||
if r.checked:
|
||||
requirement = RequiredDocument(AUXDOCID=r.data, AUXDOC=r.label.text, study=study)
|
||||
db.session.add(requirement)
|
||||
|
||||
study.STUDYID = form.STUDYID.data
|
||||
study.TITLE = form.TITLE.data
|
||||
study.NETBADGEID = form.NETBADGEID.data
|
||||
study.DATE_MODIFIED = datetime.datetime.now()
|
||||
study.Q_COMPLETE = form.Q_COMPLETE.data
|
||||
study.HSRNUMBER = form.HSRNUMBER.data
|
||||
|
||||
for r in form.requirements:
|
||||
if r.checked:
|
||||
requirement = RequiredDocument(AUXDOCID=r.data, AUXDOC=r.label.text, study=study)
|
||||
db.session.add(requirement)
|
||||
|
||||
db.session.add(study)
|
||||
db.session.commit()
|
||||
|
||||
@ -221,4 +230,4 @@ def study_details(study_id):
|
||||
|
||||
if __name__ == '__main__':
|
||||
# run our standalone gevent server
|
||||
app.run(port=4200)
|
||||
app.run(port=4200)
|
||||
|
@ -1,3 +1,3 @@
|
||||
#!/bin/bash
|
||||
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
|
||||
docker push sartography/protocol-builder-mock
|
||||
docker push sartography/protocol-builder-mock || true
|
||||
|
41
forms.py
41
forms.py
@ -1,17 +1,20 @@
|
||||
import sys
|
||||
|
||||
from flask_table import Table, Col, DateCol, LinkCol, BoolCol, DatetimeCol, NestedTableCol
|
||||
from flask_wtf import FlaskForm
|
||||
from wtforms import SelectMultipleField, SubmitField, StringField, IntegerField, BooleanField, DateField, widgets, \
|
||||
SelectField
|
||||
SelectField, validators
|
||||
from wtforms_alchemy import ModelForm
|
||||
|
||||
from models import RequiredDocument, Investigator, StudyDetails
|
||||
|
||||
|
||||
class StudyForm(FlaskForm):
|
||||
TITLE = StringField('Title')
|
||||
NETBADGEID = StringField('UVA Id for Primary Investigator')
|
||||
STUDYID = IntegerField('Study ID', [validators.required(), validators.number_range(min=10000, max=2147483647)])
|
||||
TITLE = StringField('Title', [validators.required()])
|
||||
NETBADGEID = StringField('User UVA Computing Id', [validators.required()])
|
||||
requirements = SelectMultipleField("Requirements",
|
||||
render_kw={'class':'multi'},
|
||||
render_kw={'class': 'multi'},
|
||||
choices=[(rd.AUXDOCID, rd.AUXDOC) for rd in RequiredDocument.all()])
|
||||
HSRNUMBER = StringField('HSR Number')
|
||||
Q_COMPLETE = BooleanField('Complete in Protocol Builder?', default='checked',
|
||||
@ -32,16 +35,36 @@ class RequirementsTable(Table):
|
||||
class InvestigatorsTable(Table):
|
||||
NETBADGEID = Col('UVA Id')
|
||||
INVESTIGATORTYPE = Col('Type')
|
||||
delete = LinkCol('Delete', 'del_investigator', url_kwargs=dict(inv_id='id'))
|
||||
delete = LinkCol(
|
||||
'delete', 'del_investigator', url_kwargs=dict(inv_id='id'),
|
||||
anchor_attrs={'class': 'btn btn-icon btn-warn', 'title': 'Delete Investigator'},
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Delete Investigator'}
|
||||
)
|
||||
|
||||
|
||||
class StudyTable(Table):
|
||||
def sort_url(self, col_id, reverse=False):
|
||||
pass
|
||||
edit = LinkCol('Edit', 'edit_study', url_kwargs=dict(study_id='STUDYID'))
|
||||
delete = LinkCol('Delete', 'del_study', url_kwargs=dict(study_id='STUDYID'))
|
||||
details = LinkCol('Details', 'study_details', url_kwargs=dict(study_id='STUDYID'))
|
||||
add_inv = LinkCol('Add Person', 'new_investigator', url_kwargs=dict(study_id='STUDYID'))
|
||||
edit = LinkCol(
|
||||
'edit', 'edit_study', url_kwargs=dict(study_id='STUDYID'),
|
||||
anchor_attrs={'class': 'btn btn-icon btn-primary', 'title': 'Edit Study'},
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Edit Study'}
|
||||
)
|
||||
delete = LinkCol(
|
||||
'delete', 'del_study', url_kwargs=dict(study_id='STUDYID'),
|
||||
anchor_attrs={'class': 'btn btn-icon btn-warn', 'title': 'Delete Study'},
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Delete Study'}
|
||||
)
|
||||
details = LinkCol(
|
||||
'ballot', 'study_details', url_kwargs=dict(study_id='STUDYID'),
|
||||
anchor_attrs={'class': 'btn btn-icon btn-default', 'title': 'Edit Questions'},
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Edit Questions'}
|
||||
)
|
||||
add_inv = LinkCol(
|
||||
'person_add', 'new_investigator', url_kwargs=dict(study_id='STUDYID'),
|
||||
anchor_attrs={'class': 'btn btn-icon btn-accent', 'title': 'Add Investigator'},
|
||||
th_html_attrs={'class': 'mat-icon text-center', 'title': 'Add Investigator'}
|
||||
)
|
||||
STUDYID = Col('Study Id')
|
||||
TITLE = Col('Title')
|
||||
NETBADGEID = Col('User')
|
||||
|
244
static/scss/app.scss
Normal file
244
static/scss/app.scss
Normal file
@ -0,0 +1,244 @@
|
||||
// COLOR PALETTE
|
||||
|
||||
// gray
|
||||
$color-gray: #4e4e4e;
|
||||
$color-gray-light-2: scale-color($color-gray, $lightness: +90%);
|
||||
$color-gray-light-1: scale-color($color-gray, $lightness: +70%);
|
||||
$color-gray-light: $color-gray-light-1;
|
||||
$color-gray-dark: scale-color($color-gray, $lightness: -30%);
|
||||
|
||||
// primary (UVA "Jefferson Blue")
|
||||
$color-primary: #232D4B;
|
||||
$color-primary-light: scale-color($color-primary, $lightness: +30%);
|
||||
$color-primary-dark: scale-color($color-primary, $lightness: -30%);
|
||||
|
||||
// accent (UVA "Rotunda Orange")
|
||||
$color-accent: #E57200;
|
||||
$color-accent-light: scale-color($color-accent, $lightness: +30%);
|
||||
$color-accent-dark: scale-color($color-accent, $lightness: -30%);
|
||||
|
||||
// warn (UVA "Emergency Red")
|
||||
$color-warn: #DF1E43;
|
||||
$color-warn-light: scale-color($color-warn, $lightness: +30%);
|
||||
$color-warn-dark: scale-color($color-warn, $lightness: -30%);
|
||||
|
||||
$font-size-default: 16px;
|
||||
$font-size-lg: 24px;
|
||||
$font-size-md: 16px;
|
||||
$font-size-sm: 14px;
|
||||
|
||||
@mixin mat-icon {
|
||||
font-family: 'Material Icons', sans-serif;
|
||||
font-size: $font-size-lg;
|
||||
}
|
||||
|
||||
.mat-icon {
|
||||
@include mat-icon;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
html, body {
|
||||
padding: 1em;
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: $font-size-default;
|
||||
}
|
||||
|
||||
table {
|
||||
border: 1px solid $color-gray-light;
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
border-collapse: collapse;
|
||||
|
||||
th, td {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
td, &.blueTable th {
|
||||
border: 1px solid $color-gray-light;
|
||||
}
|
||||
|
||||
tbody td {
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background: $color-gray-light-2;
|
||||
}
|
||||
|
||||
thead {
|
||||
background-color: $color-primary-light;
|
||||
|
||||
th {
|
||||
font-size: $font-size-default;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
border-left: 1px solid $color-gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
thead th:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
tfoot {
|
||||
font-size: $font-size-default;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background-color: $color-gray-light;
|
||||
|
||||
td {
|
||||
font-size: $font-size-default;
|
||||
}
|
||||
|
||||
.links {
|
||||
text-align: right;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
background: $color-primary-light;
|
||||
color: white;
|
||||
padding: 2px 8px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-size: $font-size-default;
|
||||
padding: 0.5em 1em;
|
||||
border-radius: 5px;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
white-space: nowrap;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.btn-icon {
|
||||
@include mat-icon;
|
||||
border: none;
|
||||
|
||||
&.btn-default {
|
||||
color: $color-gray;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
|
||||
&:hover {
|
||||
color: $color-gray-dark;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-primary {
|
||||
color: $color-primary;
|
||||
background-color: transparent;
|
||||
|
||||
&:hover {
|
||||
color: $color-primary-dark;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-accent {
|
||||
color: $color-accent;
|
||||
background-color: transparent;
|
||||
|
||||
&:hover {
|
||||
color: $color-accent-dark;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-warn {
|
||||
color: $color-warn;
|
||||
background-color: transparent;
|
||||
|
||||
&:hover {
|
||||
color: $color-warn-dark;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-default {
|
||||
color: $color-gray-dark;
|
||||
background-color: white;
|
||||
border: 1px solid $color-gray-light;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-gray-light-2;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-primary {
|
||||
background-color: $color-primary;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-primary-dark;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-warn {
|
||||
background-color: $color-warn;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-warn-dark;
|
||||
}
|
||||
}
|
||||
|
||||
&.btn-accent {
|
||||
background-color: $color-accent;
|
||||
|
||||
&:hover {
|
||||
background-color: $color-accent-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
select.multi {
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin-bottom: 40px;
|
||||
padding: 2em;
|
||||
|
||||
&:nth-child(even) {
|
||||
background-color: $color-gray-light-2;
|
||||
}
|
||||
|
||||
.form-field-label,
|
||||
.form-field-help,
|
||||
.form-field-input {
|
||||
width: 30%;
|
||||
text-align: left;
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
.form-field-label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.form-field-input input {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.form-field-help {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.form-field-error {
|
||||
color: $color-warn;
|
||||
}
|
||||
}
|
||||
|
@ -3,38 +3,31 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Protocol Builder Mock Configuration</title>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://use.typekit.net/kwp6dli.css">
|
||||
{% assets 'app_scss' %}
|
||||
<link href="{{ ASSET_URL }}" rel="stylesheet" type="text/css">
|
||||
{% endassets %}
|
||||
</head>
|
||||
<style>
|
||||
select.multi {
|
||||
height: 600px;
|
||||
}
|
||||
input {
|
||||
width: 500px;
|
||||
}
|
||||
span.label {
|
||||
display: inline-block;
|
||||
min-width: 200px;
|
||||
text-align: left;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<h2>{{title}}</h2>
|
||||
<p>{{details}}</p>
|
||||
<form action="{{action}}" method="post">
|
||||
<h2>{{ title }}</h2>
|
||||
<p>{{ details }}</p>
|
||||
<form action="{{ action }}" method="post">
|
||||
|
||||
{{ form.csrf_token() }}
|
||||
|
||||
{% for field in form if field.name != "csrf_token" %}
|
||||
<p>
|
||||
<span class="label">{{ field.label() }}:</span>
|
||||
{{ field }}
|
||||
<i>{{ description_map[field.name] }}</i>
|
||||
<div class="form-field">
|
||||
<div class="form-field-label">{{ field.label() }}:</div>
|
||||
<div class="form-field-input">{{ field }}</div>
|
||||
<div class="form-field-help">{{ description_map[field.name] }}</div>
|
||||
{% for error in field.errors %}
|
||||
{{ error }}
|
||||
<div class="form-field-error">{{ error }}</div>
|
||||
{% endfor %}
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<input type="submit" value="Submit">
|
||||
<button class="btn btn-primary" type="submit">Submit</button>
|
||||
<a href="/" class="btn btn-default">Cancel</a>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
|
@ -1,93 +1,33 @@
|
||||
<doctype html>
|
||||
<head>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Protocol Builder Mock</title>
|
||||
</head>
|
||||
<style>
|
||||
table {
|
||||
border: 1px solid #1C6EA4;
|
||||
background-color: #EEEEEE;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://use.typekit.net/kwp6dli.css">
|
||||
{% assets 'app_scss' %}
|
||||
<link href="{{ ASSET_URL }}" rel="stylesheet" type="text/css">
|
||||
{% endassets %}
|
||||
</head>
|
||||
<body>
|
||||
<h2>Protocol Builder Mock</h2>
|
||||
|
||||
table td, table.blueTable th {
|
||||
border: 1px solid #AAAAAA;
|
||||
padding: 3px 2px;
|
||||
}
|
||||
<p>
|
||||
<a class="btn btn-primary" href="{{ url_for('.new_study') }}"> New Study </a>
|
||||
</p>
|
||||
|
||||
table tbody td {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
table tr:nth-child(even) {
|
||||
background: #D0E4F5;
|
||||
}
|
||||
|
||||
table thead {
|
||||
background: #1C6EA4;
|
||||
background: -moz-linear-gradient(top, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
|
||||
background: -webkit-linear-gradient(top, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
|
||||
background: linear-gradient(to bottom, #5592bb 0%, #327cad 66%, #1C6EA4 100%);
|
||||
border-bottom: 2px solid #444444;
|
||||
}
|
||||
|
||||
table thead th {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
border-left: 2px solid #D0E4F5;
|
||||
}
|
||||
|
||||
table thead th:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
table tfoot {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
background: #D0E4F5;
|
||||
background: -moz-linear-gradient(top, #dcebf7 0%, #d4e6f6 66%, #D0E4F5 100%);
|
||||
background: -webkit-linear-gradient(top, #dcebf7 0%, #d4e6f6 66%, #D0E4F5 100%);
|
||||
background: linear-gradient(to bottom, #dcebf7 0%, #d4e6f6 66%, #D0E4F5 100%);
|
||||
border-top: 2px solid #444444;
|
||||
}
|
||||
|
||||
table tfoot td {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
table tfoot .links {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
table tfoot .links a {
|
||||
display: inline-block;
|
||||
background: #1C6EA4;
|
||||
color: #FFFFFF;
|
||||
padding: 2px 8px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<h2>Protocol Builder Mock</h2>
|
||||
|
||||
<p>
|
||||
<p>
|
||||
<a href="{{ url_for('.new_study') }}"> New Study </a>
|
||||
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
<ul class=flashes>
|
||||
{% for message in messages %}
|
||||
<li>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% with messages = get_flashed_messages() %}
|
||||
{% if messages %}
|
||||
<ul class=flashes>
|
||||
{% for message in messages %}
|
||||
<li>{{ message }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
{% endwith %}
|
||||
|
||||
<h3>Current Studies</h3>
|
||||
{{ table }}
|
||||
<h3>Current Studies</h3>
|
||||
{{ table }}
|
||||
</body>
|
||||
|
||||
</doctype>
|
||||
|
||||
</html>
|
||||
|
Loading…
x
Reference in New Issue
Block a user