diff --git a/static/scripts/tetalab.js b/static/scripts/tetalab.js
index f706fc8..0061ee9 100644
--- a/static/scripts/tetalab.js
+++ b/static/scripts/tetalab.js
@@ -5,6 +5,121 @@ var light_green = "#D5FCD8";
var base_bg = "#FEFEFE";
var base_border = "#555555";
+///////////////////////////////////////////
+// Cookies
+///////////////////////////////////////////
+function setcookie(cname, cvalue, exdays) {
+ var d = new Date();
+ d.setTime(d.getTime() + (exdays*24*60*60*1000));
+ var expires = "expires="+ d.toUTCString();
+ document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
+}
+
+///////////////////////////////////////////
+// Update result
+///////////////////////////////////////////
+function update_componants() {
+ obj = document.getElementById('result_container');
+ var xhttp = new XMLHttpRequest();
+ xhttp.onerror = function(){
+ obj.innerHTML = "Erreur lors de la mise à jour de la liste (1)"
+ };
+
+ xhttp.onload = function(){
+ if (xhttp.status == 200) {
+ var response = xhttp.responseText;
+ obj.innerHTML = response;
+ return;
+ }
+ obj.innerHTML = "Erreur lors de la mise à jour de la liste (2)"
+ };
+
+ xhttp.onreadystatechange = function() {
+ if (xhttp.readyState == 4 && xhttp.status == 200) {
+ var response = xhttp.responseText;
+ obj.innerHTML = response;
+ }
+ };
+ xhttp.open('POST', '/componants/update', true);
+ xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+ xhttp.send();
+}
+
+///////////////////////////////////////////
+// Result ordering
+///////////////////////////////////////////
+function update_componants_by_reference(order) {
+ setcookie('c_order', order, 30);
+ setcookie('c_sort', 'reference', 30);
+ setcookie('c_order_refresh', '1', 30);
+ update_componants();
+}
+
+function update_componants_by_designation(order) {
+ setcookie('c_order', order, 30);
+ setcookie('c_sort', 'designation', 30);
+ setcookie('c_order_refresh', '1', 30);
+ update_componants();
+}
+
+function update_componants_by_quantity(order) {
+ setcookie('c_order', order, 30);
+ setcookie('c_sort', 'quantity', 30);
+ setcookie('c_order_refresh', '1', 30);
+ update_componants();
+}
+
+function update_componants_by_place(order) {
+ setcookie('c_order', order, 30);
+ setcookie('c_sort', 'place', 30);
+ setcookie('c_order_refresh', '1', 30);
+ update_componants();
+}
+
+function previous_page(prevhop) {
+ setcookie('c_offset', prevhop, 30);
+ update_componants();
+}
+
+function next_page(nexthop) {
+ setcookie('c_offset', nexthop, 30);
+ update_componants();
+}
+
+///////////////////////////////////////////
+// Search componants
+///////////////////////////////////////////
+function search_componants_by_reference(obj) {
+ setcookie('c_reference', obj.value, 30);
+ update_componants();
+}
+
+function search_componants_by_designation(obj) {
+ setcookie('c_designation', obj.value, 30);
+ update_componants();
+}
+
+function search_componants_by_place(obj) {
+ setcookie('c_place', obj.value, 30);
+ update_componants();
+}
+
+function search_componants_by_provider(obj) {
+ setcookie('c_provider', obj.value, 30);
+ update_componants();
+}
+
+///////////////////////////////////////////
+// Delete componant
+///////////////////////////////////////////
+function confirm_delete() {
+ var msg="La suppression est définitive \net n'est pas autorisée si le \ncomposant fait partie d'un Kit.\n\nConfirmer ?";
+ return confirm(msg)
+}
+
+///////////////////////////////////////////
+// Update componant
+///////////////////////////////////////////
function update_componant(obj, componant_id, type) {
if (type == 'numeric') {
if (isNaN(obj.value)) {
@@ -47,13 +162,7 @@ function update_componant(obj, componant_id, type) {
obj.style.backgroundColor = light_red;
}
};
-
- xhttp.open('POST', '/componant/update/'+componant_id, true);
+ xhttp.open('POST', '/componants/update/'+componant_id, true);
xhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhttp.send('field='+obj.id+'&value='+obj.value);
}
-
-function confirm_delete() {
- var msg="La suppression est définitive \net n'est pas autorisée si le \ncomposant fait partie d'un Kit.\n\nConfirmer ?";
- return confirm(msg)
-}
diff --git a/static/style/style.css b/static/style/style.css
index 35242f5..7f3eefe 100644
--- a/static/style/style.css
+++ b/static/style/style.css
@@ -185,9 +185,17 @@ div.footer {
}
/* ***********************************
- * Tables
+ * Résultats
*********************************** */
+div.row_count {
+ padding: 5px;
+}
+
+div.result_container {
+ text-align: left;
+}
+
.border_left {
border-left-width: 1px;
border-left-style: solid;
@@ -200,7 +208,6 @@ div.footer {
div.block {
overflow: hidden;
- width: 1000px;
border-top-style: solid;
border-top-width: 1px;
height: 20px;
@@ -379,6 +386,7 @@ div.block input {
width: 300px;
}
+
/* ***********************************
* Classes génériques
*********************************** */
diff --git a/templates/componant.html b/templates/componant.html
index d5f798c..04ee284 100644
--- a/templates/componant.html
+++ b/templates/componant.html
@@ -1,9 +1,9 @@
{% extends "index.html" %}
{% block title %}Éditer un composant{% endblock %}
{% block top_menu %}
+
+
-
-
{% endblock %}
diff --git a/templates/componants.html b/templates/componants.html
index e26c64d..5f3c628 100644
--- a/templates/componants.html
+++ b/templates/componants.html
@@ -1,8 +1,8 @@
{% extends "index.html" %}
{% block title %}Liste des composants{% endblock %}
{% block top_menu %}
+
-
{% endblock %}
@@ -33,11 +33,11 @@
id='reference'
type='text'
class='editable'
- onchange='javascript:search_componant(this, "text");'
+ onkeyup='javascript:search_componants_by_reference(this, "text");'
maxlength='20'
title='Référence interne unique (max. 20)'
placeholder='Référence interne unique (max. 20)'
- value='' />
+ value='{{ reference }}' />
@@ -45,11 +45,11 @@
id='designation'
type='text'
class='editable'
- onchange='javascript:search_componant(this, "text");'
+ onkeyup='javascript:search_componants_by_designation(this, "text");'
maxlength='50'
title='Désignation (max. 50)'
placeholder='Désignation (max. 50)'
- value='' />
+ value='{{ designation }}' />
@@ -57,54 +57,35 @@
id='place'
type='text'
class='editable'
- onchange='javascript:search_componant(this, "text");'
+ onkeyup='javascript:search_componants_by_place(this, "text");'
maxlength='15'
title='Emplacement (max. 15)'
placeholder='Emplacement (max. 15)'
- value='' />
+ value='{{ place }}' />
-
+
- Résultat
-
-
-
-
-
-
-
- {% set row_class = cycler('odd', 'even') %}
- {% for componant in componants %}
-
-
{{ componant.reference }}
-
{{ componant.designation }}
-
{{ componant.quantity }}
-
{{ componant.place }}
-
-
-
-
-
- {% endfor %}
-
-
<
-
{{ page }} / {{ page_count }}
-
>
+
+
{% endblock %}
diff --git a/templates/result.html b/templates/result.html
new file mode 100644
index 0000000..4a5896e
--- /dev/null
+++ b/templates/result.html
@@ -0,0 +1,31 @@
+
Résultat:
+ {% set ss='' %}
+ {% if row_count > 1 %}
+ {% set ss='s' %}
+ {% endif %}
+
{{ row_count }} objet{{ ss }} selectionné{{ ss }}
+
+
+
+
+
+
+
+ {% set row_class = cycler('odd', 'even') %}
+ {% for componant in componants %}
+
+
{{ componant.reference }}
+
{{ componant.designation }}
+
{{ componant.quantity }}
+
{{ componant.place }}
+
+
+
+
+
+ {% endfor %}
+
+ <
+ {{ page }} / {{ page_count }}
+ >
+
diff --git a/tetastock.py b/tetastock.py
index 958e95e..08d7b4e 100755
--- a/tetastock.py
+++ b/tetastock.py
@@ -4,7 +4,11 @@
import math
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
from flask_sqlalchemy import SQLAlchemy
+from functools import wraps
+########################################################################
+# App settings
+########################################################################
app = Flask(__name__)
app.config.from_pyfile('config.py')
app.secret_key = '446307a5f61c2bb810436b2ee0f903f2'
@@ -12,6 +16,9 @@ app.debug = True
app.static_url_path='/static'
db = SQLAlchemy(app)
+########################################################################
+# Database
+########################################################################
class Stock_users(db.Model):
id = db.Column(db.Integer, primary_key=True)
mail = db.Column(db.Text, nullable=False)
@@ -47,6 +54,62 @@ class Stock_kit_compositions(db.Model):
component_id = db.Column(db.Integer, db.ForeignKey('Stock_componants.id'), nullable=False)
component_quantity = db.Column(db.Integer, nullable=False)
+def resume_session(func):
+ @wraps(func)
+ def check(*args, **kwargs):
+ # default
+ limit = 8
+ offset = 0
+ nexthop = offset + limit
+ prevhop = offset
+ sort = 'reference'
+ order = 'asc'
+ order_refresh = 0
+ c_empty = ''
+ c_provider = 1
+ if not 'c_limit' in session:
+ session['c_limit'] = limit
+ if not 'c_offest' in session:
+ session['c_offset'] = offset
+ if not 'c_sort' in session:
+ session['c_sort'] = sort
+ if not 'c_order' in session:
+ session['c_order'] = order
+ if not 'c_order_refresh' in session:
+ session['c_order_refresh'] = order_refresh
+ if not 'c_nexthop' in session:
+ session['c_nexthop'] = nexthop
+ if not 'c_prevhop' in session:
+ session['c_prevhop'] = prevhop
+ if not 'c_reference' in session:
+ session['c_reference'] = c_empty
+ if not 'c_designation' in session:
+ session['c_designation'] = c_empty
+ if not 'c_place' in session:
+ session['c_place'] = c_empty
+ if not 'c_provider' in session:
+ session['c_provider'] = c_provider
+ # Cookies/session sync
+ for key in request.cookies:
+ try:
+ session[key] = int(str(request.cookies[key]))
+ except ValueError:
+ # Value is not an int, will be treated as string
+ session[key] = str(request.cookies[key])
+ if key != 'session':
+ print '+', key, request.cookies[key]
+
+ # Switch sort order
+ if session['c_order_refresh'] == 1:
+ refresh = {'desc': 'asc', 'asc': 'desc'}
+ session['c_order'] = refresh[session['c_order']]
+ session['c_order_refresh'] = 0
+ return func(*args, **kwargs)
+ return check
+
+########################################################################
+# Routes
+########################################################################
@app.errorhandler(404)
def page_not_found(e):
return render_template('error.html'), 404
@@ -59,58 +122,22 @@ def authenticate():
########################################################################
# Componants
########################################################################
-@app.route('/componants', methods=['GET', 'POST'])
-def get_componants():
- if not session or not session['plop']:
- session['plop']='plip'
- limit = 8
- offset = 0
- sort = 'reference'
- order = 'asc'
- norder = 'desc'
- print '*', sort
- if len(request.args):
- if 'offset' in request.args:
- offset = request.args['offset']
- if 's' in request.args:
- sort = request.args['s']
- if 'o' in request.args:
- order = request.args['o']
- try:
- offset = int(offset)
- except ValueError:
- offset = 0
- providers = Stock_providers.query.order_by(Stock_providers.name).all()
- row_count = db.session.query(Stock_componants.id).count()
- page_count = int(math.ceil(row_count / float(limit)))
- page = int(math.ceil(float(offset + 1) / float(limit)))
- nexthop = offset + limit
- if nexthop > row_count - 1:
- nexthop = offset
- prevhop = offset - limit
- if prevhop < 0:
- prevhop = 0
- if order == 'asc':
- norder = 'desc'
- componants = Stock_componants.query.order_by(getattr(Stock_componants, sort)).offset(offset).limit(limit).all()
- else:
- norder = 'asc'
- componants = Stock_componants.query.order_by(getattr(Stock_componants, sort).desc()).offset(offset).limit(limit).all()
- return render_template('componants.html',
- componants=componants,
- providers = providers,
- offset=offset,
- nexthop=nexthop,
- prevhop=prevhop,
- page_count=page_count,
- page=page,
- sort=sort,
- order=order,
- norder=norder)
+## Main ##
+@app.route('/componants', methods=['GET', 'POST'])
+@resume_session
+def get_componants():
+ providers = Stock_providers.query.order_by(Stock_providers.name).all()
+ return render_template('componants.html',
+ providers=providers,
+ reference=session['c_reference'],
+ designation=session['c_designation'],
+ place=session['c_place'],
+ provider_id=session['c_provider'])
+
+## Componant edition ##
@app.route('/componants/
')
def get_componant(componant_id):
- print session['plop']
try:
componant_id = int(componant_id)
except ValueError as e:
@@ -123,30 +150,9 @@ def get_componant(componant_id):
return render_template('componant.html', componant=componant, providers=providers, provider=provider)
return render_template('error.html'), 404
-@app.route('/componants/delete/')
-def delete_componant(componant_id):
- try:
- componant_id = int(componant_id)
- except ValueError as e:
- return render_template('error.html'), 404
- Stock_componants.query.filter_by(id=componant_id).delete()
- db.session.commit()
- return get_componants()
-
-@app.route('/componants/new/')
-def add_componant(componant_id):
- return render_template('wip.html')
-
-@app.route('/componants/in/')
-def in_componants():
- return render_template('wip.html')
-
-@app.route('/componants/out/')
-def out_componants():
- return render_template('wip.html')
-
-@app.route('/componant/update/', methods=['POST'])
-def update_componants(componant_id):
+## Componant update ##
+@app.route('/componants/update/', methods=['POST'])
+def update_componant(componant_id):
field = request.form['field']
value = request.form['value']
if field and value:
@@ -158,6 +164,90 @@ def update_componants(componant_id):
return 'KO'
return 'OK'
+## Componant deletion ##
+@app.route('/componants/delete/')
+def delete_componant(componant_id):
+ try:
+ componant_id = int(componant_id)
+ except ValueError as e:
+ return render_template('error.html'), 404
+ Stock_componants.query.filter_by(id=componant_id).delete()
+ db.session.commit()
+ return get_componants()
+
+## Componant creation ##
+@app.route('/componants/new/')
+def add_componant(componant_id):
+ return render_template('wip.html')
+
+## Componants stock in ##
+@app.route('/componants/in/')
+def in_componants():
+ return render_template('wip.html')
+
+## Componants stock out ##
+@app.route('/componants/out/')
+def out_componants():
+ return render_template('wip.html')
+
+## Componants update result set
+@app.route('/componants/update', methods=['POST'])
+@resume_session
+def update_componants():
+ # search by reference
+ like = '%'+str(session['c_reference'])+'%'
+ componants = Stock_componants.query.filter(Stock_componants.reference.like(like))
+ # search by designation
+ like = '%'+str(session['c_designation'])+'%'
+ componants = componants.filter(Stock_componants.designation.like(like))
+ # search by place
+ like = '%'+str(session['c_place'])+'%'
+ componants = componants.filter(Stock_componants.place.like(like))
+ # search by provider
+ if session['c_provider'] > 0:
+ componants = componants.filter_by(provider_id=session['c_provider'])
+ # Pages calculation
+ row_count = componants.count()
+ session['c_pagecount'] = int(math.ceil(row_count / float(session['c_limit'])))
+ session['c_page'] = int(math.ceil(float(float(session['c_offset']) + 1) / float(session['c_limit'])))
+ if session['c_page'] > session['c_pagecount']:
+ session['c_page'] = session['c_pagecount']
+ session['c_offset'] = 0
+ print "*****", componants.count(), session['c_pagecount'], session['c_page']
+ session['c_nexthop'] = session['c_offset'] + session['c_limit']
+ if session['c_nexthop'] > row_count - 1:
+ session['c_nexthop'] = int(session['c_offset'])
+ session['c_prevhop'] = int(session['c_offset']) - session['c_limit']
+ if session['c_prevhop'] < 0:
+ session['c_prevhop'] = 0
+ # Sorting
+ sort = getattr(Stock_componants, session['c_sort'])
+ if session['c_order'] == 'desc':
+ sort = getattr(Stock_componants, session['c_sort']).desc()
+ componants = componants.order_by(sort)
+ # Applying offset
+ componants = componants.offset(session['c_offset'])
+ # Applying limit
+ componants = componants.limit(session['c_limit'])
+ # Get result
+ componants = componants.all()
+
+ response = app.make_response(render_template('result.html',
+ componants=componants,
+ offset=session['c_offset'] ,
+ nexthop=session['c_nexthop'],
+ prevhop=session['c_prevhop'],
+ page_count=session['c_pagecount'],
+ page=session['c_page'],
+ sort=session['c_sort'],
+ order=session['c_order'],
+ row_count=row_count))
+ for key in session:
+ response.set_cookie(key, value=str(session[key]))
+ if key != 'session':
+ print '++', key, session[key]
+ return response
+
########################################################################
# Kits