├── .gitignore ├── LICENSE ├── Procfile ├── README.md ├── auth.py ├── create-db.py ├── gmail_flask.py ├── main.py ├── models.py ├── params_central.json ├── readme ├── requirements.txt ├── src ├── analysis_amazon.py ├── analysis_curefit.py ├── analysis_flipkart.py ├── analysis_myntra.py ├── analysis_ola.py ├── analysis_uber.py ├── fetch_uber.py └── utils.py ├── static ├── css │ ├── main.css │ └── util.css ├── fonts │ ├── font-awesome-4.7.0 │ │ ├── HELP-US-OUT.txt │ │ ├── css │ │ │ ├── font-awesome.css │ │ │ └── font-awesome.min.css │ │ ├── fonts │ │ │ ├── FontAwesome.otf │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ └── fontawesome-webfont.woff2 │ │ ├── less │ │ │ ├── animated.less │ │ │ ├── bordered-pulled.less │ │ │ ├── core.less │ │ │ ├── fixed-width.less │ │ │ ├── font-awesome.less │ │ │ ├── icons.less │ │ │ ├── larger.less │ │ │ ├── list.less │ │ │ ├── mixins.less │ │ │ ├── path.less │ │ │ ├── rotated-flipped.less │ │ │ ├── screen-reader.less │ │ │ ├── stacked.less │ │ │ └── variables.less │ │ └── scss │ │ │ ├── _animated.scss │ │ │ ├── _bordered-pulled.scss │ │ │ ├── _core.scss │ │ │ ├── _fixed-width.scss │ │ │ ├── _icons.scss │ │ │ ├── _larger.scss │ │ │ ├── _list.scss │ │ │ ├── _mixins.scss │ │ │ ├── _path.scss │ │ │ ├── _rotated-flipped.scss │ │ │ ├── _screen-reader.scss │ │ │ ├── _stacked.scss │ │ │ ├── _variables.scss │ │ │ └── font-awesome.scss │ ├── montserrat │ │ ├── Montserrat-Black.ttf │ │ ├── Montserrat-BlackItalic.ttf │ │ ├── Montserrat-Bold.ttf │ │ ├── Montserrat-BoldItalic.ttf │ │ ├── Montserrat-ExtraBold.ttf │ │ ├── Montserrat-ExtraBoldItalic.ttf │ │ ├── Montserrat-ExtraLight.ttf │ │ ├── Montserrat-ExtraLightItalic.ttf │ │ ├── Montserrat-Italic.ttf │ │ ├── Montserrat-Light.ttf │ │ ├── Montserrat-LightItalic.ttf │ │ ├── Montserrat-Medium.ttf │ │ ├── Montserrat-MediumItalic.ttf │ │ ├── Montserrat-Regular.ttf │ │ ├── Montserrat-SemiBold.ttf │ │ ├── Montserrat-SemiBoldItalic.ttf │ │ ├── Montserrat-Thin.ttf │ │ ├── Montserrat-ThinItalic.ttf │ │ └── OFL.txt │ └── poppins │ │ ├── Poppins-Black.ttf │ │ ├── Poppins-BlackItalic.ttf │ │ ├── Poppins-Bold.ttf │ │ ├── Poppins-BoldItalic.ttf │ │ ├── Poppins-ExtraBold.ttf │ │ ├── Poppins-ExtraBoldItalic.ttf │ │ ├── Poppins-ExtraLight.ttf │ │ ├── Poppins-ExtraLightItalic.ttf │ │ ├── Poppins-Italic.ttf │ │ ├── Poppins-Light.ttf │ │ ├── Poppins-LightItalic.ttf │ │ ├── Poppins-Medium.ttf │ │ ├── Poppins-MediumItalic.ttf │ │ ├── Poppins-Regular.ttf │ │ ├── Poppins-SemiBold.ttf │ │ ├── Poppins-SemiBoldItalic.ttf │ │ ├── Poppins-Thin.ttf │ │ └── Poppins-ThinItalic.ttf ├── images │ ├── bahi_khata.png │ ├── icons │ │ ├── favicon.ico │ │ └── icon-google.png │ ├── landing-page.png │ ├── sample_report.png │ └── usage.gif ├── js │ └── main.js └── vendor │ ├── animate │ ├── animate.css │ └── checkmark.css │ ├── bootstrap │ ├── css │ │ ├── bootstrap-grid.css │ │ ├── bootstrap-grid.css.map │ │ ├── bootstrap-grid.min.css │ │ ├── bootstrap-grid.min.css.map │ │ ├── bootstrap-reboot.css │ │ ├── bootstrap-reboot.css.map │ │ ├── bootstrap-reboot.min.css │ │ ├── bootstrap-reboot.min.css.map │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ └── bootstrap.min.css.map │ └── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── popper.js │ │ ├── popper.min.js │ │ └── tooltip.js │ ├── css-hamburgers │ ├── hamburgers.css │ └── hamburgers.min.css │ ├── jquery │ └── jquery-3.2.1.min.js │ ├── select2 │ ├── select2.css │ ├── select2.js │ ├── select2.min.css │ └── select2.min.js │ └── tilt │ └── tilt.jquery.min.js ├── templates ├── base.html ├── index.html ├── login.html ├── profile.html ├── report.html ├── signup.html └── thankyou.html └── wsgi.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pickle 2 | *__pycache__* 3 | *.log 4 | .vscode 5 | data/*.json* 6 | data/*.png 7 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: gunicorn wsgi:app 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 | Logo 6 | 7 |

बही खाता

8 | 9 |
10 | A Python app to help you become prudent in your spendings 11 |
12 |
13 | View Demo 14 | · 15 | Report Bug 16 | · 17 | Request Feature 18 |
19 |
20 | 21 | 22 | 23 | 24 | ## Table of Contents 25 | 26 | - [Table of Contents](#table-of-contents) 27 | - [About The Project](#about-the-project) 28 | - [Supported Receipts](#supported-receipts) 29 | - [Built With](#built-with) 30 | - [Getting Started](#getting-started) 31 | - [Prerequisites](#prerequisites) 32 | - [Installation](#installation) 33 | - [Usage](#usage) 34 | - [Deployment](#deployment) 35 | - [Roadmap](#roadmap) 36 | - [Contributing](#contributing) 37 | - [License](#license) 38 | - [Authors](#authors) 39 | - [Acknowledgements](#acknowledgements) 40 | 41 | 42 | ![landing-page.png](static/images/landing-page.png) 43 | 44 | 45 | 46 | ## About The Project 47 | 48 | > Where does all my money go? 49 | 50 | If you have been asking this question to yourself frequently, you are not alone. Handling finances can be tricky. This project is an attempt to help you plan right, so that you worry less while living from paycheck to paycheck. 51 | 52 | 53 | ## Supported Receipts 54 | 55 | - [x] Amazon 56 | 57 | - [x] Flipkart 58 | 59 | - [x] Myntra 60 | 61 | - [x] Ola 62 | 63 | - [x] Uber 64 | 65 | - [ ] Zomato 66 | 67 | - [ ] Swiggy 68 | 69 | - [ ] Curefit 70 | 71 | 72 | ## Built With 73 | 74 | * [Flask](https://flask.palletsprojects.com/en/1.1.x) 75 | * [Heroku](http://heroku.com) 76 | * [Gmail API](https://developers.google.com/gmail/api) 77 | * [Beautiful Soup](https://www.crummy.com/software/BeautifulSoup) 78 | * [Altair](https://altair-viz.github.io) 79 | * [SendGrid](https://sendgrid.com) 80 | 81 | 82 | 83 | 84 | ## Getting Started 85 | 86 | These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See [deployment](#deployment) for notes on how to deploy the project on a live system. 87 | 88 | ### Prerequisites 89 | 90 | * python `>=3.6` 91 | * pip 92 | * [Chrome](https://www.google.com/chrome) 93 | * [ChromeDriver](https://chromedriver.chromium.org) 94 | 95 | 96 | ### Installation 97 | 98 | 1. Clone the repo 99 | ```sh 100 | git clone https://github.com/Bahi-Khata-App/Bahi-Khata 101 | ``` 102 | 2. Install the dependencies 103 | ```sh 104 | pip install -r requirements.txt 105 | ``` 106 | 3. Setup Gmail API 107 | 1. Check `gmail.readonly` scope in your Gmail API OAuth consent page 108 | 2. Add `http://localhost:5000/push` as redirect URI while generating credentials 109 | 3. Download and place your Gmail API credentials in `data/credentials.json` 110 | 4. Place your SendGrid API credentials in `data/sendgrid.json` 111 | 5. (Optional) Place your analytics tracking script in `base.html` 112 | 113 | 114 | 115 | ## Usage 116 | 117 | 1. Set flask environment variable 118 | ```sh 119 | export FLASK_APP="gmail_flask.py" 120 | ``` 121 | 2. Set `LOCAL_DEV = True` in `gmail_flask.py` 122 | 3. `flask run` 123 | 4. Complete the one time app verification 124 | 125 | ![usage.gif](static/images/usage.gif) 126 | 127 | 5. If any relevant data is found, you'll receive an email report similar as below 128 | 129 | ![sample_report.png](static/images/sample_report.png) 130 | 131 | 132 | 133 | ## Deployment 134 | 135 | 1. Set up [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli). 136 | 2. Add redirect URI `/push` in Gmail API console. 137 | 3. Add the [chromedriver](https://github.com/heroku/heroku-buildpack-chromedriver) and [google-chrome](https://github.com/heroku/heroku-buildpack-google-chrome) buildpacks in app settings on your Heroku dashboard. 138 | 4. Configure environment variables for your app in the dashboard. 139 | 140 | | KEY | VALUE | 141 | | ------------------- | ------------------------------------- | 142 | | `CHROMEDRIVER_PATH` | `/app/.chromedriver/bin/chromedriver` | 143 | | `GOOGLE_CHROME_BIN` | `/app/.apt/usr/bin/google-chrome` | 144 | 145 | 146 | 147 | ## Roadmap 148 | 149 | See the [open issues](https://github.com/Bahi-Khata-App/Bahi-Khata/issues) for a list of proposed features (and known issues). 150 | 151 | 152 | 153 | 154 | ## Contributing 155 | 156 | Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. 157 | 158 | 1. Fork the Project 159 | 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) 160 | 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) 161 | 4. Push to the Branch (`git push origin feature/AmazingFeature`) 162 | 5. Open a Pull Request 163 | 164 | 165 | 166 | 167 | ## License 168 | 169 | Distributed under the GPLv3 License. See `LICENSE` for more information. 170 | 171 | 172 | 173 | ## Authors 174 | 175 | * [Rohit Ner](https://github.com/rohitner) 176 | * [Nishant Nikhil](https://github.com/nishnik) 177 | 178 | 179 | 180 | ## Acknowledgements 181 | 182 | * Hat tip to anyone whose code was used 183 | -------------------------------------------------------------------------------- /auth.py: -------------------------------------------------------------------------------- 1 | from flask import ( 2 | Blueprint, render_template, redirect, 3 | url_for, request, flash) 4 | from flask_login import login_user, logout_user, login_required 5 | from werkzeug.security import generate_password_hash, check_password_hash 6 | from models import User 7 | from gmail_flask import db 8 | 9 | auth = Blueprint('auth', __name__) 10 | 11 | 12 | @auth.route('/login', methods=['GET']) 13 | def login(): 14 | return render_template('login.html') 15 | 16 | 17 | @auth.route('/signup', methods=['GET']) 18 | def signup(): 19 | return render_template('signup.html') 20 | 21 | 22 | @auth.route('/logout') 23 | @login_required 24 | def logout(): 25 | logout_user() 26 | return redirect(url_for('main.index')) 27 | 28 | 29 | @auth.route('/signup', methods=['POST']) 30 | def signup_post(): 31 | email = request.form.get('email') 32 | name = request.form.get('name') 33 | password = request.form.get('password') 34 | 35 | # if this returns a user, then the email already exists in database 36 | user = User.query.filter_by(email=email).first() 37 | 38 | if user: # if a user is found, we want to redirect back to signup page so user can try again 39 | flash('Email address already exists') 40 | return redirect(url_for('auth.signup')) 41 | 42 | # create new user with the form data. Hash the password so plaintext version isn't saved. 43 | new_user = User(email=email, name=name, 44 | password=generate_password_hash(password, method='sha256')) 45 | 46 | # add the new user to the database 47 | db.session.add(new_user) 48 | db.session.commit() 49 | 50 | return redirect(url_for('auth.login')) 51 | 52 | 53 | @auth.route('/login', methods=['POST']) 54 | def login_post(): 55 | email = request.form.get('email') 56 | password = request.form.get('password') 57 | remember = True if request.form.get('remember') else False 58 | 59 | user = User.query.filter_by(email=email).first() 60 | 61 | # check if user actually exists 62 | # take the user supplied password, hash it, and compare it to the hashed password in database 63 | if not user or not check_password_hash(user.password, password): 64 | flash('Please check your login details and try again.') 65 | # if user doesn't exist or password is wrong, reload the page 66 | return redirect(url_for('auth.login')) 67 | 68 | # if the above check passes, then we know the user has the right credentials 69 | login_user(user, remember=remember) 70 | return redirect(url_for('main.profile')) 71 | -------------------------------------------------------------------------------- /create-db.py: -------------------------------------------------------------------------------- 1 | from gmail_flask import db, create_app 2 | db.create_all(app=create_app()) 3 | -------------------------------------------------------------------------------- /gmail_flask.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import base64 3 | 4 | from flask import * 5 | import pickle 6 | import os.path 7 | import base64 8 | from googleapiclient.discovery import build 9 | from google_auth_oauthlib.flow import InstalledAppFlow 10 | from google.auth.transport.requests import Request 11 | import pickle 12 | import datetime 13 | import sys 14 | import importlib 15 | from threading import Thread 16 | import sendgrid 17 | from sendgrid import SendGridAPIClient 18 | from sendgrid.helpers.mail import ( 19 | Mail, Attachment, FileContent, FileName, 20 | FileType, Disposition, ContentId) 21 | 22 | import pandas as pd 23 | from pandas.plotting import register_matplotlib_converters 24 | import numpy as np 25 | from flask_sqlalchemy import SQLAlchemy 26 | from flask_login import LoginManager 27 | import altair as alt 28 | from altair_saver import save 29 | 30 | LOCAL_DEV = False 31 | PARAMS_FILE = 'params_central.json' 32 | IGNORE_LIST = ['curefit'] 33 | 34 | with open(PARAMS_FILE) as params_file: 35 | params = json.load(params_file) 36 | 37 | SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/userinfo.email', 'openid', 'https://www.googleapis.com/auth/userinfo.profile'] 38 | 39 | if LOCAL_DEV: 40 | credentials_filename = 'data/credentials.json.bak' 41 | REDIRECT_URL = "http://localhost:5000/push" 42 | else: 43 | credentials_filename = 'data/credentials.json' 44 | REDIRECT_URL = "https://bahi-khata-app.herokuapp.com/push" 45 | 46 | 47 | flow = InstalledAppFlow.from_client_secrets_file( 48 | credentials_filename, SCOPES) 49 | flow.redirect_uri = REDIRECT_URL 50 | authorization_url, state = flow.authorization_url(access_type='offline', include_granted_scopes='true') 51 | credentials = None 52 | 53 | db = SQLAlchemy() 54 | 55 | 56 | def create_app(): 57 | app = Flask(__name__) 58 | 59 | app.config['SECRET_KEY'] = '9OLWxND4o83j4K4iuopO' 60 | app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite' 61 | app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 62 | 63 | db.init_app(app) 64 | 65 | login_manager = LoginManager() 66 | login_manager.login_view = 'auth.login' 67 | login_manager.init_app(app) 68 | 69 | from models import User 70 | 71 | @login_manager.user_loader 72 | def load_user(user_id): 73 | # since the user_id is just the primary key of our user table, use it in the query for the user 74 | return User.query.get(int(user_id)) 75 | 76 | # blueprint for auth routes in our app 77 | from auth import auth as auth_blueprint 78 | app.register_blueprint(auth_blueprint) 79 | 80 | # blueprint for non-auth parts of app 81 | from main import main as main_blueprint 82 | app.register_blueprint(main_blueprint) 83 | 84 | return app 85 | 86 | 87 | app = create_app() 88 | 89 | # Use this for getting form authenticating with GMail 90 | @app.route('/auth', methods=['GET', 'POST']) 91 | def start_auth(): 92 | global authorization_url 93 | return redirect(authorization_url) 94 | 95 | @app.route('/push') 96 | def build_service(): 97 | print ("Done") 98 | print (request) 99 | print (request.args.get("code")) 100 | flow.fetch_token(code=request.args.get("code")) 101 | credentials = flow.credentials # write it to file 102 | service = build('gmail', 'v1', credentials=credentials) 103 | thread = Thread(target=push_report, args=(service,)) 104 | thread.daemon = True 105 | thread.start() 106 | return redirect(url_for('display_thankyou')) 107 | 108 | @app.route('/thankyou', methods=['GET']) 109 | def display_thankyou(): 110 | return render_template('thankyou.html') 111 | 112 | def push_report(service): 113 | user_email = service.users().getProfile(userId='me').execute()['emailAddress'] 114 | print(user_email) 115 | global params 116 | y_bottom = np.zeros(12) 117 | charts = [] 118 | df1 = pd.DataFrame() 119 | for company_name in params: 120 | company = params[company_name] 121 | if company_name in IGNORE_LIST or not create_dump(service, company): 122 | continue 123 | # if company_name in IGNORE_LIST: 124 | # continue 125 | try: 126 | x, y = getData(company_name, company['fname']) 127 | x, y = coerceData(x, y) 128 | except Exception as e: 129 | print(e) 130 | continue 131 | print(company_name, y) 132 | y_bottom = np.add(y_bottom, y) 133 | source = pd.DataFrame({ 134 | 'month': x, 135 | 'spent': y, 136 | 'company': [company_name] * 12 137 | }) 138 | chart = alt.Chart(source).mark_bar(size=15).encode( 139 | x=alt.X('month', title=''), 140 | y=alt.Y('spent', title='Amount spent (₹)') 141 | ).properties( 142 | title=company_name, 143 | ) 144 | charts.append(chart) 145 | source.set_index('month') 146 | if not df1.size: 147 | df1 = source 148 | else: 149 | df1 = df1.append(source) 150 | if not df1.size: 151 | print('No data found for ' + user_email) 152 | return 153 | stackedchart = alt.Chart(df1).mark_bar(size=15).encode( 154 | alt.X('month', title=''), 155 | y=alt.Y('sum(spent)', title='Amount spent (₹)'), 156 | color='company' 157 | ).properties( 158 | title='Aggregate Monthly Spending' 159 | ) 160 | charts.insert(0, stackedchart) 161 | repchart = alt.VConcatChart(vconcat=charts) 162 | save(repchart, os.path.dirname(os.path.abspath(__file__)) + '/data/report.png', scale_factor=1.5) 163 | with app.app_context(): 164 | context = {'amount': np.sum(y_bottom)} 165 | email_content = render_template('report.html', **context) 166 | push_email(email_content, user_email) 167 | 168 | def create_dump(service, company): 169 | query = company['query'] 170 | after_time = company['after'] 171 | filename_to_dump = company['fname'] 172 | message_ids = [] 173 | 174 | returned_request = service.users().messages().list(userId='me', q=query).execute() 175 | if 'messages' not in returned_request: 176 | return False 177 | 178 | message_ids += returned_request['messages'] 179 | 180 | while 'nextPageToken' in returned_request: 181 | next_page_token = returned_request['nextPageToken'] 182 | returned_request = service.users().messages().list(userId='me', q=query, pageToken = next_page_token).execute() 183 | message_ids += returned_request['messages'] 184 | 185 | list_all_messages = [] 186 | for i in range(len(message_ids)): 187 | msg_id = message_ids[i]['id'] 188 | message = service.users().messages().get(userId='me', id=msg_id, format = 'full').execute() 189 | try: 190 | if (datetime.datetime.fromtimestamp(int(message['internalDate'])/1000).strftime('%Y-%m-%d %H:%M:%S') > after_time): 191 | list_all_messages.append(message) 192 | print ('Message snippet: %s' % message['snippet']) 193 | else: 194 | break 195 | except Exception as e: 196 | print (e) 197 | print ("Index", i, message['snippet']) 198 | 199 | with open(filename_to_dump, 'wb') as handle: 200 | pickle.dump(list_all_messages, handle) 201 | return True 202 | 203 | 204 | def push_email(email_content, user_email): 205 | message = Mail( 206 | from_email='admin@bahikhata.com', 207 | to_emails=user_email, 208 | subject='Bahi Khata Report', 209 | html_content= email_content) 210 | file_path = './static/images/bahi_khata.png' 211 | with open(file_path, 'rb') as f: 212 | data = f.read() 213 | encoded = base64.b64encode(data).decode() 214 | attachment = Attachment() 215 | attachment.file_content = FileContent(encoded) 216 | attachment.file_type = FileType('image/png') 217 | attachment.file_name = FileName('bahi_khata.png') 218 | attachment.disposition = Disposition('inline') 219 | attachment.content_id = ContentId('bahikhatalogo') 220 | message.attachment = attachment 221 | file_path = './data/report.png' 222 | with open(file_path, 'rb') as f: 223 | data = f.read() 224 | encoded = base64.b64encode(data).decode() 225 | attachment = Attachment() 226 | attachment.file_content = FileContent(encoded) 227 | attachment.file_type = FileType('image/png') 228 | attachment.file_name = FileName('report.png') 229 | attachment.disposition = Disposition('inline') 230 | attachment.content_id = ContentId('report') 231 | message.attachment = attachment 232 | with open('data/sendgrid.json') as f: 233 | SG_API_KEY = f.readline() 234 | try: 235 | sg = SendGridAPIClient(SG_API_KEY) 236 | response = sg.send(message) 237 | print(response.status_code) 238 | print(response.body) 239 | print(response.headers) 240 | except Exception as e: 241 | print(e.to_dict) 242 | return "sent email" 243 | 244 | 245 | def getData(company_name, filename_to_dump): 246 | sys.path.append('src') 247 | return importlib.import_module('src.analysis_' + company_name).getData(filename_to_dump) 248 | 249 | 250 | def coerceData(x, y): 251 | df = pd.DataFrame({'Amount': y}, index=x) 252 | df.index = pd.to_datetime(df.index.strftime('%Y-%m-%d')) 253 | df = df['Amount'].resample('M').sum() 254 | df = df.reindex(pd.date_range('2019-07-01', periods=12, freq='M')).fillna(0.0) 255 | # print(df.index) 256 | # print(df) 257 | x = df.index.tolist() 258 | y = df.values 259 | return x, y 260 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint, render_template 2 | from flask_login import login_required, current_user 3 | from gmail_flask import db 4 | 5 | main = Blueprint('main', __name__) 6 | 7 | 8 | @main.route('/') 9 | def index(): 10 | return render_template('index.html') 11 | 12 | 13 | @main.route('/profile') 14 | @login_required 15 | def profile(): 16 | return render_template('profile.html', name=current_user.name) 17 | -------------------------------------------------------------------------------- /models.py: -------------------------------------------------------------------------------- 1 | from flask_login import UserMixin 2 | from gmail_flask import db 3 | 4 | # Models created in Flask-SQLAlchemy are represented by classes 5 | # which then translate to tables in a database 6 | 7 | 8 | class User(UserMixin, db.Model): 9 | # primary keys are required by SQLAlchemy 10 | id = db.Column(db.Integer, primary_key=True) 11 | email = db.Column(db.String(100), unique=True) 12 | password = db.Column(db.String(100)) 13 | name = db.Column(db.String(1000)) 14 | -------------------------------------------------------------------------------- /params_central.json: -------------------------------------------------------------------------------- 1 | { 2 | "amazon": { 3 | "query": "from:(Amazon.in) subject:(amazon.in your order) -{update been} ", 4 | "after": "2019-05", 5 | "fname": "data/0617_one_year_dump_amazon.pickle" 6 | }, 7 | "curefit": { 8 | "query": "from:noreply@cure.fit Confirmation for ", 9 | "after": "2019-05", 10 | "fname": "data/0617_one_year_dump_curefit.pickle" 11 | }, 12 | "flipkart": { 13 | "query": "from:(Flipkart.com) Your order has been successfully placed ", 14 | "after": "2019-05", 15 | "fname": "data/0617_one_year_dump_flipkart.pickle" 16 | }, 17 | "myntra": { 18 | "query": "from:(Myntra Updates) Your Myntra Order Confirmation -{item} ", 19 | "after": "2019-05", 20 | "fname": "data/0617_one_year_dump_myntra.pickle" 21 | }, 22 | "ola": { 23 | "query": "ola your ride to", 24 | "after": "2019-05", 25 | "fname": "data/0617_one_year_dump_ola.pickle" 26 | }, 27 | "uber": { 28 | "query": "uber receipts trip with uber", 29 | "after": "2019-05", 30 | "fname": "data/0617_one_year_dump_uber.pickle" 31 | } 32 | } -------------------------------------------------------------------------------- /readme: -------------------------------------------------------------------------------- 1 | At 6:08 PM, March 14 2 | gmail_flask.py queries mail for all the cure fit related transaction mails 3 | `dump_cure_fit.pickle` is the lists of htmls for the messages 4 | 5 | 6 | TO RUN: 7 | export FLASK_APP=gmail_flask.py 8 | python3 -m flask run 9 | 10 | 11 | First make changes to gmail_flask.py to include the desired query. 12 | Dump the output in a .pickel format in data/ 13 | Write an analysis file in src/ 14 | 15 | 16 | Selenium needed by altair to export to png 17 | Add chromedriver, google-chrome build-packages on heroku 18 | to make selenium work, also add config vars in heroku settings 19 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | altair==4.0.1 2 | altair_saver==0.5.0 3 | beautifulsoup4==4.9.1 4 | cachetools==4.1.0 5 | certifi==2020.6.20 6 | chardet==3.0.4 7 | click==7.1.2 8 | cycler==0.10.0 9 | Flask==1.1.2 10 | Flask-Login==0.5.0 11 | Flask-SQLAlchemy==2.4.3 12 | google-api-core==1.21.0 13 | google-api-python-client==1.9.3 14 | google-auth==1.18.0 15 | google-auth-httplib2==0.0.3 16 | google-auth-oauthlib==0.4.1 17 | googleapis-common-protos==1.52.0 18 | gunicorn==20.0.4 19 | httplib2==0.18.1 20 | idna==2.9 21 | itsdangerous==1.1.0 22 | Jinja2==2.11.2 23 | kiwisolver==1.1.0 24 | MarkupSafe==1.1.1 25 | matplotlib==3.0.3 26 | numpy==1.18.5 27 | oauthlib==3.1.0 28 | pandas==1.0.5 29 | protobuf==3.12.2 30 | pyasn1==0.4.8 31 | pyasn1-modules==0.2.8 32 | pyparsing==2.4.7 33 | python-dateutil==2.8.1 34 | python-http-client==3.2.7 35 | pytz==2020.1 36 | requests==2.24.0 37 | requests-oauthlib==1.3.0 38 | rsa==4.6 39 | sendgrid==6.3.1 40 | sendgrid-python==0.1.1 41 | six==1.15.0 42 | soupsieve==2.0.1 43 | uritemplate==3.0.1 44 | urllib3==1.25.9 45 | Werkzeug==1.0.1 46 | -------------------------------------------------------------------------------- /src/analysis_amazon.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import matplotlib.dates as mdates 5 | from utils import parse_mail 6 | from bs4 import BeautifulSoup 7 | import datetime 8 | import re 9 | import os 10 | 11 | 12 | def getData(dumpfile): 13 | with open(dumpfile, 'rb') as handle: 14 | data_dump = pickle.load(handle) 15 | 16 | parsed_data = parse_mail(data_dump) 17 | 18 | x = [] 19 | y = [] 20 | for parsed_row in parsed_data: 21 | date_this = parsed_row['date'] 22 | snippet = parsed_row['snippet'] 23 | subject_this = parsed_row['subject'] 24 | if 'Your Amazon.in order' in subject_this: 25 | soup = BeautifulSoup(parsed_row['str'], features="html.parser") 26 | list_amt = soup.findAll("strong", text=re.compile("Rs.")) 27 | if not len(list_amt): 28 | continue 29 | amount_parsed = float(str(list_amt[-1]).split(".")[1].replace(',','')) 30 | date_parsed = datetime.datetime.strptime(date_this, '%a, %d %b %Y %H:%M:%S %z') 31 | x.append(date_parsed) 32 | y.append(amount_parsed) 33 | 34 | return x[::-1], y[::-1] 35 | -------------------------------------------------------------------------------- /src/analysis_curefit.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import matplotlib.dates as mdates 5 | from bs4 import BeautifulSoup 6 | import os 7 | 8 | # This is old now, the way we dump now has changed so would have to modify it accordingly. 9 | # TODO: Nishant 10 | def getData(dumpfile): 11 | with open(dumpfile, 'rb') as handle: 12 | data_cure_fit = pickle.load(handle) 13 | for i in range(len(data_cure_fit)): 14 | sample_data = data_cure_fit[i] 15 | soup=BeautifulSoup(sample_data[0]) 16 | elements = soup.findAll(attrs = {"style": "padding-left: 20px; width: 55%"}) 17 | assert(len(elements) >= 2) 18 | i = -1 19 | total_sales = [] 20 | for i in range(len(data_cure_fit)): 21 | sample_data = data_cure_fit[i] 22 | soup=BeautifulSoup(sample_data[0]) 23 | elements = soup.findAll(attrs = {"style": "padding-left: 20px; width: 55%"}) 24 | item_list = [] 25 | for item in elements[1:]: 26 | item_name = item.text.strip() 27 | attrs = item.fetchNextSiblings() 28 | ind_price = attrs[0].text 29 | quantity = attrs[1].text 30 | total_price = attrs[2].text 31 | item_list.append([item_name, ind_price, quantity, total_price]) 32 | attributes_of_sale = {} 33 | elements_of_total_bill = soup.findAll("td", attrs = {"style": "padding-left: 20px; width: 85%"}) 34 | for element in elements_of_total_bill: 35 | attributes_of_sale[element.text] = element.fetchNextSiblings()[0].text 36 | attributes_of_sale["item_list"] = item_list 37 | attributes_of_sale["date"] = sample_data[-1] 38 | attributes_of_sale["subject"] = sample_data[-2] 39 | attributes_of_sale["snippet"] = sample_data[-3] 40 | total_sales.append(attributes_of_sale) 41 | num_orders = [] 42 | cumulative = 0 43 | for a in total_sales: 44 | # num_orders.append([int(a['subject'].split(" ")[-1]), datetime.datetime.strptime(a['date'], "%a, %d %b %Y %H:%M:%S %z").date()]) 45 | # num_orders.append([float(a['Total Payable']), datetime.datetime.strptime(a['date'], "%a, %d %b %Y %H:%M:%S %z").date()]) 46 | cumulative += float(a['Total Payable']) 47 | num_orders.append([cumulative, datetime.datetime.strptime(a['date'], "%a, %d %b %Y %H:%M:%S %z").date()]) 48 | total_sales.reverse() 49 | num_orders = [] 50 | cumulative = 0 51 | for a in total_sales: 52 | # num_orders.append([int(a['subject'].split(" ")[-1]), datetime.datetime.strptime(a['date'], "%a, %d %b %Y %H:%M:%S %z").date()]) 53 | # num_orders.append([float(a['Total Payable']), datetime.datetime.strptime(a['date'], "%a, %d %b %Y %H:%M:%S %z").date()]) 54 | cumulative += float(a['Total Payable']) 55 | num_orders.append([cumulative, datetime.datetime.strptime(a['date'], "%a, %d %b %Y %H:%M:%S %z").strftime("%Y%m%d")]) 56 | num_orders = np.array(num_orders) 57 | x = num_orders[:,1] 58 | y = num_orders[:,0] 59 | uniqueValues, indicesList = np.unique(x, return_index=True) 60 | x_uni = np.array(x[indicesList], dtype=float) 61 | y_uni = np.array(y[indicesList], dtype=float) 62 | return x_uni, y_uni 63 | 64 | getData("") -------------------------------------------------------------------------------- /src/analysis_flipkart.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import matplotlib.dates as mdates 5 | from utils import parse_mail 6 | from bs4 import BeautifulSoup 7 | import datetime 8 | import re 9 | import os 10 | 11 | 12 | def getData(dumpfile): 13 | with open(dumpfile, 'rb') as handle: 14 | data_dump = pickle.load(handle) 15 | 16 | parsed_data = parse_mail(data_dump) 17 | 18 | x = [] 19 | y = [] 20 | for parsed_row in parsed_data: 21 | date_this = parsed_row['date'] 22 | snippet = parsed_row['snippet'] 23 | subject_this = parsed_row['subject'] 24 | soup = BeautifulSoup(parsed_row['str'], features='html.parser') 25 | amount_parsed = float(str(soup.findAll('span', text=re.compile('₨.'))[-1]).split('₨.')[1].split('<')[0]) 26 | try: 27 | date_parsed = datetime.datetime.strptime(date_this, '%a, %d %b %Y %H:%M:%S %z (UTC)') 28 | except Exception as e: 29 | date_parsed = datetime.datetime.strptime(date_this, '%a, %d %b %Y %H:%M:%S %z') 30 | print(e, 'another date format used') 31 | x.append(date_parsed) 32 | y.append(amount_parsed) 33 | return x[::-1], y[::-1] 34 | -------------------------------------------------------------------------------- /src/analysis_myntra.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import matplotlib.dates as mdates 5 | from utils import parse_mail 6 | from bs4 import BeautifulSoup 7 | import datetime 8 | import re 9 | import os 10 | 11 | 12 | def getData(dumpfile): 13 | with open(dumpfile, 'rb') as handle: 14 | data_dump = pickle.load(handle) 15 | 16 | parsed_data = parse_mail(data_dump) 17 | 18 | x = [] 19 | y = [] 20 | for parsed_row in parsed_data: 21 | date_this = parsed_row['date'] 22 | snippet = parsed_row['snippet'] 23 | subject_this = parsed_row['subject'] 24 | soup = BeautifulSoup(parsed_row['str'], features='html.parser') 25 | amount_parsed = float(str(soup.findAll('td', text=re.compile('₹'))[-1]).split('₹')[1].split('<')[0]) 26 | date_parsed = datetime.datetime.strptime(date_this, '%a, %d %b %Y %H:%M:%S %z') 27 | x.append(date_parsed) 28 | y.append(amount_parsed) 29 | return x[::-1], y[::-1] 30 | -------------------------------------------------------------------------------- /src/analysis_ola.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import matplotlib.dates as mdates 5 | from utils import parse_mail 6 | from bs4 import BeautifulSoup 7 | import datetime 8 | import re 9 | import os 10 | 11 | 12 | def getData(dumpfile): 13 | with open(dumpfile, 'rb') as handle: 14 | data_dump = pickle.load(handle) 15 | 16 | parsed_data = parse_mail(data_dump) 17 | 18 | x = [] 19 | y = [] 20 | for parsed_row in parsed_data: 21 | date_this = parsed_row['date'] 22 | snippet = parsed_row['snippet'] 23 | subject_this = parsed_row['subject'] 24 | if 'ride to' in subject_this: 25 | amount_parsed = float(snippet.split('₹')[1].split(' ')[0]) 26 | date_parsed = datetime.datetime.strptime(date_this, '%a, %d %b %Y %H:%M:%S %z') 27 | x.append(date_parsed) 28 | y.append(amount_parsed) 29 | return x[::-1], y[::-1] 30 | -------------------------------------------------------------------------------- /src/analysis_uber.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | import matplotlib.dates as mdates 5 | from utils import parse_mail 6 | from bs4 import BeautifulSoup 7 | import pandas as pd 8 | import datetime 9 | import re 10 | import os 11 | 12 | 13 | def getData(dumpfile): 14 | with open(dumpfile, 'rb') as handle: 15 | data_dump = pickle.load(handle) 16 | 17 | parsed_data = parse_mail(data_dump) 18 | 19 | x = [] 20 | y = [] 21 | for parsed_row in parsed_data: 22 | date_this = parsed_row['date'] 23 | snippet = parsed_row['snippet'] 24 | subject_this = parsed_row['subject'] 25 | if 'trip with Uber' in subject_this and not 'We were unable to charge' in snippet: 26 | amount_parsed = float(snippet.split('₹')[1].split(" ")[0]) 27 | date_parsed = "" 28 | try: 29 | date_parsed = datetime.datetime.strptime(date_this[:-6], '%a, %d %b %Y %H:%M:%S %z') 30 | except ValueError: 31 | date_parsed = datetime.datetime.strptime(date_this, '%a, %d %b %Y %H:%M:%S %z') 32 | x.append(date_parsed) 33 | y.append(amount_parsed) 34 | 35 | return x[::-1], y[::-1] -------------------------------------------------------------------------------- /src/fetch_uber.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import pickle 3 | import os.path 4 | from googleapiclient.discovery import build 5 | from google_auth_oauthlib.flow import InstalledAppFlow 6 | from google.auth.transport.requests import Request 7 | import base64 8 | from utils import authenticate 9 | import datetime 10 | 11 | 12 | #### PARAMS 13 | ### You will mostly need to change these: 14 | query = 'uber receipts trip with uber' 15 | # 'from:noreply@cure.fit Confirmation for ' # for cure.fit 16 | after_time = '2019-05' # only messages after this time period gets their content 17 | filename_to_dump = '../data/0617_one_year_dump_uber.pickle' # should be as verbose as we can so that we don't have difficulty later on 18 | #### END of parmas 19 | 20 | 21 | service = authenticate() 22 | 23 | #### Firstly we will fetch message ids, then we will fetch the content of it 24 | message_ids = [] 25 | 26 | ### Fetch Message Ids 27 | ### This is more like a do while because we need to know if the first query has a nextPageToken or not 28 | returned_request = service.users().messages().list(userId='me', q= query).execute() 29 | message_ids += returned_request['messages'] 30 | next_page_token = returned_request['nextPageToken'] 31 | 32 | while True: 33 | returned_request = service.users().messages().list(userId='me', q= query, pageToken = next_page_token).execute() 34 | message_ids += returned_request['messages'] 35 | if 'nextPageToken' in returned_request: 36 | next_page_token = returned_request['nextPageToken'] 37 | else: 38 | break 39 | #### Fetched Message Ids 40 | 41 | #### Fetch Message Content 42 | 43 | list_all_messages = [] 44 | for i in range(len(message_ids)): 45 | msg_id = message_ids[i]['id'] 46 | message = service.users().messages().get(userId='me', id=msg_id, format = 'full').execute() 47 | try: 48 | if (datetime.datetime.fromtimestamp(int(message['internalDate'])/1000).strftime('%Y-%m-%d %H:%M:%S') > after_time): 49 | list_all_messages.append(message) 50 | print ('Message snippet: %s' % message['snippet']) 51 | else: 52 | break 53 | except Exception as e: 54 | print (e) 55 | print ("Index", i, message['snippet']) 56 | 57 | 58 | #### Dump message content 59 | with open(filename_to_dump, 'wb') as handle: 60 | pickle.dump(list_all_messages, handle) 61 | 62 | 63 | 64 | 65 | # lists[''] 66 | 67 | # message = service.users().messages().get(userId='me', id=msg_id, format = 'full').execute() 68 | 69 | # msg_str = "" 70 | # for j in range(len(message['payload']['parts'])): 71 | # if message['payload']['parts'][j]['mimeType'] == 'text/html': 72 | # msg_str = base64.urlsafe_b64decode(message['payload']['parts'][j]['body']['data']) 73 | 74 | 75 | # msg_str = msg_str.decode("utf-8") 76 | # print ('Message snippet: %s' % message['snippet']) 77 | # print (message) 78 | # f = open('out.html', 'w') 79 | # f.write(msg_str.decode("utf=8")) 80 | # f.close() 81 | # labels = results.get('labels', []) 82 | 83 | # if not labels: 84 | # print('No labels found.') 85 | # else: 86 | # print('Labels:') 87 | # for label in labels: 88 | # print(label['name']) 89 | 90 | # i = 0 91 | # msg_id = message_ids[i]['id'] 92 | # message = service.users().messages().get(userId='me', id=msg_id, format = 'full').execute() 93 | # try: 94 | # msg_str = "" 95 | # for j in range(len(message['payload']['parts'])): 96 | # if message['payload']['parts'][j]['mimeType'] == 'text/html': 97 | # msg_str = base64.urlsafe_b64decode(message['payload']['parts'][j]['body']['data']) 98 | # all_messages += (msg_str.decode("utf-8") + "\n\n\n") 99 | # list_all_messages.append([msg_str.decode("utf-8"), message['snippet'], message['payload']['headers'][16]['value'], message['payload']['headers'][18]['value']]) 100 | # print ('Message snippet: %s' % message['snippet']) 101 | # except Exception as e: 102 | # print (e) 103 | # print ("Index", i) 104 | -------------------------------------------------------------------------------- /src/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import pickle 3 | import os.path 4 | from googleapiclient.discovery import build 5 | from google_auth_oauthlib.flow import InstalledAppFlow 6 | from google.auth.transport.requests import Request 7 | import base64 8 | 9 | def authenticate(): 10 | # If modifying these scopes, delete the file token.pickle. 11 | SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'] 12 | 13 | """Shows basic usage of the Gmail API. 14 | Lists the user's Gmail labels. 15 | """ 16 | creds = None 17 | # The file token.pickle stores the user's access and refresh tokens, and is 18 | # created automatically when the authorization flow completes for the first 19 | # time. 20 | if os.path.exists('../data/token.pickle'): 21 | with open('../data/token.pickle', 'rb') as token: 22 | creds = pickle.load(token) 23 | 24 | 25 | # If there are no (valid) credentials available, let the user log in. 26 | if not creds or not creds.valid: 27 | if creds and creds.expired and creds.refresh_token: 28 | creds.refresh(Request()) 29 | else: 30 | flow = InstalledAppFlow.from_client_secrets_file( 31 | '../data/credentials.json', SCOPES) 32 | creds = flow.run_local_server(port=0) 33 | # Save the credentials for the next run 34 | with open('../data/token.pickle', 'wb') as token: 35 | pickle.dump(creds, token) 36 | 37 | service = build('gmail', 'v1', credentials=creds) 38 | return service 39 | 40 | def parse_mail(data_dump): 41 | # subject, from, date, snippet, email_html 42 | data_arr = [] 43 | for message in data_dump: 44 | if 'multipart' in message['payload']['mimeType']: 45 | for j in range(len(message['payload']['parts'])): 46 | if message['payload']['parts'][j]['mimeType'] == 'text/html': 47 | if "data" in message['payload']['parts'][j]['body']: 48 | this_str = base64.urlsafe_b64decode(message['payload']['parts'][j]['body']['data']) 49 | else: 50 | this_str = b"[attachment here]" 51 | this_str = (this_str.decode("utf-8") + "\n\n\n") 52 | else: 53 | this_str = base64.urlsafe_b64decode(message['payload']['body']['data']) 54 | this_str = (this_str.decode("utf-8") + "\n\n\n") 55 | this_snippet = message['snippet'] 56 | this_subject = -1 57 | this_from = -1 58 | this_date = -1 59 | for i in range(len(message['payload']['headers'])): 60 | # print (message['payload']['headers'][i]['name']) 61 | # print (message['payload']['headers'][i]['value'], "\n\n\n") 62 | if message['payload']['headers'][i]['name'] == 'Subject': 63 | this_subject = message['payload']['headers'][i]['value'] 64 | elif message['payload']['headers'][i]['name'] == 'From': 65 | this_from = message['payload']['headers'][i]['value'] 66 | elif message['payload']['headers'][i]['name'] == 'Date': 67 | this_date = message['payload']['headers'][i]['value'] 68 | this_dict= {} 69 | this_dict['subject'] = this_subject 70 | this_dict['from'] = this_from 71 | this_dict['date'] = this_date 72 | this_dict['snippet'] = this_snippet 73 | this_dict['str'] = this_str 74 | data_arr.append(this_dict) 75 | return data_arr 76 | 77 | 78 | -------------------------------------------------------------------------------- /static/css/main.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | /*////////////////////////////////////////////////////////////////// 6 | [ FONT ]*/ 7 | 8 | @font-face { 9 | font-family: Poppins-Regular; 10 | src: url('../fonts/poppins/Poppins-Regular.ttf'); 11 | } 12 | 13 | @font-face { 14 | font-family: Poppins-Bold; 15 | src: url('../fonts/poppins/Poppins-Bold.ttf'); 16 | } 17 | 18 | @font-face { 19 | font-family: Poppins-Medium; 20 | src: url('../fonts/poppins/Poppins-Medium.ttf'); 21 | } 22 | 23 | @font-face { 24 | font-family: Montserrat-Bold; 25 | src: url('../fonts/montserrat/Montserrat-Bold.ttf'); 26 | } 27 | 28 | /*////////////////////////////////////////////////////////////////// 29 | [ RESTYLE TAG ]*/ 30 | 31 | * { 32 | margin: 0px; 33 | padding: 0px; 34 | box-sizing: border-box; 35 | } 36 | 37 | body, html { 38 | height: 100%; 39 | font-family: Poppins-Regular, sans-serif; 40 | } 41 | 42 | /*---------------------------------------------*/ 43 | a { 44 | font-family: Poppins-Regular; 45 | font-size: 14px; 46 | line-height: 1.7; 47 | color: #666666; 48 | margin: 0px; 49 | transition: all 0.4s; 50 | -webkit-transition: all 0.4s; 51 | -o-transition: all 0.4s; 52 | -moz-transition: all 0.4s; 53 | } 54 | 55 | a:focus { 56 | outline: none !important; 57 | } 58 | 59 | a:hover { 60 | text-decoration: none; 61 | color: #57b846; 62 | } 63 | 64 | /*---------------------------------------------*/ 65 | h1,h2,h3,h4,h5,h6 { 66 | margin: 0px; 67 | } 68 | 69 | p { 70 | font-family: Poppins-Regular; 71 | font-size: 14px; 72 | line-height: 1.7; 73 | color: #666666; 74 | margin: 0px; 75 | } 76 | 77 | ul, li { 78 | margin: 0px; 79 | list-style-type: none; 80 | } 81 | 82 | 83 | /*---------------------------------------------*/ 84 | input { 85 | outline: none; 86 | border: none; 87 | } 88 | 89 | textarea { 90 | outline: none; 91 | border: none; 92 | } 93 | 94 | textarea:focus, input:focus { 95 | border-color: transparent !important; 96 | } 97 | 98 | input:focus::-webkit-input-placeholder { color:transparent; } 99 | input:focus:-moz-placeholder { color:transparent; } 100 | input:focus::-moz-placeholder { color:transparent; } 101 | input:focus:-ms-input-placeholder { color:transparent; } 102 | 103 | textarea:focus::-webkit-input-placeholder { color:transparent; } 104 | textarea:focus:-moz-placeholder { color:transparent; } 105 | textarea:focus::-moz-placeholder { color:transparent; } 106 | textarea:focus:-ms-input-placeholder { color:transparent; } 107 | 108 | input::-webkit-input-placeholder { color: #999999; } 109 | input:-moz-placeholder { color: #999999; } 110 | input::-moz-placeholder { color: #999999; } 111 | input:-ms-input-placeholder { color: #999999; } 112 | 113 | textarea::-webkit-input-placeholder { color: #999999; } 114 | textarea:-moz-placeholder { color: #999999; } 115 | textarea::-moz-placeholder { color: #999999; } 116 | textarea:-ms-input-placeholder { color: #999999; } 117 | 118 | /*---------------------------------------------*/ 119 | button { 120 | outline: none !important; 121 | border: none; 122 | background: transparent; 123 | } 124 | 125 | button:hover { 126 | cursor: pointer; 127 | } 128 | 129 | iframe { 130 | border: none !important; 131 | } 132 | 133 | 134 | /*////////////////////////////////////////////////////////////////// 135 | [ Utility ]*/ 136 | .txt1 { 137 | font-family: Poppins-Regular; 138 | font-size: 13px; 139 | line-height: 1.5; 140 | color: #999999; 141 | } 142 | 143 | .txt2 { 144 | font-family: Poppins-Regular; 145 | font-size: 13px; 146 | line-height: 1.5; 147 | color: #666666; 148 | } 149 | 150 | 151 | /*////////////////////////////////////////////////////////////////// 152 | [ login ]*/ 153 | 154 | .limiter { 155 | width: 100%; 156 | margin: 0 auto; 157 | } 158 | 159 | .container-login100 { 160 | width: 100%; 161 | min-height: 100vh; 162 | display: -webkit-box; 163 | display: -webkit-flex; 164 | display: -moz-box; 165 | display: -ms-flexbox; 166 | display: flex; 167 | flex-wrap: wrap; 168 | justify-content: center; 169 | align-items: center; 170 | padding: 15px; 171 | background: #9053c7; 172 | background: -webkit-linear-gradient(-135deg, #c850c0, #4158d0); 173 | background: -o-linear-gradient(-135deg, #c850c0, #4158d0); 174 | background: -moz-linear-gradient(-135deg, #c850c0, #4158d0); 175 | background: linear-gradient(-135deg, #c850c0, #4158d0); 176 | } 177 | 178 | .wrap-login100 { 179 | width: 960px; 180 | background: #fff; 181 | border-radius: 10px; 182 | overflow: hidden; 183 | 184 | display: -webkit-box; 185 | display: -webkit-flex; 186 | display: -moz-box; 187 | display: -ms-flexbox; 188 | display: flex; 189 | flex-wrap: wrap; 190 | justify-content: space-between; 191 | padding: 90px 130px 33px 95px; 192 | } 193 | 194 | /*------------------------------------------------------------------ 195 | [ ]*/ 196 | .login100-pic { 197 | width: 316px; 198 | } 199 | 200 | .login100-pic img { 201 | max-width: 100%; 202 | } 203 | 204 | 205 | /*------------------------------------------------------------------ 206 | [ ]*/ 207 | .login100-form { 208 | width: 290px; 209 | } 210 | 211 | .login100-form-title { 212 | font-family: Poppins-Bold; 213 | font-size: 24px; 214 | color: #333333; 215 | line-height: 1.2; 216 | text-align: center; 217 | 218 | width: 100%; 219 | display: block; 220 | padding-bottom: 54px; 221 | } 222 | 223 | #login200 { 224 | font-family: Poppins-Bold; 225 | font-size: 24px; 226 | color: #ffffff; 227 | line-height: 1.2; 228 | text-align: center; 229 | 230 | width: 100%; 231 | display: block; 232 | padding-bottom: 54px; 233 | } 234 | 235 | #login201 { 236 | font-family: Poppins-Bold; 237 | font-size: 24px; 238 | color: #000000; 239 | line-height: 1.2; 240 | text-align: center; 241 | 242 | width: 100%; 243 | display: block; 244 | padding-bottom: 54px; 245 | } 246 | 247 | #navbar100 { 248 | font-family: Poppins-Bold; 249 | font-size: 20px; 250 | color: #ffffff; 251 | line-height: 1.2; 252 | text-align: right; 253 | } 254 | 255 | /*---------------------------------------------*/ 256 | .wrap-input100 { 257 | position: relative; 258 | width: 100%; 259 | z-index: 1; 260 | margin-bottom: 10px; 261 | } 262 | 263 | .input100 { 264 | font-family: Poppins-Medium; 265 | font-size: 15px; 266 | line-height: 1.5; 267 | color: #666666; 268 | 269 | display: block; 270 | width: 100%; 271 | background: #e6e6e6; 272 | height: 50px; 273 | border-radius: 25px; 274 | padding: 0 30px 0 68px; 275 | } 276 | 277 | 278 | /*------------------------------------------------------------------ 279 | [ Button sign in with ]*/ 280 | .btn-face, 281 | .btn-google { 282 | font-family: Montserrat-Bold; 283 | font-size: 15px; 284 | line-height: 1.5; 285 | display: -webkit-box; 286 | display: -webkit-flex; 287 | display: -moz-box; 288 | display: -ms-flexbox; 289 | display: flex; 290 | justify-content: center; 291 | align-items: center; 292 | padding: 15px; 293 | width: 100%; 294 | height: 50px; 295 | border-radius: 25px; 296 | box-shadow: 0 1px 5px 0px rgba(0, 0, 0, 0.2); 297 | -moz-box-shadow: 0 1px 5px 0px rgba(0, 0, 0, 0.2); 298 | -webkit-box-shadow: 0 1px 5px 0px rgba(0, 0, 0, 0.2); 299 | -o-box-shadow: 0 1px 5px 0px rgba(0, 0, 0, 0.2); 300 | -ms-box-shadow: 0 1px 5px 0px rgba(0, 0, 0, 0.2); 301 | -webkit-transition: all 0.4s; 302 | -o-transition: all 0.4s; 303 | -moz-transition: all 0.4s; 304 | transition: all 0.4s; 305 | position: relative; 306 | z-index: 1; 307 | } 308 | 309 | .btn-google::before, 310 | .btn-face::before { 311 | content: ""; 312 | display: block; 313 | position: absolute; 314 | z-index: -1; 315 | width: 100%; 316 | height: 100%; 317 | border-radius: 25px; 318 | top: 0; 319 | left: 0; 320 | background: #a64bf4; 321 | background: -webkit-linear-gradient(45deg, #00dbde, #fc00ff); 322 | background: -o-linear-gradient(45deg, #00dbde, #fc00ff); 323 | background: -moz-linear-gradient(45deg, #00dbde, #fc00ff); 324 | background: linear-gradient(45deg, #00dbde, #fc00ff); 325 | opacity: 0; 326 | -webkit-transition: all 0.4s; 327 | -o-transition: all 0.4s; 328 | -moz-transition: all 0.4s; 329 | transition: all 0.4s; 330 | } 331 | 332 | .btn-face { 333 | color: #fff; 334 | background-color: #3b5998; 335 | } 336 | 337 | .btn-face i { 338 | font-size: 30px; 339 | margin-right: 17px; 340 | padding-bottom: 3px; 341 | } 342 | 343 | .btn-google { 344 | color: #555555; 345 | background-color: #fff; 346 | } 347 | 348 | .btn-google img { 349 | width: 30px; 350 | margin-right: 15px; 351 | padding-bottom: 3px; 352 | } 353 | 354 | .btn-face:hover:before, 355 | .btn-google:hover:before { 356 | opacity: 1; 357 | } 358 | 359 | .btn-face:hover, 360 | .btn-google:hover { 361 | color: #fff; 362 | } 363 | 364 | /*------------------------------------------------------------------ 365 | [ Focus ]*/ 366 | .focus-input100 { 367 | display: block; 368 | position: absolute; 369 | border-radius: 25px; 370 | bottom: 0; 371 | left: 0; 372 | z-index: -1; 373 | width: 100%; 374 | height: 100%; 375 | box-shadow: 0px 0px 0px 0px; 376 | color: rgba(87,184,70, 0.8); 377 | } 378 | 379 | .input100:focus + .focus-input100 { 380 | -webkit-animation: anim-shadow 0.5s ease-in-out forwards; 381 | animation: anim-shadow 0.5s ease-in-out forwards; 382 | } 383 | 384 | @-webkit-keyframes anim-shadow { 385 | to { 386 | box-shadow: 0px 0px 70px 25px; 387 | opacity: 0; 388 | } 389 | } 390 | 391 | @keyframes anim-shadow { 392 | to { 393 | box-shadow: 0px 0px 70px 25px; 394 | opacity: 0; 395 | } 396 | } 397 | 398 | .symbol-input100 { 399 | font-size: 15px; 400 | 401 | display: -webkit-box; 402 | display: -webkit-flex; 403 | display: -moz-box; 404 | display: -ms-flexbox; 405 | display: flex; 406 | align-items: center; 407 | position: absolute; 408 | border-radius: 25px; 409 | bottom: 0; 410 | left: 0; 411 | width: 100%; 412 | height: 100%; 413 | padding-left: 35px; 414 | pointer-events: none; 415 | color: #666666; 416 | 417 | -webkit-transition: all 0.4s; 418 | -o-transition: all 0.4s; 419 | -moz-transition: all 0.4s; 420 | transition: all 0.4s; 421 | } 422 | 423 | .input100:focus + .focus-input100 + .symbol-input100 { 424 | color: #57b846; 425 | padding-left: 28px; 426 | } 427 | 428 | /*------------------------------------------------------------------ 429 | [ Button ]*/ 430 | .container-login100-form-btn { 431 | width: 100%; 432 | display: -webkit-box; 433 | display: -webkit-flex; 434 | display: -moz-box; 435 | display: -ms-flexbox; 436 | display: flex; 437 | flex-wrap: wrap; 438 | justify-content: center; 439 | padding-top: 20px; 440 | } 441 | 442 | .login100-form-btn { 443 | font-family: Montserrat-Bold; 444 | font-size: 15px; 445 | line-height: 1.5; 446 | color: #fff; 447 | text-transform: uppercase; 448 | 449 | width: 100%; 450 | height: 50px; 451 | border-radius: 25px; 452 | background: #57b846; 453 | display: -webkit-box; 454 | display: -webkit-flex; 455 | display: -moz-box; 456 | display: -ms-flexbox; 457 | display: flex; 458 | justify-content: center; 459 | align-items: center; 460 | padding: 0 25px; 461 | 462 | -webkit-transition: all 0.4s; 463 | -o-transition: all 0.4s; 464 | -moz-transition: all 0.4s; 465 | transition: all 0.4s; 466 | } 467 | 468 | .login100-form-btn:hover { 469 | background: #333333; 470 | } 471 | 472 | 473 | 474 | /*------------------------------------------------------------------ 475 | [ Responsive ]*/ 476 | 477 | 478 | 479 | @media (max-width: 992px) { 480 | .wrap-login100 { 481 | padding: 177px 90px 33px 85px; 482 | } 483 | 484 | .login100-pic { 485 | width: 35%; 486 | } 487 | 488 | .login100-form { 489 | width: 50%; 490 | } 491 | } 492 | 493 | @media (max-width: 768px) { 494 | .wrap-login100 { 495 | padding: 100px 80px 33px 80px; 496 | } 497 | 498 | .login100-pic { 499 | display: none; 500 | } 501 | 502 | .login100-form { 503 | width: 100%; 504 | } 505 | } 506 | 507 | @media (max-width: 576px) { 508 | .wrap-login100 { 509 | padding: 100px 15px 33px 15px; 510 | } 511 | } 512 | 513 | 514 | /*------------------------------------------------------------------ 515 | [ Alert validate ]*/ 516 | 517 | .validate-input { 518 | position: relative; 519 | } 520 | 521 | .alert-validate::before { 522 | content: attr(data-validate); 523 | position: absolute; 524 | max-width: 70%; 525 | background-color: white; 526 | border: 1px solid #c80000; 527 | border-radius: 13px; 528 | padding: 4px 25px 4px 10px; 529 | top: 50%; 530 | -webkit-transform: translateY(-50%); 531 | -moz-transform: translateY(-50%); 532 | -ms-transform: translateY(-50%); 533 | -o-transform: translateY(-50%); 534 | transform: translateY(-50%); 535 | right: 8px; 536 | pointer-events: none; 537 | 538 | font-family: Poppins-Medium; 539 | color: #c80000; 540 | font-size: 13px; 541 | line-height: 1.4; 542 | text-align: left; 543 | 544 | visibility: hidden; 545 | opacity: 0; 546 | 547 | -webkit-transition: opacity 0.4s; 548 | -o-transition: opacity 0.4s; 549 | -moz-transition: opacity 0.4s; 550 | transition: opacity 0.4s; 551 | } 552 | 553 | .alert-validate::after { 554 | content: "\f06a"; 555 | font-family: FontAwesome; 556 | display: block; 557 | position: absolute; 558 | color: #c80000; 559 | font-size: 15px; 560 | top: 50%; 561 | -webkit-transform: translateY(-50%); 562 | -moz-transform: translateY(-50%); 563 | -ms-transform: translateY(-50%); 564 | -o-transform: translateY(-50%); 565 | transform: translateY(-50%); 566 | right: 13px; 567 | } 568 | 569 | .alert-validate:hover:before { 570 | visibility: visible; 571 | opacity: 1; 572 | } 573 | 574 | @media (max-width: 992px) { 575 | .alert-validate::before { 576 | visibility: visible; 577 | opacity: 1; 578 | } 579 | } 580 | 581 | @media (max-width: 576px) { 582 | .wrap-login100 { 583 | padding-left: 15px; 584 | padding-right: 15px; 585 | } 586 | 587 | .btn-face, 588 | .btn-google { 589 | width: 100%; 590 | } 591 | } -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/HELP-US-OUT.txt: -------------------------------------------------------------------------------- 1 | I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project, 2 | Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome, 3 | comprehensive icon sets or copy and paste your own. 4 | 5 | Please. Check it out. 6 | 7 | -Dave Gandy 8 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/font-awesome-4.7.0/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/font-awesome-4.7.0/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/animated.less: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .@{fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .@{fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/bordered-pulled.less: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em @fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .@{fa-css-prefix}-pull-left { float: left; } 11 | .@{fa-css-prefix}-pull-right { float: right; } 12 | 13 | .@{fa-css-prefix} { 14 | &.@{fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.@{fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .@{fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/core.less: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/fixed-width.less: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .@{fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/font-awesome.less: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables.less"; 7 | @import "mixins.less"; 8 | @import "path.less"; 9 | @import "core.less"; 10 | @import "larger.less"; 11 | @import "fixed-width.less"; 12 | @import "list.less"; 13 | @import "bordered-pulled.less"; 14 | @import "animated.less"; 15 | @import "rotated-flipped.less"; 16 | @import "stacked.less"; 17 | @import "icons.less"; 18 | @import "screen-reader.less"; 19 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/larger.less: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .@{fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .@{fa-css-prefix}-2x { font-size: 2em; } 11 | .@{fa-css-prefix}-3x { font-size: 3em; } 12 | .@{fa-css-prefix}-4x { font-size: 4em; } 13 | .@{fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/list.less: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: @fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .@{fa-css-prefix}-li { 11 | position: absolute; 12 | left: -@fa-li-width; 13 | width: @fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.@{fa-css-prefix}-lg { 17 | left: (-@fa-li-width + (4em / 14)); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/mixins.less: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | .fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal @fa-font-size-base/@fa-line-height-base FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | .fa-icon-rotate(@degrees, @rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation})"; 16 | -webkit-transform: rotate(@degrees); 17 | -ms-transform: rotate(@degrees); 18 | transform: rotate(@degrees); 19 | } 20 | 21 | .fa-icon-flip(@horiz, @vert, @rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=@{rotation}, mirror=1)"; 23 | -webkit-transform: scale(@horiz, @vert); 24 | -ms-transform: scale(@horiz, @vert); 25 | transform: scale(@horiz, @vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | .sr-only() { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | .sr-only-focusable() { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/path.less: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('@{fa-font-path}/fontawesome-webfont.eot?v=@{fa-version}'); 7 | src: url('@{fa-font-path}/fontawesome-webfont.eot?#iefix&v=@{fa-version}') format('embedded-opentype'), 8 | url('@{fa-font-path}/fontawesome-webfont.woff2?v=@{fa-version}') format('woff2'), 9 | url('@{fa-font-path}/fontawesome-webfont.woff?v=@{fa-version}') format('woff'), 10 | url('@{fa-font-path}/fontawesome-webfont.ttf?v=@{fa-version}') format('truetype'), 11 | url('@{fa-font-path}/fontawesome-webfont.svg?v=@{fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('@{fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/rotated-flipped.less: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-rotate-90 { .fa-icon-rotate(90deg, 1); } 5 | .@{fa-css-prefix}-rotate-180 { .fa-icon-rotate(180deg, 2); } 6 | .@{fa-css-prefix}-rotate-270 { .fa-icon-rotate(270deg, 3); } 7 | 8 | .@{fa-css-prefix}-flip-horizontal { .fa-icon-flip(-1, 1, 0); } 9 | .@{fa-css-prefix}-flip-vertical { .fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .@{fa-css-prefix}-rotate-90, 15 | :root .@{fa-css-prefix}-rotate-180, 16 | :root .@{fa-css-prefix}-rotate-270, 17 | :root .@{fa-css-prefix}-flip-horizontal, 18 | :root .@{fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/screen-reader.less: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { .sr-only(); } 5 | .sr-only-focusable { .sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/less/stacked.less: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .@{fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .@{fa-css-prefix}-stack-1x, .@{fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .@{fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .@{fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .@{fa-css-prefix}-inverse { color: @fa-inverse; } 21 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Spinning Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | -webkit-animation: fa-spin 2s infinite linear; 6 | animation: fa-spin 2s infinite linear; 7 | } 8 | 9 | .#{$fa-css-prefix}-pulse { 10 | -webkit-animation: fa-spin 1s infinite steps(8); 11 | animation: fa-spin 1s infinite steps(8); 12 | } 13 | 14 | @-webkit-keyframes fa-spin { 15 | 0% { 16 | -webkit-transform: rotate(0deg); 17 | transform: rotate(0deg); 18 | } 19 | 100% { 20 | -webkit-transform: rotate(359deg); 21 | transform: rotate(359deg); 22 | } 23 | } 24 | 25 | @keyframes fa-spin { 26 | 0% { 27 | -webkit-transform: rotate(0deg); 28 | transform: rotate(0deg); 29 | } 30 | 100% { 31 | -webkit-transform: rotate(359deg); 32 | transform: rotate(359deg); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | padding: .2em .25em .15em; 6 | border: solid .08em $fa-border-color; 7 | border-radius: .1em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix} { 14 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 15 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 16 | } 17 | 18 | /* Deprecated as of 4.4.0 */ 19 | .pull-right { float: right; } 20 | .pull-left { float: left; } 21 | 22 | .#{$fa-css-prefix} { 23 | &.pull-left { margin-right: .3em; } 24 | &.pull-right { margin-left: .3em; } 25 | } 26 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix} { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | width: (18em / 14); 5 | text-align: center; 6 | } 7 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | /* makes the font 33% larger relative to the icon container */ 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -15%; 9 | } 10 | .#{$fa-css-prefix}-2x { font-size: 2em; } 11 | .#{$fa-css-prefix}-3x { font-size: 3em; } 12 | .#{$fa-css-prefix}-4x { font-size: 4em; } 13 | .#{$fa-css-prefix}-5x { font-size: 5em; } 14 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | padding-left: 0; 6 | margin-left: $fa-li-width; 7 | list-style-type: none; 8 | > li { position: relative; } 9 | } 10 | .#{$fa-css-prefix}-li { 11 | position: absolute; 12 | left: -$fa-li-width; 13 | width: $fa-li-width; 14 | top: (2em / 14); 15 | text-align: center; 16 | &.#{$fa-css-prefix}-lg { 17 | left: -$fa-li-width + (4em / 14); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon() { 5 | display: inline-block; 6 | font: normal normal normal #{$fa-font-size-base}/#{$fa-line-height-base} FontAwesome; // shortening font declaration 7 | font-size: inherit; // can't have font-size inherit on line above, so need to override 8 | text-rendering: auto; // optimizelegibility throws things off #1094 9 | -webkit-font-smoothing: antialiased; 10 | -moz-osx-font-smoothing: grayscale; 11 | 12 | } 13 | 14 | @mixin fa-icon-rotate($degrees, $rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; 16 | -webkit-transform: rotate($degrees); 17 | -ms-transform: rotate($degrees); 18 | transform: rotate($degrees); 19 | } 20 | 21 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 22 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; 23 | -webkit-transform: scale($horiz, $vert); 24 | -ms-transform: scale($horiz, $vert); 25 | transform: scale($horiz, $vert); 26 | } 27 | 28 | 29 | // Only display content to screen readers. A la Bootstrap 4. 30 | // 31 | // See: http://a11yproject.com/posts/how-to-hide-content/ 32 | 33 | @mixin sr-only { 34 | position: absolute; 35 | width: 1px; 36 | height: 1px; 37 | padding: 0; 38 | margin: -1px; 39 | overflow: hidden; 40 | clip: rect(0,0,0,0); 41 | border: 0; 42 | } 43 | 44 | // Use in conjunction with .sr-only to only display content when it's focused. 45 | // 46 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 47 | // 48 | // Credit: HTML5 Boilerplate 49 | 50 | @mixin sr-only-focusable { 51 | &:active, 52 | &:focus { 53 | position: static; 54 | width: auto; 55 | height: auto; 56 | margin: 0; 57 | overflow: visible; 58 | clip: auto; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_path.scss: -------------------------------------------------------------------------------- 1 | /* FONT PATH 2 | * -------------------------- */ 3 | 4 | @font-face { 5 | font-family: 'FontAwesome'; 6 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?v=#{$fa-version}'); 7 | src: url('#{$fa-font-path}/fontawesome-webfont.eot?#iefix&v=#{$fa-version}') format('embedded-opentype'), 8 | url('#{$fa-font-path}/fontawesome-webfont.woff2?v=#{$fa-version}') format('woff2'), 9 | url('#{$fa-font-path}/fontawesome-webfont.woff?v=#{$fa-version}') format('woff'), 10 | url('#{$fa-font-path}/fontawesome-webfont.ttf?v=#{$fa-version}') format('truetype'), 11 | url('#{$fa-font-path}/fontawesome-webfont.svg?v=#{$fa-version}#fontawesomeregular') format('svg'); 12 | // src: url('#{$fa-font-path}/FontAwesome.otf') format('opentype'); // used when developing fonts 13 | font-weight: normal; 14 | font-style: normal; 15 | } 16 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | 11 | // Hook for IE8-9 12 | // ------------------------- 13 | 14 | :root .#{$fa-css-prefix}-rotate-90, 15 | :root .#{$fa-css-prefix}-rotate-180, 16 | :root .#{$fa-css-prefix}-rotate-270, 17 | :root .#{$fa-css-prefix}-flip-horizontal, 18 | :root .#{$fa-css-prefix}-flip-vertical { 19 | filter: none; 20 | } 21 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only(); } 5 | .sr-only-focusable { @include sr-only-focusable(); } 6 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | position: relative; 6 | display: inline-block; 7 | width: 2em; 8 | height: 2em; 9 | line-height: 2em; 10 | vertical-align: middle; 11 | } 12 | .#{$fa-css-prefix}-stack-1x, .#{$fa-css-prefix}-stack-2x { 13 | position: absolute; 14 | left: 0; 15 | width: 100%; 16 | text-align: center; 17 | } 18 | .#{$fa-css-prefix}-stack-1x { line-height: inherit; } 19 | .#{$fa-css-prefix}-stack-2x { font-size: 2em; } 20 | .#{$fa-css-prefix}-inverse { color: $fa-inverse; } 21 | -------------------------------------------------------------------------------- /static/fonts/font-awesome-4.7.0/scss/font-awesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome 3 | * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) 4 | */ 5 | 6 | @import "variables"; 7 | @import "mixins"; 8 | @import "path"; 9 | @import "core"; 10 | @import "larger"; 11 | @import "fixed-width"; 12 | @import "list"; 13 | @import "bordered-pulled"; 14 | @import "animated"; 15 | @import "rotated-flipped"; 16 | @import "stacked"; 17 | @import "icons"; 18 | @import "screen-reader"; 19 | -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-Black.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-BlackItalic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-Bold.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-BoldItalic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-ExtraBold.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-ExtraLight.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-Italic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-Light.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-LightItalic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-Medium.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-MediumItalic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-Regular.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-SemiBold.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-Thin.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/Montserrat-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/montserrat/Montserrat-ThinItalic.ttf -------------------------------------------------------------------------------- /static/fonts/montserrat/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright 2011 The Montserrat Project Authors (https://github.com/JulietaUla/Montserrat) 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-Black.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-BlackItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-BlackItalic.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-Bold.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-BoldItalic.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-ExtraBold.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-ExtraBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-ExtraBoldItalic.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-ExtraLight.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-ExtraLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-ExtraLightItalic.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-Italic.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-Light.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-LightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-LightItalic.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-Medium.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-MediumItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-MediumItalic.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-Regular.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-SemiBold.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-SemiBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-SemiBoldItalic.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-Thin.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-Thin.ttf -------------------------------------------------------------------------------- /static/fonts/poppins/Poppins-ThinItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/fonts/poppins/Poppins-ThinItalic.ttf -------------------------------------------------------------------------------- /static/images/bahi_khata.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/images/bahi_khata.png -------------------------------------------------------------------------------- /static/images/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/images/icons/favicon.ico -------------------------------------------------------------------------------- /static/images/icons/icon-google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/images/icons/icon-google.png -------------------------------------------------------------------------------- /static/images/landing-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/images/landing-page.png -------------------------------------------------------------------------------- /static/images/sample_report.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/images/sample_report.png -------------------------------------------------------------------------------- /static/images/usage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bahi-Khata-App/Bahi-Khata/3a51d9a3bec98ad5d8b7db041a88daf946293214/static/images/usage.gif -------------------------------------------------------------------------------- /static/js/main.js: -------------------------------------------------------------------------------- 1 | 2 | (function ($) { 3 | "use strict"; 4 | 5 | 6 | /*================================================================== 7 | [ Validate ]*/ 8 | var input = $('.validate-input .input100'); 9 | 10 | $('.validate-form').on('submit',function(){ 11 | var check = true; 12 | 13 | for(var i=0; i=o.clientWidth&&i>=o.clientHeight}),f=0i[e]&&!t.escapeWithReference&&(n=z(p[o],i[e]-('right'===e?p.width:p.height))),pe({},o,n)}};return n.forEach(function(e){var t=-1===['left','top'].indexOf(e)?'secondary':'primary';p=se({},p,s[t](e))}),e.offsets.popper=p,e},priority:['left','right','top','bottom'],padding:5,boundariesElement:'scrollParent'},keepTogether:{order:400,enabled:!0,fn:function(e){var t=e.offsets,o=t.popper,i=t.reference,n=e.placement.split('-')[0],r=V,p=-1!==['top','bottom'].indexOf(n),s=p?'right':'bottom',d=p?'left':'top',a=p?'width':'height';return o[s]r(i[s])&&(e.offsets.popper[d]=r(i[s])),e}},arrow:{order:500,enabled:!0,fn:function(e,t){if(!F(e.instance.modifiers,'arrow','keepTogether'))return e;var o=t.element;if('string'==typeof o){if(o=e.instance.popper.querySelector(o),!o)return e;}else if(!e.instance.popper.contains(o))return console.warn('WARNING: `arrow.element` must be child of its popper element!'),e;var i=e.placement.split('-')[0],n=e.offsets,r=n.popper,p=n.reference,s=-1!==['left','right'].indexOf(i),d=s?'height':'width',a=s?'top':'left',f=s?'left':'top',l=s?'bottom':'right',m=O(o)[d];p[l]-mr[l]&&(e.offsets.popper[a]+=p[a]+m-r[l]);var h=p[a]+p[d]/2-m/2,g=h-c(e.offsets.popper)[a];return g=_(z(r[d]-m,g),0),e.arrowElement=o,e.offsets.arrow={},e.offsets.arrow[a]=Math.round(g),e.offsets.arrow[f]='',e},element:'[x-arrow]'},flip:{order:600,enabled:!0,fn:function(e,t){if(W(e.instance.modifiers,'inner'))return e;if(e.flipped&&e.placement===e.originalPlacement)return e;var o=w(e.instance.popper,e.instance.reference,t.padding,t.boundariesElement),i=e.placement.split('-')[0],n=L(i),r=e.placement.split('-')[1]||'',p=[];switch(t.behavior){case fe.FLIP:p=[i,n];break;case fe.CLOCKWISE:p=K(i);break;case fe.COUNTERCLOCKWISE:p=K(i,!0);break;default:p=t.behavior;}return p.forEach(function(s,d){if(i!==s||p.length===d+1)return e;i=e.placement.split('-')[0],n=L(i);var a=e.offsets.popper,f=e.offsets.reference,l=V,m='left'===i&&l(a.right)>l(f.left)||'right'===i&&l(a.left)l(f.top)||'bottom'===i&&l(a.top)l(o.right),g=l(a.top)l(o.bottom),b='left'===i&&h||'right'===i&&c||'top'===i&&g||'bottom'===i&&u,y=-1!==['top','bottom'].indexOf(i),w=!!t.flipVariations&&(y&&'start'===r&&h||y&&'end'===r&&c||!y&&'start'===r&&g||!y&&'end'===r&&u);(m||b||w)&&(e.flipped=!0,(m||b)&&(i=p[d+1]),w&&(r=j(r)),e.placement=i+(r?'-'+r:''),e.offsets.popper=se({},e.offsets.popper,S(e.instance.popper,e.offsets.reference,e.placement)),e=N(e.instance.modifiers,e,'flip'))}),e},behavior:'flip',padding:5,boundariesElement:'viewport'},inner:{order:700,enabled:!1,fn:function(e){var t=e.placement,o=t.split('-')[0],i=e.offsets,n=i.popper,r=i.reference,p=-1!==['left','right'].indexOf(o),s=-1===['top','left'].indexOf(o);return n[p?'left':'top']=r[t]-(s?n[p?'width':'height']:0),e.placement=L(t),e.offsets.popper=c(n),e}},hide:{order:800,enabled:!0,fn:function(e){if(!F(e.instance.modifiers,'hide','preventOverflow'))return e;var t=e.offsets.reference,o=T(e.instance.modifiers,function(e){return'preventOverflow'===e.name}).boundaries;if(t.bottomo.right||t.top>o.bottom||t.right
', 96 | trigger: 'hover focus', 97 | offset: 0 98 | }; 99 | 100 | var Tooltip = function () { 101 | /** 102 | * Create a new Tooltip.js instance 103 | * @class Tooltip 104 | * @param {HTMLElement} reference - The DOM node used as reference of the tooltip (it can be a jQuery element). 105 | * @param {Object} options 106 | * @param {String} options.placement=bottom 107 | * Placement of the popper accepted values: `top(-start, -end), right(-start, -end), bottom(-start, -end), 108 | * left(-start, -end)` 109 | * @param {HTMLElement|String|false} options.container=false - Append the tooltip to a specific element. 110 | * @param {Number|Object} options.delay=0 111 | * Delay showing and hiding the tooltip (ms) - does not apply to manual trigger type. 112 | * If a number is supplied, delay is applied to both hide/show. 113 | * Object structure is: `{ show: 500, hide: 100 }` 114 | * @param {Boolean} options.html=false - Insert HTML into the tooltip. If false, the content will inserted with `innerText`. 115 | * @param {String|PlacementFunction} options.placement='top' - One of the allowed placements, or a function returning one of them. 116 | * @param {String} [options.template=''] 117 | * Base HTML to used when creating the tooltip. 118 | * The tooltip's `title` will be injected into the `.tooltip-inner` or `.tooltip__inner`. 119 | * `.tooltip-arrow` or `.tooltip__arrow` will become the tooltip's arrow. 120 | * The outermost wrapper element should have the `.tooltip` class. 121 | * @param {String|HTMLElement|TitleFunction} options.title='' - Default title value if `title` attribute isn't present. 122 | * @param {String} [options.trigger='hover focus'] 123 | * How tooltip is triggered - click, hover, focus, manual. 124 | * You may pass multiple triggers; separate them with a space. `manual` cannot be combined with any other trigger. 125 | * @param {HTMLElement} options.boundariesElement 126 | * The element used as boundaries for the tooltip. For more information refer to Popper.js' 127 | * [boundariesElement docs](https://popper.js.org/popper-documentation.html) 128 | * @param {Number|String} options.offset=0 - Offset of the tooltip relative to its reference. For more information refer to Popper.js' 129 | * [offset docs](https://popper.js.org/popper-documentation.html) 130 | * @param {Object} options.popperOptions={} - Popper options, will be passed directly to popper instance. For more information refer to Popper.js' 131 | * [options docs](https://popper.js.org/popper-documentation.html) 132 | * @return {Object} instance - The generated tooltip instance 133 | */ 134 | function Tooltip(reference, options) { 135 | classCallCheck(this, Tooltip); 136 | 137 | _initialiseProps.call(this); 138 | 139 | // apply user options over default ones 140 | options = _extends({}, DEFAULT_OPTIONS, options); 141 | 142 | reference.jquery && (reference = reference[0]); 143 | 144 | // cache reference and options 145 | this.reference = reference; 146 | this.options = options; 147 | 148 | // get events list 149 | var events = typeof options.trigger === 'string' ? options.trigger.split(' ').filter(function (trigger) { 150 | return ['click', 'hover', 'focus'].indexOf(trigger) !== -1; 151 | }) : []; 152 | 153 | // set initial state 154 | this._isOpen = false; 155 | 156 | // set event listeners 157 | this._setEventListeners(reference, events, options); 158 | } 159 | 160 | // 161 | // Public methods 162 | // 163 | 164 | /** 165 | * Reveals an element's tooltip. This is considered a "manual" triggering of the tooltip. 166 | * Tooltips with zero-length titles are never displayed. 167 | * @method Tooltip#show 168 | * @memberof Tooltip 169 | */ 170 | 171 | 172 | /** 173 | * Hides an element’s tooltip. This is considered a “manual” triggering of the tooltip. 174 | * @method Tooltip#hide 175 | * @memberof Tooltip 176 | */ 177 | 178 | 179 | /** 180 | * Hides and destroys an element’s tooltip. 181 | * @method Tooltip#dispose 182 | * @memberof Tooltip 183 | */ 184 | 185 | 186 | /** 187 | * Toggles an element’s tooltip. This is considered a “manual” triggering of the tooltip. 188 | * @method Tooltip#toggle 189 | * @memberof Tooltip 190 | */ 191 | 192 | 193 | // 194 | // Defaults 195 | // 196 | 197 | 198 | // 199 | // Private methods 200 | // 201 | 202 | createClass(Tooltip, [{ 203 | key: '_create', 204 | 205 | 206 | /** 207 | * Creates a new tooltip node 208 | * @memberof Tooltip 209 | * @private 210 | * @param {HTMLElement} reference 211 | * @param {String} template 212 | * @param {String|HTMLElement|TitleFunction} title 213 | * @param {Boolean} allowHtml 214 | * @return {HTMLelement} tooltipNode 215 | */ 216 | value: function _create(reference, template, title, allowHtml) { 217 | // create tooltip element 218 | var tooltipGenerator = window.document.createElement('div'); 219 | tooltipGenerator.innerHTML = template.trim(); 220 | var tooltipNode = tooltipGenerator.childNodes[0]; 221 | 222 | // add unique ID to our tooltip (needed for accessibility reasons) 223 | tooltipNode.id = 'tooltip_' + Math.random().toString(36).substr(2, 10); 224 | 225 | // set initial `aria-hidden` state to `false` (it's visible!) 226 | tooltipNode.setAttribute('aria-hidden', 'false'); 227 | 228 | // add title to tooltip 229 | var titleNode = tooltipGenerator.querySelector(this.innerSelector); 230 | if (title.nodeType === 1) { 231 | // if title is a node, append it only if allowHtml is true 232 | allowHtml && titleNode.appendChild(title); 233 | } else if (isFunction(title)) { 234 | // if title is a function, call it and set innerText or innerHtml depending by `allowHtml` value 235 | var titleText = title.call(reference); 236 | allowHtml ? titleNode.innerHTML = titleText : titleNode.innerText = titleText; 237 | } else { 238 | // if it's just a simple text, set innerText or innerHtml depending by `allowHtml` value 239 | allowHtml ? titleNode.innerHTML = title : titleNode.innerText = title; 240 | } 241 | 242 | // return the generated tooltip node 243 | return tooltipNode; 244 | } 245 | }, { 246 | key: '_show', 247 | value: function _show(reference, options) { 248 | // don't show if it's already visible 249 | if (this._isOpen) { 250 | return this; 251 | } 252 | this._isOpen = true; 253 | 254 | // if the tooltipNode already exists, just show it 255 | if (this._tooltipNode) { 256 | this._tooltipNode.style.display = ''; 257 | this._tooltipNode.setAttribute('aria-hidden', 'false'); 258 | this.popperInstance.update(); 259 | return this; 260 | } 261 | 262 | // get title 263 | var title = reference.getAttribute('title') || options.title; 264 | 265 | // don't show tooltip if no title is defined 266 | if (!title) { 267 | return this; 268 | } 269 | 270 | // create tooltip node 271 | var tooltipNode = this._create(reference, options.template, title, options.html); 272 | 273 | // Add `aria-describedby` to our reference element for accessibility reasons 274 | reference.setAttribute('aria-describedby', tooltipNode.id); 275 | 276 | // append tooltip to container 277 | var container = this._findContainer(options.container, reference); 278 | 279 | this._append(tooltipNode, container); 280 | 281 | var popperOptions = _extends({}, options.popperOptions, { 282 | placement: options.placement 283 | }); 284 | 285 | popperOptions.modifiers = _extends({}, popperOptions.modifiers, { 286 | arrow: { 287 | element: this.arrowSelector 288 | } 289 | }); 290 | 291 | if (options.boundariesElement) { 292 | popperOptions.modifiers.preventOverflow = { 293 | boundariesElement: options.boundariesElement 294 | }; 295 | } 296 | 297 | this.popperInstance = new Popper(reference, tooltipNode, popperOptions); 298 | 299 | this._tooltipNode = tooltipNode; 300 | 301 | return this; 302 | } 303 | }, { 304 | key: '_hide', 305 | value: function _hide() /*reference, options*/{ 306 | // don't hide if it's already hidden 307 | if (!this._isOpen) { 308 | return this; 309 | } 310 | 311 | this._isOpen = false; 312 | 313 | // hide tooltipNode 314 | this._tooltipNode.style.display = 'none'; 315 | this._tooltipNode.setAttribute('aria-hidden', 'true'); 316 | 317 | return this; 318 | } 319 | }, { 320 | key: '_dispose', 321 | value: function _dispose() { 322 | var _this = this; 323 | 324 | if (this._tooltipNode) { 325 | this._hide(); 326 | 327 | // destroy instance 328 | this.popperInstance.destroy(); 329 | 330 | // remove event listeners 331 | this._events.forEach(function (_ref) { 332 | var func = _ref.func, 333 | event = _ref.event; 334 | 335 | _this.reference.removeEventListener(event, func); 336 | }); 337 | this._events = []; 338 | 339 | // destroy tooltipNode 340 | this._tooltipNode.parentNode.removeChild(this._tooltipNode); 341 | this._tooltipNode = null; 342 | } 343 | return this; 344 | } 345 | }, { 346 | key: '_findContainer', 347 | value: function _findContainer(container, reference) { 348 | // if container is a query, get the relative element 349 | if (typeof container === 'string') { 350 | container = window.document.querySelector(container); 351 | } else if (container === false) { 352 | // if container is `false`, set it to reference parent 353 | container = reference.parentNode; 354 | } 355 | return container; 356 | } 357 | 358 | /** 359 | * Append tooltip to container 360 | * @memberof Tooltip 361 | * @private 362 | * @param {HTMLElement} tooltip 363 | * @param {HTMLElement|String|false} container 364 | */ 365 | 366 | }, { 367 | key: '_append', 368 | value: function _append(tooltipNode, container) { 369 | container.appendChild(tooltipNode); 370 | } 371 | }, { 372 | key: '_setEventListeners', 373 | value: function _setEventListeners(reference, events, options) { 374 | var _this2 = this; 375 | 376 | var directEvents = []; 377 | var oppositeEvents = []; 378 | 379 | events.forEach(function (event) { 380 | switch (event) { 381 | case 'hover': 382 | directEvents.push('mouseenter'); 383 | oppositeEvents.push('mouseleave'); 384 | break; 385 | case 'focus': 386 | directEvents.push('focus'); 387 | oppositeEvents.push('blur'); 388 | break; 389 | case 'click': 390 | directEvents.push('click'); 391 | oppositeEvents.push('click'); 392 | break; 393 | } 394 | }); 395 | 396 | // schedule show tooltip 397 | directEvents.forEach(function (event) { 398 | var func = function func(evt) { 399 | if (_this2._isOpen === true) { 400 | return; 401 | } 402 | evt.usedByTooltip = true; 403 | _this2._scheduleShow(reference, options.delay, options, evt); 404 | }; 405 | _this2._events.push({ event: event, func: func }); 406 | reference.addEventListener(event, func); 407 | }); 408 | 409 | // schedule hide tooltip 410 | oppositeEvents.forEach(function (event) { 411 | var func = function func(evt) { 412 | if (evt.usedByTooltip === true) { 413 | return; 414 | } 415 | _this2._scheduleHide(reference, options.delay, options, evt); 416 | }; 417 | _this2._events.push({ event: event, func: func }); 418 | reference.addEventListener(event, func); 419 | }); 420 | } 421 | }, { 422 | key: '_scheduleShow', 423 | value: function _scheduleShow(reference, delay, options /*, evt */) { 424 | var _this3 = this; 425 | 426 | // defaults to 0 427 | var computedDelay = delay && delay.show || delay || 0; 428 | window.setTimeout(function () { 429 | return _this3._show(reference, options); 430 | }, computedDelay); 431 | } 432 | }, { 433 | key: '_scheduleHide', 434 | value: function _scheduleHide(reference, delay, options, evt) { 435 | var _this4 = this; 436 | 437 | // defaults to 0 438 | var computedDelay = delay && delay.hide || delay || 0; 439 | window.setTimeout(function () { 440 | if (_this4._isOpen === false) { 441 | return; 442 | } 443 | if (!document.body.contains(_this4._tooltipNode)) { 444 | return; 445 | } 446 | 447 | // if we are hiding because of a mouseleave, we must check that the new 448 | // reference isn't the tooltip, because in this case we don't want to hide it 449 | if (evt.type === 'mouseleave') { 450 | var isSet = _this4._setTooltipNodeEvent(evt, reference, delay, options); 451 | 452 | // if we set the new event, don't hide the tooltip yet 453 | // the new event will take care to hide it if necessary 454 | if (isSet) { 455 | return; 456 | } 457 | } 458 | 459 | _this4._hide(reference, options); 460 | }, computedDelay); 461 | } 462 | }]); 463 | return Tooltip; 464 | }(); 465 | 466 | /** 467 | * Placement function, its context is the Tooltip instance. 468 | * @memberof Tooltip 469 | * @callback PlacementFunction 470 | * @param {HTMLElement} tooltip - tooltip DOM node. 471 | * @param {HTMLElement} reference - reference DOM node. 472 | * @return {String} placement - One of the allowed placement options. 473 | */ 474 | 475 | /** 476 | * Title function, its context is the Tooltip instance. 477 | * @memberof Tooltip 478 | * @callback TitleFunction 479 | * @return {String} placement - The desired title. 480 | */ 481 | 482 | 483 | var _initialiseProps = function _initialiseProps() { 484 | var _this5 = this; 485 | 486 | this.show = function () { 487 | return _this5._show(_this5.reference, _this5.options); 488 | }; 489 | 490 | this.hide = function () { 491 | return _this5._hide(); 492 | }; 493 | 494 | this.dispose = function () { 495 | return _this5._dispose(); 496 | }; 497 | 498 | this.toggle = function () { 499 | if (_this5._isOpen) { 500 | return _this5.hide(); 501 | } else { 502 | return _this5.show(); 503 | } 504 | }; 505 | 506 | this.arrowSelector = '.tooltip-arrow, .tooltip__arrow'; 507 | this.innerSelector = '.tooltip-inner, .tooltip__inner'; 508 | this._events = []; 509 | 510 | this._setTooltipNodeEvent = function (evt, reference, delay, options) { 511 | var relatedreference = evt.relatedreference || evt.toElement; 512 | 513 | var callback = function callback(evt2) { 514 | var relatedreference2 = evt2.relatedreference || evt2.toElement; 515 | 516 | // Remove event listener after call 517 | _this5._tooltipNode.removeEventListener(evt.type, callback); 518 | 519 | // If the new reference is not the reference element 520 | if (!reference.contains(relatedreference2)) { 521 | // Schedule to hide tooltip 522 | _this5._scheduleHide(reference, options.delay, options, evt2); 523 | } 524 | }; 525 | 526 | if (_this5._tooltipNode.contains(relatedreference)) { 527 | // listen to mouseleave on the tooltip element to be able to hide the tooltip 528 | _this5._tooltipNode.addEventListener(evt.type, callback); 529 | return true; 530 | } 531 | 532 | return false; 533 | }; 534 | }; 535 | 536 | return Tooltip; 537 | 538 | }))); 539 | //# sourceMappingURL=tooltip.js.map 540 | -------------------------------------------------------------------------------- /static/vendor/css-hamburgers/hamburgers.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Hamburgers 3 | * @description Tasty CSS-animated hamburgers 4 | * @author Jonathan Suh @jonsuh 5 | * @site https://jonsuh.com/hamburgers 6 | * @link https://github.com/jonsuh/hamburgers 7 | */.hamburger{font:inherit;display:inline-block;overflow:visible;margin:0;padding:15px;cursor:pointer;transition-timing-function:linear;transition-duration:.15s;transition-property:opacity,filter;text-transform:none;color:inherit;border:0;background-color:transparent}.hamburger:hover{opacity:.7}.hamburger-box{position:relative;display:inline-block;width:40px;height:24px}.hamburger-inner{top:50%;display:block;margin-top:-2px}.hamburger-inner,.hamburger-inner:after,.hamburger-inner:before{position:absolute;width:40px;height:4px;transition-timing-function:ease;transition-duration:.15s;transition-property:transform;border-radius:4px;background-color:#000}.hamburger-inner:after,.hamburger-inner:before{display:block;content:''}.hamburger-inner:before{top:-10px}.hamburger-inner:after{bottom:-10px}.hamburger--3dx .hamburger-box{perspective:80px}.hamburger--3dx .hamburger-inner{transition:transform .2s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dx .hamburger-inner:after,.hamburger--3dx .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dx.is-active .hamburger-inner{transform:rotateY(180deg);background-color:transparent}.hamburger--3dx.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dx.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--3dx-r .hamburger-box{perspective:80px}.hamburger--3dx-r .hamburger-inner{transition:transform .2s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dx-r .hamburger-inner:after,.hamburger--3dx-r .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dx-r.is-active .hamburger-inner{transform:rotateY(-180deg);background-color:transparent}.hamburger--3dx-r.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dx-r.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--3dy .hamburger-box{perspective:80px}.hamburger--3dy .hamburger-inner{transition:transform .2s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dy .hamburger-inner:after,.hamburger--3dy .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dy.is-active .hamburger-inner{transform:rotateX(-180deg);background-color:transparent}.hamburger--3dy.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dy.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--3dy-r .hamburger-box{perspective:80px}.hamburger--3dy-r .hamburger-inner{transition:transform .2s cubic-bezier(.645,.045,.355,1),background-color 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dy-r .hamburger-inner:after,.hamburger--3dy-r .hamburger-inner:before{transition:transform 0s cubic-bezier(.645,.045,.355,1) .1s}.hamburger--3dy-r.is-active .hamburger-inner{transform:rotateX(180deg);background-color:transparent}.hamburger--3dy-r.is-active .hamburger-inner:before{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--3dy-r.is-active .hamburger-inner:after{transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--arrow.is-active .hamburger-inner:before{transform:translate3d(-8px,0,0) rotate(-45deg) scaleX(.7)}.hamburger--arrow.is-active .hamburger-inner:after{transform:translate3d(-8px,0,0) rotate(45deg) scaleX(.7)}.hamburger--arrow-r.is-active .hamburger-inner:before{transform:translate3d(8px,0,0) rotate(45deg) scaleX(.7)}.hamburger--arrow-r.is-active .hamburger-inner:after{transform:translate3d(8px,0,0) rotate(-45deg) scaleX(.7)}.hamburger--arrowalt .hamburger-inner:before{transition:top .1s ease .15s,transform .15s cubic-bezier(.165,.84,.44,1)}.hamburger--arrowalt .hamburger-inner:after{transition:bottom .1s ease .15s,transform .15s cubic-bezier(.165,.84,.44,1)}.hamburger--arrowalt.is-active .hamburger-inner:before{top:0;transition:top .1s ease,transform .15s cubic-bezier(.895,.03,.685,.22) .1s;transform:translate3d(-8px,-10px,0) rotate(-45deg) scaleX(.7)}.hamburger--arrowalt.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease,transform .15s cubic-bezier(.895,.03,.685,.22) .1s;transform:translate3d(-8px,10px,0) rotate(45deg) scaleX(.7)}.hamburger--arrowalt-r .hamburger-inner:before{transition:top .1s ease .15s,transform .15s cubic-bezier(.165,.84,.44,1)}.hamburger--arrowalt-r .hamburger-inner:after{transition:bottom .1s ease .15s,transform .15s cubic-bezier(.165,.84,.44,1)}.hamburger--arrowalt-r.is-active .hamburger-inner:before{top:0;transition:top .1s ease,transform .15s cubic-bezier(.895,.03,.685,.22) .1s;transform:translate3d(8px,-10px,0) rotate(45deg) scaleX(.7)}.hamburger--arrowalt-r.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease,transform .15s cubic-bezier(.895,.03,.685,.22) .1s;transform:translate3d(8px,10px,0) rotate(-45deg) scaleX(.7)}.hamburger--boring .hamburger-inner,.hamburger--boring .hamburger-inner:after,.hamburger--boring .hamburger-inner:before{transition-property:none}.hamburger--boring.is-active .hamburger-inner{transform:rotate(45deg)}.hamburger--boring.is-active .hamburger-inner:before{top:0;opacity:0}.hamburger--boring.is-active .hamburger-inner:after{bottom:0;transform:rotate(-90deg)}.hamburger--collapse .hamburger-inner{top:auto;bottom:0;transition-delay:.15s;transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.15s}.hamburger--collapse .hamburger-inner:after{top:-20px;transition:top .3s cubic-bezier(.33333,.66667,.66667,1) .3s,opacity .1s linear}.hamburger--collapse .hamburger-inner:before{transition:top .12s cubic-bezier(.33333,.66667,.66667,1) .3s,transform .15s cubic-bezier(.55,.055,.675,.19)}.hamburger--collapse.is-active .hamburger-inner{transition-delay:.32s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--collapse.is-active .hamburger-inner:after{top:0;transition:top .3s cubic-bezier(.33333,0,.66667,.33333),opacity .1s linear .27s;opacity:0}.hamburger--collapse.is-active .hamburger-inner:before{top:0;transition:top .12s cubic-bezier(.33333,0,.66667,.33333) .18s,transform .15s cubic-bezier(.215,.61,.355,1) .42s;transform:rotate(-90deg)}.hamburger--collapse-r .hamburger-inner{top:auto;bottom:0;transition-delay:.15s;transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.15s}.hamburger--collapse-r .hamburger-inner:after{top:-20px;transition:top .3s cubic-bezier(.33333,.66667,.66667,1) .3s,opacity .1s linear}.hamburger--collapse-r .hamburger-inner:before{transition:top .12s cubic-bezier(.33333,.66667,.66667,1) .3s,transform .15s cubic-bezier(.55,.055,.675,.19)}.hamburger--collapse-r.is-active .hamburger-inner{transition-delay:.32s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:translate3d(0,-10px,0) rotate(45deg)}.hamburger--collapse-r.is-active .hamburger-inner:after{top:0;transition:top .3s cubic-bezier(.33333,0,.66667,.33333),opacity .1s linear .27s;opacity:0}.hamburger--collapse-r.is-active .hamburger-inner:before{top:0;transition:top .12s cubic-bezier(.33333,0,.66667,.33333) .18s,transform .15s cubic-bezier(.215,.61,.355,1) .42s;transform:rotate(90deg)}.hamburger--elastic .hamburger-inner{top:2px;transition-timing-function:cubic-bezier(.68,-.55,.265,1.55);transition-duration:.4s}.hamburger--elastic .hamburger-inner:before{top:10px;transition:opacity .15s ease .4s}.hamburger--elastic .hamburger-inner:after{top:20px;transition:transform .4s cubic-bezier(.68,-.55,.265,1.55)}.hamburger--elastic.is-active .hamburger-inner{transition-delay:.1s;transform:translate3d(0,10px,0) rotate(135deg)}.hamburger--elastic.is-active .hamburger-inner:before{transition-delay:0s;opacity:0}.hamburger--elastic.is-active .hamburger-inner:after{transition-delay:.1s;transform:translate3d(0,-20px,0) rotate(-270deg)}.hamburger--elastic-r .hamburger-inner{top:2px;transition-timing-function:cubic-bezier(.68,-.55,.265,1.55);transition-duration:.4s}.hamburger--elastic-r .hamburger-inner:before{top:10px;transition:opacity .15s ease .4s}.hamburger--elastic-r .hamburger-inner:after{top:20px;transition:transform .4s cubic-bezier(.68,-.55,.265,1.55)}.hamburger--elastic-r.is-active .hamburger-inner{transition-delay:.1s;transform:translate3d(0,10px,0) rotate(-135deg)}.hamburger--elastic-r.is-active .hamburger-inner:before{transition-delay:0s;opacity:0}.hamburger--elastic-r.is-active .hamburger-inner:after{transition-delay:.1s;transform:translate3d(0,-20px,0) rotate(270deg)}.hamburger--emphatic{overflow:hidden}.hamburger--emphatic .hamburger-inner{transition:background-color .2s ease-in .25s}.hamburger--emphatic .hamburger-inner:before{left:0;transition:transform .2s cubic-bezier(.6,.04,.98,.335),top .05s linear .2s,left .2s ease-in .25s}.hamburger--emphatic .hamburger-inner:after{top:10px;right:0;transition:transform .2s cubic-bezier(.6,.04,.98,.335),top .05s linear .2s,right .2s ease-in .25s}.hamburger--emphatic.is-active .hamburger-inner{transition-delay:0s;transition-timing-function:ease-out;background-color:transparent}.hamburger--emphatic.is-active .hamburger-inner:before{top:-80px;left:-80px;transition:left .2s ease-out,top .05s linear .2s,transform .2s cubic-bezier(.075,.82,.165,1) .25s;transform:translate3d(80px,80px,0) rotate(45deg)}.hamburger--emphatic.is-active .hamburger-inner:after{top:-80px;right:-80px;transition:right .2s ease-out,top .05s linear .2s,transform .2s cubic-bezier(.075,.82,.165,1) .25s;transform:translate3d(-80px,80px,0) rotate(-45deg)}.hamburger--emphatic-r{overflow:hidden}.hamburger--emphatic-r .hamburger-inner{transition:background-color .2s ease-in .25s}.hamburger--emphatic-r .hamburger-inner:before{left:0;transition:transform .2s cubic-bezier(.6,.04,.98,.335),top .05s linear .2s,left .2s ease-in .25s}.hamburger--emphatic-r .hamburger-inner:after{top:10px;right:0;transition:transform .2s cubic-bezier(.6,.04,.98,.335),top .05s linear .2s,right .2s ease-in .25s}.hamburger--emphatic-r.is-active .hamburger-inner{transition-delay:0s;transition-timing-function:ease-out;background-color:transparent}.hamburger--emphatic-r.is-active .hamburger-inner:before{top:80px;left:-80px;transition:left .2s ease-out,top .05s linear .2s,transform .2s cubic-bezier(.075,.82,.165,1) .25s;transform:translate3d(80px,-80px,0) rotate(-45deg)}.hamburger--emphatic-r.is-active .hamburger-inner:after{top:80px;right:-80px;transition:right .2s ease-out,top .05s linear .2s,transform .2s cubic-bezier(.075,.82,.165,1) .25s;transform:translate3d(-80px,-80px,0) rotate(45deg)}.hamburger--slider .hamburger-inner{top:2px}.hamburger--slider .hamburger-inner:before{top:10px;transition-timing-function:ease;transition-duration:.2s;transition-property:transform,opacity}.hamburger--slider .hamburger-inner:after{top:20px}.hamburger--slider.is-active .hamburger-inner{transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--slider.is-active .hamburger-inner:before{transform:rotate(-45deg) translate3d(-5.71429px,-6px,0);opacity:0}.hamburger--slider.is-active .hamburger-inner:after{transform:translate3d(0,-20px,0) rotate(-90deg)}.hamburger--slider-r .hamburger-inner{top:2px}.hamburger--slider-r .hamburger-inner:before{top:10px;transition-timing-function:ease;transition-duration:.2s;transition-property:transform,opacity}.hamburger--slider-r .hamburger-inner:after{top:20px}.hamburger--slider-r.is-active .hamburger-inner{transform:translate3d(0,10px,0) rotate(-45deg)}.hamburger--slider-r.is-active .hamburger-inner:before{transform:rotate(45deg) translate3d(5.71429px,-6px,0);opacity:0}.hamburger--slider-r.is-active .hamburger-inner:after{transform:translate3d(0,-20px,0) rotate(90deg)}.hamburger--spring .hamburger-inner{top:2px;transition:background-color 0s linear .15s}.hamburger--spring .hamburger-inner:before{top:10px;transition:top .12s cubic-bezier(.33333,.66667,.66667,1) .3s,transform .15s cubic-bezier(.55,.055,.675,.19)}.hamburger--spring .hamburger-inner:after{top:20px;transition:top .3s cubic-bezier(.33333,.66667,.66667,1) .3s,transform .15s cubic-bezier(.55,.055,.675,.19)}.hamburger--spring.is-active .hamburger-inner{transition-delay:.32s;background-color:transparent}.hamburger--spring.is-active .hamburger-inner:before{top:0;transition:top .12s cubic-bezier(.33333,0,.66667,.33333) .18s,transform .15s cubic-bezier(.215,.61,.355,1) .32s;transform:translate3d(0,10px,0) rotate(45deg)}.hamburger--spring.is-active .hamburger-inner:after{top:0;transition:top .3s cubic-bezier(.33333,0,.66667,.33333),transform .15s cubic-bezier(.215,.61,.355,1) .32s;transform:translate3d(0,10px,0) rotate(-45deg)}.hamburger--spring-r .hamburger-inner{top:auto;bottom:0;transition-delay:0s;transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.15s}.hamburger--spring-r .hamburger-inner:after{top:-20px;transition:top .3s cubic-bezier(.33333,.66667,.66667,1) .3s,opacity 0s linear}.hamburger--spring-r .hamburger-inner:before{transition:top .12s cubic-bezier(.33333,.66667,.66667,1) .3s,transform .15s cubic-bezier(.55,.055,.675,.19)}.hamburger--spring-r.is-active .hamburger-inner{transition-delay:.32s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:translate3d(0,-10px,0) rotate(-45deg)}.hamburger--spring-r.is-active .hamburger-inner:after{top:0;transition:top .3s cubic-bezier(.33333,0,.66667,.33333),opacity 0s linear .32s;opacity:0}.hamburger--spring-r.is-active .hamburger-inner:before{top:0;transition:top .12s cubic-bezier(.33333,0,.66667,.33333) .18s,transform .15s cubic-bezier(.215,.61,.355,1) .32s;transform:rotate(90deg)}.hamburger--stand .hamburger-inner{transition:transform .1s cubic-bezier(.55,.055,.675,.19) .22s,background-color 0s linear .1s}.hamburger--stand .hamburger-inner:before{transition:top .1s ease-in .1s,transform .1s cubic-bezier(.55,.055,.675,.19) 0s}.hamburger--stand .hamburger-inner:after{transition:bottom .1s ease-in .1s,transform .1s cubic-bezier(.55,.055,.675,.19) 0s}.hamburger--stand.is-active .hamburger-inner{transition:transform .1s cubic-bezier(.215,.61,.355,1) 0s,background-color 0s linear .22s;transform:rotate(90deg);background-color:transparent}.hamburger--stand.is-active .hamburger-inner:before{top:0;transition:top .1s ease-out .12s,transform .1s cubic-bezier(.215,.61,.355,1) .22s;transform:rotate(-45deg)}.hamburger--stand.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease-out .12s,transform .1s cubic-bezier(.215,.61,.355,1) .22s;transform:rotate(45deg)}.hamburger--stand-r .hamburger-inner{transition:transform .1s cubic-bezier(.55,.055,.675,.19) .22s,background-color 0s linear .1s}.hamburger--stand-r .hamburger-inner:before{transition:top .1s ease-in .1s,transform .1s cubic-bezier(.55,.055,.675,.19) 0s}.hamburger--stand-r .hamburger-inner:after{transition:bottom .1s ease-in .1s,transform .1s cubic-bezier(.55,.055,.675,.19) 0s}.hamburger--stand-r.is-active .hamburger-inner{transition:transform .1s cubic-bezier(.215,.61,.355,1) 0s,background-color 0s linear .22s;transform:rotate(-90deg);background-color:transparent}.hamburger--stand-r.is-active .hamburger-inner:before{top:0;transition:top .1s ease-out .12s,transform .1s cubic-bezier(.215,.61,.355,1) .22s;transform:rotate(-45deg)}.hamburger--stand-r.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease-out .12s,transform .1s cubic-bezier(.215,.61,.355,1) .22s;transform:rotate(45deg)}.hamburger--spin .hamburger-inner{transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.3s}.hamburger--spin .hamburger-inner:before{transition:top .1s ease-in .34s,opacity .1s ease-in}.hamburger--spin .hamburger-inner:after{transition:bottom .1s ease-in .34s,transform .3s cubic-bezier(.55,.055,.675,.19)}.hamburger--spin.is-active .hamburger-inner{transition-delay:.14s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:rotate(225deg)}.hamburger--spin.is-active .hamburger-inner:before{top:0;transition:top .1s ease-out,opacity .1s ease-out .14s;opacity:0}.hamburger--spin.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease-out,transform .3s cubic-bezier(.215,.61,.355,1) .14s;transform:rotate(-90deg)}.hamburger--spin-r .hamburger-inner{transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.3s}.hamburger--spin-r .hamburger-inner:before{transition:top .1s ease-in .34s,opacity .1s ease-in}.hamburger--spin-r .hamburger-inner:after{transition:bottom .1s ease-in .34s,transform .3s cubic-bezier(.55,.055,.675,.19)}.hamburger--spin-r.is-active .hamburger-inner{transition-delay:.14s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:rotate(-225deg)}.hamburger--spin-r.is-active .hamburger-inner:before{top:0;transition:top .1s ease-out,opacity .1s ease-out .14s;opacity:0}.hamburger--spin-r.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease-out,transform .3s cubic-bezier(.215,.61,.355,1) .14s;transform:rotate(90deg)}.hamburger--squeeze .hamburger-inner{transition-timing-function:cubic-bezier(.55,.055,.675,.19);transition-duration:.1s}.hamburger--squeeze .hamburger-inner:before{transition:top .1s ease .14s,opacity .1s ease}.hamburger--squeeze .hamburger-inner:after{transition:bottom .1s ease .14s,transform .1s cubic-bezier(.55,.055,.675,.19)}.hamburger--squeeze.is-active .hamburger-inner{transition-delay:.14s;transition-timing-function:cubic-bezier(.215,.61,.355,1);transform:rotate(45deg)}.hamburger--squeeze.is-active .hamburger-inner:before{top:0;transition:top .1s ease,opacity .1s ease .14s;opacity:0}.hamburger--squeeze.is-active .hamburger-inner:after{bottom:0;transition:bottom .1s ease,transform .1s cubic-bezier(.215,.61,.355,1) .14s;transform:rotate(-90deg)}.hamburger--vortex .hamburger-inner{transition-timing-function:cubic-bezier(.19,1,.22,1);transition-duration:.3s}.hamburger--vortex .hamburger-inner:after,.hamburger--vortex .hamburger-inner:before{transition-delay:.1s;transition-timing-function:linear;transition-duration:0s}.hamburger--vortex .hamburger-inner:before{transition-property:top,opacity}.hamburger--vortex .hamburger-inner:after{transition-property:bottom,transform}.hamburger--vortex.is-active .hamburger-inner{transition-timing-function:cubic-bezier(.19,1,.22,1);transform:rotate(765deg)}.hamburger--vortex.is-active .hamburger-inner:after,.hamburger--vortex.is-active .hamburger-inner:before{transition-delay:0s}.hamburger--vortex.is-active .hamburger-inner:before{top:0;opacity:0}.hamburger--vortex.is-active .hamburger-inner:after{bottom:0;transform:rotate(90deg)}.hamburger--vortex-r .hamburger-inner{transition-timing-function:cubic-bezier(.19,1,.22,1);transition-duration:.3s}.hamburger--vortex-r .hamburger-inner:after,.hamburger--vortex-r .hamburger-inner:before{transition-delay:.1s;transition-timing-function:linear;transition-duration:0s}.hamburger--vortex-r .hamburger-inner:before{transition-property:top,opacity}.hamburger--vortex-r .hamburger-inner:after{transition-property:bottom,transform}.hamburger--vortex-r.is-active .hamburger-inner{transition-timing-function:cubic-bezier(.19,1,.22,1);transform:rotate(-765deg)}.hamburger--vortex-r.is-active .hamburger-inner:after,.hamburger--vortex-r.is-active .hamburger-inner:before{transition-delay:0s}.hamburger--vortex-r.is-active .hamburger-inner:before{top:0;opacity:0}.hamburger--vortex-r.is-active .hamburger-inner:after{bottom:0;transform:rotate(-90deg)} -------------------------------------------------------------------------------- /static/vendor/select2/select2.css: -------------------------------------------------------------------------------- 1 | .select2-container { 2 | box-sizing: border-box; 3 | display: inline-block; 4 | margin: 0; 5 | position: relative; 6 | vertical-align: middle; } 7 | .select2-container .select2-selection--single { 8 | box-sizing: border-box; 9 | cursor: pointer; 10 | display: block; 11 | height: 28px; 12 | user-select: none; 13 | -webkit-user-select: none; } 14 | .select2-container .select2-selection--single .select2-selection__rendered { 15 | display: block; 16 | padding-left: 8px; 17 | padding-right: 20px; 18 | overflow: hidden; 19 | text-overflow: ellipsis; 20 | white-space: nowrap; } 21 | .select2-container .select2-selection--single .select2-selection__clear { 22 | position: relative; } 23 | .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered { 24 | padding-right: 8px; 25 | padding-left: 20px; } 26 | .select2-container .select2-selection--multiple { 27 | box-sizing: border-box; 28 | cursor: pointer; 29 | display: block; 30 | min-height: 32px; 31 | user-select: none; 32 | -webkit-user-select: none; } 33 | .select2-container .select2-selection--multiple .select2-selection__rendered { 34 | display: inline-block; 35 | overflow: hidden; 36 | padding-left: 8px; 37 | text-overflow: ellipsis; 38 | white-space: nowrap; } 39 | .select2-container .select2-search--inline { 40 | float: left; } 41 | .select2-container .select2-search--inline .select2-search__field { 42 | box-sizing: border-box; 43 | border: none; 44 | font-size: 100%; 45 | margin-top: 5px; 46 | padding: 0; } 47 | .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button { 48 | -webkit-appearance: none; } 49 | 50 | .select2-dropdown { 51 | background-color: white; 52 | border: 1px solid #aaa; 53 | border-radius: 4px; 54 | box-sizing: border-box; 55 | display: block; 56 | position: absolute; 57 | left: -100000px; 58 | width: 100%; 59 | z-index: 1051; } 60 | 61 | .select2-results { 62 | display: block; } 63 | 64 | .select2-results__options { 65 | list-style: none; 66 | margin: 0; 67 | padding: 0; } 68 | 69 | .select2-results__option { 70 | padding: 6px; 71 | user-select: none; 72 | -webkit-user-select: none; } 73 | .select2-results__option[aria-selected] { 74 | cursor: pointer; } 75 | 76 | .select2-container--open .select2-dropdown { 77 | left: 0; } 78 | 79 | .select2-container--open .select2-dropdown--above { 80 | border-bottom: none; 81 | border-bottom-left-radius: 0; 82 | border-bottom-right-radius: 0; } 83 | 84 | .select2-container--open .select2-dropdown--below { 85 | border-top: none; 86 | border-top-left-radius: 0; 87 | border-top-right-radius: 0; } 88 | 89 | .select2-search--dropdown { 90 | display: block; 91 | padding: 4px; } 92 | .select2-search--dropdown .select2-search__field { 93 | padding: 4px; 94 | width: 100%; 95 | box-sizing: border-box; } 96 | .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button { 97 | -webkit-appearance: none; } 98 | .select2-search--dropdown.select2-search--hide { 99 | display: none; } 100 | 101 | .select2-close-mask { 102 | border: 0; 103 | margin: 0; 104 | padding: 0; 105 | display: block; 106 | position: fixed; 107 | left: 0; 108 | top: 0; 109 | min-height: 100%; 110 | min-width: 100%; 111 | height: auto; 112 | width: auto; 113 | opacity: 0; 114 | z-index: 99; 115 | background-color: #fff; 116 | filter: alpha(opacity=0); } 117 | 118 | .select2-hidden-accessible { 119 | border: 0 !important; 120 | clip: rect(0 0 0 0) !important; 121 | height: 1px !important; 122 | margin: -1px !important; 123 | overflow: hidden !important; 124 | padding: 0 !important; 125 | position: absolute !important; 126 | width: 1px !important; } 127 | 128 | .select2-container--default .select2-selection--single { 129 | background-color: #fff; 130 | border: 1px solid #aaa; 131 | border-radius: 4px; } 132 | .select2-container--default .select2-selection--single .select2-selection__rendered { 133 | color: #444; 134 | line-height: 28px; } 135 | .select2-container--default .select2-selection--single .select2-selection__clear { 136 | cursor: pointer; 137 | float: right; 138 | font-weight: bold; } 139 | .select2-container--default .select2-selection--single .select2-selection__placeholder { 140 | color: #999; } 141 | .select2-container--default .select2-selection--single .select2-selection__arrow { 142 | height: 26px; 143 | position: absolute; 144 | top: 1px; 145 | right: 1px; 146 | width: 20px; } 147 | .select2-container--default .select2-selection--single .select2-selection__arrow b { 148 | border-color: #888 transparent transparent transparent; 149 | border-style: solid; 150 | border-width: 5px 4px 0 4px; 151 | height: 0; 152 | left: 50%; 153 | margin-left: -4px; 154 | margin-top: -2px; 155 | position: absolute; 156 | top: 50%; 157 | width: 0; } 158 | 159 | .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear { 160 | float: left; } 161 | 162 | .select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow { 163 | left: 1px; 164 | right: auto; } 165 | 166 | .select2-container--default.select2-container--disabled .select2-selection--single { 167 | background-color: #eee; 168 | cursor: default; } 169 | .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear { 170 | display: none; } 171 | 172 | .select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b { 173 | border-color: transparent transparent #888 transparent; 174 | border-width: 0 4px 5px 4px; } 175 | 176 | .select2-container--default .select2-selection--multiple { 177 | background-color: white; 178 | border: 1px solid #aaa; 179 | border-radius: 4px; 180 | cursor: text; } 181 | .select2-container--default .select2-selection--multiple .select2-selection__rendered { 182 | box-sizing: border-box; 183 | list-style: none; 184 | margin: 0; 185 | padding: 0 5px; 186 | width: 100%; } 187 | .select2-container--default .select2-selection--multiple .select2-selection__rendered li { 188 | list-style: none; } 189 | .select2-container--default .select2-selection--multiple .select2-selection__placeholder { 190 | color: #999; 191 | margin-top: 5px; 192 | float: left; } 193 | .select2-container--default .select2-selection--multiple .select2-selection__clear { 194 | cursor: pointer; 195 | float: right; 196 | font-weight: bold; 197 | margin-top: 5px; 198 | margin-right: 10px; } 199 | .select2-container--default .select2-selection--multiple .select2-selection__choice { 200 | background-color: #e4e4e4; 201 | border: 1px solid #aaa; 202 | border-radius: 4px; 203 | cursor: default; 204 | float: left; 205 | margin-right: 5px; 206 | margin-top: 5px; 207 | padding: 0 5px; } 208 | .select2-container--default .select2-selection--multiple .select2-selection__choice__remove { 209 | color: #999; 210 | cursor: pointer; 211 | display: inline-block; 212 | font-weight: bold; 213 | margin-right: 2px; } 214 | .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover { 215 | color: #333; } 216 | 217 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline { 218 | float: right; } 219 | 220 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice { 221 | margin-left: 5px; 222 | margin-right: auto; } 223 | 224 | .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { 225 | margin-left: 2px; 226 | margin-right: auto; } 227 | 228 | .select2-container--default.select2-container--focus .select2-selection--multiple { 229 | border: solid black 1px; 230 | outline: 0; } 231 | 232 | .select2-container--default.select2-container--disabled .select2-selection--multiple { 233 | background-color: #eee; 234 | cursor: default; } 235 | 236 | .select2-container--default.select2-container--disabled .select2-selection__choice__remove { 237 | display: none; } 238 | 239 | .select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple { 240 | border-top-left-radius: 0; 241 | border-top-right-radius: 0; } 242 | 243 | .select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple { 244 | border-bottom-left-radius: 0; 245 | border-bottom-right-radius: 0; } 246 | 247 | .select2-container--default .select2-search--dropdown .select2-search__field { 248 | border: 1px solid #aaa; } 249 | 250 | .select2-container--default .select2-search--inline .select2-search__field { 251 | background: transparent; 252 | border: none; 253 | outline: 0; 254 | box-shadow: none; 255 | -webkit-appearance: textfield; } 256 | 257 | .select2-container--default .select2-results > .select2-results__options { 258 | max-height: 200px; 259 | overflow-y: auto; } 260 | 261 | .select2-container--default .select2-results__option[role=group] { 262 | padding: 0; } 263 | 264 | .select2-container--default .select2-results__option[aria-disabled=true] { 265 | color: #999; } 266 | 267 | .select2-container--default .select2-results__option[aria-selected=true] { 268 | background-color: #ddd; } 269 | 270 | .select2-container--default .select2-results__option .select2-results__option { 271 | padding-left: 1em; } 272 | .select2-container--default .select2-results__option .select2-results__option .select2-results__group { 273 | padding-left: 0; } 274 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option { 275 | margin-left: -1em; 276 | padding-left: 2em; } 277 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 278 | margin-left: -2em; 279 | padding-left: 3em; } 280 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 281 | margin-left: -3em; 282 | padding-left: 4em; } 283 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 284 | margin-left: -4em; 285 | padding-left: 5em; } 286 | .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option { 287 | margin-left: -5em; 288 | padding-left: 6em; } 289 | 290 | .select2-container--default .select2-results__option--highlighted[aria-selected] { 291 | background-color: #5897fb; 292 | color: white; } 293 | 294 | .select2-container--default .select2-results__group { 295 | cursor: default; 296 | display: block; 297 | padding: 6px; } 298 | 299 | .select2-container--classic .select2-selection--single { 300 | background-color: #f7f7f7; 301 | border: 1px solid #aaa; 302 | border-radius: 4px; 303 | outline: 0; 304 | background-image: -webkit-linear-gradient(top, white 50%, #eeeeee 100%); 305 | background-image: -o-linear-gradient(top, white 50%, #eeeeee 100%); 306 | background-image: linear-gradient(to bottom, white 50%, #eeeeee 100%); 307 | background-repeat: repeat-x; 308 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } 309 | .select2-container--classic .select2-selection--single:focus { 310 | border: 1px solid #5897fb; } 311 | .select2-container--classic .select2-selection--single .select2-selection__rendered { 312 | color: #444; 313 | line-height: 28px; } 314 | .select2-container--classic .select2-selection--single .select2-selection__clear { 315 | cursor: pointer; 316 | float: right; 317 | font-weight: bold; 318 | margin-right: 10px; } 319 | .select2-container--classic .select2-selection--single .select2-selection__placeholder { 320 | color: #999; } 321 | .select2-container--classic .select2-selection--single .select2-selection__arrow { 322 | background-color: #ddd; 323 | border: none; 324 | border-left: 1px solid #aaa; 325 | border-top-right-radius: 4px; 326 | border-bottom-right-radius: 4px; 327 | height: 26px; 328 | position: absolute; 329 | top: 1px; 330 | right: 1px; 331 | width: 20px; 332 | background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%); 333 | background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%); 334 | background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%); 335 | background-repeat: repeat-x; 336 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0); } 337 | .select2-container--classic .select2-selection--single .select2-selection__arrow b { 338 | border-color: #888 transparent transparent transparent; 339 | border-style: solid; 340 | border-width: 5px 4px 0 4px; 341 | height: 0; 342 | left: 50%; 343 | margin-left: -4px; 344 | margin-top: -2px; 345 | position: absolute; 346 | top: 50%; 347 | width: 0; } 348 | 349 | .select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear { 350 | float: left; } 351 | 352 | .select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow { 353 | border: none; 354 | border-right: 1px solid #aaa; 355 | border-radius: 0; 356 | border-top-left-radius: 4px; 357 | border-bottom-left-radius: 4px; 358 | left: 1px; 359 | right: auto; } 360 | 361 | .select2-container--classic.select2-container--open .select2-selection--single { 362 | border: 1px solid #5897fb; } 363 | .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow { 364 | background: transparent; 365 | border: none; } 366 | .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b { 367 | border-color: transparent transparent #888 transparent; 368 | border-width: 0 4px 5px 4px; } 369 | 370 | .select2-container--classic.select2-container--open.select2-container--above .select2-selection--single { 371 | border-top: none; 372 | border-top-left-radius: 0; 373 | border-top-right-radius: 0; 374 | background-image: -webkit-linear-gradient(top, white 0%, #eeeeee 50%); 375 | background-image: -o-linear-gradient(top, white 0%, #eeeeee 50%); 376 | background-image: linear-gradient(to bottom, white 0%, #eeeeee 50%); 377 | background-repeat: repeat-x; 378 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0); } 379 | 380 | .select2-container--classic.select2-container--open.select2-container--below .select2-selection--single { 381 | border-bottom: none; 382 | border-bottom-left-radius: 0; 383 | border-bottom-right-radius: 0; 384 | background-image: -webkit-linear-gradient(top, #eeeeee 50%, white 100%); 385 | background-image: -o-linear-gradient(top, #eeeeee 50%, white 100%); 386 | background-image: linear-gradient(to bottom, #eeeeee 50%, white 100%); 387 | background-repeat: repeat-x; 388 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0); } 389 | 390 | .select2-container--classic .select2-selection--multiple { 391 | background-color: white; 392 | border: 1px solid #aaa; 393 | border-radius: 4px; 394 | cursor: text; 395 | outline: 0; } 396 | .select2-container--classic .select2-selection--multiple:focus { 397 | border: 1px solid #5897fb; } 398 | .select2-container--classic .select2-selection--multiple .select2-selection__rendered { 399 | list-style: none; 400 | margin: 0; 401 | padding: 0 5px; } 402 | .select2-container--classic .select2-selection--multiple .select2-selection__clear { 403 | display: none; } 404 | .select2-container--classic .select2-selection--multiple .select2-selection__choice { 405 | background-color: #e4e4e4; 406 | border: 1px solid #aaa; 407 | border-radius: 4px; 408 | cursor: default; 409 | float: left; 410 | margin-right: 5px; 411 | margin-top: 5px; 412 | padding: 0 5px; } 413 | .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove { 414 | color: #888; 415 | cursor: pointer; 416 | display: inline-block; 417 | font-weight: bold; 418 | margin-right: 2px; } 419 | .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover { 420 | color: #555; } 421 | 422 | .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { 423 | float: right; } 424 | 425 | .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice { 426 | margin-left: 5px; 427 | margin-right: auto; } 428 | 429 | .select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove { 430 | margin-left: 2px; 431 | margin-right: auto; } 432 | 433 | .select2-container--classic.select2-container--open .select2-selection--multiple { 434 | border: 1px solid #5897fb; } 435 | 436 | .select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple { 437 | border-top: none; 438 | border-top-left-radius: 0; 439 | border-top-right-radius: 0; } 440 | 441 | .select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple { 442 | border-bottom: none; 443 | border-bottom-left-radius: 0; 444 | border-bottom-right-radius: 0; } 445 | 446 | .select2-container--classic .select2-search--dropdown .select2-search__field { 447 | border: 1px solid #aaa; 448 | outline: 0; } 449 | 450 | .select2-container--classic .select2-search--inline .select2-search__field { 451 | outline: 0; 452 | box-shadow: none; } 453 | 454 | .select2-container--classic .select2-dropdown { 455 | background-color: white; 456 | border: 1px solid transparent; } 457 | 458 | .select2-container--classic .select2-dropdown--above { 459 | border-bottom: none; } 460 | 461 | .select2-container--classic .select2-dropdown--below { 462 | border-top: none; } 463 | 464 | .select2-container--classic .select2-results > .select2-results__options { 465 | max-height: 200px; 466 | overflow-y: auto; } 467 | 468 | .select2-container--classic .select2-results__option[role=group] { 469 | padding: 0; } 470 | 471 | .select2-container--classic .select2-results__option[aria-disabled=true] { 472 | color: grey; } 473 | 474 | .select2-container--classic .select2-results__option--highlighted[aria-selected] { 475 | background-color: #3875d7; 476 | color: white; } 477 | 478 | .select2-container--classic .select2-results__group { 479 | cursor: default; 480 | display: block; 481 | padding: 6px; } 482 | 483 | .select2-container--classic.select2-container--open .select2-dropdown { 484 | border-color: #5897fb; } -------------------------------------------------------------------------------- /static/vendor/select2/select2.min.css: -------------------------------------------------------------------------------- 1 | .select2-container{box-sizing:border-box;display:inline-block;margin:0;position:relative;vertical-align:middle}.select2-container .select2-selection--single{box-sizing:border-box;cursor:pointer;display:block;height:28px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--single .select2-selection__rendered{display:block;padding-left:8px;padding-right:20px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-selection--single .select2-selection__clear{position:relative}.select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered{padding-right:8px;padding-left:20px}.select2-container .select2-selection--multiple{box-sizing:border-box;cursor:pointer;display:block;min-height:32px;user-select:none;-webkit-user-select:none}.select2-container .select2-selection--multiple .select2-selection__rendered{display:inline-block;overflow:hidden;padding-left:8px;text-overflow:ellipsis;white-space:nowrap}.select2-container .select2-search--inline{float:left}.select2-container .select2-search--inline .select2-search__field{box-sizing:border-box;border:none;font-size:100%;margin-top:5px;padding:0}.select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-dropdown{background-color:white;border:1px solid #aaa;border-radius:4px;box-sizing:border-box;display:block;position:absolute;left:-100000px;width:100%;z-index:1051}.select2-results{display:block}.select2-results__options{list-style:none;margin:0;padding:0}.select2-results__option{padding:6px;user-select:none;-webkit-user-select:none}.select2-results__option[aria-selected]{cursor:pointer}.select2-container--open .select2-dropdown{left:0}.select2-container--open .select2-dropdown--above{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--open .select2-dropdown--below{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-search--dropdown{display:block;padding:4px}.select2-search--dropdown .select2-search__field{padding:4px;width:100%;box-sizing:border-box}.select2-search--dropdown .select2-search__field::-webkit-search-cancel-button{-webkit-appearance:none}.select2-search--dropdown.select2-search--hide{display:none}.select2-close-mask{border:0;margin:0;padding:0;display:block;position:fixed;left:0;top:0;min-height:100%;min-width:100%;height:auto;width:auto;opacity:0;z-index:99;background-color:#fff;filter:alpha(opacity=0)}.select2-hidden-accessible{border:0 !important;clip:rect(0 0 0 0) !important;height:1px !important;margin:-1px !important;overflow:hidden !important;padding:0 !important;position:absolute !important;width:1px !important}.select2-container--default .select2-selection--single{background-color:#fff;border:1px solid #aaa;border-radius:4px}.select2-container--default .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--default .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold}.select2-container--default .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--default .select2-selection--single .select2-selection__arrow{height:26px;position:absolute;top:1px;right:1px;width:20px}.select2-container--default .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow{left:1px;right:auto}.select2-container--default.select2-container--disabled .select2-selection--single{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear{display:none}.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--default .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text}.select2-container--default .select2-selection--multiple .select2-selection__rendered{box-sizing:border-box;list-style:none;margin:0;padding:0 5px;width:100%}.select2-container--default .select2-selection--multiple .select2-selection__rendered li{list-style:none}.select2-container--default .select2-selection--multiple .select2-selection__placeholder{color:#999;margin-top:5px;float:left}.select2-container--default .select2-selection--multiple .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-top:5px;margin-right:10px}.select2-container--default .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove{color:#999;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover{color:#333}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder,.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-search--inline{float:right}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--default.select2-container--focus .select2-selection--multiple{border:solid black 1px;outline:0}.select2-container--default.select2-container--disabled .select2-selection--multiple{background-color:#eee;cursor:default}.select2-container--default.select2-container--disabled .select2-selection__choice__remove{display:none}.select2-container--default.select2-container--open.select2-container--above .select2-selection--single,.select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple{border-top-left-radius:0;border-top-right-radius:0}.select2-container--default.select2-container--open.select2-container--below .select2-selection--single,.select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--default .select2-search--dropdown .select2-search__field{border:1px solid #aaa}.select2-container--default .select2-search--inline .select2-search__field{background:transparent;border:none;outline:0;box-shadow:none;-webkit-appearance:textfield}.select2-container--default .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--default .select2-results__option[role=group]{padding:0}.select2-container--default .select2-results__option[aria-disabled=true]{color:#999}.select2-container--default .select2-results__option[aria-selected=true]{background-color:#ddd}.select2-container--default .select2-results__option .select2-results__option{padding-left:1em}.select2-container--default .select2-results__option .select2-results__option .select2-results__group{padding-left:0}.select2-container--default .select2-results__option .select2-results__option .select2-results__option{margin-left:-1em;padding-left:2em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-2em;padding-left:3em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-3em;padding-left:4em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-4em;padding-left:5em}.select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option{margin-left:-5em;padding-left:6em}.select2-container--default .select2-results__option--highlighted[aria-selected]{background-color:#5897fb;color:white}.select2-container--default .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic .select2-selection--single{background-color:#f7f7f7;border:1px solid #aaa;border-radius:4px;outline:0;background-image:-webkit-linear-gradient(top, #fff 50%, #eee 100%);background-image:-o-linear-gradient(top, #fff 50%, #eee 100%);background-image:linear-gradient(to bottom, #fff 50%, #eee 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic .select2-selection--single:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--single .select2-selection__rendered{color:#444;line-height:28px}.select2-container--classic .select2-selection--single .select2-selection__clear{cursor:pointer;float:right;font-weight:bold;margin-right:10px}.select2-container--classic .select2-selection--single .select2-selection__placeholder{color:#999}.select2-container--classic .select2-selection--single .select2-selection__arrow{background-color:#ddd;border:none;border-left:1px solid #aaa;border-top-right-radius:4px;border-bottom-right-radius:4px;height:26px;position:absolute;top:1px;right:1px;width:20px;background-image:-webkit-linear-gradient(top, #eee 50%, #ccc 100%);background-image:-o-linear-gradient(top, #eee 50%, #ccc 100%);background-image:linear-gradient(to bottom, #eee 50%, #ccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFCCCCCC', GradientType=0)}.select2-container--classic .select2-selection--single .select2-selection__arrow b{border-color:#888 transparent transparent transparent;border-style:solid;border-width:5px 4px 0 4px;height:0;left:50%;margin-left:-4px;margin-top:-2px;position:absolute;top:50%;width:0}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear{float:left}.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow{border:none;border-right:1px solid #aaa;border-radius:0;border-top-left-radius:4px;border-bottom-left-radius:4px;left:1px;right:auto}.select2-container--classic.select2-container--open .select2-selection--single{border:1px solid #5897fb}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow{background:transparent;border:none}.select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b{border-color:transparent transparent #888 transparent;border-width:0 4px 5px 4px}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single{border-top:none;border-top-left-radius:0;border-top-right-radius:0;background-image:-webkit-linear-gradient(top, #fff 0%, #eee 50%);background-image:-o-linear-gradient(top, #fff 0%, #eee 50%);background-image:linear-gradient(to bottom, #fff 0%, #eee 50%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFFFFFFF', endColorstr='#FFEEEEEE', GradientType=0)}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0;background-image:-webkit-linear-gradient(top, #eee 50%, #fff 100%);background-image:-o-linear-gradient(top, #eee 50%, #fff 100%);background-image:linear-gradient(to bottom, #eee 50%, #fff 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#FFEEEEEE', endColorstr='#FFFFFFFF', GradientType=0)}.select2-container--classic .select2-selection--multiple{background-color:white;border:1px solid #aaa;border-radius:4px;cursor:text;outline:0}.select2-container--classic .select2-selection--multiple:focus{border:1px solid #5897fb}.select2-container--classic .select2-selection--multiple .select2-selection__rendered{list-style:none;margin:0;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__clear{display:none}.select2-container--classic .select2-selection--multiple .select2-selection__choice{background-color:#e4e4e4;border:1px solid #aaa;border-radius:4px;cursor:default;float:left;margin-right:5px;margin-top:5px;padding:0 5px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove{color:#888;cursor:pointer;display:inline-block;font-weight:bold;margin-right:2px}.select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover{color:#555}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{float:right}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice{margin-left:5px;margin-right:auto}.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove{margin-left:2px;margin-right:auto}.select2-container--classic.select2-container--open .select2-selection--multiple{border:1px solid #5897fb}.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple{border-bottom:none;border-bottom-left-radius:0;border-bottom-right-radius:0}.select2-container--classic .select2-search--dropdown .select2-search__field{border:1px solid #aaa;outline:0}.select2-container--classic .select2-search--inline .select2-search__field{outline:0;box-shadow:none}.select2-container--classic .select2-dropdown{background-color:#fff;border:1px solid transparent}.select2-container--classic .select2-dropdown--above{border-bottom:none}.select2-container--classic .select2-dropdown--below{border-top:none}.select2-container--classic .select2-results>.select2-results__options{max-height:200px;overflow-y:auto}.select2-container--classic .select2-results__option[role=group]{padding:0}.select2-container--classic .select2-results__option[aria-disabled=true]{color:grey}.select2-container--classic .select2-results__option--highlighted[aria-selected]{background-color:#3875d7;color:#fff}.select2-container--classic .select2-results__group{cursor:default;display:block;padding:6px}.select2-container--classic.select2-container--open .select2-dropdown{border-color:#5897fb} 2 | -------------------------------------------------------------------------------- /static/vendor/tilt/tilt.jquery.min.js: -------------------------------------------------------------------------------- 1 | "use strict";var _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};!function(t){"function"==typeof define&&define.amd?define(["jquery"],t):"object"===("undefined"==typeof module?"undefined":_typeof(module))&&module.exports?module.exports=function(i,s){return void 0===s&&(s="undefined"!=typeof window?require("jquery"):require("jquery")(i)),t(s),s}:t(jQuery)}(function(t){return t.fn.tilt=function(i){var s=function(){this.ticking||(requestAnimationFrame(g.bind(this)),this.ticking=!0)},e=function(){var i=this;t(this).on("mousemove",o),t(this).on("mouseenter",a),this.settings.reset&&t(this).on("mouseleave",l),this.settings.glare&&t(window).on("resize",d.bind(i))},n=function(){var i=this;void 0!==this.timeout&&clearTimeout(this.timeout),t(this).css({transition:this.settings.speed+"ms "+this.settings.easing}),this.settings.glare&&this.glareElement.css({transition:"opacity "+this.settings.speed+"ms "+this.settings.easing}),this.timeout=setTimeout(function(){t(i).css({transition:""}),i.settings.glare&&i.glareElement.css({transition:""})},this.settings.speed)},a=function(i){this.ticking=!1,t(this).css({"will-change":"transform"}),n.call(this),t(this).trigger("tilt.mouseEnter")},r=function(i){return"undefined"==typeof i&&(i={pageX:t(this).offset().left+t(this).outerWidth()/2,pageY:t(this).offset().top+t(this).outerHeight()/2}),{x:i.pageX,y:i.pageY}},o=function(t){this.mousePositions=r(t),s.call(this)},l=function(){n.call(this),this.reset=!0,s.call(this),t(this).trigger("tilt.mouseLeave")},h=function(){var i=t(this).outerWidth(),s=t(this).outerHeight(),e=t(this).offset().left,n=t(this).offset().top,a=(this.mousePositions.x-e)/i,r=(this.mousePositions.y-n)/s,o=(this.settings.maxTilt/2-a*this.settings.maxTilt).toFixed(2),l=(r*this.settings.maxTilt-this.settings.maxTilt/2).toFixed(2),h=Math.atan2(this.mousePositions.x-(e+i/2),-(this.mousePositions.y-(n+s/2)))*(180/Math.PI);return{tiltX:o,tiltY:l,percentageX:100*a,percentageY:100*r,angle:h}},g=function(){return this.transforms=h.call(this),this.reset?(this.reset=!1,t(this).css("transform","perspective("+this.settings.perspective+"px) rotateX(0deg) rotateY(0deg)"),void(this.settings.glare&&(this.glareElement.css("transform","rotate(180deg) translate(-50%, -50%)"),this.glareElement.css("opacity","0")))):(t(this).css("transform","perspective("+this.settings.perspective+"px) rotateX("+("x"===this.settings.disableAxis?0:this.transforms.tiltY)+"deg) rotateY("+("y"===this.settings.disableAxis?0:this.transforms.tiltX)+"deg) scale3d("+this.settings.scale+","+this.settings.scale+","+this.settings.scale+")"),this.settings.glare&&(this.glareElement.css("transform","rotate("+this.transforms.angle+"deg) translate(-50%, -50%)"),this.glareElement.css("opacity",""+this.transforms.percentageY*this.settings.maxGlare/100)),t(this).trigger("change",[this.transforms]),void(this.ticking=!1))},c=function(){var i=this.settings.glarePrerender;if(i||t(this).append('
'),this.glareElementWrapper=t(this).find(".js-tilt-glare"),this.glareElement=t(this).find(".js-tilt-glare-inner"),!i){var s={position:"absolute",top:"0",left:"0",width:"100%",height:"100%"};this.glareElementWrapper.css(s).css({overflow:"hidden","pointer-events":"none"}),this.glareElement.css({position:"absolute",top:"50%",left:"50%","background-image":"linear-gradient(0deg, rgba(255,255,255,0) 0%, rgba(255,255,255,1) 100%)",width:""+2*t(this).outerWidth(),height:""+2*t(this).outerWidth(),transform:"rotate(180deg) translate(-50%, -50%)","transform-origin":"0% 0%",opacity:"0"})}},d=function(){this.glareElement.css({width:""+2*t(this).outerWidth(),height:""+2*t(this).outerWidth()})};return t.fn.tilt.destroy=function(){t(this).each(function(){t(this).find(".js-tilt-glare").remove(),t(this).css({"will-change":"",transform:""}),t(this).off("mousemove mouseenter mouseleave")})},t.fn.tilt.getValues=function(){var i=[];return t(this).each(function(){this.mousePositions=r.call(this),i.push(h.call(this))}),i},t.fn.tilt.reset=function(){t(this).each(function(){var i=this;this.mousePositions=r.call(this),this.settings=t(this).data("settings"),l.call(this),setTimeout(function(){i.reset=!1},this.settings.transition)})},this.each(function(){var s=this;this.settings=t.extend({maxTilt:t(this).is("[data-tilt-max]")?t(this).data("tilt-max"):20,perspective:t(this).is("[data-tilt-perspective]")?t(this).data("tilt-perspective"):300,easing:t(this).is("[data-tilt-easing]")?t(this).data("tilt-easing"):"cubic-bezier(.03,.98,.52,.99)",scale:t(this).is("[data-tilt-scale]")?t(this).data("tilt-scale"):"1",speed:t(this).is("[data-tilt-speed]")?t(this).data("tilt-speed"):"400",transition:!t(this).is("[data-tilt-transition]")||t(this).data("tilt-transition"),disableAxis:t(this).is("[data-tilt-disable-axis]")?t(this).data("tilt-disable-axis"):null,axis:t(this).is("[data-tilt-axis]")?t(this).data("tilt-axis"):null,reset:!t(this).is("[data-tilt-reset]")||t(this).data("tilt-reset"),glare:!!t(this).is("[data-tilt-glare]")&&t(this).data("tilt-glare"),maxGlare:t(this).is("[data-tilt-maxglare]")?t(this).data("tilt-maxglare"):1},i),null!==this.settings.axis&&(console.warn("Tilt.js: the axis setting has been renamed to disableAxis. See https://github.com/gijsroge/tilt.js/pull/26 for more information"),this.settings.disableAxis=this.settings.axis),this.init=function(){t(s).data("settings",s.settings),s.settings.glare&&c.call(s),e.call(s)},this.init()})},t("[data-tilt]").tilt(),!0}); -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 14 | 15 | Bahi Khata 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 | 70 | 71 | {% block content %} 72 | {% endblock %} 73 |
74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 | IMG 7 |
8 | 9 |
10 | 11 | Welcome to
Bahi Khata App 12 |
13 | 14 | 20 |
21 | Copyright 2020 © Bahi Khata App 22 |
23 |
24 |
25 | {% endblock %} -------------------------------------------------------------------------------- /templates/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 | IMG 7 |
8 |
9 | 10 | Login 11 | 12 | {% with messages = get_flashed_messages() %} 13 | {% if messages %} 14 | 17 | {% endif %} 18 | {% endwith %} 19 |
20 | Email 21 | 22 |
23 |
24 | Password 25 | 26 |
27 |
28 |
29 |
30 | 33 |
34 |
35 |
36 |
37 | {% endblock %} -------------------------------------------------------------------------------- /templates/profile.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 | IMG 7 |
8 |
9 | 10 | Welcome {{ name }} 11 | 12 |
13 | Copyright 2020 © Bahi Khata App 14 |
15 |
16 |
17 | {% endblock %} -------------------------------------------------------------------------------- /templates/report.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 84 | 85 | 86 | 87 | 88 | 89 |
91 | Lorem ipsum dolor que ist 92 |
93 | 94 | 95 | 96 | 126 | 127 | 128 | 167 | 168 | 169 | 205 | 206 |
99 | 104 | 105 | 106 | 109 | 110 | 111 | 118 | 119 |
107 | 108 |
113 |

Your annual online spendings report

114 |

115 | You have spent ₹{{ amount }} in the last year 116 |

117 |
120 | 125 |
130 | 135 | 136 | 137 | 159 | 160 |
139 | 140 | 141 | 146 | 147 | 148 | 156 | 157 |
142 |
145 |
150 | 151 | 152 | 153 | 154 |
155 |
158 |
161 | 166 |
171 | 176 | 177 | 178 | 182 | 183 | 184 | 197 | 198 |
179 | 181 |
186 |

187 | 69 Amphitheatre Parkway
188 | Mountain View, CA 420 189 | 190 |

191 | 192 | View Online 193 |   •   194 | Unsubscribe 195 |

196 |
199 | 204 |
207 | 208 | 209 | -------------------------------------------------------------------------------- /templates/signup.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 | IMG 7 |
8 |
9 | 10 | Sign Up 11 | 12 | {% with messages = get_flashed_messages() %} 13 | {% if messages %} 14 | 17 | {% endif %} 18 | {% endwith %} 19 |
20 | Email 21 | 22 |
23 |
24 | Name 25 | 26 |
27 |
28 | Password 29 | 30 |
31 |
32 |
33 |
34 | 37 |
38 |
39 |
40 |
41 | {% endblock %} -------------------------------------------------------------------------------- /templates/thankyou.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 |
5 |
6 | Your Bahi Khata report will be emailed to you shortly 7 |
8 |
9 | 10 | 11 | 12 |
13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /wsgi.py: -------------------------------------------------------------------------------- 1 | from gmail_flask import app 2 | 3 | if __name__ == "__main__": 4 | app.run() 5 | --------------------------------------------------------------------------------