Initial commit
parent
0477400a74
commit
a5f7dc54dd
|
@ -1,5 +1,5 @@
|
||||||
import flask
|
import flask
|
||||||
from formity.extensions import db, migrate, admin
|
from formity.extensions import db, migrate, admin, auth, babel
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
app = flask.Flask(
|
app = flask.Flask(
|
||||||
|
@ -14,6 +14,8 @@ def create_app():
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
migrate.init_app(app, db)
|
migrate.init_app(app, db)
|
||||||
admin.init_app(app)
|
admin.init_app(app)
|
||||||
|
babel.init_app(app)
|
||||||
|
auth.init_app(app)
|
||||||
|
|
||||||
import formity.admin
|
import formity.admin
|
||||||
import formity.views
|
import formity.views
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
from formity.extensions import admin, db, ModelView
|
||||||
|
from formity.models import FaceshieldRequest
|
||||||
|
|
||||||
|
|
||||||
|
admin.add_view(ModelView(FaceshieldRequest, db.session))
|
|
@ -2,6 +2,8 @@ from flask import current_app
|
||||||
import flask_sqlalchemy
|
import flask_sqlalchemy
|
||||||
import flask_migrate
|
import flask_migrate
|
||||||
import flask_admin
|
import flask_admin
|
||||||
|
import flask_babel
|
||||||
|
import spaceauth
|
||||||
|
|
||||||
from flask_admin.contrib.sqla import ModelView as BaseModelView
|
from flask_admin.contrib.sqla import ModelView as BaseModelView
|
||||||
from flask_login import current_user
|
from flask_login import current_user
|
||||||
|
@ -26,3 +28,5 @@ class ModelView(SecurityMixin, BaseModelView):
|
||||||
db = flask_sqlalchemy.SQLAlchemy()
|
db = flask_sqlalchemy.SQLAlchemy()
|
||||||
migrate = flask_migrate.Migrate()
|
migrate = flask_migrate.Migrate()
|
||||||
admin = flask_admin.Admin(template_mode='bootstrap3', index_view=IndexView())
|
admin = flask_admin.Admin(template_mode='bootstrap3', index_view=IndexView())
|
||||||
|
babel = flask_babel.Babel()
|
||||||
|
auth = spaceauth.SpaceAuth()
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, TextAreaField, IntegerField, validators
|
||||||
|
|
||||||
|
|
||||||
|
class FaceshieldRequestForm(FlaskForm):
|
||||||
|
entity_info = TextAreaField('Dane placówki', validators=[validators.DataRequired()])
|
||||||
|
full_name = StringField('Imię i nazwisko', validators=[validators.DataRequired()])
|
||||||
|
phone_number = StringField('Numer telefonu', validators=[validators.DataRequired()])
|
||||||
|
email = StringField('Adres e-mail', validators=[validators.DataRequired(), validators.Email()])
|
||||||
|
extra = TextAreaField('Dodatkowe informacje')
|
||||||
|
|
||||||
|
faceshield_front_required = IntegerField('Pilnie potrzebna minimalna ilość samych szybek do przyłbic', validators=[validators.DataRequired()])
|
||||||
|
faceshield_model = StringField('Model przyłbicy', validators=[validators.DataRequired()])
|
||||||
|
|
||||||
|
faceshield_full_required = IntegerField('Pilnie potrzebna minimalna ilość pełnych przyłbic', validators=[validators.DataRequired()])
|
|
@ -1 +1,21 @@
|
||||||
from formity.extensions import db
|
from formity.extensions import db
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class FaceshieldRequest(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
|
||||||
|
entity_info = db.Column(db.String)
|
||||||
|
full_name = db.Column(db.String)
|
||||||
|
phone_number = db.Column(db.String)
|
||||||
|
email = db.Column(db.String)
|
||||||
|
extra = db.Column(db.String)
|
||||||
|
|
||||||
|
faceshield_front_required = db.Column(db.Integer)
|
||||||
|
faceshield_model = db.Column(db.String)
|
||||||
|
|
||||||
|
faceshield_full_required = db.Column(db.Integer)
|
||||||
|
|
||||||
|
created = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
|
||||||
|
updated = db.Column(db.DateTime, default=datetime.utcnow, nullable=False,
|
||||||
|
onupdate=datetime.utcnow)
|
||||||
|
|
|
@ -6,3 +6,8 @@ FLASK_ADMIN_FLUID_LAYOUT = True
|
||||||
|
|
||||||
SECRET_KEY = env.str('SECRET_KEY', default='randomstring')
|
SECRET_KEY = env.str('SECRET_KEY', default='randomstring')
|
||||||
SQLALCHEMY_DATABASE_URI = env.str('DATABASE_URI', default='postgresql+psycopg2://postgres:secret@postgres')
|
SQLALCHEMY_DATABASE_URI = env.str('DATABASE_URI', default='postgresql+psycopg2://postgres:secret@postgres')
|
||||||
|
|
||||||
|
SPACEAUTH_CONSUMER_KEY = env.str('SPACEAUTH_CONSUMER_KEY', default='')
|
||||||
|
SPACEAUTH_CONSUMER_SECRET = env.str('SPACEAUTH_CONSUMER_SECRET', default='')
|
||||||
|
|
||||||
|
BABEL_DEFAULT_LOCALE = 'pl'
|
||||||
|
|
|
@ -1,3 +1,20 @@
|
||||||
from flask import Blueprint
|
from flask import Blueprint, render_template, flash
|
||||||
|
from formity.extensions import db
|
||||||
|
from formity.models import FaceshieldRequest
|
||||||
|
from formity.forms import FaceshieldRequestForm
|
||||||
|
|
||||||
bp = Blueprint('main', __name__)
|
bp = Blueprint('main', __name__)
|
||||||
|
|
||||||
|
@bp.route('/', methods=['GET', 'POST'])
|
||||||
|
def index():
|
||||||
|
form = FaceshieldRequestForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
db.session.add(FaceshieldRequest(**{
|
||||||
|
k: v
|
||||||
|
for k, v in form.data.items()
|
||||||
|
if hasattr(FaceshieldRequest, k)
|
||||||
|
}))
|
||||||
|
db.session.commit()
|
||||||
|
flash('Zapytanie zostało wysłane.', 'success')
|
||||||
|
|
||||||
|
return render_template('index.html', form=form)
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
"""Initial migration
|
||||||
|
|
||||||
|
Revision ID: 1379dfa9e1d4
|
||||||
|
Revises:
|
||||||
|
Create Date: 2020-03-26 08:21:09.279323
|
||||||
|
|
||||||
|
"""
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision = '1379dfa9e1d4'
|
||||||
|
down_revision = None
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table('faceshield_request',
|
||||||
|
sa.Column('id', sa.Integer(), nullable=False),
|
||||||
|
sa.Column('entity_info', sa.String(), nullable=True),
|
||||||
|
sa.Column('full_name', sa.String(), nullable=True),
|
||||||
|
sa.Column('phone_number', sa.String(), nullable=True),
|
||||||
|
sa.Column('email', sa.String(), nullable=True),
|
||||||
|
sa.Column('extra', sa.String(), nullable=True),
|
||||||
|
sa.Column('faceshield_front_required', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('faceshield_model', sa.String(), nullable=True),
|
||||||
|
sa.Column('faceshield_full_required', sa.Integer(), nullable=True),
|
||||||
|
sa.Column('created', sa.DateTime(), nullable=False),
|
||||||
|
sa.Column('updated', sa.DateTime(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint('id')
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade():
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table('faceshield_request')
|
||||||
|
# ### end Alembic commands ###
|
|
@ -1,4 +1,5 @@
|
||||||
alembic==1.4.2
|
alembic==1.4.2
|
||||||
|
Babel==2.8.0
|
||||||
blinker==1.4
|
blinker==1.4
|
||||||
certifi==2019.11.28
|
certifi==2019.11.28
|
||||||
chardet==3.0.4
|
chardet==3.0.4
|
||||||
|
@ -6,11 +7,13 @@ click==7.1.1
|
||||||
environs==7.3.1
|
environs==7.3.1
|
||||||
Flask==1.1.1
|
Flask==1.1.1
|
||||||
Flask-Admin==1.5.5
|
Flask-Admin==1.5.5
|
||||||
|
Flask-Babel==1.0.0
|
||||||
Flask-Login==0.5.0
|
Flask-Login==0.5.0
|
||||||
Flask-Migrate==2.5.3
|
Flask-Migrate==2.5.3
|
||||||
Flask-OAuthlib==0.9.5
|
Flask-OAuthlib==0.9.5
|
||||||
git+https://code.hackerspace.pl/informatic/flask-spaceauth#egg=Flask-SpaceAuth
|
git+https://code.hackerspace.pl/informatic/flask-spaceauth#egg=Flask-SpaceAuth
|
||||||
Flask-SQLAlchemy==2.4.1
|
Flask-SQLAlchemy==2.4.1
|
||||||
|
Flask-WTF==0.14.3
|
||||||
idna==2.9
|
idna==2.9
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
Jinja2==2.11.1
|
Jinja2==2.11.1
|
||||||
|
@ -21,10 +24,11 @@ oauthlib==2.1.0
|
||||||
python-dateutil==2.8.1
|
python-dateutil==2.8.1
|
||||||
python-dotenv==0.12.0
|
python-dotenv==0.12.0
|
||||||
python-editor==1.0.4
|
python-editor==1.0.4
|
||||||
|
pytz==2019.3
|
||||||
requests==2.23.0
|
requests==2.23.0
|
||||||
requests-oauthlib==1.3.0
|
requests-oauthlib==1.3.0
|
||||||
six==1.14.0
|
six==1.14.0
|
||||||
SQLAlchemy==1.3.15
|
SQLAlchemy==1.3.15
|
||||||
urllib3==1.25.8
|
urllib3==1.25.8
|
||||||
Werkzeug==1.0.0
|
Werkzeug==0.16.1
|
||||||
WTForms==2.2.1
|
WTForms==2.2.1
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
||||||
|
{% macro format_currency(amount, color=True, precision=2) -%}
|
||||||
|
{%- if amount == None -%}
|
||||||
|
None
|
||||||
|
{%- else -%}
|
||||||
|
<span class="amount{% if color %}{% if amount < 0 %} amount-negative{% else %} amount-positive{% endif %}{% endif %}" data-original="{{ amount }}">
|
||||||
|
{{ format_currency_raw(amount, precision) }}
|
||||||
|
</span>
|
||||||
|
{%- endif %}
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{% macro format_currency_raw(amount, precision=0) -%}
|
||||||
|
{{ ("%%.%sf" | format(precision) | format(amount/100)) }}SOG
|
||||||
|
{%- endmacro %}
|
||||||
|
{% macro render_field(field, prefix=None, suffix=None, layout=True, label=True) %}
|
||||||
|
{% if field.type == 'HiddenField' or field.type == 'CSRFTokenField' %}
|
||||||
|
{{ field(**kwargs) }}
|
||||||
|
{% else %}
|
||||||
|
{% if layout %}
|
||||||
|
<div class="form-group{% if field.errors %} has-error{% endif %}">
|
||||||
|
{% if field.type == 'BooleanField' %}
|
||||||
|
<div class="col-md-3"></div>
|
||||||
|
{% elif label %}
|
||||||
|
{{ field.label(class_='col-md-3 control-label' + (' control-label-required' if field.flags.required else '')) }}
|
||||||
|
{% endif %}
|
||||||
|
<div class="col-md-9">
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ render_field_inner(field, prefix, suffix, label=label, **kwargs) }}
|
||||||
|
|
||||||
|
{% if layout %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_field_inner(field, prefix=None, suffix=None, label=True, input_group_class='') %}
|
||||||
|
{% if field.type == 'BooleanField' %}<div class="checkbox"><label for="{{ field.id }}">{% endif %}
|
||||||
|
{% if prefix or suffix %}<div class="input-group {{ input_group_class }}">{% endif %}
|
||||||
|
{% if prefix %}<span class="input-group-addon">{{ prefix }}</span>{% endif %}
|
||||||
|
{% if field.type == 'BooleanField' %}
|
||||||
|
{{ field(**kwargs) }} {% if label %}{{ field.label.text }}{% endif %}
|
||||||
|
{% elif field.type == 'RadioField' %}
|
||||||
|
{{ field(**kwargs) }}
|
||||||
|
{% else %}
|
||||||
|
{{ field(class_='form-control '+kwargs.pop('class_', ''), **kwargs) }}
|
||||||
|
{% endif %}
|
||||||
|
{% if suffix %}<span class="input-group-addon">{{ suffix }}</span>{% endif %}
|
||||||
|
{% if prefix or suffix %}</div>{% endif %}
|
||||||
|
{% if field.description and label %}
|
||||||
|
<span class="help-block">{{ field.description }}</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if field.errors %}
|
||||||
|
{% for error in field.errors %}
|
||||||
|
<span class="help-block">{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% if field.type == 'BooleanField' %}</label></div>{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_submit(label='Submit', class_='btn btn-primary', layout=True) %}
|
||||||
|
{% if layout %}
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-9 col-md-offset-3">
|
||||||
|
{% endif %}
|
||||||
|
<button type="submit" class="{{ class_ }}">{{ label }}</button>
|
||||||
|
{% if layout %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro render_pagination(pagination) %}
|
||||||
|
<ul class="pagination text-center">
|
||||||
|
{% if pagination.has_prev %}
|
||||||
|
<li><a href="{{ url_for_other_page(pagination.page - 1) }}">«</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled"><a>«</a></li>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{%- for page in pagination.iter_pages() %}
|
||||||
|
{% if page %}
|
||||||
|
{% if page != pagination.page %}
|
||||||
|
<li><a href="{{ url_for_other_page(page) }}">{{ page }}</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li class="active"><a href="{{ url_for_other_page(page) }}">{{ page }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled"><a>…</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{%- endfor %}
|
||||||
|
|
||||||
|
{% if pagination.has_next %}
|
||||||
|
<li><a href="{{ url_for_other_page(pagination.page + 1) }}">»</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li class="disabled"><a>»</a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
{% endmacro %}
|
|
@ -0,0 +1,62 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>COVID-19 Relief</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.css') }}" media="screen">
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin-top: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
padding-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
footer {
|
||||||
|
padding-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3.page-header {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
.input-group-btn .btn {
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
|
.placeholder {
|
||||||
|
text-align: center;
|
||||||
|
opacity: 0.5;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.vend-item code {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
.control-label-required::after {
|
||||||
|
content: ' *';
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="alert alert-{{category}}">{{ message }}</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
<footer class="row"><big>made by <a href="https://wiki.hackerspace.pl/people:informatic:start">inf</a></big></footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="{{ url_for('static', filename='js/jquery-1.10.2.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
|
||||||
|
{% block tail_js %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,11 @@
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% from "_helpers.html" import render_field, render_submit %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form action="" method="POST" class="form-horizontal">
|
||||||
|
{% for field in form %}
|
||||||
|
{{ render_field(field) }}
|
||||||
|
{% endfor %}
|
||||||
|
{{ render_submit() }}
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue