commit
a6604e815b
|
@ -1,5 +1,7 @@
|
|||
.idea
|
||||
__pycache__/
|
||||
app.db
|
||||
pb/static/.webassets-cache*
|
||||
pb/static/*.css
|
||||
static/.webassets-cache*
|
||||
static/*.css
|
||||
|
|
47
Dockerfile
47
Dockerfile
|
@ -1,31 +1,22 @@
|
|||
FROM python:3.7
|
||||
FROM python:3.7-slim
|
||||
|
||||
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", "flask", "db", "upgrade"]
|
||||
CMD ["pipenv", "run", "python", "/protocol-builder-mock/run.py"]
|
||||
|
||||
# expose ports
|
||||
EXPOSE 5001
|
||||
WORKDIR /app
|
||||
COPY Pipfile Pipfile.lock /app/
|
||||
|
||||
RUN set -xe \
|
||||
&& pip install pipenv \
|
||||
&& apt-get update -q \
|
||||
&& apt-get install -y -q \
|
||||
gcc python3-dev libssl-dev \
|
||||
curl postgresql-client git-core \
|
||||
gunicorn3 postgresql-client \
|
||||
&& pipenv install --dev \
|
||||
&& apt-get remove -y gcc python3-dev libssl-dev \
|
||||
&& apt-get autoremove -y \
|
||||
&& apt-get clean -y \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& mkdir -p /app \
|
||||
&& useradd _gunicorn --no-create-home --user-group
|
||||
|
||||
COPY . /app/
|
||||
WORKDIR /app
|
||||
|
|
4
Pipfile
4
Pipfile
|
@ -4,6 +4,7 @@ url = "https://pypi.org/simple"
|
|||
verify_ssl = true
|
||||
|
||||
[dev-packages]
|
||||
pbr = "*"
|
||||
|
||||
[packages]
|
||||
flask = "*"
|
||||
|
@ -21,6 +22,9 @@ marshmallow-sqlalchemy = "*"
|
|||
wtforms-alchemy = "*"
|
||||
psycopg2-binary = "*"
|
||||
pyscss = "*"
|
||||
gunicorn = "*"
|
||||
werkzeug = "*"
|
||||
flask-cors = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.7"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "ca92325f9ff90d6263f261dc514de998c618a3e91614f9c1987b2f0db9b72dcf"
|
||||
"sha256": "4897f5ad1de5dcc7a407c45a670a3e5cf332d56fa138bfe1805441aa18c195cc"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
@ -38,10 +38,10 @@
|
|||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3",
|
||||
"sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f"
|
||||
"sha256:1d987a998c75633c40847cc966fcf5904906c920a7f17ef374f5aa4282abd304",
|
||||
"sha256:51fcb31174be6e6664c5f69e3e1691a2d72a1a12e90f872cbdb1567eb47b6519"
|
||||
],
|
||||
"version": "==2019.11.28"
|
||||
"version": "==2020.4.5.1"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
|
@ -52,10 +52,10 @@
|
|||
},
|
||||
"click": {
|
||||
"hashes": [
|
||||
"sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc",
|
||||
"sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a"
|
||||
"sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a",
|
||||
"sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"
|
||||
],
|
||||
"version": "==7.1.1"
|
||||
"version": "==7.1.2"
|
||||
},
|
||||
"clickclick": {
|
||||
"hashes": [
|
||||
|
@ -69,11 +69,11 @@
|
|||
"swagger-ui"
|
||||
],
|
||||
"hashes": [
|
||||
"sha256:bf32bfae6af337cfa4a8489c21516adbe5c50e3f8dc0b7ed2394ce8dde218018",
|
||||
"sha256:c568e579f84be808e387dcb8570bb00a536891be1318718a0dad3ba90f034191"
|
||||
"sha256:1ccfac57d4bb7adf4295ba6f5e48f5a1f66057df6a0713417766c9b5235182ee",
|
||||
"sha256:5439e9659a89c4380d93a07acfbf3380d70be4130574de8881e5f0dfec7ad0e2"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.6.0"
|
||||
"version": "==2.7.0"
|
||||
},
|
||||
"decorator": {
|
||||
"hashes": [
|
||||
|
@ -84,11 +84,11 @@
|
|||
},
|
||||
"flask": {
|
||||
"hashes": [
|
||||
"sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52",
|
||||
"sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6"
|
||||
"sha256:4efa1ae2d7c9865af48986de8aeb8504bf32c7f3d6fdc9353d34b21f4b127060",
|
||||
"sha256:8a4fdd8936eba2512e9c85df320a37e694c93945b33ef33c89946a340a238557"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.1.1"
|
||||
"version": "==1.1.2"
|
||||
},
|
||||
"flask-assets": {
|
||||
"hashes": [
|
||||
|
@ -105,13 +105,21 @@
|
|||
],
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"flask-marshmallow": {
|
||||
"flask-cors": {
|
||||
"hashes": [
|
||||
"sha256:01520ef1851ccb64d4ffb33196cddff895cc1302ae1585bff1abf58684a8111a",
|
||||
"sha256:28b969193958d9602ab5d6add6d280e0e360c8e373d3492c2f73b024ecd36374"
|
||||
"sha256:72170423eb4612f0847318afff8c247b38bd516b7737adfc10d1c2cdbb382d16",
|
||||
"sha256:f4d97201660e6bbcff2d89d082b5b6d31abee04b1b3003ee073a6fd25ad1d69a"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.11.0"
|
||||
"version": "==3.0.8"
|
||||
},
|
||||
"flask-marshmallow": {
|
||||
"hashes": [
|
||||
"sha256:6e6aec171b8e092e0eafaf035ff5b8637bf3a58ab46f568c4c1bab02f2a3c196",
|
||||
"sha256:a1685536e7ab5abdc712bbc1ac1a6b0b50951a368502f7985e7d1c27b3c21e59"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.12.0"
|
||||
},
|
||||
"flask-migrate": {
|
||||
"hashes": [
|
||||
|
@ -123,11 +131,11 @@
|
|||
},
|
||||
"flask-sqlalchemy": {
|
||||
"hashes": [
|
||||
"sha256:0078d8663330dc05a74bc72b3b6ddc441b9a744e2f56fe60af1a5bfc81334327",
|
||||
"sha256:6974785d913666587949f7c2946f7001e4fa2cb2d19f4e69ead02e4b8f50b33d"
|
||||
"sha256:2298f6b874c2a2f1f048eaf21ce5d984e36a04ca849b0ac473050a67c8dae76f",
|
||||
"sha256:6cd9f71a97ef18ca5ae7d8bd316a32b82814efe7b088096ba68fddfd8a17cbe7"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.4.1"
|
||||
"version": "==2.4.2"
|
||||
},
|
||||
"flask-table": {
|
||||
"hashes": [
|
||||
|
@ -146,32 +154,31 @@
|
|||
},
|
||||
"gevent": {
|
||||
"hashes": [
|
||||
"sha256:0774babec518a24d9a7231d4e689931f31b332c4517a771e532002614e270a64",
|
||||
"sha256:0e1e5b73a445fe82d40907322e1e0eec6a6745ca3cea19291c6f9f50117bb7ea",
|
||||
"sha256:0ff2b70e8e338cf13bedf146b8c29d475e2a544b5d1fe14045aee827c073842c",
|
||||
"sha256:107f4232db2172f7e8429ed7779c10f2ed16616d75ffbe77e0e0c3fcdeb51a51",
|
||||
"sha256:14b4d06d19d39a440e72253f77067d27209c67e7611e352f79fe69e0f618f76e",
|
||||
"sha256:1b7d3a285978b27b469c0ff5fb5a72bcd69f4306dbbf22d7997d83209a8ba917",
|
||||
"sha256:1eb7fa3b9bd9174dfe9c3b59b7a09b768ecd496debfc4976a9530a3e15c990d1",
|
||||
"sha256:2711e69788ddb34c059a30186e05c55a6b611cb9e34ac343e69cf3264d42fe1c",
|
||||
"sha256:28a0c5417b464562ab9842dd1fb0cc1524e60494641d973206ec24d6ec5f6909",
|
||||
"sha256:3249011d13d0c63bea72d91cec23a9cf18c25f91d1f115121e5c9113d753fa12",
|
||||
"sha256:44089ed06a962a3a70e96353c981d628b2d4a2f2a75ea5d90f916a62d22af2e8",
|
||||
"sha256:4bfa291e3c931ff3c99a349d8857605dca029de61d74c6bb82bd46373959c942",
|
||||
"sha256:50024a1ee2cf04645535c5ebaeaa0a60c5ef32e262da981f4be0546b26791950",
|
||||
"sha256:53b72385857e04e7faca13c613c07cab411480822ac658d97fd8a4ddbaf715c8",
|
||||
"sha256:74b7528f901f39c39cdbb50cdf08f1a2351725d9aebaef212a29abfbb06895ee",
|
||||
"sha256:7d0809e2991c9784eceeadef01c27ee6a33ca09ebba6154317a257353e3af922",
|
||||
"sha256:896b2b80931d6b13b5d9feba3d4eebc67d5e6ec54f0cf3339d08487d55d93b0e",
|
||||
"sha256:8d9ec51cc06580f8c21b41fd3f2b3465197ba5b23c00eb7d422b7ae0380510b0",
|
||||
"sha256:9f7a1e96fec45f70ad364e46de32ccacab4d80de238bd3c2edd036867ccd48ad",
|
||||
"sha256:ab4dc33ef0e26dc627559786a4fba0c2227f125db85d970abbf85b77506b3f51",
|
||||
"sha256:d1e6d1f156e999edab069d79d890859806b555ce4e4da5b6418616322f0a3df1",
|
||||
"sha256:d752bcf1b98174780e2317ada12013d612f05116456133a6acf3e17d43b71f05",
|
||||
"sha256:e5bcc4270671936349249d26140c267397b7b4b1381f5ec8b13c53c5b53ab6e1"
|
||||
"sha256:00b03601b8dd1ee2aa07811cb60a4befe36173b15d91c6e207e37f8d77dd6fac",
|
||||
"sha256:0acc15ba2ac2a555529ad82d5a28fc85dbb6b2ff947657d67bebfd352e2b5c14",
|
||||
"sha256:15eae3cd450dac7dae7f4ac59e01db1378965c9ef565c39c5ae78c5a888f9ac9",
|
||||
"sha256:1dc7f1f6bc1f67d625e4272b01e717eba0b4fa024d2ff7934c8d320674d6f7fa",
|
||||
"sha256:1dd95433be45e1115053878366e3f5332ae99c39cb345be23851327c062b9f4a",
|
||||
"sha256:28b7d83b4327ceb79668eca2049bf4b9ce66d5ace18a88335e3035b573f889fd",
|
||||
"sha256:31dc5d4ab8172cc00c4ff17cb18edee633babd961f64bf54214244d769bc3a74",
|
||||
"sha256:38db524ea88d81d596b2cbb6948fced26654a15fec40ea4529224e239a6f45e8",
|
||||
"sha256:3ff477b6d275396123faf8ce2d5b82f96d85ba264e0b9d4b56a2bac49d1b9adc",
|
||||
"sha256:4d2729dd4bf9c4d0f29482f53cdf9fc90a498aebb5cd7ae8b45d35657437d2ac",
|
||||
"sha256:52e5cd607749ed3b8aa0272cacf2c11deec61fca4c3bec57a9fea8c49316627d",
|
||||
"sha256:5c604179cebcc57f10505d8db177b92a715907815a464b066e7eba322d1c33ac",
|
||||
"sha256:88c76df4967c5229f853aa67ad1b394d9e4f985b0359c9bc9879416bba3e7c68",
|
||||
"sha256:929c33df8e9bcbe31906024fcd21580bd018196dbd3249eb5b2f19d63e11092d",
|
||||
"sha256:92edc18a357473e01a4e4a82c073ed3c99ceca6e3ce93c23668dd4a2401f07dc",
|
||||
"sha256:937d36730f2b0dee3387712074b1f15b802e2e074a3d7c6dcaf70521236d607c",
|
||||
"sha256:9b4e940fc6071afebb86ba5f48dbb5f1fc3cb96ebeb8cf145eb5b499e9c6ee33",
|
||||
"sha256:a7805934e8ce81610b61f806572c3d504cedd698cc8c9460d78d2893ba598c4a",
|
||||
"sha256:d07a2afe4215731eb57d5b257a2e7e7e170d8a7ae1f02f6d0682cd3403debea9",
|
||||
"sha256:e01d5373528e4ebdde66dc47a608d225fa3c4408ccd828d26c49b7ff75d82bd9",
|
||||
"sha256:efd9546468502a30ddd4699c3124ccb9d3099130f9b5ae1e2a54ad5b46e86120",
|
||||
"sha256:fcb64f3a28420d1b872b7ef41b12e8a1a4dcadfc8eff3c09993ab0cdf52584a1"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.4.0"
|
||||
"version": "==20.5.0"
|
||||
},
|
||||
"greenlet": {
|
||||
"hashes": [
|
||||
|
@ -201,6 +208,14 @@
|
|||
"markers": "platform_python_implementation == 'CPython'",
|
||||
"version": "==0.4.15"
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
"sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626",
|
||||
"sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==20.0.4"
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
|
||||
|
@ -210,11 +225,11 @@
|
|||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
"sha256:06f5b3a99029c7134207dd882428a66992a9de2bef7c2b699b5641f9886c3302",
|
||||
"sha256:b97607a1a18a5100839aec1dc26a1ea17ee0d93b20b0f008d80a5a050afb200b"
|
||||
"sha256:2a688cbaa90e0cc587f1df48bdc97a6eadccdcd9c35fb3f976a09e3b5016d90f",
|
||||
"sha256:34513a8a0c4962bc66d35b359558fd8a5e10cd472d37aec5f66858addef32c1e"
|
||||
],
|
||||
"markers": "python_version < '3.8'",
|
||||
"version": "==1.5.0"
|
||||
"version": "==1.6.0"
|
||||
},
|
||||
"infinity": {
|
||||
"hashes": [
|
||||
|
@ -224,9 +239,10 @@
|
|||
},
|
||||
"inflection": {
|
||||
"hashes": [
|
||||
"sha256:18ea7fb7a7d152853386523def08736aa8c32636b047ade55f7578c4edeb16ca"
|
||||
"sha256:32a5c3341d9583ec319548b9015b7fbdf8c429cbcb575d326c33ae3a0e90d52c",
|
||||
"sha256:9a15d3598f01220e93f2207c432cfede50daff53137ce660fb8be838ef1ca6cc"
|
||||
],
|
||||
"version": "==0.3.1"
|
||||
"version": "==0.4.0"
|
||||
},
|
||||
"intervals": {
|
||||
"hashes": [
|
||||
|
@ -243,10 +259,10 @@
|
|||
},
|
||||
"jinja2": {
|
||||
"hashes": [
|
||||
"sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250",
|
||||
"sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49"
|
||||
"sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0",
|
||||
"sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"
|
||||
],
|
||||
"version": "==2.11.1"
|
||||
"version": "==2.11.2"
|
||||
},
|
||||
"jsonschema": {
|
||||
"hashes": [
|
||||
|
@ -315,18 +331,18 @@
|
|||
},
|
||||
"marshmallow": {
|
||||
"hashes": [
|
||||
"sha256:90854221bbb1498d003a0c3cc9d8390259137551917961c8b5258c64026b2f85",
|
||||
"sha256:ac2e13b30165501b7d41fc0371b8df35944f5849769d136f20e2c5f6cdc6e665"
|
||||
"sha256:c2673233aa21dde264b84349dc2fd1dce5f30ed724a0a00e75426734de5b84ab",
|
||||
"sha256:f88fe96434b1f0f476d54224d59333eba8ca1a203a2695683c1855675c4049a7"
|
||||
],
|
||||
"version": "==3.5.1"
|
||||
"version": "==3.6.0"
|
||||
},
|
||||
"marshmallow-sqlalchemy": {
|
||||
"hashes": [
|
||||
"sha256:9301c6fd197bd97337820ea1417aa1233d0ee3e22748ebd5821799bc841a57e8",
|
||||
"sha256:dde9e20bcb710e9e59f765a38e3d6d17f1b2d6b4320cbdc2cea0f6b57f70d08c"
|
||||
"sha256:3247e41e424146340b03a369f2b7c6f0364477ccedc4e2481e84d5f3a8d3c67f",
|
||||
"sha256:dbbe51d28bb28e7ee2782e51310477f7a2c5a111a301f6dd8e264e11ab820427"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==0.22.3"
|
||||
"version": "==0.23.0"
|
||||
},
|
||||
"openapi-spec-validator": {
|
||||
"hashes": [
|
||||
|
@ -338,41 +354,39 @@
|
|||
},
|
||||
"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"
|
||||
"sha256:008da3ab51adc70a5f1cfbbe5db3a22607ab030eb44bcecf517ad11a0c2b3cac",
|
||||
"sha256:07cf82c870ec2d2ce94d18e70c13323c89f2f2a2628cbf1feee700630be2519a",
|
||||
"sha256:08507efbe532029adee21b8d4c999170a83760d38249936038bd0602327029b5",
|
||||
"sha256:107d9be3b614e52a192719c6bf32e8813030020ea1d1215daa86ded9a24d8b04",
|
||||
"sha256:17a0ea0b0eabf07035e5e0d520dabc7950aeb15a17c6d36128ba99b2721b25b1",
|
||||
"sha256:3286541b9d85a340ee4ed42732d15fc1bb441dc500c97243a768154ab8505bb5",
|
||||
"sha256:3939cf75fc89c5e9ed836e228c4a63604dff95ad19aed2bbf71d5d04c15ed5ce",
|
||||
"sha256:40abc319f7f26c042a11658bf3dd3b0b3bceccf883ec1c565d5c909a90204434",
|
||||
"sha256:51f7823f1b087d2020d8e8c9e6687473d3d239ba9afc162d9b2ab6e80b53f9f9",
|
||||
"sha256:6bb2dd006a46a4a4ce95201f836194eb6a1e863f69ee5bab506673e0ca767057",
|
||||
"sha256:702f09d8f77dc4794651f650828791af82f7c2efd8c91ae79e3d9fe4bb7d4c98",
|
||||
"sha256:7036ccf715925251fac969f4da9ad37e4b7e211b1e920860148a10c0de963522",
|
||||
"sha256:7b832d76cc65c092abd9505cc670c4e3421fd136fb6ea5b94efbe4c146572505",
|
||||
"sha256:8f74e631b67482d504d7e9cf364071fc5d54c28e79a093ff402d5f8f81e23bfa",
|
||||
"sha256:930315ac53dc65cbf52ab6b6d27422611f5fb461d763c531db229c7e1af6c0b3",
|
||||
"sha256:96d3038f5bd061401996614f65d27a4ecb62d843eb4f48e212e6d129171a721f",
|
||||
"sha256:a20299ee0ea2f9cca494396ac472d6e636745652a64a418b39522c120fd0a0a4",
|
||||
"sha256:a34826d6465c2e2bbe9d0605f944f19d2480589f89863ed5f091943be27c9de4",
|
||||
"sha256:a69970ee896e21db4c57e398646af9edc71c003bc52a3cc77fb150240fefd266",
|
||||
"sha256:b9a8b391c2b0321e0cd7ec6b4cfcc3dd6349347bd1207d48bcb752aa6c553a66",
|
||||
"sha256:ba13346ff6d3eb2dca0b6fa0d8a9d999eff3dcd9b55f3a890f12b0b6362b2b38",
|
||||
"sha256:bb0608694a91db1e230b4a314e8ed00ad07ed0c518f9a69b83af2717e31291a3",
|
||||
"sha256:c8830b7d5f16fd79d39b21e3d94f247219036b29b30c8270314c46bf8b732389",
|
||||
"sha256:cac918cd7c4c498a60f5d2a61d4f0a6091c2c9490d81bc805c963444032d0dab",
|
||||
"sha256:cc30cb900f42c8a246e2cb76539d9726f407330bc244ca7729c41a44e8d807fb",
|
||||
"sha256:ccdc6a87f32b491129ada4b87a43b1895cf2c20fdb7f98ad979647506ffc41b6",
|
||||
"sha256:d1a8b01f6a964fec702d6b6dac1f91f2b9f9fe41b310cbb16c7ef1fac82df06d",
|
||||
"sha256:e004db88e5a75e5fdab1620fb9f90c9598c2a195a594225ac4ed2a6f1c23e162",
|
||||
"sha256:eb2f43ae3037f1ef5e19339c41cf56947021ac892f668765cd65f8ab9814192e",
|
||||
"sha256:fa466306fcf6b39b8a61d003123d442b23707d635a5cb05ac4e1b62cc79105cd"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.8.4"
|
||||
"version": "==2.8.5"
|
||||
},
|
||||
"pyrsistent": {
|
||||
"hashes": [
|
||||
|
@ -382,10 +396,10 @@
|
|||
},
|
||||
"pyscss": {
|
||||
"hashes": [
|
||||
"sha256:123c1a9087f1c420bea891ebf19d5222262c7d30ced20bb38586023de28c9d4f"
|
||||
"sha256:f1df571569021a23941a538eb154405dde80bed35dc1ea7c5f3e18e0144746bf"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.3.6"
|
||||
"version": "==1.3.7"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
|
@ -404,10 +418,10 @@
|
|||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
|
||||
"sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
|
||||
"sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed",
|
||||
"sha256:c35965d010ce31b23eeb663ed3cc8c906275d6be1a34393a1d73a41febf4a048"
|
||||
],
|
||||
"version": "==2019.3"
|
||||
"version": "==2020.1"
|
||||
},
|
||||
"pyyaml": {
|
||||
"hashes": [
|
||||
|
@ -434,23 +448,50 @@
|
|||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
"sha256:236bdbdce46e6e6a3d61a337c0f8b763ca1e8717c03b369e87a7ec7ce1319c0a",
|
||||
"sha256:8f3cd2e254d8f793e7f3d6d9df77b92252b52637291d0f0da013c76ea2724b6c"
|
||||
"sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
|
||||
"sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
|
||||
],
|
||||
"version": "==1.14.0"
|
||||
"version": "==1.15.0"
|
||||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
"sha256:c4cca4aed606297afbe90d4306b49ad3a4cd36feb3f87e4bfd655c57fd9ef445"
|
||||
"sha256:128bc917ed20d78143a45024455ff0aed7d3b96772eba13d5dbaf9cc57e5c41b",
|
||||
"sha256:156a27548ba4e1fed944ff9fcdc150633e61d350d673ae7baaf6c25c04ac1f71",
|
||||
"sha256:27e2efc8f77661c9af2681755974205e7462f1ae126f498f4fe12a8b24761d15",
|
||||
"sha256:2a12f8be25b9ea3d1d5b165202181f2b7da4b3395289000284e5bb86154ce87c",
|
||||
"sha256:31c043d5211aa0e0773821fcc318eb5cbe2ec916dfbc4c6eea0c5188971988eb",
|
||||
"sha256:65eb3b03229f684af0cf0ad3bcc771970c1260a82a791a8d07bffb63d8c95bcc",
|
||||
"sha256:6cd157ce74a911325e164441ff2d9b4e244659a25b3146310518d83202f15f7a",
|
||||
"sha256:703c002277f0fbc3c04d0ae4989a174753a7554b2963c584ce2ec0cddcf2bc53",
|
||||
"sha256:869bbb637de58ab0a912b7f20e9192132f9fbc47fc6b5111cd1e0f6cdf5cf9b0",
|
||||
"sha256:8a0e0cd21da047ea10267c37caf12add400a92f0620c8bc09e4a6531a765d6d7",
|
||||
"sha256:8d01e949a5d22e5c4800d59b50617c56125fc187fbeb8fa423e99858546de616",
|
||||
"sha256:925b4fe5e7c03ed76912b75a9a41dfd682d59c0be43bce88d3b27f7f5ba028fb",
|
||||
"sha256:9cb1819008f0225a7c066cac8bb0cf90847b2c4a6eb9ebb7431dbd00c56c06c5",
|
||||
"sha256:a87d496884f40c94c85a647c385f4fd5887941d2609f71043e2b73f2436d9c65",
|
||||
"sha256:a9030cd30caf848a13a192c5e45367e3c6f363726569a56e75dc1151ee26d859",
|
||||
"sha256:a9e75e49a0f1583eee0ce93270232b8e7bb4b1edc89cc70b07600d525aef4f43",
|
||||
"sha256:b50f45d0e82b4562f59f0e0ca511f65e412f2a97d790eea5f60e34e5f1aabc9a",
|
||||
"sha256:b7878e59ec31f12d54b3797689402ee3b5cfcb5598f2ebf26491732758751908",
|
||||
"sha256:ce1ddaadee913543ff0154021d31b134551f63428065168e756d90bdc4c686f5",
|
||||
"sha256:ce2646e4c0807f3461be0653502bb48c6e91a5171d6e450367082c79e12868bf",
|
||||
"sha256:ce6c3d18b2a8ce364013d47b9cad71db815df31d55918403f8db7d890c9d07ae",
|
||||
"sha256:e4e2664232005bd306f878b0f167a31f944a07c4de0152c444f8c61bbe3cfb38",
|
||||
"sha256:e8aa395482728de8bdcca9cc0faf3765ab483e81e01923aaa736b42f0294f570",
|
||||
"sha256:eb4fcf7105bf071c71068c6eee47499ab8d4b8f5a11fc35147c934f0faa60f23",
|
||||
"sha256:ed375a79f06cad285166e5be74745df1ed6845c5624aafadec4b7a29c25866ef",
|
||||
"sha256:f35248f7e0d63b234a109dd72fbfb4b5cb6cb6840b221d0df0ecbf54ab087654",
|
||||
"sha256:f502ef245c492b391e0e23e94cba030ab91722dcc56963c85bfd7f3441ea2bbe",
|
||||
"sha256:fe01bac7226499aedf472c62fa3b85b2c619365f3f14dd222ffe4f3aa91e5f98"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.3.15"
|
||||
"version": "==1.3.17"
|
||||
},
|
||||
"sqlalchemy-utils": {
|
||||
"hashes": [
|
||||
"sha256:f268af5bc03597fe7690d60df3e5f1193254a83e07e4686f720f61587ec4493a"
|
||||
"sha256:7a7fab14bed80df065412bbf71a0a9b0bfeb4b7c111c2d9bffe57283082f3a6b"
|
||||
],
|
||||
"version": "==0.36.3"
|
||||
"version": "==0.36.6"
|
||||
},
|
||||
"swagger-ui-bundle": {
|
||||
"hashes": [
|
||||
|
@ -462,16 +503,16 @@
|
|||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc",
|
||||
"sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc"
|
||||
"sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
|
||||
"sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
|
||||
],
|
||||
"version": "==1.25.8"
|
||||
"version": "==1.25.9"
|
||||
},
|
||||
"validators": {
|
||||
"hashes": [
|
||||
"sha256:b192e6bde7d617811d59f50584ed240b580375648cd032d106edeb3164099508"
|
||||
"sha256:31e8bb01b48b48940a021b8a9576b840f98fa06b91762ef921d02cb96d38727a"
|
||||
],
|
||||
"version": "==0.14.2"
|
||||
"version": "==0.15.0"
|
||||
},
|
||||
"webassets": {
|
||||
"hashes": [
|
||||
|
@ -482,17 +523,18 @@
|
|||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
|
||||
"sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16"
|
||||
"sha256:2de2a5db0baeae7b2d2664949077c2ac63fbd16d98da0ff71837f7d1dea3fd43",
|
||||
"sha256:6c80b1e5ad3665290ea39320b91e1be1e0d5f60652b964a3070216de83d2e47c"
|
||||
],
|
||||
"version": "==1.0.0"
|
||||
"index": "pypi",
|
||||
"version": "==1.0.1"
|
||||
},
|
||||
"wtforms": {
|
||||
"hashes": [
|
||||
"sha256:0cdbac3e7f6878086c334aa25dc5a33869a3954e9d1e015130d65a69309b3b61",
|
||||
"sha256:e3ee092c827582c50877cdbd49e9ce6d2c5c1f6561f849b3b068c1b8029626f1"
|
||||
"sha256:6ff8635f4caeed9f38641d48cfe019d0d3896f41910ab04494143fc027866e1b",
|
||||
"sha256:861a13b3ae521d6700dac3b2771970bd354a63ba7043ecc3a82b5288596a1972"
|
||||
],
|
||||
"version": "==2.2.1"
|
||||
"version": "==2.3.1"
|
||||
},
|
||||
"wtforms-alchemy": {
|
||||
"hashes": [
|
||||
|
@ -515,5 +557,14 @@
|
|||
"version": "==3.1.0"
|
||||
}
|
||||
},
|
||||
"develop": {}
|
||||
"develop": {
|
||||
"pbr": {
|
||||
"hashes": [
|
||||
"sha256:07f558fece33b05caf857474a366dfcc00562bca13dd8b47b2b3e22d9f9bf55c",
|
||||
"sha256:579170e23f8e0c2f24b0de612f71f648eccb79fb1322c814ae6b3c07b5ba23e8"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.4.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import re
|
||||
import os
|
||||
from os import environ
|
||||
|
||||
|
@ -5,10 +6,13 @@ basedir = os.path.abspath(os.path.dirname(__file__))
|
|||
|
||||
NAME = "CR Connect Protocol Builder Mock"
|
||||
FLASK_PORT = environ.get('PORT0') or environ.get('FLASK_PORT', default="5001")
|
||||
CORS_ENABLED = False
|
||||
CORS_ALLOW_ORIGINS = re.split(r',\s*', environ.get('CORS_ALLOW_ORIGINS', default="localhost:5000"))
|
||||
DEVELOPMENT = environ.get('DEVELOPMENT', default="true") == "true"
|
||||
TESTING = environ.get('TESTING', default="false") == "true"
|
||||
|
||||
# Add trailing slash to base path
|
||||
APPLICATION_ROOT = re.sub(r'//', '/', '/%s/' % environ.get('APPLICATION_ROOT', default="/").strip('/'))
|
||||
|
||||
DB_HOST = environ.get('DB_HOST', default="localhost")
|
||||
DB_PORT = environ.get('DB_PORT', default="5432")
|
||||
DB_NAME = environ.get('DB_NAME', default="pb")
|
||||
|
@ -22,5 +26,7 @@ SECRET_KEY = environ.get('SECRET_KEY', default='a really really really really lo
|
|||
|
||||
print('=== USING DEFAULT CONFIG: ===')
|
||||
print('DB_HOST = ', DB_HOST)
|
||||
print('CORS_ALLOW_ORIGINS = ', CORS_ALLOW_ORIGINS)
|
||||
print('DEVELOPMENT = ', DEVELOPMENT)
|
||||
print('TESTING = ', TESTING)
|
||||
print('APPLICATION_ROOT = ', APPLICATION_ROOT)
|
||||
|
|
|
@ -1,6 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
# run migrations
|
||||
export FLASK_APP=./app.py
|
||||
pipenv run flask db upgrade
|
||||
pipenv run python ./run.py
|
||||
export FLASK_APP=/app/pb/__init__.py
|
||||
|
||||
if [ "$DOWNGRADE_DB" = "true" ]; then
|
||||
echo 'Downgrading database...'
|
||||
pipenv run flask db downgrade
|
||||
fi
|
||||
|
||||
if [ "$UPGRADE_DB" = "true" ]; then
|
||||
echo 'Upgrading database...'
|
||||
pipenv run flask db upgrade
|
||||
fi
|
||||
|
||||
if [ "$RESET_DB" = "true" ]; then
|
||||
echo 'Resetting database...'
|
||||
pipenv run flask load-example-data
|
||||
fi
|
||||
|
||||
if [ "$APPLICATION_ROOT" = "/" ]; then
|
||||
pipenv run gunicorn --bind 0.0.0.0:$PORT0 wsgi:app
|
||||
else
|
||||
pipenv run gunicorn -e SCRIPT_NAME="$APPLICATION_ROOT" --bind 0.0.0.0:$PORT0 wsgi:app
|
||||
fi
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
import datetime
|
||||
import os
|
||||
import re
|
||||
import yaml
|
||||
from datetime import date
|
||||
|
||||
import connexion
|
||||
import yaml
|
||||
from flask_cors import CORS
|
||||
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
|
||||
from sqlalchemy import func
|
||||
|
||||
from wtforms.ext.appengine.db import model_form
|
||||
|
||||
PROTOCOLS = {}
|
||||
|
@ -39,11 +40,8 @@ def get_study_details(studyid):
|
|||
def get_form(id, requirement_code):
|
||||
return
|
||||
|
||||
|
||||
conn = connexion.App('Protocol Builder', specification_dir='./')
|
||||
conn.add_api('api.yml')
|
||||
|
||||
app = conn.app
|
||||
connexion_app = connexion.FlaskApp('Protocol Builder', specification_dir='pb')
|
||||
app = connexion_app.app
|
||||
|
||||
app.config.from_object('config.default')
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
|
@ -55,17 +53,53 @@ else:
|
|||
app.config.root_path = app.instance_path
|
||||
app.config.from_pyfile('config.py', silent=True)
|
||||
|
||||
connexion_app.add_api('api.yml', base_path='/v2.0')
|
||||
|
||||
# Convert list of allowed origins to list of regexes
|
||||
origins_re = [r"^https?:\/\/%s(.*)" % o.replace('.', '\.') for o in app.config['CORS_ALLOW_ORIGINS']]
|
||||
cors = CORS(connexion_app.app, origins=origins_re)
|
||||
|
||||
db = SQLAlchemy(app)
|
||||
migrate = Migrate(app, db)
|
||||
ma = Marshmallow(app)
|
||||
|
||||
# Set the path of the static directory
|
||||
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||
APP_STATIC = os.path.join(APP_ROOT, 'static')
|
||||
BASE_HREF = app.config['APPLICATION_ROOT'].strip('/')
|
||||
app.static_folder = APP_STATIC
|
||||
app.static_url_path = app.config['APPLICATION_ROOT'] + 'static'
|
||||
|
||||
print('app.static_folder', app.static_folder)
|
||||
print('app.static_url_path', app.static_url_path)
|
||||
|
||||
# remove old static map
|
||||
url_map = app.url_map
|
||||
try:
|
||||
for rule in url_map.iter_rules('static'):
|
||||
url_map._rules.remove(rule)
|
||||
except ValueError:
|
||||
# no static view was created yet
|
||||
pass
|
||||
|
||||
# register new; the same view function is used
|
||||
app.add_url_rule(
|
||||
app.static_url_path + '/<path:filename>',
|
||||
endpoint='static', view_func=app.send_static_file)
|
||||
|
||||
assets = Environment(app)
|
||||
assets.init_app(app)
|
||||
assets.url = app.static_url_path
|
||||
scss = Bundle('scss/app.scss', filters='pyscss', output='app.css')
|
||||
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 = {}
|
||||
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']:
|
||||
|
@ -82,14 +116,14 @@ def has_no_empty_params(rule):
|
|||
return len(defaults) >= len(arguments)
|
||||
|
||||
|
||||
@app.route("/site_map")
|
||||
@app.route('/site_map')
|
||||
def site_map():
|
||||
links = []
|
||||
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):
|
||||
url = url_for(rule.endpoint, **(rule.defaults or {}))
|
||||
url = app.confg['APPLICATION_ROOT'].strip('/') + url_for(rule.endpoint, **(rule.defaults or {}))
|
||||
links.append((url, rule.endpoint))
|
||||
return json.dumps({"links": links})
|
||||
|
||||
|
@ -97,8 +131,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
|
||||
|
||||
|
||||
|
@ -107,25 +141,33 @@ def index():
|
|||
# display results
|
||||
studies = db.session.query(Study).order_by(Study.DATE_MODIFIED.desc()).all()
|
||||
table = StudyTable(studies)
|
||||
return render_template('index.html', table=table)
|
||||
return render_template(
|
||||
'index.html',
|
||||
table=table,
|
||||
base_href=BASE_HREF
|
||||
)
|
||||
|
||||
|
||||
@app.route('/new_study', methods=['GET', 'POST'])
|
||||
def new_study():
|
||||
form = StudyForm(request.form)
|
||||
action = "/new_study"
|
||||
action = BASE_HREF + "/new_study"
|
||||
title = "New Study"
|
||||
if request.method == 'POST':
|
||||
study = Study()
|
||||
study.study_details = StudyDetails()
|
||||
_update_study(study, form)
|
||||
flash('Study created successfully!')
|
||||
return redirect('/')
|
||||
return redirect_home()
|
||||
|
||||
return render_template('form.html', form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
description_map=description_map)
|
||||
return render_template(
|
||||
'form.html',
|
||||
form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
description_map=description_map,
|
||||
base_href=BASE_HREF
|
||||
)
|
||||
|
||||
|
||||
@app.route('/study/<study_id>', methods=['GET', 'POST'])
|
||||
|
@ -133,7 +175,7 @@ def edit_study(study_id):
|
|||
study = db.session.query(Study).filter(Study.STUDYID == study_id).first()
|
||||
form = StudyForm(request.form, obj=study)
|
||||
if request.method == 'GET':
|
||||
action = "/study/" + study_id
|
||||
action = BASE_HREF + "/study/" + study_id
|
||||
title = "Edit Study #" + study_id
|
||||
if study.requirements:
|
||||
form.requirements.data = list(map(lambda r: r.AUXDOCID, list(study.requirements)))
|
||||
|
@ -142,17 +184,21 @@ def edit_study(study_id):
|
|||
if request.method == 'POST':
|
||||
_update_study(study, form)
|
||||
flash('Study updated successfully!')
|
||||
return redirect('/')
|
||||
return render_template('form.html', form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
description_map={})
|
||||
return redirect_home()
|
||||
return render_template(
|
||||
'form.html',
|
||||
form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
description_map={},
|
||||
base_href=BASE_HREF
|
||||
)
|
||||
|
||||
|
||||
@app.route('/investigator/<study_id>', methods=['GET', 'POST'])
|
||||
def new_investigator(study_id):
|
||||
form = InvestigatorForm(request.form)
|
||||
action = "/investigator/" + study_id
|
||||
action = BASE_HREF + "/investigator/" + study_id
|
||||
title = "Add Investigator to Study " + study_id
|
||||
if request.method == 'POST':
|
||||
investigator = Investigator(STUDYID=study_id)
|
||||
|
@ -161,19 +207,23 @@ def new_investigator(study_id):
|
|||
db.session.add(investigator)
|
||||
db.session.commit()
|
||||
flash('Investigator created successfully!')
|
||||
return redirect('/')
|
||||
return redirect_home()
|
||||
|
||||
return render_template('form.html', form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
description_map={})
|
||||
return render_template(
|
||||
'form.html',
|
||||
form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
description_map={},
|
||||
base_href=BASE_HREF
|
||||
)
|
||||
|
||||
|
||||
@app.route('/del_investigator/<inv_id>', methods=['GET'])
|
||||
def del_investigator(inv_id):
|
||||
db.session.query(Investigator).filter(Investigator.id == inv_id).delete()
|
||||
db.session.commit()
|
||||
return redirect('/')
|
||||
return redirect_home()
|
||||
|
||||
|
||||
@app.route('/del_study/<study_id>', methods=['GET'])
|
||||
|
@ -183,7 +233,7 @@ def del_study(study_id):
|
|||
db.session.query(StudyDetails).filter(StudyDetails.STUDYID == study_id).delete()
|
||||
db.session.query(Study).filter(Study.STUDYID == study_id).delete()
|
||||
db.session.commit()
|
||||
return redirect('/')
|
||||
return redirect_home()
|
||||
|
||||
|
||||
def _update_study(study, form):
|
||||
|
@ -218,7 +268,7 @@ def study_details(study_id):
|
|||
study_details = StudyDetails(STUDYID=study_id)
|
||||
form = StudyDetailsForm(request.form, obj=study_details)
|
||||
if request.method == 'GET':
|
||||
action = "/study_details/" + study_id
|
||||
action = BASE_HREF + "/study_details/" + study_id
|
||||
title = "Edit Study Details for Study #" + study_id
|
||||
details = "Numeric fields can be 1 for true, 0 or false, or Null if not applicable."
|
||||
if request.method == 'POST':
|
||||
|
@ -226,12 +276,20 @@ def study_details(study_id):
|
|||
db.session.add(study_details)
|
||||
db.session.commit()
|
||||
flash('Study updated successfully!')
|
||||
return redirect('/')
|
||||
return render_template('form.html', form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
details=details,
|
||||
description_map=description_map)
|
||||
return redirect_home()
|
||||
return render_template(
|
||||
'form.html',
|
||||
form=form,
|
||||
action=action,
|
||||
title=title,
|
||||
details=details,
|
||||
description_map=description_map,
|
||||
base_href=BASE_HREF
|
||||
)
|
||||
|
||||
|
||||
def redirect_home():
|
||||
return redirect(url_for('index'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
|
@ -10,8 +10,6 @@ info:
|
|||
name: Apache 2.0
|
||||
url: http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
# Added by API Auto Mocking Plugin
|
||||
servers:
|
||||
- url: http://localhost:5000/pb
|
||||
# tags are used for organizing operations
|
||||
tags:
|
||||
- name: CR-Connect
|
||||
|
@ -22,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
|
||||
|
@ -51,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
|
||||
|
@ -74,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
|
||||
|
@ -103,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:
|
|
@ -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):
|
|
@ -1,5 +1,5 @@
|
|||
from sqlalchemy import func
|
||||
from app import db, ma
|
||||
from pb import db, ma
|
||||
|
||||
|
||||
class Study(db.Model):
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
2
run.py
2
run.py
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
from setuptools import setup
|
||||
|
||||
setup(setup_requires=["pbr"], pbr=True)
|
|
@ -3,11 +3,13 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Protocol Builder Mock Configuration</title>
|
||||
<base href="/">
|
||||
<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">
|
||||
<link href="{{ base_href + ASSET_URL }}" rel="stylesheet" type="text/css">
|
||||
{% endassets %}
|
||||
<link rel="shortcut icon" href="{{ base_href + url_for('static', filename='favicon.ico') }}">
|
||||
</head>
|
||||
<body>
|
||||
<h2>{{ title }}</h2>
|
||||
|
@ -27,7 +29,7 @@
|
|||
</div>
|
||||
{% endfor %}
|
||||
<button class="btn btn-primary" type="submit">Submit</button>
|
||||
<a href="/" class="btn btn-default">Cancel</a>
|
||||
<a href="{{ url_for('index') }}" class="btn btn-default">Cancel</a>
|
||||
</form>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
<html lang="en">
|
||||
<head>
|
||||
<title>Protocol Builder Mock</title>
|
||||
<base href="/">
|
||||
<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">
|
||||
<link href="{{ base_href + ASSET_URL }}" rel="stylesheet" type="text/css">
|
||||
{% endassets %}
|
||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||
<link rel="shortcut icon" href="{{ base_href + url_for('static', filename='favicon.ico') }}">
|
||||
</head>
|
||||
<body>
|
||||
<h2>Protocol Builder Mock</h2>
|
||||
|
|
|
@ -3,9 +3,11 @@ import os
|
|||
os.environ["TESTING"] = "true"
|
||||
|
||||
import unittest
|
||||
from app import app, db
|
||||
from forms import StudyForm
|
||||
from models import Study, RequiredDocument
|
||||
import random
|
||||
import string
|
||||
from pb import app, db
|
||||
from pb.forms import StudyForm
|
||||
from pb.models import Study, RequiredDocument
|
||||
|
||||
|
||||
class Sanity_Check_Test(unittest.TestCase):
|
||||
|
@ -32,7 +34,8 @@ class Sanity_Check_Test(unittest.TestCase):
|
|||
|
||||
def test_add_and_edit_study(self):
|
||||
"""Add and edit a study"""
|
||||
study = Study(TITLE="My Test Document", NETBADGEID="dhf8r")
|
||||
study_title = "My Test Document" + ''.join(random.choices(string.digits, k=8))
|
||||
study = Study(TITLE=study_title, NETBADGEID="dhf8r")
|
||||
form = StudyForm(formdata=None, obj=study)
|
||||
num_reqs = len(form.requirements.choices)
|
||||
self.assertGreater(num_reqs, 0)
|
||||
|
@ -40,9 +43,9 @@ class Sanity_Check_Test(unittest.TestCase):
|
|||
for r in form.requirements:
|
||||
form.data['requirements'].append(r.data)
|
||||
|
||||
r = self.app.post('/new_study', data=form.data, follow_redirects=True)
|
||||
assert r.status_code == 200
|
||||
added_study = Study.query.filter(Study.TITLE == "My Test Document").first()
|
||||
r = self.app.post('/new_study', data=form.data, follow_redirects=False)
|
||||
assert r.status_code == 302
|
||||
added_study = Study.query.filter(Study.TITLE == study_title).first()
|
||||
assert added_study
|
||||
num_studies_before = Study.query.count()
|
||||
|
||||
|
@ -50,14 +53,14 @@ class Sanity_Check_Test(unittest.TestCase):
|
|||
self.assertEqual(num_reqs, num_docs_before)
|
||||
|
||||
"""Edit an existing study"""
|
||||
added_study.title = "New Title"
|
||||
added_study.title = "New Title" + ''.join(random.choices(string.digits, k=8))
|
||||
form_2 = StudyForm(formdata=None, obj=added_study)
|
||||
|
||||
for r in form_2.requirements:
|
||||
form_2.data['requirements'].append(r.data)
|
||||
|
||||
r_2 = self.app.post('/study/%i' % added_study.STUDYID, data=form_2.data, follow_redirects=True)
|
||||
assert r_2.status_code == 200
|
||||
r_2 = self.app.post('/study/%i' % added_study.STUDYID, data=form_2.data, follow_redirects=False)
|
||||
assert r_2.status_code == 302
|
||||
num_studies_after = Study.query.count()
|
||||
edited_study = Study.query.filter(Study.STUDYID == added_study.STUDYID).first()
|
||||
assert edited_study
|
|
@ -0,0 +1,23 @@
|
|||
from werkzeug.exceptions import NotFound
|
||||
from werkzeug.middleware.dispatcher import DispatcherMiddleware
|
||||
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
|
||||
from pb import app
|
||||
|
||||
if __name__ == "__main__":
|
||||
def no_app(environ, start_response):
|
||||
return NotFound()(environ, start_response)
|
||||
|
||||
# Remove trailing slash, but add leading slash
|
||||
base_url = '/' + app.config['APPLICATION_ROOT'].strip('/')
|
||||
routes = {'/': app.wsgi_app}
|
||||
|
||||
if base_url != '/':
|
||||
routes[base_url] = app.wsgi_app
|
||||
|
||||
app.wsgi_app = DispatcherMiddleware(no_app, routes)
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app)
|
||||
|
||||
flask_port = app.config['FLASK_PORT']
|
||||
|
||||
app.run(host='0.0.0.0', port=flask_port)
|
Loading…
Reference in New Issue