mirror of
https://github.com/sartography/protocol-builder-mock.git
synced 2025-01-12 08:44:46 +00:00
Moves styles into scss. Makes things prettier.
This commit is contained in:
parent
43a9a66d63
commit
52f8b0d2f9
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
.idea
|
||||
__pycache__/
|
||||
app.db
|
||||
static/.webassets-cache*
|
||||
static/*.css
|
||||
|
2
Pipfile
2
Pipfile
@ -12,12 +12,14 @@ gevent = "*"
|
||||
flask-wtf = "*"
|
||||
sqlalchemy = "*"
|
||||
flask-sqlalchemy = "*"
|
||||
flask-assets = "*"
|
||||
flask-table = "*"
|
||||
flask-migrate = "*"
|
||||
flask-marshmallow = "*"
|
||||
ma = "*"
|
||||
marshmallow-sqlalchemy = "*"
|
||||
wtforms-alchemy = "*"
|
||||
pyscss = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.7"
|
||||
|
42
Pipfile.lock
generated
42
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "96c16527bfb9e0a4363b92b0fff94997f533b831fedb0c5b06c84fcad31231d8"
|
||||
"sha256": "d08ffb3e7cd1b35e9acf7581587157d4f9577b937b3f4a0289ac7ab7a0b2134e"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
@ -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",
|
||||
@ -195,10 +203,10 @@
|
||||
},
|
||||
"idna": {
|
||||
"hashes": [
|
||||
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
|
||||
"sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
|
||||
"sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb",
|
||||
"sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"
|
||||
],
|
||||
"version": "==2.8"
|
||||
"version": "==2.9"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
@ -306,10 +314,10 @@
|
||||
},
|
||||
"marshmallow": {
|
||||
"hashes": [
|
||||
"sha256:7669b944d6233b81f68739d5826f1176c3841cc31cf6b856841083b5a72f5ca9",
|
||||
"sha256:c9d277f6092f32300395fb83d343be9f61b5e99d66d22bae1e5e7cd82608fee6"
|
||||
"sha256:3a94945a7461f2ab4df9576e51c97d66bee2c86155d3d3933fab752b31effab8",
|
||||
"sha256:4b95c7735f93eb781dfdc4dded028108998cad759dda8dd9d4b5b4ac574cbf13"
|
||||
],
|
||||
"version": "==3.4.0"
|
||||
"version": "==3.5.0"
|
||||
},
|
||||
"marshmallow-sqlalchemy": {
|
||||
"hashes": [
|
||||
@ -333,6 +341,13 @@
|
||||
],
|
||||
"version": "==0.15.7"
|
||||
},
|
||||
"pyscss": {
|
||||
"hashes": [
|
||||
"sha256:14a25c33c221a66bb1f000a6a067f376528d3df2f9333cee9c95709a9280cdb0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.3.5"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
|
||||
@ -373,10 +388,10 @@
|
||||
},
|
||||
"requests": {
|
||||
"hashes": [
|
||||
"sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
|
||||
"sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
|
||||
"sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee",
|
||||
"sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6"
|
||||
],
|
||||
"version": "==2.22.0"
|
||||
"version": "==2.23.0"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
@ -419,6 +434,13 @@
|
||||
],
|
||||
"version": "==0.14.2"
|
||||
},
|
||||
"webassets": {
|
||||
"hashes": [
|
||||
"sha256:167132337677c8cedc9705090f6d48da3fb262c8e0b2773b29f3352f050181cd",
|
||||
"sha256:a31a55147752ba1b3dc07dee0ad8c8efff274464e08bbdb88c1fd59ffd552724"
|
||||
],
|
||||
"version": "==2.0"
|
||||
},
|
||||
"werkzeug": {
|
||||
"hashes": [
|
||||
"sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096",
|
||||
|
5
app.py
5
app.py
@ -4,6 +4,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
|
||||
@ -47,6 +48,10 @@ app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
|
||||
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 = {}
|
||||
|
30
forms.py
30
forms.py
@ -32,16 +32,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