├── app ├── views.py ├── home │ ├── forms.py │ ├── __init__.py │ └── views.py ├── static │ ├── semantic │ │ ├── .versions │ │ ├── themes │ │ │ └── default │ │ │ │ └── assets │ │ │ │ ├── fonts │ │ │ │ ├── icons.eot │ │ │ │ ├── icons.otf │ │ │ │ ├── icons.ttf │ │ │ │ ├── icons.woff │ │ │ │ └── icons.woff2 │ │ │ │ └── images │ │ │ │ └── flags.png │ │ ├── README.md │ │ ├── package.json │ │ ├── components │ │ │ ├── sticky.min.css │ │ │ ├── tab.min.css │ │ │ ├── breadcrumb.min.css │ │ │ ├── video.min.css │ │ │ ├── rail.min.css │ │ │ ├── nag.min.css │ │ │ ├── sticky.css │ │ │ ├── embed.min.css │ │ │ ├── container.min.css │ │ │ ├── ad.min.css │ │ │ ├── tab.css │ │ │ ├── site.min.css │ │ │ ├── shape.min.css │ │ │ ├── breadcrumb.css │ │ │ ├── reset.min.css │ │ │ ├── video.css │ │ │ ├── comment.min.css │ │ │ ├── dimmer.min.css │ │ │ ├── colorize.min.js │ │ │ ├── rail.css │ │ │ ├── nag.css │ │ │ ├── feed.min.css │ │ │ ├── image.min.css │ │ │ ├── container.css │ │ │ ├── embed.css │ │ │ ├── shape.css │ │ │ ├── loader.min.css │ │ │ ├── site.css │ │ │ ├── rating.min.js │ │ │ ├── ad.css │ │ │ ├── nag.min.js │ │ │ ├── dimmer.css │ │ │ ├── reveal.min.css │ │ │ ├── visit.min.js │ │ │ ├── item.min.css │ │ │ ├── site.min.js │ │ │ ├── divider.min.css │ │ │ └── video.min.js │ │ ├── package.js │ │ └── LICENSE │ ├── img │ │ ├── favicon.ico │ │ └── logo │ │ │ ├── logo.jpg │ │ │ ├── logo.png │ │ │ ├── logo-grey.jpg │ │ │ ├── logo-grey.png │ │ │ ├── logo-large.jpg │ │ │ ├── logo-large.png │ │ │ ├── logo-grey-large.jpg │ │ │ ├── logo-grey-large.png │ │ │ ├── logo-basic-200-x-200.jpg │ │ │ ├── logo-basic-200-x-200.png │ │ │ ├── logo-basic-grey-200-x-200.jpg │ │ │ ├── logo-basic-grey-200-x-200.png │ │ │ └── Read me before using your logo.txt │ ├── login-page │ │ ├── logo.png │ │ ├── container.css │ │ ├── login-page-template.html │ │ └── site.css │ └── css │ │ └── style.css ├── admin │ ├── __init__.py │ └── forms.py ├── auth │ ├── __init__.py │ ├── forms.py │ └── views.py ├── templates │ ├── home │ │ ├── dashboard.html │ │ ├── admin_dashboard.html │ │ └── index.html │ ├── errors │ │ ├── 404.html │ │ ├── 403.html │ │ └── 500.html │ ├── admin │ │ ├── employees │ │ │ ├── employee.html │ │ │ └── employees.html │ │ ├── roles │ │ │ ├── role.html │ │ │ └── roles.html │ │ └── departments │ │ │ ├── department.html │ │ │ └── departments.html │ └── auth │ │ └── login.html ├── __init__.py └── models.py ├── migrations ├── README ├── script.py.mako ├── alembic.ini ├── versions │ ├── 379ff2e91076_.py │ └── a34b0520b5b3_.py └── env.py ├── screenshots ├── employees-screenshot.png ├── home-page-screenshot.png ├── register-screenshot.png └── home-page-screenshot2.png ├── run.py ├── requirements.txt ├── conda_environment.txt ├── config.py └── .gitignore /app/views.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/home/forms.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /migrations/README: -------------------------------------------------------------------------------- 1 | Generic single-database configuration. -------------------------------------------------------------------------------- /app/static/semantic/.versions: -------------------------------------------------------------------------------- 1 | jquery@1.11.3_2 2 | meteor@1.1.6 3 | semantic:ui-css@2.0.7 4 | underscore@1.0.3 5 | -------------------------------------------------------------------------------- /app/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/favicon.ico -------------------------------------------------------------------------------- /app/static/img/logo/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo.jpg -------------------------------------------------------------------------------- /app/static/img/logo/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo.png -------------------------------------------------------------------------------- /app/admin/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | admin = Blueprint('admin', __name__) 4 | 5 | from . import views 6 | -------------------------------------------------------------------------------- /app/auth/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | auth = Blueprint('auth', __name__) 4 | 5 | from . import views 6 | -------------------------------------------------------------------------------- /app/home/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | home = Blueprint('home', __name__) 4 | 5 | from . import views 6 | -------------------------------------------------------------------------------- /app/static/login-page/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/login-page/logo.png -------------------------------------------------------------------------------- /app/static/img/logo/logo-grey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-grey.jpg -------------------------------------------------------------------------------- /app/static/img/logo/logo-grey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-grey.png -------------------------------------------------------------------------------- /app/static/img/logo/logo-large.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-large.jpg -------------------------------------------------------------------------------- /app/static/img/logo/logo-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-large.png -------------------------------------------------------------------------------- /screenshots/employees-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/screenshots/employees-screenshot.png -------------------------------------------------------------------------------- /screenshots/home-page-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/screenshots/home-page-screenshot.png -------------------------------------------------------------------------------- /screenshots/register-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/screenshots/register-screenshot.png -------------------------------------------------------------------------------- /app/static/img/logo/logo-grey-large.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-grey-large.jpg -------------------------------------------------------------------------------- /app/static/img/logo/logo-grey-large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-grey-large.png -------------------------------------------------------------------------------- /screenshots/home-page-screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/screenshots/home-page-screenshot2.png -------------------------------------------------------------------------------- /app/static/img/logo/logo-basic-200-x-200.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-basic-200-x-200.jpg -------------------------------------------------------------------------------- /app/static/img/logo/logo-basic-200-x-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-basic-200-x-200.png -------------------------------------------------------------------------------- /app/static/img/logo/logo-basic-grey-200-x-200.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-basic-grey-200-x-200.jpg -------------------------------------------------------------------------------- /app/static/img/logo/logo-basic-grey-200-x-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/img/logo/logo-basic-grey-200-x-200.png -------------------------------------------------------------------------------- /app/static/semantic/themes/default/assets/fonts/icons.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/semantic/themes/default/assets/fonts/icons.eot -------------------------------------------------------------------------------- /app/static/semantic/themes/default/assets/fonts/icons.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/semantic/themes/default/assets/fonts/icons.otf -------------------------------------------------------------------------------- /app/static/semantic/themes/default/assets/fonts/icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/semantic/themes/default/assets/fonts/icons.ttf -------------------------------------------------------------------------------- /app/static/semantic/themes/default/assets/fonts/icons.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/semantic/themes/default/assets/fonts/icons.woff -------------------------------------------------------------------------------- /app/static/semantic/themes/default/assets/fonts/icons.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/semantic/themes/default/assets/fonts/icons.woff2 -------------------------------------------------------------------------------- /app/static/semantic/themes/default/assets/images/flags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/16967143/basic-CRUD-flask-app/HEAD/app/static/semantic/themes/default/assets/images/flags.png -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | # run.py 2 | 3 | import os 4 | 5 | from app import create_app 6 | 7 | config_name = os.getenv('FLASK_CONFIG') 8 | app = create_app(config_name) 9 | 10 | if __name__ == '__main__': 11 | app.run() -------------------------------------------------------------------------------- /app/static/semantic/README.md: -------------------------------------------------------------------------------- 1 | # CSS Distribution 2 | 3 | This repository is automatically synced with the main [Semantic UI](https://github.com/Semantic-Org/Semantic-UI) repository to provide lightweight CSS only version of Semantic UI. 4 | 5 | This package **does not support theming** and includes generated CSS files of the default theme only. 6 | 7 | You can view more on Semantic UI at [LearnSemantic.com](http://www.learnsemantic.com) and [Semantic-UI.com](http://www.semantic-ui.com) 8 | -------------------------------------------------------------------------------- /app/static/img/logo/Read me before using your logo.txt: -------------------------------------------------------------------------------- 1 | To use this logo for free, you must give credit by sharing DesignEvo on your social media, blog or website. 2 | 3 | 1. Share www.designevo.com on your social media, such as Facebook, Twitter, Google+, LinkedIn, etc. 4 | 5 | 2. Share www.designevo.com on your blog or website, or directly copy the code below and paste it on your website. 6 | 7 |
Logo made with DesignEvo
-------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | alembic==0.9.7 2 | certifi==2016.2.28 3 | click==6.7 4 | dominate==2.3.1 5 | Flask==0.12.2 6 | Flask-Bootstrap==3.3.7.1 7 | Flask-Login==0.4.1 8 | Flask-Migrate==2.1.1 9 | Flask-SQLAlchemy==2.3.2 10 | Flask-Testing==0.7.1 11 | Flask-WTF==0.14.2 12 | itsdangerous==0.24 13 | Jinja2==2.9.6 14 | Mako==1.0.7 15 | MarkupSafe==1.0 16 | psycopg2==2.7.4 17 | python-dateutil==2.6.1 18 | python-editor==1.0.3 19 | six==1.11.0 20 | SQLAlchemy==1.2.2 21 | visitor==0.1.3 22 | Werkzeug==0.12.2 23 | WTForms==2.1 24 | -------------------------------------------------------------------------------- /conda_environment.txt: -------------------------------------------------------------------------------- 1 | # This file may be used to create an environment using: 2 | # $ conda create --name --file 3 | # platform: linux-64 4 | certifi=2016.2.28=py36_0 5 | click=6.7=py36_0 6 | flask=0.12.2=py36_0 7 | itsdangerous=0.24=py36_0 8 | jinja2=2.9.6=py36_0 9 | markupsafe=1.0=py36_0 10 | openssl=1.0.2l=0 11 | pip=9.0.1=py36_1 12 | postgresql=9.5.4=0 13 | python=3.6.2=0 14 | readline=6.2=2 15 | setuptools=36.4.0=py36_1 16 | sqlite=3.13.0=0 17 | tk=8.5.18=0 18 | werkzeug=0.12.2=py36_0 19 | wheel=0.29.0=py36_0 20 | xz=5.2.3=0 21 | zlib=1.2.11=0 22 | -------------------------------------------------------------------------------- /app/static/semantic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "semantic-ui-css", 3 | "version": "2.2.14", 4 | "title": "Semantic UI", 5 | "description": "CSS Only distribution of Semantic UI", 6 | "homepage": "http://www.semantic-ui.com", 7 | "author": "Jack Lukic ", 8 | "license": "MIT", 9 | "main": "semantic.js", 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/Semantic-Org/Semantic-UI-CSS.git" 13 | }, 14 | "bugs": { 15 | "url": "https://github.com/Semantic-Org/Semantic-UI/issues" 16 | }, 17 | "dependencies": { 18 | "jquery": "x.*" 19 | } 20 | } -------------------------------------------------------------------------------- /migrations/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | ${imports if imports else ""} 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = ${repr(up_revision)} 14 | down_revision = ${repr(down_revision)} 15 | branch_labels = ${repr(branch_labels)} 16 | depends_on = ${repr(depends_on)} 17 | 18 | 19 | def upgrade(): 20 | ${upgrades if upgrades else "pass"} 21 | 22 | 23 | def downgrade(): 24 | ${downgrades if downgrades else "pass"} 25 | -------------------------------------------------------------------------------- /app/static/semantic/components/sticky.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Sticky 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.sticky{position:static;-webkit-transition:none;transition:none;z-index:800}.ui.sticky.bound{position:absolute;left:auto;right:auto}.ui.sticky.fixed{position:fixed;left:auto;right:auto}.ui.sticky.bound.top,.ui.sticky.fixed.top{top:0;bottom:auto}.ui.sticky.bound.bottom,.ui.sticky.fixed.bottom{top:auto;bottom:0}.ui.native.sticky{position:-webkit-sticky;position:-moz-sticky;position:-ms-sticky;position:-o-sticky;position:sticky} -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | # config.py 2 | 3 | class Config(object): 4 | """ 5 | Common configurations 6 | """ 7 | 8 | SQLALCHEMY_TRACK_MODIFICATIONS = False # suppresses annoying deprecation warning 9 | 10 | class DevelopmentConfig(Config): 11 | """ 12 | Development configurations 13 | """ 14 | 15 | DEBUG = True 16 | SQLALCHEMY_ECHO = True 17 | 18 | class ProductionConfig(Config): 19 | """ 20 | Production configurations 21 | """ 22 | 23 | DEBUG = False 24 | 25 | class TestingConfig(Config): 26 | """ 27 | Testing configurations 28 | """ 29 | 30 | TESTING = True 31 | 32 | app_config = { 33 | 'development': DevelopmentConfig, 34 | 'production': ProductionConfig, 35 | 'testing': TestingConfig 36 | } -------------------------------------------------------------------------------- /app/static/semantic/package.js: -------------------------------------------------------------------------------- 1 | var 2 | where = 'client' // Adds files only to the client 3 | ; 4 | 5 | Package.describe({ 6 | name : 'semantic:ui-css', 7 | summary : 'Semantic UI - CSS Release of Semantic UI', 8 | version : '2.2.14', 9 | git : 'git://github.com/Semantic-Org/Semantic-UI-CSS.git', 10 | }); 11 | 12 | Package.onUse(function(api) { 13 | 14 | api.versionsFrom('1.0'); 15 | 16 | api.use('jquery', 'client'); 17 | 18 | api.addFiles([ 19 | // icons 20 | 'themes/default/assets/fonts/icons.eot', 21 | 'themes/default/assets/fonts/icons.svg', 22 | 'themes/default/assets/fonts/icons.ttf', 23 | 'themes/default/assets/fonts/icons.woff', 24 | 'themes/default/assets/fonts/icons.woff2', 25 | 26 | // flags 27 | 'themes/default/assets/images/flags.png', 28 | 29 | // release 30 | 'semantic.css', 31 | 'semantic.js' 32 | ], 'client'); 33 | 34 | }); 35 | -------------------------------------------------------------------------------- /migrations/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # template used to generate migration files 5 | # file_template = %%(rev)s_%%(slug)s 6 | 7 | # set to 'true' to run the environment during 8 | # the 'revision' command, regardless of autogenerate 9 | # revision_environment = false 10 | 11 | 12 | # Logging configuration 13 | [loggers] 14 | keys = root,sqlalchemy,alembic 15 | 16 | [handlers] 17 | keys = console 18 | 19 | [formatters] 20 | keys = generic 21 | 22 | [logger_root] 23 | level = WARN 24 | handlers = console 25 | qualname = 26 | 27 | [logger_sqlalchemy] 28 | level = WARN 29 | handlers = 30 | qualname = sqlalchemy.engine 31 | 32 | [logger_alembic] 33 | level = INFO 34 | handlers = 35 | qualname = alembic 36 | 37 | [handler_console] 38 | class = StreamHandler 39 | args = (sys.stderr,) 40 | level = NOTSET 41 | formatter = generic 42 | 43 | [formatter_generic] 44 | format = %(levelname)-5.5s [%(name)s] %(message)s 45 | datefmt = %H:%M:%S 46 | -------------------------------------------------------------------------------- /app/static/semantic/components/tab.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Tab 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.tab{display:none}.ui.tab.active,.ui.tab.open{display:block}.ui.tab.loading{position:relative;overflow:hidden;display:block;min-height:250px}.ui.tab.loading *{position:relative!important;left:-10000px!important}.ui.tab.loading.segment:before,.ui.tab.loading:before{position:absolute;content:'';top:100px;left:50%;margin:-1.25em 0 0 -1.25em;width:2.5em;height:2.5em;border-radius:500rem;border:.2em solid rgba(0,0,0,.1)}.ui.tab.loading.segment:after,.ui.tab.loading:after{position:absolute;content:'';top:100px;left:50%;margin:-1.25em 0 0 -1.25em;width:2.5em;height:2.5em;-webkit-animation:button-spin .6s linear;animation:button-spin .6s linear;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;border-radius:500rem;border-color:#767676 transparent transparent;border-style:solid;border-width:.2em;-webkit-box-shadow:0 0 0 1px transparent;box-shadow:0 0 0 1px transparent} -------------------------------------------------------------------------------- /app/home/views.py: -------------------------------------------------------------------------------- 1 | from flask import abort, render_template 2 | from flask_login import current_user, login_required 3 | 4 | from . import home 5 | 6 | @home.route('/') 7 | def homepage(): 8 | """ 9 | Render the homepage template on the / route 10 | """ 11 | return render_template('home/index.html', title="Welcome") 12 | 13 | @home.route('/dashboard') 14 | @login_required 15 | def dashboard(): 16 | """ 17 | Render the dashboard template on the /dashboard route 18 | """ 19 | return render_template('home/dashboard.html', title="Dashboard") 20 | 21 | # add admin dashboard view 22 | @home.route('/admin/dashboard') 23 | @login_required 24 | def admin_dashboard(): 25 | # prevent non-admins from accessing the page 26 | if not current_user.is_admin: 27 | abort(403) 28 | 29 | return render_template('home/admin_dashboard.html', title="Dashboard") 30 | 31 | @home.route('/test2') 32 | def test2(): 33 | """ 34 | [temporary] Render the test homepage template on the /test2 route 35 | """ 36 | return render_template('home/index-attempt-to-fix-footer.html', title="Test2") 37 | 38 | -------------------------------------------------------------------------------- /migrations/versions/379ff2e91076_.py: -------------------------------------------------------------------------------- 1 | """empty message 2 | 3 | Revision ID: 379ff2e91076 4 | Revises: a34b0520b5b3 5 | Create Date: 2018-02-24 11:18:04.434971 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = '379ff2e91076' 14 | down_revision = 'a34b0520b5b3' 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | # ### commands auto generated by Alembic - please adjust! ### 21 | op.add_column('employees', sa.Column('user_type', sa.String(length=20), nullable=True)) 22 | op.drop_index('ix_employees_username', table_name='employees') 23 | op.drop_column('employees', 'username') 24 | # ### end Alembic commands ### 25 | 26 | 27 | def downgrade(): 28 | # ### commands auto generated by Alembic - please adjust! ### 29 | op.add_column('employees', sa.Column('username', sa.VARCHAR(length=60), autoincrement=False, nullable=True)) 30 | op.create_index('ix_employees_username', 'employees', ['username'], unique=True) 31 | op.drop_column('employees', 'user_type') 32 | # ### end Alembic commands ### 33 | -------------------------------------------------------------------------------- /app/static/semantic/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Semantic Org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /app/static/semantic/components/breadcrumb.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Breadcrumb 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.breadcrumb{line-height:1;display:inline-block;margin:0 0;vertical-align:middle}.ui.breadcrumb:first-child{margin-top:0}.ui.breadcrumb:last-child{margin-bottom:0}.ui.breadcrumb .divider{display:inline-block;opacity:.7;margin:0 .21428571rem 0;font-size:.92857143em;color:rgba(0,0,0,.4);vertical-align:baseline}.ui.breadcrumb a{color:#4183c4}.ui.breadcrumb a:hover{color:#1e70bf}.ui.breadcrumb .icon.divider{font-size:.85714286em;vertical-align:baseline}.ui.breadcrumb a.section{cursor:pointer}.ui.breadcrumb .section{display:inline-block;margin:0;padding:0}.ui.breadcrumb.segment{display:inline-block;padding:.78571429em 1em}.ui.breadcrumb .active.section{font-weight:700}.ui.mini.breadcrumb{font-size:.78571429rem}.ui.tiny.breadcrumb{font-size:.85714286rem}.ui.small.breadcrumb{font-size:.92857143rem}.ui.breadcrumb{font-size:1rem}.ui.large.breadcrumb{font-size:1.14285714rem}.ui.big.breadcrumb{font-size:1.28571429rem}.ui.huge.breadcrumb{font-size:1.42857143rem}.ui.massive.breadcrumb{font-size:1.71428571rem} -------------------------------------------------------------------------------- /app/templates/home/dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Dashboard{% endblock %} 5 | 6 | {% block head %} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 34 | {% endblock %} 35 | 36 | {% block body %} 37 |
38 |
39 |

40 | Dashboard page! 41 |

42 |
43 |
44 | 45 | {% endblock %} -------------------------------------------------------------------------------- /app/templates/home/admin_dashboard.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Admin Dashboard{% endblock %} 5 | {% block head %} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 33 | {% endblock %} 34 | 35 | {% block body %} 36 |
37 |
38 |

39 | Admin Dashboard page! 40 |

