diff --git a/apps/permission/fixtures/initial.json b/apps/permission/fixtures/initial.json index 00f952cc..4a34f99a 100644 --- a/apps/permission/fixtures/initial.json +++ b/apps/permission/fixtures/initial.json @@ -3829,9 +3829,89 @@ "mask": 3, "field": "", "permanent": false, - "description": "Voir les profils des membres du club" + "description": "Voir les profils des membres du club" } }, + { + "model": "permission.permission", + "pk": 244, + "fields": { + "model": [ + "wrapped", + "wrapped" + ], + "query": "{\"public\": true}", + "type": "view", + "mask": 1, + "field": "", + "permanent": false, + "description": "Voir les wrapped public" + } + }, + { + "model": "permission.permission", + "pk": 245, + "fields": { + "model": [ + "wrapped", + "wrapped" + ], + "query": "{\"note__noteuser__user\": [\"user\"]}", + "type": "view", + "mask": 1, + "field": "", + "permanent": true, + "description": "Voir ses propres wrapped, pour toujours" + } + }, + { + "model": "permission.permission", + "pk": 246, + "fields": { + "model": [ + "wrapped", + "wrapped" + ], + "query": "{\"note__noteuser__user\": [\"user\"]}", + "type": "change", + "mask": 1, + "field": "public", + "permanent": true, + "description": "Modifier la visibilité de ses wrapped, pour toujours" + } + }, + { + "model": "permission.permission", + "pk": 247, + "fields": { + "model": [ + "wrapped", + "wrapped" + ], + "query": "{\"note__noteclub__club\": [\"club\"]}", + "type": "view", + "mask": 1, + "field": "", + "permanent": false, + "description": "Voir les wrapped de son club" + } + }, + { + "model": "permission.permission", + "pk": 248, + "fields": { + "model": [ + "wrapped", + "wrapped" + ], + "query": "{\"note__noteclub__club\": [\"club\"]}", + "type": "change", + "mask": 1, + "field": "public", + "permanent": false, + "description": "Modifier la visibilité des wrapped de son club" + } + }, { "model": "permission.role", "pk": 1, @@ -3881,7 +3961,10 @@ 203, 204, 205, - 206 + 206, + 244, + 245, + 246 ] } }, @@ -3970,7 +4053,9 @@ 227, 233, 234, - 237 + 237, + 247, + 248 ] } }, diff --git a/apps/wrapped/management/commands/generate_wrapped.py b/apps/wrapped/management/commands/generate_wrapped.py index 0ba6d396..f156c989 100644 --- a/apps/wrapped/management/commands/generate_wrapped.py +++ b/apps/wrapped/management/commands/generate_wrapped.py @@ -1,14 +1,15 @@ # Copyright (C) 2028-2024 by BDE ENS Paris-Saclay # SPDX-License-Identifier: GPL-3.0-or-later -### Import ### - +import json from argparse import ArgumentParser from django.core.management import BaseCommand from django.db.models import Q -from note.models import Note -from member.models import User, Club +from note.models import Note, Transaction +from member.models import User, Club, Membership +from activity.models import Activity, Entry +from wei.models import WEIClub from ...models import Bde, Wrapped @@ -78,9 +79,7 @@ class Command(BaseCommand): warning = yellow + 'WARNING' success = green + 'SUCCESS' - ################################### - #### Traitement des paramètres #### - ################################### + # Traitement des paramètres verb = options['verbosity'] bde = [] if options['bde']: @@ -177,19 +176,18 @@ class Command(BaseCommand): if verb >=1 and not create: print(warning) print(yellow + 'create is set to false, wrapped will not be created !') - if verb >= 2 or change or not create: + if verb >= 3 or change or not create: a = str(input('\033[mContinue ? (y/n) ')).lower() if a in ['n','no','non','0']: if verb >= 0: print(abort) return - note = self.convert_to_note(user=user, club=club, verb=verb) + note = self.convert_to_note(change, create, bde=bde, user=user, club=club, verb=verb) if verb >= 1: print("\033[32mUser and/or Club given has successfully convert in their note\033[m") - global_data = self.global_data(bde, verb=verb) if verb >= 1: print("\033[32mGlobal data has been successfully generated\033[m") - unique_data = self.unique_data(bde, note, change, create, global_data=global_data, verb=verb) + unique_data = self.unique_data(bde, note, global_data=global_data, verb=verb) if verb >= 1: print("\033[32mUnique data has been successfully generated\033[m") self.make_wrapped(unique_data, note, bde, change, create, verb=verb) @@ -198,69 +196,334 @@ class Command(BaseCommand): return - def convert_to_note(self, user=None, club=None, verb=1): - query = Q(pk=-1) - if user: - if 'custom' in user[0]: - for u in user[1]: - query |= Q(noteuser__user=u) - elif user[0] == 'all': - query |= Q(noteuser__user__pk__gte=-1) - elif user[0] == 'adh': - # TODO some complex query - query |= query - elif user[0] == 'superuser': - query |= Q(noteuser__user__is_superuser=True) - else: - return + def convert_to_note(self, change, create, bde=None, user=None, club=None, verb=1): + N = [] + for b in bde: + note = Note.objects.filter(pk__lte=-1) + if user: + if 'custom' in user[0]: + for u in user[1]: + query = Q(noteuser__user=u) + note |= Note.objects.filter(query) + elif user[0] == 'all': + query = Q(noteuser__user__pk__gte=-1) + note |= Note.objects.filter(query) + elif user[0] == 'adh': + M = Membership.objects.filter(club=1, + date_start__lt=b.date_end, + date_end__gt=b.date_start, + ).distinct('user') + for m in M: + note |= Note.objects.filter(noteuser__user=m.user) - if club: - if 'custom' in club[0]: - for c in club[1]: - query |= Q(noteclub__club=c) - elif club[0] == 'all': - query |= Q(noteclub__club__pk__gte=-1) - elif club[0] == 'active': - # TODO some complex query - query |= query - else: - return - - if verb >= 3: print('\033[mQuery: ' + str(query)) - note = Note.objects.filter(query) + elif user[0] == 'superuser': + query |= Q(noteuser__user__is_superuser=True) + note |= Note.objects.filter(query) - return note + if club: + if 'custom' in club[0]: + for c in club[1]: + query = Q(noteclub__club=c) + note |= Note.objects.filter(query) + elif club[0] == 'all': + query = Q(noteclub__club__pk__gte=-1) + note |= Note.objects.filter(query) + elif club[0] == 'active': + nc = Note.objects.filter(noteclub__club__pk__gte=-1) + for n in nc: + if Transaction.objects.filter( + Q(created_at__gte=b.date_start, + created_at__lte=b.date_end) & + (Q(source=n) | Q(destination=n))): + note |= Note.objects.filter(pk=n.pk) + + note = self.filter_note(b, note, change, create, verb=verb) + N.append(note) + if verb >= 2: + print("\033[m{nb} note selectionned for bde {bde}".format(nb=len(note) ,bde=b.name)) + return N def global_data(self, bde, verb=1): data = {} for b in bde: if b.name == 'Rave Part[list]': - # TODO - data = {} + if verb >= 2: print("Begin to make global data") + if verb >= 3: print('nb_transaction') + # nb total de transactions + data['nb_transaction'] = Transaction.objects.filter( + created_at__gte=b.date_start, + created_at__lte=b.date_end, + valid=True).count() + + if verb >= 3: print('nb_vieux_con') + # nb total de vielleux con·ne·s derrière le bar + button_id = [2884,2585] + T = Transaction.objects.filter( + created_at__gte=b.date_start, + created_at__lte=b.date_end, + valid=True, + recurrenttransaction__template__pk__in=button_id) + + q = 0 + for t in T: q += t.quantity + data['nb_vieux_con'] = q + + if verb >= 3: print('nb_soiree') + # nb total de soirée + a_type_id = [1, 2, 4, 5, 7, 10] + data['nb_soiree'] = Activity.objects.filter( + date_end__gte=b.date_start, + date_start__lte=b.date_end, + valid=True, + activity_type__pk__in=a_type_id).count() + + if verb >= 3: print('pots, nb_entree_pot') + # nb d'entrée totale aux pots + pot_id = [1, 4, 10] + pots = Activity.objects.filter( + date_end__gte=b.date_start, + date_start__lte=b.date_end, + activity_type__pk__in=pot_id) + data['pots'] = pots # utile dans unique_data + data['nb_entree_pot'] = 0 + for pot in pots: + data['nb_entree_pot'] += Entry.objects.filter(activity=pot).count() + + if verb >= 3: print('top3_buttons') + # top 3 des boutons les plus cliqués + T = Transaction.objects.filter( + created_at__gte=b.date_start, + created_at__lte=b.date_end, + valid=True, + amount__gt=0, + recurrenttransaction__template__pk__gte=-1) + + d = {} + for t in T: + if t.recurrenttransaction.template.name in d: + d[t.recurrenttransaction.template.name] += t.quantity + else : d[t.recurrenttransaction.template.name] = t.quantity + + data['top3_buttons'] = list(sorted(d.items(), key=lambda item: item[1], reverse=True))[:3] + + if verb >= 3: print('class_conso_all') + # le classement des plus gros consommateurs (BDE + club) + T = Transaction.objects.filter( + created_at__gte=b.date_start, + created_at__lte=b.date_end, + valid=True, + source__noteuser__user__pk__gte=-1, + destination__noteclub__club__pk__gte=-1) + + d = {} + for t in T: + if t.source in d: d[t.source] += t.total + else : d[t.source] = t.total + + data['class_conso_all'] = dict(sorted(d.items(), key=lambda item: item[1], reverse=True)) + + if verb >= 3: print('class_conso_bde') + # le classement des plus gros consommateurs BDE + T = Transaction.objects.filter( + created_at__gte=b.date_start, + created_at__lte=b.date_end, + valid=True, + source__noteuser__user__pk__gte=-1, + destination=5) + + d = {} + for t in T: + if t.source in d: d[t.source] += t.total + else : d[t.source] = t.total + + data['class_conso_bde'] = dict(sorted(d.items(), key=lambda item: item[1], reverse=True)) + else: # make your wrapped or reuse previous wrapped raise NotImplementedError("The BDE: {bde_name} has not personalized wrapped, make it !" .format(bde_name=b.name)) return data - def unique_data(self, bde, note, change, create, global_data=None, verb=1): - data = {} + def unique_data(self, bde, note, global_data=None, verb=1): + data = [] for i in range(len(bde)): - if verb >= 2: print('\033[mlen(note) = {nb}'.format(nb=len(note))) - note_filtered = self.filter_note(bde[i], note, change, create, verb=verb) - if verb >= 2: print('\033[mlen(note_after_filter) = {nb}'.format(nb=len(note_filtered))) + data_bde = [] if bde[i].name == 'Rave Part[list]': - # TODO - data = {} + if verb >= 3: + total = len(note[i]) + current = 0 + print('Make {nb} data for wrapped sponsored by {bde}' + .format(nb=total, bde=bde[i].name)) + for n in note[i]: + d = {} + if 'user' in n.__dir__(): + # première conso du mandat + T = Transaction.objects.filter( + valid=True, + recurrenttransaction__template__id__gte=-1, + created_at__gte=bde[i].date_start, + created_at__lte=bde[i].date_end, + source=n, + destination=5).order_by('created_at') + if T: + d['first_conso'] = T[0].template.name + else: + d['first_conso'] = '' + # Wei + bus + W = WEIClub.objects.filter( + date_start__lte=bde[i].date_end, + date_end__gte=bde[i].date_start) + if not W: + d['wei'] = '' + d['bus'] = '' + else: + w = W[0] + M = Membership.objects.filter(club=w, user=n.user) + if not M: + d['wei'] = '' + d['bus'] = '' + else : + A = [] + for a in w.note.alias.iterator(): + A.append(str(a)) + d['wei'] = A[-1] + d['bus'] = M[0].weimembership.bus.name + # top3 conso + T = Transaction.objects.filter( + valid=True, + created_at__gte=bde[i].date_start, + created_at__lte=bde[i].date_end, + source=n, + amount__gt=0, + recurrenttransaction__template__id__gte=-1) + dt = {} + dc = {} + for t in T: + if t.template.name in dt: dt[t.template.name] += t.quantity + else : dt[t.template.name] = t.quantity + if t.template.category.name in dc: dc[t.template.category.name] += t.quantity + else : dc[t.template.category.name] = t.quantity + + d['top3_conso'] = list(sorted(dt.items(), key=lambda item: item[1], reverse=True))[:3] + # catégorie de bouton préférée + if dc: + d['top_category'] = list(sorted(dc.items(), key=lambda item: item[1], reverse=True))[0][0] + else: + d['top_category'] = '' + # nombre de pot, et nombre d'entrée pot + pots = global_data['pots'] + d['nb_pots'] = pots.count() + + p = 0 + for pot in pots: + if Entry.objects.filter(activity=pot,note=n): + p += 1 + d['nb_pot_entry'] = p + # ton nombre de rechargement + d['nb_rechargement'] = Transaction.objects.filter( + valid=True, + created_at__gte=bde[i].date_start, + created_at__lte=bde[i].date_end, + destination=n, + source__pk__in=[1,2,3,4]).count() + # ajout info globale spécifique user + # classement et montant conso all + d['class_part_all'] = len(global_data['class_conso_all']) + if n in global_data['class_conso_all']: + d['class_conso_all'] = list(global_data['class_conso_all']).index(n) + 1 + d['amount_conso_all'] = global_data['class_conso_all'][n]/100 + else: + d['class_conso_all'] = 0 + d['amount_conso_all'] = 0 + # classement et montant conso bde + d['class_part_bde'] = len(global_data['class_conso_bde']) + if n in global_data['class_conso_bde']: + d['class_conso_bde'] = list(global_data['class_conso_bde']).index(n) + 1 + d['amount_conso_bde'] = global_data['class_conso_bde'][n]/100 + else: + d['class_conso_bde'] = 0 + d['amount_conso_bde'] = 0 + + if 'club' in n.__dir__(): + # plus gros consommateur + T = Transaction.objects.filter( + valid=True, + created_at__lte=bde[i].date_end, + created_at__gte=bde[i].date_start, + destination=n, + source__noteuser__user__pk__gte=-1) + dt = {} + + for t in T: + if t.source.user.username in dt: dt[t.source.user.username] += t.total + else : dt[t.source.user.username] = t.total + if dt: + d['big_consumer'] = list(sorted(dt.items(), key=lambda item: item[1], reverse=True))[0] + d['big_consumer'] = (d['big_consumer'][0], d['big_consumer'][1]/100) + else: + d['big_consumer'] = '' + # plus gros créancier + T = Transaction.objects.filter( + valid=True, + created_at__lte=bde[i].date_end, + created_at__gte=bde[i].date_start, + source=n, + destination__noteuser__user__pk__gte=-1) + dt = {} + + for t in T: + if t.destination.user.username in dt: dt[t.destination.user.username] += t.total + else : dt[t.destination.user.username] = t.total + if dt: + d['big_creancier'] = list(sorted(dt.items(), key=lambda item: item[1], reverse=True))[0] + d['big_creancier'] = (d['big_creancier'][0], d['big_creancier'][1]/100) + else: + d['big_creancier'] = '' + # nb de soirée organisée + d['nb_soiree_orga'] = Activity.objects.filter( + valid=True, + date_start__lte=bde[i].date_end, + date_end__gte=bde[i].date_start, + organizer=n.club).count() + # nb de membres cumulé + d['nb_member'] = Membership.objects.filter( + date_start__lte=bde[i].date_end, + date_end__gte=bde[i].date_start, + club=n.club).distinct('user').count() + + # ajout info globale + # top3 button + d['glob_top3_conso'] = global_data['top3_buttons'] + # nb entree pot + d['glob_nb_entree_pot'] = global_data['nb_entree_pot'] + # nb soiree + d['glob_nb_soiree'] = global_data['nb_soiree'] + # nb vieux con + d['glob_nb_vieux_con'] = global_data['nb_vieux_con'] + # nb transaction + d['glob_nb_transaction'] = global_data['nb_transaction'] + + data_bde.append(json.dumps(d)) + if verb >= 3: + current += 1 + print('\033[2K' + '({c}/{t})'.format(c=current, t=total) + '\033[1A') + else: # make your wrapped or reuse previous wrapped raise NotImplementedError("The BDE: {bde_name} has not personalized wrapped, make it !" .format(bde_name=bde[i].name)) + data.append(data_bde) return data def make_wrapped(self, unique_data, note, bde, change, create, verb=1): + if verb >= 3: + current = 0 + total = 0 + for l in note: + total += len(l) + print('\033[mMake {nb} wrapped'.format(nb=total)) for i in range(len(bde)): - for j in len(note[i]): + for j in range(len(note[i])): if create and not Wrapped.objects.filter(bde=bde[i], note=note[i][j]): Wrapped(bde=bde[i], note=note[i][j], @@ -271,11 +534,14 @@ class Command(BaseCommand): w = Wrapped.objects.get(bde=bde[i], note=note[i][j]) w.data_json = unique_data[i][j] w.save() + if verb >= 3: + current += 1 + print('\033[2K' + '({c}/{t})'.format(c=current, t=total) + '\033[1A') return def filter_note(self, bde, note, change, create, verb=1): if change and create: - return note + return list(note) if change and not create: note_new = [] for n in note: diff --git a/apps/wrapped/static/wrapped/css/1/custom.css b/apps/wrapped/static/wrapped/css/1/custom.css new file mode 100644 index 00000000..50415ffb --- /dev/null +++ b/apps/wrapped/static/wrapped/css/1/custom.css @@ -0,0 +1,69 @@ +:root { + --accent-primary: #FF0065; + --accent-secondary: #FFCB20; +} +body { + font-family: Arial, sans-serif; + background: linear-gradient(135deg, var(--accent-primary), var(--accent-secondary)); + color: white; + text-align: center; + padding: 50px; +} +#name { + font-size: 2em; + font-weight: bold; + text-shadow: 2px 2px 15px var(--accent-secondary); +} +.wrap-container { + max-width: 500px; + margin: auto; + padding: 20px; + background: rgba(0, 0, 0, 0.8); + border-radius: 10px; + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.3); +} +.category { + display: flex; + justify-content: space-between; + padding: 10px; + background: rgba(255, 255, 255, 0.2); + border-radius: 5px; + margin: 10px 0; + padding: 10px; +} +h1 { + font-size: 2.5em; + font-weight: bold; + text-transform: uppercase; + letter-spacing: 2px; + background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary)); + -webkit-background-clip: text; +} +.list { + list-style: none; + padding: 0; +} +.list li { + display: flex; + justify-content: space-between; + background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary)); + margin: 10px 0; + padding: 10px; + border-radius: 5px; + font-weight: bold; +} +.ranking-bar { + width: 100%; + height: 20px; + background: rgba(255, 255, 255, 0.2); + border-radius: 10px; + overflow: hidden; + margin-top: 10px; + position: relative; +} +.ranking-progress { + height: 100%; + width: 0%; + background: linear-gradient(90deg, var(--accent-primary), var(--accent-secondary)); + border-radius: 10px; +} diff --git a/apps/wrapped/static/wrapped/favicon/1/android-chrome-192x192.png b/apps/wrapped/static/wrapped/favicon/1/android-chrome-192x192.png new file mode 100644 index 00000000..40f01b34 Binary files /dev/null and b/apps/wrapped/static/wrapped/favicon/1/android-chrome-192x192.png differ diff --git a/apps/wrapped/static/wrapped/favicon/1/android-chrome-512x512.png b/apps/wrapped/static/wrapped/favicon/1/android-chrome-512x512.png new file mode 100644 index 00000000..6bd8616e Binary files /dev/null and b/apps/wrapped/static/wrapped/favicon/1/android-chrome-512x512.png differ diff --git a/apps/wrapped/static/wrapped/favicon/1/apple-touch-icon.png b/apps/wrapped/static/wrapped/favicon/1/apple-touch-icon.png new file mode 100644 index 00000000..ccd657d9 Binary files /dev/null and b/apps/wrapped/static/wrapped/favicon/1/apple-touch-icon.png differ diff --git a/apps/wrapped/static/wrapped/favicon/1/browserconfig.xml b/apps/wrapped/static/wrapped/favicon/1/browserconfig.xml new file mode 100644 index 00000000..eb5c9b5e --- /dev/null +++ b/apps/wrapped/static/wrapped/favicon/1/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #00a300 + + + diff --git a/apps/wrapped/static/wrapped/favicon/1/favicon-16x16.png b/apps/wrapped/static/wrapped/favicon/1/favicon-16x16.png new file mode 100644 index 00000000..b7a7c124 Binary files /dev/null and b/apps/wrapped/static/wrapped/favicon/1/favicon-16x16.png differ diff --git a/apps/wrapped/static/wrapped/favicon/1/favicon-32x32.png b/apps/wrapped/static/wrapped/favicon/1/favicon-32x32.png new file mode 100644 index 00000000..4f3f95f0 Binary files /dev/null and b/apps/wrapped/static/wrapped/favicon/1/favicon-32x32.png differ diff --git a/apps/wrapped/static/wrapped/favicon/1/favicon.ico b/apps/wrapped/static/wrapped/favicon/1/favicon.ico new file mode 100644 index 00000000..cbc82dde Binary files /dev/null and b/apps/wrapped/static/wrapped/favicon/1/favicon.ico differ diff --git a/apps/wrapped/static/wrapped/favicon/1/mstile-150x150.png b/apps/wrapped/static/wrapped/favicon/1/mstile-150x150.png new file mode 100644 index 00000000..7cdfc755 Binary files /dev/null and b/apps/wrapped/static/wrapped/favicon/1/mstile-150x150.png differ diff --git a/apps/wrapped/static/wrapped/favicon/1/safari-pinned-tab.svg b/apps/wrapped/static/wrapped/favicon/1/safari-pinned-tab.svg new file mode 100644 index 00000000..43a9370f --- /dev/null +++ b/apps/wrapped/static/wrapped/favicon/1/safari-pinned-tab.svg @@ -0,0 +1,503 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/wrapped/static/wrapped/favicon/1/site.webmanifest b/apps/wrapped/static/wrapped/favicon/1/site.webmanifest new file mode 100644 index 00000000..79d235df --- /dev/null +++ b/apps/wrapped/static/wrapped/favicon/1/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/static/favicon/1/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/static/favicon/1/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/apps/wrapped/tables.py b/apps/wrapped/tables.py index 4c3cc107..86428e35 100644 --- a/apps/wrapped/tables.py +++ b/apps/wrapped/tables.py @@ -2,7 +2,7 @@ # SPDX-License-Identifier: GPL-3.0-or-later from django.utils import timezone -from django.utils.html import escape +from django.utils.html import escape, format_html from django.utils.safestring import mark_safe from django.utils.translation import gettext_lazy as _ from note_kfet.middlewares import get_current_request @@ -66,6 +66,24 @@ class WrappedTable(tables.Table): }, ) + share = tables.Column( + accessor="pk", + orderable=False, + attrs={ + "td": { + "class": 'col-sm-2', + "title": _("Click to copy the link in the press paper"), + } + }, + ) + + def render_share(self, value, record): + val = '' + val += _('Copy link') + val += '' + return format_html(val) + def render_public(self, value, record): val = "✔" if record.public else "✖" return val diff --git a/apps/wrapped/templates/wrapped/1/wrapped_base.html b/apps/wrapped/templates/wrapped/1/wrapped_base.html new file mode 100644 index 00000000..23e63339 --- /dev/null +++ b/apps/wrapped/templates/wrapped/1/wrapped_base.html @@ -0,0 +1,76 @@ +{% load static i18n pretty_money getenv %} +{% comment %} +Copyright (C) 2018-2024 by BDE ENS Paris-Saclay +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} + +{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %} + + + + + + + {% block title %}{{ title }}{% endblock title %} - {{ request.site.name }} + + + + {# Favicon #} + + + + + + + + + + + {# Bootstrap, Font Awesome and custom CSS #} + + + + + {# JQuery, Bootstrap and Turbolinks JavaScript #} + + + + + + + + {# Translation in javascript files #} + + + {# If extra ressources are needed for a form, load here #} + {% if form.media %} + {{ form.media }} + {% endif %} + + {% block extracss %}{% endblock %} + + + {% block content %} +

