parent
37415e93e3
commit
c4f3892707
@ -0,0 +1,45 @@
|
|||||||
|
from flask import Flask
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
from flask_bcrypt import Bcrypt
|
||||||
|
from flask_login import LoginManager
|
||||||
|
from flask_mail import Mail
|
||||||
|
from minibase.config import Config
|
||||||
|
|
||||||
|
# (DATABASE) Definition
|
||||||
|
db = SQLAlchemy()
|
||||||
|
|
||||||
|
# (PASSWORD) Hashign Program to save paswords safely
|
||||||
|
bcrypt = Bcrypt()
|
||||||
|
|
||||||
|
# (LOGIN) Login manage plugin configuration
|
||||||
|
login_manager = LoginManager()
|
||||||
|
login_manager.login_view = 'users.login'
|
||||||
|
login_manager.login_message_category = 'info' # Boostrap Info Message
|
||||||
|
|
||||||
|
# (EMAIL AGENT) Definition
|
||||||
|
mail = Mail()
|
||||||
|
|
||||||
|
|
||||||
|
def create_minibase(config_class=Config):
|
||||||
|
# (FLASK) Main Flask Application
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config.from_object(Config)
|
||||||
|
# (DATABASE) Initialisation
|
||||||
|
db.init_app(app)
|
||||||
|
# (PASSWORD) Initialisation
|
||||||
|
bcrypt.init_app(app)
|
||||||
|
# (LOGIN) Initialisation
|
||||||
|
login_manager.init_app(app)
|
||||||
|
# (EMAIL AGENT) Initialisation
|
||||||
|
mail.init_app(app)
|
||||||
|
# (FLASK) Importing adn then registering blueprints
|
||||||
|
from minibase.users.routes import users
|
||||||
|
from minibase.posts.routes import posts
|
||||||
|
from minibase.main.routes import main
|
||||||
|
from minibase.errors.handlers import errors
|
||||||
|
app.register_blueprint(users)
|
||||||
|
app.register_blueprint(posts)
|
||||||
|
app.register_blueprint(main)
|
||||||
|
app.register_blueprint(errors)
|
||||||
|
# Retunr The ccreated app
|
||||||
|
return app
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,45 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class themeMinibase():
|
||||||
|
# Basic Color definitions
|
||||||
|
black = "#191717"
|
||||||
|
white = "#f1f1f1"
|
||||||
|
light_blue = "#9bd7d1"
|
||||||
|
dark_blue = "#305d7a"
|
||||||
|
light_orange = "#f9a36c"
|
||||||
|
orange = "#f26628"
|
||||||
|
yellow = "#f8cb66"
|
||||||
|
# Define layout styling
|
||||||
|
layoutBgColor = "background-color: " + white
|
||||||
|
layoutNavbarBgColor = "background-color: " + black
|
||||||
|
# (formUserInput) Used For password email and acount informations
|
||||||
|
userInputFormColor = "background-color: #f1f1ff"
|
||||||
|
userInputFormStyle = {'class': 'form-control form-control-lg'}
|
||||||
|
userInputFormWitdh = "width: 420px;"
|
||||||
|
userInputDivClass = "content-section"
|
||||||
|
tableClass = "table table-striped table-dark"
|
||||||
|
homeOverviewBgColor = "background-color: " + yellow
|
||||||
|
homeNewsBgColor = "background-color: " + light_blue
|
||||||
|
homeSearchBgColor = "background-color: " + light_orange
|
||||||
|
# General Template Definition
|
||||||
|
|
||||||
|
image = "rounded-circle account-img"
|
||||||
|
legend = "border-bottom mb-2"
|
||||||
|
smallInfoTextClass = "text-muted"
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
# (FLASK) Sectret key wich will be used to secure some requests an connections
|
||||||
|
SECRET_KEY = os.environ.get('MINIBASE_SECRET_KEY')
|
||||||
|
|
||||||
|
# (SQLALCHEMY) COnfiguration
|
||||||
|
SQLALCHEMY_DATABASE_URI = os.environ.get('MINIBASE_SQLALCHEMY_DATABASE_URI')
|
||||||
|
|
||||||
|
# (MAIL AGENT) Configure mail Server to send EMails.
|
||||||
|
MAIL_SERVER = os.environ.get('MINIBASE_MAIL_SERVER')
|
||||||
|
MAIL_USERNAME = os.environ.get('MINIBASE_MAIL_USERNAME')
|
||||||
|
MAIL_PASSWORD = os.environ.get('MINIBASE_MAIL_PASSWORD')
|
||||||
|
MAIL_PORT = 465
|
||||||
|
MAIL_USE_TLS = False
|
||||||
|
MAIL_USE_SSL = True
|
Binary file not shown.
@ -0,0 +1,16 @@
|
|||||||
|
from flask import Blueprint, render_template
|
||||||
|
|
||||||
|
errors = Blueprint('errors', __name__)
|
||||||
|
|
||||||
|
@errors.app_errorhandler(404)
|
||||||
|
def error_404(error):
|
||||||
|
return render_template('errors/404.html'), 404
|
||||||
|
|
||||||
|
@errors.app_errorhandler(403)
|
||||||
|
def error_403(error):
|
||||||
|
return render_template('errors/403.html'), 403
|
||||||
|
|
||||||
|
@errors.app_errorhandler(500)
|
||||||
|
def error_500(error):
|
||||||
|
return render_template('errors/500.html'), 500
|
||||||
|
|
Binary file not shown.
@ -0,0 +1,26 @@
|
|||||||
|
from flask import render_template, request, Blueprint
|
||||||
|
from minibase.models import Post
|
||||||
|
from minibase.config import themeMinibase
|
||||||
|
|
||||||
|
# Declaring a blueprint
|
||||||
|
main = Blueprint('main', __name__)
|
||||||
|
|
||||||
|
# Redirect from / and also /home routes to the /
|
||||||
|
@main.route("/")
|
||||||
|
@main.route("/home")
|
||||||
|
def home():
|
||||||
|
# (PAGINATION) Defines the page number that we will start with
|
||||||
|
page = request.args.get('page', 1, type=int)
|
||||||
|
# (POSTS) Query posts usin SQLAlchemy
|
||||||
|
posts = Post.query.order_by(Post.date_posted.asc()).paginate(per_page=2)
|
||||||
|
# (HTML) Renders the template for templates/home.html
|
||||||
|
return render_template('home.html', theme=themeMinibase, posts=posts)
|
||||||
|
|
||||||
|
|
||||||
|
@main.route("/about")
|
||||||
|
def about():
|
||||||
|
return render_template('about.html', theme=themeMinibase, title='About')
|
||||||
|
|
||||||
|
@main.route("/customer")
|
||||||
|
def customer():
|
||||||
|
return render_template('customer.html', theme=themeMinibase, title='About')
|
@ -0,0 +1,49 @@
|
|||||||
|
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
|
||||||
|
from datetime import datetime
|
||||||
|
from minibase import db, login_manager
|
||||||
|
from flask_login import UserMixin
|
||||||
|
from flask import url_for, current_app
|
||||||
|
|
||||||
|
|
||||||
|
@login_manager.user_loader
|
||||||
|
def load_user(user_id):
|
||||||
|
return User.query.get(int(user_id))
|
||||||
|
|
||||||
|
|
||||||
|
class User(db.Model, UserMixin):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
username = db.Column(db.String(20), unique=True, nullable=False)
|
||||||
|
email = db.Column(db.String(120), unique=True, nullable=False)
|
||||||
|
image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
|
||||||
|
password = db.Column(db.String(60), nullable=False)
|
||||||
|
# Additional Querry to link a post wiht an author in the sql this won't be an field
|
||||||
|
posts = db.relationship('Post', backref='author', lazy=True)
|
||||||
|
|
||||||
|
def get_reset_token(self, expires_sec=1800):
|
||||||
|
s = Serializer(current_app.config['SECRET_KEY'], expires_sec)
|
||||||
|
return s.dumps({'user_id': self.id}).decode('utf-8')
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def verify_reset_token(token):
|
||||||
|
s = Serializer(current_app.config['SECRET_KEY'])
|
||||||
|
try:
|
||||||
|
user_id = s.loads(token)['user_id']
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
return User.query.get(user_id)
|
||||||
|
|
||||||
|
# returns a more information-rich, or official, string representation of an object
|
||||||
|
def __repr__(self):
|
||||||
|
return f"User('{self.username}', '{self.email}', '{self.image_file}')"
|
||||||
|
|
||||||
|
|
||||||
|
class Post(db.Model):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
title = db.Column(db.String(100), nullable=False)
|
||||||
|
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
|
||||||
|
content = db.Column(db.Text, nullable=False)
|
||||||
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
|
||||||
|
|
||||||
|
# returns a more information-rich, or official, string representation of an object
|
||||||
|
def __repr__(self):
|
||||||
|
return f"User('{self.title}', '{self.date_posted}')"
|
@ -0,0 +1,17 @@
|
|||||||
|
.bg-kynsight {
|
||||||
|
background-color: #191717;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-section {
|
||||||
|
padding: 10px 20px;
|
||||||
|
border: 1px solid #dddddd;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.account-img {
|
||||||
|
height: 125px;
|
||||||
|
width: 125px;
|
||||||
|
margin-right: 20px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 364 KiB |
After Width: | Height: | Size: 11 KiB |
@ -0,0 +1,5 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>About Page</h1>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,62 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="content-section">
|
||||||
|
<div class="media">
|
||||||
|
<img class="rounded-circle account-img" src="{{ image_file }}">
|
||||||
|
<div class="media-body">
|
||||||
|
<h2 class="account-heading" style="color: {{ theme.orange }};">{{ current_user.username }}</h2>
|
||||||
|
<p class="text-secondary">
|
||||||
|
Name : kerem yollu <br>
|
||||||
|
Address : Meireackerstasse 10 / 8610 Uster / Schweiz <br>
|
||||||
|
Email:{{ current_user.email }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<form method="POST" action="" enctype="multipart/form-data">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group">
|
||||||
|
<legend class="border-bottom mb-4"> Account Info </legend>
|
||||||
|
<div class="form-group" style=" {{ theme.userInputFormWitdh }}">
|
||||||
|
{{ form.username.label(class="form-control-label") }}
|
||||||
|
{% if form.username.errors %}
|
||||||
|
{{ form.username(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.username.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.username(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="form-group" style=" {{ theme.userInputFormWitdh }}">
|
||||||
|
{{ form.email.label(class="form-control-label") }}
|
||||||
|
{% if form.email.errors %}
|
||||||
|
{{ form.email(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.email.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.email(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</br>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.picture.label() }} </br>
|
||||||
|
{{ form.picture(class="form-control-file") }}</br>
|
||||||
|
{% if form.picture.errors %}
|
||||||
|
{% for error in form.picture.errors %}
|
||||||
|
<span class="text-danger">{{ error }}</span></br>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</br>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,40 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="content-section">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group">
|
||||||
|
<legend class="border-bottom mb-4">{{ legend }}</legend>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.title.label(class="form-control-label") }}
|
||||||
|
{% if form.title.errors %}
|
||||||
|
{{ form.title(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.title.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.title(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.content.label(class="form-control-label") }}
|
||||||
|
{% if form.content.errors %}
|
||||||
|
{{ form.content(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.content.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.content(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,130 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form class="form-inline">
|
||||||
|
<input class="form-control mr-sm-2" type="search" placeholder="Customer Name" aria-label="Search">
|
||||||
|
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>Steinel</h4>
|
||||||
|
<ul class="nav nav-tabs card-header-tabs">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="#">Overview</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">Projects</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">Components</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">Sales</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm">
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">TOP PROJ.</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Potential</th>
|
||||||
|
<th scope="col">Delivered</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">1</th>
|
||||||
|
<td>Mark</td>
|
||||||
|
<td>Otto</td>
|
||||||
|
<td>@mdo</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">2</th>
|
||||||
|
<td>Jacob</td>
|
||||||
|
<td>Thornton</td>
|
||||||
|
<td>@fat</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">3</th>
|
||||||
|
<td>Larry</td>
|
||||||
|
<td>the Bird</td>
|
||||||
|
<td>@twitter</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">TOP IC's</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Potential</th>
|
||||||
|
<th scope="col">Delivered</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">1</th>
|
||||||
|
<td>Mark</td>
|
||||||
|
<td>Otto</td>
|
||||||
|
<td>@mdo</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">2</th>
|
||||||
|
<td>Jacob</td>
|
||||||
|
<td>Thornton</td>
|
||||||
|
<td>@fat</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">3</th>
|
||||||
|
<td>Larry</td>
|
||||||
|
<td>the Bird</td>
|
||||||
|
<td>@twitter</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">TOP MAN.</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Potential</th>
|
||||||
|
<th scope="col">Delivered</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">1</th>
|
||||||
|
<td>Mark</td>
|
||||||
|
<td>Otto</td>
|
||||||
|
<td>@mdo</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">2</th>
|
||||||
|
<td>Jacob</td>
|
||||||
|
<td>Thornton</td>
|
||||||
|
<td>@fat</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">3</th>
|
||||||
|
<td>Larry</td>
|
||||||
|
<td>the Bird</td>
|
||||||
|
<td>@twitter</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="#" class="btn btn-primary">Client View</a>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -0,0 +1,9 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="content-section">
|
||||||
|
<h1>Your dont have permission to do that (403)</h1>
|
||||||
|
<p>PLease Check your account and try again</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,9 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="content-section">
|
||||||
|
<h1>Ooops :S Page Not Found (404)</h1>
|
||||||
|
<p>That page doens not exist. Please try another one</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,9 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
cat: templates/errors/500.html: No such file or directory
|
||||||
|
<div class="content-section">
|
||||||
|
<h1>Something Went Wrong (500)</h1>
|
||||||
|
<p>There Was an Error from our side please give us a moment and try again later</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,189 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="container-fluid pt-2">
|
||||||
|
<div class="container-fluid" style="{{ theme.homeOverviewBgColor }}">
|
||||||
|
<h1 class="text-center"> Overwiev </h1>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3> <a href="#">Projects</a> </h3>
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Total</th>
|
||||||
|
<th scope="col">Active</th>
|
||||||
|
<th scope="col">Inactive</th>
|
||||||
|
<th scope="col">ToDo</th>
|
||||||
|
<th scope="col">Warning</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">239</th>
|
||||||
|
<td>200</td>
|
||||||
|
<td>39</td>
|
||||||
|
<td>58</td>
|
||||||
|
<td>5</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<h3> <a href="#">Components</a> </h3>
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Total</th>
|
||||||
|
<th scope="col">Accepted</th>
|
||||||
|
<th scope="col">Declined</th>
|
||||||
|
<th scope="col">Closed</th>
|
||||||
|
<th scope="col">Warning</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">239</th>
|
||||||
|
<td>200</td>
|
||||||
|
<td>39</td>
|
||||||
|
<td>58</td>
|
||||||
|
<td>5</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<h3> <a href="#">Economics</a> </h3>
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Total POS</th>
|
||||||
|
<th scope="col">Max Marg</th>
|
||||||
|
<th scope="col">Min Marg</th>
|
||||||
|
<th scope="col">Avg Marg</th>
|
||||||
|
<th scope="col">Total Rev</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">100'000 CHF</th>
|
||||||
|
<td>35 %</td>
|
||||||
|
<td>12 %</td>
|
||||||
|
<td>23 %</td>
|
||||||
|
<td>12'453 CHF</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid pt-2" style="{{ theme.homeNewsBgColor }}">
|
||||||
|
<h1 class="text-center"> News </h1>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3> <a href="#">Last News</a> </h3>
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Date <a href="#">▲</a></th>
|
||||||
|
<th scope="col">Author</th>
|
||||||
|
<th scope="col">Client</th>
|
||||||
|
<th scope="col">Content</th>
|
||||||
|
<th scope="col">Due-Date</th>
|
||||||
|
<th scope="col">Uregncy<a href="#"> ▲▼</a></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">08.08.23</th>
|
||||||
|
<td>Kerem Yollu</td>
|
||||||
|
<td>Steinel</td>
|
||||||
|
<td>Please Call Stefan concerning the Stm32f0313 delivery that won't be made in time Chris Straub from st is informed</td>
|
||||||
|
<td>16.08.23</td>
|
||||||
|
<td>Normal</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container-fluid pt-2>
|
||||||
|
<div class="container-fluid" style="{{ theme.homeSearchBgColor }}">
|
||||||
|
<h1 class="text-center"> Quick Sreach </h1>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h3> <a href="#">Contacts</a> </h3>
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Company</th>
|
||||||
|
<th scope="col">Mail</th>
|
||||||
|
<th scope="col">Tel</th>
|
||||||
|
<th scope="col">Address</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr> <th scope="row">Stefan Walker</th>
|
||||||
|
<td>Steinel</td>
|
||||||
|
<td>stefan.walker@steinel.com</td>
|
||||||
|
<td>+41554182111</td>
|
||||||
|
<td>Allmeindstrasse 10, 8840 Einsiedeln</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<h3> <a href="#">Projects</a> </h3>
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Customer</th>
|
||||||
|
<th scope="col">Customer Resp.</th>
|
||||||
|
<th scope="col">Kynsight Resp.</th>
|
||||||
|
<th scope="col">Date Created</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">STWH-HS</th>
|
||||||
|
<td>Steinel</td>
|
||||||
|
<td>Stefan Walker</td>
|
||||||
|
<td>Kerem Yollu</td>
|
||||||
|
<td>01.02.2018</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<h3> <a href="#">Components</a> </h3>
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Art.</th>
|
||||||
|
<th scope="col">Manufacturer</th>
|
||||||
|
<th scope="col">Desing In</th>
|
||||||
|
<th scope="col">MDQ</th>
|
||||||
|
<th scope="col">MOQ</th>
|
||||||
|
<th scope="col">MPQ</th>
|
||||||
|
<th scope="col">Price</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">STM32F032G6T6Q</th>
|
||||||
|
<td>StMicroelectronics</td>
|
||||||
|
<td>YES</td>
|
||||||
|
<td>1000</td>
|
||||||
|
<td>500</td>
|
||||||
|
<td>250</td>
|
||||||
|
<td>1.2 USD</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,100 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='main.css') }}">
|
||||||
|
|
||||||
|
{% if title %}
|
||||||
|
<title> MiniBase - {{ title }} </title>
|
||||||
|
{% else %}
|
||||||
|
<title> MiniBase </title>
|
||||||
|
{% endif %}
|
||||||
|
</head>
|
||||||
|
<body style="{{ theme.layoutBgColor }};">
|
||||||
|
<nav class="navbar navbar-expand-lg" style="{{ theme.layoutNavbarBgColor }}">
|
||||||
|
<a class="navbar-brand" style="color: {{ theme.orange }};" href="#">MiniBase</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav mr-auto">
|
||||||
|
|
||||||
|
<!-- Checks if the user is logged in or not-->
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<li class="nav-item"><a class="nav-link" href="{{ url_for('main.home') }}">Overwiev</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="#">Projects</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="{{ url_for('main.customer') }}">Custommer</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="#">Manufacturer</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="#">Contacts</a></li>
|
||||||
|
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Search By</a>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
|
<a class="dropdown-item" href="#">Project Name</a>
|
||||||
|
<a class="dropdown-item" href="#">Customer Name</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" href="#">Project ID</a>
|
||||||
|
<a class="dropdown-item" href="#">Customer ID</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" href="#">Cutsom Options</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<!-- If not then -->
|
||||||
|
{% else %}
|
||||||
|
<li class="nav-item"><a class="nav-link disabled" href="#">Overwiev</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link disabled" href="#">Projects</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link disabled" href="#">Custommer</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link disabled" href="#">Manufacturer</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link disabled" href="#">Messages</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link disabled" href="#">FuP</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link disabled" href="#">Contacts</a></li>
|
||||||
|
|
||||||
|
<li class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle disabled" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Search By</a>
|
||||||
|
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
|
||||||
|
<a class="dropdown-item" href="#">Project Name</a>
|
||||||
|
<a class="dropdown-item" href="#">Customer Name</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" href="#">Project ID</a>
|
||||||
|
<a class="dropdown-item" href="#">Customer ID</a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a class="dropdown-item" href="#">Cutsom Options</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<!-- End -->
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
<ul class="navbar-nav ml-auto">
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<li class="nav-item"><a class="nav-link" style="color: {{ theme.light_blue }};" href="{{ url_for('users.account') }}">Account</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" style="color: {{ theme.light_blue }};" href="{{ url_for('users.logout') }}">Logout</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li class="nav-item"><a class="nav-link" style="color: {{ theme.light_blue }};" href="{{ url_for('users.login') }}">Login</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" style="color: {{ theme.light_blue }};" href="{{ url_for('users.register') }}">Register</a></li>
|
||||||
|
{% endif %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<main>
|
||||||
|
<!-- This part will catch anny messages that we whant to send when something has been updated -->
|
||||||
|
{% with messages = get_flashed_messages(with_categories=true) %}
|
||||||
|
{% if messages %}
|
||||||
|
{% for category, message in messages %}
|
||||||
|
<div class="alert alert-{{ category }}">
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
|
||||||
|
<!-- Every extra template will be placed here for examplem login.htlm and so on -->
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,49 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group">
|
||||||
|
<legend class={{ theme.legend }}>Log In</legend>
|
||||||
|
<div class="form-group" style=" {{ theme.userInputFormWitdh }}">
|
||||||
|
{{ form.email.label(class="form-control-label") }}
|
||||||
|
{% if form.email.errors %}
|
||||||
|
{{ form.email(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.email.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.email(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group" style=" {{ theme.userInputFormWitdh }}">
|
||||||
|
{{ form.password.label(class="form-control-label") }}
|
||||||
|
{% if form.password.errors %}
|
||||||
|
{{ form.password(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.password.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.password(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check">
|
||||||
|
{{ form.remember(class="form-check-input") }}
|
||||||
|
{{ form.remember.label(class="form-check-label") }}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
<small>
|
||||||
|
<a class=" {{ theme.smallInfoTextClass }}" href="{{ url_for('users.reset_request') }}">Forgot Password?</a>
|
||||||
|
</small>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,40 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<article class="media content-section">
|
||||||
|
<img class="{{ theme.image }} article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
|
||||||
|
<div class="media-body">
|
||||||
|
<div class="article-metadata">
|
||||||
|
<a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }}" >{{ post.author.username }}</a>
|
||||||
|
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
|
||||||
|
{% if post.author == current_user %}
|
||||||
|
<div>
|
||||||
|
<a class="btn btn-secondary btn-sm m-1" href="{{ url_for('posts.post_update', post_id=post.id) }}">Update</a>
|
||||||
|
<button type="button" class="btn btn-danger btn-sm m-1" data-bs-toggle="modal" data-bs-target="#staticBackdrop">Delete</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<h2 class="article-title">{{ post.title }}</h2>
|
||||||
|
<p class="article-content">{{ post.content }}</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="staticBackdrop" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="staticBackdropLabel">Modal title</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Your last chance, are you Sure?
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
<form action="{{ url_for('posts.post_delete', post_id=post.id) }}" method="POST">
|
||||||
|
<input class="btn btn-danger" type="submit" value="Delete">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,72 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group">
|
||||||
|
<legend class="border-bottom mb-4">Join Today</legend>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.username.label(class="form-control-label") }}
|
||||||
|
|
||||||
|
{% if form.username.errors %}
|
||||||
|
{{ form.username(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.username.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.username(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.email.label(class="form-control-label") }}
|
||||||
|
{% if form.email.errors %}
|
||||||
|
{{ form.email(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.email.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.email(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.password.label(class="form-control-label") }}
|
||||||
|
{% if form.password.errors %}
|
||||||
|
{{ form.password(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.password.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.password(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.password_confirm.label(class="form-control-label") }}
|
||||||
|
{% if form.password_confirm.errors %}
|
||||||
|
{{ form.password_confirm(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.password_confirm.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.password_confirm(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="border-top pt-3">
|
||||||
|
<small class="text-muted">
|
||||||
|
Already Have An Account? <a class="ml-2" href="{{ url_for('users.login') }}">Sign In</a>
|
||||||
|
</small>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,27 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group">
|
||||||
|
<legend class={{ theme.legend }}>Reset Password</legend>
|
||||||
|
<div class="form-group" style=" {{ theme.userInputFormWitdh }}">
|
||||||
|
{{ form.email.label(class="form-control-label") }}
|
||||||
|
{% if form.email.errors %}
|
||||||
|
{{ form.email(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.email.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.email(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,40 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="content-section">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group">
|
||||||
|
<legend class="border-bottom mb-4">Reset Password</legend>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.password.label(class="form-control-label") }}
|
||||||
|
{% if form.password.errors %}
|
||||||
|
{{ form.password(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.password.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.password(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.password_confirm.label(class="form-control-label") }}
|
||||||
|
{% if form.password_confirm.errors %}
|
||||||
|
{{ form.password_confirm(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.password_confirm.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.password_confirm(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,29 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1 class="mb-3"> Posts By {{ user.username }} ({{ posts.total }}) </h1>
|
||||||
|
{% for post in posts.items %}
|
||||||
|
<article class="media content-section">
|
||||||
|
<img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
|
||||||
|
<div class="media-body">
|
||||||
|
<div class="article-metadata">
|
||||||
|
<a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }} ">{{ post.author.username }}</a>
|
||||||
|
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
|
||||||
|
</div>
|
||||||
|
<h2><a class="article-title" href="{{ url_for('posts.post', post_id=post.id) }}">{{ post.title }}</a></h2>
|
||||||
|
<p class="article-content">{{ post.content }}</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
{% endfor %}
|
||||||
|
{% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
|
||||||
|
{% if page_num %}
|
||||||
|
{% if posts.page == page_num %}
|
||||||
|
<a class="btn btn-info mb-4" href="{{ url_for('users.user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a>
|
||||||
|
{% else %}
|
||||||
|
<a class="btn btn-outline-info mb-4" href="{{ url_for('users.user_posts', username=user.username, page=page_num) }}">{{ page_num }}</a>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
...
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock content %}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,81 @@
|
|||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from flask_wtf.file import FileField, FileAllowed
|
||||||
|
from wtforms import StringField, PasswordField, SubmitField, BooleanField
|
||||||
|
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
|
||||||
|
from flask_login import current_user
|
||||||
|
from minibase.models import User
|
||||||
|
from minibase.config import themeMinibase
|
||||||
|
|
||||||
|
|
||||||
|
class registrationForm(FlaskForm):
|
||||||
|
# Decalarion of the fields for the form and it's propereties>
|
||||||
|
username = StringField('User Name',
|
||||||
|
validators=[DataRequired(), Length(min=3, max=20)])
|
||||||
|
email = StringField('Email', validators=[DataRequired(), Email()])
|
||||||
|
password = PasswordField('Password',
|
||||||
|
validators=[DataRequired()])
|
||||||
|
password_confirm = PasswordField('Confirm Password',
|
||||||
|
validators=[DataRequired(), EqualTo('password')])
|
||||||
|
submit = SubmitField('Sing Up')
|
||||||
|
|
||||||
|
# Definiton of the validation that has to be made in order to validate the form
|
||||||
|
def validate_username(self, username):
|
||||||
|
user = User.query.filter_by(username=username.data).first() # Database Querry
|
||||||
|
if user:
|
||||||
|
raise ValidationError('That username is taken please choose another one')
|
||||||
|
|
||||||
|
def validate_email(self, email):
|
||||||
|
email = User.query.filter_by(email=email.data).first() # Database Querry
|
||||||
|
if email:
|
||||||
|
raise ValidationError('That email is taken do you have an acocunt ?')
|
||||||
|
|
||||||
|
|
||||||
|
class loginForm(FlaskForm):
|
||||||
|
email = StringField('Email',
|
||||||
|
validators=[DataRequired(), Email()])
|
||||||
|
password = PasswordField('Password',
|
||||||
|
validators=[DataRequired()])
|
||||||
|
remember = BooleanField('Remember Me')
|
||||||
|
submit = SubmitField('Log In')
|
||||||
|
|
||||||
|
|
||||||
|
class updateAccountForm(FlaskForm):
|
||||||
|
username = StringField('User Name',
|
||||||
|
validators=[DataRequired(), Length(min=3, max=20)])
|
||||||
|
email = StringField('Email',
|
||||||
|
validators=[DataRequired(), Email()])
|
||||||
|
picture = FileField('Update Profile Picture',
|
||||||
|
validators=[FileAllowed(['jpg', 'png'])])
|
||||||
|
submit = SubmitField('Update')
|
||||||
|
|
||||||
|
def validate_username(self, username):
|
||||||
|
if username.data != current_user.username:
|
||||||
|
user = User.query.filter_by(username=username.data).first()
|
||||||
|
if user:
|
||||||
|
raise ValidationError('That username is taken please choose another one')
|
||||||
|
|
||||||
|
def validate_email(self, email):
|
||||||
|
if email.data != current_user.email:
|
||||||
|
email = User.query.filter_by(email=email.data).first()
|
||||||
|
if email:
|
||||||
|
raise ValidationError('That email is taken do you have an acocunt ?')
|
||||||
|
|
||||||
|
|
||||||
|
class requestResetForm(FlaskForm):
|
||||||
|
email = StringField('Email',
|
||||||
|
validators=[DataRequired(), Email()])
|
||||||
|
submit = SubmitField('Request Password Reset')
|
||||||
|
|
||||||
|
def validate_email(self, email):
|
||||||
|
email = User.query.filter_by(email=email.data).first()
|
||||||
|
if email is None:
|
||||||
|
raise ValidationError('There is no Account with this email your must register first.')
|
||||||
|
|
||||||
|
|
||||||
|
class resetPasswordForm(FlaskForm):
|
||||||
|
password = PasswordField('Password',
|
||||||
|
validators=[DataRequired()])
|
||||||
|
password_confirm = PasswordField('Confirm Password',
|
||||||
|
validators=[DataRequired(), EqualTo('password')])
|
||||||
|
submit = SubmitField('Reset Password')
|
||||||
|
|
@ -0,0 +1,130 @@
|
|||||||
|
from flask import render_template, url_for, flash, redirect, request, Blueprint
|
||||||
|
from flask_login import login_user, current_user, logout_user, login_required
|
||||||
|
from minibase import db, bcrypt
|
||||||
|
from minibase.config import themeMinibase
|
||||||
|
from minibase.models import User, Post
|
||||||
|
from minibase.users.forms import (registrationForm, loginForm, updateAccountForm,
|
||||||
|
requestResetForm, resetPasswordForm)
|
||||||
|
from minibase.users.utils import save_picture, send_reset_email
|
||||||
|
|
||||||
|
|
||||||
|
# Declaring a blueprint
|
||||||
|
users = Blueprint('users', __name__)
|
||||||
|
|
||||||
|
# Route is the file that is going to be generated
|
||||||
|
@users.route("/register", methods=['GET', 'POST'])
|
||||||
|
def register():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect(url_for('main.home'))
|
||||||
|
|
||||||
|
form = registrationForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
|
||||||
|
user = User(username=form.username.data, email=form.email.data, password=hashed_pw)
|
||||||
|
db.session.add(user)
|
||||||
|
db.session.commit()
|
||||||
|
flash(f'{"Your account has benn created you can now log in!"}', 'success')
|
||||||
|
return redirect(url_for('users.login'))
|
||||||
|
|
||||||
|
return render_template('register.html',
|
||||||
|
title='Register',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
|
||||||
|
@users.route("/login", methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
if current_user.is_authenticated: # Is the user alredy authenticated?
|
||||||
|
return redirect(url_for('main.home'))
|
||||||
|
|
||||||
|
form = loginForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
user = User.query.filter_by(email=form.email.data).first()
|
||||||
|
if user and bcrypt.check_password_hash(user.password, form.password.data):
|
||||||
|
login_user(user, remember=form.remember.data)
|
||||||
|
next_page = request.args.get('next')
|
||||||
|
return redirect(next_page) if next_page else redirect(url_for('main.home'))
|
||||||
|
else:
|
||||||
|
flash('Login unsuccessful. Please chek your Email and Password!', 'danger')
|
||||||
|
return render_template('login.html',
|
||||||
|
title='Login',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
|
||||||
|
@users.route("/logout")
|
||||||
|
def logout():
|
||||||
|
logout_user()
|
||||||
|
return redirect(url_for('main.home'))
|
||||||
|
|
||||||
|
|
||||||
|
@users.route("/account", methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def account():
|
||||||
|
form = updateAccountForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
if form.picture.data:
|
||||||
|
picture_file = save_picture(form.picture.data)
|
||||||
|
current_user.image_file = picture_file
|
||||||
|
current_user.username = form.username.data
|
||||||
|
current_user.email = form.email.data
|
||||||
|
db.session.commit()
|
||||||
|
flash('Your account has been updated!', 'success')
|
||||||
|
return redirect(url_for('users.account'))
|
||||||
|
elif request.method == 'GET':
|
||||||
|
form.username.data = current_user.username
|
||||||
|
form.email.data = current_user.email
|
||||||
|
image_file = url_for('static', filename='pics/' + current_user.image_file)
|
||||||
|
return render_template('account.html',
|
||||||
|
title='Account',
|
||||||
|
image_file=image_file,
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
|
||||||
|
@users.route("/user/<string:username>")
|
||||||
|
def user_posts(username):
|
||||||
|
user = User.query.filter_by(username=username).first_or_404()
|
||||||
|
page = request.args.get('page', 1, type=int)
|
||||||
|
posts = Post.query.filter_by(author=user)\
|
||||||
|
.order_by(Post.date_posted.asc())\
|
||||||
|
.paginate(page=page, per_page=2)
|
||||||
|
return render_template('user_posts.html',
|
||||||
|
posts=posts,
|
||||||
|
user=user)
|
||||||
|
|
||||||
|
|
||||||
|
@users.route("/reset_password", methods=['GET', 'POST'])
|
||||||
|
def reset_request():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect(url_for('main.home'))
|
||||||
|
form = requestResetForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
user = User.query.filter_by(email=form.email.data).first()
|
||||||
|
send_reset_email(user)
|
||||||
|
flash('An Email has benn sent with instruction to reset your password', 'warning')
|
||||||
|
return render_template('reset_request.html',
|
||||||
|
title='Reset Password',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
|
||||||
|
@users.route("/reset_password/<token>", methods=['GET', 'POST'])
|
||||||
|
def reset_token(token):
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect(url_for('main.home'))
|
||||||
|
user = User.verify_reset_token(token)
|
||||||
|
if user is None:
|
||||||
|
flash('That is an invalid or expired token', 'warning')
|
||||||
|
return redirect(url_for('users.reset_request'))
|
||||||
|
form = resetPasswordForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
|
||||||
|
user.password = hashed_pw
|
||||||
|
db.session.commit()
|
||||||
|
flash(f'{"Your password has benn updated"}', 'success')
|
||||||
|
return redirect(url_for('users.login'))
|
||||||
|
return render_template('reset_token.html',
|
||||||
|
title='Reset Password',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
@ -0,0 +1,30 @@
|
|||||||
|
import os
|
||||||
|
import secrets
|
||||||
|
from PIL import Image
|
||||||
|
from flask import url_for, current_app
|
||||||
|
from flask_mail import Message
|
||||||
|
from minibase import mail
|
||||||
|
|
||||||
|
|
||||||
|
def save_picture(form_picture):
|
||||||
|
random_hex = secrets.token_hex(8)
|
||||||
|
_, f_ext = os.path.splitext(form_picture.filename)
|
||||||
|
picture_fn = random_hex + f_ext
|
||||||
|
picture_path = os.path.join(current_app.root_path, 'static/pics', picture_fn)
|
||||||
|
output_size = (125, 125)
|
||||||
|
i = Image.open(form_picture)
|
||||||
|
i.thumbnail(output_size)
|
||||||
|
i.save(picture_path)
|
||||||
|
return picture_fn
|
||||||
|
|
||||||
|
|
||||||
|
def send_reset_email(user):
|
||||||
|
token = user.get_reset_token()
|
||||||
|
msg = Message('Password Reset Request',
|
||||||
|
sender='noreply@demo.com',
|
||||||
|
recipients=[user.email])
|
||||||
|
msg.body = f'''To reset your password, visit the following link:
|
||||||
|
{url_for('reset_token', token=token, _external=True)}
|
||||||
|
If you didn't make this request, then simply ingnore this email and no chancges will be made.
|
||||||
|
'''
|
||||||
|
mail.send(msg)
|
@ -0,0 +1,7 @@
|
|||||||
|
from minibase import create_minibase
|
||||||
|
# Enable debug option even if run directly form Python3
|
||||||
|
|
||||||
|
app = create_minibase()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app.run(debug=True)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,31 @@
|
|||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, SubmitField
|
||||||
|
from wtforms.validators import DataRequired
|
||||||
|
|
||||||
|
|
||||||
|
class compIndustryForm(FlaskForm): # Defines the form class to be used for the user registretion
|
||||||
|
# Decalarion of the fields for the form and it's propereties
|
||||||
|
name = StringField('Name', validators=[DataRequired()])
|
||||||
|
description = StringField('Description', validators=[DataRequired()])
|
||||||
|
submit = SubmitField('Register Industry')
|
||||||
|
|
||||||
|
|
||||||
|
class compRelationForm(FlaskForm): # Defines the form class to be used for the user registretion
|
||||||
|
# Decalarion of the fields for the form and it's propereties
|
||||||
|
name = StringField('Name', validators=[DataRequired()])
|
||||||
|
description = StringField('Description', validators=[DataRequired()])
|
||||||
|
submit = SubmitField('Register Relation')
|
||||||
|
|
||||||
|
|
||||||
|
class compLegalEntityForm(FlaskForm): # Defines the form class to be used for the user registretion
|
||||||
|
# Decalarion of the fields for the form and it's propereties
|
||||||
|
name = StringField('Name', validators=[DataRequired()])
|
||||||
|
description = StringField('Description', validators=[DataRequired()])
|
||||||
|
submit = SubmitField('Register Legal Entity')
|
||||||
|
|
||||||
|
|
||||||
|
class personRole(FlaskForm): # Defines the form class to be used for the user registretion
|
||||||
|
# Decalarion of the fields for the form and it's propereties
|
||||||
|
name = StringField('Name', validators=[DataRequired()])
|
||||||
|
description = StringField('Description', validators=[DataRequired()])
|
||||||
|
submit = SubmitField('Register Role')
|
@ -0,0 +1,77 @@
|
|||||||
|
from flask import render_template, url_for, flash, redirect, request, Blueprint
|
||||||
|
from minibase import db
|
||||||
|
from minibase.config import themeMinibase
|
||||||
|
from minibase.models import Company, Company_industry, Company_legal_entity, Company_relation
|
||||||
|
from minibase.administration.forms import compLegalEntityForm, compRelationForm, compIndustryForm
|
||||||
|
|
||||||
|
# Declaring a blueprint
|
||||||
|
administration = Blueprint('administration', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@administration.route("/administration_company_legal_entity", methods=['GET', 'POST'])
|
||||||
|
def administration_company_legal_entity():
|
||||||
|
form = compLegalEntityForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
companyLegal = Company_legal_entity(
|
||||||
|
name=form.name.data,
|
||||||
|
description=form.description.data)
|
||||||
|
# Here we need to give the id of thr role as this is a foreign key
|
||||||
|
db.session.add(companyLegal)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
flash(f'{"Company Legal Entity registered!"}', 'success')
|
||||||
|
return render_template('administration_company_legal_entity.html',
|
||||||
|
title='Register Company Legal Entity',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
return render_template('administration_company_legal_entity.html',
|
||||||
|
title='Register Company Legal Entity',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
|
||||||
|
@administration.route("/administration_company_relation", methods=['GET', 'POST'])
|
||||||
|
def administration_company_relation():
|
||||||
|
form = compRelationForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
companyLegal = Company_relation(
|
||||||
|
name=form.name.data,
|
||||||
|
description=form.description.data)
|
||||||
|
# Here we need to give the id of thr role as this is a foreign key
|
||||||
|
db.session.add(companyLegal)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
flash(f'{"Company Relation registered!"}', 'success')
|
||||||
|
return render_template('administration_company_relation.html',
|
||||||
|
title='Register Company Relation',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
return render_template('administration_company_relation.html',
|
||||||
|
title='Register Company Relation',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
|
||||||
|
@administration.route("/administration_company_industry", methods=['GET', 'POST'])
|
||||||
|
def administration_company_industry():
|
||||||
|
form = compIndustryForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
companyLegal = Company_industry(
|
||||||
|
name=form.name.data,
|
||||||
|
description=form.description.data)
|
||||||
|
# Here we need to give the id of thr role as this is a foreign key
|
||||||
|
db.session.add(companyLegal)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
flash(f'{"Company Idustry registered!"}', 'success')
|
||||||
|
return render_template('administration_company_industry.html',
|
||||||
|
title='Register Company Industry',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
||||||
|
|
||||||
|
return render_template('administration_company_industry.html',
|
||||||
|
title='Register Company Industry',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
@ -0,0 +1,11 @@
|
|||||||
|
from minibase.models import Countries
|
||||||
|
|
||||||
|
# Retunrs the query of all awailable Country names on the table named Countries
|
||||||
|
# Note that the formating is done during the SQLAlchemy Table declaration.
|
||||||
|
# Important note This table is ImporteD externally from a modifier SQL version of
|
||||||
|
# Github : https://github.com/dr5hn/countries-states-cities-database
|
||||||
|
def country_choices():
|
||||||
|
choices = Countries.query.all()
|
||||||
|
return choices
|
||||||
|
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,27 @@
|
|||||||
|
from flask_wtf import FlaskForm
|
||||||
|
from wtforms import StringField, SubmitField, IntegerField, SelectField
|
||||||
|
from wtforms.validators import DataRequired, Length, ValidationError
|
||||||
|
from minibase.models import Company, Company_relation
|
||||||
|
import minibase.company.utils as utils
|
||||||
|
import minibase.administration.utils as adminUtils
|
||||||
|
|
||||||
|
|
||||||
|
class companyForm(FlaskForm): # Defines the form class to be used for the user registretion
|
||||||
|
# Decalarion of the fields for the form and it's propereties
|
||||||
|
name = StringField('Name', validators=[DataRequired(), Length(min=3, max=100)])
|
||||||
|
legal_entity = SelectField('Legal Entity', choices=utils.company_legal_entity_choices, validators=[DataRequired()])
|
||||||
|
relation = SelectField('Relation', choices=utils.company_relation_choices, validators=[DataRequired()])
|
||||||
|
country = SelectField('Country', choices=adminUtils.country_choices, validators=[DataRequired()])
|
||||||
|
state = StringField('State', validators=[DataRequired()])
|
||||||
|
city = StringField('City', validators=[DataRequired()])
|
||||||
|
post = IntegerField('Zip', validators=[DataRequired()])
|
||||||
|
street = StringField('Street', validators=[DataRequired()])
|
||||||
|
no = IntegerField('No', validators=[DataRequired()])
|
||||||
|
industry = SelectField('Area', choices=utils.company_industry_choices, validators=[DataRequired()])
|
||||||
|
submit = SubmitField('Register Company')
|
||||||
|
|
||||||
|
def validate_company_duplicate(self, name, country, relation):
|
||||||
|
companyName = Company.query.filter_by(name=name.data).first()
|
||||||
|
if companyName:
|
||||||
|
raise ValidationError('That Company Allredy Exitst Please modify it instead')
|
||||||
|
|
@ -0,0 +1,43 @@
|
|||||||
|
from flask import render_template, url_for, flash, redirect, request, Blueprint
|
||||||
|
from minibase import db
|
||||||
|
from minibase.config import themeMinibase
|
||||||
|
from minibase.models import Company, Company_industry
|
||||||
|
from minibase.company.forms import companyForm
|
||||||
|
import minibase.company.utils as utils
|
||||||
|
|
||||||
|
# Declaring a blueprint
|
||||||
|
company = Blueprint('company', __name__)
|
||||||
|
|
||||||
|
|
||||||
|
@company.route("/company_register", methods=['GET', 'POST'])
|
||||||
|
def company_register():
|
||||||
|
form = companyForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
company = Company(
|
||||||
|
name=form.name.data,
|
||||||
|
country_bill=form.country.data,
|
||||||
|
state_bill=form.state.data,
|
||||||
|
city_bill=form.city.data,
|
||||||
|
postal_code_bill=form.post.data,
|
||||||
|
street_bill=form.street.data,
|
||||||
|
street_no_bill=form.no.data,
|
||||||
|
country_ship=form.country.data,
|
||||||
|
state_ship=form.state.data,
|
||||||
|
city_ship=form.city.data,
|
||||||
|
postal_code_ship=form.post.data,
|
||||||
|
street_ship=form.street.data,
|
||||||
|
street_no_ship=form.no.data,
|
||||||
|
industry=utils.getIndustryId(form.industry.data),
|
||||||
|
relation=utils.getRelationId(form.relation.data),
|
||||||
|
legal_entity=utils.getLegalEntityId(form.legal_entity.data))
|
||||||
|
# Here we need to give the id of thr role as this is a foreign key
|
||||||
|
db.session.add(company)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
flash(f'{"Company succesfull registered!"} { company.industry} ', 'success')
|
||||||
|
return redirect(url_for('company.company_register'))
|
||||||
|
|
||||||
|
return render_template('company_register.html',
|
||||||
|
title='Register Company',
|
||||||
|
theme=themeMinibase,
|
||||||
|
form=form)
|
@ -0,0 +1,47 @@
|
|||||||
|
import os
|
||||||
|
from minibase.models import Company, Company_industry, Company_relation, Company_legal_entity
|
||||||
|
|
||||||
|
|
||||||
|
# Retunrs the qurry of all awailable industrie names on the table named Company_industr
|
||||||
|
# Note that the formating is done during the SQLAlchemy Table declaration.
|
||||||
|
def company_industry_choices():
|
||||||
|
choices = Company_industry.query.all()
|
||||||
|
return choices
|
||||||
|
|
||||||
|
|
||||||
|
# Retunrs the query of all awailable legal entity names on the table named Company_legal_entity
|
||||||
|
# Note that the formating is done during the SQLAlchemy Table declaration.
|
||||||
|
def company_legal_entity_choices():
|
||||||
|
choices = Company_legal_entity.query.all()
|
||||||
|
return choices
|
||||||
|
|
||||||
|
|
||||||
|
# Retunrs the query of all awailable Relation names on the table named Company_relation
|
||||||
|
# Note that the formating is done during the SQLAlchemy Table declaration.
|
||||||
|
def company_relation_choices():
|
||||||
|
choices = Company_relation.query.all()
|
||||||
|
return choices
|
||||||
|
|
||||||
|
|
||||||
|
# The Company Model has Industry Column as a foreign key and it requires the Industry's ID
|
||||||
|
# And not the name. so this function returns the right ID of the name shown at the
|
||||||
|
# Register Company Form
|
||||||
|
def getIndustryId(nameForId):
|
||||||
|
selection = Company_industry.query.filter_by(name=nameForId).first() # Gets the id of Role
|
||||||
|
return selection.id
|
||||||
|
|
||||||
|
|
||||||
|
# The Company Model has Relation Column as a foreign key and it requires the Industry's ID
|
||||||
|
# And not the name. so this function returns the right ID of the name shown at the
|
||||||
|
# Register Company Form
|
||||||
|
def getRelationId(nameForId):
|
||||||
|
selection = Company_relation.query.filter_by(name=nameForId).first() # Gets the id of Role
|
||||||
|
return selection.id
|
||||||
|
|
||||||
|
|
||||||
|
# The Company Model has Legal Entity Column as a foreign key and it requires the Industry's ID
|
||||||
|
# And not the name. so this function returns the right ID of the name shown at the
|
||||||
|
# Register Company Form
|
||||||
|
def getLegalEntityId(nameForId):
|
||||||
|
selection = Company_legal_entity.query.filter_by(name=nameForId).first() # Gets the id of Role
|
||||||
|
return selection.id
|
File diff suppressed because one or more lines are too long
Binary file not shown.
@ -1,16 +1,19 @@
|
|||||||
from flask import Blueprint, render_template
|
from flask import Blueprint, render_template
|
||||||
|
from minibase.config import themeMinibase
|
||||||
|
|
||||||
|
errors = Blueprint('errors', __name__) # Blueprintis are a way of defining new routes.
|
||||||
|
|
||||||
errors = Blueprint('errors', __name__)
|
|
||||||
|
|
||||||
@errors.app_errorhandler(404)
|
@errors.app_errorhandler(404)
|
||||||
def error_404(error):
|
def error_404(error):
|
||||||
return render_template('errors/404.html'), 404
|
return render_template('errors/404.html', theme=themeMinibase), 404
|
||||||
|
|
||||||
|
|
||||||
@errors.app_errorhandler(403)
|
@errors.app_errorhandler(403)
|
||||||
def error_403(error):
|
def error_403(error):
|
||||||
return render_template('errors/403.html'), 403
|
return render_template('errors/403.html', theme=themeMinibase), 403
|
||||||
|
|
||||||
|
|
||||||
@errors.app_errorhandler(500)
|
@errors.app_errorhandler(500)
|
||||||
def error_500(error):
|
def error_500(error):
|
||||||
return render_template('errors/500.html'), 500
|
return render_template('errors/500.html', theme=themeMinibase), 500
|
||||||
|
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 3.9 KiB |
@ -0,0 +1,46 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group"></fieldset>
|
||||||
|
<legend class="border-bottom mb-4">Register Company Endustry</legend>
|
||||||
|
|
||||||
|
<!-- name of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.name.label(class="form-control-label") }}
|
||||||
|
{% if form.name.errors %}
|
||||||
|
{{ form.name(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.name.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.name(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- description of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.description.label(class="form-control-label") }}
|
||||||
|
{% if form.description.errors %}
|
||||||
|
{{ form.description(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.description.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.description(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Submit Button -->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,46 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group"></fieldset>
|
||||||
|
<legend class="border-bottom mb-4">Register Company Legal Entity</legend>
|
||||||
|
|
||||||
|
<!-- name of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.name.label(class="form-control-label") }}
|
||||||
|
{% if form.name.errors %}
|
||||||
|
{{ form.name(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.name.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.name(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- description of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.description.label(class="form-control-label") }}
|
||||||
|
{% if form.description.errors %}
|
||||||
|
{{ form.description(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.description.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.description(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Submit Button -->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,46 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group"></fieldset>
|
||||||
|
<legend class="border-bottom mb-4">Register Company Relation</legend>
|
||||||
|
|
||||||
|
<!-- name of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.name.label(class="form-control-label") }}
|
||||||
|
{% if form.name.errors %}
|
||||||
|
{{ form.name(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.name.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.name(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- description of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.description.label(class="form-control-label") }}
|
||||||
|
{% if form.description.errors %}
|
||||||
|
{{ form.description(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.description.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.description(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Submit Button -->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
@ -0,0 +1,168 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form method="POST" action="">
|
||||||
|
{{ form.hidden_tag() }}
|
||||||
|
<fieldset class="form-group"></fieldset>
|
||||||
|
<legend class="border-bottom mb-4">Register Company</legend>
|
||||||
|
|
||||||
|
<!-- name of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.name.label(class="form-control-label") }}
|
||||||
|
{% if form.name.errors %}
|
||||||
|
{{ form.name(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.name.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.name(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- legal_entity of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.legal_entity.label(class="form-control-label") }}
|
||||||
|
{% if form.legal_entity.errors %}
|
||||||
|
{{ form.legal_entity(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.legal_entity.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.legal_entity(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Relation of the company to us-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.relation.label(class="form-control-label") }}
|
||||||
|
{% if form.relation.errors %}
|
||||||
|
{{ form.relation(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.relation.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.relation(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- industry of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.industry.label(class="form-control-label") }}
|
||||||
|
{% if form.industry.errors %}
|
||||||
|
{{ form.industry(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.industry.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.industry(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- street of the company -->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.street.label(class="form-control-label") }}
|
||||||
|
{% if form.street.errors %}
|
||||||
|
{{ form.street(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.street.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.street(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- no of the company -->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.no.label(class="form-control-label") }}
|
||||||
|
{% if form.no.errors %}
|
||||||
|
{{ form.no(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.no.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.no(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- city of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.city.label(class="form-control-label") }}
|
||||||
|
{% if form.city.errors %}
|
||||||
|
{{ form.city(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.city.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.city(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- state of the company-->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.state.label(class="form-control-label") }}
|
||||||
|
{% if form.state.errors %}
|
||||||
|
{{ form.state(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.state.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.state(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Postal Code of the company -->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.post.label(class="form-control-label") }}
|
||||||
|
{% if form.post.errors %}
|
||||||
|
{{ form.post(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.post.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.post(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Country of the company -->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.country.label(class="form-control-label") }}
|
||||||
|
{% if form.country.errors %}
|
||||||
|
{{ form.country(class="form-control form-control-lg is-invalid") }}
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{% for error in form.country.errors %}
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form.country(class="form-control form-control-lg") }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Submit Button -->
|
||||||
|
<div class="form-group">
|
||||||
|
{{ form.submit(class="btn btn-outline-info") }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -0,0 +1,130 @@
|
|||||||
|
{% extends "layout.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="{{ theme.userInputDivClass }}" style="{{ theme.userInputFormColor }}">
|
||||||
|
<form class="form-inline">
|
||||||
|
<input class="form-control mr-sm-2" type="search" placeholder="Customer Name" aria-label="Search">
|
||||||
|
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>Steinel</h4>
|
||||||
|
<ul class="nav nav-tabs card-header-tabs">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link active" href="#">Overview</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">Projects</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">Components</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="#">Sales</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm">
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">TOP PROJ.</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Potential</th>
|
||||||
|
<th scope="col">Delivered</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">1</th>
|
||||||
|
<td>Mark</td>
|
||||||
|
<td>Otto</td>
|
||||||
|
<td>@mdo</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">2</th>
|
||||||
|
<td>Jacob</td>
|
||||||
|
<td>Thornton</td>
|
||||||
|
<td>@fat</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">3</th>
|
||||||
|
<td>Larry</td>
|
||||||
|
<td>the Bird</td>
|
||||||
|
<td>@twitter</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">TOP IC's</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Potential</th>
|
||||||
|
<th scope="col">Delivered</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">1</th>
|
||||||
|
<td>Mark</td>
|
||||||
|
<td>Otto</td>
|
||||||
|
<td>@mdo</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">2</th>
|
||||||
|
<td>Jacob</td>
|
||||||
|
<td>Thornton</td>
|
||||||
|
<td>@fat</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">3</th>
|
||||||
|
<td>Larry</td>
|
||||||
|
<td>the Bird</td>
|
||||||
|
<td>@twitter</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">TOP MAN.</th>
|
||||||
|
<th scope="col">Name</th>
|
||||||
|
<th scope="col">Potential</th>
|
||||||
|
<th scope="col">Delivered</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">1</th>
|
||||||
|
<td>Mark</td>
|
||||||
|
<td>Otto</td>
|
||||||
|
<td>@mdo</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">2</th>
|
||||||
|
<td>Jacob</td>
|
||||||
|
<td>Thornton</td>
|
||||||
|
<td>@fat</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">3</th>
|
||||||
|
<td>Larry</td>
|
||||||
|
<td>the Bird</td>
|
||||||
|
<td>@twitter</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<a href="#" class="btn btn-primary">Client View</a>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
|
|
@ -1,28 +1,56 @@
|
|||||||
{% extends "layout.html" %}
|
{% extends "layout.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
{% for post in posts.items %}
|
<div class="container-fluid pt-2">
|
||||||
<article class="media content-section">
|
<div class="container-fluid" style="{{ theme.homeOverviewBgColor }}">
|
||||||
<img class="rounded-circle article-img" src="{{ url_for('static', filename='pics/' + post.author.image_file) }}">
|
<h1 class="text-center"> Overwiev </h1>
|
||||||
<div class="media-body">
|
<div class="row">
|
||||||
<div class="article-metadata">
|
<div class="col">
|
||||||
<a class="mr-2" href="{{ url_for('users.user_posts', username=post.author.username) }} ">{{ post.author.username }}</a>
|
<h3> <a href="#">Projects</a> </h3>
|
||||||
<small class="text-muted">{{ post.date_posted.strftime('%Y-%m-%d') }}</small>
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Total</th>
|
||||||
|
<th scope="col">Active</th>
|
||||||
|
<th scope="col">Inactive</th>
|
||||||
|
<th scope="col">ToDo</th>
|
||||||
|
<th scope="col">Warning</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">239</th>
|
||||||
|
<td>200</td>
|
||||||
|
<td>39</td>
|
||||||
|
<td>58</td>
|
||||||
|
<td>5</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<h3> <a href="#">News</a> </h3>
|
||||||
|
<table class="{{ theme.tableClass }}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col">Total POS</th>
|
||||||
|
<th scope="col">Max Marg</th>
|
||||||
|
<th scope="col">Min Marg</th>
|
||||||
|
<th scope="col">Avg Marg</th>
|
||||||
|
<th scope="col">Total Rev</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">100'000 CHF</th>
|
||||||
|
<td>35 %</td>
|
||||||
|
<td>12 %</td>
|
||||||
|
<td>23 %</td>
|
||||||
|
<td>12'453 CHF</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h2><a class="article-title" href="{{ url_for('posts.post', post_id=post.id) }}">{{ post.title }}</a></h2>
|
|
||||||
<p class="article-content">{{ post.content }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</article>
|
|
||||||
{% endfor %}
|
|
||||||
{% for page_num in posts.iter_pages(left_edge=1, right_edge=1, left_current=1, right_current=2) %}
|
|
||||||
{% if page_num %}
|
|
||||||
{% if posts.page == page_num %}
|
|
||||||
<a class="btn btn-info mb-4" href="{{ url_for('main.home', page=page_num) }}">{{ page_num }}</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="btn btn-outline-info mb-4" href="{{ url_for('main.home', page=page_num) }}">{{ page_num }}</a>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
...
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue