mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-07-19 23:51:25 +02:00
JS for manage page
This commit is contained in:
@ -8,8 +8,7 @@ var LOCK = false
|
||||
* Refresh the history table on the consumptions page.
|
||||
*/
|
||||
function refreshHistory () {
|
||||
$('#history').load('/note/consos/ #history')
|
||||
$('#most_used').load('/note/consos/ #most_used')
|
||||
$('#history').load('/family/manage/ #history')
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
@ -38,18 +37,14 @@ notes_display = []
|
||||
buttons = []
|
||||
|
||||
// When the user searches an alias, we update the auto-completion
|
||||
autoCompleteNote('note', 'note_list', notes, notes_display,
|
||||
'alias', 'note', 'user_note', 'profile_pic', function () {
|
||||
if (buttons.length > 0 && $('#single_conso').is(':checked')) {
|
||||
consumeAll()
|
||||
return false
|
||||
}
|
||||
autoCompleteFamily('note', 'note_list', notes, notes_display,
|
||||
'note', 'user_note', 'profile_pic', function () {
|
||||
return true
|
||||
})
|
||||
|
||||
/**
|
||||
* Add a transaction from a button.
|
||||
* @param dest Where the money goes
|
||||
* @param fam Where the money goes
|
||||
* @param amount The price of the item
|
||||
* @param type The type of the transaction (content type id for RecurrentTransaction)
|
||||
* @param category_id The category identifier
|
||||
@ -57,35 +52,32 @@ autoCompleteNote('note', 'note_list', notes, notes_display,
|
||||
* @param template_id The identifier of the button
|
||||
* @param template_name The name of the button
|
||||
*/
|
||||
function addConso (dest, amount, type, category_id, category_name, template_id, template_name) {
|
||||
var button = null
|
||||
function addChallenge (id, name, amount) {
|
||||
var challenge = null
|
||||
/** Ajout de 1 à chaque clic d'un bouton déjà choisi */
|
||||
buttons.forEach(function (b) {
|
||||
if (b.id === template_id) {
|
||||
if (b.id === id) {
|
||||
b.quantity += 1
|
||||
button = b
|
||||
challenge = b
|
||||
}
|
||||
})
|
||||
if (button == null) {
|
||||
button = {
|
||||
id: template_id,
|
||||
name: template_name,
|
||||
dest: dest,
|
||||
if (challenge == null) {
|
||||
challenge = {
|
||||
id: id,
|
||||
name: name,
|
||||
quantity: 1,
|
||||
amount: amount,
|
||||
type: type,
|
||||
category_id: category_id,
|
||||
category_name: category_name
|
||||
}
|
||||
buttons.push(button)
|
||||
buttons.push(challenge)
|
||||
}
|
||||
|
||||
const dc_obj = $('#double_conso')
|
||||
if (dc_obj.is(':checked') || notes_display.length === 0) {
|
||||
const list = dc_obj.is(':checked') ? 'consos_list' : 'note_list'
|
||||
const dc_obj = true
|
||||
|
||||
const list = 'consos_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>')
|
||||
buttons.forEach(function (challenge) {
|
||||
html += li('conso_button_' + challenge.id, challenge.name +
|
||||
'<span class="badge badge-dark badge-pill">' + challenge.quantity + '</span>')
|
||||
})
|
||||
document.getElementById(list).innerHTML = html
|
||||
|
||||
@ -95,13 +87,14 @@ function addConso (dest, amount, type, category_id, category_name, template_id,
|
||||
removeNote(button, 'conso_button', buttons, list)()
|
||||
})
|
||||
})
|
||||
} else { consumeAll() }
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the page as its initial state.
|
||||
*/
|
||||
function reset () {
|
||||
console.log("reset lancée")
|
||||
notes_display.length = 0
|
||||
notes.length = 0
|
||||
buttons.length = 0
|
||||
@ -113,7 +106,6 @@ function reset () {
|
||||
document.getElementById('profile_pic').src = '/static/member/img/default_picture.png'
|
||||
document.getElementById('profile_pic_link').href = '#'
|
||||
refreshHistory()
|
||||
refreshBalance()
|
||||
LOCK = false
|
||||
}
|
||||
|
||||
@ -121,6 +113,7 @@ function reset () {
|
||||
* Apply all transactions: all notes in `notes` buy each item in `buttons`
|
||||
*/
|
||||
function consumeAll () {
|
||||
console.log("consumeAll lancée")
|
||||
if (LOCK) { return }
|
||||
|
||||
LOCK = true
|
||||
@ -129,12 +122,12 @@ function consumeAll () {
|
||||
|
||||
if (notes_display.length === 0) {
|
||||
document.getElementById('note').classList.add('is-invalid')
|
||||
$('#note_list').html(li('', '<strong>Ajoutez des émetteurs.</strong>', 'text-danger'))
|
||||
$('#note_list').html(li('', '<strong>Ajoutez des familles.</strong>', 'text-danger'))
|
||||
error = true
|
||||
}
|
||||
|
||||
if (buttons.length === 0) {
|
||||
$('#consos_list').html(li('', '<strong>Ajoutez des consommations.</strong>', 'text-danger'))
|
||||
$('#consos_list').html(li('', '<strong>Ajoutez des défis.</strong>', 'text-danger'))
|
||||
error = true
|
||||
}
|
||||
|
||||
@ -143,79 +136,39 @@ function consumeAll () {
|
||||
return
|
||||
}
|
||||
|
||||
notes_display.forEach(function (note_display) {
|
||||
buttons.forEach(function (button) {
|
||||
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)
|
||||
notes_display.forEach(function (family) {
|
||||
buttons.forEach(function (challenge) {
|
||||
grantAchievement(family, challenge)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new transaction from a button through the API.
|
||||
* @param source The note that paid the item (type: note)
|
||||
* @param source_alias The alias used for the source (type: str)
|
||||
* @param dest The note that sold the item (type: int)
|
||||
* @param quantity The quantity sold (type: int)
|
||||
* @param amount The price of one item, in cents (type: int)
|
||||
* @param reason The transaction details (type: str)
|
||||
* @param type The type of the transaction (content type id for RecurrentTransaction)
|
||||
* @param category The category id of the button (type: int)
|
||||
* @param template The button id (type: int)
|
||||
* Create a new achievement through the API.
|
||||
* @param family The selected family
|
||||
* @param challenge The selected challenge
|
||||
*/
|
||||
function consume (source, source_alias, dest, quantity, amount, reason, type, category, template) {
|
||||
$.post('/api/note/transaction/transaction/',
|
||||
function grantAchievement (family, challenge) {
|
||||
console.log("grant lancée",family,challenge)
|
||||
$.post('/api/family/achievement/',
|
||||
{
|
||||
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
|
||||
family: family.id,
|
||||
challenge: challenge.id,
|
||||
})
|
||||
.done(function () {
|
||||
if (!isNaN(source.balance)) {
|
||||
const newBalance = source.balance - quantity * amount
|
||||
if (newBalance <= -2000) {
|
||||
addMsg(interpolate(gettext('Warning, the transaction from the note %s succeed, ' +
|
||||
'but the emitter note %s is very negative.'), [source_alias, source_alias]), 'danger', 30000)
|
||||
} else if (newBalance < 0) {
|
||||
addMsg(interpolate(gettext('Warning, the transaction from the note %s succeed, ' +
|
||||
'but the emitter note %s is negative.'), [source_alias, source_alias]), 'warning', 30000)
|
||||
}
|
||||
if (source.membership && source.membership.date_end < new Date().toISOString()) {
|
||||
addMsg(interpolate(gettext('Warning, the emitter note %s is no more a BDE member.'), [source_alias]),
|
||||
'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.id,
|
||||
source_alias: source_alias,
|
||||
destination: dest,
|
||||
template: template
|
||||
}).done(function () {
|
||||
reset()
|
||||
addMsg(gettext("The transaction couldn't be validated because of insufficient balance."), 'danger', 10000)
|
||||
}).fail(function () {
|
||||
reset()
|
||||
addMsg("Défi validé pour la famille !", 'success', 5000)
|
||||
})
|
||||
.fail(function (e) {
|
||||
reset()
|
||||
if (e.responseJSON) {
|
||||
errMsg(e.responseJSON)
|
||||
})
|
||||
} else if (e.responseText) {
|
||||
errMsg(e.responseText)
|
||||
} else {
|
||||
errMsg("Erreur inconnue lors de la création de l'achievement.")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@ -261,3 +214,222 @@ function createshiny() {
|
||||
shiny_class.replace('btn-outline-dark', 'btn-outline-dark-shiny')
|
||||
}
|
||||
createshiny()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Query the 20 first matched notes with a given pattern
|
||||
* @param pattern The pattern that is queried
|
||||
* @param fun For each found note with the matched alias `alias`, fun(note, alias) is called.
|
||||
*/
|
||||
function getMatchedFamilies (pattern, fun) {
|
||||
$.getJSON('/api/family/family/?format=json&alias=' + pattern + '&search=family', fun)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a <li> entry with a given id and text
|
||||
*/
|
||||
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 ' +
|
||||
(extra_css || '') + '"' + ' id="' + id + '">' + text + '</li>\n'
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Génère un champ d'auto-complétion pour rechercher une famille par son nom (version simplifiée sans alias)
|
||||
* @param field_id L'identifiant du champ texte où le nom est saisi
|
||||
* @param family_list_id L'identifiant du bloc div où les familles sélectionnées sont affichées
|
||||
* @param families Un tableau contenant les objets famille sélectionnés
|
||||
* @param families_display Un tableau contenant les infos des familles sélectionnées : [nom, id, objet famille, quantité]
|
||||
* @param family_prefix Le préfixe des <li> pour les familles sélectionnées
|
||||
* @param user_family_field L'identifiant du champ qui affiche la famille survolée (optionnel)
|
||||
* @param profile_pic_field L'identifiant du champ qui affiche la photo de la famille survolée (optionnel)
|
||||
* @param family_click Fonction appelée lors du clic sur un nom. Si elle existe et ne retourne pas true, la famille n'est pas affichée.
|
||||
*/
|
||||
function autoCompleteFamily(field_id, family_list_id, families, families_display, family_prefix = 'family', user_family_field = null, profile_pic_field = null, family_click = null) {
|
||||
const field = $('#' + field_id)
|
||||
console.log("autoCompleteFamily commence")
|
||||
// Configuration du tooltip
|
||||
field.tooltip({
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
title: 'Chargement...',
|
||||
trigger: 'manual',
|
||||
container: field.parent(),
|
||||
fallbackPlacement: 'clockwise'
|
||||
})
|
||||
|
||||
// Masquer le tooltip lors d'un clic ailleurs
|
||||
$(document).click(function (e) {
|
||||
if (!e.target.id.startsWith(family_prefix)) {
|
||||
field.tooltip('hide')
|
||||
}
|
||||
})
|
||||
|
||||
let old_pattern = null
|
||||
|
||||
// Réinitialiser la recherche au clic
|
||||
field.click(function () {
|
||||
field.tooltip('hide')
|
||||
field.removeClass('is-invalid')
|
||||
field.val('')
|
||||
old_pattern = ''
|
||||
})
|
||||
|
||||
// Sur "Entrée", sélectionner la première famille
|
||||
field.keypress(function (event) {
|
||||
if (event.originalEvent.charCode === 13 && families.length > 0) {
|
||||
const li_obj = field.parent().find('ul li').first()
|
||||
displayFamily(families[0], families[0].name, user_family_field, profile_pic_field)
|
||||
li_obj.trigger('click')
|
||||
}
|
||||
})
|
||||
|
||||
// Mise à jour des suggestions lors de la saisie
|
||||
field.keyup(function (e) {
|
||||
field.removeClass('is-invalid')
|
||||
|
||||
if (e.originalEvent.charCode === 13) { return }
|
||||
|
||||
const pattern = field.val()
|
||||
|
||||
if (pattern === old_pattern) { return }
|
||||
old_pattern = pattern
|
||||
families.length = 0
|
||||
|
||||
if (pattern === '') {
|
||||
field.tooltip('hide')
|
||||
families.length = 0
|
||||
return
|
||||
}
|
||||
|
||||
// Appel à l'API pour récupérer les familles correspondantes
|
||||
$.getJSON('/api/family/family/?format=json&search=' + pattern,
|
||||
function (results) {
|
||||
if (pattern !== $('#' + field_id).val()) { return }
|
||||
|
||||
let matched_html = '<ul class="list-group list-group-flush">'
|
||||
results.results.forEach(function (family) {
|
||||
matched_html += li(family_prefix + '_' + family.id,
|
||||
family.name,
|
||||
'')
|
||||
families.push(family)
|
||||
})
|
||||
matched_html += '</ul>'
|
||||
|
||||
field.attr('data-original-title', matched_html).tooltip('show')
|
||||
|
||||
results.results.forEach(function (family) {
|
||||
const family_obj = $('#' + family_prefix + '_' + family.id)
|
||||
family_obj.hover(function () {
|
||||
displayFamily(family, family.name, user_family_field, profile_pic_field)
|
||||
})
|
||||
family_obj.click(function () {
|
||||
var disp = null
|
||||
families_display.forEach(function (d) {
|
||||
if (d.id === family.id) {
|
||||
d.quantity += 1
|
||||
disp = d
|
||||
}
|
||||
})
|
||||
if (disp == null) {
|
||||
disp = {
|
||||
name: family.name,
|
||||
id: family.id,
|
||||
family: family,
|
||||
quantity: 1
|
||||
}
|
||||
families_display.push(disp)
|
||||
}
|
||||
|
||||
if (family_click && !family_click()) { return }
|
||||
|
||||
const family_list = $('#' + family_list_id)
|
||||
let html = ''
|
||||
families_display.forEach(function (disp) {
|
||||
html += li(family_prefix + '_' + disp.id,
|
||||
disp.name +
|
||||
'<span class="badge badge-dark badge-pill">' +
|
||||
disp.quantity + '</span>',
|
||||
'')
|
||||
})
|
||||
|
||||
family_list.html(html)
|
||||
field.tooltip('update')
|
||||
|
||||
families_display.forEach(function (disp) {
|
||||
const line_obj = $('#' + family_prefix + '_' + disp.id)
|
||||
line_obj.hover(function () {
|
||||
displayFamily(disp.family, disp.name, user_family_field, profile_pic_field)
|
||||
})
|
||||
line_obj.click(removeFamily(disp, family_prefix, families_display, family_list_id, user_family_field,
|
||||
profile_pic_field))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Affiche le nom et la photo d'une famille
|
||||
* @param family L'objet famille à afficher
|
||||
* @param user_family_field L'identifiant du champ où afficher le nom (optionnel)
|
||||
* @param profile_pic_field L'identifiant du champ où afficher la photo (optionnel)
|
||||
*/
|
||||
function displayFamily(family, user_family_field = null, profile_pic_field = null) {
|
||||
if (!family.display_image) {
|
||||
family.display_image = '/static/member/img/default_picture.png'
|
||||
}
|
||||
if (user_family_field !== null) {
|
||||
$('#' + user_family_field).removeAttr('class')
|
||||
$('#' + user_family_field).text(family.name)
|
||||
if (profile_pic_field != null) {
|
||||
$('#' + profile_pic_field).attr('src', family.display_image)
|
||||
// Si tu veux un lien vers la page famille :
|
||||
$('#' + profile_pic_field + '_link').attr('href', '/family/detail/' + family.id + '/')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retire une famille de la liste sélectionnée.
|
||||
* @param d La famille à retirer
|
||||
* @param family_prefix Le préfixe des <li>
|
||||
* @param families_display Le tableau des familles sélectionnées
|
||||
* @param family_list_id L'id du bloc où sont affichées les familles
|
||||
* @param user_family_field Champ d'affichage (optionnel)
|
||||
* @param profile_pic_field Champ photo (optionnel)
|
||||
* @returns une fonction compatible avec les événements jQuery
|
||||
*/
|
||||
function removeFamily(d, family_prefix, families_display, family_list_id, user_family_field = null, profile_pic_field = null) {
|
||||
return function () {
|
||||
const new_families_display = []
|
||||
let html = ''
|
||||
families_display.forEach(function (disp) {
|
||||
if (disp.quantity > 1 || disp.id !== d.id) {
|
||||
disp.quantity -= disp.id === d.id ? 1 : 0
|
||||
new_families_display.push(disp)
|
||||
html += li(family_prefix + '_' + disp.id, disp.name +
|
||||
'<span class="badge badge-dark badge-pill">' + disp.quantity + '</span>')
|
||||
}
|
||||
})
|
||||
|
||||
families_display.length = 0
|
||||
new_families_display.forEach(function (disp) {
|
||||
families_display.push(disp)
|
||||
})
|
||||
|
||||
$('#' + family_list_id).html(html)
|
||||
families_display.forEach(function (disp) {
|
||||
const obj = $('#' + family_prefix + '_' + disp.id)
|
||||
obj.click(removeFamily(disp, family_prefix, families_display, family_list_id, user_family_field, profile_pic_field))
|
||||
obj.hover(function () {
|
||||
displayFamily(disp.family, user_family_field, profile_pic_field)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
@ -9,180 +9,176 @@ SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-xl-12">
|
||||
<div class="btn-group btn-group-toggle" style="width: 100%; padding: 0 0 2em 0">
|
||||
<a href="{% url "family:family_list" %}" class="btn btn-sm btn-outline-primary">
|
||||
{% trans "Families" %}
|
||||
</a>
|
||||
<a href="{% url "family:challenge_list" %}" class="btn btn-sm btn-outline-primary">
|
||||
{% trans "Challenges" %}
|
||||
</a>
|
||||
<a href="#" class="btn btn-sm btn-outline-primary active">
|
||||
{% trans "Manage" %}
|
||||
</a>
|
||||
<div class="col-xl-12">
|
||||
<div class="btn-group btn-group-toggle" style="width: 100%; padding: 0 0 2em 0">
|
||||
<a href="{% url "family:family_list" %}" class="btn btn-sm btn-outline-primary">
|
||||
{% trans "Families" %}
|
||||
</a>
|
||||
<a href="{% url "family:challenge_list" %}" class="btn btn-sm btn-outline-primary">
|
||||
{% trans "Challenges" %}
|
||||
</a>
|
||||
<a href="#" class="btn btn-sm btn-outline-primary active">
|
||||
{% trans "Manage" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-sm-5 col-xl-6" id="infos_div">
|
||||
<div class="row justify-content-center justify-content-md-end">
|
||||
{# User details column #}
|
||||
<div class="col picture-col">
|
||||
<div class="card bg-light mb-4 text-center">
|
||||
<a id="profile_pic_link" href="#">
|
||||
<img src="{% static "member/img/default_picture.png" %}" id="profile_pic" alt="" class="card-img-top d-none d-sm-block">
|
||||
</a>
|
||||
<div class="card-body text-center text-break p-2">
|
||||
<span id="user_note"><i class="small">{% trans "Please select a family" %}</i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='col-sm-5 col-xl-6' id="infos_div">
|
||||
<div class="row justify-content-center justify-content-md-end">
|
||||
{# Family details column #}
|
||||
<div class="col picture-col">
|
||||
<div class="card bg-light mb-4 text-center">
|
||||
<a id="profile_pic_link" href="#">
|
||||
<img src="{% static "member/img/default_picture.png" %}" id="profile_pic" alt="" class="card-img-top d-none d-sm-block">
|
||||
</a>
|
||||
<div class="card-body text-center text-break p-2">
|
||||
<span id="user_note"><i class="small">{% trans "Please select a family" %}</i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Family selection column #}
|
||||
<div class="col-xl" id="user_select_div">
|
||||
{# Family selection column #}
|
||||
<div class="col-xl" id="user_select_div">
|
||||
<div class="card bg-light border-success mb-4">
|
||||
<div class="card-header">
|
||||
<p class="card-text font-weight-bold">
|
||||
{% trans "Families" %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body p-0" style="min-height:125px;">
|
||||
<ul class="list-group list-group-flush" id="note_list"></ul>
|
||||
</div>
|
||||
{# User search with autocompletion #}
|
||||
<div class="card-footer">
|
||||
<input class="form-control mx-auto d-block" placeholder="{% trans "Name" %}" type="text" id="note" autofocus />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Summary of challenges and validate button #}
|
||||
<div class="col-xl-5" id="consos_list_div">
|
||||
<div class="card bg-light border-info mb-4">
|
||||
<div class="card-header">
|
||||
<p class="card-text font-weight-bold">
|
||||
{% trans "Challenges" %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body p-0" style="min-height:125px;">
|
||||
<ul class="list-group list-group-flush" id="consos_list"></ul>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
<span id="consume_all" class="btn btn-primary">
|
||||
{% trans "Validate!" %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Create family/challenge buttons #}
|
||||
<div class="card bg-light border-success mb-4">
|
||||
<div class="card-header">
|
||||
<p class="card-text font-weight-bold">
|
||||
{% trans "Families" %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body p-0" style="min-height:125px;">
|
||||
<ul class="list-group list-group-flush" id="note_list"></ul>
|
||||
</div>
|
||||
{# User search with autocompletion #}
|
||||
<div class="card-footer">
|
||||
<input class="form-control mx-auto d-block" placeholder="{% trans "Name" %}" type="text" id="note" autofocus />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Summary of challenges and validate button #}
|
||||
<div class="col-xl-5" id="consos_list_div">
|
||||
<div class="card bg-light border-info mb-4">
|
||||
<div class="card-header">
|
||||
<p class="card-text font-weight-bold">
|
||||
{% trans "Challenges" %}
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body p-0" style="min-height:125px;">
|
||||
<ul class="list-group list-group-flush" id="consos_list"></ul>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
<span id="consume_all" class="btn btn-primary">
|
||||
{% trans "Validate!" %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Create family/challenge buttons #}
|
||||
<div class="card bg-light border-success mb-4">
|
||||
<h3 class="card-header font-weight-bold text-center">
|
||||
{% trans "Create a family or challenge" %}
|
||||
</h3>
|
||||
<div class="card-body text-center">
|
||||
{% if can_add_family %}
|
||||
<a class="btn btn-sm btn-primary mx-2" href="{% url 'family:add_family' %}">
|
||||
{% trans "Add a family" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if can_add_challenge %}
|
||||
<a class="btn btn-sm btn-primary mx-2" href="{% url 'family:add_challenge' %}">
|
||||
{% trans "Add a challenge" %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Buttons column #}
|
||||
<div class="col">
|
||||
<div class="card bg-light border-primary text-center mb-4">
|
||||
{# Tabs for list and search #}
|
||||
<div class="card-header">
|
||||
<ul class="nav nav-tabs nav-fill card-header-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link font-weight-bold" data-toggle="tab" href="#list">
|
||||
{% trans "List" %}
|
||||
<h3 class="card-header font-weight-bold text-center">
|
||||
{% trans "Create a family or challenge" %}
|
||||
</h3>
|
||||
<div class="card-body text-center">
|
||||
{% if can_add_family %}
|
||||
<a class="btn btn-sm btn-primary mx-2" href="{% url "family:add_family" %}">
|
||||
{% trans "Add a family" %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link font-weight-bold" data-toggle="tab" href="#search">
|
||||
{% trans "Search" %}
|
||||
{% endif %}
|
||||
{% if can_add_challenge %}
|
||||
<a class="btn btn-sm btn-primary mx-2" href="{% url "family:add_challenge" %}">
|
||||
{% trans "Add a challenge" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{# Tabs content #}
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane" id="list">
|
||||
<div class="d-inline-flex flex-wrap justify-content-center">
|
||||
{% for challenge in all_challenges %}
|
||||
<button class="btn btn-outline-dark rounded-0 flex-fill"
|
||||
id="challenge{{ challenge.id }}" name="button" value="{{ challenge.name }}">
|
||||
{{ challenge.name }} ({{ challenge.points }} {% trans "points" %})
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="search">
|
||||
<input class="form-control mx-auto d-block mb-3" placeholder="{% trans "Search challenge..." %}" type="search" id="search-input"/>
|
||||
<div class="d-inline-flex flex-wrap justify-content-center" id="search-results">
|
||||
{% for challenge in all_challenges %}
|
||||
<button class="btn btn-outline-dark rounded-0 flex-fill" hidden
|
||||
id="search_challenge{{ challenge.id }}" name="button" value="{{ challenge.name }}">
|
||||
{{ challenge.name }} ({{ challenge.points }} {% trans "points" %})
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Buttons column #}
|
||||
<div class="col">
|
||||
<div class="card bg-light border-primary text-center mb-4">
|
||||
{# Tabs for list and search #}
|
||||
<div class="card-header">
|
||||
<ul class="nav nav-tabs nav-fill card-header-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link font-weight-bold" data-toggle="tab" href="#list">
|
||||
{% trans "List" %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link font-weight-bold" data-toggle="tab" href="#search">
|
||||
{% trans "Search" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{# Tabs content #}
|
||||
<div class="card-body">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane" id="list">
|
||||
<div class="d-inline-flex flex-wrap justify-content-center">
|
||||
{% for challenge in all_challenges %}
|
||||
<button class="btn btn-outline-dark rounded-0 flex-fill"
|
||||
id="challenge{{ challenge.id }}" name="button" value="{{ challenge.name }}">
|
||||
{{ challenge.name }} ({{ challenge.points }} {% trans "points" %})
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane" id="search">
|
||||
<input class="form-control mx-auto d-block mb-3" placeholder="{% trans "Search challenge..." %}" type="search" id="search-input"/>
|
||||
<div class="d-inline-flex flex-wrap justify-content-center" id="search-results">
|
||||
{% for challenge in all_challenges %}
|
||||
<button class="btn btn-outline-dark rounded-0 flex-fill" hidden
|
||||
id="search_challenge{{ challenge.id }}" name="button" value="{{ challenge.name }}">
|
||||
{{ challenge.name }} ({{ challenge.points }} {% trans "points" %})
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Mode switch #}
|
||||
<div class="card-footer border-primary">
|
||||
<a class="btn btn-sm btn-secondary float-left" href="{% url 'note:template_list' %}">
|
||||
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Mode switch #}
|
||||
<div class="card-footer border-primary">
|
||||
<a class="btn btn-sm btn-secondary float-left" href="{% url 'note:template_list' %}">
|
||||
<i class="fa fa-edit"></i> {% trans "Edit" %}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# transaction history #}
|
||||
<div class="card mb-4" id="history">
|
||||
<div class="card-header">
|
||||
<p class="card-text font-weight-bold">
|
||||
{% trans "Recent achievements history" %}
|
||||
</p>
|
||||
</div>
|
||||
{% render_table table %}
|
||||
</div>
|
||||
<div class="card mb-4" id="history">
|
||||
<div class="card-header">
|
||||
<p class="card-text font-weight-bold">
|
||||
{% trans "Recent achievements history" %}
|
||||
</p>
|
||||
</div>
|
||||
{% render_table table %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extrajavascript %}
|
||||
<script type="text/javascript" src="{% static "family/js/consos.js" %}"></script>
|
||||
<script type="text/javascript">
|
||||
{% for button in all_challenges %}
|
||||
document.getElementById("button{{ button.id }}").addEventListener("click", function() {
|
||||
addConso({{ button.destination_id }}, {{ button.amount }},
|
||||
{{ polymorphic_ctype }}, {{ button.category_id }}, "{{ button.category.name|escapejs }}",
|
||||
{{ button.id }}, "{{ button.name|escapejs }}");
|
||||
});
|
||||
{% endfor %}
|
||||
|
||||
{% for button in all_challenges %}
|
||||
{% if button.display %}
|
||||
document.getElementById("search_button{{ button.id }}").addEventListener("click", function() {
|
||||
addConso({{ button.destination_id }}, {{ button.amount }},
|
||||
{{ polymorphic_ctype }}, {{ button.category_id }}, "{{ button.category.name|escapejs }}",
|
||||
{{ button.id }}, "{{ button.name|escapejs }}");
|
||||
|
||||
{% block extrajavascript %}
|
||||
<script type="text/javascript" src="{% static "family/js/achievements.js" %}"></script>
|
||||
<script type="text/javascript">
|
||||
{% for challenge in all_challenges %}
|
||||
document.getElementById("challenge{{ challenge.id }}").addEventListener("click", function() {
|
||||
addChallenge({{ challenge.id}}, "{{ challenge.name|escapejs }}", {{ challenge.points }});
|
||||
});
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</script>
|
||||
{% endfor %}
|
||||
|
||||
{% for challenge in all_challenges %}
|
||||
document.getElementById("search_challenge{{ challenge.id }}").addEventListener("click", function() {
|
||||
addChallenge({{ challenge.id}}, "{{ challenge.name|escapejs }}", {{ challenge.points }});
|
||||
});
|
||||
{% endfor %}
|
||||
</script>
|
||||
{% endblock %}
|
Reference in New Issue
Block a user