diff --git a/Pipfile b/Pipfile
index 535b7e4..59200d4 100644
--- a/Pipfile
+++ b/Pipfile
@@ -9,6 +9,10 @@ verify_ssl = true
flask = "*"
connexion = {extras = ["swagger-ui"],version = "*"}
gevent = "*"
+flask-wtf = "*"
+sqlalchemy = "*"
+flask-sqlalchemy = "*"
+flask-table = "*"
[requires]
python_version = "3.7"
diff --git a/Pipfile.lock b/Pipfile.lock
index 678df94..5ce8cea 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,11 +1,11 @@
{
"_meta": {
"hash": {
- "sha256": "53f3c053174686a450c6276f298ee9678a273d57984d0126070d08fd9b4f97e6"
+ "sha256": "72fff5c0cf2514d4307a4fc4eb60d57cc5bd0bf19603dc77587835bf01e43bd7"
},
"pipfile-spec": 6,
"requires": {
- "python_version": "3.6"
+ "python_version": "3.7"
},
"sources": [
{
@@ -23,6 +23,13 @@
],
"version": "==19.3.0"
},
+ "babel": {
+ "hashes": [
+ "sha256:1aac2ae2d0d8ea368fa90906567f5c08463d98ade155c0c4bfedd6a0f7160e38",
+ "sha256:d670ea0b10f8b723672d3a6abeb87b565b244da220d76b4dba1b66269ec152d4"
+ ],
+ "version": "==2.8.0"
+ },
"certifi": {
"hashes": [
"sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
@@ -56,11 +63,11 @@
"swagger-ui"
],
"hashes": [
- "sha256:3f6c2cb8a3f24af281ff561eebaaa926700b24f4c430f4d945c8ace0384c220c",
- "sha256:56854c65334281b303120a1097df09a79ffa44bdaecfc4400e7194821e17566d"
+ "sha256:bf32bfae6af337cfa4a8489c21516adbe5c50e3f8dc0b7ed2394ce8dde218018",
+ "sha256:c568e579f84be808e387dcb8570bb00a536891be1318718a0dad3ba90f034191"
],
"index": "pypi",
- "version": "==2.5.1"
+ "version": "==2.6.0"
},
"flask": {
"hashes": [
@@ -70,6 +77,36 @@
"index": "pypi",
"version": "==1.1.1"
},
+ "flask-babel": {
+ "hashes": [
+ "sha256:247f4ec34cf605d03781f480bccb1a5acb719df1d1a2a743c091ab3db5d5fde2",
+ "sha256:d6a70468f9a8919d59fba2a291a003da3a05ff884275dddbd965f3b98b09ab3e"
+ ],
+ "version": "==1.0.0"
+ },
+ "flask-sqlalchemy": {
+ "hashes": [
+ "sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327",
+ "sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d"
+ ],
+ "index": "pypi",
+ "version": "==2.4.1"
+ },
+ "flask-table": {
+ "hashes": [
+ "sha256:320e5756cd7252e902e03b6cd1087f2c7ebc31364341b482f41f30074d10a770"
+ ],
+ "index": "pypi",
+ "version": "==0.5.0"
+ },
+ "flask-wtf": {
+ "hashes": [
+ "sha256:57b3faf6fe5d6168bda0c36b0df1d05770f8e205e18332d0376ddb954d17aef2",
+ "sha256:d417e3a0008b5ba583da1763e4db0f55a1269d9dd91dcc3eb3c026d3c5dbd720"
+ ],
+ "index": "pypi",
+ "version": "==0.14.3"
+ },
"gevent": {
"hashes": [
"sha256:0774babec518a24d9a7231d4e689931f31b332c4517a771e532002614e270a64",
@@ -105,7 +142,9 @@
"sha256:0d48200bc50cbf498716712129eef819b1729339e34c3ae71656964dac907c28",
"sha256:23d12eacffa9d0f290c0fe0c4e81ba6d5f3a5b7ac3c30a5eaf0126bf4deda5c8",
"sha256:37c9ba82bd82eb6a23c2e5acc03055c0e45697253b2393c9a50cef76a3985304",
+ "sha256:51155342eb4d6058a0ffcd98a798fe6ba21195517da97e15fca3db12ab201e6e",
"sha256:51503524dd6f152ab4ad1fbd168fc6c30b5795e8c70be4410a64940b3abb55c0",
+ "sha256:7457d685158522df483196b16ec648b28f8e847861adb01a55d41134e7734122",
"sha256:8041e2de00e745c0e05a502d6e6db310db7faa7c979b3a5877123548a4c0b214",
"sha256:81fcd96a275209ef117e9ec91f75c731fa18dcfd9ffaa1c0adbdaa3616a86043",
"sha256:853da4f9563d982e4121fed8c92eea1a4594a2299037b3034c3c898cb8e933d6",
@@ -119,7 +158,8 @@
"sha256:bcb530089ff24f6458a81ac3fa699e8c00194208a724b644ecc68422e1111939",
"sha256:beeabe25c3b704f7d56b573f7d2ff88fc99f0138e43480cecdfcaa3b87fe4f87",
"sha256:d634a7ea1fc3380ff96f9e44d8d22f38418c1c381d5fac680b272d7d90883720",
- "sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656"
+ "sha256:d97b0661e1aead761f0ded3b769044bb00ed5d33e1ec865e891a8b128bf7c656",
+ "sha256:e538b8dae561080b542b0f5af64d47ef859f22517f7eca617bb314e0e03fd7ef"
],
"markers": "platform_python_implementation == 'CPython'",
"version": "==0.4.15"
@@ -133,11 +173,11 @@
},
"importlib-metadata": {
"hashes": [
- "sha256:073a852570f92da5f744a3472af1b61e28e9f78ccf0c9117658dc32b15de7b45",
- "sha256:d95141fbfa7ef2ec65cfd945e2af7e5a6ddbd7c8d9a25e66ff3be8e3daf9f60f"
+ "sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302",
+ "sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"
],
"markers": "python_version < '3.8'",
- "version": "==1.3.0"
+ "version": "==1.5.0"
},
"inflection": {
"hashes": [
@@ -154,10 +194,10 @@
},
"jinja2": {
"hashes": [
- "sha256:74320bb91f31270f9551d46522e33af46a80c3d619f4a4bf42b3164d30b5911f",
- "sha256:9fe95f19286cfefaa917656583d020be14e7859c6b0252588391e47db34527de"
+ "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
+ "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
],
- "version": "==2.10.3"
+ "version": "==2.11.1"
},
"jsonschema": {
"hashes": [
@@ -172,13 +212,16 @@
"sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
"sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
"sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
+ "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42",
"sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
"sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
"sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
"sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
"sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
"sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
+ "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b",
"sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
+ "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15",
"sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
"sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
"sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
@@ -195,17 +238,12 @@
"sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
"sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
"sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
- "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
+ "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2",
+ "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7",
+ "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"
],
"version": "==1.1.1"
},
- "more-itertools": {
- "hashes": [
- "sha256:b84b238cce0d9adad5ed87e745778d20a3f8487d0f0cb8b8a586816c7496458d",
- "sha256:c833ef592a0324bcc6a60e48440da07645063c453880c9477ceb22490aec1564"
- ],
- "version": "==8.0.2"
- },
"openapi-spec-validator": {
"hashes": [
"sha256:0caacd9829e9e3051e830165367bf58d436d9487b29a09220fa7edb9f47ff81b",
@@ -216,9 +254,16 @@
},
"pyrsistent": {
"hashes": [
- "sha256:f3b280d030afb652f79d67c5586157c5c1355c9a58dfc7940566e28d28f3df1b"
+ "sha256:cdc7b5e3ed77bed61270a47d35434a30617b9becdf2478af76ad2c6ade307280"
],
- "version": "==0.15.6"
+ "version": "==0.15.7"
+ },
+ "pytz": {
+ "hashes": [
+ "sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
+ "sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
+ ],
+ "version": "==2019.3"
},
"pyyaml": {
"hashes": [
@@ -245,10 +290,17 @@
},
"six": {
"hashes": [
- "sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
- "sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
+ "sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
+ "sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
],
- "version": "==1.13.0"
+ "version": "==1.14.0"
+ },
+ "sqlalchemy": {
+ "hashes": [
+ "sha256:64a7b71846db6423807e96820993fa12a03b89127d278290ca25c0b11ed7b4fb"
+ ],
+ "index": "pypi",
+ "version": "==1.3.13"
},
"swagger-ui-bundle": {
"hashes": [
@@ -260,24 +312,31 @@
},
"urllib3": {
"hashes": [
- "sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293",
- "sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"
+ "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
+ "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
],
- "version": "==1.25.7"
+ "version": "==1.25.8"
},
"werkzeug": {
"hashes": [
- "sha256:7280924747b5733b246fe23972186c6b348f9ae29724135a6dfc1e53cea433e7",
- "sha256:e5f4a1f98b52b18a93da705a7458e55afb26f32bff83ff5d19189f92462d65c4"
+ "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
+ "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16"
],
- "version": "==0.16.0"
+ "version": "==1.0.0"
+ },
+ "wtforms": {
+ "hashes": [
+ "sha256:0cdbac3e7f6878086c334aa25dc5a33869a3954e9d1e015130d65a69309b3b61",
+ "sha256:e3ee092c827582c50877cdbd49e9ce6d2c5c1f6561f849b3b068c1b8029626f1"
+ ],
+ "version": "==2.2.1"
},
"zipp": {
"hashes": [
- "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e",
- "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335"
+ "sha256:5c56e330306215cd3553342cfafc73dda2c60792384117893f3a83f8a1209f50",
+ "sha256:d65287feb793213ffe11c0f31b81602be31448f38aeb8ffc2eb286c4f6f6657e"
],
- "version": "==0.6.0"
+ "version": "==2.2.0"
}
},
"develop": {}
diff --git a/api.yml b/api.yml
index ee221dc..a5785d3 100644
--- a/api.yml
+++ b/api.yml
@@ -121,10 +121,6 @@ components:
type: number
example: 11770
description: The unique id of the study in Protocol Builder. Sometimes referenced as the "HSR Submission number" if you are looking at Protocol Builder
- PID:
- type: number
- example:
- description: (Protocol_id) is similar to studyid but its for IRB online
HSRNUMBER:
type: number
example: 15378
@@ -211,7 +207,7 @@ components:
type: number
enum: [0,1,null]
example: 1
- description: Unknown
+ description: Was the investigational new drug developed at UVa?
IS_IDE:
type: number
enum: [0,1,null]
@@ -221,7 +217,7 @@ components:
type: number
enum: [0,1,null]
example: 1
- description: Unknown
+ description: Was the investigational device developed at UVa?
IDE_NUMBERS:
type: array
items:
@@ -231,306 +227,268 @@ components:
type: number
enum: [0,1,null]
example: 1
- description: Unknown
+ description: Does this include chart reviews which do not requre the consent of the Study group?
IS_RADIATION:
type: number
enum: [0,1,null]
example: true
- description: Unknown
+ description: Does the Study include radiation treatment?
GCRC_NUMBER:
type: string
- description: Unknown
+ description: The General Clinical Research Center number, if funded by GCRC
IS_GCRC:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will any part of this study take place in or be funded by the General Clinical Research Center?
IS_PRC_DSMP:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Does this protocol involve the testing of a new device or improvement of a method of detection or diagnosis for cancer?
IS_PRC:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Does the Study require Cancer Center Protocol Review Committee oversight?
PRC_NUMBER:
type: string
- description: Unkown
+ description: Cancer Center Protocol Review Committee number
IS_IBC:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will this Study need the approval of the Institutional Biosafety Committee?
IBC_NUMBER:
type: number
enum: [0,1,null]
example: true
- description: Unkown
- IS_SPONSOR_TRACKING:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
- SPONSOR_TRACKING:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
+ description: Site identifier that the location has been approved to handle biological agents by the Institutional Biosafety Committee.
SPONSORS_PROTOCOL_REVISION_DATE:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the study be part of a UVA faculty member's-sponsored Investigational Device application?
IS_SPONSOR_MONITORING:
type: number
enum: [0,1,null]
example: true
- description: Unkown
- IS_DSMB:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
- IS_COMPLETE_NON_IRB_REGULATORY:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
+ description: Will the Sponsor monitor the Study?
IS_AUX:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Is Auxilliary Info needed?
IS_SPONSOR:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Is there an outside sponsor involved?
IS_GRANT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Is grant money funding all or part of the Study?
IS_COMMITTEE_CONFLICT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Does someone on the IRB Review Committee have a conflict of interest?
DSMB:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will this study be monitored by a Data and Safety Monitoring Board?
DSMB_FREQUENCY:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
+ type: String
+ example: A lot
+ description: UNDOCUMENTED.
IS_DB:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Is the ONLY intent of this protocol to establish a research database (repository)?
IS_UVA_DB:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will any of the data be kept at UVA outside of the official medical record or will specimens be kept at UVA outside of clinical labs?
IS_CENTRAL_REG_DB:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will any data from UVA subjects be sent to a central registry or database outside of UVA?
IS_CONSENT_WAIVER:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will there be a consent waiver?
IS_HGT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Are you storing specimens, sequences analysis of DNA/RNA for an unspecified future use.
IS_GENE_TRANSFER:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study involve gene transfer?
IS_TISSUE_BANKING:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study involve tissue banking?
IS_SURROGATE_CONSENT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study require the consent of a surrogate?
IS_ADULT_PARTICIPANT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study group include adults?
IS_MINOR_PARTICIPANT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Are any of the subjects between the ages of 15 and < 18?
IS_MINOR:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Does the study enroll subjects under the age of 18?
IS_BIOMEDICAL:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will this study involve biomedical research?
IS_QUALITATIVE:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will this study involve only qualitative research?
IS_PI_SCHOOL:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will this study be submitted through the PI's current primary school and department appointment?
IS_PRISONERS_POP:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study group include prisoners?
IS_PREGNANT_POP:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study group include pregnant women?
IS_FETUS_POP:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study be done on fetuses?
IS_MENTAL_IMPAIRMENT_POP:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study group include anyone who is mentally impaired?
IS_ELDERLY_POP:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study group include the elderly?
IS_OTHER_VULNERABLE_POP:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study group include other vulnerable populations?
OTHER_VULNERABLE_DESC:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
+ type: string
+ example: homeless people
+ description: Other vulnerable population description
IS_MULTI_SITE:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study be conducted at multiple sites?
IS_UVA_LOCATION:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study be done at UVa?
NON_UVA_LOCATION:
type: string
- description: Unkown
+ description: Will the Study be done at non-UVa sites?
MULTI_SITE_LOCATIONS:
type: string
- description: Unkown
+ description: List if other sites involved.
IS_OUTSIDE_CONTRACT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study be funded by an outside contract?
IS_UVA_PI_MULTI:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the PI be from UVa for multi-site study?
IS_NOT_PRC_WAIVER:
type: number
enum: [0,1,null]
example: true
- description: Unkown
- IS_INSIDE_CONTRACT:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
+ description: Have you received notification from the Cancer Center Protocol Review Committee (PRC) that this protocol does not need approval from the PRC?
IS_CANCER_PATIENT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study involve cancer patients?
UPLOAD_COMPLETE:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: bit indicating that the study was moved to IRB online
IS_FUNDING_SOURCE:
type: number
enum: [0,1,null]
example: true
- description: Unkown
- IS_CODED_RESEARCH:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
- IS_OUTSIDE_SPONSOR:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
+ description: Is there an outside supply source other than the sponsor/funding source supporting this study?
IS_PI_INITIATED:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Was the Study initiated by the Principal Investigator?
IS_ENGAGED_RESEARCH:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study group be contacted by UVa employees or agents or obtain personnally identifiable information about them?
IS_APPROVED_DEVICE:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Has the device in the Study been approved by the FDA?
IS_FINANCIAL_CONFLICT:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Has the Conflict of Interest Committee provided a COI Management Plan?
IS_NOT_CONSENT_WAIVER:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Do you plan on getting VERBAL CONSENT for ONLY a PART of this study (waiver of documentation of consent) and getting WRITTEN CONSENT for another part of the study?
IS_FOR_CANCER_CENTER:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study involve the UVa Cancer Center?
IS_REVIEW_BY_CENTRAL_IRB:
type: number
enum: [0,1,null]
example: true
- description: Unkown
+ description: Will the Study require review by the Central IRB?
IRBREVIEWERADMIN:
- type: number
- enum: [0,1,null]
- example: true
- description: Unkown
+ type: string
+ example: "dhf8r"
+ description: Netbadge id of IRB staff assinged to do the review
diff --git a/app.py b/app.py
index 0f13b39..82ebf80 100644
--- a/app.py
+++ b/app.py
@@ -1,5 +1,7 @@
import connexion
-from flask import url_for, json
+from flask import url_for, json, redirect, render_template, request, flash
+
+from flask_sqlalchemy import SQLAlchemy
PROTOCOLS = {}
@@ -25,11 +27,13 @@ def get_form(id, requirement_code):
return
-app = connexion.App('Protocol Builder', specification_dir='./')
-app.add_api('api.yml')
+conn = connexion.App('Protocol Builder', specification_dir='./')
+conn.add_api('api.yml')
-application = app.app
+app = conn.app
+app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
+db = SQLAlchemy(app)
def has_no_empty_params(rule):
defaults = rule.defaults if rule.defaults is not None else ()
@@ -37,10 +41,10 @@ def has_no_empty_params(rule):
return len(defaults) >= len(arguments)
-@application.route("/")
+@app.route("/site_map")
def site_map():
links = []
- for rule in application.url_map.iter_rules():
+ for rule in app.url_map.iter_rules():
# Filter out rules we can't navigate to in a browser
# and rules that require parameters
if "GET" in rule.methods and has_no_empty_params(rule):
@@ -49,6 +53,55 @@ def site_map():
return json.dumps({"links": links})
+app.config['SECRET_KEY'] = 'a really really really really long secret key'
+
+from forms import Study, StudyForm, StudySearchForm, StudyTable, RequiredDocument
+
+@app.route('/', methods=['GET', 'POST'])
+def index():
+ search = StudySearchForm(request.form)
+ if request.method == 'POST':
+ return search_results(search)
+ return render_template('index.html', form=search)
+
+
+@app.route('/results')
+def search_results(search):
+ results = []
+ search_string = search.data['search']
+ if search.data['search'] == '':
+ qry = db.session.query(Study)
+ results = qry.all()
+ if not results:
+ flash('No results found!')
+ return redirect('/')
+ else:
+ # display results
+ studies = db.session.query("Study").all()
+ table = StudyTable(studies)
+ return render_template('results.html', table=table)
+
+
+@app.route('/new_study', methods=['GET', 'POST'])
+def new_study():
+ form = StudyForm(request.form)
+ if request.method == 'POST':
+ # save the study
+ study = Study()
+ study.id = form.id
+ study.title = form.title
+# for r in form.requirements:
+# requirement = RequiredDocument(id = r.id,
+# study.requirements = form.requirements
+ db.session.add(study)
+ db.session.commit()
+ flash('Album created successfully!')
+ return redirect('/')
+
+ form = StudyForm(request.form)
+ return render_template('study_form.html', form=form)
+
+
if __name__ == '__main__':
# run our standalone gevent server
app.run(port=4200)
\ No newline at end of file
diff --git a/forms.py b/forms.py
new file mode 100644
index 0000000..a1a9a8e
--- /dev/null
+++ b/forms.py
@@ -0,0 +1,70 @@
+from flask_table import Table, Col
+from flask_wtf import FlaskForm
+from wtforms import SelectMultipleField, SubmitField, StringField, IntegerField
+
+from app import db
+
+
+class Study(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ title = db.Column(db.String(80), nullable=False)
+ requirements = db.relationship("RequiredDocument", backref="study", lazy='dynamic')
+
+
+class RequiredDocument(db.Model):
+ id = db.Column(db.Integer, primary_key=True)
+ name = db.Column(db.String(80), nullable=False)
+ active = db.Column(db.Boolean, default=False)
+ study_id = db.Column(db.Integer, db.ForeignKey('study.id'))
+
+ @staticmethod
+ def all():
+ docs = [RequiredDocument(id=1, name="Investigators Brochure"),
+ RequiredDocument(id=6, name="Cancer Center's PRC Approval Form"),
+ RequiredDocument(id=8, name="SOM CTO IND/IDE Review Letter"),
+ RequiredDocument(id=9, name="HIRE Approval"),
+ RequiredDocument(id=10, name="Cancer Center's PRC Approval Waiver"),
+ RequiredDocument(id=12, name="Certificate of Confidentiality Application"),
+ RequiredDocument(id=14, name="Institutional Biosafety Committee Approval"),
+ RequiredDocument(id=18, name="SOM CTO Approval Letter - UVA PI Multisite Trial"),
+ RequiredDocument(id=20,
+ name="IRB Approval or Letter of Approval from Administration: Study Conducted at non- UVA Facilities "),
+ RequiredDocument(id=21, name="New Medical Device Form"),
+ RequiredDocument(id=22, name="SOM CTO Review regarding need for IDE"),
+ RequiredDocument(id=23, name="SOM CTO Review regarding need for IND"),
+ RequiredDocument(id=24, name="InfoSec Approval"),
+ RequiredDocument(id=25, name="Scientific Pre-review Documentation"),
+ RequiredDocument(id=26, name="IBC Number"),
+ RequiredDocument(id=32, name="IDS - Investigational Drug Service Approval"),
+ RequiredDocument(id=36, name="RDRC Approval "),
+ RequiredDocument(id=40, name="SBS/IRB Approval-FERPA"),
+ RequiredDocument(id=41, name="HIRE Standard Radiation Language"),
+ RequiredDocument(id=42, name="COI Management Plan "),
+ RequiredDocument(id=43, name="SOM CTO Approval Letter-Non UVA, Non Industry PI MultiSite Study"),
+ RequiredDocument(id=44, name="GRIME Approval"),
+ RequiredDocument(id=45, name="GMEC Approval"),
+ RequiredDocument(id=46, name="IRB Reliance Agreement Request Form- IRB-HSR is IRB of Record"),
+ RequiredDocument(id=47, name="Non UVA IRB Approval - Initial and Last Continuation"),
+ RequiredDocument(id=48, name="MR Physicist Approval- Use of Gadolinium"),
+ RequiredDocument(id=49, name="SOM CTO Approval- Non- UVA Academia PI of IDE"),
+ RequiredDocument(id=51, name="IDS Waiver"),
+ RequiredDocument(id=52, name="Package Inserts"),
+ RequiredDocument(id=53, name="IRB Reliance Agreement Request Form- IRB-HSR Not IRB of Record"),
+ RequiredDocument(id=54, name="ESCRO Approval"),
+ RequiredDocument(id=57, name="Laser Safety Officer Approval")]
+ return docs
+
+
+class StudySearchForm(FlaskForm):
+ search = StringField('')
+
+
+class StudyForm(FlaskForm):
+ id = IntegerField('Study Id')
+ title = StringField('Title')
+ requirements = SelectMultipleField("Requirements", choices=[(rd.id, rd.name) for rd in RequiredDocument.all()])
+
+class StudyTable(Table):
+ id = Col('Id')
+ title = Col('Artist')
+ requirements = Col('Title')
diff --git a/templates/index.html b/templates/index.html
new file mode 100644
index 0000000..05b242d
--- /dev/null
+++ b/templates/index.html
@@ -0,0 +1,24 @@
+
+
+ New Study
+
+{% with messages = get_flashed_messages() %}
+ {% if messages %}
+ Protocol Builder Mock
+
+
+ {% for message in messages %}
+
+ {% endif %}
+{% endwith %}
+
+{{ table }}
+
+