"Initial commit"

This commit is contained in:
Doug Le Tough 2017-10-19 11:57:28 +02:00
commit 33131ed07b
15 changed files with 558 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*un~
*.swp
*.pyc
config.tetalab.py

2
config.local.py Normal file
View File

@ -0,0 +1,2 @@
SQLALCHEMY_TRACK_MODIFICATIONS = True
SQLALCHEMY_DATABASE_URI = "postgresql://tetalab_user:tetalab@localhost/tetalab_stock"

1
config.py Symbolic link
View File

@ -0,0 +1 @@
config.local.py

3
ref.tetalab.org.wsgi Normal file
View File

@ -0,0 +1,3 @@
import sys
sys.path.insert(0, '/var/www/stock.tetalab.org')
from stock_tetalab import app as application

BIN
static/images/404.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
static/images/working.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
static/images/working.xcf Normal file

Binary file not shown.

View File

224
static/style/style.css Normal file
View File

@ -0,0 +1,224 @@
body {
font-family: sans-serif;
background-color: #2B2B2B;
}
div.main_wrapper {
width: 1280px;
height: auto;
margin: 0 auto;
padding: 10px;
position: relative;
}
div.center {
width: auto;
background-color: #E5E5E5;
height: auto;
border-style: solid;
border-color: #AAAAAA;
border-width: 1px 0 1px 0;
}
div.banner {
background: url(../images/logo_tetalab.png);
background-repeat: no-repeat;
background-position: 10px -2px;
background-color: #FF5D00;
color: #FFFFFF;
font-size: 24px;
padding: 10px;
text-align: right;
font-weight: bold;
height: 40px;
text-shadow: 0 0 1px #000000;
}
div.top_menu {
background-color: #BBBBBB;
height: 30px;
text-align: right;
line-height: 30px;
border-style: solid;
border-color: #888888;
border-width: 1px 0 0 0;
}
span.top_menu_item {
margin: 5px 2px 0 0;
font-size: 12px;
background-color: #F0ECE0;
padding: 1px 5px 1px 5px;
border-radius: 4px;
border-style: solid;
border-color: #888888;
border-width: 1px;
font-weight: bold;
color: #FF5D00;
line-height: 30px;
}
span.top_menu_item_selected {
margin: 5px 2px 0 0;
font-size: 12px;
background-color: #FF5D00;
padding: 1px 5px 1px 5px;
border-radius: 4px;
border-style: solid;
border-color: #888888;
border-width: 1px;
font-weight: bold;
color: #F0ECE0;
line-height: 30px;
}
span.top_menu_item:hover, span.top_menu_item_selected:hover {
background-color: #FFB387;
color: #555555;
cursor: pointer;
}
div.content_wrapper {
height: 497px;
width: 1280px;
}
div.left_menu {
background-color: #E5E5E5;
border-style: solid;
border-color: #AAAAAA;
border-width: 1px 1px 1px 0;
overflow-y: auto;
overflow-x: hidden;
width: 249px;
height: 495px;
line-height: 50px;
}
div.left_menu_item, div.left_menu_item_selected {
background-color: #E5E5E5;
width: 229px;
height: 40px;
overflow-y: hidden;
border-style: solid;
border-color: #AAAAAA;
border-width: 0 0 1px 0;
padding: 10px;
line-height: 50px;
font-weight: bold;
font-size: 20px;
color: #555555;
}
div.left_menu_item:hover, div.left_menu_item_selected:hover {
background-color: #FFB387;
color: #555555;
cursor: pointer;
}
div.left_menu_item_selected {
color: #F0ECE0;
background-color: #FF5D00;
}
div.content {
position: absolute;
top: 102px;
left: 260px;
width: 1010px;
height: 475px;
background-color: #E5E5E5;
overflow-y: auto;
padding: 10px;
border-style: solid;
border-color: #AAAAAA;
border-width: 1px 0 1px 0;
color: #555555;
text-align: justify;
}
div.git_desc, pre {
border-style: solid;
border-color: #FF5D00;
border-width: 1px;
background-color: #FFFFFF;
padding: 5px;
}
div.git_desc {
text-align: justify;
}
div.error {
background: url(../images/404.jpg);
background-repeat: no-repeat;
background-position: center center;
background-color: #000000;
height: 476px;
padding: 10px;
text-align: center;
font-size: 70px;
font-weight: bold;
color: #FF5D00;
}
div.wip {
background: url(../images/working.jpg);
background-repeat: no-repeat;
background-position: center center;
background-color: #000000;
height: 476px;
padding: 10px;
text-align: center;
font-size: 70px;
font-weight: bold;
color: #FF5D00;
}
div.footer {
background-color: #FF5D00;
font-size: 10px;
color: #2B2B2B;
text-align: center;
}
/* ***********************************
* Classes génériques
*********************************** */
h3, h4 {
text-decoration: underline;
}
a {
color: #FF5D00;
text-decoration: none;
padding: 2px;
}
a:hover {
background-color: #FFB387;
}
span.bold {
font-weight: bold;
}
table {
border-collapse: collapse;
width: 100%;
}
th {
background-color: #FFB387;
}
th, td {
text-align: left;
padding: 8px;
}
tr:nth-child(even){background-color: #f2f2f2}

43
stock.sql Normal file
View File

@ -0,0 +1,43 @@
CREATE TABLE Stock_users (
id serial primary key,
mail text not NULL,
password text not NULL,
name text not NULL
);
CREATE TABLE Stock_kits (
id serial primary key,
name text not NULL,
description text not NULL
);
CREATE TABLE Stock_providers (
id serial primary key,
address text not NULL,
mail text not NULL,
url text not NULL,
comment text not NULL
);
CREATE TABLE Stock_componants (
id serial primary key,
name text not NULL,
description text not NULL,
last_price NUMERIC not NULL,
mean_price NUMERIC not NULL,
quantity NUMERIC not NULL,
min_quantity NUMERIC not NULL,
place text not NULL,
provider_id integer REFERENCES Stock_providers(id)
);
CREATE TABLE Stock_kit_compositions (
id serial primary key,
kit_id integer REFERENCES Stock_kits(id),
componant_id integer REFERENCES Stock_componants(id),
quantity integer not NULL
);

164
stock_tetalab.py Executable file
View File

@ -0,0 +1,164 @@
#!/usr/bin/env python
# -*- coding: utf-8
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_pyfile('config.py')
app.secret_key = app.config.get('446307a5f61c2bb810436b2ee0f903f2')
app.debug = True
app.static_url_path='/static'
db = SQLAlchemy(app)
class Stock_users(db.Model):
id = db.Column(db.Integer, primary_key=True)
mail = db.Column(db.Text, nullable=False)
password = db.Column(db.Text, nullable=False)
name = db.Column(db.Text, nullable=False)
class Stock_componants(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text, nullable=False)
description = db.Column(db.Text, nullable=False)
last_price = db.Column(db.Float)
mean_price = db.Column(db.Float)
quantity = db.Column(db.Integer)
min_quantity = db.Column(db.Integer)
place = db.Column(db.Text, nullable=False)
provider_id = db.Column(db.Integer, nullable=False)
class Stock_providers(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text, nullable=False)
postal_address = db.Column(db.Text)
url = db.Column(db.Text)
comment = db.Column(db.Text)
class Stock_kits(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.Text, nullable=False)
description = db.Column(db.Text, nullable=False)
class Stock_kit_compositions(db.Model):
id = db.Column(db.Integer, primary_key=True)
kit_id = db.Column(db.Integer, db.ForeignKey('Stock_kits.id'), nullable=False)
component_id = db.Column(db.Integer, db.ForeignKey('Stock_componants.id'), nullable=False)
component_quantity = db.Column(db.Integer, nullable=False)
@app.errorhandler(404)
def page_not_found(e):
return render_template('error.html'), 404
@app.route("/")
def authenticate():
return render_template('index.html')
########################################################################
# Componants
########################################################################
@app.route('/componants')
def get_componants():
return render_template('wip.html')
@app.route('/componants/<componant_id>')
def get_componant(componant_id):
return render_template('wip.html')
@app.route('/componants/add/<componant_id>')
def add_componant(componant_id):
return render_template('wip.html')
@app.route('/componants/edit/<componant_id>')
def edit_componant(componant_id):
return render_template('wip.html')
@app.route('/componants/delete/<componant_id>')
def delete_componant(componant_id):
return render_template('wip.html')
########################################################################
# Kits
########################################################################
@app.route('/kits')
def get_kits():
return render_template('wip.html')
@app.route('/kits/<kit_id>')
def get_kit(kit_id):
return render_template('wip.html')
@app.route('/kits/add/<kit_id>')
def add_kit(kit_id):
return render_template('wip.html')
@app.route('/kits/edit/<kit_id>')
def edit_kit(kit_id):
return render_template('wip.html')
@app.route('/kits/delete/<kit_id>')
def delete_kit(kit_id):
return render_template('wip.html')
########################################################################
# Providers
########################################################################
@app.route('/providers')
def get_providers():
return render_template('wip.html')
@app.route('/providers/<provider_id>')
def get_provider(provider_id):
return render_template('wip.html')
@app.route('/providers/add/<provider_id>')
def add_provider(provider_id):
return render_template('wip.html')
@app.route('/providers/edit/<provider_id>')
def edit_provider(provider_id):
return render_template('wip.html')
@app.route('/providers/delete/<provider_id>')
def delete_provider(provider_id):
return render_template('wip.html')
########################################################################
# Users
########################################################################
@app.route('/users')
def get_users():
return render_template('wip.html')
@app.route('/users/<user_id>')
def get_user(user_id):
return render_template('wip.html')
@app.route('/users/add/<user_id>')
def add_user(user_id):
return render_template('wip.html')
@app.route('/users/edit/<user_id>')
def edit_user(user_id):
return render_template('wip.html')
@app.route('/users/delete/<user_id>')
def delete_user(user_id):
return render_template('wip.html')
##############################################
def get_distinct(query):
results = []
for result in query:
result = result[0]
if result not in results:
results.append(result)
return results
# Main #######################################
if __name__ == '__main__':
app.run()

30
templates/error.html Normal file
View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr" dir="ltr">
<head>
<title>Référentiel Infrastructure Tetalab - {% block title %}How The Fuck{% endblock %}</title>
<meta name="viewport" content="initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="/static/style/style.css" />
<script type="text/javascript" src="/static/scripts/tetalab.js"></script>
</head>
<body>
<div class='main_wrapper'>
<div class='center'>
<div class='banner' title='Référentiel infrastrusture Tetalab'>
Référentiel Infrastructure Tetalab
</div>
<div class='top_menu'>
<span class='top_menu_item' onclick='javascript:document.location="/";'>Retour</span>
</div>
<div class='content_wrapper'>
<div class='error'>
404
</div>
</div>
<div class='footer'>
Tetalab - Le Hacker Space Toulousain Putaing' Cong' -
</div>
</div>
</div>
</body>
</html>

56
templates/index.html Normal file
View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr" dir="ltr">
<head>
<meta name="generator" content="HTML Tidy for HTML5 for Linux version 5.5.21" />
<title>Stock Tetalab - {% block title %}Accueil{% endblock %}</title>
<meta name="viewport" content="initial-scale=1.0" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" type="text/css" href="/static/style/style.css" />
<script type="text/javascript" src="/static/scripts/tetalab.js"></script>
</head>
<body>
<div class='main_wrapper'>
<div class='center'>
<div class='banner' title='Stock Tetalab'>
Stock Tetalab
</div>
<div class='top_menu'>
{% block top_menu %} <span class='top_menu_item_selected' onclick='javascript:document.location="./";'>Accueil</span> {% endblock %}
</div>
<div class='content_wrapper'>
<div class='left_menu'>
{% block left_menu %}
<div class='left_menu_item_selected' onclick='javascript:document.location="/";'>
Accueil
</div>
<div class='left_menu_item' onclick='javascript:document.location="/componants";'>
Composants
</div>
<div class='left_menu_item' onclick='javascript:document.location="/kits";'>
Kits
</div>
<div class='left_menu_item' onclick='javascript:document.location="/providers";'>
Fournisseurs
</div>{% endblock %}
</div>
<div class='content'>
{% block content %}
<h1>Gestion du stock</h1>
<p>Ceci est l'outil de gestion de stock du <a href='https://www.tetalab.org'>Tetalab</a>.</p>
<p>Cet outil vous permet:
<ul>
<li>De gérer la liste des composants électroniques en possession du Tetalab</li>
<li>De gérer la liste des fournisseurs de composants</li>
<li>De gérer la liste des kits de montage</li>
</ul>
</p>
{% endblock %}
</div>
</div>
<div class='footer'>
Tetalab - Le Hacker Space Toulousaing' Putaing' Cong' -
</div>
</div>
</div>
</body>
</html>

30
templates/wip.html Normal file
View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr" dir="ltr">
<head>
<title>Référentiel Infrastructure Tetalab - {% block title %}How The Fuck{% endblock %}</title>
<meta name="viewport" content="initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="/static/style/style.css" />
<script type="text/javascript" src="/static/scripts/tetalab.js"></script>
</head>
<body>
<div class='main_wrapper'>
<div class='center'>
<div class='banner' title='Référentiel infrastrusture Tetalab'>
Référentiel Infrastructure Tetalab
</div>
<div class='top_menu'>
<span class='top_menu_item' onclick='javascript:document.location="/";'>Retour</span>
</div>
<div class='content_wrapper'>
<div class='wip'>
Work In Progress
</div>
</div>
<div class='footer'>
Tetalab - Le Hacker Space Toulousain Putaing' Cong' -
</div>
</div>
</div>
</body>
</html>