Default content...

+ {% endblock %} +
+
+

{% trans "The NoteKfet this year it's also:" %}

+ +
+ + diff --git a/apps/wrapped/templates/wrapped/1/wrapped_view.html b/apps/wrapped/templates/wrapped/1/wrapped_view.html deleted file mode 100644 index 48ad8efe..00000000 --- a/apps/wrapped/templates/wrapped/1/wrapped_view.html +++ /dev/null @@ -1,8 +0,0 @@ -{% comment %} -Copyright (C) 2018-2024 by BDE ENS Paris-Saclay -SPDX-License-Identifier: GPL-3.0-or-later -{% endcomment %} -{% block content %} -{{ wrapped.data_json }} -{% endblock %} - diff --git a/apps/wrapped/templates/wrapped/1/wrapped_view_club.html b/apps/wrapped/templates/wrapped/1/wrapped_view_club.html new file mode 100644 index 00000000..958199fa --- /dev/null +++ b/apps/wrapped/templates/wrapped/1/wrapped_view_club.html @@ -0,0 +1,30 @@ +{% extends "wrapped/1/wrapped_base.html" %} +{% comment %} +COPYRIGHT (C) 2018-2024 BDE ENS Paris-Saclay +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n pretty_money %} +{% block content %} +
+

{% trans "NoteKfet Wrapped" %}

