mirror of
https://gitlab.crans.org/bde/nk20
synced 2024-11-26 18:37:12 +00:00
Format JS files
This commit is contained in:
parent
a97a36bc9e
commit
bad5fe3c22
@ -2,22 +2,22 @@
|
|||||||
* On form submit, create a new alias
|
* On form submit, create a new alias
|
||||||
*/
|
*/
|
||||||
function create_alias (e) {
|
function create_alias (e) {
|
||||||
// Do not submit HTML form
|
// Do not submit HTML form
|
||||||
e.preventDefault();
|
e.preventDefault()
|
||||||
|
|
||||||
// Get data and send to API
|
// Get data and send to API
|
||||||
const formData = new FormData(e.target);
|
const formData = new FormData(e.target)
|
||||||
$.post("/api/note/alias/", {
|
$.post('/api/note/alias/', {
|
||||||
"csrfmiddlewaretoken": formData.get("csrfmiddlewaretoken"),
|
csrfmiddlewaretoken: formData.get('csrfmiddlewaretoken'),
|
||||||
"name": formData.get("name"),
|
name: formData.get('name'),
|
||||||
"note": formData.get("note")
|
note: formData.get('note')
|
||||||
}).done(function () {
|
}).done(function () {
|
||||||
// Reload table
|
// Reload table
|
||||||
$("#alias_table").load(location.pathname + " #alias_table");
|
$('#alias_table').load(location.pathname + ' #alias_table')
|
||||||
addMsg("Alias ajouté", "success");
|
addMsg('Alias ajouté', 'success')
|
||||||
}).fail(function (xhr, _textStatus, _error) {
|
}).fail(function (xhr, _textStatus, _error) {
|
||||||
errMsg(xhr.responseJSON);
|
errMsg(xhr.responseJSON)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -25,19 +25,19 @@ function create_alias (e) {
|
|||||||
* @param Integer button_id Alias id to remove
|
* @param Integer button_id Alias id to remove
|
||||||
*/
|
*/
|
||||||
function delete_button (button_id) {
|
function delete_button (button_id) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/api/note/alias/" + button_id + "/",
|
url: '/api/note/alias/' + button_id + '/',
|
||||||
method: "DELETE",
|
method: 'DELETE',
|
||||||
headers: { "X-CSRFTOKEN": CSRF_TOKEN }
|
headers: { 'X-CSRFTOKEN': CSRF_TOKEN }
|
||||||
}).done(function () {
|
}).done(function () {
|
||||||
addMsg('Alias supprimé', 'success');
|
addMsg('Alias supprimé', 'success')
|
||||||
$("#alias_table").load(location.pathname + " #alias_table");
|
$('#alias_table').load(location.pathname + ' #alias_table')
|
||||||
}).fail(function (xhr, _textStatus, _error) {
|
}).fail(function (xhr, _textStatus, _error) {
|
||||||
errMsg(xhr.responseJSON);
|
errMsg(xhr.responseJSON)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
// Attach event
|
// Attach event
|
||||||
document.getElementById("form_alias").addEventListener("submit", create_alias);
|
document.getElementById('form_alias').addEventListener('submit', create_alias)
|
||||||
})
|
})
|
@ -1,57 +1,53 @@
|
|||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$(".autocomplete").keyup(function(e) {
|
$('.autocomplete').keyup(function (e) {
|
||||||
let target = $("#" + e.target.id);
|
const target = $('#' + e.target.id)
|
||||||
let prefix = target.attr("id");
|
const prefix = target.attr('id')
|
||||||
let api_url = target.attr("api_url");
|
const api_url = target.attr('api_url')
|
||||||
let api_url_suffix = target.attr("api_url_suffix");
|
let api_url_suffix = target.attr('api_url_suffix')
|
||||||
if (!api_url_suffix)
|
if (!api_url_suffix) { api_url_suffix = '' }
|
||||||
api_url_suffix = "";
|
let name_field = target.attr('name_field')
|
||||||
let name_field = target.attr("name_field");
|
if (!name_field) { name_field = 'name' }
|
||||||
if (!name_field)
|
const input = target.val()
|
||||||
name_field = "name";
|
target.addClass('is-invalid')
|
||||||
let input = target.val();
|
target.removeClass('is-valid')
|
||||||
target.addClass("is-invalid");
|
$('#' + prefix + '_reset').removeClass('d-none')
|
||||||
target.removeClass("is-valid");
|
|
||||||
$("#" + prefix + "_reset").removeClass("d-none");
|
|
||||||
|
|
||||||
$.getJSON(api_url + (api_url.includes("?") ? "&" : "?") + "format=json&search=^" + input + api_url_suffix, function(objects) {
|
$.getJSON(api_url + (api_url.includes('?') ? '&' : '?') + 'format=json&search=^' + input + api_url_suffix, function (objects) {
|
||||||
let html = "";
|
let html = ''
|
||||||
|
|
||||||
objects.results.forEach(function (obj) {
|
objects.results.forEach(function (obj) {
|
||||||
html += li(prefix + "_" + obj.id, obj[name_field]);
|
html += li(prefix + '_' + obj.id, obj[name_field])
|
||||||
});
|
})
|
||||||
|
|
||||||
let results_list = $("#" + prefix + "_list");
|
const results_list = $('#' + prefix + '_list')
|
||||||
results_list.html(html);
|
results_list.html(html)
|
||||||
|
|
||||||
objects.results.forEach(function (obj) {
|
objects.results.forEach(function (obj) {
|
||||||
$("#" + prefix + "_" + obj.id).click(function() {
|
$('#' + prefix + '_' + obj.id).click(function () {
|
||||||
target.val(obj[name_field]);
|
target.val(obj[name_field])
|
||||||
$("#" + prefix + "_pk").val(obj.id);
|
$('#' + prefix + '_pk').val(obj.id)
|
||||||
|
|
||||||
results_list.html("");
|
results_list.html('')
|
||||||
target.removeClass("is-invalid");
|
target.removeClass('is-invalid')
|
||||||
target.addClass("is-valid");
|
target.addClass('is-valid')
|
||||||
|
|
||||||
if (typeof autocompleted != 'undefined')
|
if (typeof autocompleted !== 'undefined') { autocompleted(obj, prefix) }
|
||||||
autocompleted(obj, prefix)
|
})
|
||||||
});
|
|
||||||
|
|
||||||
if (input === obj[name_field])
|
if (input === obj[name_field]) { $('#' + prefix + '_pk').val(obj.id) }
|
||||||
$("#" + prefix + "_pk").val(obj.id);
|
})
|
||||||
});
|
|
||||||
|
|
||||||
if (results_list.children().length === 1 && e.originalEvent.keyCode >= 32) {
|
if (results_list.children().length === 1 && e.originalEvent.keyCode >= 32) {
|
||||||
results_list.children().first().trigger("click");
|
results_list.children().first().trigger('click')
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
$(".autocomplete-reset").click(function() {
|
$('.autocomplete-reset').click(function () {
|
||||||
let name = $(this).attr("id").replace("_reset", "");
|
const name = $(this).attr('id').replace('_reset', '')
|
||||||
$("#" + name + "_pk").val("");
|
$('#' + name + '_pk').val('')
|
||||||
$("#" + name).val("");
|
$('#' + name).val('')
|
||||||
$("#" + name + "_list").html("");
|
$('#' + name + '_list').html('')
|
||||||
$(this).addClass("d-none");
|
$(this).addClass('d-none')
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
// Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
// Copyright (C) 2018-2020 by BDE ENS Paris-Saclay
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert balance in cents to a human readable amount
|
* Convert balance in cents to a human readable amount
|
||||||
* @param value the balance, in cents
|
* @param value the balance, in cents
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
function pretty_money (value) {
|
function pretty_money (value) {
|
||||||
if (value % 100 === 0)
|
if (value % 100 === 0) { return (value < 0 ? '- ' : '') + Math.floor(Math.abs(value) / 100) + ' €' } else {
|
||||||
return (value < 0 ? "- " : "") + Math.floor(Math.abs(value) / 100) + " €";
|
return (value < 0 ? '- ' : '') + Math.floor(Math.abs(value) / 100) + '.' +
|
||||||
else
|
(Math.abs(value) % 100 < 10 ? '0' : '') + (Math.abs(value) % 100) + ' €'
|
||||||
return (value < 0 ? "- " : "") + Math.floor(Math.abs(value) / 100) + "."
|
}
|
||||||
+ (Math.abs(value) % 100 < 10 ? "0" : "") + (Math.abs(value) % 100) + " €";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,19 +20,19 @@ function pretty_money (value) {
|
|||||||
* @param timeout The delay (in millis) after that the message is auto-closed. If negative, then it is ignored.
|
* @param timeout The delay (in millis) after that the message is auto-closed. If negative, then it is ignored.
|
||||||
*/
|
*/
|
||||||
function addMsg (msg, alert_type, timeout = -1) {
|
function addMsg (msg, alert_type, timeout = -1) {
|
||||||
let msgDiv = $("#messages");
|
const msgDiv = $('#messages')
|
||||||
let html = msgDiv.html();
|
let html = msgDiv.html()
|
||||||
let id = Math.floor(10000 * Math.random() + 1);
|
const id = Math.floor(10000 * Math.random() + 1)
|
||||||
html += "<div class=\"alert alert-" + alert_type + " alert-dismissible\">" +
|
html += '<div class="alert alert-' + alert_type + ' alert-dismissible">' +
|
||||||
"<button id=\"close-message-" + id + "\" class=\"close\" data-dismiss=\"alert\" href=\"#\"><span aria-hidden=\"true\">×</span></button>"
|
'<button id="close-message-' + id + '" class="close" data-dismiss="alert" href="#"><span aria-hidden="true">×</span></button>' +
|
||||||
+ msg + "</div>\n";
|
msg + '</div>\n'
|
||||||
msgDiv.html(html);
|
msgDiv.html(html)
|
||||||
|
|
||||||
if (timeout > 0) {
|
if (timeout > 0) {
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
$("#close-message-" + id).click();
|
$('#close-message-' + id).click()
|
||||||
}, timeout);
|
}, timeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,34 +41,34 @@ function addMsg (msg, alert_type, timeout = -1) {
|
|||||||
* @param timeout The delay (in millis) after that the message is auto-closed. If negative, then it is ignored.
|
* @param timeout The delay (in millis) after that the message is auto-closed. If negative, then it is ignored.
|
||||||
*/
|
*/
|
||||||
function errMsg (errs_obj, timeout = -1) {
|
function errMsg (errs_obj, timeout = -1) {
|
||||||
for (const err_msg of Object.values(errs_obj)) {
|
for (const err_msg of Object.values(errs_obj)) {
|
||||||
addMsg(err_msg, 'danger', timeout);
|
addMsg(err_msg, 'danger', timeout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var reloadWithTurbolinks = (function () {
|
var reloadWithTurbolinks = (function () {
|
||||||
var scrollPosition;
|
var scrollPosition
|
||||||
|
|
||||||
function reload () {
|
function reload () {
|
||||||
scrollPosition = [window.scrollX, window.scrollY];
|
scrollPosition = [window.scrollX, window.scrollY]
|
||||||
Turbolinks.visit(window.location.toString(), { action: 'replace' })
|
Turbolinks.visit(window.location.toString(), { action: 'replace' })
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('turbolinks:load', function () {
|
||||||
|
if (scrollPosition) {
|
||||||
|
window.scrollTo.apply(window, scrollPosition)
|
||||||
|
scrollPosition = null
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
document.addEventListener('turbolinks:load', function () {
|
return reload
|
||||||
if (scrollPosition) {
|
})()
|
||||||
window.scrollTo.apply(window, scrollPosition);
|
|
||||||
scrollPosition = null
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return reload;
|
|
||||||
})();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reload the balance of the user on the right top corner
|
* Reload the balance of the user on the right top corner
|
||||||
*/
|
*/
|
||||||
function refreshBalance () {
|
function refreshBalance () {
|
||||||
$("#user_balance").load("/ #user_balance");
|
$('#user_balance').load('/ #user_balance')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,15 +77,15 @@ function refreshBalance () {
|
|||||||
* @param fun For each found note with the matched alias `alias`, fun(note, alias) is called.
|
* @param fun For each found note with the matched alias `alias`, fun(note, alias) is called.
|
||||||
*/
|
*/
|
||||||
function getMatchedNotes (pattern, fun) {
|
function getMatchedNotes (pattern, fun) {
|
||||||
$.getJSON("/api/note/alias/?format=json&alias=" + pattern + "&search=user|club", fun);
|
$.getJSON('/api/note/alias/?format=json&alias=' + pattern + '&search=user|club', fun)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a <li> entry with a given id and text
|
* Generate a <li> entry with a given id and text
|
||||||
*/
|
*/
|
||||||
function li (id, text, extra_css) {
|
function li (id, text, extra_css) {
|
||||||
return "<li class=\"list-group-item py-1 px-2 d-flex justify-content-between align-items-center text-truncate "
|
return '<li class="list-group-item py-1 px-2 d-flex justify-content-between align-items-center text-truncate ' +
|
||||||
+ (extra_css ? extra_css : "") + "\"" + " id=\"" + id + "\">" + text + "</li>\n";
|
(extra_css || '') + '"' + ' id="' + id + '">' + text + '</li>\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -95,24 +93,13 @@ function li (id, text, extra_css) {
|
|||||||
* @param note The concerned note.
|
* @param note The concerned note.
|
||||||
*/
|
*/
|
||||||
function displayStyle (note) {
|
function displayStyle (note) {
|
||||||
if (!note)
|
if (!note) { return '' }
|
||||||
return "";
|
const balance = note.balance
|
||||||
let balance = note.balance;
|
var css = ''
|
||||||
var css = "";
|
if (balance < -5000) { css += ' text-danger bg-dark' } else if (balance < -1000) { css += ' text-danger' } else if (balance < 0) { css += ' text-warning' } else if (!note.email_confirmed) { css += ' text-white bg-primary' } else if (!note.is_active || (note.membership && note.membership.date_end < new Date().toISOString())) { css += 'text-white bg-info' }
|
||||||
if (balance < -5000)
|
return css
|
||||||
css += " text-danger bg-dark";
|
|
||||||
else if (balance < -1000)
|
|
||||||
css += " text-danger";
|
|
||||||
else if (balance < 0)
|
|
||||||
css += " text-warning";
|
|
||||||
else if (!note.email_confirmed)
|
|
||||||
css += " text-white bg-primary";
|
|
||||||
else if (!note.is_active || (note.membership && note.membership.date_end < new Date().toISOString()))
|
|
||||||
css += "text-white bg-info";
|
|
||||||
return css;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render note name and picture
|
* Render note name and picture
|
||||||
* @param note The note to render
|
* @param note The note to render
|
||||||
@ -121,23 +108,22 @@ function displayStyle (note) {
|
|||||||
* @param profile_pic_field
|
* @param profile_pic_field
|
||||||
*/
|
*/
|
||||||
function displayNote (note, alias, user_note_field = null, profile_pic_field = null) {
|
function displayNote (note, alias, user_note_field = null, profile_pic_field = null) {
|
||||||
if (!note.display_image) {
|
if (!note.display_image) {
|
||||||
note.display_image = '/static/member/img/default_picture.png';
|
note.display_image = '/static/member/img/default_picture.png'
|
||||||
}
|
}
|
||||||
let img = note.display_image;
|
const img = note.display_image
|
||||||
if (alias !== note.name && note.name)
|
if (alias !== note.name && note.name) { alias += ' (aka. ' + note.name + ')' }
|
||||||
alias += " (aka. " + note.name + ")";
|
if (user_note_field !== null) {
|
||||||
if (user_note_field !== null) {
|
$('#' + user_note_field).removeAttr('class')
|
||||||
$("#" + user_note_field).removeAttr('class');
|
$('#' + user_note_field).addClass(displayStyle(note))
|
||||||
$("#" + user_note_field).addClass(displayStyle(note));
|
$('#' + user_note_field).text(alias + (note.balance == null ? '' : (' :\n' + pretty_money(note.balance))))
|
||||||
$("#" + user_note_field).text(alias + (note.balance == null ? "" : (" :\n" + pretty_money(note.balance))));
|
if (profile_pic_field != null) {
|
||||||
if (profile_pic_field != null) {
|
$('#' + profile_pic_field).attr('src', img)
|
||||||
$("#" + profile_pic_field).attr('src', img);
|
$('#' + profile_pic_field + '_link').attr('href', note.resourcetype === 'NoteUser'
|
||||||
$("#" + profile_pic_field + "_link").attr('href', note.resourcetype === "NoteUser" ?
|
? '/accounts/user/' + note.user : note.resourcetype === 'NoteClub'
|
||||||
"/accounts/user/" + note.user : note.resourcetype === "NoteClub" ?
|
? '/accounts/club/' + note.club : '#')
|
||||||
"/accounts/club/" + note.club : "#");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -152,35 +138,34 @@ function displayNote (note, alias, user_note_field = null, profile_pic_field = n
|
|||||||
* (useful in consumptions, put null if not used)
|
* (useful in consumptions, put null if not used)
|
||||||
* @returns an anonymous function to be compatible with jQuery events
|
* @returns an anonymous function to be compatible with jQuery events
|
||||||
*/
|
*/
|
||||||
function removeNote (d, note_prefix = "note", notes_display, note_list_id, user_note_field = null, profile_pic_field = null) {
|
function removeNote (d, note_prefix = 'note', notes_display, note_list_id, user_note_field = null, profile_pic_field = null) {
|
||||||
return (function () {
|
return function () {
|
||||||
let new_notes_display = [];
|
const new_notes_display = []
|
||||||
let html = "";
|
let html = ''
|
||||||
notes_display.forEach(function (disp) {
|
notes_display.forEach(function (disp) {
|
||||||
if (disp.quantity > 1 || disp.id !== d.id) {
|
if (disp.quantity > 1 || disp.id !== d.id) {
|
||||||
disp.quantity -= disp.id === d.id ? 1 : 0;
|
disp.quantity -= disp.id === d.id ? 1 : 0
|
||||||
new_notes_display.push(disp);
|
new_notes_display.push(disp)
|
||||||
html += li(note_prefix + "_" + disp.id, disp.name
|
html += li(note_prefix + '_' + disp.id, disp.name +
|
||||||
+ "<span class=\"badge badge-dark badge-pill\">" + disp.quantity + "</span>",
|
'<span class="badge badge-dark badge-pill">' + disp.quantity + '</span>',
|
||||||
displayStyle(disp.note));
|
displayStyle(disp.note))
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
notes_display.length = 0;
|
notes_display.length = 0
|
||||||
new_notes_display.forEach(function (disp) {
|
new_notes_display.forEach(function (disp) {
|
||||||
notes_display.push(disp);
|
notes_display.push(disp)
|
||||||
});
|
})
|
||||||
|
|
||||||
$("#" + note_list_id).html(html);
|
$('#' + note_list_id).html(html)
|
||||||
notes_display.forEach(function (disp) {
|
notes_display.forEach(function (disp) {
|
||||||
let obj = $("#" + note_prefix + "_" + disp.id);
|
const obj = $('#' + note_prefix + '_' + disp.id)
|
||||||
obj.click(removeNote(disp, note_prefix, notes_display, note_list_id, user_note_field, profile_pic_field));
|
obj.click(removeNote(disp, note_prefix, notes_display, note_list_id, user_note_field, profile_pic_field))
|
||||||
obj.hover(function () {
|
obj.hover(function () {
|
||||||
if (disp.note)
|
if (disp.note) { displayNote(disp.note, disp.name, user_note_field, profile_pic_field) }
|
||||||
displayNote(disp.note, disp.name, user_note_field, profile_pic_field);
|
})
|
||||||
});
|
})
|
||||||
});
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,203 +184,193 @@ function removeNote (d, note_prefix = "note", notes_display, note_list_id, user_
|
|||||||
* the associated note is not displayed.
|
* the associated note is not displayed.
|
||||||
* Useful for a consumption if the item is selected before.
|
* Useful for a consumption if the item is selected before.
|
||||||
*/
|
*/
|
||||||
function autoCompleteNote (field_id, note_list_id, notes, notes_display, alias_prefix = "alias",
|
function autoCompleteNote (field_id, note_list_id, notes, notes_display, alias_prefix = 'alias',
|
||||||
note_prefix = "note", user_note_field = null, profile_pic_field = null, alias_click = null) {
|
note_prefix = 'note', user_note_field = null, profile_pic_field = null, alias_click = null) {
|
||||||
let field = $("#" + field_id);
|
const field = $('#' + field_id)
|
||||||
|
|
||||||
// Configure tooltip
|
// Configure tooltip
|
||||||
field.tooltip({
|
field.tooltip({
|
||||||
html: true,
|
html: true,
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
title: 'Loading...',
|
title: 'Loading...',
|
||||||
trigger: 'manual',
|
trigger: 'manual',
|
||||||
container: field.parent(),
|
container: field.parent(),
|
||||||
fallbackPlacement: 'clockwise'
|
fallbackPlacement: 'clockwise'
|
||||||
});
|
})
|
||||||
|
|
||||||
// When the user clicks elsewhere, we hide the tooltip
|
// When the user clicks elsewhere, we hide the tooltip
|
||||||
$(document).click(function(e) {
|
$(document).click(function (e) {
|
||||||
if (!e.target.id.startsWith(alias_prefix)) {
|
if (!e.target.id.startsWith(alias_prefix)) {
|
||||||
field.tooltip("hide");
|
field.tooltip('hide')
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
let old_pattern = null;
|
let old_pattern = null
|
||||||
|
|
||||||
// Clear search on click
|
// Clear search on click
|
||||||
field.click(function () {
|
field.click(function () {
|
||||||
field.tooltip('hide');
|
field.tooltip('hide')
|
||||||
field.removeClass('is-invalid');
|
field.removeClass('is-invalid')
|
||||||
field.val("");
|
field.val('')
|
||||||
old_pattern = "";
|
old_pattern = ''
|
||||||
});
|
})
|
||||||
|
|
||||||
// When the user type "Enter", the first alias is clicked
|
// When the user type "Enter", the first alias is clicked
|
||||||
field.keypress(function (event) {
|
field.keypress(function (event) {
|
||||||
if (event.originalEvent.charCode === 13 && notes.length > 0) {
|
if (event.originalEvent.charCode === 13 && notes.length > 0) {
|
||||||
let li_obj = field.parent().find("ul li").first();
|
const li_obj = field.parent().find('ul li').first()
|
||||||
displayNote(notes[0], li_obj.text(), user_note_field, profile_pic_field);
|
displayNote(notes[0], li_obj.text(), user_note_field, profile_pic_field)
|
||||||
li_obj.trigger("click");
|
li_obj.trigger('click')
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
// When the user type something, the matched aliases are refreshed
|
// When the user type something, the matched aliases are refreshed
|
||||||
field.keyup(function (e) {
|
field.keyup(function (e) {
|
||||||
field.removeClass('is-invalid');
|
field.removeClass('is-invalid')
|
||||||
|
|
||||||
if (e.originalEvent.charCode === 13)
|
if (e.originalEvent.charCode === 13) { return }
|
||||||
return;
|
|
||||||
|
|
||||||
let pattern = field.val();
|
const pattern = field.val()
|
||||||
|
|
||||||
// If the pattern is not modified, we don't query the API
|
// If the pattern is not modified, we don't query the API
|
||||||
if (pattern === old_pattern)
|
if (pattern === old_pattern) { return }
|
||||||
return;
|
old_pattern = pattern
|
||||||
old_pattern = pattern;
|
notes.length = 0
|
||||||
notes.length = 0;
|
|
||||||
|
|
||||||
// get matched Alias with note associated
|
// get matched Alias with note associated
|
||||||
if (pattern === "") {
|
if (pattern === '') {
|
||||||
field.tooltip('hide');
|
field.tooltip('hide')
|
||||||
notes.length = 0;
|
notes.length = 0
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
$.getJSON("/api/note/consumer/?format=json&alias=" + pattern + "&search=user|club",
|
$.getJSON('/api/note/consumer/?format=json&alias=' + pattern + '&search=user|club',
|
||||||
function (consumers) {
|
function (consumers) {
|
||||||
// The response arrived too late, we stop the request
|
// The response arrived too late, we stop the request
|
||||||
if (pattern !== $("#" + field_id).val())
|
if (pattern !== $('#' + field_id).val()) { return }
|
||||||
return;
|
|
||||||
|
|
||||||
// Build tooltip content
|
// Build tooltip content
|
||||||
let aliases_matched_html = '<ul class="list-group list-group-flush">';
|
let aliases_matched_html = '<ul class="list-group list-group-flush">'
|
||||||
consumers.results.forEach(function (consumer) {
|
consumers.results.forEach(function (consumer) {
|
||||||
let note = consumer.note;
|
const note = consumer.note
|
||||||
note.email_confirmed = consumer.email_confirmed;
|
note.email_confirmed = consumer.email_confirmed
|
||||||
if (consumer.hasOwnProperty("membership") && consumer.membership)
|
if (consumer.hasOwnProperty('membership') && consumer.membership) { note.membership = consumer.membership } else { note.membership = undefined }
|
||||||
note.membership = consumer.membership;
|
const extra_css = displayStyle(note)
|
||||||
else
|
aliases_matched_html += li(alias_prefix + '_' + consumer.id,
|
||||||
note.membership = undefined;
|
consumer.name,
|
||||||
let extra_css = displayStyle(note);
|
extra_css)
|
||||||
aliases_matched_html += li(alias_prefix + '_' + consumer.id,
|
notes.push(note)
|
||||||
consumer.name,
|
})
|
||||||
extra_css);
|
aliases_matched_html += '</ul>'
|
||||||
notes.push(note);
|
|
||||||
});
|
|
||||||
aliases_matched_html += '</ul>';
|
|
||||||
|
|
||||||
// Show tooltip
|
// Show tooltip
|
||||||
field.attr('data-original-title', aliases_matched_html).tooltip('show');
|
field.attr('data-original-title', aliases_matched_html).tooltip('show')
|
||||||
|
|
||||||
consumers.results.forEach(function (consumer) {
|
consumers.results.forEach(function (consumer) {
|
||||||
let consumer_obj = $("#" + alias_prefix + "_" + consumer.id);
|
const consumer_obj = $('#' + alias_prefix + '_' + consumer.id)
|
||||||
consumer_obj.hover(function () {
|
consumer_obj.hover(function () {
|
||||||
displayNote(consumer.note, consumer.name, user_note_field, profile_pic_field)
|
displayNote(consumer.note, consumer.name, user_note_field, profile_pic_field)
|
||||||
});
|
})
|
||||||
consumer_obj.click(function () {
|
consumer_obj.click(function () {
|
||||||
var disp = null;
|
var disp = null
|
||||||
notes_display.forEach(function (d) {
|
notes_display.forEach(function (d) {
|
||||||
// We compare the alias ids
|
// We compare the alias ids
|
||||||
if (d.id === consumer.id) {
|
if (d.id === consumer.id) {
|
||||||
d.quantity += 1;
|
d.quantity += 1
|
||||||
disp = d;
|
disp = d
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
// In the other case, we add a new emitter
|
// In the other case, we add a new emitter
|
||||||
if (disp == null) {
|
if (disp == null) {
|
||||||
disp = {
|
disp = {
|
||||||
name: consumer.name,
|
name: consumer.name,
|
||||||
id: consumer.id,
|
id: consumer.id,
|
||||||
note: consumer.note,
|
note: consumer.note,
|
||||||
quantity: 1
|
quantity: 1
|
||||||
};
|
}
|
||||||
notes_display.push(disp);
|
notes_display.push(disp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the function alias_click exists, it is called. If it doesn't return true, then the notes are
|
// If the function alias_click exists, it is called. If it doesn't return true, then the notes are
|
||||||
// note displayed. Useful for a consumption when a button is already clicked
|
// note displayed. Useful for a consumption when a button is already clicked
|
||||||
if (alias_click && !alias_click())
|
if (alias_click && !alias_click()) { return }
|
||||||
return;
|
|
||||||
|
|
||||||
let note_list = $("#" + note_list_id);
|
const note_list = $('#' + note_list_id)
|
||||||
let html = "";
|
let html = ''
|
||||||
notes_display.forEach(function (disp) {
|
notes_display.forEach(function (disp) {
|
||||||
html += li(note_prefix + "_" + disp.id,
|
html += li(note_prefix + '_' + disp.id,
|
||||||
disp.name
|
disp.name +
|
||||||
+ "<span class=\"badge badge-dark badge-pill\">"
|
'<span class="badge badge-dark badge-pill">' +
|
||||||
+ disp.quantity + "</span>",
|
disp.quantity + '</span>',
|
||||||
displayStyle(disp.note));
|
displayStyle(disp.note))
|
||||||
});
|
})
|
||||||
|
|
||||||
// Emitters are displayed
|
// Emitters are displayed
|
||||||
note_list.html(html);
|
note_list.html(html)
|
||||||
|
|
||||||
// Update tooltip position
|
// Update tooltip position
|
||||||
field.tooltip('update');
|
field.tooltip('update')
|
||||||
|
|
||||||
notes_display.forEach(function (disp) {
|
notes_display.forEach(function (disp) {
|
||||||
let line_obj = $("#" + note_prefix + "_" + disp.id);
|
const line_obj = $('#' + note_prefix + '_' + disp.id)
|
||||||
// Hover an emitter display also the profile picture
|
// Hover an emitter display also the profile picture
|
||||||
line_obj.hover(function () {
|
line_obj.hover(function () {
|
||||||
displayNote(disp.note, disp.name, user_note_field, profile_pic_field);
|
displayNote(disp.note, disp.name, user_note_field, profile_pic_field)
|
||||||
});
|
})
|
||||||
|
|
||||||
// When an emitter is clicked, it is removed
|
// When an emitter is clicked, it is removed
|
||||||
line_obj.click(removeNote(disp, note_prefix, notes_display, note_list_id, user_note_field,
|
line_obj.click(removeNote(disp, note_prefix, notes_display, note_list_id, user_note_field,
|
||||||
profile_pic_field));
|
profile_pic_field))
|
||||||
});
|
})
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
})// end getJSON alias
|
||||||
});// end getJSON alias
|
})
|
||||||
});
|
|
||||||
}// end function autocomplete
|
}// end function autocomplete
|
||||||
|
|
||||||
|
|
||||||
// When a validate button is clicked, we switch the validation status
|
// When a validate button is clicked, we switch the validation status
|
||||||
function de_validate (id, validated, resourcetype) {
|
function de_validate (id, validated, resourcetype) {
|
||||||
let validate_obj = $("#validate_" + id);
|
const validate_obj = $('#validate_' + id)
|
||||||
|
|
||||||
if (validate_obj.data("pending"))
|
if (validate_obj.data('pending'))
|
||||||
// The button is already clicked
|
// The button is already clicked
|
||||||
return;
|
{ return }
|
||||||
|
|
||||||
let invalidity_reason = $("#invalidity_reason_" + id).val();
|
const invalidity_reason = $('#invalidity_reason_' + id).val()
|
||||||
validate_obj.html("<strong style=\"font-size: 16pt;\">⟳</strong>");
|
validate_obj.html('<strong style="font-size: 16pt;">⟳</strong>')
|
||||||
validate_obj.data("pending", true);
|
validate_obj.data('pending', true)
|
||||||
|
|
||||||
// Perform a PATCH request to the API in order to update the transaction
|
// Perform a PATCH request to the API in order to update the transaction
|
||||||
// If the user has insufficient rights, an error message will appear
|
// If the user has insufficient rights, an error message will appear
|
||||||
$.ajax({
|
$.ajax({
|
||||||
"url": "/api/note/transaction/transaction/" + id + "/",
|
url: '/api/note/transaction/transaction/' + id + '/',
|
||||||
type: "PATCH",
|
type: 'PATCH',
|
||||||
dataType: "json",
|
dataType: 'json',
|
||||||
headers: {
|
headers: {
|
||||||
"X-CSRFTOKEN": CSRF_TOKEN
|
'X-CSRFTOKEN': CSRF_TOKEN
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
"resourcetype": resourcetype,
|
resourcetype: resourcetype,
|
||||||
"valid": !validated,
|
valid: !validated,
|
||||||
"invalidity_reason": invalidity_reason,
|
invalidity_reason: invalidity_reason
|
||||||
},
|
},
|
||||||
success: function () {
|
success: function () {
|
||||||
refreshBalance();
|
refreshBalance()
|
||||||
// error if this method doesn't exist. Please define it.
|
// error if this method doesn't exist. Please define it.
|
||||||
refreshHistory();
|
refreshHistory()
|
||||||
},
|
},
|
||||||
error: function (err) {
|
error: function (err) {
|
||||||
let errObj = JSON.parse(err.responseText);
|
const errObj = JSON.parse(err.responseText)
|
||||||
let error = errObj["detail"] ? errObj["detail"] : errObj["non_field_errors"];
|
let error = errObj.detail ? errObj.detail : errObj.non_field_errors
|
||||||
if (!error)
|
if (!error) { error = err.responseText }
|
||||||
error = err.responseText;
|
addMsg('Une erreur est survenue lors de la validation/dévalidation ' +
|
||||||
addMsg("Une erreur est survenue lors de la validation/dévalidation " +
|
'de cette transaction : ' + error, 'danger')
|
||||||
"de cette transaction : " + error, "danger");
|
|
||||||
|
|
||||||
refreshBalance();
|
refreshBalance()
|
||||||
// error if this method doesn't exist. Please define it.
|
// error if this method doesn't exist. Please define it.
|
||||||
refreshHistory();
|
refreshHistory()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -404,10 +379,10 @@ function de_validate (id, validated, resourcetype) {
|
|||||||
* @param wait Debounced milliseconds
|
* @param wait Debounced milliseconds
|
||||||
*/
|
*/
|
||||||
function debounce (callback, wait) {
|
function debounce (callback, wait) {
|
||||||
let timeout;
|
let timeout
|
||||||
return (...args) => {
|
return (...args) => {
|
||||||
const context = this;
|
const context = this
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout)
|
||||||
timeout = setTimeout(() => callback.apply(context, args), wait);
|
timeout = setTimeout(() => callback.apply(context, args), wait)
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,95 +2,92 @@
|
|||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// When a transaction is performed, lock the interface to prevent spam clicks.
|
// When a transaction is performed, lock the interface to prevent spam clicks.
|
||||||
var LOCK = false;
|
var LOCK = false
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the history table on the consumptions page.
|
* Refresh the history table on the consumptions page.
|
||||||
*/
|
*/
|
||||||
function refreshHistory() {
|
function refreshHistory () {
|
||||||
$("#history").load("/note/consos/ #history");
|
$('#history').load('/note/consos/ #history')
|
||||||
$("#most_used").load("/note/consos/ #most_used");
|
$('#most_used').load('/note/consos/ #most_used')
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function () {
|
||||||
// If hash of a category in the URL, then select this category
|
// If hash of a category in the URL, then select this category
|
||||||
// else select the first one
|
// else select the first one
|
||||||
if (location.hash) {
|
if (location.hash) {
|
||||||
$("a[href='" + location.hash + "']").tab("show");
|
$("a[href='" + location.hash + "']").tab('show')
|
||||||
} else {
|
} else {
|
||||||
$("a[data-toggle='tab']").first().tab("show");
|
$("a[data-toggle='tab']").first().tab('show')
|
||||||
|
}
|
||||||
|
|
||||||
|
// When selecting a category, change URL
|
||||||
|
$(document.body).on('click', "a[data-toggle='tab']", function () {
|
||||||
|
location.hash = this.getAttribute('href')
|
||||||
|
})
|
||||||
|
|
||||||
|
// Switching in double consumptions mode should update the layout
|
||||||
|
$('#double_conso').change(function () {
|
||||||
|
$('#consos_list_div').removeClass('d-none')
|
||||||
|
$('#user_select_div').attr('class', 'col-xl-4')
|
||||||
|
$('#infos_div').attr('class', 'col-sm-5 col-xl-6')
|
||||||
|
|
||||||
|
const note_list_obj = $('#note_list')
|
||||||
|
if (buttons.length > 0 && note_list_obj.text().length > 0) {
|
||||||
|
$('#consos_list').html(note_list_obj.html())
|
||||||
|
note_list_obj.html('')
|
||||||
|
|
||||||
|
buttons.forEach(function (button) {
|
||||||
|
$('#conso_button_' + button.id).click(function () {
|
||||||
|
if (LOCK) { return }
|
||||||
|
removeNote(button, 'conso_button', buttons, 'consos_list')()
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// When selecting a category, change URL
|
$('#single_conso').change(function () {
|
||||||
$(document.body).on("click", "a[data-toggle='tab']", function() {
|
$('#consos_list_div').addClass('d-none')
|
||||||
location.hash = this.getAttribute("href");
|
$('#user_select_div').attr('class', 'col-xl-7')
|
||||||
});
|
$('#infos_div').attr('class', 'col-sm-5 col-md-4')
|
||||||
|
|
||||||
// Switching in double consumptions mode should update the layout
|
const consos_list_obj = $('#consos_list')
|
||||||
$("#double_conso").change(function() {
|
if (buttons.length > 0) {
|
||||||
$("#consos_list_div").removeClass('d-none');
|
if (notes_display.length === 0 && consos_list_obj.text().length > 0) {
|
||||||
$("#user_select_div").attr('class', 'col-xl-4');
|
$('#note_list').html(consos_list_obj.html())
|
||||||
$("#infos_div").attr('class', 'col-sm-5 col-xl-6');
|
consos_list_obj.html('')
|
||||||
|
buttons.forEach(function (button) {
|
||||||
|
$('#conso_button_' + button.id).click(function () {
|
||||||
|
if (LOCK) { return }
|
||||||
|
removeNote(button, 'conso_button', buttons, 'note_list')()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
buttons.length = 0
|
||||||
|
consos_list_obj.html('')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
let note_list_obj = $("#note_list");
|
// Ensure we begin in single consumption. Fix issue with TurboLinks and BootstrapJS
|
||||||
if (buttons.length > 0 && note_list_obj.text().length > 0) {
|
$("label[for='double_conso']").removeClass('active')
|
||||||
$("#consos_list").html(note_list_obj.html());
|
|
||||||
note_list_obj.html("");
|
|
||||||
|
|
||||||
buttons.forEach(function(button) {
|
$('#consume_all').click(consumeAll)
|
||||||
$("#conso_button_" + button.id).click(function() {
|
})
|
||||||
if (LOCK)
|
|
||||||
return;
|
|
||||||
removeNote(button, "conso_button", buttons,"consos_list")();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#single_conso").change(function() {
|
notes = []
|
||||||
$("#consos_list_div").addClass('d-none');
|
notes_display = []
|
||||||
$("#user_select_div").attr('class', 'col-xl-7');
|
buttons = []
|
||||||
$("#infos_div").attr('class', 'col-sm-5 col-md-4');
|
|
||||||
|
|
||||||
let consos_list_obj = $("#consos_list");
|
|
||||||
if (buttons.length > 0) {
|
|
||||||
if (notes_display.length === 0 && consos_list_obj.text().length > 0) {
|
|
||||||
$("#note_list").html(consos_list_obj.html());
|
|
||||||
consos_list_obj.html("");
|
|
||||||
buttons.forEach(function(button) {
|
|
||||||
$("#conso_button_" + button.id).click(function() {
|
|
||||||
if (LOCK)
|
|
||||||
return;
|
|
||||||
removeNote(button, "conso_button", buttons,"note_list")();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buttons.length = 0;
|
|
||||||
consos_list_obj.html("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ensure we begin in single consumption. Fix issue with TurboLinks and BootstrapJS
|
|
||||||
$("label[for='double_conso']").removeClass('active');
|
|
||||||
|
|
||||||
$("#consume_all").click(consumeAll);
|
|
||||||
});
|
|
||||||
|
|
||||||
notes = [];
|
|
||||||
notes_display = [];
|
|
||||||
buttons = [];
|
|
||||||
|
|
||||||
// When the user searches an alias, we update the auto-completion
|
// When the user searches an alias, we update the auto-completion
|
||||||
autoCompleteNote("note", "note_list", notes, notes_display,
|
autoCompleteNote('note', 'note_list', notes, notes_display,
|
||||||
"alias", "note", "user_note", "profile_pic", function() {
|
'alias', 'note', 'user_note', 'profile_pic', function () {
|
||||||
if (buttons.length > 0 && $("#single_conso").is(":checked")) {
|
if (buttons.length > 0 && $('#single_conso').is(':checked')) {
|
||||||
consumeAll();
|
consumeAll()
|
||||||
return false;
|
return false
|
||||||
}
|
}
|
||||||
return true;
|
return true
|
||||||
});
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a transaction from a button.
|
* Add a transaction from a button.
|
||||||
@ -102,103 +99,98 @@ autoCompleteNote("note", "note_list", notes, notes_display,
|
|||||||
* @param template_id The identifier of the button
|
* @param template_id The identifier of the button
|
||||||
* @param template_name The name of the button
|
* @param template_name The name of the button
|
||||||
*/
|
*/
|
||||||
function addConso(dest, amount, type, category_id, category_name, template_id, template_name) {
|
function addConso (dest, amount, type, category_id, category_name, template_id, template_name) {
|
||||||
var button = null;
|
var button = null
|
||||||
buttons.forEach(function(b) {
|
buttons.forEach(function (b) {
|
||||||
if (b.id === template_id) {
|
if (b.id === template_id) {
|
||||||
b.quantity += 1;
|
b.quantity += 1
|
||||||
button = b;
|
button = b
|
||||||
}
|
|
||||||
});
|
|
||||||
if (button == null) {
|
|
||||||
button = {
|
|
||||||
id: template_id,
|
|
||||||
name: template_name,
|
|
||||||
dest: dest,
|
|
||||||
quantity: 1,
|
|
||||||
amount: amount,
|
|
||||||
type: type,
|
|
||||||
category_id: category_id,
|
|
||||||
category_name: category_name
|
|
||||||
};
|
|
||||||
buttons.push(button);
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
let dc_obj = $("#double_conso");
|
if (button == null) {
|
||||||
if (dc_obj.is(":checked") || notes_display.length === 0) {
|
button = {
|
||||||
let list = dc_obj.is(":checked") ? "consos_list" : "note_list";
|
id: template_id,
|
||||||
let html = "";
|
name: template_name,
|
||||||
buttons.forEach(function(button) {
|
dest: dest,
|
||||||
html += li("conso_button_" + button.id, button.name
|
quantity: 1,
|
||||||
+ "<span class=\"badge badge-dark badge-pill\">" + button.quantity + "</span>");
|
amount: amount,
|
||||||
});
|
type: type,
|
||||||
|
category_id: category_id,
|
||||||
$("#" + list).html(html);
|
category_name: category_name
|
||||||
|
|
||||||
buttons.forEach(function(button) {
|
|
||||||
$("#conso_button_" + button.id).click(function() {
|
|
||||||
if (LOCK)
|
|
||||||
return;
|
|
||||||
removeNote(button, "conso_button", buttons, list)();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
else
|
buttons.push(button)
|
||||||
consumeAll();
|
}
|
||||||
|
|
||||||
|
const dc_obj = $('#double_conso')
|
||||||
|
if (dc_obj.is(':checked') || notes_display.length === 0) {
|
||||||
|
const list = dc_obj.is(':checked') ? 'consos_list' : 'note_list'
|
||||||
|
let html = ''
|
||||||
|
buttons.forEach(function (button) {
|
||||||
|
html += li('conso_button_' + button.id, button.name +
|
||||||
|
'<span class="badge badge-dark badge-pill">' + button.quantity + '</span>')
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#' + list).html(html)
|
||||||
|
|
||||||
|
buttons.forEach(function (button) {
|
||||||
|
$('#conso_button_' + button.id).click(function () {
|
||||||
|
if (LOCK) { return }
|
||||||
|
removeNote(button, 'conso_button', buttons, list)()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else { consumeAll() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the page as its initial state.
|
* Reset the page as its initial state.
|
||||||
*/
|
*/
|
||||||
function reset() {
|
function reset () {
|
||||||
notes_display.length = 0;
|
notes_display.length = 0
|
||||||
notes.length = 0;
|
notes.length = 0
|
||||||
buttons.length = 0;
|
buttons.length = 0
|
||||||
$("#note_list").html("");
|
$('#note_list').html('')
|
||||||
$("#consos_list").html("");
|
$('#consos_list').html('')
|
||||||
$("#note").val("");
|
$('#note').val('')
|
||||||
$("#note").attr("data-original-title", "").tooltip("hide");
|
$('#note').attr('data-original-title', '').tooltip('hide')
|
||||||
$("#profile_pic").attr("src", "/static/member/img/default_picture.png");
|
$('#profile_pic').attr('src', '/static/member/img/default_picture.png')
|
||||||
$("#profile_pic_link").attr("href", "#");
|
$('#profile_pic_link').attr('href', '#')
|
||||||
refreshHistory();
|
refreshHistory()
|
||||||
refreshBalance();
|
refreshBalance()
|
||||||
LOCK = false;
|
LOCK = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply all transactions: all notes in `notes` buy each item in `buttons`
|
* Apply all transactions: all notes in `notes` buy each item in `buttons`
|
||||||
*/
|
*/
|
||||||
function consumeAll() {
|
function consumeAll () {
|
||||||
if (LOCK)
|
if (LOCK) { return }
|
||||||
return;
|
|
||||||
|
|
||||||
LOCK = true;
|
LOCK = true
|
||||||
|
|
||||||
let error = false;
|
let error = false
|
||||||
|
|
||||||
if (notes_display.length === 0) {
|
if (notes_display.length === 0) {
|
||||||
$("#note").addClass('is-invalid');
|
$('#note').addClass('is-invalid')
|
||||||
$("#note_list").html(li("", "<strong>Ajoutez des émetteurs.</strong>", "text-danger"));
|
$('#note_list').html(li('', '<strong>Ajoutez des émetteurs.</strong>', 'text-danger'))
|
||||||
error = true;
|
error = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buttons.length === 0) {
|
if (buttons.length === 0) {
|
||||||
$("#consos_list").html(li("", "<strong>Ajoutez des consommations.</strong>", "text-danger"));
|
$('#consos_list').html(li('', '<strong>Ajoutez des consommations.</strong>', 'text-danger'))
|
||||||
error = true;
|
error = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
LOCK = false;
|
LOCK = false
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
notes_display.forEach(function(note_display) {
|
notes_display.forEach(function (note_display) {
|
||||||
buttons.forEach(function(button) {
|
buttons.forEach(function (button) {
|
||||||
consume(note_display.note, note_display.name, button.dest, button.quantity * note_display.quantity, button.amount,
|
consume(note_display.note, note_display.name, button.dest, button.quantity * note_display.quantity, button.amount,
|
||||||
button.name + " (" + button.category_name + ")", button.type, button.category_id, button.id);
|
button.name + ' (' + button.category_name + ')', button.type, button.category_id, button.id)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -213,58 +205,60 @@ function consumeAll() {
|
|||||||
* @param category The category id of the button (type: int)
|
* @param category The category id of the button (type: int)
|
||||||
* @param template The button id (type: int)
|
* @param template The button id (type: int)
|
||||||
*/
|
*/
|
||||||
function consume(source, source_alias, dest, quantity, amount, reason, type, category, template) {
|
function consume (source, source_alias, dest, quantity, amount, reason, type, category, template) {
|
||||||
$.post("/api/note/transaction/transaction/",
|
$.post('/api/note/transaction/transaction/',
|
||||||
|
{
|
||||||
|
csrfmiddlewaretoken: CSRF_TOKEN,
|
||||||
|
quantity: quantity,
|
||||||
|
amount: amount,
|
||||||
|
reason: reason,
|
||||||
|
valid: true,
|
||||||
|
polymorphic_ctype: type,
|
||||||
|
resourcetype: 'RecurrentTransaction',
|
||||||
|
source: source.id,
|
||||||
|
source_alias: source_alias,
|
||||||
|
destination: dest,
|
||||||
|
template: template
|
||||||
|
})
|
||||||
|
.done(function () {
|
||||||
|
if (!isNaN(source.balance)) {
|
||||||
|
const newBalance = source.balance - quantity * amount
|
||||||
|
if (newBalance <= -5000) {
|
||||||
|
addMsg('Attention, La transaction depuis la note ' + source_alias + ' a été réalisée avec ' +
|
||||||
|
'succès, mais la note émettrice ' + source_alias + ' est en négatif sévère.',
|
||||||
|
'danger', 30000)
|
||||||
|
} else if (newBalance < 0) {
|
||||||
|
addMsg('Attention, La transaction depuis la note ' + source_alias + ' a été réalisée avec ' +
|
||||||
|
'succès, mais la note émettrice ' + source_alias + ' est en négatif.',
|
||||||
|
'warning', 30000)
|
||||||
|
}
|
||||||
|
if (source.membership && source.membership.date_end < new Date().toISOString()) {
|
||||||
|
addMsg('Attention : la note émettrice ' + source.name + " n'est plus adhérente.",
|
||||||
|
'danger', 30000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reset()
|
||||||
|
}).fail(function (e) {
|
||||||
|
$.post('/api/note/transaction/transaction/',
|
||||||
{
|
{
|
||||||
"csrfmiddlewaretoken": CSRF_TOKEN,
|
csrfmiddlewaretoken: CSRF_TOKEN,
|
||||||
"quantity": quantity,
|
quantity: quantity,
|
||||||
"amount": amount,
|
amount: amount,
|
||||||
"reason": reason,
|
reason: reason,
|
||||||
"valid": true,
|
valid: false,
|
||||||
"polymorphic_ctype": type,
|
invalidity_reason: 'Solde insuffisant',
|
||||||
"resourcetype": "RecurrentTransaction",
|
polymorphic_ctype: type,
|
||||||
"source": source.id,
|
resourcetype: 'RecurrentTransaction',
|
||||||
"source_alias": source_alias,
|
source: source,
|
||||||
"destination": dest,
|
source_alias: source_alias,
|
||||||
"template": template
|
destination: dest,
|
||||||
})
|
template: template
|
||||||
.done(function () {
|
}).done(function () {
|
||||||
if (!isNaN(source.balance)) {
|
reset()
|
||||||
let newBalance = source.balance - quantity * amount;
|
addMsg("La transaction n'a pas pu être validée pour cause de solde insuffisant.", 'danger', 10000)
|
||||||
if (newBalance <= -5000)
|
}).fail(function () {
|
||||||
addMsg("Attention, La transaction depuis la note " + source_alias + " a été réalisée avec " +
|
reset()
|
||||||
"succès, mais la note émettrice " + source_alias + " est en négatif sévère.",
|
errMsg(e.responseJSON)
|
||||||
"danger", 30000);
|
})
|
||||||
else if (newBalance < 0)
|
})
|
||||||
addMsg("Attention, La transaction depuis la note " + source_alias + " a été réalisée avec " +
|
|
||||||
"succès, mais la note émettrice " + source_alias + " est en négatif.",
|
|
||||||
"warning", 30000);
|
|
||||||
if (source.membership && source.membership.date_end < new Date().toISOString())
|
|
||||||
addMsg("Attention : la note émettrice " + source.name + " n'est plus adhérente.",
|
|
||||||
"danger", 30000);
|
|
||||||
}
|
|
||||||
reset();
|
|
||||||
}).fail(function (e) {
|
|
||||||
$.post("/api/note/transaction/transaction/",
|
|
||||||
{
|
|
||||||
"csrfmiddlewaretoken": CSRF_TOKEN,
|
|
||||||
"quantity": quantity,
|
|
||||||
"amount": amount,
|
|
||||||
"reason": reason,
|
|
||||||
"valid": false,
|
|
||||||
"invalidity_reason": "Solde insuffisant",
|
|
||||||
"polymorphic_ctype": type,
|
|
||||||
"resourcetype": "RecurrentTransaction",
|
|
||||||
"source": source,
|
|
||||||
"source_alias": source_alias,
|
|
||||||
"destination": dest,
|
|
||||||
"template": template
|
|
||||||
}).done(function() {
|
|
||||||
reset();
|
|
||||||
addMsg("La transaction n'a pas pu être validée pour cause de solde insuffisant.", "danger", 10000);
|
|
||||||
}).fail(function () {
|
|
||||||
reset();
|
|
||||||
errMsg(e.responseJSON);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -9,241 +9,240 @@
|
|||||||
* Licensed under the New BSD License
|
* Licensed under the New BSD License
|
||||||
* See: http://www.opensource.org/licenses/bsd-license.php
|
* See: http://www.opensource.org/licenses/bsd-license.php
|
||||||
*/
|
*/
|
||||||
;(function($) {
|
;(function ($) {
|
||||||
$.fn.formset = function(opts)
|
$.fn.formset = function (opts) {
|
||||||
{
|
var options = $.extend({}, $.fn.formset.defaults, opts)
|
||||||
var options = $.extend({}, $.fn.formset.defaults, opts),
|
var flatExtraClasses = options.extraClasses.join(' ')
|
||||||
flatExtraClasses = options.extraClasses.join(' '),
|
var totalForms = $('#id_' + options.prefix + '-TOTAL_FORMS')
|
||||||
totalForms = $('#id_' + options.prefix + '-TOTAL_FORMS'),
|
var maxForms = $('#id_' + options.prefix + '-MAX_NUM_FORMS')
|
||||||
maxForms = $('#id_' + options.prefix + '-MAX_NUM_FORMS'),
|
var minForms = $('#id_' + options.prefix + '-MIN_NUM_FORMS')
|
||||||
minForms = $('#id_' + options.prefix + '-MIN_NUM_FORMS'),
|
var childElementSelector = 'input,select,textarea,label,div'
|
||||||
childElementSelector = 'input,select,textarea,label,div',
|
var $$ = $(this)
|
||||||
$$ = $(this),
|
|
||||||
|
|
||||||
applyExtraClasses = function(row, ndx) {
|
var applyExtraClasses = function (row, ndx) {
|
||||||
if (options.extraClasses) {
|
if (options.extraClasses) {
|
||||||
row.removeClass(flatExtraClasses);
|
row.removeClass(flatExtraClasses)
|
||||||
row.addClass(options.extraClasses[ndx % options.extraClasses.length]);
|
row.addClass(options.extraClasses[ndx % options.extraClasses.length])
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
updateElementIndex = function(elem, prefix, ndx) {
|
var updateElementIndex = function (elem, prefix, ndx) {
|
||||||
var idRegex = new RegExp(prefix + '-(\\d+|__prefix__)-'),
|
var idRegex = new RegExp(prefix + '-(\\d+|__prefix__)-')
|
||||||
replacement = prefix + '-' + ndx + '-';
|
var replacement = prefix + '-' + ndx + '-'
|
||||||
if (elem.attr("for")) elem.attr("for", elem.attr("for").replace(idRegex, replacement));
|
if (elem.attr('for')) elem.attr('for', elem.attr('for').replace(idRegex, replacement))
|
||||||
if (elem.attr('id')) elem.attr('id', elem.attr('id').replace(idRegex, replacement));
|
if (elem.attr('id')) elem.attr('id', elem.attr('id').replace(idRegex, replacement))
|
||||||
if (elem.attr('name')) elem.attr('name', elem.attr('name').replace(idRegex, replacement));
|
if (elem.attr('name')) elem.attr('name', elem.attr('name').replace(idRegex, replacement))
|
||||||
},
|
}
|
||||||
|
|
||||||
hasChildElements = function(row) {
|
var hasChildElements = function (row) {
|
||||||
return row.find(childElementSelector).length > 0;
|
return row.find(childElementSelector).length > 0
|
||||||
},
|
}
|
||||||
|
|
||||||
showAddButton = function() {
|
var showAddButton = function () {
|
||||||
return maxForms.length == 0 || // For Django versions pre 1.2
|
return maxForms.length == 0 || // For Django versions pre 1.2
|
||||||
(maxForms.val() == '' || (maxForms.val() - totalForms.val() > 0));
|
(maxForms.val() == '' || (maxForms.val() - totalForms.val() > 0))
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether delete link(s) can be displayed - when total forms > min forms
|
* Indicates whether delete link(s) can be displayed - when total forms > min forms
|
||||||
*/
|
*/
|
||||||
showDeleteLinks = function() {
|
var showDeleteLinks = function () {
|
||||||
return minForms.length == 0 || // For Django versions pre 1.7
|
return minForms.length == 0 || // For Django versions pre 1.7
|
||||||
(minForms.val() == '' || (totalForms.val() - minForms.val() > 0));
|
(minForms.val() == '' || (totalForms.val() - minForms.val() > 0))
|
||||||
},
|
}
|
||||||
|
|
||||||
insertDeleteLink = function(row) {
|
var insertDeleteLink = function (row) {
|
||||||
var delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.'),
|
var delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.')
|
||||||
addCssSelector = $.trim(options.addCssClass).replace(/\s+/g, '.');
|
var addCssSelector = $.trim(options.addCssClass).replace(/\s+/g, '.')
|
||||||
|
|
||||||
var delButtonHTML = '<a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText +'</a>';
|
var delButtonHTML = '<a class="' + options.deleteCssClass + '" href="javascript:void(0)">' + options.deleteText + '</a>'
|
||||||
if (options.deleteContainerClass) {
|
if (options.deleteContainerClass) {
|
||||||
// If we have a specific container for the remove button,
|
// If we have a specific container for the remove button,
|
||||||
// place it as the last child of that container:
|
// place it as the last child of that container:
|
||||||
row.find('[class*="' + options.deleteContainerClass + '"]').append(delButtonHTML);
|
row.find('[class*="' + options.deleteContainerClass + '"]').append(delButtonHTML)
|
||||||
} else if (row.is('TR')) {
|
} else if (row.is('TR')) {
|
||||||
// If the forms are laid out in table rows, insert
|
// If the forms are laid out in table rows, insert
|
||||||
// the remove button into the last table cell:
|
// the remove button into the last table cell:
|
||||||
row.children('td:last').append(delButtonHTML);
|
row.children('td:last').append(delButtonHTML)
|
||||||
} else if (row.is('UL') || row.is('OL')) {
|
} else if (row.is('UL') || row.is('OL')) {
|
||||||
// If they're laid out as an ordered/unordered list,
|
// If they're laid out as an ordered/unordered list,
|
||||||
// insert an <li> after the last list item:
|
// insert an <li> after the last list item:
|
||||||
row.append('<li>' + delButtonHTML + '</li>');
|
row.append('<li>' + delButtonHTML + '</li>')
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, just insert the remove button as the
|
// Otherwise, just insert the remove button as the
|
||||||
// last child element of the form's container:
|
// last child element of the form's container:
|
||||||
row.append(delButtonHTML);
|
row.append(delButtonHTML)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if we're under the minimum number of forms - not to display delete link at rendering
|
// Check if we're under the minimum number of forms - not to display delete link at rendering
|
||||||
if (!showDeleteLinks()){
|
if (!showDeleteLinks()) {
|
||||||
row.find('a.' + delCssSelector).hide();
|
row.find('a.' + delCssSelector).hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
row.find('a.' + delCssSelector).click(function() {
|
row.find('a.' + delCssSelector).click(function () {
|
||||||
var row = $(this).parents('.' + options.formCssClass),
|
var row = $(this).parents('.' + options.formCssClass)
|
||||||
del = row.find('input:hidden[id $= "-DELETE"]'),
|
var del = row.find('input:hidden[id $= "-DELETE"]')
|
||||||
buttonRow = row.siblings("a." + addCssSelector + ', .' + options.formCssClass + '-add'),
|
var buttonRow = row.siblings('a.' + addCssSelector + ', .' + options.formCssClass + '-add')
|
||||||
forms;
|
var forms
|
||||||
if (del.length) {
|
if (del.length) {
|
||||||
// We're dealing with an inline formset.
|
// We're dealing with an inline formset.
|
||||||
// Rather than remove this form from the DOM, we'll mark it as deleted
|
// Rather than remove this form from the DOM, we'll mark it as deleted
|
||||||
// and hide it, then let Django handle the deleting:
|
// and hide it, then let Django handle the deleting:
|
||||||
del.val('on');
|
del.val('on')
|
||||||
row.hide();
|
row.hide()
|
||||||
forms = $('.' + options.formCssClass).not(':hidden');
|
forms = $('.' + options.formCssClass).not(':hidden')
|
||||||
} else {
|
} else {
|
||||||
row.remove();
|
row.remove()
|
||||||
// Update the TOTAL_FORMS count:
|
// Update the TOTAL_FORMS count:
|
||||||
forms = $('.' + options.formCssClass).not('.formset-custom-template');
|
forms = $('.' + options.formCssClass).not('.formset-custom-template')
|
||||||
totalForms.val(forms.length);
|
totalForms.val(forms.length)
|
||||||
}
|
|
||||||
for (var i=0, formCount=forms.length; i<formCount; i++) {
|
|
||||||
// Apply `extraClasses` to form rows so they're nicely alternating:
|
|
||||||
applyExtraClasses(forms.eq(i), i);
|
|
||||||
if (!del.length) {
|
|
||||||
// Also update names and IDs for all child controls (if this isn't
|
|
||||||
// a delete-able inline formset) so they remain in sequence:
|
|
||||||
forms.eq(i).find(childElementSelector).each(function() {
|
|
||||||
updateElementIndex($(this), options.prefix, i);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if we've reached the minimum number of forms - hide all delete link(s)
|
|
||||||
if (!showDeleteLinks()){
|
|
||||||
$('a.' + delCssSelector).each(function(){$(this).hide();});
|
|
||||||
}
|
|
||||||
// Check if we need to show the add button:
|
|
||||||
if (buttonRow.is(':hidden') && showAddButton()) buttonRow.show();
|
|
||||||
// If a post-delete callback was provided, call it with the deleted form:
|
|
||||||
if (options.removed) options.removed(row);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$$.each(function(i) {
|
|
||||||
var row = $(this),
|
|
||||||
del = row.find('input:checkbox[id $= "-DELETE"]');
|
|
||||||
if (del.length) {
|
|
||||||
// If you specify "can_delete = True" when creating an inline formset,
|
|
||||||
// Django adds a checkbox to each form in the formset.
|
|
||||||
// Replace the default checkbox with a hidden field:
|
|
||||||
if (del.is(':checked')) {
|
|
||||||
// If an inline formset containing deleted forms fails validation, make sure
|
|
||||||
// we keep the forms hidden (thanks for the bug report and suggested fix Mike)
|
|
||||||
del.before('<input type="hidden" name="' + del.attr('name') +'" id="' + del.attr('id') +'" value="on" />');
|
|
||||||
row.hide();
|
|
||||||
} else {
|
|
||||||
del.before('<input type="hidden" name="' + del.attr('name') +'" id="' + del.attr('id') +'" />');
|
|
||||||
}
|
|
||||||
// Hide any labels associated with the DELETE checkbox:
|
|
||||||
$('label[for="' + del.attr('id') + '"]').hide();
|
|
||||||
del.remove();
|
|
||||||
}
|
|
||||||
if (hasChildElements(row)) {
|
|
||||||
row.addClass(options.formCssClass);
|
|
||||||
if (row.is(':visible')) {
|
|
||||||
insertDeleteLink(row);
|
|
||||||
applyExtraClasses(row, i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($$.length) {
|
|
||||||
var hideAddButton = !showAddButton(),
|
|
||||||
addButton, template;
|
|
||||||
if (options.formTemplate) {
|
|
||||||
// If a form template was specified, we'll clone it to generate new form instances:
|
|
||||||
template = (options.formTemplate instanceof $) ? options.formTemplate : $(options.formTemplate);
|
|
||||||
template.removeAttr('id').addClass(options.formCssClass + ' formset-custom-template');
|
|
||||||
template.find(childElementSelector).each(function() {
|
|
||||||
updateElementIndex($(this), options.prefix, '__prefix__');
|
|
||||||
});
|
|
||||||
insertDeleteLink(template);
|
|
||||||
} else {
|
|
||||||
// Otherwise, use the last form in the formset; this works much better if you've got
|
|
||||||
// extra (>= 1) forms (thnaks to justhamade for pointing this out):
|
|
||||||
if (options.hideLastAddForm) $('.' + options.formCssClass + ':last').hide();
|
|
||||||
template = $('.' + options.formCssClass + ':last').clone(true).removeAttr('id');
|
|
||||||
template.find('input:hidden[id $= "-DELETE"]').remove();
|
|
||||||
// Clear all cloned fields, except those the user wants to keep (thanks to brunogola for the suggestion):
|
|
||||||
template.find(childElementSelector).not(options.keepFieldValues).each(function() {
|
|
||||||
var elem = $(this);
|
|
||||||
// If this is a checkbox or radiobutton, uncheck it.
|
|
||||||
// This fixes Issue 1, reported by Wilson.Andrew.J:
|
|
||||||
if (elem.is('input:checkbox') || elem.is('input:radio')) {
|
|
||||||
elem.attr('checked', false);
|
|
||||||
} else {
|
|
||||||
elem.val('');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// FIXME: Perhaps using $.data would be a better idea?
|
|
||||||
options.formTemplate = template;
|
|
||||||
|
|
||||||
var addButtonHTML = '<a class="' + options.addCssClass + '" href="javascript:void(0)">' + options.addText + '</a>';
|
|
||||||
if (options.addContainerClass) {
|
|
||||||
// If we have a specific container for the "add" button,
|
|
||||||
// place it as the last child of that container:
|
|
||||||
var addContainer = $('[class*="' + options.addContainerClass + '"');
|
|
||||||
addContainer.append(addButtonHTML);
|
|
||||||
addButton = addContainer.find('[class="' + options.addCssClass + '"]');
|
|
||||||
} else if ($$.is('TR')) {
|
|
||||||
// If forms are laid out as table rows, insert the
|
|
||||||
// "add" button in a new table row:
|
|
||||||
var numCols = $$.eq(0).children().length, // This is a bit of an assumption :|
|
|
||||||
buttonRow = $('<tr><td colspan="' + numCols + '">' + addButtonHTML + '</tr>').addClass(options.formCssClass + '-add');
|
|
||||||
$$.parent().append(buttonRow);
|
|
||||||
addButton = buttonRow.find('a');
|
|
||||||
} else {
|
|
||||||
// Otherwise, insert it immediately after the last form:
|
|
||||||
$$.filter(':last').after(addButtonHTML);
|
|
||||||
addButton = $$.filter(':last').next();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hideAddButton) addButton.hide();
|
|
||||||
|
|
||||||
addButton.click(function() {
|
|
||||||
var formCount = parseInt(totalForms.val()),
|
|
||||||
row = options.formTemplate.clone(true).removeClass('formset-custom-template'),
|
|
||||||
buttonRow = $($(this).parents('tr.' + options.formCssClass + '-add').get(0) || this),
|
|
||||||
delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.');
|
|
||||||
applyExtraClasses(row, formCount);
|
|
||||||
row.insertBefore(buttonRow).show();
|
|
||||||
row.find(childElementSelector).each(function() {
|
|
||||||
updateElementIndex($(this), options.prefix, formCount);
|
|
||||||
});
|
|
||||||
totalForms.val(formCount + 1);
|
|
||||||
// Check if we're above the minimum allowed number of forms -> show all delete link(s)
|
|
||||||
if (showDeleteLinks()){
|
|
||||||
$('a.' + delCssSelector).each(function(){$(this).show();});
|
|
||||||
}
|
|
||||||
// Check if we've exceeded the maximum allowed number of forms:
|
|
||||||
if (!showAddButton()) buttonRow.hide();
|
|
||||||
// If a post-add callback was supplied, call it with the added form:
|
|
||||||
if (options.added) options.added(row);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
for (var i = 0, formCount = forms.length; i < formCount; i++) {
|
||||||
|
// Apply `extraClasses` to form rows so they're nicely alternating:
|
||||||
|
applyExtraClasses(forms.eq(i), i)
|
||||||
|
if (!del.length) {
|
||||||
|
// Also update names and IDs for all child controls (if this isn't
|
||||||
|
// a delete-able inline formset) so they remain in sequence:
|
||||||
|
forms.eq(i).find(childElementSelector).each(function () {
|
||||||
|
updateElementIndex($(this), options.prefix, i)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check if we've reached the minimum number of forms - hide all delete link(s)
|
||||||
|
if (!showDeleteLinks()) {
|
||||||
|
$('a.' + delCssSelector).each(function () { $(this).hide() })
|
||||||
|
}
|
||||||
|
// Check if we need to show the add button:
|
||||||
|
if (buttonRow.is(':hidden') && showAddButton()) buttonRow.show()
|
||||||
|
// If a post-delete callback was provided, call it with the deleted form:
|
||||||
|
if (options.removed) options.removed(row)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return $$;
|
$$.each(function (i) {
|
||||||
};
|
var row = $(this)
|
||||||
|
var del = row.find('input:checkbox[id $= "-DELETE"]')
|
||||||
|
if (del.length) {
|
||||||
|
// If you specify "can_delete = True" when creating an inline formset,
|
||||||
|
// Django adds a checkbox to each form in the formset.
|
||||||
|
// Replace the default checkbox with a hidden field:
|
||||||
|
if (del.is(':checked')) {
|
||||||
|
// If an inline formset containing deleted forms fails validation, make sure
|
||||||
|
// we keep the forms hidden (thanks for the bug report and suggested fix Mike)
|
||||||
|
del.before('<input type="hidden" name="' + del.attr('name') + '" id="' + del.attr('id') + '" value="on" />')
|
||||||
|
row.hide()
|
||||||
|
} else {
|
||||||
|
del.before('<input type="hidden" name="' + del.attr('name') + '" id="' + del.attr('id') + '" />')
|
||||||
|
}
|
||||||
|
// Hide any labels associated with the DELETE checkbox:
|
||||||
|
$('label[for="' + del.attr('id') + '"]').hide()
|
||||||
|
del.remove()
|
||||||
|
}
|
||||||
|
if (hasChildElements(row)) {
|
||||||
|
row.addClass(options.formCssClass)
|
||||||
|
if (row.is(':visible')) {
|
||||||
|
insertDeleteLink(row)
|
||||||
|
applyExtraClasses(row, i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
/* Setup plugin defaults */
|
if ($$.length) {
|
||||||
$.fn.formset.defaults = {
|
var hideAddButton = !showAddButton()
|
||||||
prefix: 'form', // The form prefix for your django formset
|
var addButton; var template
|
||||||
formTemplate: null, // The jQuery selection cloned to generate new form instances
|
if (options.formTemplate) {
|
||||||
addText: 'add another', // Text for the add link
|
// If a form template was specified, we'll clone it to generate new form instances:
|
||||||
deleteText: 'remove', // Text for the delete link
|
template = (options.formTemplate instanceof $) ? options.formTemplate : $(options.formTemplate)
|
||||||
addContainerClass: null, // Container CSS class for the add link
|
template.removeAttr('id').addClass(options.formCssClass + ' formset-custom-template')
|
||||||
deleteContainerClass: null, // Container CSS class for the delete link
|
template.find(childElementSelector).each(function () {
|
||||||
addCssClass: 'add-row', // CSS class applied to the add link
|
updateElementIndex($(this), options.prefix, '__prefix__')
|
||||||
deleteCssClass: 'delete-row', // CSS class applied to the delete link
|
})
|
||||||
formCssClass: 'dynamic-form', // CSS class applied to each form in a formset
|
insertDeleteLink(template)
|
||||||
extraClasses: [], // Additional CSS classes, which will be applied to each form in turn
|
} else {
|
||||||
keepFieldValues: '', // jQuery selector for fields whose values should be kept when the form is cloned
|
// Otherwise, use the last form in the formset; this works much better if you've got
|
||||||
added: null, // Function called each time a new form is added
|
// extra (>= 1) forms (thnaks to justhamade for pointing this out):
|
||||||
removed: null, // Function called each time a form is deleted
|
if (options.hideLastAddForm) $('.' + options.formCssClass + ':last').hide()
|
||||||
hideLastAddForm: false // When set to true, hide last empty add form (becomes visible when clicking on add button)
|
template = $('.' + options.formCssClass + ':last').clone(true).removeAttr('id')
|
||||||
};
|
template.find('input:hidden[id $= "-DELETE"]').remove()
|
||||||
})(jQuery);
|
// Clear all cloned fields, except those the user wants to keep (thanks to brunogola for the suggestion):
|
||||||
|
template.find(childElementSelector).not(options.keepFieldValues).each(function () {
|
||||||
|
var elem = $(this)
|
||||||
|
// If this is a checkbox or radiobutton, uncheck it.
|
||||||
|
// This fixes Issue 1, reported by Wilson.Andrew.J:
|
||||||
|
if (elem.is('input:checkbox') || elem.is('input:radio')) {
|
||||||
|
elem.attr('checked', false)
|
||||||
|
} else {
|
||||||
|
elem.val('')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// FIXME: Perhaps using $.data would be a better idea?
|
||||||
|
options.formTemplate = template
|
||||||
|
|
||||||
|
var addButtonHTML = '<a class="' + options.addCssClass + '" href="javascript:void(0)">' + options.addText + '</a>'
|
||||||
|
if (options.addContainerClass) {
|
||||||
|
// If we have a specific container for the "add" button,
|
||||||
|
// place it as the last child of that container:
|
||||||
|
var addContainer = $('[class*="' + options.addContainerClass + '"')
|
||||||
|
addContainer.append(addButtonHTML)
|
||||||
|
addButton = addContainer.find('[class="' + options.addCssClass + '"]')
|
||||||
|
} else if ($$.is('TR')) {
|
||||||
|
// If forms are laid out as table rows, insert the
|
||||||
|
// "add" button in a new table row:
|
||||||
|
var numCols = $$.eq(0).children().length // This is a bit of an assumption :|
|
||||||
|
var buttonRow = $('<tr><td colspan="' + numCols + '">' + addButtonHTML + '</tr>').addClass(options.formCssClass + '-add')
|
||||||
|
$$.parent().append(buttonRow)
|
||||||
|
addButton = buttonRow.find('a')
|
||||||
|
} else {
|
||||||
|
// Otherwise, insert it immediately after the last form:
|
||||||
|
$$.filter(':last').after(addButtonHTML)
|
||||||
|
addButton = $$.filter(':last').next()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hideAddButton) addButton.hide()
|
||||||
|
|
||||||
|
addButton.click(function () {
|
||||||
|
var formCount = parseInt(totalForms.val())
|
||||||
|
var row = options.formTemplate.clone(true).removeClass('formset-custom-template')
|
||||||
|
var buttonRow = $($(this).parents('tr.' + options.formCssClass + '-add').get(0) || this)
|
||||||
|
var delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.')
|
||||||
|
applyExtraClasses(row, formCount)
|
||||||
|
row.insertBefore(buttonRow).show()
|
||||||
|
row.find(childElementSelector).each(function () {
|
||||||
|
updateElementIndex($(this), options.prefix, formCount)
|
||||||
|
})
|
||||||
|
totalForms.val(formCount + 1)
|
||||||
|
// Check if we're above the minimum allowed number of forms -> show all delete link(s)
|
||||||
|
if (showDeleteLinks()) {
|
||||||
|
$('a.' + delCssSelector).each(function () { $(this).show() })
|
||||||
|
}
|
||||||
|
// Check if we've exceeded the maximum allowed number of forms:
|
||||||
|
if (!showAddButton()) buttonRow.hide()
|
||||||
|
// If a post-add callback was supplied, call it with the added form:
|
||||||
|
if (options.added) options.added(row)
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return $$
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup plugin defaults */
|
||||||
|
$.fn.formset.defaults = {
|
||||||
|
prefix: 'form', // The form prefix for your django formset
|
||||||
|
formTemplate: null, // The jQuery selection cloned to generate new form instances
|
||||||
|
addText: 'add another', // Text for the add link
|
||||||
|
deleteText: 'remove', // Text for the delete link
|
||||||
|
addContainerClass: null, // Container CSS class for the add link
|
||||||
|
deleteContainerClass: null, // Container CSS class for the delete link
|
||||||
|
addCssClass: 'add-row', // CSS class applied to the add link
|
||||||
|
deleteCssClass: 'delete-row', // CSS class applied to the delete link
|
||||||
|
formCssClass: 'dynamic-form', // CSS class applied to each form in a formset
|
||||||
|
extraClasses: [], // Additional CSS classes, which will be applied to each form in turn
|
||||||
|
keepFieldValues: '', // jQuery selector for fields whose values should be kept when the form is cloned
|
||||||
|
added: null, // Function called each time a new form is added
|
||||||
|
removed: null, // Function called each time a form is deleted
|
||||||
|
hideLastAddForm: false // When set to true, hide last empty add form (becomes visible when clicking on add button)
|
||||||
|
}
|
||||||
|
})(jQuery)
|
||||||
|
@ -6,40 +6,40 @@
|
|||||||
let cursor = 0
|
let cursor = 0
|
||||||
const KONAMI_CODE = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65]
|
const KONAMI_CODE = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65]
|
||||||
|
|
||||||
function afterKonami() {
|
function afterKonami () {
|
||||||
// Load Rythm.js
|
// Load Rythm.js
|
||||||
var rythmScript = document.createElement('script')
|
var rythmScript = document.createElement('script')
|
||||||
rythmScript.setAttribute('src','//unpkg.com/rythm.js@2.2.5/rythm.min.js')
|
rythmScript.setAttribute('src', '//unpkg.com/rythm.js@2.2.5/rythm.min.js')
|
||||||
document.head.appendChild(rythmScript)
|
document.head.appendChild(rythmScript)
|
||||||
|
|
||||||
rythmScript.addEventListener('load', function() {
|
rythmScript.addEventListener('load', function () {
|
||||||
// Ker-Lyon audio courtesy of @adalan, ker-lyon.fr
|
// Ker-Lyon audio courtesy of @adalan, ker-lyon.fr
|
||||||
const audioElement = new Audio('/static/song/konami.ogg')
|
const audioElement = new Audio('/static/song/konami.ogg')
|
||||||
audioElement.loop = true
|
audioElement.loop = true
|
||||||
audioElement.play()
|
audioElement.play()
|
||||||
|
|
||||||
const rythm = new Rythm()
|
const rythm = new Rythm()
|
||||||
rythm.connectExternalAudioElement(audioElement)
|
rythm.connectExternalAudioElement(audioElement)
|
||||||
rythm.addRythm('card', 'pulse', 50, 50, {
|
rythm.addRythm('card', 'pulse', 50, 50, {
|
||||||
min: 1,
|
min: 1,
|
||||||
max: 1.1
|
max: 1.1
|
||||||
})
|
})
|
||||||
rythm.addRythm('d-flex', 'color', 50, 50, {
|
rythm.addRythm('d-flex', 'color', 50, 50, {
|
||||||
from: [64,64,64],
|
from: [64, 64, 64],
|
||||||
to:[128,64,128]
|
to: [128, 64, 128]
|
||||||
})
|
})
|
||||||
rythm.addRythm('nav-link', 'jump', 150, 50, {
|
rythm.addRythm('nav-link', 'jump', 150, 50, {
|
||||||
min: 0,
|
min: 0,
|
||||||
max: 10
|
max: 10
|
||||||
})
|
})
|
||||||
rythm.start()
|
rythm.start()
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register custom event
|
// Register custom event
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
cursor = (e.keyCode == KONAMI_CODE[cursor]) ? cursor + 1 : 0;
|
cursor = (e.keyCode == KONAMI_CODE[cursor]) ? cursor + 1 : 0
|
||||||
if (cursor == KONAMI_CODE.length) {
|
if (cursor == KONAMI_CODE.length) {
|
||||||
afterKonami()
|
afterKonami()
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
@ -1,440 +1,422 @@
|
|||||||
var LOCK = false;
|
var LOCK = false
|
||||||
|
|
||||||
sources = [];
|
sources = []
|
||||||
sources_notes_display = [];
|
sources_notes_display = []
|
||||||
dests = [];
|
dests = []
|
||||||
dests_notes_display = [];
|
dests_notes_display = []
|
||||||
|
|
||||||
function refreshHistory() {
|
function refreshHistory () {
|
||||||
$("#history").load("/note/transfer/ #history");
|
$('#history').load('/note/transfer/ #history')
|
||||||
}
|
}
|
||||||
|
|
||||||
function reset(refresh=true) {
|
function reset (refresh = true) {
|
||||||
sources_notes_display.length = 0;
|
sources_notes_display.length = 0
|
||||||
sources.length = 0;
|
sources.length = 0
|
||||||
dests_notes_display.length = 0;
|
dests_notes_display.length = 0
|
||||||
dests.length = 0;
|
dests.length = 0
|
||||||
$("#source_note_list").html("");
|
$('#source_note_list').html('')
|
||||||
$("#dest_note_list").html("");
|
$('#dest_note_list').html('')
|
||||||
let source_field = $("#source_note");
|
const source_field = $('#source_note')
|
||||||
source_field.val("");
|
source_field.val('')
|
||||||
let event = jQuery.Event("keyup");
|
const event = jQuery.Event('keyup')
|
||||||
event.originalEvent = {charCode: 97};
|
event.originalEvent = { charCode: 97 }
|
||||||
source_field.trigger(event);
|
source_field.trigger(event)
|
||||||
source_field.removeClass('is-invalid');
|
source_field.removeClass('is-invalid')
|
||||||
source_field.attr("data-original-title", "").tooltip("hide");
|
source_field.attr('data-original-title', '').tooltip('hide')
|
||||||
let dest_field = $("#dest_note");
|
const dest_field = $('#dest_note')
|
||||||
dest_field.val("");
|
dest_field.val('')
|
||||||
dest_field.trigger(event);
|
dest_field.trigger(event)
|
||||||
dest_field.removeClass('is-invalid');
|
dest_field.removeClass('is-invalid')
|
||||||
dest_field.attr("data-original-title", "").tooltip("hide");
|
dest_field.attr('data-original-title', '').tooltip('hide')
|
||||||
let amount_field = $("#amount");
|
const amount_field = $('#amount')
|
||||||
amount_field.val("");
|
amount_field.val('')
|
||||||
amount_field.removeClass('is-invalid');
|
amount_field.removeClass('is-invalid')
|
||||||
$("#amount-required").html("");
|
$('#amount-required').html('')
|
||||||
let reason_field = $("#reason");
|
const reason_field = $('#reason')
|
||||||
reason_field.val("");
|
reason_field.val('')
|
||||||
reason_field.removeClass('is-invalid');
|
reason_field.removeClass('is-invalid')
|
||||||
$("#reason-required").html("");
|
$('#reason-required').html('')
|
||||||
$("#last_name").val("");
|
$('#last_name').val('')
|
||||||
$("#first_name").val("");
|
$('#first_name').val('')
|
||||||
$("#bank").val("");
|
$('#bank').val('')
|
||||||
$("#user_note").val("");
|
$('#user_note').val('')
|
||||||
$("#profile_pic").attr("src", "/static/member/img/default_picture.png");
|
$('#profile_pic').attr('src', '/static/member/img/default_picture.png')
|
||||||
$("#profile_pic_link").attr("href", "#");
|
$('#profile_pic_link').attr('href', '#')
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
refreshBalance();
|
refreshBalance()
|
||||||
refreshHistory();
|
refreshHistory()
|
||||||
}
|
}
|
||||||
|
|
||||||
LOCK = false;
|
LOCK = false
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function () {
|
||||||
/**
|
/**
|
||||||
* If we are in credit/debit mode, check that only one note is entered.
|
* If we are in credit/debit mode, check that only one note is entered.
|
||||||
* More over, get first name and last name to autocomplete fields.
|
* More over, get first name and last name to autocomplete fields.
|
||||||
*/
|
*/
|
||||||
function checkUniqueNote() {
|
function checkUniqueNote () {
|
||||||
if ($("#type_credit").is(":checked") || $("#type_debit").is(":checked")) {
|
if ($('#type_credit').is(':checked') || $('#type_debit').is(':checked')) {
|
||||||
let arr = $("#type_credit").is(":checked") ? dests_notes_display : sources_notes_display;
|
const arr = $('#type_credit').is(':checked') ? dests_notes_display : sources_notes_display
|
||||||
|
|
||||||
if (arr.length === 0)
|
if (arr.length === 0) { return }
|
||||||
return;
|
|
||||||
|
|
||||||
let last = arr[arr.length - 1];
|
const last = arr[arr.length - 1]
|
||||||
arr.length = 0;
|
arr.length = 0
|
||||||
arr.push(last);
|
arr.push(last)
|
||||||
|
|
||||||
last.quantity = 1;
|
last.quantity = 1
|
||||||
|
|
||||||
if (!last.note.user) {
|
if (!last.note.user) {
|
||||||
$.getJSON("/api/note/note/" + last.note.id + "/?format=json", function(note) {
|
$.getJSON('/api/note/note/' + last.note.id + '/?format=json', function (note) {
|
||||||
last.note.user = note.user;
|
last.note.user = note.user
|
||||||
$.getJSON("/api/user/" + last.note.user + "/", function(user) {
|
$.getJSON('/api/user/' + last.note.user + '/', function (user) {
|
||||||
$("#last_name").val(user.last_name);
|
$('#last_name').val(user.last_name)
|
||||||
$("#first_name").val(user.first_name);
|
$('#first_name').val(user.first_name)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
} else {
|
||||||
|
$.getJSON('/api/user/' + last.note.user + '/', function (user) {
|
||||||
|
$('#last_name').val(user.last_name)
|
||||||
|
$('#first_name').val(user.first_name)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
autoCompleteNote('source_note', 'source_note_list', sources, sources_notes_display,
|
||||||
|
'source_alias', 'source_note', 'user_note', 'profile_pic', checkUniqueNote)
|
||||||
|
autoCompleteNote('dest_note', 'dest_note_list', dests, dests_notes_display,
|
||||||
|
'dest_alias', 'dest_note', 'user_note', 'profile_pic', checkUniqueNote)
|
||||||
|
|
||||||
|
const source = $('#source_note')
|
||||||
|
const dest = $('#dest_note')
|
||||||
|
|
||||||
|
$('#type_transfer').change(function () {
|
||||||
|
if (LOCK) { return }
|
||||||
|
|
||||||
|
$('#source_me_div').removeClass('d-none')
|
||||||
|
$('#source_note').removeClass('is-invalid')
|
||||||
|
$('#dest_note').removeClass('is-invalid')
|
||||||
|
$('#special_transaction_div').addClass('d-none')
|
||||||
|
source.removeClass('d-none')
|
||||||
|
$('#source_note_list').removeClass('d-none')
|
||||||
|
$('#credit_type').addClass('d-none')
|
||||||
|
dest.removeClass('d-none')
|
||||||
|
$('#dest_note_list').removeClass('d-none')
|
||||||
|
$('#debit_type').addClass('d-none')
|
||||||
|
|
||||||
|
$('#source_note_label').text(select_emitters_label)
|
||||||
|
$('#dest_note_label').text(select_receveirs_label)
|
||||||
|
|
||||||
|
location.hash = 'transfer'
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#type_credit').change(function () {
|
||||||
|
if (LOCK) { return }
|
||||||
|
|
||||||
|
$('#source_me_div').addClass('d-none')
|
||||||
|
$('#source_note').removeClass('is-invalid')
|
||||||
|
$('#dest_note').removeClass('is-invalid')
|
||||||
|
$('#special_transaction_div').removeClass('d-none')
|
||||||
|
$('#source_note_list').addClass('d-none')
|
||||||
|
$('#dest_note_list').removeClass('d-none')
|
||||||
|
source.addClass('d-none')
|
||||||
|
source.tooltip('hide')
|
||||||
|
$('#credit_type').removeClass('d-none')
|
||||||
|
dest.removeClass('d-none')
|
||||||
|
dest.val('')
|
||||||
|
dest.tooltip('hide')
|
||||||
|
$('#debit_type').addClass('d-none')
|
||||||
|
|
||||||
|
$('#source_note_label').text(transfer_type_label)
|
||||||
|
$('#dest_note_label').text(select_receveir_label)
|
||||||
|
|
||||||
|
if (dests_notes_display.length > 1) {
|
||||||
|
$('#dest_note_list').html('')
|
||||||
|
dests_notes_display.length = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
location.hash = 'credit'
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#type_debit').change(function () {
|
||||||
|
if (LOCK) { return }
|
||||||
|
|
||||||
|
$('#source_me_div').addClass('d-none')
|
||||||
|
$('#source_note').removeClass('is-invalid')
|
||||||
|
$('#dest_note').removeClass('is-invalid')
|
||||||
|
$('#special_transaction_div').removeClass('d-none')
|
||||||
|
$('#source_note_list').removeClass('d-none')
|
||||||
|
$('#dest_note_list').addClass('d-none')
|
||||||
|
source.removeClass('d-none')
|
||||||
|
source.val('')
|
||||||
|
source.tooltip('hide')
|
||||||
|
$('#credit_type').addClass('d-none')
|
||||||
|
dest.addClass('d-none')
|
||||||
|
dest.tooltip('hide')
|
||||||
|
$('#debit_type').removeClass('d-none')
|
||||||
|
|
||||||
|
$('#source_note_label').text(select_emitter_label)
|
||||||
|
$('#dest_note_label').text(transfer_type_label)
|
||||||
|
|
||||||
|
if (sources_notes_display.length > 1) {
|
||||||
|
$('#source_note_list').html('')
|
||||||
|
sources_notes_display.length = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
location.hash = 'debit'
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#credit_type').change(function () {
|
||||||
|
const type = $('#credit_type option:selected').text()
|
||||||
|
if ($('#type_credit').is(':checked')) { source.val(type) } else { dest.val(type) }
|
||||||
|
})
|
||||||
|
|
||||||
|
// Ensure we begin in transfer mode. Removing these lines may cause problems when reloading.
|
||||||
|
const type_transfer = $('#type_transfer') // Default mode
|
||||||
|
type_transfer.removeAttr('checked')
|
||||||
|
$('#type_credit').removeAttr('checked')
|
||||||
|
$('#type_debit').removeAttr('checked')
|
||||||
|
|
||||||
|
if (location.hash) { $('#type_' + location.hash.substr(1)).click() } else { type_transfer.click() }
|
||||||
|
|
||||||
|
$('#source_me').click(function () {
|
||||||
|
if (LOCK) { return }
|
||||||
|
|
||||||
|
// Shortcut to set the current user as the only emitter
|
||||||
|
sources_notes_display.length = 0
|
||||||
|
sources.length = 0
|
||||||
|
$('#source_note_list').html('')
|
||||||
|
|
||||||
|
const source_note = $('#source_note')
|
||||||
|
source_note.focus()
|
||||||
|
source_note.val('')
|
||||||
|
let event = jQuery.Event('keyup')
|
||||||
|
event.originalEvent = { charCode: 97 }
|
||||||
|
source_note.trigger(event)
|
||||||
|
source_note.val(username)
|
||||||
|
event = jQuery.Event('keyup')
|
||||||
|
event.originalEvent = { charCode: 97 }
|
||||||
|
source_note.trigger(event)
|
||||||
|
const fill_note = function () {
|
||||||
|
if (sources.length === 0) {
|
||||||
|
setTimeout(fill_note, 100)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
event = jQuery.Event('keypress')
|
||||||
|
event.originalEvent = { charCode: 13 }
|
||||||
|
source_note.trigger(event)
|
||||||
|
|
||||||
|
source_note.tooltip('hide')
|
||||||
|
source_note.val('')
|
||||||
|
$('#dest_note').focus()
|
||||||
|
}
|
||||||
|
fill_note()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
$('#btn_transfer').click(function () {
|
||||||
|
if (LOCK) { return }
|
||||||
|
|
||||||
|
LOCK = true
|
||||||
|
|
||||||
|
let error = false
|
||||||
|
|
||||||
|
const amount_field = $('#amount')
|
||||||
|
amount_field.removeClass('is-invalid')
|
||||||
|
$('#amount-required').html('')
|
||||||
|
|
||||||
|
const reason_field = $('#reason')
|
||||||
|
reason_field.removeClass('is-invalid')
|
||||||
|
$('#reason-required').html('')
|
||||||
|
|
||||||
|
if (!amount_field.val() || isNaN(amount_field.val()) || amount_field.val() <= 0) {
|
||||||
|
amount_field.addClass('is-invalid')
|
||||||
|
$('#amount-required').html('<strong>Ce champ est requis et doit comporter un nombre décimal strictement positif.</strong>')
|
||||||
|
error = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const amount = Math.floor(100 * amount_field.val())
|
||||||
|
if (amount > 2147483647) {
|
||||||
|
amount_field.addClass('is-invalid')
|
||||||
|
$('#amount-required').html('<strong>Le montant ne doit pas excéder 21474836.47 €.</strong>')
|
||||||
|
error = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!reason_field.val()) {
|
||||||
|
reason_field.addClass('is-invalid')
|
||||||
|
$('#reason-required').html('<strong>Ce champ est requis.</strong>')
|
||||||
|
error = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sources_notes_display.length && !$('#type_credit').is(':checked')) {
|
||||||
|
$('#source_note').addClass('is-invalid')
|
||||||
|
error = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dests_notes_display.length && !$('#type_debit').is(':checked')) {
|
||||||
|
$('#dest_note').addClass('is-invalid')
|
||||||
|
error = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
LOCK = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let reason = reason_field.val()
|
||||||
|
|
||||||
|
if ($('#type_transfer').is(':checked')) {
|
||||||
|
// We copy the arrays to ensure that transactions are well-processed even if the form is reset
|
||||||
|
[...sources_notes_display].forEach(function (source) {
|
||||||
|
[...dests_notes_display].forEach(function (dest) {
|
||||||
|
if (source.note.id === dest.note.id) {
|
||||||
|
addMsg('Attention : la transaction de ' + pretty_money(amount) + ' de la note ' + source.name +
|
||||||
|
' vers la note ' + dest.name + " n'a pas été faite car il s'agit de la même note au départ" +
|
||||||
|
" et à l'arrivée.", 'warning', 10000)
|
||||||
|
LOCK = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$.post('/api/note/transaction/transaction/',
|
||||||
|
{
|
||||||
|
csrfmiddlewaretoken: CSRF_TOKEN,
|
||||||
|
quantity: source.quantity * dest.quantity,
|
||||||
|
amount: amount,
|
||||||
|
reason: reason,
|
||||||
|
valid: true,
|
||||||
|
polymorphic_ctype: TRANSFER_POLYMORPHIC_CTYPE,
|
||||||
|
resourcetype: 'Transaction',
|
||||||
|
source: source.note.id,
|
||||||
|
source_alias: source.name,
|
||||||
|
destination: dest.note.id,
|
||||||
|
destination_alias: dest.name
|
||||||
|
}).done(function () {
|
||||||
|
if (source.note.membership && source.note.membership.date_end < new Date().toISOString()) {
|
||||||
|
addMsg('Attention : la note émettrice ' + source.name + " n'est plus adhérente.",
|
||||||
|
'danger', 30000)
|
||||||
|
}
|
||||||
|
if (dest.note.membership && dest.note.membership.date_end < new Date().toISOString()) {
|
||||||
|
addMsg('Attention : la note destination ' + dest.name + " n'est plus adhérente.",
|
||||||
|
'danger', 30000)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isNaN(source.note.balance)) {
|
||||||
|
const newBalance = source.note.balance - source.quantity * dest.quantity * amount
|
||||||
|
if (newBalance <= -5000) {
|
||||||
|
addMsg('Le transfert de ' +
|
||||||
|
pretty_money(source.quantity * dest.quantity * amount) + ' de la note ' +
|
||||||
|
source.name + ' vers la note ' + dest.name + ' a été fait avec succès, ' +
|
||||||
|
'mais la note émettrice est en négatif sévère.', 'danger', 10000)
|
||||||
|
reset()
|
||||||
|
return
|
||||||
|
} else if (newBalance < 0) {
|
||||||
|
addMsg('Le transfert de ' +
|
||||||
|
pretty_money(source.quantity * dest.quantity * amount) + ' de la note ' +
|
||||||
|
source.name + ' vers la note ' + dest.name + ' a été fait avec succès, ' +
|
||||||
|
'mais la note émettrice est en négatif.', 'warning', 10000)
|
||||||
|
reset()
|
||||||
|
return
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
$.getJSON("/api/user/" + last.note.user + "/", function(user) {
|
addMsg('Le transfert de ' +
|
||||||
$("#last_name").val(user.last_name);
|
pretty_money(source.quantity * dest.quantity * amount) + ' de la note ' + source.name +
|
||||||
$("#first_name").val(user.first_name);
|
' vers la note ' + dest.name + ' a été fait avec succès !', 'success', 10000)
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
reset()
|
||||||
}
|
}).fail(function (err) { // do it again but valid = false
|
||||||
|
const errObj = JSON.parse(err.responseText)
|
||||||
|
if (errObj.non_field_errors) {
|
||||||
|
addMsg('Le transfert de ' +
|
||||||
|
pretty_money(source.quantity * dest.quantity * amount) + ' de la note ' + source.name +
|
||||||
|
' vers la note ' + dest.name + ' a échoué : ' + errObj.non_field_errors, 'danger')
|
||||||
|
LOCK = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
autoCompleteNote("source_note", "source_note_list", sources, sources_notes_display,
|
$.post('/api/note/transaction/transaction/',
|
||||||
"source_alias", "source_note", "user_note", "profile_pic", checkUniqueNote);
|
|
||||||
autoCompleteNote("dest_note", "dest_note_list", dests, dests_notes_display,
|
|
||||||
"dest_alias", "dest_note", "user_note", "profile_pic", checkUniqueNote);
|
|
||||||
|
|
||||||
let source = $("#source_note");
|
|
||||||
let dest = $("#dest_note");
|
|
||||||
|
|
||||||
$("#type_transfer").change(function() {
|
|
||||||
if (LOCK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
$("#source_me_div").removeClass('d-none');
|
|
||||||
$("#source_note").removeClass('is-invalid');
|
|
||||||
$("#dest_note").removeClass('is-invalid');
|
|
||||||
$("#special_transaction_div").addClass('d-none');
|
|
||||||
source.removeClass('d-none');
|
|
||||||
$("#source_note_list").removeClass('d-none');
|
|
||||||
$("#credit_type").addClass('d-none');
|
|
||||||
dest.removeClass('d-none');
|
|
||||||
$("#dest_note_list").removeClass('d-none');
|
|
||||||
$("#debit_type").addClass('d-none');
|
|
||||||
|
|
||||||
$("#source_note_label").text(select_emitters_label);
|
|
||||||
$("#dest_note_label").text(select_receveirs_label);
|
|
||||||
|
|
||||||
location.hash = "transfer";
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#type_credit").change(function() {
|
|
||||||
if (LOCK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
$("#source_me_div").addClass('d-none');
|
|
||||||
$("#source_note").removeClass('is-invalid');
|
|
||||||
$("#dest_note").removeClass('is-invalid');
|
|
||||||
$("#special_transaction_div").removeClass('d-none');
|
|
||||||
$("#source_note_list").addClass('d-none');
|
|
||||||
$("#dest_note_list").removeClass('d-none');
|
|
||||||
source.addClass('d-none');
|
|
||||||
source.tooltip('hide');
|
|
||||||
$("#credit_type").removeClass('d-none');
|
|
||||||
dest.removeClass('d-none');
|
|
||||||
dest.val('');
|
|
||||||
dest.tooltip('hide');
|
|
||||||
$("#debit_type").addClass('d-none');
|
|
||||||
|
|
||||||
$("#source_note_label").text(transfer_type_label);
|
|
||||||
$("#dest_note_label").text(select_receveir_label);
|
|
||||||
|
|
||||||
if (dests_notes_display.length > 1) {
|
|
||||||
$("#dest_note_list").html('');
|
|
||||||
dests_notes_display.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
location.hash = "credit";
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#type_debit").change(function() {
|
|
||||||
if (LOCK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
$("#source_me_div").addClass('d-none');
|
|
||||||
$("#source_note").removeClass('is-invalid');
|
|
||||||
$("#dest_note").removeClass('is-invalid');
|
|
||||||
$("#special_transaction_div").removeClass('d-none');
|
|
||||||
$("#source_note_list").removeClass('d-none');
|
|
||||||
$("#dest_note_list").addClass('d-none');
|
|
||||||
source.removeClass('d-none');
|
|
||||||
source.val('');
|
|
||||||
source.tooltip('hide');
|
|
||||||
$("#credit_type").addClass('d-none');
|
|
||||||
dest.addClass('d-none');
|
|
||||||
dest.tooltip('hide');
|
|
||||||
$("#debit_type").removeClass('d-none');
|
|
||||||
|
|
||||||
$("#source_note_label").text(select_emitter_label);
|
|
||||||
$("#dest_note_label").text(transfer_type_label);
|
|
||||||
|
|
||||||
if (sources_notes_display.length > 1) {
|
|
||||||
$("#source_note_list").html('');
|
|
||||||
sources_notes_display.length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
location.hash = "debit";
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#credit_type").change(function() {
|
|
||||||
let type = $("#credit_type option:selected").text();
|
|
||||||
if ($("#type_credit").is(":checked"))
|
|
||||||
source.val(type);
|
|
||||||
else
|
|
||||||
dest.val(type);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Ensure we begin in transfer mode. Removing these lines may cause problems when reloading.
|
|
||||||
let type_transfer = $("#type_transfer"); // Default mode
|
|
||||||
type_transfer.removeAttr('checked');
|
|
||||||
$("#type_credit").removeAttr('checked');
|
|
||||||
$("#type_debit").removeAttr('checked');
|
|
||||||
|
|
||||||
if (location.hash)
|
|
||||||
$("#type_" + location.hash.substr(1)).click();
|
|
||||||
else
|
|
||||||
type_transfer.click();
|
|
||||||
|
|
||||||
$("#source_me").click(function() {
|
|
||||||
if (LOCK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Shortcut to set the current user as the only emitter
|
|
||||||
sources_notes_display.length = 0;
|
|
||||||
sources.length = 0;
|
|
||||||
$("#source_note_list").html("");
|
|
||||||
|
|
||||||
let source_note = $("#source_note");
|
|
||||||
source_note.focus();
|
|
||||||
source_note.val("");
|
|
||||||
let event = jQuery.Event("keyup");
|
|
||||||
event.originalEvent = {charCode: 97};
|
|
||||||
source_note.trigger(event);
|
|
||||||
source_note.val(username);
|
|
||||||
event = jQuery.Event("keyup");
|
|
||||||
event.originalEvent = {charCode: 97};
|
|
||||||
source_note.trigger(event);
|
|
||||||
let fill_note = function() {
|
|
||||||
if (sources.length === 0) {
|
|
||||||
setTimeout(fill_note, 100);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
event = jQuery.Event("keypress");
|
|
||||||
event.originalEvent = {charCode: 13};
|
|
||||||
source_note.trigger(event);
|
|
||||||
|
|
||||||
source_note.tooltip('hide');
|
|
||||||
source_note.val('');
|
|
||||||
$("#dest_note").focus();
|
|
||||||
};
|
|
||||||
fill_note();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#btn_transfer").click(function() {
|
|
||||||
if (LOCK)
|
|
||||||
return;
|
|
||||||
|
|
||||||
LOCK = true;
|
|
||||||
|
|
||||||
let error = false;
|
|
||||||
|
|
||||||
let amount_field = $("#amount");
|
|
||||||
amount_field.removeClass('is-invalid');
|
|
||||||
$("#amount-required").html("");
|
|
||||||
|
|
||||||
let reason_field = $("#reason");
|
|
||||||
reason_field.removeClass('is-invalid');
|
|
||||||
$("#reason-required").html("");
|
|
||||||
|
|
||||||
if (!amount_field.val() || isNaN(amount_field.val()) || amount_field.val() <= 0) {
|
|
||||||
amount_field.addClass('is-invalid');
|
|
||||||
$("#amount-required").html("<strong>Ce champ est requis et doit comporter un nombre décimal strictement positif.</strong>");
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let amount = Math.floor(100 * amount_field.val());
|
|
||||||
if (amount > 2147483647) {
|
|
||||||
amount_field.addClass('is-invalid');
|
|
||||||
$("#amount-required").html("<strong>Le montant ne doit pas excéder 21474836.47 €.</strong>");
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!reason_field.val()) {
|
|
||||||
reason_field.addClass('is-invalid');
|
|
||||||
$("#reason-required").html("<strong>Ce champ est requis.</strong>");
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sources_notes_display.length && !$("#type_credit").is(':checked')) {
|
|
||||||
$("#source_note").addClass('is-invalid');
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!dests_notes_display.length && !$("#type_debit").is(':checked')) {
|
|
||||||
$("#dest_note").addClass('is-invalid');
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
LOCK = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let reason = reason_field.val();
|
|
||||||
|
|
||||||
if ($("#type_transfer").is(':checked')) {
|
|
||||||
// We copy the arrays to ensure that transactions are well-processed even if the form is reset
|
|
||||||
[...sources_notes_display].forEach(function (source) {
|
|
||||||
[...dests_notes_display].forEach(function (dest) {
|
|
||||||
if (source.note.id === dest.note.id) {
|
|
||||||
addMsg("Attention : la transaction de " + pretty_money(amount) + " de la note " + source.name
|
|
||||||
+ " vers la note " + dest.name + " n'a pas été faite car il s'agit de la même note au départ" +
|
|
||||||
" et à l'arrivée.","warning", 10000);
|
|
||||||
LOCK = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.post("/api/note/transaction/transaction/",
|
|
||||||
{
|
|
||||||
"csrfmiddlewaretoken": CSRF_TOKEN,
|
|
||||||
"quantity": source.quantity * dest.quantity,
|
|
||||||
"amount": amount,
|
|
||||||
"reason": reason,
|
|
||||||
"valid": true,
|
|
||||||
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
|
|
||||||
"resourcetype": "Transaction",
|
|
||||||
"source": source.note.id,
|
|
||||||
"source_alias": source.name,
|
|
||||||
"destination": dest.note.id,
|
|
||||||
"destination_alias": dest.name
|
|
||||||
}).done(function () {
|
|
||||||
if (source.note.membership && source.note.membership.date_end < new Date().toISOString())
|
|
||||||
addMsg("Attention : la note émettrice " + source.name + " n'est plus adhérente.",
|
|
||||||
"danger", 30000);
|
|
||||||
if (dest.note.membership && dest.note.membership.date_end < new Date().toISOString())
|
|
||||||
addMsg("Attention : la note destination " + dest.name + " n'est plus adhérente.",
|
|
||||||
"danger", 30000);
|
|
||||||
|
|
||||||
if (!isNaN(source.note.balance)) {
|
|
||||||
let newBalance = source.note.balance - source.quantity * dest.quantity * amount;
|
|
||||||
if (newBalance <= -5000) {
|
|
||||||
addMsg("Le transfert de "
|
|
||||||
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note "
|
|
||||||
+ source.name + " vers la note " + dest.name + " a été fait avec succès, " +
|
|
||||||
"mais la note émettrice est en négatif sévère.", "danger", 10000);
|
|
||||||
reset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (newBalance < 0) {
|
|
||||||
addMsg("Le transfert de "
|
|
||||||
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note "
|
|
||||||
+ source.name + " vers la note " + dest.name + " a été fait avec succès, " +
|
|
||||||
"mais la note émettrice est en négatif.", "warning", 10000);
|
|
||||||
reset();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
addMsg("Le transfert de "
|
|
||||||
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name
|
|
||||||
+ " vers la note " + dest.name + " a été fait avec succès !", "success", 10000);
|
|
||||||
|
|
||||||
reset();
|
|
||||||
}).fail(function (err) { // do it again but valid = false
|
|
||||||
let errObj = JSON.parse(err.responseText);
|
|
||||||
if (errObj["non_field_errors"]) {
|
|
||||||
addMsg("Le transfert de "
|
|
||||||
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name
|
|
||||||
+ " vers la note " + dest.name + " a échoué : " + errObj["non_field_errors"], "danger");
|
|
||||||
LOCK = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$.post("/api/note/transaction/transaction/",
|
|
||||||
{
|
|
||||||
"csrfmiddlewaretoken": CSRF_TOKEN,
|
|
||||||
"quantity": source.quantity * dest.quantity,
|
|
||||||
"amount": amount,
|
|
||||||
"reason": reason,
|
|
||||||
"valid": false,
|
|
||||||
"invalidity_reason": "Solde insuffisant",
|
|
||||||
"polymorphic_ctype": TRANSFER_POLYMORPHIC_CTYPE,
|
|
||||||
"resourcetype": "Transaction",
|
|
||||||
"source": source.note.id,
|
|
||||||
"source_alias": source.name,
|
|
||||||
"destination": dest.note.id,
|
|
||||||
"destination_alias": dest.name
|
|
||||||
}).done(function () {
|
|
||||||
addMsg("Le transfert de "
|
|
||||||
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name
|
|
||||||
+ " vers la note " + dest.name + " a échoué : Solde insuffisant", "danger", 10000);
|
|
||||||
reset();
|
|
||||||
}).fail(function (err) {
|
|
||||||
let errObj = JSON.parse(err.responseText);
|
|
||||||
let error = errObj["detail"] ? errObj["detail"] : errObj["non_field_errors"]
|
|
||||||
if (!error)
|
|
||||||
error = err.responseText;
|
|
||||||
addMsg("Le transfert de "
|
|
||||||
+ pretty_money(source.quantity * dest.quantity * amount) + " de la note " + source.name
|
|
||||||
+ " vers la note " + dest.name + " a échoué : " + error, "danger");
|
|
||||||
LOCK = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else if ($("#type_credit").is(':checked') || $("#type_debit").is(':checked')) {
|
|
||||||
let special_note;
|
|
||||||
let user_note;
|
|
||||||
let alias;
|
|
||||||
let given_reason = reason;
|
|
||||||
let source_id, dest_id;
|
|
||||||
if ($("#type_credit").is(':checked')) {
|
|
||||||
special_note = $("#credit_type").val();
|
|
||||||
user_note = dests_notes_display[0].note;
|
|
||||||
alias = dests_notes_display[0].name;
|
|
||||||
source_id = special_note;
|
|
||||||
dest_id = user_note.id;
|
|
||||||
reason = "Crédit " + $("#credit_type option:selected").text().toLowerCase();
|
|
||||||
if (given_reason.length > 0)
|
|
||||||
reason += " (" + given_reason + ")";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
special_note = $("#debit_type").val();
|
|
||||||
user_note = sources_notes_display[0].note;
|
|
||||||
alias = sources_notes_display[0].name;
|
|
||||||
source_id = user_note.id;
|
|
||||||
dest_id = special_note;
|
|
||||||
reason = "Retrait " + $("#credit_type option:selected").text().toLowerCase();
|
|
||||||
if (given_reason.length > 0)
|
|
||||||
reason += " (" + given_reason + ")";
|
|
||||||
}
|
|
||||||
$.post("/api/note/transaction/transaction/",
|
|
||||||
{
|
{
|
||||||
"csrfmiddlewaretoken": CSRF_TOKEN,
|
csrfmiddlewaretoken: CSRF_TOKEN,
|
||||||
"quantity": 1,
|
quantity: source.quantity * dest.quantity,
|
||||||
"amount": amount,
|
amount: amount,
|
||||||
"reason": reason,
|
reason: reason,
|
||||||
"valid": true,
|
valid: false,
|
||||||
"polymorphic_ctype": SPECIAL_TRANSFER_POLYMORPHIC_CTYPE,
|
invalidity_reason: 'Solde insuffisant',
|
||||||
"resourcetype": "SpecialTransaction",
|
polymorphic_ctype: TRANSFER_POLYMORPHIC_CTYPE,
|
||||||
"source": source_id,
|
resourcetype: 'Transaction',
|
||||||
"source_alias": sources_notes_display.length ? alias : null,
|
source: source.note.id,
|
||||||
"destination": dest_id,
|
source_alias: source.name,
|
||||||
"destination_alias": dests_notes_display.length ? alias : null,
|
destination: dest.note.id,
|
||||||
"last_name": $("#last_name").val(),
|
destination_alias: dest.name
|
||||||
"first_name": $("#first_name").val(),
|
|
||||||
"bank": $("#bank").val()
|
|
||||||
}).done(function () {
|
}).done(function () {
|
||||||
addMsg("Le crédit/retrait a bien été effectué !", "success", 10000);
|
addMsg('Le transfert de ' +
|
||||||
if (user_note.membership && user_note.membership.date_end < new Date().toISOString())
|
pretty_money(source.quantity * dest.quantity * amount) + ' de la note ' + source.name +
|
||||||
addMsg("Attention : la note " + alias + " n'est plus adhérente.", "danger", 10000);
|
' vers la note ' + dest.name + ' a échoué : Solde insuffisant', 'danger', 10000)
|
||||||
reset();
|
reset()
|
||||||
}).fail(function (err) {
|
}).fail(function (err) {
|
||||||
let errObj = JSON.parse(err.responseText);
|
const errObj = JSON.parse(err.responseText)
|
||||||
let error = errObj["detail"] ? errObj["detail"] : errObj["non_field_errors"]
|
let error = errObj.detail ? errObj.detail : errObj.non_field_errors
|
||||||
if (!error)
|
if (!error) { error = err.responseText }
|
||||||
error = err.responseText;
|
addMsg('Le transfert de ' +
|
||||||
addMsg("Le crédit/retrait a échoué : " + error, "danger", 10000);
|
pretty_money(source.quantity * dest.quantity * amount) + ' de la note ' + source.name +
|
||||||
LOCK = false;
|
' vers la note ' + dest.name + ' a échoué : ' + error, 'danger')
|
||||||
});
|
LOCK = false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} else if ($('#type_credit').is(':checked') || $('#type_debit').is(':checked')) {
|
||||||
|
let special_note
|
||||||
|
let user_note
|
||||||
|
let alias
|
||||||
|
const given_reason = reason
|
||||||
|
let source_id, dest_id
|
||||||
|
if ($('#type_credit').is(':checked')) {
|
||||||
|
special_note = $('#credit_type').val()
|
||||||
|
user_note = dests_notes_display[0].note
|
||||||
|
alias = dests_notes_display[0].name
|
||||||
|
source_id = special_note
|
||||||
|
dest_id = user_note.id
|
||||||
|
reason = 'Crédit ' + $('#credit_type option:selected').text().toLowerCase()
|
||||||
|
if (given_reason.length > 0) { reason += ' (' + given_reason + ')' }
|
||||||
|
} else {
|
||||||
|
special_note = $('#debit_type').val()
|
||||||
|
user_note = sources_notes_display[0].note
|
||||||
|
alias = sources_notes_display[0].name
|
||||||
|
source_id = user_note.id
|
||||||
|
dest_id = special_note
|
||||||
|
reason = 'Retrait ' + $('#credit_type option:selected').text().toLowerCase()
|
||||||
|
if (given_reason.length > 0) { reason += ' (' + given_reason + ')' }
|
||||||
}
|
}
|
||||||
});
|
$.post('/api/note/transaction/transaction/',
|
||||||
|
{
|
||||||
|
csrfmiddlewaretoken: CSRF_TOKEN,
|
||||||
|
quantity: 1,
|
||||||
|
amount: amount,
|
||||||
|
reason: reason,
|
||||||
|
valid: true,
|
||||||
|
polymorphic_ctype: SPECIAL_TRANSFER_POLYMORPHIC_CTYPE,
|
||||||
|
resourcetype: 'SpecialTransaction',
|
||||||
|
source: source_id,
|
||||||
|
source_alias: sources_notes_display.length ? alias : null,
|
||||||
|
destination: dest_id,
|
||||||
|
destination_alias: dests_notes_display.length ? alias : null,
|
||||||
|
last_name: $('#last_name').val(),
|
||||||
|
first_name: $('#first_name').val(),
|
||||||
|
bank: $('#bank').val()
|
||||||
|
}).done(function () {
|
||||||
|
addMsg('Le crédit/retrait a bien été effectué !', 'success', 10000)
|
||||||
|
if (user_note.membership && user_note.membership.date_end < new Date().toISOString()) { addMsg('Attention : la note ' + alias + " n'est plus adhérente.", 'danger', 10000) }
|
||||||
|
reset()
|
||||||
|
}).fail(function (err) {
|
||||||
|
const errObj = JSON.parse(err.responseText)
|
||||||
|
let error = errObj.detail ? errObj.detail : errObj.non_field_errors
|
||||||
|
if (!error) { error = err.responseText }
|
||||||
|
addMsg('Le crédit/retrait a échoué : ' + error, 'danger', 10000)
|
||||||
|
LOCK = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user