41 |
42 |
43 | 44 | {% endblock %} -------------------------------------------------------------------------------- /app/static/semantic/components/video.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.0.0 - Video 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Copyright 2014 Contributors 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */.ui.video{background-color:#ddd;position:relative;max-width:100%;padding-bottom:56.25%;height:0;overflow:hidden}.ui.video .placeholder{background-color:#333}.ui.video .play{cursor:pointer;position:absolute;top:0;left:0;z-index:10;width:100%;height:100%;background:0 0;-webkit-transition:background .2s ease;transition:background .2s ease}.ui.video .play.icon:before{position:absolute;top:50%;left:50%;z-index:11;-webkit-transform:translateX(-50%)translateY(-50%);-ms-transform:translateX(-50%)translateY(-50%);transform:translateX(-50%)translateY(-50%);color:rgba(255,255,255,.7);font-size:7rem;text-shadow:2px 2px 0 rgba(0,0,0,.15);-webkit-transition:color .2s ease;transition:color .2s ease}.ui.video .placeholder{position:absolute;top:0;left:0;display:block;width:100%;height:100%}.ui.video .embed embed,.ui.video .embed iframe,.ui.video .embed object{position:absolute;border:none;width:100%;height:100%;top:0;left:0;margin:0;padding:0}.ui.video .play:hover{background:0 0}.ui.video .play:hover:before{color:#fff}.ui.active.video .placeholder,.ui.active.video .play{display:none}.ui.active.video .embed{display:inline} -------------------------------------------------------------------------------- /app/templates/errors/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Page Not Found{% endblock %} 5 | {% block head %} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 33 | {% endblock %} 34 | 35 | {% block body %} 36 |
37 |
38 |

39 | 404 Error 40 |

41 |

The page you're looking for doesn't exist.

42 |
43 |
44 | 45 | {% endblock %} -------------------------------------------------------------------------------- /app/templates/errors/403.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Forbidden{% endblock %} 5 | 6 | {% block head %} 7 | 8 | 9 | 10 | 11 | 12 | 13 | 34 | {% endblock %} 35 | 36 | {% block body %} 37 |
38 |
39 |

40 | 403 Error 41 |

42 |

You do not have sufficient permissions to access this page.

43 |
44 |
45 | 46 | {% endblock %} -------------------------------------------------------------------------------- /app/templates/errors/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Internal Server Error{% endblock %} 5 | {% block head %} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 33 | {% endblock %} 34 | 35 | {% block body %} 36 |
37 |
38 |

39 | 500 Error 40 |

41 |

The server encountered an internal error. That's all we know.

42 |
43 |
44 | 45 | {% endblock %} -------------------------------------------------------------------------------- /app/admin/forms.py: -------------------------------------------------------------------------------- 1 | # app/admin/forms.py 2 | 3 | from flask_wtf import FlaskForm 4 | from wtforms import StringField, SubmitField 5 | from wtforms.validators import DataRequired 6 | from wtforms.ext.sqlalchemy.fields import QuerySelectField 7 | 8 | from ..models import Department, Role 9 | 10 | 11 | class DepartmentForm(FlaskForm): 12 | """ 13 | Form for admin to add or edit a department 14 | """ 15 | name = StringField('Name', validators=[DataRequired()]) 16 | description = StringField('Description', validators=[DataRequired()]) 17 | submit = SubmitField('Submit') 18 | 19 | class RoleForm(FlaskForm): 20 | """ 21 | Form for admin to add or edit a role 22 | """ 23 | name = StringField('Name', validators=[DataRequired()]) 24 | description = StringField('Description', validators=[DataRequired()]) 25 | submit = SubmitField('Submit') 26 | 27 | class EmployeeAssignForm(FlaskForm): 28 | """ 29 | Form for admin to assign departments and roles to employees 30 | """ 31 | department = QuerySelectField(query_factory=lambda: Department.query.all(), 32 | get_label=lambda x: x.name, get_pk=lambda x: x.id) # important! prevents "ValueError: too many values to unpack (expected 2)" 33 | role = QuerySelectField(query_factory=lambda: Role.query.all(), 34 | get_label=lambda x: x.name, get_pk=lambda x: x.id) 35 | submit = SubmitField('Submit') -------------------------------------------------------------------------------- /app/static/semantic/components/rail.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Rail 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.rail{position:absolute;top:0;width:300px;height:100%}.ui.left.rail{left:auto;right:100%;padding:0 2rem 0 0;margin:0 2rem 0 0}.ui.right.rail{left:100%;right:auto;padding:0 0 0 2rem;margin:0 0 0 2rem}.ui.left.internal.rail{left:0;right:auto;padding:0 0 0 2rem;margin:0 0 0 2rem}.ui.right.internal.rail{left:auto;right:0;padding:0 2rem 0 0;margin:0 2rem 0 0}.ui.dividing.rail{width:302.5px}.ui.left.dividing.rail{padding:0 2.5rem 0 0;margin:0 2.5rem 0 0;border-right:1px solid rgba(34,36,38,.15)}.ui.right.dividing.rail{border-left:1px solid rgba(34,36,38,.15);padding:0 0 0 2.5rem;margin:0 0 0 2.5rem}.ui.close.rail{width:calc(300px + 1em)}.ui.close.left.rail{padding:0 1em 0 0;margin:0 1em 0 0}.ui.close.right.rail{padding:0 0 0 1em;margin:0 0 0 1em}.ui.very.close.rail{width:calc(300px + .5em)}.ui.very.close.left.rail{padding:0 .5em 0 0;margin:0 .5em 0 0}.ui.very.close.right.rail{padding:0 0 0 .5em;margin:0 0 0 .5em}.ui.attached.left.rail,.ui.attached.right.rail{padding:0;margin:0}.ui.mini.rail{font-size:.78571429rem}.ui.tiny.rail{font-size:.85714286rem}.ui.small.rail{font-size:.92857143rem}.ui.rail{font-size:1rem}.ui.large.rail{font-size:1.14285714rem}.ui.big.rail{font-size:1.28571429rem}.ui.huge.rail{font-size:1.42857143rem}.ui.massive.rail{font-size:1.71428571rem} -------------------------------------------------------------------------------- /app/static/semantic/components/nag.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Nag 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.nag{display:none;opacity:.95;position:relative;top:0;left:0;z-index:999;min-height:0;width:100%;margin:0;padding:.75em 1em;background:#555;-webkit-box-shadow:0 1px 2px 0 rgba(0,0,0,.2);box-shadow:0 1px 2px 0 rgba(0,0,0,.2);font-size:1rem;text-align:center;color:rgba(0,0,0,.87);border-radius:0 0 .28571429rem .28571429rem;-webkit-transition:.2s background ease;transition:.2s background ease}a.ui.nag{cursor:pointer}.ui.nag>.title{display:inline-block;margin:0 .5em;color:#fff}.ui.nag>.close.icon{cursor:pointer;opacity:.4;position:absolute;top:50%;right:1em;font-size:1em;margin:-.5em 0 0;color:#fff;-webkit-transition:opacity .2s ease;transition:opacity .2s ease}.ui.nag:hover{background:#555;opacity:1}.ui.nag .close:hover{opacity:1}.ui.overlay.nag{position:absolute;display:block}.ui.fixed.nag{position:fixed}.ui.bottom.nag,.ui.bottom.nags{border-radius:.28571429rem .28571429rem 0 0;top:auto;bottom:0}.ui.inverted.nag,.ui.inverted.nags .nag{background-color:#f3f4f5;color:rgba(0,0,0,.85)}.ui.inverted.nag .close,.ui.inverted.nag .title,.ui.inverted.nags .nag .close,.ui.inverted.nags .nag .title{color:rgba(0,0,0,.4)}.ui.nags .nag{border-radius:0!important}.ui.nags .nag:last-child{border-radius:0 0 .28571429rem .28571429rem}.ui.bottom.nags .nag:last-child{border-radius:.28571429rem .28571429rem 0 0} -------------------------------------------------------------------------------- /app/static/semantic/components/sticky.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Sticky 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Sticky 14 | *******************************/ 15 | 16 | .ui.sticky { 17 | position: static; 18 | -webkit-transition: none; 19 | transition: none; 20 | z-index: 800; 21 | } 22 | 23 | 24 | /******************************* 25 | States 26 | *******************************/ 27 | 28 | 29 | /* Bound */ 30 | .ui.sticky.bound { 31 | position: absolute; 32 | left: auto; 33 | right: auto; 34 | } 35 | 36 | /* Fixed */ 37 | .ui.sticky.fixed { 38 | position: fixed; 39 | left: auto; 40 | right: auto; 41 | } 42 | 43 | /* Bound/Fixed Position */ 44 | .ui.sticky.bound.top, 45 | .ui.sticky.fixed.top { 46 | top: 0px; 47 | bottom: auto; 48 | } 49 | .ui.sticky.bound.bottom, 50 | .ui.sticky.fixed.bottom { 51 | top: auto; 52 | bottom: 0px; 53 | } 54 | 55 | 56 | /******************************* 57 | Types 58 | *******************************/ 59 | 60 | .ui.native.sticky { 61 | position: -webkit-sticky; 62 | position: -moz-sticky; 63 | position: -ms-sticky; 64 | position: -o-sticky; 65 | position: sticky; 66 | } 67 | 68 | 69 | /******************************* 70 | Theme Overrides 71 | *******************************/ 72 | 73 | 74 | 75 | /******************************* 76 | Site Overrides 77 | *******************************/ 78 | 79 | -------------------------------------------------------------------------------- /app/auth/forms.py: -------------------------------------------------------------------------------- 1 | from flask_wtf import FlaskForm 2 | from wtforms import PasswordField, StringField, SubmitField, ValidationError 3 | from wtforms.validators import DataRequired, Email, EqualTo, AnyOf 4 | 5 | from ..models import Employee 6 | 7 | class RegistrationForm(FlaskForm): 8 | """ 9 | Form for users to create new account 10 | """ 11 | email = StringField('Email', validators=[DataRequired(), Email()]) 12 | # username = StringField('Username', validators=[DataRequired()]) 13 | first_name = StringField('First Name', validators=[DataRequired()]) 14 | last_name = StringField('Last Name', validators=[DataRequired()]) 15 | password = PasswordField('Password', validators=[ 16 | DataRequired(), 17 | EqualTo('confirm_password') 18 | ]) 19 | confirm_password = PasswordField('Confirm Password') 20 | user_type = StringField('User Type', validators=[AnyOf(['Bioinformatics User', 'Standard User'])]) 21 | submit = SubmitField('Register') 22 | 23 | def validate_email(self, field): 24 | if Employee.query.filter_by(email=field.data).first(): 25 | raise ValidationError('Email is already in use.') 26 | 27 | def validate_username(self, field): 28 | if Employee.query.filter_by(username=field.data).first(): 29 | raise ValidationError('Username is already in use.') 30 | 31 | class LoginForm(FlaskForm): 32 | """ 33 | Form for users to login 34 | """ 35 | email = StringField('Email', validators=[DataRequired(), Email()]) 36 | password = PasswordField('Password', validators=[DataRequired()]) 37 | submit = SubmitField('Login') -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Instance directory for app 2 | instance/ 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # dotenv 86 | .env 87 | 88 | # virtualenv 89 | .venv 90 | venv/ 91 | ENV/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | # app/__init__.py 2 | 3 | # third-party imports 4 | from flask import abort, Flask, render_template 5 | from flask_sqlalchemy import SQLAlchemy 6 | from flask_login import LoginManager 7 | from flask_migrate import Migrate 8 | from flask_bootstrap import Bootstrap 9 | 10 | # local imports 11 | from config import app_config 12 | 13 | # db variable initialization 14 | db = SQLAlchemy() 15 | # login manager initialisation 16 | login_manager = LoginManager() 17 | 18 | def create_app(config_name): 19 | app = Flask(__name__, instance_relative_config=True) 20 | app.config.from_object(app_config[config_name]) 21 | app.config.from_pyfile('config.py') 22 | 23 | Bootstrap(app) # seems to be required for routes with prefixes to work... 24 | db.init_app(app) 25 | login_manager.init_app(app) 26 | login_manager.login_message = "You must be logged in to access this page." 27 | login_manager.login_view = "auth.login" 28 | migrate = Migrate(app, db) 29 | 30 | from app import models 31 | 32 | from .admin import admin as admin_blueprint 33 | app.register_blueprint(admin_blueprint, url_prefix='/admin') 34 | 35 | from .auth import auth as auth_blueprint 36 | app.register_blueprint(auth_blueprint) 37 | 38 | from .home import home as home_blueprint 39 | app.register_blueprint(home_blueprint) 40 | 41 | @app.errorhandler(403) 42 | def forbidden(error): 43 | return render_template('errors/403.html', title='Forbidden'), 403 44 | 45 | @app.errorhandler(404) 46 | def page_not_found(error): 47 | return render_template('errors/404.html', title='Page Not Found'), 404 48 | 49 | @app.errorhandler(500) 50 | def internal_server_error(error): 51 | return render_template('errors/500.html', title='Server Error'), 500 52 | 53 | return app -------------------------------------------------------------------------------- /app/static/semantic/components/embed.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Video 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.embed{position:relative;max-width:100%;height:0;overflow:hidden;background:#dcddde;padding-bottom:56.25%}.ui.embed embed,.ui.embed iframe,.ui.embed object{position:absolute;border:none;width:100%;height:100%;top:0;left:0;margin:0;padding:0}.ui.embed>.embed{display:none}.ui.embed>.placeholder{position:absolute;cursor:pointer;top:0;left:0;display:block;width:100%;height:100%;background-color:radial-gradient(transparent 45%,rgba(0,0,0,.3))}.ui.embed>.icon{cursor:pointer;position:absolute;top:0;left:0;width:100%;height:100%;z-index:2}.ui.embed>.icon:after{position:absolute;top:0;left:0;width:100%;height:100%;z-index:3;content:'';background:-webkit-radial-gradient(transparent 45%,rgba(0,0,0,.3));background:radial-gradient(transparent 45%,rgba(0,0,0,.3));opacity:.5;-webkit-transition:opacity .5s ease;transition:opacity .5s ease}.ui.embed>.icon:before{position:absolute;top:50%;left:50%;z-index:4;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);color:#fff;font-size:6rem;text-shadow:0 2px 10px rgba(34,36,38,.2);-webkit-transition:opacity .5s ease,color .5s ease;transition:opacity .5s ease,color .5s ease;z-index:10}.ui.embed .icon:hover:after{background:-webkit-radial-gradient(transparent 45%,rgba(0,0,0,.3));background:radial-gradient(transparent 45%,rgba(0,0,0,.3));opacity:1}.ui.embed .icon:hover:before{color:#fff}.ui.active.embed>.icon,.ui.active.embed>.placeholder{display:none}.ui.active.embed>.embed{display:block}.ui.square.embed{padding-bottom:100%}.ui[class*="4:3"].embed{padding-bottom:75%}.ui[class*="16:9"].embed{padding-bottom:56.25%}.ui[class*="21:9"].embed{padding-bottom:42.85714286%} -------------------------------------------------------------------------------- /app/static/semantic/components/container.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Container 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.container{display:block;max-width:100%!important}@media only screen and (max-width:767px){.ui.container{width:auto!important;margin-left:1em!important;margin-right:1em!important}.ui.grid.container{width:auto!important}.ui.relaxed.grid.container{width:auto!important}.ui.very.relaxed.grid.container{width:auto!important}}@media only screen and (min-width:768px) and (max-width:991px){.ui.container{width:723px;margin-left:auto!important;margin-right:auto!important}.ui.grid.container{width:calc(723px + 2rem)!important}.ui.relaxed.grid.container{width:calc(723px + 3rem)!important}.ui.very.relaxed.grid.container{width:calc(723px + 5rem)!important}}@media only screen and (min-width:992px) and (max-width:1199px){.ui.container{width:933px;margin-left:auto!important;margin-right:auto!important}.ui.grid.container{width:calc(933px + 2rem)!important}.ui.relaxed.grid.container{width:calc(933px + 3rem)!important}.ui.very.relaxed.grid.container{width:calc(933px + 5rem)!important}}@media only screen and (min-width:1200px){.ui.container{width:1127px;margin-left:auto!important;margin-right:auto!important}.ui.grid.container{width:calc(1127px + 2rem)!important}.ui.relaxed.grid.container{width:calc(1127px + 3rem)!important}.ui.very.relaxed.grid.container{width:calc(1127px + 5rem)!important}}.ui.text.container{font-family:Lato,'Helvetica Neue',Arial,Helvetica,sans-serif;max-width:700px!important;line-height:1.5}.ui.text.container{font-size:1.14285714rem}.ui.fluid.container{width:100%}.ui[class*="left aligned"].container{text-align:left}.ui[class*="center aligned"].container{text-align:center}.ui[class*="right aligned"].container{text-align:right}.ui.justified.container{text-align:justify;-webkit-hyphens:auto;-ms-hyphens:auto;hyphens:auto} -------------------------------------------------------------------------------- /app/static/semantic/components/ad.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Ad 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Copyright 2013 Contributors 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */.ui.ad{display:block;overflow:hidden;margin:1em 0}.ui.ad:first-child{margin:0}.ui.ad:last-child{margin:0}.ui.ad iframe{margin:0;padding:0;border:none;overflow:hidden}.ui.leaderboard.ad{width:728px;height:90px}.ui[class*="medium rectangle"].ad{width:300px;height:250px}.ui[class*="large rectangle"].ad{width:336px;height:280px}.ui[class*="half page"].ad{width:300px;height:600px}.ui.square.ad{width:250px;height:250px}.ui[class*="small square"].ad{width:200px;height:200px}.ui[class*="small rectangle"].ad{width:180px;height:150px}.ui[class*="vertical rectangle"].ad{width:240px;height:400px}.ui.button.ad{width:120px;height:90px}.ui[class*="square button"].ad{width:125px;height:125px}.ui[class*="small button"].ad{width:120px;height:60px}.ui.skyscraper.ad{width:120px;height:600px}.ui[class*="wide skyscraper"].ad{width:160px}.ui.banner.ad{width:468px;height:60px}.ui[class*="vertical banner"].ad{width:120px;height:240px}.ui[class*="top banner"].ad{width:930px;height:180px}.ui[class*="half banner"].ad{width:234px;height:60px}.ui[class*="large leaderboard"].ad{width:970px;height:90px}.ui.billboard.ad{width:970px;height:250px}.ui.panorama.ad{width:980px;height:120px}.ui.netboard.ad{width:580px;height:400px}.ui[class*="large mobile banner"].ad{width:320px;height:100px}.ui[class*="mobile leaderboard"].ad{width:320px;height:50px}.ui.mobile.ad{display:none}@media only screen and (max-width:767px){.ui.mobile.ad{display:block}}.ui.centered.ad{margin-left:auto;margin-right:auto}.ui.test.ad{position:relative;background:#545454}.ui.test.ad:after{position:absolute;top:50%;left:50%;width:100%;text-align:center;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%);content:'Ad';color:#fff;font-size:1em;font-weight:700}.ui.mobile.test.ad:after{font-size:.85714286em}.ui.test.ad[data-text]:after{content:attr(data-text)} -------------------------------------------------------------------------------- /app/static/semantic/components/tab.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Tab 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | UI Tabs 14 | *******************************/ 15 | 16 | .ui.tab { 17 | display: none; 18 | } 19 | 20 | 21 | /******************************* 22 | States 23 | *******************************/ 24 | 25 | 26 | /*-------------------- 27 | Active 28 | ---------------------*/ 29 | 30 | .ui.tab.active, 31 | .ui.tab.open { 32 | display: block; 33 | } 34 | 35 | /*-------------------- 36 | Loading 37 | ---------------------*/ 38 | 39 | .ui.tab.loading { 40 | position: relative; 41 | overflow: hidden; 42 | display: block; 43 | min-height: 250px; 44 | } 45 | .ui.tab.loading * { 46 | position: relative !important; 47 | left: -10000px !important; 48 | } 49 | .ui.tab.loading:before, 50 | .ui.tab.loading.segment:before { 51 | position: absolute; 52 | content: ''; 53 | top: 100px; 54 | left: 50%; 55 | margin: -1.25em 0em 0em -1.25em; 56 | width: 2.5em; 57 | height: 2.5em; 58 | border-radius: 500rem; 59 | border: 0.2em solid rgba(0, 0, 0, 0.1); 60 | } 61 | .ui.tab.loading:after, 62 | .ui.tab.loading.segment:after { 63 | position: absolute; 64 | content: ''; 65 | top: 100px; 66 | left: 50%; 67 | margin: -1.25em 0em 0em -1.25em; 68 | width: 2.5em; 69 | height: 2.5em; 70 | -webkit-animation: button-spin 0.6s linear; 71 | animation: button-spin 0.6s linear; 72 | -webkit-animation-iteration-count: infinite; 73 | animation-iteration-count: infinite; 74 | border-radius: 500rem; 75 | border-color: #767676 transparent transparent; 76 | border-style: solid; 77 | border-width: 0.2em; 78 | -webkit-box-shadow: 0px 0px 0px 1px transparent; 79 | box-shadow: 0px 0px 0px 1px transparent; 80 | } 81 | 82 | 83 | /******************************* 84 | Tab Overrides 85 | *******************************/ 86 | 87 | 88 | 89 | /******************************* 90 | User Overrides 91 | *******************************/ 92 | 93 | -------------------------------------------------------------------------------- /app/static/semantic/components/site.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Site 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */@import url(https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin);body,html{height:100%}html{font-size:14px}body{margin:0;padding:0;overflow-x:hidden;min-width:320px;background:#fff;font-family:Lato,'Helvetica Neue',Arial,Helvetica,sans-serif;font-size:14px;line-height:1.4285em;color:rgba(0,0,0,.87);font-smoothing:antialiased}h1,h2,h3,h4,h5{font-family:Lato,'Helvetica Neue',Arial,Helvetica,sans-serif;line-height:1.28571429em;margin:calc(2rem - .14285714em) 0 1rem;font-weight:700;padding:0}h1{min-height:1rem;font-size:2rem}h2{font-size:1.71428571rem}h3{font-size:1.28571429rem}h4{font-size:1.07142857rem}h5{font-size:1rem}h1:first-child,h2:first-child,h3:first-child,h4:first-child,h5:first-child{margin-top:0}h1:last-child,h2:last-child,h3:last-child,h4:last-child,h5:last-child{margin-bottom:0}p{margin:0 0 1em;line-height:1.4285em}p:first-child{margin-top:0}p:last-child{margin-bottom:0}a{color:#4183c4;text-decoration:none}a:hover{color:#1e70bf;text-decoration:none}::-webkit-selection{background-color:#cce2ff;color:rgba(0,0,0,.87)}::-moz-selection{background-color:#cce2ff;color:rgba(0,0,0,.87)}::selection{background-color:#cce2ff;color:rgba(0,0,0,.87)}input::-webkit-selection,textarea::-webkit-selection{background-color:rgba(100,100,100,.4);color:rgba(0,0,0,.87)}input::-moz-selection,textarea::-moz-selection{background-color:rgba(100,100,100,.4);color:rgba(0,0,0,.87)}input::selection,textarea::selection{background-color:rgba(100,100,100,.4);color:rgba(0,0,0,.87)}body ::-webkit-scrollbar{-webkit-appearance:none;width:10px;height:10px}body ::-webkit-scrollbar-track{background:rgba(0,0,0,.1);border-radius:0}body ::-webkit-scrollbar-thumb{cursor:pointer;border-radius:5px;background:rgba(0,0,0,.25);-webkit-transition:color .2s ease;transition:color .2s ease}body ::-webkit-scrollbar-thumb:window-inactive{background:rgba(0,0,0,.15)}body ::-webkit-scrollbar-thumb:hover{background:rgba(128,135,139,.8)}body .ui.inverted::-webkit-scrollbar-track{background:rgba(255,255,255,.1)}body .ui.inverted::-webkit-scrollbar-thumb{background:rgba(255,255,255,.25)}body .ui.inverted::-webkit-scrollbar-thumb:window-inactive{background:rgba(255,255,255,.15)}body .ui.inverted::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.35)} -------------------------------------------------------------------------------- /app/static/semantic/components/shape.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Shape 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.shape{position:relative;vertical-align:top;display:inline-block;-webkit-perspective:2000px;perspective:2000px;-webkit-transition:left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out;transition:left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out,left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out;transition:transform .6s ease-in-out,left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out}.ui.shape .sides{-webkit-transform-style:preserve-3d;transform-style:preserve-3d}.ui.shape .side{opacity:1;width:100%;margin:0!important;-webkit-backface-visibility:hidden;backface-visibility:hidden}.ui.shape .side{display:none}.ui.shape .side *{-webkit-backface-visibility:visible!important;backface-visibility:visible!important}.ui.cube.shape .side{min-width:15em;height:15em;padding:2em;background-color:#e6e6e6;color:rgba(0,0,0,.87);-webkit-box-shadow:0 0 2px rgba(0,0,0,.3);box-shadow:0 0 2px rgba(0,0,0,.3)}.ui.cube.shape .side>.content{width:100%;height:100%;display:table;text-align:center;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.ui.cube.shape .side>.content>div{display:table-cell;vertical-align:middle;font-size:2em}.ui.text.shape.animating .sides{position:static}.ui.text.shape .side{white-space:nowrap}.ui.text.shape .side>*{white-space:normal}.ui.loading.shape{position:absolute;top:-9999px;left:-9999px}.ui.shape .animating.side{position:absolute;top:0;left:0;display:block;z-index:100}.ui.shape .hidden.side{opacity:.6}.ui.shape.animating .sides{position:absolute}.ui.shape.animating .sides{-webkit-transition:left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out;transition:left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out;transition:transform .6s ease-in-out,left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out;transition:transform .6s ease-in-out,left .6s ease-in-out,width .6s ease-in-out,height .6s ease-in-out,-webkit-transform .6s ease-in-out}.ui.shape.animating .side{-webkit-transition:opacity .6s ease-in-out;transition:opacity .6s ease-in-out}.ui.shape .active.side{display:block} -------------------------------------------------------------------------------- /app/static/css/style.css: -------------------------------------------------------------------------------- 1 | /* app/static/css/style.css */ 2 | 3 | body, html { 4 | width: 100%; 5 | height: 100%; 6 | font-family: 'Mandali';font-size: 22px; 7 | 8 | } 9 | 10 | 11 | a, .navbar-default .navbar-brand, .navbar-default .navbar-nav>li>a { 12 | color: #aec251; 13 | } 14 | 15 | a:hover, .navbar-default .navbar-brand:hover, .navbar-default .navbar-nav>li>a:hover { 16 | color: #687430; 17 | } 18 | 19 | footer { 20 | padding: 50px 0; 21 | background-color: #f8f8f8; 22 | } 23 | 24 | p.copyright { 25 | margin: 15px 0 0; 26 | } 27 | 28 | .alert-info { 29 | width: 50%; 30 | margin: auto; 31 | color: #687430; 32 | background-color: #e6ecca; 33 | border-color: #aec251; 34 | } 35 | 36 | .btn-default { 37 | border-color: #aec251; 38 | color: #aec251; 39 | } 40 | 41 | .btn-default:hover { 42 | background-color: #aec251; 43 | } 44 | 45 | .center { 46 | margin: auto; 47 | padding: 10px; 48 | } 49 | 50 | .content-section { 51 | padding: 50px 0; 52 | border-top: 1px solid #e7e7e7; 53 | } 54 | 55 | .footer, .push { 56 | clear: both; 57 | height: 4em; 58 | } 59 | 60 | .intro-divider { 61 | width: 400px; 62 | border-top: 1px solid #f8f8f8; 63 | border-bottom: 1px solid rgba(0,0,0,0.2); 64 | } 65 | 66 | .intro-header { 67 | padding-top: 50px; 68 | padding-bottom: 50px; 69 | text-align: center; 70 | color: #f8f8f8; 71 | background: url(../img/intro-bg.jpg) no-repeat center center; 72 | background-size: cover; 73 | height: 100%; 74 | } 75 | 76 | .intro-message { 77 | position: relative; 78 | padding-top: 20%; 79 | padding-bottom: 20%; 80 | } 81 | 82 | .intro-message > h1 { 83 | margin: 0; 84 | text-shadow: 2px 2px 3px rgba(0,0,0,0.6); 85 | font-size: 5em; 86 | } 87 | 88 | .intro-message > h3 { 89 | text-shadow: 2px 2px 3px rgba(0,0,0,0.6); 90 | } 91 | 92 | .lead { 93 | font-size: 18px; 94 | font-weight: 400; 95 | } 96 | 97 | .topnav { 98 | font-size: 14px; 99 | } 100 | 101 | .wrapper { 102 | min-height: 100%; 103 | height: auto !important; 104 | height: 100%; 105 | margin: 0 auto -4em; 106 | } 107 | 108 | 109 | .outer { 110 | display: table; 111 | position: absolute; 112 | height: 70%; 113 | width: 100%; 114 | } 115 | 116 | .middle { 117 | display: table-cell; 118 | vertical-align: middle; 119 | } 120 | 121 | .inner { 122 | margin-left: auto; 123 | margin-right: auto; 124 | } -------------------------------------------------------------------------------- /app/auth/views.py: -------------------------------------------------------------------------------- 1 | # app/auth/views.py 2 | 3 | from flask import flash, redirect, render_template, url_for 4 | from flask_login import login_required, login_user, logout_user 5 | 6 | from . import auth 7 | from .forms import LoginForm, RegistrationForm 8 | from .. import db 9 | from ..models import Employee 10 | 11 | @auth.route('/register', methods=['GET', 'POST']) 12 | def register(): 13 | """ 14 | Handle requests to the /register route 15 | Add an employee to the database through the registration form 16 | """ 17 | form = RegistrationForm() 18 | 19 | if form.validate_on_submit(): 20 | employee = Employee(email=form.email.data, 21 | first_name=form.first_name.data, 22 | last_name=form.last_name.data, 23 | password=form.password.data, 24 | user_type=form.user_type.data) 25 | 26 | # add employee to the database 27 | db.session.add(employee) 28 | db.session.commit() 29 | flash('You have successfully registered! You may now login.', 'success') 30 | 31 | # redirect to the login page 32 | return redirect(url_for('auth.login')) 33 | 34 | # load registration template 35 | return render_template('auth/register.html', form=form, title='Register') 36 | 37 | @auth.route('/login', methods=['GET', 'POST']) 38 | def login(): 39 | form = LoginForm() 40 | if form.validate_on_submit(): 41 | 42 | # check whether employee exists in the database and whether 43 | # the password entered matches the password in the database 44 | employee = Employee.query.filter_by(email=form.email.data).first() 45 | if employee is not None and employee.verify_password( 46 | form.password.data): 47 | # log employee in 48 | login_user(employee) 49 | 50 | # redirect to the appropriate dashboard page 51 | if employee.is_admin: 52 | return redirect(url_for('home.admin_dashboard')) 53 | else: 54 | return redirect(url_for('home.dashboard')) 55 | 56 | # when login details are incorrect 57 | else: 58 | flash('Invalid email or password', 'error') 59 | 60 | # load login template 61 | return render_template('auth/login.html', form=form, title='Login') 62 | 63 | @auth.route('/logout') 64 | @login_required 65 | def logout(): 66 | """ 67 | Handle requests to the /logout route 68 | Log an employee out through the logout link 69 | """ 70 | logout_user() 71 | flash('You have successfully been logged out.') 72 | 73 | # redirect to the login page 74 | return redirect(url_for('auth.login')) -------------------------------------------------------------------------------- /app/static/semantic/components/breadcrumb.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Breadcrumb 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Breadcrumb 14 | *******************************/ 15 | 16 | .ui.breadcrumb { 17 | line-height: 1; 18 | display: inline-block; 19 | margin: 0em 0em; 20 | vertical-align: middle; 21 | } 22 | .ui.breadcrumb:first-child { 23 | margin-top: 0em; 24 | } 25 | .ui.breadcrumb:last-child { 26 | margin-bottom: 0em; 27 | } 28 | 29 | 30 | /******************************* 31 | Content 32 | *******************************/ 33 | 34 | 35 | /* Divider */ 36 | .ui.breadcrumb .divider { 37 | display: inline-block; 38 | opacity: 0.7; 39 | margin: 0em 0.21428571rem 0em; 40 | font-size: 0.92857143em; 41 | color: rgba(0, 0, 0, 0.4); 42 | vertical-align: baseline; 43 | } 44 | 45 | /* Link */ 46 | .ui.breadcrumb a { 47 | color: #4183C4; 48 | } 49 | .ui.breadcrumb a:hover { 50 | color: #1e70bf; 51 | } 52 | 53 | /* Icon Divider */ 54 | .ui.breadcrumb .icon.divider { 55 | font-size: 0.85714286em; 56 | vertical-align: baseline; 57 | } 58 | 59 | /* Section */ 60 | .ui.breadcrumb a.section { 61 | cursor: pointer; 62 | } 63 | .ui.breadcrumb .section { 64 | display: inline-block; 65 | margin: 0em; 66 | padding: 0em; 67 | } 68 | 69 | /* Loose Coupling */ 70 | .ui.breadcrumb.segment { 71 | display: inline-block; 72 | padding: 0.78571429em 1em; 73 | } 74 | 75 | 76 | /******************************* 77 | States 78 | *******************************/ 79 | 80 | .ui.breadcrumb .active.section { 81 | font-weight: bold; 82 | } 83 | 84 | 85 | /******************************* 86 | Variations 87 | *******************************/ 88 | 89 | .ui.mini.breadcrumb { 90 | font-size: 0.78571429rem; 91 | } 92 | .ui.tiny.breadcrumb { 93 | font-size: 0.85714286rem; 94 | } 95 | .ui.small.breadcrumb { 96 | font-size: 0.92857143rem; 97 | } 98 | .ui.breadcrumb { 99 | font-size: 1rem; 100 | } 101 | .ui.large.breadcrumb { 102 | font-size: 1.14285714rem; 103 | } 104 | .ui.big.breadcrumb { 105 | font-size: 1.28571429rem; 106 | } 107 | .ui.huge.breadcrumb { 108 | font-size: 1.42857143rem; 109 | } 110 | .ui.massive.breadcrumb { 111 | font-size: 1.71428571rem; 112 | } 113 | 114 | 115 | /******************************* 116 | Theme Overrides 117 | *******************************/ 118 | 119 | 120 | 121 | /******************************* 122 | Site Overrides 123 | *******************************/ 124 | 125 | -------------------------------------------------------------------------------- /app/models.py: -------------------------------------------------------------------------------- 1 | from flask_login import UserMixin 2 | from werkzeug.security import generate_password_hash, check_password_hash 3 | 4 | from app import db, login_manager 5 | 6 | class Employee(UserMixin, db.Model): 7 | """ 8 | Create an Employee table 9 | """ 10 | 11 | # Ensures table will be named in plural and not in singular 12 | # as is the name of the model 13 | __tablename__ = 'employees' 14 | 15 | id = db.Column(db.Integer, primary_key=True) 16 | email = db.Column(db.String(60), index=True, unique=True) 17 | first_name = db.Column(db.String(60), index=True) 18 | last_name = db.Column(db.String(60), index=True) 19 | password_hash = db.Column(db.String(128)) 20 | user_type = db.Column(db.String(20)) 21 | department_id = db.Column(db.Integer, db.ForeignKey('departments.id')) 22 | role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) 23 | is_admin = db.Column(db.Boolean, default=False) 24 | 25 | @property 26 | def password(self): 27 | """ 28 | Prevent pasword from being accessed 29 | """ 30 | raise AttributeError('password is not a readable attribute.') 31 | 32 | @password.setter 33 | def password(self, password): 34 | """ 35 | Set password to a hashed password 36 | """ 37 | self.password_hash = generate_password_hash(password) 38 | 39 | def verify_password(self, password): 40 | """ 41 | Check if hashed password matches actual password 42 | """ 43 | return check_password_hash(self.password_hash, password) 44 | 45 | def __repr__(self): 46 | return ''.format(self.username) 47 | 48 | # Set up user_loader 49 | @login_manager.user_loader 50 | def load_user(user_id): 51 | return Employee.query.get(int(user_id)) 52 | 53 | class Department(db.Model): 54 | """ 55 | Create a Department table 56 | """ 57 | 58 | __tablename__ = 'departments' 59 | 60 | id = db.Column(db.Integer, primary_key=True) 61 | name = db.Column(db.String(60), unique=True) 62 | description = db.Column(db.String(200)) 63 | employees = db.relationship('Employee', backref='department', 64 | lazy='dynamic') 65 | 66 | def __repr__(self): 67 | return ''.format(self.name) 68 | 69 | class Role(db.Model): 70 | """ 71 | Create a Role table 72 | """ 73 | 74 | __tablename__ = 'roles' 75 | 76 | id = db.Column(db.Integer, primary_key=True) 77 | name = db.Column(db.String(60), unique=True) 78 | description = db.Column(db.String(200)) 79 | employees = db.relationship('Employee', backref='role', 80 | lazy='dynamic') 81 | 82 | def __repr__(self): 83 | return ''.format(self.name) -------------------------------------------------------------------------------- /app/static/semantic/components/reset.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Reset 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */*,:after,:before{-webkit-box-sizing:inherit;box-sizing:inherit}html{-webkit-box-sizing:border-box;box-sizing:border-box}input[type=email],input[type=password],input[type=search],input[type=text]{-webkit-appearance:none;-moz-appearance:none}/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none} -------------------------------------------------------------------------------- /migrations/versions/a34b0520b5b3_.py: -------------------------------------------------------------------------------- 1 | """empty message 2 | 3 | Revision ID: a34b0520b5b3 4 | Revises: 5 | Create Date: 2018-02-18 10:39:47.414711 6 | 7 | """ 8 | from alembic import op 9 | import sqlalchemy as sa 10 | 11 | 12 | # revision identifiers, used by Alembic. 13 | revision = 'a34b0520b5b3' 14 | down_revision = None 15 | branch_labels = None 16 | depends_on = None 17 | 18 | 19 | def upgrade(): 20 | # ### commands auto generated by Alembic - please adjust! ### 21 | op.create_table('departments', 22 | sa.Column('id', sa.Integer(), nullable=False), 23 | sa.Column('name', sa.String(length=60), nullable=True), 24 | sa.Column('description', sa.String(length=200), nullable=True), 25 | sa.PrimaryKeyConstraint('id'), 26 | sa.UniqueConstraint('name') 27 | ) 28 | op.create_table('roles', 29 | sa.Column('id', sa.Integer(), nullable=False), 30 | sa.Column('name', sa.String(length=60), nullable=True), 31 | sa.Column('description', sa.String(length=200), nullable=True), 32 | sa.PrimaryKeyConstraint('id'), 33 | sa.UniqueConstraint('name') 34 | ) 35 | op.create_table('employees', 36 | sa.Column('id', sa.Integer(), nullable=False), 37 | sa.Column('email', sa.String(length=60), nullable=True), 38 | sa.Column('username', sa.String(length=60), nullable=True), 39 | sa.Column('first_name', sa.String(length=60), nullable=True), 40 | sa.Column('last_name', sa.String(length=60), nullable=True), 41 | sa.Column('password_hash', sa.String(length=128), nullable=True), 42 | sa.Column('department_id', sa.Integer(), nullable=True), 43 | sa.Column('role_id', sa.Integer(), nullable=True), 44 | sa.Column('is_admin', sa.Boolean(), nullable=True), 45 | sa.ForeignKeyConstraint(['department_id'], ['departments.id'], ), 46 | sa.ForeignKeyConstraint(['role_id'], ['roles.id'], ), 47 | sa.PrimaryKeyConstraint('id') 48 | ) 49 | op.create_index(op.f('ix_employees_email'), 'employees', ['email'], unique=True) 50 | op.create_index(op.f('ix_employees_first_name'), 'employees', ['first_name'], unique=False) 51 | op.create_index(op.f('ix_employees_last_name'), 'employees', ['last_name'], unique=False) 52 | op.create_index(op.f('ix_employees_username'), 'employees', ['username'], unique=True) 53 | # ### end Alembic commands ### 54 | 55 | 56 | def downgrade(): 57 | # ### commands auto generated by Alembic - please adjust! ### 58 | op.drop_index(op.f('ix_employees_username'), table_name='employees') 59 | op.drop_index(op.f('ix_employees_last_name'), table_name='employees') 60 | op.drop_index(op.f('ix_employees_first_name'), table_name='employees') 61 | op.drop_index(op.f('ix_employees_email'), table_name='employees') 62 | op.drop_table('employees') 63 | op.drop_table('roles') 64 | op.drop_table('departments') 65 | # ### end Alembic commands ### 66 | -------------------------------------------------------------------------------- /app/static/semantic/components/video.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.0.0 - Video 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Copyright 2014 Contributors 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */ 11 | 12 | 13 | /******************************* 14 | Video 15 | *******************************/ 16 | 17 | .ui.video { 18 | background-color: #dddddd; 19 | position: relative; 20 | max-width: 100%; 21 | padding-bottom: 56.25%; 22 | height: 0px; 23 | overflow: hidden; 24 | } 25 | 26 | /*-------------- 27 | Content 28 | ---------------*/ 29 | 30 | 31 | /* Placeholder Image */ 32 | .ui.video .placeholder { 33 | background-color: #333333; 34 | } 35 | 36 | /* Play Icon Overlay */ 37 | .ui.video .play { 38 | cursor: pointer; 39 | position: absolute; 40 | top: 0px; 41 | left: 0px; 42 | z-index: 10; 43 | width: 100%; 44 | height: 100%; 45 | background: transparent; 46 | -webkit-transition: background 0.2s ease; 47 | transition: background 0.2s ease; 48 | } 49 | .ui.video .play.icon:before { 50 | position: absolute; 51 | top: 50%; 52 | left: 50%; 53 | z-index: 11; 54 | -webkit-transform: translateX(-50%) translateY(-50%); 55 | -ms-transform: translateX(-50%) translateY(-50%); 56 | transform: translateX(-50%) translateY(-50%); 57 | color: rgba(255, 255, 255, 0.7); 58 | font-size: 7rem; 59 | text-shadow: 2px 2px 0px rgba(0, 0, 0, 0.15); 60 | -webkit-transition: color 0.2s ease; 61 | transition: color 0.2s ease; 62 | } 63 | .ui.video .placeholder { 64 | position: absolute; 65 | top: 0px; 66 | left: 0px; 67 | display: block; 68 | width: 100%; 69 | height: 100%; 70 | } 71 | 72 | /* IFrame Embed */ 73 | .ui.video .embed iframe, 74 | .ui.video .embed embed, 75 | .ui.video .embed object { 76 | position: absolute; 77 | border: none; 78 | width: 100%; 79 | height: 100%; 80 | top: 0px; 81 | left: 0px; 82 | margin: 0em; 83 | padding: 0em; 84 | } 85 | 86 | 87 | /******************************* 88 | States 89 | *******************************/ 90 | 91 | 92 | /*-------------- 93 | Hover 94 | ---------------*/ 95 | 96 | .ui.video .play:hover { 97 | background: rgba(0, 0, 0, 0); 98 | } 99 | .ui.video .play:hover:before { 100 | color: #ffffff; 101 | } 102 | 103 | /*-------------- 104 | Active 105 | ---------------*/ 106 | 107 | .ui.active.video .play, 108 | .ui.active.video .placeholder { 109 | display: none; 110 | } 111 | .ui.active.video .embed { 112 | display: inline; 113 | } 114 | 115 | 116 | /******************************* 117 | Video Overrides 118 | *******************************/ 119 | 120 | 121 | 122 | /******************************* 123 | Site Overrides 124 | *******************************/ 125 | 126 | -------------------------------------------------------------------------------- /app/static/semantic/components/comment.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Comment 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.comments{margin:1.5em 0;max-width:650px}.ui.comments:first-child{margin-top:0}.ui.comments:last-child{margin-bottom:0}.ui.comments .comment{position:relative;background:0 0;margin:.5em 0 0;padding:.5em 0 0;border:none;border-top:none;line-height:1.2}.ui.comments .comment:first-child{margin-top:0;padding-top:0}.ui.comments .comment .comments{margin:0 0 .5em .5em;padding:1em 0 1em 1em}.ui.comments .comment .comments:before{position:absolute;top:0;left:0}.ui.comments .comment .comments .comment{border:none;border-top:none;background:0 0}.ui.comments .comment .avatar{display:block;width:2.5em;height:auto;float:left;margin:.2em 0 0}.ui.comments .comment .avatar img,.ui.comments .comment img.avatar{display:block;margin:0 auto;width:100%;height:100%;border-radius:.25rem}.ui.comments .comment>.content{display:block}.ui.comments .comment>.avatar~.content{margin-left:3.5em}.ui.comments .comment .author{font-size:1em;color:rgba(0,0,0,.87);font-weight:700}.ui.comments .comment a.author{cursor:pointer}.ui.comments .comment a.author:hover{color:#1e70bf}.ui.comments .comment .metadata{display:inline-block;margin-left:.5em;color:rgba(0,0,0,.4);font-size:.875em}.ui.comments .comment .metadata>*{display:inline-block;margin:0 .5em 0 0}.ui.comments .comment .metadata>:last-child{margin-right:0}.ui.comments .comment .text{margin:.25em 0 .5em;font-size:1em;word-wrap:break-word;color:rgba(0,0,0,.87);line-height:1.3}.ui.comments .comment .actions{font-size:.875em}.ui.comments .comment .actions a{cursor:pointer;display:inline-block;margin:0 .75em 0 0;color:rgba(0,0,0,.4)}.ui.comments .comment .actions a:last-child{margin-right:0}.ui.comments .comment .actions a.active,.ui.comments .comment .actions a:hover{color:rgba(0,0,0,.8)}.ui.comments>.reply.form{margin-top:1em}.ui.comments .comment .reply.form{width:100%;margin-top:1em}.ui.comments .reply.form textarea{font-size:1em;height:12em}.ui.collapsed.comments,.ui.comments .collapsed.comment,.ui.comments .collapsed.comments{display:none}.ui.threaded.comments .comment .comments{margin:-1.5em 0 -1em 1.25em;padding:3em 0 2em 2.25em;-webkit-box-shadow:-1px 0 0 rgba(34,36,38,.15);box-shadow:-1px 0 0 rgba(34,36,38,.15)}.ui.minimal.comments .comment .actions{opacity:0;position:absolute;top:0;right:0;left:auto;-webkit-transition:opacity .2s ease;transition:opacity .2s ease;-webkit-transition-delay:.1s;transition-delay:.1s}.ui.minimal.comments .comment>.content:hover>.actions{opacity:1}.ui.mini.comments{font-size:.78571429rem}.ui.tiny.comments{font-size:.85714286rem}.ui.small.comments{font-size:.92857143rem}.ui.comments{font-size:1rem}.ui.large.comments{font-size:1.14285714rem}.ui.big.comments{font-size:1.28571429rem}.ui.huge.comments{font-size:1.42857143rem}.ui.massive.comments{font-size:1.71428571rem} -------------------------------------------------------------------------------- /app/static/semantic/components/dimmer.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Dimmer 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.dimmable:not(body){position:relative}.ui.dimmer{display:none;position:absolute;top:0!important;left:0!important;width:100%;height:100%;text-align:center;vertical-align:middle;background-color:rgba(0,0,0,.85);opacity:0;line-height:1;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.5s;animation-duration:.5s;-webkit-transition:background-color .5s linear;transition:background-color .5s linear;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;will-change:opacity;z-index:1000}.ui.dimmer>.content{width:100%;height:100%;display:table;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text}.ui.dimmer>.content>*{display:table-cell;vertical-align:middle;color:#fff}.ui.segment>.ui.dimmer{border-radius:inherit!important}.ui.dimmer:not(.inverted)::-webkit-scrollbar-track{background:rgba(255,255,255,.1)}.ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb{background:rgba(255,255,255,.25)}.ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb:window-inactive{background:rgba(255,255,255,.15)}.ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb:hover{background:rgba(255,255,255,.35)}.animating.dimmable:not(body),.dimmed.dimmable:not(body){overflow:hidden}.dimmed.dimmable>.ui.animating.dimmer,.dimmed.dimmable>.ui.visible.dimmer,.ui.active.dimmer{display:block;opacity:1}.ui.disabled.dimmer{width:0!important;height:0!important}.ui.page.dimmer{position:fixed;-webkit-transform-style:'';transform-style:'';-webkit-perspective:2000px;perspective:2000px;-webkit-transform-origin:center center;transform-origin:center center}body.animating.in.dimmable,body.dimmed.dimmable{overflow:hidden}body.dimmable>.dimmer{position:fixed}.blurring.dimmable>:not(.dimmer){-webkit-filter:blur(0) grayscale(0);filter:blur(0) grayscale(0);-webkit-transition:.8s -webkit-filter ease;transition:.8s -webkit-filter ease;transition:.8s filter ease;transition:.8s filter ease,.8s -webkit-filter ease}.blurring.dimmed.dimmable>:not(.dimmer){-webkit-filter:blur(5px) grayscale(.7);filter:blur(5px) grayscale(.7)}.blurring.dimmable>.dimmer{background-color:rgba(0,0,0,.6)}.blurring.dimmable>.inverted.dimmer{background-color:rgba(255,255,255,.6)}.ui.dimmer>.top.aligned.content>*{vertical-align:top}.ui.dimmer>.bottom.aligned.content>*{vertical-align:bottom}.ui.inverted.dimmer{background-color:rgba(255,255,255,.85)}.ui.inverted.dimmer>.content>*{color:#fff}.ui.simple.dimmer{display:block;overflow:hidden;opacity:1;width:0%;height:0%;z-index:-100;background-color:rgba(0,0,0,0)}.dimmed.dimmable>.ui.simple.dimmer{overflow:visible;opacity:1;width:100%;height:100%;background-color:rgba(0,0,0,.85);z-index:1}.ui.simple.inverted.dimmer{background-color:rgba(255,255,255,0)}.dimmed.dimmable>.ui.simple.inverted.dimmer{background-color:rgba(255,255,255,.85)} -------------------------------------------------------------------------------- /app/templates/home/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Home{% endblock %} 5 | 6 | {% block head %} 7 | {% endblock %} 8 | 9 | {% block home_body %} 10 |
11 |
12 |
13 |
14 |

We Help Companies and Companions

15 |

We can give your company superpowers to do things that they never thought possible. Let us delight 16 | your customers and empower your needs...through pure data analytics.

17 |

We Make Bananas That Can Dance

18 |

Yes that's right, you thought it was the stuff of dreams, but even bananas can be bioengineered.

19 |
20 |
21 | 22 |
23 |
24 |
25 |
26 | Check Them Out 27 |
28 |
29 |
30 |
31 | 32 | 33 |
34 |
35 |
36 |
37 |

"What a Company"

38 |

That is what they all say about us

39 |
40 |
41 |

"I shouldn't have gone with their competitor."

42 |

43 | Nan Chief Fun Officer Acme 44 | Toys 45 |

46 |
47 |
48 |
49 |
50 | 51 |
52 |
53 |

Breaking The Grid, Grabs Your Attention

54 |

Instead of focusing on content creation and hard work, we have learned how to master the art of doing nothing 55 | by providing massive amounts of whitespace and generic content that can seem massive, monolithic and worth 56 | your attention.

57 | Read More 58 |

59 | Case Studies 60 |

61 |

Did We Tell You About Our Bananas?

62 |

Yes I know you probably disregarded the earlier boasts as non-sequitur filler content, but its really true. 63 | It took years of gene splicing and combinatory DNA research, but our bananas can really dance.

64 | I'm Still Quite Interested 65 |
66 |
67 | 68 | {% endblock %} -------------------------------------------------------------------------------- /migrations/env.py: -------------------------------------------------------------------------------- 1 | from __future__ import with_statement 2 | from alembic import context 3 | from sqlalchemy import engine_from_config, pool 4 | from logging.config import fileConfig 5 | import logging 6 | 7 | # this is the Alembic Config object, which provides 8 | # access to the values within the .ini file in use. 9 | config = context.config 10 | 11 | # Interpret the config file for Python logging. 12 | # This line sets up loggers basically. 13 | fileConfig(config.config_file_name) 14 | logger = logging.getLogger('alembic.env') 15 | 16 | # add your model's MetaData object here 17 | # for 'autogenerate' support 18 | # from myapp import mymodel 19 | # target_metadata = mymodel.Base.metadata 20 | from flask import current_app 21 | config.set_main_option('sqlalchemy.url', 22 | current_app.config.get('SQLALCHEMY_DATABASE_URI')) 23 | target_metadata = current_app.extensions['migrate'].db.metadata 24 | 25 | # other values from the config, defined by the needs of env.py, 26 | # can be acquired: 27 | # my_important_option = config.get_main_option("my_important_option") 28 | # ... etc. 29 | 30 | 31 | def run_migrations_offline(): 32 | """Run migrations in 'offline' mode. 33 | 34 | This configures the context with just a URL 35 | and not an Engine, though an Engine is acceptable 36 | here as well. By skipping the Engine creation 37 | we don't even need a DBAPI to be available. 38 | 39 | Calls to context.execute() here emit the given string to the 40 | script output. 41 | 42 | """ 43 | url = config.get_main_option("sqlalchemy.url") 44 | context.configure(url=url) 45 | 46 | with context.begin_transaction(): 47 | context.run_migrations() 48 | 49 | 50 | def run_migrations_online(): 51 | """Run migrations in 'online' mode. 52 | 53 | In this scenario we need to create an Engine 54 | and associate a connection with the context. 55 | 56 | """ 57 | 58 | # this callback is used to prevent an auto-migration from being generated 59 | # when there are no changes to the schema 60 | # reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html 61 | def process_revision_directives(context, revision, directives): 62 | if getattr(config.cmd_opts, 'autogenerate', False): 63 | script = directives[0] 64 | if script.upgrade_ops.is_empty(): 65 | directives[:] = [] 66 | logger.info('No changes in schema detected.') 67 | 68 | engine = engine_from_config(config.get_section(config.config_ini_section), 69 | prefix='sqlalchemy.', 70 | poolclass=pool.NullPool) 71 | 72 | connection = engine.connect() 73 | context.configure(connection=connection, 74 | target_metadata=target_metadata, 75 | process_revision_directives=process_revision_directives, 76 | **current_app.extensions['migrate'].configure_args) 77 | 78 | try: 79 | with context.begin_transaction(): 80 | context.run_migrations() 81 | finally: 82 | connection.close() 83 | 84 | if context.is_offline_mode(): 85 | run_migrations_offline() 86 | else: 87 | run_migrations_online() 88 | -------------------------------------------------------------------------------- /app/static/semantic/components/colorize.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.0.0 - Colorize 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Copyright 2015 Contributors 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */ 11 | !function(e,n,i,t){"use strict";e.fn.colorize=function(n){var i=e.isPlainObject(n)?e.extend(!0,{},e.fn.colorize.settings,n):e.extend({},e.fn.colorize.settings),o=arguments||!1;return e(this).each(function(n){var a,r,c,s,d,g,u,l,m=e(this),f=e("")[0],h=e("")[0],p=e("")[0],v=new Image,w=i.colors,b=(i.paths,i.namespace),y=i.error,C=m.data("module-"+b);return l={checkPreconditions:function(){return l.debug("Checking pre-conditions"),!e.isPlainObject(w)||e.isEmptyObject(w)?(l.error(y.undefinedColors),!1):!0},async:function(e){i.async?setTimeout(e,0):e()},getMetadata:function(){l.debug("Grabbing metadata"),s=m.data("image")||i.image||t,d=m.data("name")||i.name||n,g=i.width||m.width(),u=i.height||m.height(),(0===g||0===u)&&l.error(y.undefinedSize)},initialize:function(){l.debug("Initializing with colors",w),l.checkPreconditions()&&l.async(function(){l.getMetadata(),l.canvas.create(),l.draw.image(function(){l.draw.colors(),l.canvas.merge()}),m.data("module-"+b,l)})},redraw:function(){l.debug("Redrawing image"),l.async(function(){l.canvas.clear(),l.draw.colors(),l.canvas.merge()})},change:{color:function(e,n){return l.debug("Changing color",e),w[e]===t?(l.error(y.missingColor),!1):(w[e]=n,void l.redraw())}},canvas:{create:function(){l.debug("Creating canvases"),f.width=g,f.height=u,h.width=g,h.height=u,p.width=g,p.height=u,a=f.getContext("2d"),r=h.getContext("2d"),c=p.getContext("2d"),m.append(f),a=m.children("canvas")[0].getContext("2d")},clear:function(e){l.debug("Clearing canvas"),c.fillStyle="#FFFFFF",c.fillRect(0,0,g,u)},merge:function(){return e.isFunction(a.blendOnto)?(a.putImageData(r.getImageData(0,0,g,u),0,0),void c.blendOnto(a,"multiply")):void l.error(y.missingPlugin)}},draw:{image:function(e){l.debug("Drawing image"),e=e||function(){},s?(v.src=s,v.onload=function(){r.drawImage(v,0,0),e()}):(l.error(y.noImage),e())},colors:function(){l.debug("Drawing color overlays",w),e.each(w,function(e,n){i.onDraw(c,d,e,n)})}},debug:function(e,n){i.debug&&(n!==t?console.info(i.name+": "+e,n):console.info(i.name+": "+e))},error:function(e){console.warn(i.name+": "+e)},invoke:function(n,o,a){var r;return a=a||Array.prototype.slice.call(arguments,2),"string"==typeof n&&C!==t&&(n=n.split("."),e.each(n,function(n,t){return e.isPlainObject(C[t])?(C=C[t],!0):e.isFunction(C[t])?(r=C[t],!0):(l.error(i.error.method),!1)})),e.isFunction(r)?r.apply(o,a):!1}},C!==t&&o?("invoke"==o[0]&&(o=Array.prototype.slice.call(o,1)),l.invoke(o[0],this,Array.prototype.slice.call(o,1))):void l.initialize()}),this},e.fn.colorize.settings={name:"Image Colorizer",debug:!0,namespace:"colorize",onDraw:function(e,n,i,t){},async:!0,colors:{},metadata:{image:"image",name:"name"},error:{noImage:"No tracing image specified",undefinedColors:"No default colors specified.",missingColor:"Attempted to change color that does not exist",missingPlugin:"Blend onto plug-in must be included",undefinedHeight:"The width or height of image canvas could not be automatically determined. Please specify a height."}}}(jQuery,window,document); -------------------------------------------------------------------------------- /app/static/semantic/components/rail.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Rail 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Rails 14 | *******************************/ 15 | 16 | .ui.rail { 17 | position: absolute; 18 | top: 0%; 19 | width: 300px; 20 | height: 100%; 21 | } 22 | .ui.left.rail { 23 | left: auto; 24 | right: 100%; 25 | padding: 0em 2rem 0em 0em; 26 | margin: 0em 2rem 0em 0em; 27 | } 28 | .ui.right.rail { 29 | left: 100%; 30 | right: auto; 31 | padding: 0em 0em 0em 2rem; 32 | margin: 0em 0em 0em 2rem; 33 | } 34 | 35 | 36 | /******************************* 37 | Variations 38 | *******************************/ 39 | 40 | 41 | /*-------------- 42 | Internal 43 | ---------------*/ 44 | 45 | .ui.left.internal.rail { 46 | left: 0%; 47 | right: auto; 48 | padding: 0em 0em 0em 2rem; 49 | margin: 0em 0em 0em 2rem; 50 | } 51 | .ui.right.internal.rail { 52 | left: auto; 53 | right: 0%; 54 | padding: 0em 2rem 0em 0em; 55 | margin: 0em 2rem 0em 0em; 56 | } 57 | 58 | /*-------------- 59 | Dividing 60 | ---------------*/ 61 | 62 | .ui.dividing.rail { 63 | width: 302.5px; 64 | } 65 | .ui.left.dividing.rail { 66 | padding: 0em 2.5rem 0em 0em; 67 | margin: 0em 2.5rem 0em 0em; 68 | border-right: 1px solid rgba(34, 36, 38, 0.15); 69 | } 70 | .ui.right.dividing.rail { 71 | border-left: 1px solid rgba(34, 36, 38, 0.15); 72 | padding: 0em 0em 0em 2.5rem; 73 | margin: 0em 0em 0em 2.5rem; 74 | } 75 | 76 | /*-------------- 77 | Distance 78 | ---------------*/ 79 | 80 | .ui.close.rail { 81 | width: calc( 300px + 1em ); 82 | } 83 | .ui.close.left.rail { 84 | padding: 0em 1em 0em 0em; 85 | margin: 0em 1em 0em 0em; 86 | } 87 | .ui.close.right.rail { 88 | padding: 0em 0em 0em 1em; 89 | margin: 0em 0em 0em 1em; 90 | } 91 | .ui.very.close.rail { 92 | width: calc( 300px + 0.5em ); 93 | } 94 | .ui.very.close.left.rail { 95 | padding: 0em 0.5em 0em 0em; 96 | margin: 0em 0.5em 0em 0em; 97 | } 98 | .ui.very.close.right.rail { 99 | padding: 0em 0em 0em 0.5em; 100 | margin: 0em 0em 0em 0.5em; 101 | } 102 | 103 | /*-------------- 104 | Attached 105 | ---------------*/ 106 | 107 | .ui.attached.left.rail, 108 | .ui.attached.right.rail { 109 | padding: 0em; 110 | margin: 0em; 111 | } 112 | 113 | /*-------------- 114 | Sizing 115 | ---------------*/ 116 | 117 | .ui.mini.rail { 118 | font-size: 0.78571429rem; 119 | } 120 | .ui.tiny.rail { 121 | font-size: 0.85714286rem; 122 | } 123 | .ui.small.rail { 124 | font-size: 0.92857143rem; 125 | } 126 | .ui.rail { 127 | font-size: 1rem; 128 | } 129 | .ui.large.rail { 130 | font-size: 1.14285714rem; 131 | } 132 | .ui.big.rail { 133 | font-size: 1.28571429rem; 134 | } 135 | .ui.huge.rail { 136 | font-size: 1.42857143rem; 137 | } 138 | .ui.massive.rail { 139 | font-size: 1.71428571rem; 140 | } 141 | 142 | 143 | /******************************* 144 | Theme Overrides 145 | *******************************/ 146 | 147 | 148 | 149 | /******************************* 150 | Site Overrides 151 | *******************************/ 152 | 153 | -------------------------------------------------------------------------------- /app/templates/admin/employees/employee.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Assign Employee{% endblock %} 5 | 6 | {% block head %} 7 | 8 | 35 | 36 | 44 | 45 | {% endblock %} 46 | {% block body %} 47 | 48 |
49 |
50 |
51 | 52 | {% with messages = get_flashed_messages() %} 53 | {% if messages %} 54 |
    55 | {% for message in messages %} 56 |
  • {{ message }}
  • 57 | {% endfor %} 58 |
59 | {% endif %} 60 | {% endwith %} 61 | 62 |
63 |

65 | Assign departments and roles 66 |

67 |

Select a department and role to assign to 68 | {{ employee.first_name }} {{ employee.last_name }} 69 |

70 |
71 | 72 |
73 |
74 | {{ form.hidden_tag() }} 75 | 76 |
77 |
78 | 79 | {{ form.department(class="ui fluid dropdown", default_text="Please select a department") }} 80 |
81 | 82 |
83 | 84 | {{ form.role(class="ui fluid dropdown", default_text="Please select a role") }} 85 |
86 | 87 | 88 | 92 |
93 |
94 |
95 |
96 | 97 | 98 |
99 |
100 |
101 | 102 | {% endblock %} -------------------------------------------------------------------------------- /app/static/semantic/components/nag.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Nag 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Nag 14 | *******************************/ 15 | 16 | .ui.nag { 17 | display: none; 18 | opacity: 0.95; 19 | position: relative; 20 | top: 0em; 21 | left: 0px; 22 | z-index: 999; 23 | min-height: 0em; 24 | width: 100%; 25 | margin: 0em; 26 | padding: 0.75em 1em; 27 | background: #555555; 28 | -webkit-box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.2); 29 | box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.2); 30 | font-size: 1rem; 31 | text-align: center; 32 | color: rgba(0, 0, 0, 0.87); 33 | border-radius: 0em 0em 0.28571429rem 0.28571429rem; 34 | -webkit-transition: 0.2s background ease; 35 | transition: 0.2s background ease; 36 | } 37 | a.ui.nag { 38 | cursor: pointer; 39 | } 40 | .ui.nag > .title { 41 | display: inline-block; 42 | margin: 0em 0.5em; 43 | color: #FFFFFF; 44 | } 45 | .ui.nag > .close.icon { 46 | cursor: pointer; 47 | opacity: 0.4; 48 | position: absolute; 49 | top: 50%; 50 | right: 1em; 51 | font-size: 1em; 52 | margin: -0.5em 0em 0em; 53 | color: #FFFFFF; 54 | -webkit-transition: opacity 0.2s ease; 55 | transition: opacity 0.2s ease; 56 | } 57 | 58 | 59 | /******************************* 60 | States 61 | *******************************/ 62 | 63 | 64 | /* Hover */ 65 | .ui.nag:hover { 66 | background: #555555; 67 | opacity: 1; 68 | } 69 | .ui.nag .close:hover { 70 | opacity: 1; 71 | } 72 | 73 | 74 | /******************************* 75 | Variations 76 | *******************************/ 77 | 78 | 79 | /*-------------- 80 | Static 81 | ---------------*/ 82 | 83 | .ui.overlay.nag { 84 | position: absolute; 85 | display: block; 86 | } 87 | 88 | /*-------------- 89 | Fixed 90 | ---------------*/ 91 | 92 | .ui.fixed.nag { 93 | position: fixed; 94 | } 95 | 96 | /*-------------- 97 | Bottom 98 | ---------------*/ 99 | 100 | .ui.bottom.nags, 101 | .ui.bottom.nag { 102 | border-radius: 0.28571429rem 0.28571429rem 0em 0em; 103 | top: auto; 104 | bottom: 0em; 105 | } 106 | 107 | /*-------------- 108 | White 109 | ---------------*/ 110 | 111 | .ui.inverted.nags .nag, 112 | .ui.inverted.nag { 113 | background-color: #F3F4F5; 114 | color: rgba(0, 0, 0, 0.85); 115 | } 116 | .ui.inverted.nags .nag .close, 117 | .ui.inverted.nags .nag .title, 118 | .ui.inverted.nag .close, 119 | .ui.inverted.nag .title { 120 | color: rgba(0, 0, 0, 0.4); 121 | } 122 | 123 | 124 | /******************************* 125 | Groups 126 | *******************************/ 127 | 128 | .ui.nags .nag { 129 | border-radius: 0em !important; 130 | } 131 | .ui.nags .nag:last-child { 132 | border-radius: 0em 0em 0.28571429rem 0.28571429rem; 133 | } 134 | .ui.bottom.nags .nag:last-child { 135 | border-radius: 0.28571429rem 0.28571429rem 0em 0em; 136 | } 137 | 138 | 139 | /******************************* 140 | Theme Overrides 141 | *******************************/ 142 | 143 | 144 | 145 | /******************************* 146 | User Overrides 147 | *******************************/ 148 | 149 | -------------------------------------------------------------------------------- /app/static/semantic/components/feed.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Feed 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.feed{margin:1em 0}.ui.feed:first-child{margin-top:0}.ui.feed:last-child{margin-bottom:0}.ui.feed>.event{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;width:100%;padding:.21428571rem 0;margin:0;background:0 0;border-top:none}.ui.feed>.event:first-child{border-top:0;padding-top:0}.ui.feed>.event:last-child{padding-bottom:0}.ui.feed>.event>.label{display:block;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;width:2.5em;height:auto;-ms-flex-item-align:stretch;align-self:stretch;text-align:left}.ui.feed>.event>.label .icon{opacity:1;font-size:1.5em;width:100%;padding:.25em;background:0 0;border:none;border-radius:none;color:rgba(0,0,0,.6)}.ui.feed>.event>.label img{width:100%;height:auto;border-radius:500rem}.ui.feed>.event>.label+.content{margin:.5em 0 .35714286em 1.14285714em}.ui.feed>.event>.content{display:block;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;-ms-flex-item-align:stretch;align-self:stretch;text-align:left;word-wrap:break-word}.ui.feed>.event:last-child>.content{padding-bottom:0}.ui.feed>.event>.content a{cursor:pointer}.ui.feed>.event>.content .date{margin:-.5rem 0 0;padding:0;font-weight:400;font-size:1em;font-style:normal;color:rgba(0,0,0,.4)}.ui.feed>.event>.content .summary{margin:0;font-size:1em;font-weight:700;color:rgba(0,0,0,.87)}.ui.feed>.event>.content .summary img{display:inline-block;width:auto;height:10em;margin:-.25em .25em 0 0;border-radius:.25em;vertical-align:middle}.ui.feed>.event>.content .user{display:inline-block;font-weight:700;margin-right:0;vertical-align:baseline}.ui.feed>.event>.content .user img{margin:-.25em .25em 0 0;width:auto;height:10em;vertical-align:middle}.ui.feed>.event>.content .summary>.date{display:inline-block;float:none;font-weight:400;font-size:.85714286em;font-style:normal;margin:0 0 0 .5em;padding:0;color:rgba(0,0,0,.4)}.ui.feed>.event>.content .extra{margin:.5em 0 0;background:0 0;padding:0;color:rgba(0,0,0,.87)}.ui.feed>.event>.content .extra.images img{display:inline-block;margin:0 .25em 0 0;width:6em}.ui.feed>.event>.content .extra.text{padding:0;border-left:none;font-size:1em;max-width:500px;line-height:1.4285em}.ui.feed>.event>.content .meta{display:inline-block;font-size:.85714286em;margin:.5em 0 0;background:0 0;border:none;border-radius:0;-webkit-box-shadow:none;box-shadow:none;padding:0;color:rgba(0,0,0,.6)}.ui.feed>.event>.content .meta>*{position:relative;margin-left:.75em}.ui.feed>.event>.content .meta>:after{content:'';color:rgba(0,0,0,.2);top:0;left:-1em;opacity:1;position:absolute;vertical-align:top}.ui.feed>.event>.content .meta .like{color:'';-webkit-transition:.2s color ease;transition:.2s color ease}.ui.feed>.event>.content .meta .like:hover .icon{color:#ff2733}.ui.feed>.event>.content .meta .active.like .icon{color:#ef404a}.ui.feed>.event>.content .meta>:first-child{margin-left:0}.ui.feed>.event>.content .meta>:first-child::after{display:none}.ui.feed>.event>.content .meta a,.ui.feed>.event>.content .meta>.icon{cursor:pointer;opacity:1;color:rgba(0,0,0,.5);-webkit-transition:color .1s ease;transition:color .1s ease}.ui.feed>.event>.content .meta a:hover,.ui.feed>.event>.content .meta a:hover .icon,.ui.feed>.event>.content .meta>.icon:hover{color:rgba(0,0,0,.95)}.ui.small.feed{font-size:.92857143rem}.ui.feed{font-size:1rem}.ui.large.feed{font-size:1.14285714rem} -------------------------------------------------------------------------------- /app/static/semantic/components/image.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Image 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.image{position:relative;display:inline-block;vertical-align:middle;max-width:100%;background-color:transparent}img.ui.image{display:block}.ui.image img,.ui.image svg{display:block;max-width:100%;height:auto}.ui.hidden.image,.ui.hidden.images{display:none}.ui.hidden.transition.image,.ui.hidden.transition.images{display:block;visibility:hidden}.ui.disabled.image,.ui.disabled.images{cursor:default;opacity:.45}.ui.inline.image,.ui.inline.image img,.ui.inline.image svg{display:inline-block}.ui.top.aligned.image,.ui.top.aligned.image img,.ui.top.aligned.image svg,.ui.top.aligned.images .image{display:inline-block;vertical-align:top}.ui.middle.aligned.image,.ui.middle.aligned.image img,.ui.middle.aligned.image svg,.ui.middle.aligned.images .image{display:inline-block;vertical-align:middle}.ui.bottom.aligned.image,.ui.bottom.aligned.image img,.ui.bottom.aligned.image svg,.ui.bottom.aligned.images .image{display:inline-block;vertical-align:bottom}.ui.rounded.image,.ui.rounded.image>*,.ui.rounded.images .image,.ui.rounded.images .image>*{border-radius:.3125em}.ui.bordered.image img,.ui.bordered.image svg,.ui.bordered.images .image,.ui.bordered.images img,.ui.bordered.images svg,img.ui.bordered.image{border:1px solid rgba(0,0,0,.1)}.ui.circular.image,.ui.circular.images{overflow:hidden}.ui.circular.image,.ui.circular.image>*,.ui.circular.images .image,.ui.circular.images .image>*{border-radius:500rem}.ui.fluid.image,.ui.fluid.image img,.ui.fluid.image svg,.ui.fluid.images,.ui.fluid.images img,.ui.fluid.images svg{display:block;width:100%;height:auto}.ui.avatar.image,.ui.avatar.image img,.ui.avatar.image svg,.ui.avatar.images .image,.ui.avatar.images img,.ui.avatar.images svg{margin-right:.25em;display:inline-block;width:2em;height:2em;border-radius:500rem}.ui.spaced.image{display:inline-block!important;margin-left:.5em;margin-right:.5em}.ui[class*="left spaced"].image{margin-left:.5em;margin-right:0}.ui[class*="right spaced"].image{margin-left:0;margin-right:.5em}.ui.floated.image,.ui.floated.images{float:left;margin-right:1em;margin-bottom:1em}.ui.right.floated.image,.ui.right.floated.images{float:right;margin-right:0;margin-bottom:1em;margin-left:1em}.ui.floated.image:last-child,.ui.floated.images:last-child{margin-bottom:0}.ui.centered.image,.ui.centered.images{margin-left:auto;margin-right:auto}.ui.mini.image,.ui.mini.images .image,.ui.mini.images img,.ui.mini.images svg{width:35px;height:auto;font-size:.78571429rem}.ui.tiny.image,.ui.tiny.images .image,.ui.tiny.images img,.ui.tiny.images svg{width:80px;height:auto;font-size:.85714286rem}.ui.small.image,.ui.small.images .image,.ui.small.images img,.ui.small.images svg{width:150px;height:auto;font-size:.92857143rem}.ui.medium.image,.ui.medium.images .image,.ui.medium.images img,.ui.medium.images svg{width:300px;height:auto;font-size:1rem}.ui.large.image,.ui.large.images .image,.ui.large.images img,.ui.large.images svg{width:450px;height:auto;font-size:1.14285714rem}.ui.big.image,.ui.big.images .image,.ui.big.images img,.ui.big.images svg{width:600px;height:auto;font-size:1.28571429rem}.ui.huge.image,.ui.huge.images .image,.ui.huge.images img,.ui.huge.images svg{width:800px;height:auto;font-size:1.42857143rem}.ui.massive.image,.ui.massive.images .image,.ui.massive.images img,.ui.massive.images svg{width:960px;height:auto;font-size:1.71428571rem}.ui.images{font-size:0;margin:0 -.25rem 0}.ui.images .image,.ui.images img,.ui.images svg{display:inline-block;margin:0 .25rem .5rem} -------------------------------------------------------------------------------- /app/static/semantic/components/container.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Container 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Container 14 | *******************************/ 15 | 16 | 17 | /* All Sizes */ 18 | .ui.container { 19 | display: block; 20 | max-width: 100% !important; 21 | } 22 | 23 | /* Mobile */ 24 | @media only screen and (max-width: 767px) { 25 | .ui.container { 26 | width: auto !important; 27 | margin-left: 1em !important; 28 | margin-right: 1em !important; 29 | } 30 | .ui.grid.container { 31 | width: auto !important; 32 | } 33 | .ui.relaxed.grid.container { 34 | width: auto !important; 35 | } 36 | .ui.very.relaxed.grid.container { 37 | width: auto !important; 38 | } 39 | } 40 | 41 | /* Tablet */ 42 | @media only screen and (min-width: 768px) and (max-width: 991px) { 43 | .ui.container { 44 | width: 723px; 45 | margin-left: auto !important; 46 | margin-right: auto !important; 47 | } 48 | .ui.grid.container { 49 | width: calc( 723px + 2rem ) !important; 50 | } 51 | .ui.relaxed.grid.container { 52 | width: calc( 723px + 3rem ) !important; 53 | } 54 | .ui.very.relaxed.grid.container { 55 | width: calc( 723px + 5rem ) !important; 56 | } 57 | } 58 | 59 | /* Small Monitor */ 60 | @media only screen and (min-width: 992px) and (max-width: 1199px) { 61 | .ui.container { 62 | width: 933px; 63 | margin-left: auto !important; 64 | margin-right: auto !important; 65 | } 66 | .ui.grid.container { 67 | width: calc( 933px + 2rem ) !important; 68 | } 69 | .ui.relaxed.grid.container { 70 | width: calc( 933px + 3rem ) !important; 71 | } 72 | .ui.very.relaxed.grid.container { 73 | width: calc( 933px + 5rem ) !important; 74 | } 75 | } 76 | 77 | /* Large Monitor */ 78 | @media only screen and (min-width: 1200px) { 79 | .ui.container { 80 | width: 1127px; 81 | margin-left: auto !important; 82 | margin-right: auto !important; 83 | } 84 | .ui.grid.container { 85 | width: calc( 1127px + 2rem ) !important; 86 | } 87 | .ui.relaxed.grid.container { 88 | width: calc( 1127px + 3rem ) !important; 89 | } 90 | .ui.very.relaxed.grid.container { 91 | width: calc( 1127px + 5rem ) !important; 92 | } 93 | } 94 | 95 | 96 | /******************************* 97 | Types 98 | *******************************/ 99 | 100 | 101 | /* Text Container */ 102 | .ui.text.container { 103 | font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; 104 | max-width: 700px !important; 105 | line-height: 1.5; 106 | } 107 | .ui.text.container { 108 | font-size: 1.14285714rem; 109 | } 110 | 111 | /* Fluid */ 112 | .ui.fluid.container { 113 | width: 100%; 114 | } 115 | 116 | 117 | /******************************* 118 | Variations 119 | *******************************/ 120 | 121 | .ui[class*="left aligned"].container { 122 | text-align: left; 123 | } 124 | .ui[class*="center aligned"].container { 125 | text-align: center; 126 | } 127 | .ui[class*="right aligned"].container { 128 | text-align: right; 129 | } 130 | .ui.justified.container { 131 | text-align: justify; 132 | -webkit-hyphens: auto; 133 | -ms-hyphens: auto; 134 | hyphens: auto; 135 | } 136 | 137 | 138 | /******************************* 139 | Theme Overrides 140 | *******************************/ 141 | 142 | 143 | 144 | /******************************* 145 | Site Overrides 146 | *******************************/ 147 | 148 | -------------------------------------------------------------------------------- /app/static/semantic/components/embed.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Video 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Types 14 | *******************************/ 15 | 16 | .ui.embed { 17 | position: relative; 18 | max-width: 100%; 19 | height: 0px; 20 | overflow: hidden; 21 | background: #DCDDDE; 22 | padding-bottom: 56.25%; 23 | } 24 | 25 | /*----------------- 26 | Embedded Content 27 | ------------------*/ 28 | 29 | .ui.embed iframe, 30 | .ui.embed embed, 31 | .ui.embed object { 32 | position: absolute; 33 | border: none; 34 | width: 100%; 35 | height: 100%; 36 | top: 0px; 37 | left: 0px; 38 | margin: 0em; 39 | padding: 0em; 40 | } 41 | 42 | /*----------------- 43 | Embed 44 | ------------------*/ 45 | 46 | .ui.embed > .embed { 47 | display: none; 48 | } 49 | 50 | /*-------------- 51 | Placeholder 52 | ---------------*/ 53 | 54 | .ui.embed > .placeholder { 55 | position: absolute; 56 | cursor: pointer; 57 | top: 0px; 58 | left: 0px; 59 | display: block; 60 | width: 100%; 61 | height: 100%; 62 | background-color: radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); 63 | } 64 | 65 | /*-------------- 66 | Icon 67 | ---------------*/ 68 | 69 | .ui.embed > .icon { 70 | cursor: pointer; 71 | position: absolute; 72 | top: 0px; 73 | left: 0px; 74 | width: 100%; 75 | height: 100%; 76 | z-index: 2; 77 | } 78 | .ui.embed > .icon:after { 79 | position: absolute; 80 | top: 0%; 81 | left: 0%; 82 | width: 100%; 83 | height: 100%; 84 | z-index: 3; 85 | content: ''; 86 | background: -webkit-radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); 87 | background: radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); 88 | opacity: 0.5; 89 | -webkit-transition: opacity 0.5s ease; 90 | transition: opacity 0.5s ease; 91 | } 92 | .ui.embed > .icon:before { 93 | position: absolute; 94 | top: 50%; 95 | left: 50%; 96 | z-index: 4; 97 | -webkit-transform: translateX(-50%) translateY(-50%); 98 | transform: translateX(-50%) translateY(-50%); 99 | color: #FFFFFF; 100 | font-size: 6rem; 101 | text-shadow: 0px 2px 10px rgba(34, 36, 38, 0.2); 102 | -webkit-transition: opacity 0.5s ease, color 0.5s ease; 103 | transition: opacity 0.5s ease, color 0.5s ease; 104 | z-index: 10; 105 | } 106 | 107 | 108 | /******************************* 109 | States 110 | *******************************/ 111 | 112 | 113 | /*-------------- 114 | Hover 115 | ---------------*/ 116 | 117 | .ui.embed .icon:hover:after { 118 | background: -webkit-radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); 119 | background: radial-gradient(transparent 45%, rgba(0, 0, 0, 0.3)); 120 | opacity: 1; 121 | } 122 | .ui.embed .icon:hover:before { 123 | color: #FFFFFF; 124 | } 125 | 126 | /*-------------- 127 | Active 128 | ---------------*/ 129 | 130 | .ui.active.embed > .icon, 131 | .ui.active.embed > .placeholder { 132 | display: none; 133 | } 134 | .ui.active.embed > .embed { 135 | display: block; 136 | } 137 | 138 | 139 | /******************************* 140 | Video Overrides 141 | *******************************/ 142 | 143 | 144 | 145 | /******************************* 146 | Site Overrides 147 | *******************************/ 148 | 149 | 150 | 151 | /******************************* 152 | Variations 153 | *******************************/ 154 | 155 | .ui.square.embed { 156 | padding-bottom: 100%; 157 | } 158 | .ui[class*="4:3"].embed { 159 | padding-bottom: 75%; 160 | } 161 | .ui[class*="16:9"].embed { 162 | padding-bottom: 56.25%; 163 | } 164 | .ui[class*="21:9"].embed { 165 | padding-bottom: 42.85714286%; 166 | } 167 | -------------------------------------------------------------------------------- /app/static/login-page/container.css: -------------------------------------------------------------------------------- 1 | /* 2 | * # Semantic UI - 2.3.0 3 | * https://github.com/Semantic-Org/Semantic-UI 4 | * http://www.semantic-ui.com/ 5 | * 6 | * Copyright 2014 Contributors 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */ 11 | /*! 12 | * # Semantic UI - Container 13 | * http://github.com/semantic-org/semantic-ui/ 14 | * 15 | * 16 | * Released under the MIT license 17 | * http://opensource.org/licenses/MIT 18 | * 19 | */ 20 | 21 | 22 | /******************************* 23 | Container 24 | *******************************/ 25 | 26 | 27 | /* All Sizes */ 28 | .ui.container { 29 | display: block; 30 | max-width: 100% !important; 31 | } 32 | 33 | /* Mobile */ 34 | @media only screen and (max-width: 767px) { 35 | .ui.container { 36 | width: auto !important; 37 | margin-left: 1em !important; 38 | margin-right: 1em !important; 39 | } 40 | .ui.grid.container { 41 | width: auto !important; 42 | } 43 | .ui.relaxed.grid.container { 44 | width: auto !important; 45 | } 46 | .ui.very.relaxed.grid.container { 47 | width: auto !important; 48 | } 49 | } 50 | 51 | /* Tablet */ 52 | @media only screen and (min-width: 768px) and (max-width: 991px) { 53 | .ui.container { 54 | width: 723px; 55 | margin-left: auto !important; 56 | margin-right: auto !important; 57 | } 58 | .ui.grid.container { 59 | width: calc( 723px + 2rem ) !important; 60 | } 61 | .ui.relaxed.grid.container { 62 | width: calc( 723px + 3rem ) !important; 63 | } 64 | .ui.very.relaxed.grid.container { 65 | width: calc( 723px + 5rem ) !important; 66 | } 67 | } 68 | 69 | /* Small Monitor */ 70 | @media only screen and (min-width: 992px) and (max-width: 1199px) { 71 | .ui.container { 72 | width: 933px; 73 | margin-left: auto !important; 74 | margin-right: auto !important; 75 | } 76 | .ui.grid.container { 77 | width: calc( 933px + 2rem ) !important; 78 | } 79 | .ui.relaxed.grid.container { 80 | width: calc( 933px + 3rem ) !important; 81 | } 82 | .ui.very.relaxed.grid.container { 83 | width: calc( 933px + 5rem ) !important; 84 | } 85 | } 86 | 87 | /* Large Monitor */ 88 | @media only screen and (min-width: 1200px) { 89 | .ui.container { 90 | width: 1127px; 91 | margin-left: auto !important; 92 | margin-right: auto !important; 93 | } 94 | .ui.grid.container { 95 | width: calc( 1127px + 2rem ) !important; 96 | } 97 | .ui.relaxed.grid.container { 98 | width: calc( 1127px + 3rem ) !important; 99 | } 100 | .ui.very.relaxed.grid.container { 101 | width: calc( 1127px + 5rem ) !important; 102 | } 103 | } 104 | 105 | 106 | /******************************* 107 | Types 108 | *******************************/ 109 | 110 | 111 | /* Text Container */ 112 | .ui.text.container { 113 | font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; 114 | max-width: 700px !important; 115 | line-height: 1.5; 116 | } 117 | .ui.text.container { 118 | font-size: 1.14285714rem; 119 | } 120 | 121 | /* Fluid */ 122 | .ui.fluid.container { 123 | width: 100%; 124 | } 125 | 126 | 127 | /******************************* 128 | Variations 129 | *******************************/ 130 | 131 | .ui[class*="left aligned"].container { 132 | text-align: left; 133 | } 134 | .ui[class*="center aligned"].container { 135 | text-align: center; 136 | } 137 | .ui[class*="right aligned"].container { 138 | text-align: right; 139 | } 140 | .ui.justified.container { 141 | text-align: justify; 142 | -webkit-hyphens: auto; 143 | -ms-hyphens: auto; 144 | hyphens: auto; 145 | } 146 | 147 | 148 | /******************************* 149 | Theme Overrides 150 | *******************************/ 151 | 152 | 153 | 154 | /******************************* 155 | Site Overrides 156 | *******************************/ 157 | 158 | -------------------------------------------------------------------------------- /app/static/semantic/components/shape.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Shape 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Shape 14 | *******************************/ 15 | 16 | .ui.shape { 17 | position: relative; 18 | vertical-align: top; 19 | display: inline-block; 20 | -webkit-perspective: 2000px; 21 | perspective: 2000px; 22 | -webkit-transition: left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; 23 | transition: left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; 24 | transition: transform 0.6s ease-in-out, left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out; 25 | transition: transform 0.6s ease-in-out, left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; 26 | } 27 | .ui.shape .sides { 28 | -webkit-transform-style: preserve-3d; 29 | transform-style: preserve-3d; 30 | } 31 | .ui.shape .side { 32 | opacity: 1; 33 | width: 100%; 34 | margin: 0em !important; 35 | -webkit-backface-visibility: hidden; 36 | backface-visibility: hidden; 37 | } 38 | .ui.shape .side { 39 | display: none; 40 | } 41 | .ui.shape .side * { 42 | -webkit-backface-visibility: visible !important; 43 | backface-visibility: visible !important; 44 | } 45 | 46 | 47 | /******************************* 48 | Types 49 | *******************************/ 50 | 51 | .ui.cube.shape .side { 52 | min-width: 15em; 53 | height: 15em; 54 | padding: 2em; 55 | background-color: #E6E6E6; 56 | color: rgba(0, 0, 0, 0.87); 57 | -webkit-box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.3); 58 | box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.3); 59 | } 60 | .ui.cube.shape .side > .content { 61 | width: 100%; 62 | height: 100%; 63 | display: table; 64 | text-align: center; 65 | -webkit-user-select: text; 66 | -moz-user-select: text; 67 | -ms-user-select: text; 68 | user-select: text; 69 | } 70 | .ui.cube.shape .side > .content > div { 71 | display: table-cell; 72 | vertical-align: middle; 73 | font-size: 2em; 74 | } 75 | 76 | 77 | /******************************* 78 | Variations 79 | *******************************/ 80 | 81 | .ui.text.shape.animating .sides { 82 | position: static; 83 | } 84 | .ui.text.shape .side { 85 | white-space: nowrap; 86 | } 87 | .ui.text.shape .side > * { 88 | white-space: normal; 89 | } 90 | 91 | 92 | /******************************* 93 | States 94 | *******************************/ 95 | 96 | 97 | /*-------------- 98 | Loading 99 | ---------------*/ 100 | 101 | .ui.loading.shape { 102 | position: absolute; 103 | top: -9999px; 104 | left: -9999px; 105 | } 106 | 107 | /*-------------- 108 | Animating 109 | ---------------*/ 110 | 111 | .ui.shape .animating.side { 112 | position: absolute; 113 | top: 0px; 114 | left: 0px; 115 | display: block; 116 | z-index: 100; 117 | } 118 | .ui.shape .hidden.side { 119 | opacity: 0.6; 120 | } 121 | 122 | /*-------------- 123 | CSS 124 | ---------------*/ 125 | 126 | .ui.shape.animating .sides { 127 | position: absolute; 128 | } 129 | .ui.shape.animating .sides { 130 | -webkit-transition: left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; 131 | transition: left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; 132 | transition: transform 0.6s ease-in-out, left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out; 133 | transition: transform 0.6s ease-in-out, left 0.6s ease-in-out, width 0.6s ease-in-out, height 0.6s ease-in-out, -webkit-transform 0.6s ease-in-out; 134 | } 135 | .ui.shape.animating .side { 136 | -webkit-transition: opacity 0.6s ease-in-out; 137 | transition: opacity 0.6s ease-in-out; 138 | } 139 | 140 | /*-------------- 141 | Active 142 | ---------------*/ 143 | 144 | .ui.shape .active.side { 145 | display: block; 146 | } 147 | 148 | 149 | /******************************* 150 | Theme Overrides 151 | *******************************/ 152 | 153 | 154 | 155 | /******************************* 156 | User Overrides 157 | *******************************/ 158 | 159 | -------------------------------------------------------------------------------- /app/static/semantic/components/loader.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Loader 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.loader{display:none;position:absolute;top:50%;left:50%;margin:0;text-align:center;z-index:1000;-webkit-transform:translateX(-50%) translateY(-50%);transform:translateX(-50%) translateY(-50%)}.ui.loader:before{position:absolute;content:'';top:0;left:50%;width:100%;height:100%;border-radius:500rem;border:.2em solid rgba(0,0,0,.1)}.ui.loader:after{position:absolute;content:'';top:0;left:50%;width:100%;height:100%;-webkit-animation:loader .6s linear;animation:loader .6s linear;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;border-radius:500rem;border-color:#767676 transparent transparent;border-style:solid;border-width:.2em;-webkit-box-shadow:0 0 0 1px transparent;box-shadow:0 0 0 1px transparent}@-webkit-keyframes loader{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loader{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.ui.mini.loader:after,.ui.mini.loader:before{width:1rem;height:1rem;margin:0 0 0 -.5rem}.ui.tiny.loader:after,.ui.tiny.loader:before{width:1.14285714rem;height:1.14285714rem;margin:0 0 0 -.57142857rem}.ui.small.loader:after,.ui.small.loader:before{width:1.71428571rem;height:1.71428571rem;margin:0 0 0 -.85714286rem}.ui.loader:after,.ui.loader:before{width:2.28571429rem;height:2.28571429rem;margin:0 0 0 -1.14285714rem}.ui.large.loader:after,.ui.large.loader:before{width:3.42857143rem;height:3.42857143rem;margin:0 0 0 -1.71428571rem}.ui.big.loader:after,.ui.big.loader:before{width:3.71428571rem;height:3.71428571rem;margin:0 0 0 -1.85714286rem}.ui.huge.loader:after,.ui.huge.loader:before{width:4.14285714rem;height:4.14285714rem;margin:0 0 0 -2.07142857rem}.ui.massive.loader:after,.ui.massive.loader:before{width:4.57142857rem;height:4.57142857rem;margin:0 0 0 -2.28571429rem}.ui.dimmer .loader{display:block}.ui.dimmer .ui.loader{color:rgba(255,255,255,.9)}.ui.dimmer .ui.loader:before{border-color:rgba(255,255,255,.15)}.ui.dimmer .ui.loader:after{border-color:#fff transparent transparent}.ui.inverted.dimmer .ui.loader{color:rgba(0,0,0,.87)}.ui.inverted.dimmer .ui.loader:before{border-color:rgba(0,0,0,.1)}.ui.inverted.dimmer .ui.loader:after{border-color:#767676 transparent transparent}.ui.text.loader{width:auto!important;height:auto!important;text-align:center;font-style:normal}.ui.indeterminate.loader:after{animation-direction:reverse;-webkit-animation-duration:1.2s;animation-duration:1.2s}.ui.loader.active,.ui.loader.visible{display:block}.ui.loader.disabled,.ui.loader.hidden{display:none}.ui.inverted.dimmer .ui.mini.loader,.ui.mini.loader{width:1rem;height:1rem;font-size:.78571429em}.ui.inverted.dimmer .ui.tiny.loader,.ui.tiny.loader{width:1.14285714rem;height:1.14285714rem;font-size:.85714286em}.ui.inverted.dimmer .ui.small.loader,.ui.small.loader{width:1.71428571rem;height:1.71428571rem;font-size:.92857143em}.ui.inverted.dimmer .ui.loader,.ui.loader{width:2.28571429rem;height:2.28571429rem;font-size:1em}.ui.inverted.dimmer .ui.large.loader,.ui.large.loader{width:3.42857143rem;height:3.42857143rem;font-size:1.14285714em}.ui.big.loader,.ui.inverted.dimmer .ui.big.loader{width:3.71428571rem;height:3.71428571rem;font-size:1.28571429em}.ui.huge.loader,.ui.inverted.dimmer .ui.huge.loader{width:4.14285714rem;height:4.14285714rem;font-size:1.42857143em}.ui.inverted.dimmer .ui.massive.loader,.ui.massive.loader{width:4.57142857rem;height:4.57142857rem;font-size:1.71428571em}.ui.mini.text.loader{min-width:1rem;padding-top:1.78571429rem}.ui.tiny.text.loader{min-width:1.14285714rem;padding-top:1.92857143rem}.ui.small.text.loader{min-width:1.71428571rem;padding-top:2.5rem}.ui.text.loader{min-width:2.28571429rem;padding-top:3.07142857rem}.ui.large.text.loader{min-width:3.42857143rem;padding-top:4.21428571rem}.ui.big.text.loader{min-width:3.71428571rem;padding-top:4.5rem}.ui.huge.text.loader{min-width:4.14285714rem;padding-top:4.92857143rem}.ui.massive.text.loader{min-width:4.57142857rem;padding-top:5.35714286rem}.ui.inverted.loader{color:rgba(255,255,255,.9)}.ui.inverted.loader:before{border-color:rgba(255,255,255,.15)}.ui.inverted.loader:after{border-top-color:#fff}.ui.inline.loader{position:relative;vertical-align:middle;margin:0;left:0;top:0;-webkit-transform:none;transform:none}.ui.inline.loader.active,.ui.inline.loader.visible{display:inline-block}.ui.centered.inline.loader.active,.ui.centered.inline.loader.visible{display:block;margin-left:auto;margin-right:auto} -------------------------------------------------------------------------------- /app/static/login-page/login-page-template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Login Example - Semantic 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 47 | 85 | 86 | 87 | 88 |
89 |
90 |

91 | 92 |
93 | Log-in to your account 94 |
95 |

96 |
97 |
98 |
99 |
100 | 101 | 102 |
103 |
104 |
105 |
106 | 107 | 108 |
109 |
110 |
Login
111 |
112 | 113 |
114 | 115 |
116 | 117 |
118 | New to us? Sign Up 119 |
120 |
121 |
122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /app/templates/admin/roles/role.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %} 5 | {% if add_department %} 6 | Add Role 7 | {% else %} 8 | Edit Role 9 | {% endif %} 10 | {% endblock %} 11 | 12 | 13 | {% block head %} 14 | 15 | 42 | 75 | {% endblock %} 76 | {% block body %} 77 | 78 |
79 |
80 |
81 | 82 | {% with messages = get_flashed_messages() %} 83 | {% if messages %} 84 |
    85 | {% for message in messages %} 86 |
  • {{ message }}
  • 87 | {% endfor %} 88 |
89 | {% endif %} 90 | {% endwith %} 91 | 92 |
93 | {% if add_department %} 94 |

96 | Add role 97 |

98 | {% else %} 99 |

101 | Edit role 102 |

103 | {% endif %} 104 |
105 | 106 |
107 |
108 | {{ form.hidden_tag() }} 109 |
110 |
111 | 112 |
113 | 114 | {{ form.name(placeholder="Role Name") }} 115 |
116 |
117 |
118 | 119 | 120 |
121 | 122 | {{ form.description(placeholder="Description") }} 123 |
124 |
125 | 133 |
134 |
135 |
136 |
137 | 138 | 139 |
140 |
141 |
142 | 143 | {% endblock %} -------------------------------------------------------------------------------- /app/static/semantic/components/site.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Site 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Page 14 | *******************************/ 15 | 16 | @import url('https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin'); 17 | html, 18 | body { 19 | height: 100%; 20 | } 21 | html { 22 | font-size: 14px; 23 | } 24 | body { 25 | margin: 0px; 26 | padding: 0px; 27 | overflow-x: hidden; 28 | min-width: 320px; 29 | background: #FFFFFF; 30 | font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; 31 | font-size: 14px; 32 | line-height: 1.4285em; 33 | color: rgba(0, 0, 0, 0.87); 34 | font-smoothing: antialiased; 35 | } 36 | 37 | 38 | /******************************* 39 | Headers 40 | *******************************/ 41 | 42 | h1, 43 | h2, 44 | h3, 45 | h4, 46 | h5 { 47 | font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; 48 | line-height: 1.28571429em; 49 | margin: calc(2rem - 0.14285714em ) 0em 1rem; 50 | font-weight: bold; 51 | padding: 0em; 52 | } 53 | h1 { 54 | min-height: 1rem; 55 | font-size: 2rem; 56 | } 57 | h2 { 58 | font-size: 1.71428571rem; 59 | } 60 | h3 { 61 | font-size: 1.28571429rem; 62 | } 63 | h4 { 64 | font-size: 1.07142857rem; 65 | } 66 | h5 { 67 | font-size: 1rem; 68 | } 69 | h1:first-child, 70 | h2:first-child, 71 | h3:first-child, 72 | h4:first-child, 73 | h5:first-child { 74 | margin-top: 0em; 75 | } 76 | h1:last-child, 77 | h2:last-child, 78 | h3:last-child, 79 | h4:last-child, 80 | h5:last-child { 81 | margin-bottom: 0em; 82 | } 83 | 84 | 85 | /******************************* 86 | Text 87 | *******************************/ 88 | 89 | p { 90 | margin: 0em 0em 1em; 91 | line-height: 1.4285em; 92 | } 93 | p:first-child { 94 | margin-top: 0em; 95 | } 96 | p:last-child { 97 | margin-bottom: 0em; 98 | } 99 | 100 | /*------------------- 101 | Links 102 | --------------------*/ 103 | 104 | a { 105 | color: #4183C4; 106 | text-decoration: none; 107 | } 108 | a:hover { 109 | color: #1e70bf; 110 | text-decoration: none; 111 | } 112 | 113 | 114 | /******************************* 115 | Scrollbars 116 | *******************************/ 117 | 118 | 119 | 120 | /******************************* 121 | Highlighting 122 | *******************************/ 123 | 124 | 125 | /* Site */ 126 | ::-webkit-selection { 127 | background-color: #CCE2FF; 128 | color: rgba(0, 0, 0, 0.87); 129 | } 130 | ::-moz-selection { 131 | background-color: #CCE2FF; 132 | color: rgba(0, 0, 0, 0.87); 133 | } 134 | ::selection { 135 | background-color: #CCE2FF; 136 | color: rgba(0, 0, 0, 0.87); 137 | } 138 | 139 | /* Form */ 140 | textarea::-webkit-selection, 141 | input::-webkit-selection { 142 | background-color: rgba(100, 100, 100, 0.4); 143 | color: rgba(0, 0, 0, 0.87); 144 | } 145 | textarea::-moz-selection, 146 | input::-moz-selection { 147 | background-color: rgba(100, 100, 100, 0.4); 148 | color: rgba(0, 0, 0, 0.87); 149 | } 150 | textarea::selection, 151 | input::selection { 152 | background-color: rgba(100, 100, 100, 0.4); 153 | color: rgba(0, 0, 0, 0.87); 154 | } 155 | 156 | /* Force Simple Scrollbars */ 157 | body ::-webkit-scrollbar { 158 | -webkit-appearance: none; 159 | width: 10px; 160 | height: 10px; 161 | } 162 | body ::-webkit-scrollbar-track { 163 | background: rgba(0, 0, 0, 0.1); 164 | border-radius: 0px; 165 | } 166 | body ::-webkit-scrollbar-thumb { 167 | cursor: pointer; 168 | border-radius: 5px; 169 | background: rgba(0, 0, 0, 0.25); 170 | -webkit-transition: color 0.2s ease; 171 | transition: color 0.2s ease; 172 | } 173 | body ::-webkit-scrollbar-thumb:window-inactive { 174 | background: rgba(0, 0, 0, 0.15); 175 | } 176 | body ::-webkit-scrollbar-thumb:hover { 177 | background: rgba(128, 135, 139, 0.8); 178 | } 179 | 180 | /* Inverted UI */ 181 | body .ui.inverted::-webkit-scrollbar-track { 182 | background: rgba(255, 255, 255, 0.1); 183 | } 184 | body .ui.inverted::-webkit-scrollbar-thumb { 185 | background: rgba(255, 255, 255, 0.25); 186 | } 187 | body .ui.inverted::-webkit-scrollbar-thumb:window-inactive { 188 | background: rgba(255, 255, 255, 0.15); 189 | } 190 | body .ui.inverted::-webkit-scrollbar-thumb:hover { 191 | background: rgba(255, 255, 255, 0.35); 192 | } 193 | 194 | 195 | /******************************* 196 | Global Overrides 197 | *******************************/ 198 | 199 | 200 | 201 | /******************************* 202 | Site Overrides 203 | *******************************/ 204 | 205 | -------------------------------------------------------------------------------- /app/templates/auth/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% extends "base.html" %} 5 | {% block title %}Login{% endblock %} 6 | 7 | {% block head %} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 40 | 41 | 79 | 80 | {% endblock %} 81 | 82 | {% block body %} 83 | 84 | 85 |
86 |
87 |

88 | 89 | 91 |
92 | Log-in to your account 93 |
94 |

95 |
96 | {{ form.hidden_tag() }} 97 |
98 |
99 |
100 | 101 | {{ form.email(placeholder="Email address") }} 102 |
103 |
104 |
105 |
106 | 107 | {{ form.password(placeholder="Password") }} 108 |
109 |
110 | 113 |
114 |
115 |
116 | {% with messages = get_flashed_messages(category_filter=["error"]) %} 117 | {% if messages %} 118 |
119 |
    120 | {% for message in messages %} 121 |
  • {{ message }}
  • 122 | {% endfor %} 123 |
124 |
125 | {% endif %} 126 | {% endwith %} 127 | 128 | {% with messages = get_flashed_messages(category_filter=["success"]) %} 129 | {% if messages %} 130 |
131 |
    132 | {% for message in messages %} 133 |
  • {{ message }}
  • 134 | {% endfor %} 135 |
136 |
137 | {% endif %} 138 | {% endwith %} 139 | 140 |
141 | New to this site? Register 142 |
143 | 144 |
145 |
146 | 147 | {% endblock %} -------------------------------------------------------------------------------- /app/static/login-page/site.css: -------------------------------------------------------------------------------- 1 | /* 2 | * # Semantic UI - 2.3.0 3 | * https://github.com/Semantic-Org/Semantic-UI 4 | * http://www.semantic-ui.com/ 5 | * 6 | * Copyright 2014 Contributors 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */ 11 | /*! 12 | * # Semantic UI - Site 13 | * http://github.com/semantic-org/semantic-ui/ 14 | * 15 | * 16 | * Released under the MIT license 17 | * http://opensource.org/licenses/MIT 18 | * 19 | */ 20 | 21 | 22 | /******************************* 23 | Page 24 | *******************************/ 25 | 26 | @import url('https://fonts.googleapis.com/css?family=Lato:400,700,400italic,700italic&subset=latin'); 27 | html, 28 | body { 29 | height: 100%; 30 | } 31 | html { 32 | font-size: 14px; 33 | } 34 | body { 35 | margin: 0px; 36 | padding: 0px; 37 | overflow-x: hidden; 38 | min-width: 320px; 39 | background: #FFFFFF; 40 | font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; 41 | font-size: 14px; 42 | line-height: 1.4285em; 43 | color: rgba(0, 0, 0, 0.87); 44 | font-smoothing: antialiased; 45 | } 46 | 47 | 48 | /******************************* 49 | Headers 50 | *******************************/ 51 | 52 | h1, 53 | h2, 54 | h3, 55 | h4, 56 | h5 { 57 | font-family: 'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif; 58 | line-height: 1.28571429em; 59 | margin: calc(2rem - 0.14285714em ) 0em 1rem; 60 | font-weight: bold; 61 | padding: 0em; 62 | } 63 | h1 { 64 | min-height: 1rem; 65 | font-size: 2rem; 66 | } 67 | h2 { 68 | font-size: 1.71428571rem; 69 | } 70 | h3 { 71 | font-size: 1.28571429rem; 72 | } 73 | h4 { 74 | font-size: 1.07142857rem; 75 | } 76 | h5 { 77 | font-size: 1rem; 78 | } 79 | h1:first-child, 80 | h2:first-child, 81 | h3:first-child, 82 | h4:first-child, 83 | h5:first-child { 84 | margin-top: 0em; 85 | } 86 | h1:last-child, 87 | h2:last-child, 88 | h3:last-child, 89 | h4:last-child, 90 | h5:last-child { 91 | margin-bottom: 0em; 92 | } 93 | 94 | 95 | /******************************* 96 | Text 97 | *******************************/ 98 | 99 | p { 100 | margin: 0em 0em 1em; 101 | line-height: 1.4285em; 102 | } 103 | p:first-child { 104 | margin-top: 0em; 105 | } 106 | p:last-child { 107 | margin-bottom: 0em; 108 | } 109 | 110 | /*------------------- 111 | Links 112 | --------------------*/ 113 | 114 | a { 115 | color: #4183C4; 116 | text-decoration: none; 117 | } 118 | a:hover { 119 | color: #1e70bf; 120 | text-decoration: none; 121 | } 122 | 123 | 124 | /******************************* 125 | Scrollbars 126 | *******************************/ 127 | 128 | 129 | 130 | /******************************* 131 | Highlighting 132 | *******************************/ 133 | 134 | 135 | /* Site */ 136 | ::-webkit-selection { 137 | background-color: #CCE2FF; 138 | color: rgba(0, 0, 0, 0.87); 139 | } 140 | ::-moz-selection { 141 | background-color: #CCE2FF; 142 | color: rgba(0, 0, 0, 0.87); 143 | } 144 | ::selection { 145 | background-color: #CCE2FF; 146 | color: rgba(0, 0, 0, 0.87); 147 | } 148 | 149 | /* Form */ 150 | textarea::-webkit-selection, 151 | input::-webkit-selection { 152 | background-color: rgba(100, 100, 100, 0.4); 153 | color: rgba(0, 0, 0, 0.87); 154 | } 155 | textarea::-moz-selection, 156 | input::-moz-selection { 157 | background-color: rgba(100, 100, 100, 0.4); 158 | color: rgba(0, 0, 0, 0.87); 159 | } 160 | textarea::selection, 161 | input::selection { 162 | background-color: rgba(100, 100, 100, 0.4); 163 | color: rgba(0, 0, 0, 0.87); 164 | } 165 | 166 | /* Force Simple Scrollbars */ 167 | body ::-webkit-scrollbar { 168 | -webkit-appearance: none; 169 | width: 10px; 170 | height: 10px; 171 | } 172 | body ::-webkit-scrollbar-track { 173 | background: rgba(0, 0, 0, 0.1); 174 | border-radius: 0px; 175 | } 176 | body ::-webkit-scrollbar-thumb { 177 | cursor: pointer; 178 | border-radius: 5px; 179 | background: rgba(0, 0, 0, 0.25); 180 | -webkit-transition: color 0.2s ease; 181 | transition: color 0.2s ease; 182 | } 183 | body ::-webkit-scrollbar-thumb:window-inactive { 184 | background: rgba(0, 0, 0, 0.15); 185 | } 186 | body ::-webkit-scrollbar-thumb:hover { 187 | background: rgba(128, 135, 139, 0.8); 188 | } 189 | 190 | /* Inverted UI */ 191 | body .ui.inverted::-webkit-scrollbar-track { 192 | background: rgba(255, 255, 255, 0.1); 193 | } 194 | body .ui.inverted::-webkit-scrollbar-thumb { 195 | background: rgba(255, 255, 255, 0.25); 196 | } 197 | body .ui.inverted::-webkit-scrollbar-thumb:window-inactive { 198 | background: rgba(255, 255, 255, 0.15); 199 | } 200 | body .ui.inverted::-webkit-scrollbar-thumb:hover { 201 | background: rgba(255, 255, 255, 0.35); 202 | } 203 | 204 | 205 | /******************************* 206 | Global Overrides 207 | *******************************/ 208 | 209 | 210 | 211 | /******************************* 212 | Site Overrides 213 | *******************************/ 214 | 215 | -------------------------------------------------------------------------------- /app/templates/admin/departments/department.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %} 5 | {% if add_department %} 6 | Add Department 7 | {% else %} 8 | Edit Department 9 | {% endif %} 10 | {% endblock %} 11 | 12 | 13 | {% block head %} 14 | 15 | 16 | 17 | 18 | 19 | 46 | 79 | {% endblock %} 80 | {% block body %} 81 | 82 |
83 |
84 |
85 | 86 | {% with messages = get_flashed_messages() %} 87 | {% if messages %} 88 |
    89 | {% for message in messages %} 90 |
  • {{ message }}
  • 91 | {% endfor %} 92 |
93 | {% endif %} 94 | {% endwith %} 95 | 96 |
97 | {% if add_department %} 98 |

100 | Add department 101 |

102 | {% else %} 103 |

105 | Edit department 106 |

107 | {% endif %} 108 |
109 | 110 |
111 |
112 | {{ form.hidden_tag() }} 113 |
114 |
115 | 116 |
117 | 118 | {{ form.name(placeholder="Department Name") }} 119 |
120 |
121 |
122 | 123 | 124 |
125 | 126 | {{ form.description(placeholder="Description") }} 127 |
128 |
129 | 137 |
138 |
139 |
140 |
141 | 142 | 143 |
144 |
145 |
146 | 147 | {% endblock %} -------------------------------------------------------------------------------- /app/templates/admin/employees/employees.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Employees{% endblock %} 5 | {% block head %} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 40 | 41 | 42 | {% endblock %} 43 | {% block body %} 44 | 45 |
46 |
47 |
48 | 49 |
50 |

52 | Employees 53 |

54 |
55 | 56 | {% if employees %} 57 |
58 |

The following employees are currently present in the database:

59 |
60 |
61 |
62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | {% for employee in employees %} 74 | {% if employee.is_admin %} 75 | 76 | 77 | 78 | 79 | 80 | 81 | {% else %} 82 | 83 | 84 | 91 | 98 | 103 | 104 | {% endif %} 105 | {% endfor %} 106 | 107 |
NameDepartmentRoleAssign
Admin N/A N/A N/A
{{ employee.first_name }} {{ employee.last_name }} 85 | {% if employee.department %} 86 | {{ employee.department.name }} 87 | {% else %} 88 | - 89 | {% endif %} 90 | 92 | {% if employee.role %} 93 | {{ employee.role.name }} 94 | {% else %} 95 | - 96 | {% endif %} 97 | 99 | 100 | Assign 101 | 102 |
108 |
109 | {% endif %} 110 | 111 | 112 | {% with messages = get_flashed_messages(category_filter=["success"]) %} 113 | {% if messages %} 114 | 122 | {% endif %} 123 | {% endwith %} 124 | 125 | 126 | {% with messages = get_flashed_messages(category_filter=["error"]) %} 127 | {% if messages %} 128 | 136 | {% endif %} 137 | {% endwith %} 138 |
139 |
140 |
141 | {% endblock %} 142 | 143 | {% block javascript %} 144 | {% endblock %} -------------------------------------------------------------------------------- /app/static/semantic/components/rating.min.js: -------------------------------------------------------------------------------- 1 | !function(e,n,t,i){"use strict";n=void 0!==n&&n.Math==Math?n:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")(),e.fn.rating=function(n){var t,a=e(this),o=a.selector||"",r=(new Date).getTime(),s=[],l=arguments[0],c="string"==typeof l,u=[].slice.call(arguments,1);return a.each(function(){var d,g,m=e.isPlainObject(n)?e.extend(!0,{},e.fn.rating.settings,n):e.extend({},e.fn.rating.settings),f=m.namespace,v=m.className,p=m.metadata,b=m.selector,h=(m.error,"."+f),y="module-"+f,x=this,R=e(this).data(y),C=e(this),T=C.find(b.icon);g={initialize:function(){g.verbose("Initializing rating module",m),0===T.length&&g.setup.layout(),m.interactive?g.enable():g.disable(),g.set.initialLoad(),g.set.rating(g.get.initialRating()),g.remove.initialLoad(),g.instantiate()},instantiate:function(){g.verbose("Instantiating module",m),R=g,C.data(y,g)},destroy:function(){g.verbose("Destroying previous instance",R),g.remove.events(),C.removeData(y)},refresh:function(){T=C.find(b.icon)},setup:{layout:function(){var n=g.get.maxRating(),t=e.fn.rating.settings.templates.icon(n);g.debug("Generating icon html dynamically"),C.html(t),g.refresh()}},event:{mouseenter:function(){var n=e(this);n.nextAll().removeClass(v.selected),C.addClass(v.selected),n.addClass(v.selected).prevAll().addClass(v.selected)},mouseleave:function(){C.removeClass(v.selected),T.removeClass(v.selected)},click:function(){var n=e(this),t=g.get.rating(),i=T.index(n)+1;("auto"==m.clearable?1===T.length:m.clearable)&&t==i?g.clearRating():g.set.rating(i)}},clearRating:function(){g.debug("Clearing current rating"),g.set.rating(0)},bind:{events:function(){g.verbose("Binding events"),C.on("mouseenter"+h,b.icon,g.event.mouseenter).on("mouseleave"+h,b.icon,g.event.mouseleave).on("click"+h,b.icon,g.event.click)}},remove:{events:function(){g.verbose("Removing events"),C.off(h)},initialLoad:function(){d=!1}},enable:function(){g.debug("Setting rating to interactive mode"),g.bind.events(),C.removeClass(v.disabled)},disable:function(){g.debug("Setting rating to read-only mode"),g.remove.events(),C.addClass(v.disabled)},is:{initialLoad:function(){return d}},get:{initialRating:function(){return C.data(p.rating)!==i?(C.removeData(p.rating),C.data(p.rating)):m.initialRating},maxRating:function(){return C.data(p.maxRating)!==i?(C.removeData(p.maxRating),C.data(p.maxRating)):m.maxRating},rating:function(){var e=T.filter("."+v.active).length;return g.verbose("Current rating retrieved",e),e}},set:{rating:function(e){var n=e-1>=0?e-1:0,t=T.eq(n);C.removeClass(v.selected),T.removeClass(v.selected).removeClass(v.active),e>0&&(g.verbose("Setting current rating to",e),t.prevAll().addBack().addClass(v.active)),g.is.initialLoad()||m.onRate.call(x,e)},initialLoad:function(){d=!0}},setting:function(n,t){if(g.debug("Changing setting",n,t),e.isPlainObject(n))e.extend(!0,m,n);else{if(t===i)return m[n];e.isPlainObject(m[n])?e.extend(!0,m[n],t):m[n]=t}},internal:function(n,t){if(e.isPlainObject(n))e.extend(!0,g,n);else{if(t===i)return g[n];g[n]=t}},debug:function(){!m.silent&&m.debug&&(m.performance?g.performance.log(arguments):(g.debug=Function.prototype.bind.call(console.info,console,m.name+":"),g.debug.apply(console,arguments)))},verbose:function(){!m.silent&&m.verbose&&m.debug&&(m.performance?g.performance.log(arguments):(g.verbose=Function.prototype.bind.call(console.info,console,m.name+":"),g.verbose.apply(console,arguments)))},error:function(){m.silent||(g.error=Function.prototype.bind.call(console.error,console,m.name+":"),g.error.apply(console,arguments))},performance:{log:function(e){var n,t;m.performance&&(t=(n=(new Date).getTime())-(r||n),r=n,s.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:x,"Execution Time":t})),clearTimeout(g.performance.timer),g.performance.timer=setTimeout(g.performance.display,500)},display:function(){var n=m.name+":",t=0;r=!1,clearTimeout(g.performance.timer),e.each(s,function(e,n){t+=n["Execution Time"]}),n+=" "+t+"ms",o&&(n+=" '"+o+"'"),a.length>1&&(n+=" ("+a.length+")"),(console.group!==i||console.table!==i)&&s.length>0&&(console.groupCollapsed(n),console.table?console.table(s):e.each(s,function(e,n){console.log(n.Name+": "+n["Execution Time"]+"ms")}),console.groupEnd()),s=[]}},invoke:function(n,a,o){var r,s,l,c=R;return a=a||u,o=x||o,"string"==typeof n&&c!==i&&(n=n.split(/[\. ]/),r=n.length-1,e.each(n,function(t,a){var o=t!=r?a+n[t+1].charAt(0).toUpperCase()+n[t+1].slice(1):n;if(e.isPlainObject(c[o])&&t!=r)c=c[o];else{if(c[o]!==i)return s=c[o],!1;if(!e.isPlainObject(c[a])||t==r)return c[a]!==i&&(s=c[a],!1);c=c[a]}})),e.isFunction(s)?l=s.apply(o,a):s!==i&&(l=s),e.isArray(t)?t.push(l):t!==i?t=[t,l]:l!==i&&(t=l),s}},c?(R===i&&g.initialize(),g.invoke(l)):(R!==i&&R.invoke("destroy"),g.initialize())}),t!==i?t:this},e.fn.rating.settings={name:"Rating",namespace:"rating",slent:!1,debug:!1,verbose:!1,performance:!0,initialRating:0,interactive:!0,maxRating:4,clearable:"auto",fireOnInit:!1,onRate:function(e){},error:{method:"The method you called is not defined",noMaximum:"No maximum rating specified. Cannot generate HTML automatically"},metadata:{rating:"rating",maxRating:"maxRating"},className:{active:"active",disabled:"disabled",selected:"selected",loading:"loading"},selector:{icon:".icon"},templates:{icon:function(e){for(var n=1,t="";n<=e;)t+='',n++;return t}}}}(jQuery,window,document); -------------------------------------------------------------------------------- /app/templates/admin/departments/departments.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Departments{% endblock %} 5 | {% block head %} 6 | 7 | 8 | 9 | 10 | 36 | 37 | 38 | {% endblock %} 39 | {% block body %} 40 | 41 |
42 |
43 |
44 | 45 |
46 |

48 | Departments 49 |

50 |
51 | 52 | {% if departments %} 53 |
54 |

The following departments are currently present in the database: 55 |

56 |
57 |
58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | {% for department in departments %} 72 | 73 | 74 | 75 | 82 | 87 | 92 | 93 | {% endfor %} 94 | 95 |
NameDescriptionEmployee CountEditDelete
{{ department.name }} {{ department.description }} 76 | {% if department.employees %} 77 | {{ department.employees.count() }} 78 | {% else %} 79 | 0 80 | {% endif %} 81 | 83 | 84 | Edit 85 | 86 | 88 | 89 | Delete 90 | 91 |
96 |
97 | {% else %} 98 |
99 |

No departments have been added.

100 |
101 |
102 | {% endif %} 103 | 109 | 110 | 111 | {% with messages = get_flashed_messages(category_filter=["success"]) %} 112 | {% if messages %} 113 | 120 | {% endif %} 121 | {% endwith %} 122 | 123 | 124 | {% with messages = get_flashed_messages(category_filter=["error"]) %} 125 | {% if messages %} 126 | 133 | {% endif %} 134 | {% endwith %} 135 |
136 |
137 |
138 | 139 | {% endblock %} 140 | 141 | {% block javascript %} 142 | 143 | {% endblock %} -------------------------------------------------------------------------------- /app/templates/admin/roles/roles.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "base.html" %} 4 | {% block title %}Roles{% endblock %} 5 | {% block head %} 6 | 7 | 8 | 9 | 10 | 11 | 12 | 37 | 38 | 39 | {% endblock %} 40 | {% block body %} 41 | 42 |
43 |
44 |
45 | 46 |
47 |

49 | Roles 50 |

51 |
52 | 53 | {% if roles %} 54 |
55 |

The following roles are currently present in the database: 56 |

57 |
58 |
59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | {% for role in roles %} 73 | 74 | 75 | 76 | 83 | 88 | 93 | 94 | {% endfor %} 95 | 96 |
NameDescriptionEmployee CountEditDelete
{{ role.name }} {{ role.description }} 77 | {% if role.employees %} 78 | {{ role.employees.count() }} 79 | {% else %} 80 | 0 81 | {% endif %} 82 | 84 | 85 | Edit 86 | 87 | 89 | 90 | Delete 91 | 92 |
97 |
98 | {% else %} 99 |
100 |

No roles have been added.

101 |
102 |
103 | {% endif %} 104 | 110 | 111 | 112 | {% with messages = get_flashed_messages(category_filter=["success"]) %} 113 | {% if messages %} 114 | 121 | {% endif %} 122 | {% endwith %} 123 | 124 | 125 | {% with messages = get_flashed_messages(category_filter=["error"]) %} 126 | {% if messages %} 127 | 134 | {% endif %} 135 | {% endwith %} 136 |
137 |
138 |
139 | 140 | {% endblock %} 141 | 142 | {% block javascript %} 143 | 144 | {% endblock %} -------------------------------------------------------------------------------- /app/static/semantic/components/ad.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Ad 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Copyright 2013 Contributors 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */ 11 | 12 | 13 | /******************************* 14 | Advertisement 15 | *******************************/ 16 | 17 | .ui.ad { 18 | display: block; 19 | overflow: hidden; 20 | margin: 1em 0em; 21 | } 22 | .ui.ad:first-child { 23 | margin: 0em; 24 | } 25 | .ui.ad:last-child { 26 | margin: 0em; 27 | } 28 | .ui.ad iframe { 29 | margin: 0em; 30 | padding: 0em; 31 | border: none; 32 | overflow: hidden; 33 | } 34 | 35 | /*-------------- 36 | Common 37 | ---------------*/ 38 | 39 | 40 | /* Leaderboard */ 41 | .ui.leaderboard.ad { 42 | width: 728px; 43 | height: 90px; 44 | } 45 | 46 | /* Medium Rectangle */ 47 | .ui[class*="medium rectangle"].ad { 48 | width: 300px; 49 | height: 250px; 50 | } 51 | 52 | /* Large Rectangle */ 53 | .ui[class*="large rectangle"].ad { 54 | width: 336px; 55 | height: 280px; 56 | } 57 | 58 | /* Half Page */ 59 | .ui[class*="half page"].ad { 60 | width: 300px; 61 | height: 600px; 62 | } 63 | 64 | /*-------------- 65 | Square 66 | ---------------*/ 67 | 68 | 69 | /* Square */ 70 | .ui.square.ad { 71 | width: 250px; 72 | height: 250px; 73 | } 74 | 75 | /* Small Square */ 76 | .ui[class*="small square"].ad { 77 | width: 200px; 78 | height: 200px; 79 | } 80 | 81 | /*-------------- 82 | Rectangle 83 | ---------------*/ 84 | 85 | 86 | /* Small Rectangle */ 87 | .ui[class*="small rectangle"].ad { 88 | width: 180px; 89 | height: 150px; 90 | } 91 | 92 | /* Vertical Rectangle */ 93 | .ui[class*="vertical rectangle"].ad { 94 | width: 240px; 95 | height: 400px; 96 | } 97 | 98 | /*-------------- 99 | Button 100 | ---------------*/ 101 | 102 | .ui.button.ad { 103 | width: 120px; 104 | height: 90px; 105 | } 106 | .ui[class*="square button"].ad { 107 | width: 125px; 108 | height: 125px; 109 | } 110 | .ui[class*="small button"].ad { 111 | width: 120px; 112 | height: 60px; 113 | } 114 | 115 | /*-------------- 116 | Skyscrapers 117 | ---------------*/ 118 | 119 | 120 | /* Skyscraper */ 121 | .ui.skyscraper.ad { 122 | width: 120px; 123 | height: 600px; 124 | } 125 | 126 | /* Wide Skyscraper */ 127 | .ui[class*="wide skyscraper"].ad { 128 | width: 160px; 129 | } 130 | 131 | /*-------------- 132 | Banners 133 | ---------------*/ 134 | 135 | 136 | /* Banner */ 137 | .ui.banner.ad { 138 | width: 468px; 139 | height: 60px; 140 | } 141 | 142 | /* Vertical Banner */ 143 | .ui[class*="vertical banner"].ad { 144 | width: 120px; 145 | height: 240px; 146 | } 147 | 148 | /* Top Banner */ 149 | .ui[class*="top banner"].ad { 150 | width: 930px; 151 | height: 180px; 152 | } 153 | 154 | /* Half Banner */ 155 | .ui[class*="half banner"].ad { 156 | width: 234px; 157 | height: 60px; 158 | } 159 | 160 | /*-------------- 161 | Boards 162 | ---------------*/ 163 | 164 | 165 | /* Leaderboard */ 166 | .ui[class*="large leaderboard"].ad { 167 | width: 970px; 168 | height: 90px; 169 | } 170 | 171 | /* Billboard */ 172 | .ui.billboard.ad { 173 | width: 970px; 174 | height: 250px; 175 | } 176 | 177 | /*-------------- 178 | Panorama 179 | ---------------*/ 180 | 181 | 182 | /* Panorama */ 183 | .ui.panorama.ad { 184 | width: 980px; 185 | height: 120px; 186 | } 187 | 188 | /*-------------- 189 | Netboard 190 | ---------------*/ 191 | 192 | 193 | /* Netboard */ 194 | .ui.netboard.ad { 195 | width: 580px; 196 | height: 400px; 197 | } 198 | 199 | /*-------------- 200 | Mobile 201 | ---------------*/ 202 | 203 | 204 | /* Large Mobile Banner */ 205 | .ui[class*="large mobile banner"].ad { 206 | width: 320px; 207 | height: 100px; 208 | } 209 | 210 | /* Mobile Leaderboard */ 211 | .ui[class*="mobile leaderboard"].ad { 212 | width: 320px; 213 | height: 50px; 214 | } 215 | 216 | 217 | /******************************* 218 | Types 219 | *******************************/ 220 | 221 | 222 | /* Mobile Sizes */ 223 | .ui.mobile.ad { 224 | display: none; 225 | } 226 | @media only screen and (max-width: 767px) { 227 | .ui.mobile.ad { 228 | display: block; 229 | } 230 | } 231 | 232 | 233 | /******************************* 234 | Variations 235 | *******************************/ 236 | 237 | .ui.centered.ad { 238 | margin-left: auto; 239 | margin-right: auto; 240 | } 241 | .ui.test.ad { 242 | position: relative; 243 | background: #545454; 244 | } 245 | .ui.test.ad:after { 246 | position: absolute; 247 | top: 50%; 248 | left: 50%; 249 | width: 100%; 250 | text-align: center; 251 | -webkit-transform: translateX(-50%) translateY(-50%); 252 | transform: translateX(-50%) translateY(-50%); 253 | content: 'Ad'; 254 | color: #FFFFFF; 255 | font-size: 1em; 256 | font-weight: bold; 257 | } 258 | .ui.mobile.test.ad:after { 259 | font-size: 0.85714286em; 260 | } 261 | .ui.test.ad[data-text]:after { 262 | content: attr(data-text); 263 | } 264 | 265 | 266 | /******************************* 267 | Theme Overrides 268 | *******************************/ 269 | 270 | 271 | 272 | /******************************* 273 | User Variable Overrides 274 | *******************************/ 275 | 276 | -------------------------------------------------------------------------------- /app/static/semantic/components/nag.min.js: -------------------------------------------------------------------------------- 1 | !function(e,o,t,n){"use strict";o=void 0!==o&&o.Math==Math?o:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")(),e.fn.nag=function(t){var i,s=e(this),a=s.selector||"",r=(new Date).getTime(),l=[],c=arguments[0],g="string"==typeof c,u=[].slice.call(arguments,1);return s.each(function(){var s,d=e.isPlainObject(t)?e.extend(!0,{},e.fn.nag.settings,t):e.extend({},e.fn.nag.settings),m=(d.className,d.selector),f=d.error,p=d.namespace,h="."+p,b=p+"-module",v=e(this),y=(v.find(m.close),d.context?e(d.context):e("body")),k=this,S=v.data(b);o.requestAnimationFrame||o.mozRequestAnimationFrame||o.webkitRequestAnimationFrame||o.msRequestAnimationFrame;s={initialize:function(){s.verbose("Initializing element"),v.on("click"+h,m.close,s.dismiss).data(b,s),d.detachable&&v.parent()[0]!==y[0]&&v.detach().prependTo(y),d.displayTime>0&&setTimeout(s.hide,d.displayTime),s.show()},destroy:function(){s.verbose("Destroying instance"),v.removeData(b).off(h)},show:function(){s.should.show()&&!v.is(":visible")&&(s.debug("Showing nag",d.animation.show),"fade"==d.animation.show?v.fadeIn(d.duration,d.easing):v.slideDown(d.duration,d.easing))},hide:function(){s.debug("Showing nag",d.animation.hide),"fade"==d.animation.show?v.fadeIn(d.duration,d.easing):v.slideUp(d.duration,d.easing)},onHide:function(){s.debug("Removing nag",d.animation.hide),v.remove(),d.onHide&&d.onHide()},dismiss:function(e){d.storageMethod&&s.storage.set(d.key,d.value),s.hide(),e.stopImmediatePropagation(),e.preventDefault()},should:{show:function(){return d.persist?(s.debug("Persistent nag is set, can show nag"),!0):s.storage.get(d.key)!=d.value.toString()?(s.debug("Stored value is not set, can show nag",s.storage.get(d.key)),!0):(s.debug("Stored value is set, cannot show nag",s.storage.get(d.key)),!1)}},get:{storageOptions:function(){var e={};return d.expires&&(e.expires=d.expires),d.domain&&(e.domain=d.domain),d.path&&(e.path=d.path),e}},clear:function(){s.storage.remove(d.key)},storage:{set:function(t,i){var a=s.get.storageOptions();if("localstorage"==d.storageMethod&&o.localStorage!==n)o.localStorage.setItem(t,i),s.debug("Value stored using local storage",t,i);else if("sessionstorage"==d.storageMethod&&o.sessionStorage!==n)o.sessionStorage.setItem(t,i),s.debug("Value stored using session storage",t,i);else{if(e.cookie===n)return void s.error(f.noCookieStorage);e.cookie(t,i,a),s.debug("Value stored using cookie",t,i,a)}},get:function(t,i){var a;return"localstorage"==d.storageMethod&&o.localStorage!==n?a=o.localStorage.getItem(t):"sessionstorage"==d.storageMethod&&o.sessionStorage!==n?a=o.sessionStorage.getItem(t):e.cookie!==n?a=e.cookie(t):s.error(f.noCookieStorage),"undefined"!=a&&"null"!=a&&a!==n&&null!==a||(a=n),a},remove:function(t){var i=s.get.storageOptions();"localstorage"==d.storageMethod&&o.localStorage!==n?o.localStorage.removeItem(t):"sessionstorage"==d.storageMethod&&o.sessionStorage!==n?o.sessionStorage.removeItem(t):e.cookie!==n?e.removeCookie(t,i):s.error(f.noStorage)}},setting:function(o,t){if(s.debug("Changing setting",o,t),e.isPlainObject(o))e.extend(!0,d,o);else{if(t===n)return d[o];e.isPlainObject(d[o])?e.extend(!0,d[o],t):d[o]=t}},internal:function(o,t){if(e.isPlainObject(o))e.extend(!0,s,o);else{if(t===n)return s[o];s[o]=t}},debug:function(){!d.silent&&d.debug&&(d.performance?s.performance.log(arguments):(s.debug=Function.prototype.bind.call(console.info,console,d.name+":"),s.debug.apply(console,arguments)))},verbose:function(){!d.silent&&d.verbose&&d.debug&&(d.performance?s.performance.log(arguments):(s.verbose=Function.prototype.bind.call(console.info,console,d.name+":"),s.verbose.apply(console,arguments)))},error:function(){d.silent||(s.error=Function.prototype.bind.call(console.error,console,d.name+":"),s.error.apply(console,arguments))},performance:{log:function(e){var o,t;d.performance&&(t=(o=(new Date).getTime())-(r||o),r=o,l.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:k,"Execution Time":t})),clearTimeout(s.performance.timer),s.performance.timer=setTimeout(s.performance.display,500)},display:function(){var o=d.name+":",t=0;r=!1,clearTimeout(s.performance.timer),e.each(l,function(e,o){t+=o["Execution Time"]}),o+=" "+t+"ms",a&&(o+=" '"+a+"'"),(console.group!==n||console.table!==n)&&l.length>0&&(console.groupCollapsed(o),console.table?console.table(l):e.each(l,function(e,o){console.log(o.Name+": "+o["Execution Time"]+"ms")}),console.groupEnd()),l=[]}},invoke:function(o,t,a){var r,l,c,g=S;return t=t||u,a=k||a,"string"==typeof o&&g!==n&&(o=o.split(/[\. ]/),r=o.length-1,e.each(o,function(t,i){var a=t!=r?i+o[t+1].charAt(0).toUpperCase()+o[t+1].slice(1):o;if(e.isPlainObject(g[a])&&t!=r)g=g[a];else{if(g[a]!==n)return l=g[a],!1;if(!e.isPlainObject(g[i])||t==r)return g[i]!==n?(l=g[i],!1):(s.error(f.method,o),!1);g=g[i]}})),e.isFunction(l)?c=l.apply(a,t):l!==n&&(c=l),e.isArray(i)?i.push(c):i!==n?i=[i,c]:c!==n&&(i=c),l}},g?(S===n&&s.initialize(),s.invoke(c)):(S!==n&&S.invoke("destroy"),s.initialize())}),i!==n?i:this},e.fn.nag.settings={name:"Nag",silent:!1,debug:!1,verbose:!1,performance:!0,namespace:"Nag",persist:!1,displayTime:0,animation:{show:"slide",hide:"slide"},context:!1,detachable:!1,expires:30,domain:!1,path:"/",storageMethod:"cookie",key:"nag",value:"dismiss",error:{noCookieStorage:"$.cookie is not included. A storage solution is required.",noStorage:"Neither $.cookie or store is defined. A storage solution is required for storing state",method:"The method you called is not defined."},className:{bottom:"bottom",fixed:"fixed"},selector:{close:".close.icon"},speed:500,easing:"easeOutQuad",onHide:function(){}},e.extend(e.easing,{easeOutQuad:function(e,o,t,n,i){return-n*(o/=i)*(o-2)+t}})}(jQuery,window,document); -------------------------------------------------------------------------------- /app/static/semantic/components/dimmer.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Dimmer 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */ 10 | 11 | 12 | /******************************* 13 | Dimmer 14 | *******************************/ 15 | 16 | .dimmable:not(body) { 17 | position: relative; 18 | } 19 | .ui.dimmer { 20 | display: none; 21 | position: absolute; 22 | top: 0em !important; 23 | left: 0em !important; 24 | width: 100%; 25 | height: 100%; 26 | text-align: center; 27 | vertical-align: middle; 28 | background-color: rgba(0, 0, 0, 0.85); 29 | opacity: 0; 30 | line-height: 1; 31 | -webkit-animation-fill-mode: both; 32 | animation-fill-mode: both; 33 | -webkit-animation-duration: 0.5s; 34 | animation-duration: 0.5s; 35 | -webkit-transition: background-color 0.5s linear; 36 | transition: background-color 0.5s linear; 37 | -webkit-user-select: none; 38 | -moz-user-select: none; 39 | -ms-user-select: none; 40 | user-select: none; 41 | will-change: opacity; 42 | z-index: 1000; 43 | } 44 | 45 | /* Dimmer Content */ 46 | .ui.dimmer > .content { 47 | width: 100%; 48 | height: 100%; 49 | display: table; 50 | -webkit-user-select: text; 51 | -moz-user-select: text; 52 | -ms-user-select: text; 53 | user-select: text; 54 | } 55 | .ui.dimmer > .content > * { 56 | display: table-cell; 57 | vertical-align: middle; 58 | color: #FFFFFF; 59 | } 60 | 61 | /* Loose Coupling */ 62 | .ui.segment > .ui.dimmer { 63 | border-radius: inherit !important; 64 | } 65 | 66 | /* Scrollbars */ 67 | .ui.dimmer:not(.inverted)::-webkit-scrollbar-track { 68 | background: rgba(255, 255, 255, 0.1); 69 | } 70 | .ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb { 71 | background: rgba(255, 255, 255, 0.25); 72 | } 73 | .ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb:window-inactive { 74 | background: rgba(255, 255, 255, 0.15); 75 | } 76 | .ui.dimmer:not(.inverted)::-webkit-scrollbar-thumb:hover { 77 | background: rgba(255, 255, 255, 0.35); 78 | } 79 | 80 | 81 | /******************************* 82 | States 83 | *******************************/ 84 | 85 | .animating.dimmable:not(body), 86 | .dimmed.dimmable:not(body) { 87 | overflow: hidden; 88 | } 89 | .dimmed.dimmable > .ui.animating.dimmer, 90 | .dimmed.dimmable > .ui.visible.dimmer, 91 | .ui.active.dimmer { 92 | display: block; 93 | opacity: 1; 94 | } 95 | .ui.disabled.dimmer { 96 | width: 0 !important; 97 | height: 0 !important; 98 | } 99 | 100 | 101 | /******************************* 102 | Variations 103 | *******************************/ 104 | 105 | 106 | /*-------------- 107 | Page 108 | ---------------*/ 109 | 110 | .ui.page.dimmer { 111 | position: fixed; 112 | -webkit-transform-style: ''; 113 | transform-style: ''; 114 | -webkit-perspective: 2000px; 115 | perspective: 2000px; 116 | -webkit-transform-origin: center center; 117 | transform-origin: center center; 118 | } 119 | body.animating.in.dimmable, 120 | body.dimmed.dimmable { 121 | overflow: hidden; 122 | } 123 | body.dimmable > .dimmer { 124 | position: fixed; 125 | } 126 | 127 | /*-------------- 128 | Blurring 129 | ---------------*/ 130 | 131 | .blurring.dimmable > :not(.dimmer) { 132 | -webkit-filter: blur(0px) grayscale(0); 133 | filter: blur(0px) grayscale(0); 134 | -webkit-transition: 800ms -webkit-filter ease; 135 | transition: 800ms -webkit-filter ease; 136 | transition: 800ms filter ease; 137 | transition: 800ms filter ease, 800ms -webkit-filter ease; 138 | } 139 | .blurring.dimmed.dimmable > :not(.dimmer) { 140 | -webkit-filter: blur(5px) grayscale(0.7); 141 | filter: blur(5px) grayscale(0.7); 142 | } 143 | 144 | /* Dimmer Color */ 145 | .blurring.dimmable > .dimmer { 146 | background-color: rgba(0, 0, 0, 0.6); 147 | } 148 | .blurring.dimmable > .inverted.dimmer { 149 | background-color: rgba(255, 255, 255, 0.6); 150 | } 151 | 152 | /*-------------- 153 | Aligned 154 | ---------------*/ 155 | 156 | .ui.dimmer > .top.aligned.content > * { 157 | vertical-align: top; 158 | } 159 | .ui.dimmer > .bottom.aligned.content > * { 160 | vertical-align: bottom; 161 | } 162 | 163 | /*-------------- 164 | Inverted 165 | ---------------*/ 166 | 167 | .ui.inverted.dimmer { 168 | background-color: rgba(255, 255, 255, 0.85); 169 | } 170 | .ui.inverted.dimmer > .content > * { 171 | color: #FFFFFF; 172 | } 173 | 174 | /*-------------- 175 | Simple 176 | ---------------*/ 177 | 178 | 179 | /* Displays without javascript */ 180 | .ui.simple.dimmer { 181 | display: block; 182 | overflow: hidden; 183 | opacity: 1; 184 | width: 0%; 185 | height: 0%; 186 | z-index: -100; 187 | background-color: rgba(0, 0, 0, 0); 188 | } 189 | .dimmed.dimmable > .ui.simple.dimmer { 190 | overflow: visible; 191 | opacity: 1; 192 | width: 100%; 193 | height: 100%; 194 | background-color: rgba(0, 0, 0, 0.85); 195 | z-index: 1; 196 | } 197 | .ui.simple.inverted.dimmer { 198 | background-color: rgba(255, 255, 255, 0); 199 | } 200 | .dimmed.dimmable > .ui.simple.inverted.dimmer { 201 | background-color: rgba(255, 255, 255, 0.85); 202 | } 203 | 204 | 205 | /******************************* 206 | Theme Overrides 207 | *******************************/ 208 | 209 | 210 | 211 | /******************************* 212 | User Overrides 213 | *******************************/ 214 | 215 | -------------------------------------------------------------------------------- /app/static/semantic/components/reveal.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Reveal 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.reveal{display:inherit;position:relative!important;font-size:0!important}.ui.reveal>.visible.content{position:absolute!important;top:0!important;left:0!important;z-index:3!important;-webkit-transition:all .5s ease .1s;transition:all .5s ease .1s}.ui.reveal>.hidden.content{position:relative!important;z-index:2!important}.ui.active.reveal .visible.content,.ui.reveal:hover .visible.content{z-index:4!important}.ui.slide.reveal{position:relative!important;overflow:hidden!important;white-space:nowrap}.ui.slide.reveal>.content{display:block;width:100%;float:left;margin:0;-webkit-transition:-webkit-transform .5s ease .1s;transition:-webkit-transform .5s ease .1s;transition:transform .5s ease .1s;transition:transform .5s ease .1s,-webkit-transform .5s ease .1s}.ui.slide.reveal>.visible.content{position:relative!important}.ui.slide.reveal>.hidden.content{position:absolute!important;left:0!important;width:100%!important;-webkit-transform:translateX(100%)!important;transform:translateX(100%)!important}.ui.slide.active.reveal>.visible.content,.ui.slide.reveal:hover>.visible.content{-webkit-transform:translateX(-100%)!important;transform:translateX(-100%)!important}.ui.slide.active.reveal>.hidden.content,.ui.slide.reveal:hover>.hidden.content{-webkit-transform:translateX(0)!important;transform:translateX(0)!important}.ui.slide.right.reveal>.visible.content{-webkit-transform:translateX(0)!important;transform:translateX(0)!important}.ui.slide.right.reveal>.hidden.content{-webkit-transform:translateX(-100%)!important;transform:translateX(-100%)!important}.ui.slide.right.active.reveal>.visible.content,.ui.slide.right.reveal:hover>.visible.content{-webkit-transform:translateX(100%)!important;transform:translateX(100%)!important}.ui.slide.right.active.reveal>.hidden.content,.ui.slide.right.reveal:hover>.hidden.content{-webkit-transform:translateX(0)!important;transform:translateX(0)!important}.ui.slide.up.reveal>.hidden.content{-webkit-transform:translateY(100%)!important;transform:translateY(100%)!important}.ui.slide.up.active.reveal>.visible.content,.ui.slide.up.reveal:hover>.visible.content{-webkit-transform:translateY(-100%)!important;transform:translateY(-100%)!important}.ui.slide.up.active.reveal>.hidden.content,.ui.slide.up.reveal:hover>.hidden.content{-webkit-transform:translateY(0)!important;transform:translateY(0)!important}.ui.slide.down.reveal>.hidden.content{-webkit-transform:translateY(-100%)!important;transform:translateY(-100%)!important}.ui.slide.down.active.reveal>.visible.content,.ui.slide.down.reveal:hover>.visible.content{-webkit-transform:translateY(100%)!important;transform:translateY(100%)!important}.ui.slide.down.active.reveal>.hidden.content,.ui.slide.down.reveal:hover>.hidden.content{-webkit-transform:translateY(0)!important;transform:translateY(0)!important}.ui.fade.reveal>.visible.content{opacity:1}.ui.fade.active.reveal>.visible.content,.ui.fade.reveal:hover>.visible.content{opacity:0}.ui.move.reveal{position:relative!important;overflow:hidden!important;white-space:nowrap}.ui.move.reveal>.content{display:block;float:left;margin:0;-webkit-transition:-webkit-transform .5s cubic-bezier(.175,.885,.32,1) .1s;transition:-webkit-transform .5s cubic-bezier(.175,.885,.32,1) .1s;transition:transform .5s cubic-bezier(.175,.885,.32,1) .1s;transition:transform .5s cubic-bezier(.175,.885,.32,1) .1s,-webkit-transform .5s cubic-bezier(.175,.885,.32,1) .1s}.ui.move.reveal>.visible.content{position:relative!important}.ui.move.reveal>.hidden.content{position:absolute!important;left:0!important;width:100%!important}.ui.move.active.reveal>.visible.content,.ui.move.reveal:hover>.visible.content{-webkit-transform:translateX(-100%)!important;transform:translateX(-100%)!important}.ui.move.right.active.reveal>.visible.content,.ui.move.right.reveal:hover>.visible.content{-webkit-transform:translateX(100%)!important;transform:translateX(100%)!important}.ui.move.up.active.reveal>.visible.content,.ui.move.up.reveal:hover>.visible.content{-webkit-transform:translateY(-100%)!important;transform:translateY(-100%)!important}.ui.move.down.active.reveal>.visible.content,.ui.move.down.reveal:hover>.visible.content{-webkit-transform:translateY(100%)!important;transform:translateY(100%)!important}.ui.rotate.reveal>.visible.content{-webkit-transition-duration:.5s;transition-duration:.5s;-webkit-transform:rotate(0);transform:rotate(0)}.ui.rotate.reveal>.visible.content,.ui.rotate.right.reveal>.visible.content{-webkit-transform-origin:bottom right;transform-origin:bottom right}.ui.rotate.active.reveal>.visible.content,.ui.rotate.reveal:hover>.visible.content,.ui.rotate.right.active.reveal>.visible.content,.ui.rotate.right.reveal:hover>.visible.content{-webkit-transform:rotate(110deg);transform:rotate(110deg)}.ui.rotate.left.reveal>.visible.content{-webkit-transform-origin:bottom left;transform-origin:bottom left}.ui.rotate.left.active.reveal>.visible.content,.ui.rotate.left.reveal:hover>.visible.content{-webkit-transform:rotate(-110deg);transform:rotate(-110deg)}.ui.disabled.reveal:hover>.visible.visible.content{position:static!important;display:block!important;opacity:1!important;top:0!important;left:0!important;right:auto!important;bottom:auto!important;-webkit-transform:none!important;transform:none!important}.ui.disabled.reveal:hover>.hidden.hidden.content{display:none!important}.ui.reveal>.ui.ribbon.label{z-index:5}.ui.visible.reveal{overflow:visible}.ui.instant.reveal>.content{-webkit-transition-delay:0s!important;transition-delay:0s!important}.ui.reveal>.content{font-size:1rem!important} -------------------------------------------------------------------------------- /app/static/semantic/components/visit.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.0.0 - Visit 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Copyright 2015 Contributors 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */ 11 | !function(e,t,i,n){"use strict";e.visit=e.fn.visit=function(i){var o,r=e(e.isFunction(this)?t:this),s=r.selector||"",a=(new Date).getTime(),c=[],u=arguments[0],l="string"==typeof u,d=[].slice.call(arguments,1);return r.each(function(){var g,m=e.isPlainObject(i)?e.extend(!0,{},e.fn.visit.settings,i):e.extend({},e.fn.visit.settings),f=m.error,p=m.namespace,v=p+"-module",h=e(this),b=e(),y=this,k=h.data(v);g={initialize:function(){m.count?g.store(m.key.count,m.count):m.id?g.add.id(m.id):m.increment&&"increment"!==l&&g.increment(),g.add.display(h),g.instantiate()},instantiate:function(){g.verbose("Storing instance of visit module",g),k=g,h.data(v,g)},destroy:function(){g.verbose("Destroying instance"),h.removeData(v)},increment:function(e){var t=g.get.count(),i=+t+1;e?g.add.id(e):(i>m.limit&&!m.surpass&&(i=m.limit),g.debug("Incrementing visits",i),g.store(m.key.count,i))},decrement:function(e){var t=g.get.count(),i=+t-1;e?g.remove.id(e):(g.debug("Removing visit"),g.store(m.key.count,i))},get:{count:function(){return+g.retrieve(m.key.count)||0},idCount:function(e){return e=e||g.get.ids(),e.length},ids:function(e){var t=[];return e=e||g.retrieve(m.key.ids),"string"==typeof e&&(t=e.split(m.delimiter)),g.verbose("Found visited ID list",t),t},storageOptions:function(e){var t={};return m.expires&&(t.expires=m.expires),m.domain&&(t.domain=m.domain),m.path&&(t.path=m.path),t}},has:{visited:function(t,i){var o=!1;return i=i||g.get.ids(),t!==n&&i&&e.each(i,function(e,i){i==t&&(o=!0)}),o}},set:{count:function(e){g.store(m.key.count,e)},ids:function(e){g.store(m.key.ids,e)}},reset:function(){g.store(m.key.count,0),g.store(m.key.ids,null)},add:{id:function(e){var t=g.retrieve(m.key.ids),i=t===n||""===t?e:t+m.delimiter+e;g.has.visited(e)?g.debug("Unique content already visited, not adding visit",e,t):e===n?g.debug("ID is not defined"):(g.debug("Adding visit to unique content",e),g.store(m.key.ids,i)),g.set.count(g.get.idCount())},display:function(t){var i=e(t);i.length>0&&!e.isWindow(i[0])&&(g.debug("Updating visit count for element",i),b=b.length>0?b.add(i):i)}},remove:{id:function(t){var i=g.get.ids(),o=[];t!==n&&i!==n&&(g.debug("Removing visit to unique content",t,i),e.each(i,function(e,i){i!==t&&o.push(i)}),o=o.join(m.delimiter),g.store(m.key.ids,o)),g.set.count(g.get.idCount())}},check:{limit:function(e){e=e||g.get.count(),m.limit&&(e>=m.limit&&(g.debug("Pages viewed exceeded limit, firing callback",e,m.limit),m.onLimit.call(y,e)),g.debug("Limit not reached",e,m.limit),m.onChange.call(y,e)),g.update.display(e)}},update:{display:function(e){e=e||g.get.count(),b.length>0&&(g.debug("Updating displayed view count",b),b.html(e))}},store:function(i,o){var r=g.get.storageOptions(o);if("localstorage"==m.storageMethod&&t.localStorage!==n)t.localStorage.setItem(i,o),g.debug("Value stored using local storage",i,o);else{if(e.cookie===n)return void g.error(f.noCookieStorage);e.cookie(i,o,r),g.debug("Value stored using cookie",i,o,r)}i==m.key.count&&g.check.limit(o)},retrieve:function(i,o){var r;return"localstorage"==m.storageMethod&&t.localStorage!==n?r=t.localStorage.getItem(i):e.cookie!==n?r=e.cookie(i):g.error(f.noCookieStorage),("undefined"==r||"null"==r||r===n||null===r)&&(r=n),r},setting:function(t,i){if(e.isPlainObject(t))e.extend(!0,m,t);else{if(i===n)return m[t];m[t]=i}},internal:function(t,i){return g.debug("Changing internal",t,i),i===n?g[t]:void(e.isPlainObject(t)?e.extend(!0,g,t):g[t]=i)},debug:function(){m.debug&&(m.performance?g.performance.log(arguments):(g.debug=Function.prototype.bind.call(console.info,console,m.name+":"),g.debug.apply(console,arguments)))},verbose:function(){m.verbose&&m.debug&&(m.performance?g.performance.log(arguments):(g.verbose=Function.prototype.bind.call(console.info,console,m.name+":"),g.verbose.apply(console,arguments)))},error:function(){g.error=Function.prototype.bind.call(console.error,console,m.name+":"),g.error.apply(console,arguments)},performance:{log:function(e){var t,i,n;m.performance&&(t=(new Date).getTime(),n=a||t,i=t-n,a=t,c.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:y,"Execution Time":i})),clearTimeout(g.performance.timer),g.performance.timer=setTimeout(g.performance.display,500)},display:function(){var t=m.name+":",i=0;a=!1,clearTimeout(g.performance.timer),e.each(c,function(e,t){i+=t["Execution Time"]}),t+=" "+i+"ms",s&&(t+=" '"+s+"'"),r.length>1&&(t+=" ("+r.length+")"),(console.group!==n||console.table!==n)&&c.length>0&&(console.groupCollapsed(t),console.table?console.table(c):e.each(c,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),c=[]}},invoke:function(t,i,r){var s,a,c,u=k;return i=i||d,r=y||r,"string"==typeof t&&u!==n&&(t=t.split(/[\. ]/),s=t.length-1,e.each(t,function(i,o){var r=i!=s?o+t[i+1].charAt(0).toUpperCase()+t[i+1].slice(1):t;if(e.isPlainObject(u[r])&&i!=s)u=u[r];else{if(u[r]!==n)return a=u[r],!1;if(!e.isPlainObject(u[o])||i==s)return u[o]!==n?(a=u[o],!1):!1;u=u[o]}})),e.isFunction(a)?c=a.apply(r,i):a!==n&&(c=a),e.isArray(o)?o.push(c):o!==n?o=[o,c]:c!==n&&(o=c),a}},l?(k===n&&g.initialize(),g.invoke(u)):(k!==n&&k.invoke("destroy"),g.initialize())}),o!==n?o:this},e.fn.visit.settings={name:"Visit",debug:!1,verbose:!1,performance:!0,namespace:"visit",increment:!1,surpass:!1,count:!1,limit:!1,delimiter:"&",storageMethod:"localstorage",key:{count:"visit-count",ids:"visit-ids"},expires:30,domain:!1,path:"/",onLimit:function(){},onChange:function(){},error:{method:"The method you called is not defined",missingPersist:"Using the persist setting requires the inclusion of PersistJS",noCookieStorage:"The default storage cookie requires $.cookie to be included."}}}(jQuery,window,document); -------------------------------------------------------------------------------- /app/static/semantic/components/item.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Item 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.items>.item{display:-webkit-box;display:-ms-flexbox;display:flex;margin:1em 0;width:100%;min-height:0;background:0 0;padding:0;border:none;border-radius:0;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:-webkit-box-shadow .1s ease;transition:-webkit-box-shadow .1s ease;transition:box-shadow .1s ease;transition:box-shadow .1s ease,-webkit-box-shadow .1s ease;z-index:''}.ui.items>.item a{cursor:pointer}.ui.items{margin:1.5em 0}.ui.items:first-child{margin-top:0!important}.ui.items:last-child{margin-bottom:0!important}.ui.items>.item:after{display:block;content:' ';height:0;clear:both;overflow:hidden;visibility:hidden}.ui.items>.item:first-child{margin-top:0}.ui.items>.item:last-child{margin-bottom:0}.ui.items>.item>.image{position:relative;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;display:block;float:none;margin:0;padding:0;max-height:'';-ms-flex-item-align:top;align-self:top}.ui.items>.item>.image>img{display:block;width:100%;height:auto;border-radius:.125rem;border:none}.ui.items>.item>.image:only-child>img{border-radius:0}.ui.items>.item>.content{display:block;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;background:0 0;margin:0;padding:0;-webkit-box-shadow:none;box-shadow:none;font-size:1em;border:none;border-radius:0}.ui.items>.item>.content:after{display:block;content:' ';height:0;clear:both;overflow:hidden;visibility:hidden}.ui.items>.item>.image+.content{min-width:0;width:auto;display:block;margin-left:0;-ms-flex-item-align:top;align-self:top;padding-left:1.5em}.ui.items>.item>.content>.header{display:inline-block;margin:-.21425em 0 0;font-family:Lato,'Helvetica Neue',Arial,Helvetica,sans-serif;font-weight:700;color:rgba(0,0,0,.85)}.ui.items>.item>.content>.header:not(.ui){font-size:1.28571429em}.ui.items>.item [class*="left floated"]{float:left}.ui.items>.item [class*="right floated"]{float:right}.ui.items>.item .content img{-ms-flex-item-align:middle;align-self:middle;width:''}.ui.items>.item .avatar img,.ui.items>.item img.avatar{width:'';height:'';border-radius:500rem}.ui.items>.item>.content>.description{margin-top:.6em;max-width:auto;font-size:1em;line-height:1.4285em;color:rgba(0,0,0,.87)}.ui.items>.item>.content p{margin:0 0 .5em}.ui.items>.item>.content p:last-child{margin-bottom:0}.ui.items>.item .meta{margin:.5em 0 .5em;font-size:1em;line-height:1em;color:rgba(0,0,0,.6)}.ui.items>.item .meta *{margin-right:.3em}.ui.items>.item .meta :last-child{margin-right:0}.ui.items>.item .meta [class*="right floated"]{margin-right:0;margin-left:.3em}.ui.items>.item>.content a:not(.ui){color:'';-webkit-transition:color .1s ease;transition:color .1s ease}.ui.items>.item>.content a:not(.ui):hover{color:''}.ui.items>.item>.content>a.header{color:rgba(0,0,0,.85)}.ui.items>.item>.content>a.header:hover{color:#1e70bf}.ui.items>.item .meta>a:not(.ui){color:rgba(0,0,0,.4)}.ui.items>.item .meta>a:not(.ui):hover{color:rgba(0,0,0,.87)}.ui.items>.item>.content .favorite.icon{cursor:pointer;opacity:.75;-webkit-transition:color .1s ease;transition:color .1s ease}.ui.items>.item>.content .favorite.icon:hover{opacity:1;color:#ffb70a}.ui.items>.item>.content .active.favorite.icon{color:#ffe623}.ui.items>.item>.content .like.icon{cursor:pointer;opacity:.75;-webkit-transition:color .1s ease;transition:color .1s ease}.ui.items>.item>.content .like.icon:hover{opacity:1;color:#ff2733}.ui.items>.item>.content .active.like.icon{color:#ff2733}.ui.items>.item .extra{display:block;position:relative;background:0 0;margin:.5rem 0 0;width:100%;padding:0 0 0;top:0;left:0;color:rgba(0,0,0,.4);-webkit-box-shadow:none;box-shadow:none;-webkit-transition:color .1s ease;transition:color .1s ease;border-top:none}.ui.items>.item .extra>*{margin:.25rem .5rem .25rem 0}.ui.items>.item .extra>[class*="right floated"]{margin:.25rem 0 .25rem .5rem}.ui.items>.item .extra:after{display:block;content:' ';height:0;clear:both;overflow:hidden;visibility:hidden}.ui.items>.item>.image:not(.ui){width:175px}@media only screen and (min-width:768px) and (max-width:991px){.ui.items>.item{margin:1em 0}.ui.items>.item>.image:not(.ui){width:150px}.ui.items>.item>.image+.content{display:block;padding:0 0 0 1em}}@media only screen and (max-width:767px){.ui.items:not(.unstackable)>.item{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:2em 0}.ui.items:not(.unstackable)>.item>.image{display:block;margin-left:auto;margin-right:auto}.ui.items:not(.unstackable)>.item>.image,.ui.items:not(.unstackable)>.item>.image>img{max-width:100%!important;width:auto!important;max-height:250px!important}.ui.items:not(.unstackable)>.item>.image+.content{display:block;padding:1.5em 0 0}}.ui.items>.item>.image+[class*="top aligned"].content{-ms-flex-item-align:start;align-self:flex-start}.ui.items>.item>.image+[class*="middle aligned"].content{-ms-flex-item-align:center;align-self:center}.ui.items>.item>.image+[class*="bottom aligned"].content{-ms-flex-item-align:end;align-self:flex-end}.ui.relaxed.items>.item{margin:1.5em 0}.ui[class*="very relaxed"].items>.item{margin:2em 0}.ui.divided.items>.item{border-top:1px solid rgba(34,36,38,.15);margin:0;padding:1em 0}.ui.divided.items>.item:first-child{border-top:none;margin-top:0!important;padding-top:0!important}.ui.divided.items>.item:last-child{margin-bottom:0!important;padding-bottom:0!important}.ui.relaxed.divided.items>.item{margin:0;padding:1.5em 0}.ui[class*="very relaxed"].divided.items>.item{margin:0;padding:2em 0}.ui.items a.item:hover,.ui.link.items>.item:hover{cursor:pointer}.ui.items a.item:hover .content .header,.ui.link.items>.item:hover .content .header{color:#1e70bf}.ui.items>.item{font-size:1em}@media only screen and (max-width:767px){.ui.unstackable.items>.item>.image,.ui.unstackable.items>.item>.image>img{width:125px!important}} -------------------------------------------------------------------------------- /app/static/semantic/components/site.min.js: -------------------------------------------------------------------------------- 1 | !function(e,n,o,i){e.site=e.fn.site=function(t){var s,r,a=(new Date).getTime(),c=[],l=arguments[0],u="string"==typeof l,m=[].slice.call(arguments,1),d=e.isPlainObject(t)?e.extend(!0,{},e.site.settings,t):e.extend({},e.site.settings),g=d.namespace,f=d.error,b="module-"+g,p=e(o),v=this,h=p.data(b);return s={initialize:function(){s.instantiate()},instantiate:function(){s.verbose("Storing instance of site",s),h=s,p.data(b,s)},normalize:function(){s.fix.console(),s.fix.requestAnimationFrame()},fix:{console:function(){s.debug("Normalizing window.console"),console!==i&&console.log!==i||(s.verbose("Console not available, normalizing events"),s.disable.console()),void 0!==console.group&&void 0!==console.groupEnd&&void 0!==console.groupCollapsed||(s.verbose("Console group not available, normalizing events"),n.console.group=function(){},n.console.groupEnd=function(){},n.console.groupCollapsed=function(){}),void 0===console.markTimeline&&(s.verbose("Mark timeline not available, normalizing events"),n.console.markTimeline=function(){})},consoleClear:function(){s.debug("Disabling programmatic console clearing"),n.console.clear=function(){}},requestAnimationFrame:function(){s.debug("Normalizing requestAnimationFrame"),n.requestAnimationFrame===i&&(s.debug("RequestAnimationFrame not available, normalizing event"),n.requestAnimationFrame=n.requestAnimationFrame||n.mozRequestAnimationFrame||n.webkitRequestAnimationFrame||n.msRequestAnimationFrame||function(e){setTimeout(e,0)})}},moduleExists:function(n){return e.fn[n]!==i&&e.fn[n].settings!==i},enabled:{modules:function(n){var o=[];return n=n||d.modules,e.each(n,function(e,n){s.moduleExists(n)&&o.push(n)}),o}},disabled:{modules:function(n){var o=[];return n=n||d.modules,e.each(n,function(e,n){s.moduleExists(n)||o.push(n)}),o}},change:{setting:function(n,o,t,r){t="string"==typeof t?"all"===t?d.modules:[t]:t||d.modules,r=r===i||r,e.each(t,function(i,t){var a,c=!s.moduleExists(t)||(e.fn[t].settings.namespace||!1);s.moduleExists(t)&&(s.verbose("Changing default setting",n,o,t),e.fn[t].settings[n]=o,r&&c&&(a=e(":data(module-"+c+")")).length>0&&(s.verbose("Modifying existing settings",a),a[t]("setting",n,o)))})},settings:function(n,o,t){o="string"==typeof o?[o]:o||d.modules,t=t===i||t,e.each(o,function(o,i){var r;s.moduleExists(i)&&(s.verbose("Changing default setting",n,i),e.extend(!0,e.fn[i].settings,n),t&&g&&(r=e(":data(module-"+g+")")).length>0&&(s.verbose("Modifying existing settings",r),r[i]("setting",n)))})}},enable:{console:function(){s.console(!0)},debug:function(e,n){e=e||d.modules,s.debug("Enabling debug for modules",e),s.change.setting("debug",!0,e,n)},verbose:function(e,n){e=e||d.modules,s.debug("Enabling verbose debug for modules",e),s.change.setting("verbose",!0,e,n)}},disable:{console:function(){s.console(!1)},debug:function(e,n){e=e||d.modules,s.debug("Disabling debug for modules",e),s.change.setting("debug",!1,e,n)},verbose:function(e,n){e=e||d.modules,s.debug("Disabling verbose debug for modules",e),s.change.setting("verbose",!1,e,n)}},console:function(e){if(e){if(h.cache.console===i)return void s.error(f.console);s.debug("Restoring console function"),n.console=h.cache.console}else s.debug("Disabling console function"),h.cache.console=n.console,n.console={clear:function(){},error:function(){},group:function(){},groupCollapsed:function(){},groupEnd:function(){},info:function(){},log:function(){},markTimeline:function(){},warn:function(){}}},destroy:function(){s.verbose("Destroying previous site for",p),p.removeData(b)},cache:{},setting:function(n,o){if(e.isPlainObject(n))e.extend(!0,d,n);else{if(o===i)return d[n];d[n]=o}},internal:function(n,o){if(e.isPlainObject(n))e.extend(!0,s,n);else{if(o===i)return s[n];s[n]=o}},debug:function(){d.debug&&(d.performance?s.performance.log(arguments):(s.debug=Function.prototype.bind.call(console.info,console,d.name+":"),s.debug.apply(console,arguments)))},verbose:function(){d.verbose&&d.debug&&(d.performance?s.performance.log(arguments):(s.verbose=Function.prototype.bind.call(console.info,console,d.name+":"),s.verbose.apply(console,arguments)))},error:function(){s.error=Function.prototype.bind.call(console.error,console,d.name+":"),s.error.apply(console,arguments)},performance:{log:function(e){var n,o;d.performance&&(o=(n=(new Date).getTime())-(a||n),a=n,c.push({Element:v,Name:e[0],Arguments:[].slice.call(e,1)||"","Execution Time":o})),clearTimeout(s.performance.timer),s.performance.timer=setTimeout(s.performance.display,500)},display:function(){var n=d.name+":",o=0;a=!1,clearTimeout(s.performance.timer),e.each(c,function(e,n){o+=n["Execution Time"]}),n+=" "+o+"ms",(console.group!==i||console.table!==i)&&c.length>0&&(console.groupCollapsed(n),console.table?console.table(c):e.each(c,function(e,n){console.log(n.Name+": "+n["Execution Time"]+"ms")}),console.groupEnd()),c=[]}},invoke:function(n,o,t){var a,c,l,u=h;return o=o||m,t=v||t,"string"==typeof n&&u!==i&&(n=n.split(/[\. ]/),a=n.length-1,e.each(n,function(o,t){var r=o!=a?t+n[o+1].charAt(0).toUpperCase()+n[o+1].slice(1):n;if(e.isPlainObject(u[r])&&o!=a)u=u[r];else{if(u[r]!==i)return c=u[r],!1;if(!e.isPlainObject(u[t])||o==a)return u[t]!==i?(c=u[t],!1):(s.error(f.method,n),!1);u=u[t]}})),e.isFunction(c)?l=c.apply(t,o):c!==i&&(l=c),e.isArray(r)?r.push(l):r!==i?r=[r,l]:l!==i&&(r=l),c}},u?(h===i&&s.initialize(),s.invoke(l)):(h!==i&&s.destroy(),s.initialize()),r!==i?r:this},e.site.settings={name:"Site",namespace:"site",error:{console:"Console cannot be restored, most likely it was overwritten outside of module",method:"The method you called is not defined."},debug:!1,verbose:!1,performance:!0,modules:["accordion","api","checkbox","dimmer","dropdown","embed","form","modal","nag","popup","rating","shape","sidebar","state","sticky","tab","transition","visit","visibility"],siteNamespace:"site",namespaceStub:{cache:{},config:{},sections:{},section:{},utilities:{}}},e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(n){return function(o){return!!e.data(o,n)}}):function(n,o,i){return!!e.data(n,i[3])}})}(jQuery,window,document); -------------------------------------------------------------------------------- /app/static/semantic/components/divider.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.2.14 - Divider 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Released under the MIT license 7 | * http://opensource.org/licenses/MIT 8 | * 9 | */.ui.divider{margin:1rem 0;line-height:1;height:0;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:rgba(0,0,0,.85);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-tap-highlight-color:transparent}.ui.divider:not(.vertical):not(.horizontal){border-top:1px solid rgba(34,36,38,.15);border-bottom:1px solid rgba(255,255,255,.1)}.ui.grid>.column+.divider,.ui.grid>.row>.column+.divider{left:auto}.ui.horizontal.divider{display:table;white-space:nowrap;height:auto;margin:'';line-height:1;text-align:center}.ui.horizontal.divider:after,.ui.horizontal.divider:before{content:'';display:table-cell;position:relative;top:50%;width:50%;background-repeat:no-repeat}.ui.horizontal.divider:before{background-position:right 1em top 50%}.ui.horizontal.divider:after{background-position:left 1em top 50%}.ui.vertical.divider{position:absolute;z-index:2;top:50%;left:50%;margin:0;padding:0;width:auto;height:50%;line-height:0;text-align:center;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.ui.vertical.divider:after,.ui.vertical.divider:before{position:absolute;left:50%;content:'';z-index:3;border-left:1px solid rgba(34,36,38,.15);border-right:1px solid rgba(255,255,255,.1);width:0%;height:calc(100% - 1rem)}.ui.vertical.divider:before{top:-100%}.ui.vertical.divider:after{top:auto;bottom:0}@media only screen and (max-width:767px){.ui.grid .stackable.row .ui.vertical.divider,.ui.stackable.grid .ui.vertical.divider{display:table;white-space:nowrap;height:auto;margin:'';overflow:hidden;line-height:1;text-align:center;position:static;top:0;left:0;-webkit-transform:none;transform:none}.ui.grid .stackable.row .ui.vertical.divider:after,.ui.grid .stackable.row .ui.vertical.divider:before,.ui.stackable.grid .ui.vertical.divider:after,.ui.stackable.grid .ui.vertical.divider:before{position:static;left:0;border-left:none;border-right:none;content:'';display:table-cell;position:relative;top:50%;width:50%;background-repeat:no-repeat}.ui.grid .stackable.row .ui.vertical.divider:before,.ui.stackable.grid .ui.vertical.divider:before{background-position:right 1em top 50%}.ui.grid .stackable.row .ui.vertical.divider:after,.ui.stackable.grid .ui.vertical.divider:after{background-position:left 1em top 50%}}.ui.divider>.icon{margin:0;font-size:1rem;height:1em;vertical-align:middle}.ui.hidden.divider{border-color:transparent!important}.ui.hidden.divider:after,.ui.hidden.divider:before{display:none}.ui.divider.inverted,.ui.horizontal.inverted.divider,.ui.vertical.inverted.divider{color:#fff}.ui.divider.inverted,.ui.divider.inverted:after,.ui.divider.inverted:before{border-top-color:rgba(34,36,38,.15)!important;border-left-color:rgba(34,36,38,.15)!important;border-bottom-color:rgba(255,255,255,.15)!important;border-right-color:rgba(255,255,255,.15)!important}.ui.fitted.divider{margin:0}.ui.clearing.divider{clear:both}.ui.section.divider{margin-top:2rem;margin-bottom:2rem}.ui.divider{font-size:1rem}.ui.horizontal.divider:after,.ui.horizontal.divider:before{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAACCAYAAACuTHuKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1OThBRDY4OUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1OThBRDY4QUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU5OEFENjg3Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5OEFENjg4Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VU513gAAADVJREFUeNrs0DENACAQBDBIWLGBJQby/mUcJn5sJXQmOQMAAAAAAJqt+2prAAAAAACg2xdgANk6BEVuJgyMAAAAAElFTkSuQmCC)}@media only screen and (max-width:767px){.ui.grid .stackable.row .ui.vertical.divider:after,.ui.grid .stackable.row .ui.vertical.divider:before,.ui.stackable.grid .ui.vertical.divider:after,.ui.stackable.grid .ui.vertical.divider:before{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABaAAAAACCAYAAACuTHuKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyFpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo1OThBRDY4OUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo1OThBRDY4QUNDMTYxMUU0OUE3NUVGOEJDMzMzMjE2NyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjU5OEFENjg3Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3IiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjU5OEFENjg4Q0MxNjExRTQ5QTc1RUY4QkMzMzMyMTY3Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+VU513gAAADVJREFUeNrs0DENACAQBDBIWLGBJQby/mUcJn5sJXQmOQMAAAAAAJqt+2prAAAAAACg2xdgANk6BEVuJgyMAAAAAElFTkSuQmCC)}} -------------------------------------------------------------------------------- /app/static/semantic/components/video.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * # Semantic UI 2.0.0 - Video 3 | * http://github.com/semantic-org/semantic-ui/ 4 | * 5 | * 6 | * Copyright 2014 Contributorss 7 | * Released under the MIT license 8 | * http://opensource.org/licenses/MIT 9 | * 10 | */ 11 | !function(e,o,t,n){"use strict";e.fn.video=function(t){{var a,i=e(this),r=i.selector||"",l=(new Date).getTime(),c=[],u=arguments[0],s="string"==typeof u,m=[].slice.call(arguments,1);o.requestAnimationFrame||o.mozRequestAnimationFrame||o.webkitRequestAnimationFrame||o.msRequestAnimationFrame||function(e){setTimeout(e,0)}}return i.each(function(){var d,p=e.isPlainObject(t)?e.extend(!0,{},e.fn.video.settings,t):e.extend({},e.fn.video.settings),f=p.selector,g=p.className,h=p.error,v=p.metadata,b=p.namespace,y=p.templates,w="."+b,x="module-"+b,F=(e(o),e(this)),C=F.find(f.placeholder),E=F.find(f.playButton),T=F.find(f.embed),A=this,P=F.data(x);d={initialize:function(){d.debug("Initializing video"),d.create(),F.on("click"+w,f.placeholder,d.play).on("click"+w,f.playButton,d.play),d.instantiate()},instantiate:function(){d.verbose("Storing instance of module",d),P=d,F.data(x,d)},create:function(){var e=F.data(v.image),o=y.video(e);F.html(o),d.refresh(),e||d.play(),d.debug("Creating html for video element",o)},destroy:function(){d.verbose("Destroying previous instance of video"),d.reset(),F.removeData(x).off(w)},refresh:function(){d.verbose("Refreshing selector cache"),C=F.find(f.placeholder),E=F.find(f.playButton),T=F.find(f.embed)},change:function(e,o,t){d.debug("Changing video to ",e,o,t),F.data(v.source,e).data(v.id,o).data(v.url,t),p.onChange()},reset:function(){d.debug("Clearing video embed and showing placeholder"),F.removeClass(g.active),T.html(" "),C.show(),p.onReset()},play:function(){d.debug("Playing video");var e=F.data(v.source)||!1,o=F.data(v.url)||!1,t=F.data(v.id)||!1;T.html(d.generate.html(e,t,o)),F.addClass(g.active),p.onPlay()},get:{source:function(e){return"string"!=typeof e?!1:-1!==e.search("youtube.com")?"youtube":-1!==e.search("vimeo.com")?"vimeo":!1},id:function(e){return e.match(p.regExp.youtube)?e.match(p.regExp.youtube)[1]:e.match(p.regExp.vimeo)?e.match(p.regExp.vimeo)[2]:!1}},generate:{html:function(e,o,t){d.debug("Generating embed html");var n;return e=e||p.source,o=o||p.id,e&&o||t?(e&&o||(e=d.get.source(t),o=d.get.id(t)),"vimeo"==e?n='':"youtube"==e&&(n='')):d.error(h.noVideo),n},url:function(e){var o=p.api?1:0,t="auto"===p.autoplay?F.data("image")!==n:p.autoplay,a=p.hd?1:0,i=p.showUI?1:0,r=p.showUI?0:1,l="";return"vimeo"==e&&(l="api="+o+"&title="+i+"&byline="+i+"&portrait="+i+"&autoplay="+t,p.color&&(l+="&color="+p.color)),"ustream"==e?(l="autoplay="+t,p.color&&(l+="&color="+p.color)):"youtube"==e&&(l="enablejsapi="+o+"&autoplay="+t+"&autohide="+r+"&hq="+a+"&modestbranding=1",p.color&&(l+="&color="+p.color)),l}},setting:function(o,t){if(d.debug("Changing setting",o,t),e.isPlainObject(o))e.extend(!0,p,o);else{if(t===n)return p[o];p[o]=t}},internal:function(o,t){if(e.isPlainObject(o))e.extend(!0,d,o);else{if(t===n)return d[o];d[o]=t}},debug:function(){p.debug&&(p.performance?d.performance.log(arguments):(d.debug=Function.prototype.bind.call(console.info,console,p.name+":"),d.debug.apply(console,arguments)))},verbose:function(){p.verbose&&p.debug&&(p.performance?d.performance.log(arguments):(d.verbose=Function.prototype.bind.call(console.info,console,p.name+":"),d.verbose.apply(console,arguments)))},error:function(){d.error=Function.prototype.bind.call(console.error,console,p.name+":"),d.error.apply(console,arguments)},performance:{log:function(e){var o,t,n;p.performance&&(o=(new Date).getTime(),n=l||o,t=o-n,l=o,c.push({Name:e[0],Arguments:[].slice.call(e,1)||"",Element:A,"Execution Time":t})),clearTimeout(d.performance.timer),d.performance.timer=setTimeout(d.performance.display,500)},display:function(){var o=p.name+":",t=0;l=!1,clearTimeout(d.performance.timer),e.each(c,function(e,o){t+=o["Execution Time"]}),o+=" "+t+"ms",r&&(o+=" '"+r+"'"),i.length>1&&(o+=" ("+i.length+")"),(console.group!==n||console.table!==n)&&c.length>0&&(console.groupCollapsed(o),console.table?console.table(c):e.each(c,function(e,o){console.log(o.Name+": "+o["Execution Time"]+"ms")}),console.groupEnd()),c=[]}},invoke:function(o,t,i){var r,l,c,u=P;return t=t||m,i=A||i,"string"==typeof o&&u!==n&&(o=o.split(/[\. ]/),r=o.length-1,e.each(o,function(t,a){var i=t!=r?a+o[t+1].charAt(0).toUpperCase()+o[t+1].slice(1):o;if(e.isPlainObject(u[i])&&t!=r)u=u[i];else{if(u[i]!==n)return l=u[i],!1;if(!e.isPlainObject(u[a])||t==r)return u[a]!==n?(l=u[a],!1):(d.error(h.method,o),!1);u=u[a]}})),e.isFunction(l)?c=l.apply(i,t):l!==n&&(c=l),e.isArray(a)?a.push(c):a!==n?a=[a,c]:c!==n&&(a=c),l}},s?(P===n&&d.initialize(),d.invoke(u)):(P!==n&&P.invoke("destroy"),d.initialize())}),a!==n?a:this},e.fn.video.settings={name:"Video",namespace:"video",debug:!1,verbose:!1,performance:!0,metadata:{id:"id",image:"image",source:"source",url:"url"},source:!1,url:!1,id:!1,aspectRatio:16/9,onPlay:function(){},onReset:function(){},onChange:function(){},onPause:function(){},onStop:function(){},width:"auto",height:"auto",autoplay:"auto",color:"#442359",hd:!0,showUI:!1,api:!0,regExp:{youtube:/^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/,vimeo:/http:\/\/(www\.)?vimeo.com\/(\d+)($|\/)/},error:{noVideo:"No video specified",method:"The method you called is not defined"},className:{active:"active"},selector:{embed:".embed",placeholder:".placeholder",playButton:".play"}},e.fn.video.settings.templates={video:function(e){var o="";return e&&(o+=''),o+='
'}}}(jQuery,window,document); --------------------------------------------------------------------------------