+

{{ wrapped.note.club.name }}

+ {% trans "Your best consumer:" %} +
+ {% trans "Your worst creditor:" %} +
+ +
+ +{% endblock %} diff --git a/apps/wrapped/templates/wrapped/1/wrapped_view_user.html b/apps/wrapped/templates/wrapped/1/wrapped_view_user.html new file mode 100644 index 00000000..4a457c1d --- /dev/null +++ b/apps/wrapped/templates/wrapped/1/wrapped_view_user.html @@ -0,0 +1,58 @@ +{% extends "wrapped/1/wrapped_base.html" %} +{% comment %} +COPYRIGHT (C) 2018-2024 BDE ENS Paris-Saclay +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n pretty_money %} +{% block content %} +
+

{% trans "NoteKfet Wrapped" %}

+

{{ wrapped.note.user.username }}

+
+ You participate to the wei: {{ wei }} in the bus {{ bus }} +
+
+
+ {{ nb_pot_entry }}/{{ nb_pots }} pots ! +
+ +
+ +
+ Tu as rechargé ta note {{ nb_rechargement }} fois. +
+ Tes dépenses globales +
+
+ {{ class_conso_all }}/{{ class_part_all }} with {{ amount_conso_all }}€ +
+
+
Tes dépenses au BDE +
+
+ {{ class_conso_bde }}/{{ class_part_bde }} with {{ amount_conso_bde }}€ +
+
+ +
+{% endblock %} diff --git a/apps/wrapped/templates/wrapped/wrapped_list.html b/apps/wrapped/templates/wrapped/wrapped_list.html index fd6bcb7e..28892de5 100644 --- a/apps/wrapped/templates/wrapped/wrapped_list.html +++ b/apps/wrapped/templates/wrapped/wrapped_list.html @@ -22,10 +22,17 @@ SPDX-License-Identifier: GPL-3.0-or-later {% block extrajavascript %}