WIP: Aureplop/kpsul js refactor #501

Draft
delobell wants to merge 215 commits from aureplop/kpsul_js_refactor into master
2 changed files with 355 additions and 185 deletions
Showing only changes of commit 890be9b343 - Show all commits

View file

@ -91,6 +91,10 @@ input[type=number]::-webkit-outer-spin-button {
font-weight:bold; font-weight:bold;
} }
#account-is_cof {
font-weight:bold;
}
#account .buttons { #account .buttons {
position:absolute; position:absolute;
bottom:0; bottom:0;

View file

@ -170,12 +170,26 @@
<script type="text/javascript"> <script type="text/javascript">
function intCheck(v) {
return Number.parseInt(v);
}
function floatCheck(v) { function floatCheck(v) {
if (typeof v === 'number') if (typeof v === 'number')
return v; return v;
return Number.parseFloat(v); return Number.parseFloat(v);
} }
function booleanCheck(v) {
return v == true;
}
function functionCheck(v) {
if (typeof v === 'function')
return v;
return function(){};
}
class Config { class Config {
static getAll() { static getAll() {
@ -213,6 +227,322 @@ class Config {
} }
String.prototype.formatTri = function() {
return this.toUpperCase();
}
String.prototype.isValidTri = function() {
var pattern = /^[^a-z]{3}$/;
return pattern.test(this);
}
String.prototype.urlify = function() {
return encodeURIComponent(this);
}
class Account {
constructor() {
$.extend(this, this.constructor.default_data);
}
static get default_data() {
return {
'id': 0, 'trigramme': '', 'name': '', 'nickname': '', 'email': '',
'is_cof' : false, 'promo': '', 'balance': 0, 'is_frozen': false,
'departement': '',
};
};
get id() { return this._id; }
get balance() { return this._balance; }
get is_cof() { return this._is_cof; }
get is_frozen() { return this._is_frozen; }
set id(v) { this._id = intCheck(v); }
set balance(v) { this._balance = floatCheck(v); }
set is_cof(v) { this._is_cof = booleanCheck(v); }
set is_frozen(v) { this._is_frozen = booleanCheck(v); }
from(data, callback) {
callback = functionCheck(callback);
$.extend(this, Account.default_data, data);
callback();
}
fromAPI(trigramme, on_success, on_error) {
on_error = functionCheck(on_error);
var that = this;
$.ajax({
dataType: "json",
url : "{% url 'kfet.account.read.json' %}",
method : "POST",
data : { trigramme: trigramme },
})
.done((data) => this.from(data, on_success))
.fail(on_error);
}
reset() {
this.from({});
}
}
class AccountFormatter {
constructor(account) {
this._account = account;
}
static get _data_balance_default() { return ''; }
static get _data_balance_frozen() { return 'frozen'; }
static get _data_balance_ok() { return 'ok'; }
static get _data_balance_low() { return 'low'; }
static get _data_balance_neg() { return 'neg'; }
get str_balance_ukf() { return ''; }
get str_is_cof() { return ''; }
get data_balance() { return this.constructor._data_balance_default; }
display($container) {
var a = this._account;
$container
.find('#account-balance')
.text(this.str_balance_ukf)
.end()
.find('#account-is_cof')
.text(this.str_is_cof)
.end()
.find('#account-name')
.text(a.name)
.end()
.find('#account-nickname')
.text(a.nickname)
.end()
.find('#account-departement')
.text(a.departement)
.end()
.find('#account-promo')
.text(a.promo)
.end()
.find('#account-email')
.text(a.email)
.end();
$container.attr('data-balance', this.data_balance);
}
}
class StandardAccountFormatter extends AccountFormatter {
get str_balance_ukf() {
return amountToUKF(this._account.balance, this._account.is_cof);
}
get str_is_cof() {
return this._account.is_cof ? 'COF' : 'Non-COF';
}
get data_balance() {
var is_frozen = this._account.is_frozen;
var balance = this._account.balance;
if (is_frozen) { return this.constructor._data_balance_frozen; }
else if (balance >= 5) { return this.constructor._data_balance_ok; }
else if (balance >= 0) { return this.constructor._data_balance_low; }
else /* balance < 0 */ { return this.constructor._data_balance_neg; }
}
}
class LIQAccountFormatter extends AccountFormatter {
get str_balance_ukf() { return ''; }
get str_is_cof() { return ''; }
get data_balance() { return this.constructor.data_balance_ok; }
}
class AccountManager {
constructor(env) {
this._env = env; // temporary, should be a link to "kpsul_manager" or something like this
this.account = new Account();
this.search = new AccountSearch(this);
this._$container = $('#account');
this._$input_trigramme = $('#id_trigramme');
this._init_events();
}
get is_empty() {
return this.account.id == 0;
}
get formatter() {
if (this.account.trigramme == 'LIQ') { return LIQAccountFormatter; }
else if (!this.is_empty) { return StandardAccountFormatter; }
else /* account is empty */ { return AccountFormatter; }
}
display() {
this._display_data();
this._display_buttons();
}
_display_data() {
(new (this.formatter)(this.account)).display(this._$container);
}
_display_buttons() {
// dirty
var buttons = '';
if (this.is_empty) {
var trigramme = this._$input_trigramme.val().formatTri();
if (trigramme.isValidTri()) {
var url_base = "{% url 'kfet.account.create' %}";
var url = url_base + '?trigramme=' + trigramme.urlify();
buttons += '<a href="'+url+'" class="btn btn-primary" target="_blank" title="Créer ce compte"><span class="glyphicon glyphicon-plus"></span></a>';
} else { /* trigramme input is empty or invalid */
buttons += '<button class="btn btn-primary search" title="Rechercher"><span class="glyphicon glyphicon-search"></span></button>';
}
} else { /* an account is loaded */
var url_pattern = "{% url 'kfet.account.read' 'LIQ' %}";
var url_base = url_pattern.substr(0, url_pattern.length - 3); /* dirty */
var url = url_base + this.account.trigramme.urlify();
buttons += '<a href="'+url+'" class="btn btn-primary" target="_blank" title="Modifier ce compte"><span class="glyphicon glyphicon-cog"></span></a>';
}
this._$container.find('.buttons').html(buttons);
}
update() {
var trigramme = this._$input_trigramme.val().formatTri();
if (trigramme.isValidTri()) {
this.account.fromAPI(trigramme,
() => this.on_api_success(),
() => this.reset_data()
);
} else {
this.reset_data();
}
}
on_api_success() {
$('#id_on_acc').val(this.account.id);
this.display();
this._env.articleSelect.focus();
this._env.updateBasketAmount();
this._env.updateBasketRel();
}
_init_events() {
var that = this;
this._$input_trigramme
.on('input', () => this.update()); // doesn't want "that.update" instead of "() => this.update()"
this._$input_trigramme
.on('keydown', function(e) {
// keys: 13:Enter|40:Arrow-Down
if (e.keyCode == 13 || e.keyCode == 40) {
that._$input_trigramme.val('LIQ');
that.update();
}
});
/* open search on button click */
this._$container
.on('click', '.search', () => this.search.open());
/* open search on Ctrl-F */
this._$container
.on('keydown', function(e) {
if (e.which == 70 && e.ctrlKey) {
that.search.open();
e.preventDefault() ;
}
});
}
reset() {
$('#id_on_acc').val(0);
this._$input_trigramme.val('');
this.reset_data();
}
reset_data() {
this.account.reset();
this.display();
}
}
class AccountSearch {
constructor(account_manager) {
this.account_manager = account_manager;
this._content = '<input type="text" name="q" id="search_autocomplete" autocomplete="off" spellcheck="false" autofocus><div id="account_results"></div>' ;
this._input = '#search_autocomplete';
this._results_container = '#account_results';
}
open() {
console.log('plop');
var that = this;
this._$dialog = $.dialog({
title: 'Recherche de compte',
content: this._content,
backgroundDismiss: true,
animation: 'top',
closeAnimation: 'bottom',
keyboardEnabled: true,
onOpen: function() {
that._$input = $(that._input);
that._$results_container = $(that._results_container);
that._init_input();
that._init_events();
}
});
}
_init_input() {
var that = this;
this._$input.yourlabsAutocomplete({
url: '{% url "kfet.account.search.autocomplete" %}',
minimumCharacters: 2,
id: 'search_autocomplete',
choiceSelector: '.choice',
placeholder: "Chercher un utilisateur K-Fêt",
container: that._$results_container,
box: that._$results_container,
});
}
_init_events() {
this._$input.bind('selectChoice', (e, choice, autocomplete) => this._on_select(e, choice, autocomplete));
}
_on_select(e, choice, autocomplete) {
this.account_manager._$input_trigramme.val(choice.find('.trigramme').text());
this.account_manager._$input_trigramme.trigger('input');
this.close();
}
close() {
this._$dialog.close();
}
}
$(document).ready(function() { $(document).ready(function() {
'use strict'; 'use strict';
// ----- // -----
@ -222,178 +552,6 @@ $(document).ready(function() {
// Lock to avoid multiple requests // Lock to avoid multiple requests
var lock = 0; var lock = 0;
// -----
// Account data management
// -----
// Initializing
var account_container = $('#account');
var triInput = $('#id_trigramme');
var account_data = {};
var account_data_default = {
'id' : 0,
'name' : '',
'email': '',
'is_cof' : '',
'promo' : '',
'balance': '',
'trigramme' : '',
'is_frozen' : false,
'departement': '',
'nickname' : '',
};
// Display data
function displayAccountData() {
var balance = account_data['trigramme'] != 'LIQ' ? account_data['balance'] : '';
if (balance != '')
balance = amountToUKF(account_data['balance'], account_data['is_cof']);
var is_cof = account_data['trigramme'] ? account_data['is_cof'] : '';
if (is_cof !== '')
is_cof = is_cof ? '<b>COF</b>' : '<b>Non-COF</b>';
for (var elem in account_data) {
if (elem == 'balance') {
$('#account-balance').text(balance);
} else if (elem == 'is_cof') {
$('#account-is_cof').html(is_cof);
} else {
$('#account-'+elem).text(account_data[elem]);
}
}
if (account_data['is_frozen']) {
$('#account').attr('data-balance', 'frozen');
} else if (account_data['balance'] >= 5 || account_data['trigramme'] == 'LIQ') {
$('#account').attr('data-balance', 'ok');
} else if (account_data['balance'] == '') {
$('#account').attr('data-balance', '');
} else if (account_data['balance'] >= 0) {
$('#account').attr('data-balance', 'low');
} else {
$('#account').attr('data-balance', 'neg');
}
var buttons = '';
if (account_data['id'] != 0) {
var url_base = '{% url 'kfet.account.read' 'LIQ' %}';
url_base = url_base.substr(0, url_base.length - 3);
trigramme = encodeURIComponent(account_data['trigramme']) ;
buttons += '<a href="'+ url_base + trigramme +'" class="btn btn-primary" target="_blank" title="Modifier"><span class="glyphicon glyphicon-cog"></span></a>';
}
if (account_data['id'] == 0) {
var trigramme = triInput.val().toUpperCase();
if (isValidTrigramme(trigramme)) {
var url_base = '{% url 'kfet.account.create' %}'
trigramme = encodeURIComponent(trigramme);
buttons += '<a href="'+url_base+'?trigramme='+trigramme+'" class="btn btn-primary" target="_blank" title="Créer"><span class="glyphicon glyphicon-plus"></span></a>';
} else {
var url_base = '{% url 'kfet.account' %}'
buttons += '<button class="btn btn-primary search" title="Rechercher"><span class="glyphicon glyphicon-search"></span></button>';
}
}
account_container.find('.buttons').html(buttons);
}
// Search for an account
function searchAccount() {
var content = '<input type="text" name="q" id="search_autocomplete" spellcheck="false" autofocus><div id="account_results"></div>' ;
$.dialog({
title: 'Recherche de compte',
content: content,
backgroundDismiss: true,
animation: 'top',
closeAnimation: 'bottom',
keyboardEnabled: true,
onOpen: function() {
var that=this ;
$('input#search_autocomplete').yourlabsAutocomplete({
url: '{% url "kfet.account.search.autocomplete" %}',
minimumCharacters: 2,
id: 'search_autocomplete',
choiceSelector: '.choice',
placeholder: "Chercher un utilisateur K-Fêt",
box: $("#account_results"),
});
$('input#search_autocomplete').bind(
'selectChoice',
function(e, choice, autocomplete) {
autocomplete.hide() ;
triInput.val(choice.find('.trigramme').text()) ;
triInput.trigger('input') ;
that.close() ;
});
}
});
}
account_container.on('click', '.search', function () {
searchAccount() ;
}) ;
account_container.on('keydown', function(e) {
if (e.which == 70 && e.ctrlKey) {
// Ctrl + F : universal search shortcut
searchAccount() ;
e.preventDefault() ;
}
});
// Clear data
function resetAccountData() {
account_data = account_data_default;
$('#id_on_acc').val(0);
displayAccountData();
}
function resetAccount() {
triInput.val('');
resetAccountData();
}
// Store data
function storeAccountData(data) {
account_data = $.extend({}, account_data_default, data);
account_data['balance'] = parseFloat(account_data['balance']);
$('#id_on_acc').val(account_data['id']);
displayAccountData();
}
// Retrieve via ajax
function retrieveAccountData(tri) {
$.ajax({
dataType: "json",
url : "{% url 'kfet.account.read.json' %}",
method : "POST",
data : { trigramme: tri },
})
.done(function(data) {
storeAccountData(data);
articleSelect.focus();
updateBasketAmount();
updateBasketRel();
})
.fail(function() { resetAccountData() });
}
// Event listener
triInput.on('input', function() {
var tri = triInput.val().toUpperCase();
// Checking if tri is valid to avoid sending requests
if (isValidTrigramme(tri)) {
retrieveAccountData(tri);
} else {
resetAccountData();
}
});
triInput.on('keydown', function(e) {
if (e.keyCode == 40) {
// Arrow Down - Shorcut to LIQ
triInput.val('LIQ');
triInput.trigger('input');
}
});
// ----- // -----
// Checkout data management // Checkout data management
// ----- // -----
@ -475,7 +633,7 @@ $(document).ready(function() {
if (account_data['trigramme']) { if (account_data['trigramme']) {
articleSelect.focus().select(); articleSelect.focus().select();
} else { } else {
triInput.focus().select(); account_manager._$input_trigramme.focus().select();
} }
}); });
@ -612,7 +770,7 @@ $(document).ready(function() {
case 403: case 403:
requestAuth(data, function(password) { requestAuth(data, function(password) {
cancelOperations(opes_array, password); cancelOperations(opes_array, password);
}, triInput); }, account_manager._$input_trigramme);
break; break;
case 400: case 400:
displayErrors(getErrorsHtml(data)); displayErrors(getErrorsHtml(data));
@ -779,7 +937,7 @@ $(document).ready(function() {
if (text == '' && e.keyCode == 13) if (text == '' && e.keyCode == 13)
performOperations(); performOperations();
if (e.keyCode == 8) if (e.keyCode == 8)
updateMatchedArticles(text.substring(0,text.length-1), commit=false); updateMatchedArticles(text.substring(0,text.length-1), false);
if (e.charCode == 65 && e.ctrlKey) { if (e.charCode == 65 && e.ctrlKey) {
articleId.val(0); articleId.val(0);
articleSelect.val(''); articleSelect.val('');
@ -951,9 +1109,9 @@ $(document).ready(function() {
basketrel_html += '<div>Sur 20€: '+ (20-amount).toFixed(2) +' €</div>'; basketrel_html += '<div>Sur 20€: '+ (20-amount).toFixed(2) +' €</div>';
} else if (account_data['trigramme'] != '' && !isBasketEmpty()) { } else if (account_data['trigramme'] != '' && !isBasketEmpty()) {
var amount = getAmountBasket(); var amount = getAmountBasket();
var amountUKF = amountToUKF(amount, account_data['is_cof']); var amountUKF = amountToUKF(amount, account_manager.account.is_cof);
var newBalance = account_data['balance'] + amount; var newBalance = account_manager.account.balance + amount;
var newBalanceUKF = amountToUKF(newBalance, account_data['is_cof']); var newBalanceUKF = amountToUKF(newBalance, account_manager.account.is_cof);
basketrel_html += '<div>Total: '+amountUKF+'</div>'; basketrel_html += '<div>Total: '+amountUKF+'</div>';
basketrel_html += '<div>Nouveau solde: '+newBalanceUKF+'</div>'; basketrel_html += '<div>Nouveau solde: '+newBalanceUKF+'</div>';
if (newBalance < 0) if (newBalance < 0)
@ -1131,7 +1289,7 @@ $(document).ready(function() {
function updatePreviousOp() { function updatePreviousOp() {
var previousop_html = ''; var previousop_html = '';
var trigramme = account_data['trigramme']; var trigramme = account_manager.account.trigramme;
previousop_html += '<div class="trigramme">Trigramme : '+trigramme+'</div>'; previousop_html += '<div class="trigramme">Trigramme : '+trigramme+'</div>';
previousop_html += basketrel_container.html(); previousop_html += basketrel_container.html();
previousop_container.html(previousop_html); previousop_container.html(previousop_html);
@ -1182,7 +1340,7 @@ $(document).ready(function() {
case 403: case 403:
requestAuth(data, function(password) { requestAuth(data, function(password) {
sendAddcost(trigramme, amount, password); sendAddcost(trigramme, amount, password);
}, triInput); }, account_manager._$input_trigramme);
break; break;
case 400: case 400:
askAddcost(getErrorsHtml(data)); askAddcost(getErrorsHtml(data));
@ -1213,7 +1371,7 @@ $(document).ready(function() {
} }
}); });
}, },
onClose: function() { this._lastFocused = triInput; } onClose: function() { this._lastFocused = account_manager._$input_trigramme; }
}); });
} }
@ -1298,12 +1456,12 @@ $(document).ready(function() {
// Reset functions // Reset functions
function coolReset(give_tri_focus=true) { function coolReset(give_tri_focus=true) {
resetAccount(); account_manager.reset();
resetBasket(); resetBasket();
resetComment(); resetComment();
resetSelectable(); resetSelectable();
if (give_tri_focus) if (give_tri_focus)
triInput.focus(); account_manager._$input_trigramme.focus();
} }
function hardReset(give_tri_focus=true) { function hardReset(give_tri_focus=true) {
@ -1353,8 +1511,8 @@ $(document).ready(function() {
case 113: case 113:
if (e.shiftKey) { if (e.shiftKey) {
// Shift+F2 - Account reset // Shift+F2 - Account reset
resetAccount(); account_manager.reset();
triInput.focus(); account_manager._$input_trigramme.focus();
} else { } else {
// F2 - Basket reset // F2 - Basket reset
resetBasket(); resetBasket();
@ -1389,6 +1547,14 @@ $(document).ready(function() {
// Initiliazing all // Initiliazing all
// ----- // -----
var env = {
articleSelect: articleSelect,
updateBasketAmount: updateBasketAmount,
updateBasketRel: updateBasketRel,
};
var account_manager = new AccountManager(env);
hardReset(); hardReset();
}); });