mirror of
https://github.com/ae-utbm/sith.git
synced 2025-11-04 19:13:08 +00:00
Compare commits
78 Commits
features/m
...
feature/im
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
46fa14ed12 | ||
|
|
18dffb0053 | ||
|
|
6e47d1471e | ||
|
|
b5146569e1 | ||
|
|
acde993352 | ||
|
|
8852ef990e | ||
|
|
87295ad9b7 | ||
|
|
5ab5ef681c | ||
|
|
c9e70889dd | ||
|
|
b30ee0a27a | ||
|
|
ef968f3673 | ||
|
|
96dede5077 | ||
|
|
66fcb76cb5 | ||
|
|
63c8e51137 | ||
|
|
12bec5c553 | ||
|
|
08460a6964 | ||
|
|
b5a40cfda9 | ||
|
|
c78953b036 | ||
|
|
427f7ceaff | ||
|
|
1055385bcc | ||
|
|
c1022642a2 | ||
|
|
06253f029c | ||
|
|
0501e6417a | ||
|
|
a198f5252d | ||
|
|
d83842af27 | ||
|
|
f605f7dcc6 | ||
|
|
8e7c025e47 | ||
|
|
1bfe929ab3 | ||
|
|
93cc2c883e | ||
|
|
44290a20a6 | ||
|
|
1f10a284f2 | ||
|
|
28f397574f | ||
|
|
6c1fa6de0b | ||
|
|
f0a08afd31 | ||
|
|
9e0b5b0b82 | ||
|
|
25c5a3297c | ||
|
|
5ea181829e | ||
|
|
0cf203669f | ||
|
|
559bfcac60 | ||
|
|
db8a1ed0ab | ||
|
|
16150905a0 | ||
|
|
9a376887ac | ||
|
|
773808fa59 | ||
|
|
c1e59a0676 | ||
|
|
05febc60bd | ||
|
|
a73fe598ef | ||
|
|
585923c827 | ||
|
|
394e17d599 | ||
|
|
59136850b8 | ||
|
|
d726f4b1e8 | ||
|
|
705b9b1e6a | ||
|
|
31e8ad8a3e | ||
|
|
99827e005b | ||
|
|
751c8a8bc6 | ||
|
|
37216cd16b | ||
|
|
dae68638cf | ||
|
|
7cadc0bc28 | ||
|
|
cce686f3a8 | ||
|
|
4fe46fbcef | ||
|
|
fe8b8f46aa | ||
|
|
7079761ffe | ||
|
|
f681c981c6 | ||
|
|
5d97146d14 | ||
|
|
7b56bd697d | ||
|
|
14cd268d69 | ||
|
|
754be1c9c9 | ||
|
|
da2c155254 | ||
|
|
ceb2888f82 | ||
|
|
26c94c9ec6 | ||
|
|
639197f4c8 | ||
|
|
faccc1367f | ||
|
|
22b83b0814 | ||
|
|
1d82e2a7d9 | ||
|
|
b8a72c57e1 | ||
|
|
9188565a86 | ||
|
|
4d7d22c337 | ||
|
|
b58116b023 | ||
|
|
fe9e5ce861 |
8
.github/actions/setup_project/action.yml
vendored
8
.github/actions/setup_project/action.yml
vendored
@@ -6,13 +6,13 @@ runs:
|
|||||||
- name: Install apt packages
|
- name: Install apt packages
|
||||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||||
with:
|
with:
|
||||||
packages: gettext libgraphviz-dev
|
packages: gettext libxapian-dev libgraphviz-dev
|
||||||
version: 1.0 # increment to reset cache
|
version: 1.0 # increment to reset cache
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install gettext libgraphviz-dev
|
sudo apt install gettext libxapian-dev libgraphviz-dev
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|
||||||
- name: Set up python
|
- name: Set up python
|
||||||
@@ -25,7 +25,7 @@ runs:
|
|||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.local
|
path: ~/.local
|
||||||
key: poetry-0 # increment to reset cache
|
key: poetry-0 # increment to reset cache
|
||||||
|
|
||||||
- name: Install Poetry
|
- name: Install Poetry
|
||||||
if: steps.cached-poetry.outputs.cache-hit != 'true'
|
if: steps.cached-poetry.outputs.cache-hit != 'true'
|
||||||
|
|||||||
10
.github/actions/setup_xapian/action.yml
vendored
Normal file
10
.github/actions/setup_xapian/action.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
name: "Setup xapian"
|
||||||
|
description: "Setup the xapian indexes"
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Setup xapian index
|
||||||
|
run: |
|
||||||
|
mkdir -p /dev/shm/search_indexes
|
||||||
|
ln -s /dev/shm/search_indexes sith/search_indexes
|
||||||
|
shell: bash
|
||||||
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
@@ -2,10 +2,13 @@ name: Sith 3 CI
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [master, taiste, features/**]
|
branches:
|
||||||
|
- master
|
||||||
|
- taiste
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [master, taiste]
|
branches:
|
||||||
workflow_dispatch:
|
- master
|
||||||
|
- taiste
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
black:
|
black:
|
||||||
@@ -21,16 +24,11 @@ jobs:
|
|||||||
tests:
|
tests:
|
||||||
name: Run tests and generate coverage report
|
name: Run tests and generate coverage report
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
|
||||||
image: docker.elastic.co/elasticsearch/elasticsearch:7.17.14
|
|
||||||
env:
|
|
||||||
discovery.type: single-node
|
|
||||||
ports:
|
|
||||||
- 9200
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository
|
- name: Check out repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- uses: ./.github/actions/setup_project
|
- uses: ./.github/actions/setup_project
|
||||||
|
- uses: ./.github/actions/setup_xapian
|
||||||
- uses: ./.github/actions/compile_messages
|
- uses: ./.github/actions/compile_messages
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: poetry run coverage run ./manage.py test
|
run: poetry run coverage run ./manage.py test
|
||||||
|
|||||||
3
.github/workflows/taiste.yml
vendored
3
.github/workflows/taiste.yml
vendored
@@ -2,8 +2,7 @@ name: Sith3 taiste
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [taiste]
|
branches: [ taiste ]
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deployment:
|
deployment:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{% from 'core/macros.jinja' import user_profile_link, paginate %}
|
{% from 'core/macros.jinja' import user_profile_link, paginate %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>{% trans %}Sales{% endtrans %}</h3>
|
<h3>{% trans %}Sellings{% endtrans %}</h3>
|
||||||
<form id="form" action="?page=1" method="post">
|
<form id="form" action="?page=1" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form }}
|
{{ form }}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
{% if object.club_account.exists() %}
|
{% if object.club_account.exists() %}
|
||||||
<h4>{% trans %}Accounting: {% endtrans %}</h4>
|
<h4>{% trans %}Accouting: {% endtrans %}</h4>
|
||||||
<ul>
|
<ul>
|
||||||
{% for ca in object.club_account.all() %}
|
{% for ca in object.club_account.all() %}
|
||||||
<li><a href="{{ url('accounting:club_details', c_account_id=ca.id) }}">{{ ca.get_display_name() }}</a></li>
|
<li><a href="{{ url('accounting:club_details', c_account_id=ca.id) }}">{{ ca.get_display_name() }}</a></li>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
<p> <a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Moderate{% endtrans %}</a></p>
|
<p> <a href="{{ url('com:news_moderate', news_id=news.id) }}">{% trans %}Moderate{% endtrans %}</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.can_edit(news) %}
|
{% if user.can_edit(news) %}
|
||||||
<p> <a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit (will be moderated again){% endtrans %}</a></p>
|
<p> <a href="{{ url('com:news_edit', news_id=news.id) }}">{% trans %}Edit (will be remoderated){% endtrans %}</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
27
com/tests.py
27
com/tests.py
@@ -159,33 +159,6 @@ class NewsTest(TestCase):
|
|||||||
self.assertFalse(self.new.is_owned_by(self.anonymous))
|
self.assertFalse(self.new.is_owned_by(self.anonymous))
|
||||||
self.assertFalse(self.new.is_owned_by(self.sli))
|
self.assertFalse(self.new.is_owned_by(self.sli))
|
||||||
|
|
||||||
def test_news_viewer(self):
|
|
||||||
"""
|
|
||||||
Test that moderated news can be viewed by anyone
|
|
||||||
and not moderated news only by com admins
|
|
||||||
"""
|
|
||||||
# by default a news isn't moderated
|
|
||||||
self.assertTrue(self.new.can_be_viewed_by(self.com_admin))
|
|
||||||
self.assertFalse(self.new.can_be_viewed_by(self.sli))
|
|
||||||
self.assertFalse(self.new.can_be_viewed_by(self.anonymous))
|
|
||||||
self.assertFalse(self.new.can_be_viewed_by(self.author))
|
|
||||||
|
|
||||||
self.new.is_moderated = True
|
|
||||||
self.new.save()
|
|
||||||
self.assertTrue(self.new.can_be_viewed_by(self.com_admin))
|
|
||||||
self.assertTrue(self.new.can_be_viewed_by(self.sli))
|
|
||||||
self.assertTrue(self.new.can_be_viewed_by(self.anonymous))
|
|
||||||
self.assertTrue(self.new.can_be_viewed_by(self.author))
|
|
||||||
|
|
||||||
def test_news_editor(self):
|
|
||||||
"""
|
|
||||||
Test that only com admins can edit news
|
|
||||||
"""
|
|
||||||
self.assertTrue(self.new.can_be_edited_by(self.com_admin))
|
|
||||||
self.assertFalse(self.new.can_be_edited_by(self.sli))
|
|
||||||
self.assertFalse(self.new.can_be_edited_by(self.anonymous))
|
|
||||||
self.assertFalse(self.new.can_be_edited_by(self.author))
|
|
||||||
|
|
||||||
|
|
||||||
class WeekmailArticleTest(TestCase):
|
class WeekmailArticleTest(TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -180,15 +180,14 @@ def get_group(*, pk: int = None, name: str = None) -> Optional[Group]:
|
|||||||
:param pk: The primary key of the group
|
:param pk: The primary key of the group
|
||||||
:param name: The name of the group
|
:param name: The name of the group
|
||||||
:return: The group if it exists, else None
|
:return: The group if it exists, else None
|
||||||
:raise ValueError: If no group matches the criteria
|
:raises ValueError: If no group matches the criteria
|
||||||
"""
|
"""
|
||||||
if pk is None and name is None:
|
if pk is None and name is None:
|
||||||
raise ValueError("Either pk or name must be set")
|
raise ValueError("Either pk or name must be set")
|
||||||
|
if name is not None:
|
||||||
# replace space characters to hide warnings with memcached backend
|
name = name.replace(" ", "_") # avoid errors with memcached backend
|
||||||
pk_or_name: Union[str, int] = pk if pk is not None else name.replace(" ", "_")
|
pk_or_name: Union[str, int] = pk if pk is not None else name
|
||||||
group = cache.get(f"sith_group_{pk_or_name}")
|
group = cache.get(f"sith_group_{pk_or_name}")
|
||||||
|
|
||||||
if group == "not_found":
|
if group == "not_found":
|
||||||
# Using None as a cache value is a little bit tricky,
|
# Using None as a cache value is a little bit tricky,
|
||||||
# so we use a special string to represent None
|
# so we use a special string to represent None
|
||||||
@@ -810,10 +809,6 @@ class AnonymousUser(AuthAnonymousUser):
|
|||||||
def can_edit(self, obj):
|
def can_edit(self, obj):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
|
||||||
def is_com_admin(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def can_view(self, obj):
|
def can_view(self, obj):
|
||||||
if (
|
if (
|
||||||
hasattr(obj, "view_groups")
|
hasattr(obj, "view_groups")
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 434 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
1232
core/static/core/font-awesome/js/fontawesome.min.js
vendored
1232
core/static/core/font-awesome/js/fontawesome.min.js
vendored
File diff suppressed because one or more lines are too long
165
core/static/core/fontawesome/LICENSE.txt
Normal file
165
core/static/core/fontawesome/LICENSE.txt
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
Fonticons, Inc. (https://fontawesome.com)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Font Awesome Free License
|
||||||
|
|
||||||
|
Font Awesome Free is free, open source, and GPL friendly. You can use it for
|
||||||
|
commercial projects, open source projects, or really almost whatever you want.
|
||||||
|
Full Font Awesome Free license: https://fontawesome.com/license/free.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
|
||||||
|
|
||||||
|
The Font Awesome Free download is licensed under a Creative Commons
|
||||||
|
Attribution 4.0 International License and applies to all icons packaged
|
||||||
|
as SVG and JS file types.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Fonts: SIL OFL 1.1 License
|
||||||
|
|
||||||
|
In the Font Awesome Free download, the SIL OFL license applies to all icons
|
||||||
|
packaged as web and desktop font files.
|
||||||
|
|
||||||
|
Copyright (c) 2023 Fonticons, Inc. (https://fontawesome.com)
|
||||||
|
with Reserved Font Name: "Font Awesome".
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
SIL OPEN FONT LICENSE
|
||||||
|
Version 1.1 - 26 February 2007
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting — in part or in whole — any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Code: MIT License (https://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
In the Font Awesome Free download, the MIT license applies to all non-font and
|
||||||
|
non-icon files.
|
||||||
|
|
||||||
|
Copyright 2023 Fonticons, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in the
|
||||||
|
Software without restriction, including without limitation the rights to use, copy,
|
||||||
|
modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
and to permit persons to whom the Software is furnished to do so, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Attribution
|
||||||
|
|
||||||
|
Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font
|
||||||
|
Awesome Free files already contain embedded comments with sufficient
|
||||||
|
attribution, so you shouldn't need to do anything additional when using these
|
||||||
|
files normally.
|
||||||
|
|
||||||
|
We've kept attribution comments terse, so we ask that you do not actively work
|
||||||
|
to remove them from files, especially code. They're a great way for folks to
|
||||||
|
learn about Font Awesome.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Brand Icons
|
||||||
|
|
||||||
|
All brand icons are trademarks of their respective owners. The use of these
|
||||||
|
trademarks does not indicate endorsement of the trademark holder by Font
|
||||||
|
Awesome, nor vice versa. **Please do not use brand logos for any purpose except
|
||||||
|
to represent the company, product, or service to which they refer.**
|
||||||
9
core/static/core/fontawesome/css/all.min.css
vendored
Normal file
9
core/static/core/fontawesome/css/all.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/css/brands.min.css
vendored
Normal file
6
core/static/core/fontawesome/css/brands.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
9
core/static/core/fontawesome/css/fontawesome.min.css
vendored
Normal file
9
core/static/core/fontawesome/css/fontawesome.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/css/regular.min.css
vendored
Normal file
6
core/static/core/fontawesome/css/regular.min.css
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*!
|
||||||
|
* Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com
|
||||||
|
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||||
|
* Copyright 2023 Fonticons, Inc.
|
||||||
|
*/
|
||||||
|
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}.fa-regular,.far{font-weight:400}
|
||||||
6
core/static/core/fontawesome/css/solid.min.css
vendored
Normal file
6
core/static/core/fontawesome/css/solid.min.css
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*!
|
||||||
|
* Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com
|
||||||
|
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||||
|
* Copyright 2023 Fonticons, Inc.
|
||||||
|
*/
|
||||||
|
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}
|
||||||
6
core/static/core/fontawesome/css/svg-with-js.min.css
vendored
Normal file
6
core/static/core/fontawesome/css/svg-with-js.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/css/v4-font-face.min.css
vendored
Normal file
6
core/static/core/fontawesome/css/v4-font-face.min.css
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*!
|
||||||
|
* Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com
|
||||||
|
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||||
|
* Copyright 2023 Fonticons, Inc.
|
||||||
|
*/
|
||||||
|
@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a}
|
||||||
6
core/static/core/fontawesome/css/v4-shims.min.css
vendored
Normal file
6
core/static/core/fontawesome/css/v4-shims.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/css/v5-font-face.min.css
vendored
Normal file
6
core/static/core/fontawesome/css/v5-font-face.min.css
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/*!
|
||||||
|
* Font Awesome Free 6.4.0 by @fontawesome - https://fontawesome.com
|
||||||
|
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||||
|
* Copyright 2023 Fonticons, Inc.
|
||||||
|
*/
|
||||||
|
@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}
|
||||||
6
core/static/core/fontawesome/js/all.min.js
vendored
Normal file
6
core/static/core/fontawesome/js/all.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/js/brands.min.js
vendored
Normal file
6
core/static/core/fontawesome/js/brands.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/js/conflict-detection.min.js
vendored
Normal file
6
core/static/core/fontawesome/js/conflict-detection.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/js/fontawesome.min.js
vendored
Normal file
6
core/static/core/fontawesome/js/fontawesome.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/js/regular.min.js
vendored
Normal file
6
core/static/core/fontawesome/js/regular.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/js/solid.min.js
vendored
Normal file
6
core/static/core/fontawesome/js/solid.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
core/static/core/fontawesome/js/v4-shims.min.js
vendored
Normal file
6
core/static/core/fontawesome/js/v4-shims.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
core/static/core/fontawesome/webfonts/fa-brands-400.ttf
Normal file
BIN
core/static/core/fontawesome/webfonts/fa-brands-400.ttf
Normal file
Binary file not shown.
BIN
core/static/core/fontawesome/webfonts/fa-brands-400.woff2
Normal file
BIN
core/static/core/fontawesome/webfonts/fa-brands-400.woff2
Normal file
Binary file not shown.
BIN
core/static/core/fontawesome/webfonts/fa-regular-400.ttf
Normal file
BIN
core/static/core/fontawesome/webfonts/fa-regular-400.ttf
Normal file
Binary file not shown.
BIN
core/static/core/fontawesome/webfonts/fa-regular-400.woff2
Normal file
BIN
core/static/core/fontawesome/webfonts/fa-regular-400.woff2
Normal file
Binary file not shown.
BIN
core/static/core/fontawesome/webfonts/fa-solid-900.ttf
Normal file
BIN
core/static/core/fontawesome/webfonts/fa-solid-900.ttf
Normal file
Binary file not shown.
BIN
core/static/core/fontawesome/webfonts/fa-solid-900.woff2
Normal file
BIN
core/static/core/fontawesome/webfonts/fa-solid-900.woff2
Normal file
Binary file not shown.
BIN
core/static/core/fontawesome/webfonts/fa-v4compatibility.ttf
Normal file
BIN
core/static/core/fontawesome/webfonts/fa-v4compatibility.ttf
Normal file
Binary file not shown.
BIN
core/static/core/fontawesome/webfonts/fa-v4compatibility.woff2
Normal file
BIN
core/static/core/fontawesome/webfonts/fa-v4compatibility.woff2
Normal file
Binary file not shown.
@@ -191,13 +191,157 @@ $hovered-red-text-color: #ff4d4d;
|
|||||||
>.right {
|
>.right {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
>.links {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
height: 40px;
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 375px) {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
font-size: 20px;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>.notification {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
>a {
|
||||||
|
color: $text-color;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $hovered-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
>span {
|
||||||
|
color: $text-color;
|
||||||
|
font-size: 14px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: $red-text-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: absolute;
|
||||||
|
top: -50%;
|
||||||
|
right: -50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>#header_notif {
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
margin: 0;
|
||||||
|
background-color: whitesmoke;
|
||||||
|
top: calc(100% + 10px);
|
||||||
|
right: calc(50% - 30px);
|
||||||
|
width: 400px;
|
||||||
|
max-width: calc(100vw - 30px);
|
||||||
|
padding: 10px;
|
||||||
|
z-index: 100;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 3px 3px 3px 0 #767676;
|
||||||
|
|
||||||
|
>ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
min-height: 20px;
|
||||||
|
max-height: 120px;
|
||||||
|
overflow-y: auto;
|
||||||
|
|
||||||
|
>li {
|
||||||
|
>a {
|
||||||
|
.datetime {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
font-style: italic;
|
||||||
|
font-size: .8em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.empty-notification {
|
||||||
|
text-align: center;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.options {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-top: 10px;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
>a {
|
||||||
|
color: black;
|
||||||
|
padding: 5px;
|
||||||
|
width: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
text-align: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #ddd;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(0, 0, 0, .2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
>a {
|
||||||
|
text-align: right;
|
||||||
|
color: $text-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $hovered-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
color: $red-text-color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $hovered-red-text-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
>.user {
|
>.user {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 15px;
|
gap: 10px;
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
@media (max-width: 1200px) {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -216,161 +360,26 @@ $hovered-red-text-color: #ff4d4d;
|
|||||||
background-color: $background-color;
|
background-color: $background-color;
|
||||||
}
|
}
|
||||||
|
|
||||||
>.options {
|
>.username {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
justify-content: flex-end;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
|
||||||
>.username {
|
@media (max-width: 500px) {
|
||||||
display: flex;
|
justify-content: flex-start;
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 5px;
|
|
||||||
|
|
||||||
@media (max-width: 500px) {
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
>a {
|
|
||||||
color: $text-color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $hovered-text-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
>.links {
|
>a {
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 15px;
|
|
||||||
|
|
||||||
@media (max-width: 1200px) {
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
>a {
|
|
||||||
text-align: right;
|
|
||||||
color: $text-color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $hovered-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
color: $red-text-color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $hovered-red-text-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
>.notification {
|
|
||||||
height: 100%;
|
|
||||||
width: 55px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
>a {
|
|
||||||
color: $text-color;
|
|
||||||
position: relative;
|
|
||||||
font-size: 25px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $hovered-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
>span {
|
|
||||||
color: $text-color;
|
color: $text-color;
|
||||||
font-size: 14px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
width: 10px;
|
|
||||||
height: 10px;
|
|
||||||
padding: 5px;
|
|
||||||
background-color: $red-text-color;
|
|
||||||
border-radius: 50%;
|
|
||||||
position: absolute;
|
|
||||||
top: -50%;
|
|
||||||
right: -50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
>#header_notif {
|
&:hover {
|
||||||
box-sizing: border-box;
|
color: $hovered-text-color;
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
margin: 0;
|
|
||||||
background-color: whitesmoke;
|
|
||||||
top: calc(100% + 10px);
|
|
||||||
right: calc(50% - 30px);
|
|
||||||
width: 400px;
|
|
||||||
max-width: calc(100vw - 30px);
|
|
||||||
padding: 10px;
|
|
||||||
z-index: 100;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 3px 3px 3px 0 #767676;
|
|
||||||
|
|
||||||
>ul {
|
|
||||||
list-style-type: none;
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 10px;
|
|
||||||
min-height: 20px;
|
|
||||||
max-height: 120px;
|
|
||||||
overflow-y: auto;
|
|
||||||
|
|
||||||
>li {
|
|
||||||
>a {
|
|
||||||
.datetime {
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-start;
|
|
||||||
gap: 10px;
|
|
||||||
font-style: italic;
|
|
||||||
font-size: .8em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.empty-notification {
|
|
||||||
text-align: center;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.options {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-top: 10px;
|
|
||||||
gap: 5px;
|
|
||||||
|
|
||||||
>a {
|
|
||||||
color: black;
|
|
||||||
padding: 5px;
|
|
||||||
width: 50%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: 5px;
|
|
||||||
background-color: #ddd;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(0, 0, 0, .2);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
>.left {
|
>.left {
|
||||||
|
|||||||
@@ -1031,7 +1031,7 @@ thead {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tbody > tr {
|
tbody > tr {
|
||||||
&:nth-child(even):not(.highlight) {
|
&:nth-child(even) {
|
||||||
background: $primary-neutral-light-color;
|
background: $primary-neutral-light-color;
|
||||||
}
|
}
|
||||||
&.clickable:hover {
|
&.clickable:hover {
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
{# Thile file is quite heavy (around 250kb), so declaring it in a block allows easy removal #}
|
{# Thile file is quite heavy (around 250kb), so declaring it in a block allows easy removal #}
|
||||||
<link rel="stylesheet" href="{{ static('core/js/ui/jquery-ui.min.css') }}">
|
<link rel="stylesheet" href="{{ static('core/js/ui/jquery-ui.min.css') }}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
<link rel="preload" as="style" href="{{ static('core/font-awesome/css/font-awesome.min.css') }}" onload="this.onload=null;this.rel='stylesheet'">
|
<!-- Font Awesome 6 -->
|
||||||
<noscript><link rel="stylesheet" href="{{ static('core/font-awesome/css/font-awesome.min.css') }}"></noscript>
|
<link rel="preload" as="style" href="{{ static('core/fontawesome/css/all.min.css') }}" onload="this.onload=null;this.rel='stylesheet'">
|
||||||
<script defer href="{{ static('core/font-awesome/js/fontawesone.min.js') }}"></script>
|
<noscript><link rel="stylesheet" href="{{ static('core/fontawesome/css/all.min.css') }}"></noscript>
|
||||||
|
<script defer href="{{ static('core/fontawesome/js/all.min.js') }}"></script>
|
||||||
|
|
||||||
<!-- Jquery declared here to be accessible in every django widgets -->
|
<!-- Jquery declared here to be accessible in every django widgets -->
|
||||||
<script src="{{ static('core/js/jquery-3.6.2.min.js') }}"></script>
|
<script src="{{ static('core/js/jquery-3.6.2.min.js') }}"></script>
|
||||||
@@ -72,11 +73,11 @@
|
|||||||
<a href="{{ url('counter:activity', counter_id=bar.id) }}">
|
<a href="{{ url('counter:activity', counter_id=bar.id) }}">
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if bar.is_inactive() %}
|
{% if bar.is_inactive() %}
|
||||||
<i class="fa fa-question" style="color: #f39c12"></i>
|
<i class="fa-solid fa-question" style="color: #f39c12"></i>
|
||||||
{% elif bar.is_open(): %}
|
{% elif bar.is_open(): %}
|
||||||
<i class="fa fa-check" style="color: #2ecc71"></i>
|
<i class="fa-solid fa-check" style="color: #2ecc71"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fa fa-times" style="color: #eb2f06"></i>
|
<i class="fa-solid fa-xmark" style="color: #eb2f06"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<span>{{ bar }}</span>
|
<span>{{ bar }}</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -87,14 +88,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="user">
|
<div class="user">
|
||||||
<div class="options">
|
<div class="username">
|
||||||
<div class="username">
|
<a href="{{ url('core:user_profile', user_id=user.id) }}">{{ user.get_display_name() }}</a>
|
||||||
<a href="{{ url('core:user_profile', user_id=user.id) }}">{{ user.get_display_name() }}</a>
|
|
||||||
</div>
|
|
||||||
<div class="links">
|
|
||||||
<a href="{{ url('core:user_tools') }}">{% trans %}Tools{% endtrans %}</a>
|
|
||||||
<a href="{{ url('core:logout') }}">{% trans %}Logout{% endtrans %}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<a
|
<a
|
||||||
href="{{ url('core:user_profile', user_id=user.id) }}"
|
href="{{ url('core:user_profile', user_id=user.id) }}"
|
||||||
@@ -105,54 +100,54 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
></a>
|
></a>
|
||||||
</div>
|
</div>
|
||||||
<div class="notification">
|
|
||||||
<a href="#" onclick="display_notif()">
|
|
||||||
<i class="fa fa-bell-o"></i>
|
|
||||||
{% set notification_count = user.notifications.filter(viewed=False).count() %}
|
|
||||||
|
|
||||||
{% if notification_count > 0 %}
|
<div class="links">
|
||||||
<span>
|
<div class="notification">
|
||||||
{% if notification_count < 100 %}
|
<a href="#" onclick="display_notif()">
|
||||||
{{ notification_count }}
|
<i class="fa-solid fa-bell"></i>
|
||||||
{% else %}
|
{% set notification_count = user.notifications.filter(viewed=False).count() %}
|
||||||
|
|
||||||
{% endif %}
|
{% if notification_count > 0 %}
|
||||||
</span>
|
<span>
|
||||||
{% endif %}
|
{% if notification_count < 100 %} {{ notification_count }} {% else %} {% endif %} </span>
|
||||||
</a>
|
{% endif %}
|
||||||
<div id="header_notif">
|
</a>
|
||||||
<ul>
|
<div id="header_notif">
|
||||||
{% if user.notifications.filter(viewed=False).count() > 0 %}
|
<ul>
|
||||||
|
{% if user.notifications.filter(viewed=False).count() > 0 %}
|
||||||
{% for n in user.notifications.filter(viewed=False).order_by('-date') %}
|
{% for n in user.notifications.filter(viewed=False).order_by('-date') %}
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url("core:notification", notif_id=n.id) }}">
|
<a href="{{ url('core:notification', notif_id=n.id) }}">
|
||||||
<div class="datetime">
|
<div class="datetime">
|
||||||
<span class="header_notif_date">
|
<span class="header_notif_date">
|
||||||
{{ n.date|localtime|date(DATE_FORMAT) }}
|
{{ n.date|localtime|date(DATE_FORMAT) }}
|
||||||
</span>
|
</span>
|
||||||
<span class="header_notif_time">
|
<span class="header_notif_time">
|
||||||
{{ n.date|localtime|time(DATETIME_FORMAT) }}
|
{{ n.date|localtime|time(DATETIME_FORMAT) }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="reason">
|
<div class="reason">
|
||||||
{{ n }}
|
{{ n }}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<li class="empty-notification">{% trans %}You do not have any unread notification{% endtrans %}</li>
|
<li class="empty-notification">{% trans %}You do not have any unread notification{% endtrans %}</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
<div class="options">
|
<div class="options">
|
||||||
<a href="{{ url('core:notification_list') }}">
|
<a href="{{ url('core:notification_list') }}">
|
||||||
{% trans %}View more{% endtrans %}
|
{% trans %}View more{% endtrans %}
|
||||||
</a>
|
</a>
|
||||||
<a href="{{ url('core:notification_list') }}?see_all">
|
<a href="{{ url('core:notification_list') }}?see_all">
|
||||||
{% trans %}Mark all as read{% endtrans %}
|
{% trans %}Mark all as read{% endtrans %}
|
||||||
</a>
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<a href="{{ url('core:user_tools') }}"><i class="fa-solid fa-wrench"></i></a>
|
||||||
|
<a href="{{ url('core:logout') }}"><i class="fa-solid fa-right-from-bracket"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -195,7 +190,7 @@
|
|||||||
{% block nav %}
|
{% block nav %}
|
||||||
{% if not popup %}
|
{% if not popup %}
|
||||||
<nav class="navbar">
|
<nav class="navbar">
|
||||||
<button class="expand-button" onclick="showMenu()"><i class="fa fa-bars"></i></button>
|
<button class="expand-button" onclick="showMenu()"><i class="fa-solid fa-bars"></i></button>
|
||||||
<div id="navbar-content" class="content" style="display: none;">
|
<div id="navbar-content" class="content" style="display: none;">
|
||||||
<a class="link" href="{{ url('core:index') }}">{% trans %}Main{% endtrans %}</a>
|
<a class="link" href="{{ url('core:index') }}">{% trans %}Main{% endtrans %}</a>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
@@ -203,7 +198,11 @@
|
|||||||
<ul class="content">
|
<ul class="content">
|
||||||
<li><a href="{{ url('core:page', page_name='ae') }}">{% trans %}AE{% endtrans %}</a></li>
|
<li><a href="{{ url('core:page', page_name='ae') }}">{% trans %}AE{% endtrans %}</a></li>
|
||||||
<li><a href="{{ url('core:page', page_name='clubs') }}">{% trans %}AE's clubs{% endtrans %}</a></li>
|
<li><a href="{{ url('core:page', page_name='clubs') }}">{% trans %}AE's clubs{% endtrans %}</a></li>
|
||||||
<li><a href="{{ url('core:page', page_name='utbm-associations') }}">{% trans %}Others UTBM's Associations{% endtrans %}</a></li>
|
<li><a href="{{ url('core:page', page_name='bdf') }}">{% trans %}BdF{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('core:page', page_name='bds') }}">{% trans %}BDS{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('core:page', page_name='cetu') }}">{% trans %}CETU{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('core:page', page_name='clubs/doceo') }}">{% trans %}Doceo{% endtrans %}</a></li>
|
||||||
|
<li><a href="{{ url('core:page', page_name='positions') }}">{% trans %}Positions{% endtrans %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
{% block file %}
|
{% block file %}
|
||||||
<h3>
|
<h3>
|
||||||
{% if file.is_folder %}
|
{% if file.is_folder %}
|
||||||
<i class="fa fa-folder fa-3x" aria-hidden="true"></i>
|
<i class="fa-solid fa-folder-open"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fa fa-file fa-3x" aria-hidden="true"></i>
|
<i class="fa-solid fa-file"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{{ file.get_display_name() }}
|
{{ file.get_display_name() }}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -41,9 +41,9 @@
|
|||||||
<li style="list-style-type: none;">
|
<li style="list-style-type: none;">
|
||||||
<input type="checkbox" name="file_list" value="{{ f.id }}">
|
<input type="checkbox" name="file_list" value="{{ f.id }}">
|
||||||
{% if f.is_folder %}
|
{% if f.is_folder %}
|
||||||
<i class="fa fa-folder" aria-hidden="true"></i>
|
<i class="fa-solid fa-folder"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fa fa-file" aria-hidden="true"></i>
|
<i class="fa-solid fa-file"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ url('core:file_detail', file_id=f.id, popup=popup) }}">{{ f.get_display_name() }}</a></li>
|
<a href="{{ url('core:file_detail', file_id=f.id, popup=popup) }}">{{ f.get_display_name() }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
{% for f in file_list %}
|
{% for f in file_list %}
|
||||||
<li style="list-style-type: none;">
|
<li style="list-style-type: none;">
|
||||||
{% if f.is_folder %}
|
{% if f.is_folder %}
|
||||||
<i class="fa fa-folder" aria-hidden="true"></i>
|
<i class="fa-solid fa-folder"></i>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fa fa-file" aria-hidden="true"></i>
|
<i class="fa-solid fa-file"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<a href="{{ url('core:file_detail', file_id=f.id, popup=popup) }}">{{ f.name }}</a></li>
|
<a href="{{ url('core:file_detail', file_id=f.id, popup=popup) }}">{{ f.name }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -40,11 +40,11 @@
|
|||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro fb_quick(news) -%}
|
{% macro fb_quick(news) -%}
|
||||||
<a rel="nofollow" target="#" href="https://www.facebook.com/sharer/sharer.php?u={{ news.get_full_url() }}" class="fb fa fa-facebook-square fa-2x"></a>
|
<a rel="nofollow" target="#" href="https://www.facebook.com/sharer/sharer.php?u={{ news.get_full_url() }}" class="fb fa-brands fa-facebook fa-2x"></a>
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro tweet_quick(news) -%}
|
{% macro tweet_quick(news) -%}
|
||||||
<a rel="nofollow" target="#" href="https://twitter.com/intent/tweet?text={{ news.get_full_url() }}" class="twitter fa fa-twitter-square fa-2x"></a>
|
<a rel="nofollow" target="#" href="https://twitter.com/intent/tweet?text={{ news.get_full_url() }}" class="twitter fa-brands fa-twitter fa-2x"></a>
|
||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{% macro user_mini_profile(user) %}
|
{% macro user_mini_profile(user) %}
|
||||||
|
|||||||
@@ -40,25 +40,25 @@
|
|||||||
{
|
{
|
||||||
name: "heading-smaller",
|
name: "heading-smaller",
|
||||||
action: EasyMDE.toggleHeadingSmaller,
|
action: EasyMDE.toggleHeadingSmaller,
|
||||||
className: "fa fa-header",
|
className: "fa-solid fa-heading",
|
||||||
title: "{{ translations.heading_smaller }}"
|
title: "{{ translations.heading_smaller }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "italic",
|
name: "italic",
|
||||||
action: EasyMDE.toggleItalic,
|
action: EasyMDE.toggleItalic,
|
||||||
className: "fa fa-italic",
|
className: "fa-solid fa-italic",
|
||||||
title: "{{ translations.italic }}"
|
title: "{{ translations.italic }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "bold",
|
name: "bold",
|
||||||
action: EasyMDE.toggleBold,
|
action: EasyMDE.toggleBold,
|
||||||
className: "fa fa-bold",
|
className: "fa-solid fa-bold",
|
||||||
title: "{{ translations.bold }}"
|
title: "{{ translations.bold }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "strikethrough",
|
name: "strikethrough",
|
||||||
action: EasyMDE.toggleStrikethrough,
|
action: EasyMDE.toggleStrikethrough,
|
||||||
className: "fa fa-strikethrough",
|
className: "fa-solid fa-strikethrough",
|
||||||
title: "{{ translations.strikethrough }}"
|
title: "{{ translations.strikethrough }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
let cm = editor.codemirror;
|
let cm = editor.codemirror;
|
||||||
cm.replaceSelection('__' + cm.getSelection() + '__');
|
cm.replaceSelection('__' + cm.getSelection() + '__');
|
||||||
},
|
},
|
||||||
className: "fa fa-underline",
|
className: "fa-solid fa-underline",
|
||||||
title: "{{ translations.underline }}"
|
title: "{{ translations.underline }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
let cm = editor.codemirror;
|
let cm = editor.codemirror;
|
||||||
cm.replaceSelection('<sup>' + cm.getSelection() + '</sup>');
|
cm.replaceSelection('<sup>' + cm.getSelection() + '</sup>');
|
||||||
},
|
},
|
||||||
className: "fa fa-superscript",
|
className: "fa-solid fa-superscript",
|
||||||
title: "{{ translations.superscript }}"
|
title: "{{ translations.superscript }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -85,84 +85,84 @@
|
|||||||
let cm = editor.codemirror;
|
let cm = editor.codemirror;
|
||||||
cm.replaceSelection('<sub>' + cm.getSelection() + '</sub>');
|
cm.replaceSelection('<sub>' + cm.getSelection() + '</sub>');
|
||||||
},
|
},
|
||||||
className: "fa fa-subscript",
|
className: "fa-solid fa-subscript",
|
||||||
title: "{{ translations.subscript }}"
|
title: "{{ translations.subscript }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "code",
|
name: "code",
|
||||||
action: EasyMDE.toggleCodeBlock,
|
action: EasyMDE.toggleCodeBlock,
|
||||||
className: "fa fa-code",
|
className: "fa-solid fa-code",
|
||||||
title: "{{ translations.code }}"
|
title: "{{ translations.code }}"
|
||||||
},
|
},
|
||||||
"|",
|
"|",
|
||||||
{
|
{
|
||||||
name: "quote",
|
name: "quote",
|
||||||
action: EasyMDE.toggleBlockquote,
|
action: EasyMDE.toggleBlockquote,
|
||||||
className: "fa fa-quote-left",
|
className: "fa-solid fa-quote-left",
|
||||||
title: "{{ translations.quote }}"
|
title: "{{ translations.quote }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "unordered-list",
|
name: "unordered-list",
|
||||||
action: EasyMDE.toggleUnorderedList,
|
action: EasyMDE.toggleUnorderedList,
|
||||||
className: "fa fa-list-ul",
|
className: "fa-solid fa-list-ul",
|
||||||
title: "{{ translations.unordered_list }}"
|
title: "{{ translations.unordered_list }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ordered-list",
|
name: "ordered-list",
|
||||||
action: EasyMDE.toggleOrderedList,
|
action: EasyMDE.toggleOrderedList,
|
||||||
className: "fa fa-list-ol",
|
className: "fa-solid fa-list-ol",
|
||||||
title: "{{ translations.ordered_list }}"
|
title: "{{ translations.ordered_list }}"
|
||||||
},
|
},
|
||||||
"|",
|
"|",
|
||||||
{
|
{
|
||||||
name: "link",
|
name: "link",
|
||||||
action: EasyMDE.drawLink,
|
action: EasyMDE.drawLink,
|
||||||
className: "fa fa-link",
|
className: "fa-solid fa-link",
|
||||||
title: "{{ translations.link }}"
|
title: "{{ translations.link }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "image",
|
name: "image",
|
||||||
action: EasyMDE.drawImage,
|
action: EasyMDE.drawImage,
|
||||||
className: "fa fa-picture-o",
|
className: "fa-solid fa-image",
|
||||||
title: "{{ translations.image }}"
|
title: "{{ translations.image }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "table",
|
name: "table",
|
||||||
action: EasyMDE.drawTable,
|
action: EasyMDE.drawTable,
|
||||||
className: "fa fa-table",
|
className: "fa-solid fa-table",
|
||||||
title: "{{ translations.table }}"
|
title: "{{ translations.table }}"
|
||||||
},
|
},
|
||||||
"|",
|
"|",
|
||||||
{
|
{
|
||||||
name: "clean-block",
|
name: "clean-block",
|
||||||
action: EasyMDE.cleanBlock,
|
action: EasyMDE.cleanBlock,
|
||||||
className: "fa fa-eraser fa-clean-block",
|
className: "fa-solid fa-eraser",
|
||||||
title: "{{ translations.clean_block }}"
|
title: "{{ translations.clean_block }}"
|
||||||
},
|
},
|
||||||
"|",
|
"|",
|
||||||
{
|
{
|
||||||
name: "preview",
|
name: "preview",
|
||||||
action: EasyMDE.togglePreview,
|
action: EasyMDE.togglePreview,
|
||||||
className: "fa fa-eye no-disable",
|
className: "fa-solid fa-eye no-disable",
|
||||||
title: "{{ translations.preview }}"
|
title: "{{ translations.preview }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "side-by-side",
|
name: "side-by-side",
|
||||||
action: EasyMDE.toggleSideBySide,
|
action: EasyMDE.toggleSideBySide,
|
||||||
className: "fa fa-columns no-disable no-mobile",
|
className: "fa-solid fa-columns no-disable no-mobile",
|
||||||
title: "{{ translations.side_by_side }}"
|
title: "{{ translations.side_by_side }}"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "fullscreen",
|
name: "fullscreen",
|
||||||
action: EasyMDE.toggleFullScreen,
|
action: EasyMDE.toggleFullScreen,
|
||||||
className: "fa fa-arrows-alt no-disable no-mobile",
|
className: "fa-solid fa-arrows-alt no-disable no-mobile",
|
||||||
title: "{{ translations.fullscreen }}"
|
title: "{{ translations.fullscreen }}"
|
||||||
},
|
},
|
||||||
"|",
|
"|",
|
||||||
{
|
{
|
||||||
name: "guide",
|
name: "guide",
|
||||||
action: "/page/Aide_sur_la_syntaxe",
|
action: "/page/Aide_sur_la_syntaxe",
|
||||||
className: "fa fa-question-circle",
|
className: "fa-solid fa-question-circle",
|
||||||
title: "{{ translations.guide }}"
|
title: "{{ translations.guide }}"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
{% if user_registered %}
|
{% if user_registered %}
|
||||||
{% trans user_name=user_registered.get_display_name() %}Welcome {{ user_name }}!{% endtrans %}<br>
|
{% trans user_name=user_registered.get_display_name() %}Welcome {{ user_name }}!{% endtrans %}<br>
|
||||||
{% trans %}You successfully registered and you will soon receive a confirmation mail.{% endtrans %}<br>
|
{% trans %}You successfully registred and you will soon receive a confirmation mail.{% endtrans %}<br>
|
||||||
{% trans username=user_registered.username %}Your username is {{ username }}.{% endtrans %}<br>
|
{% trans username=user_registered.username %}Your username is {{ username }}.{% endtrans %}<br>
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|||||||
@@ -41,11 +41,11 @@
|
|||||||
{% set refilled = customer.refillings.exists() %}
|
{% set refilled = customer.refillings.exists() %}
|
||||||
{% if bought or refilled %}
|
{% if bought or refilled %}
|
||||||
{% if bought %}
|
{% if bought %}
|
||||||
<h5>{% trans %}Account purchases{% endtrans %}</h5>
|
<h5>{% trans %}Account buyings{% endtrans %}</h5>
|
||||||
{{ monthly(buyings_month) }}
|
{{ monthly(buyings_month) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if refilled %}
|
{% if refilled %}
|
||||||
<h5>{% trans %}Reloads{% endtrans %}</h5>
|
<h5>{% trans %}Refillings{% endtrans %}</h5>
|
||||||
{{ monthly(refilling_month) }}
|
{{ monthly(refilling_month) }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<p>{% trans %}Amount: {% endtrans %}{{ customer.amount }} €</p>
|
<p>{% trans %}Amount: {% endtrans %}{{ customer.amount }} €</p>
|
||||||
<p><a href="{{ url('core:user_account', user_id=profile.id) }}">{% trans %}Back{% endtrans %}</a></p>
|
<p><a href="{{ url('core:user_account', user_id=profile.id) }}">{% trans %}Back{% endtrans %}</a></p>
|
||||||
{% if customer.buyings.exists() %}
|
{% if customer.buyings.exists() %}
|
||||||
<h4>{% trans %}Account purchases{% endtrans %}</h4>
|
<h4>{% trans %}Account buyings{% endtrans %}</h4>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
</table>
|
</table>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if customer.refillings.exists() %}
|
{% if customer.refillings.exists() %}
|
||||||
<h4>{% trans %}Reloads{% endtrans %}</h4>
|
<h4>{% trans %}Refillings{% endtrans %}</h4>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -165,18 +165,62 @@
|
|||||||
<a href="{{ url('subscription:subscription') }}?member={{ profile.id }}">{% trans %}New subscription{% endtrans
|
<a href="{{ url('subscription:subscription') }}?member={{ profile.id }}">{% trans %}New subscription{% endtrans
|
||||||
%}</a>
|
%}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<br>
|
{% endif %}
|
||||||
{% if profile.was_subscribed and (user == profile or user.can_read_subscription_history)%}
|
<br>
|
||||||
|
{% if profile.was_subscribed and (user == profile or user.can_read_subscription_history)%}
|
||||||
|
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
|
||||||
|
<div class="collapse-header clickable" @click="collapsed = !collapsed">
|
||||||
|
<span class="collapse-header-text">
|
||||||
|
{% trans %}Subscription history{% endtrans %}
|
||||||
|
</span>
|
||||||
|
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
|
||||||
|
<i class="fa-sharp fa-solid fa-caret-down"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="collapse-body" x-show="collapsed" x-transition.scale.origin.top>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{% trans %}Subscription start{% endtrans %}</th>
|
||||||
|
<th>{% trans %}Subscription end{% endtrans %}</th>
|
||||||
|
<th>{% trans %}Subscription type{% endtrans %}</th>
|
||||||
|
<th>{% trans %}Payment method{% endtrans %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
{% for sub in profile.subscriptions.all() %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ sub.subscription_start }}</td>
|
||||||
|
<td>{{ sub.subscription_end }}</td>
|
||||||
|
<td>{{ sub.subscription_type }}</td>
|
||||||
|
<td>{{ sub.get_payment_method_display() }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
<hr>
|
||||||
|
<div>
|
||||||
|
{% if user.is_root or user.is_board_member %}
|
||||||
|
<form class="form-gifts" action="{{ url('core:user_gift_create', user_id=profile.id) }}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ gift_form.label }}
|
||||||
|
{{ gift_form.user }}
|
||||||
|
<input type="submit" value="{% trans %}Give gift{% endtrans %}">
|
||||||
|
</form>
|
||||||
|
{% if profile.gifts.exists() %}
|
||||||
|
{% set gifts = profile.gifts.order_by("-date")|list %}
|
||||||
|
<br>
|
||||||
|
|
||||||
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
|
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
|
||||||
<div class="collapse-header clickable" @click="collapsed = !collapsed">
|
<div class="collapse-header clickable" @click="collapsed = !collapsed">
|
||||||
<span class="collapse-header-text">
|
<span class="collapse-header-text">
|
||||||
{% trans %}Subscription history{% endtrans %}
|
{% trans %}Last given gift :{% endtrans %} {{ gifts[0] }}
|
||||||
</span>
|
</span>
|
||||||
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
|
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
|
||||||
<i class="fa fa-caret-down"></i>
|
<i class="fa-solid fa-caret-down"></i>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="collapse-body" x-show="collapsed" x-transition.scale.origin.top>
|
<div class="collapse-body" x-show="collapsed" x-transition.scale.origin.top>
|
||||||
@@ -190,54 +234,20 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{% for sub in profile.subscriptions.all() %}
|
{% for sub in profile.subscriptions.all() %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ sub.subscription_start }}</td>
|
<td>{{ sub.subscription_start }}</td>
|
||||||
<td>{{ sub.subscription_end }}</td>
|
<td>{{ sub.subscription_end }}</td>
|
||||||
<td>{{ sub.subscription_type }}</td>
|
<td>{{ sub.subscription_type }}</td>
|
||||||
<td>{{ sub.get_payment_method_display() }}</td>
|
<td>{{ sub.get_payment_method_display() }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<hr>
|
|
||||||
<div>
|
|
||||||
{% if user.is_root or user.is_board_member %}
|
|
||||||
<form class="form-gifts" action="{{ url('core:user_gift_create', user_id=profile.id) }}" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ gift_form.label }}
|
|
||||||
{{ gift_form.user }}
|
|
||||||
<input type="submit" value="{% trans %}Give gift{% endtrans %}">
|
|
||||||
</form>
|
|
||||||
{% if profile.gifts.exists() %}
|
|
||||||
{% set gifts = profile.gifts.order_by("-date")|list %}
|
|
||||||
<br>
|
|
||||||
<div class="collapse" :class="{'shadow': collapsed}" x-data="{collapsed: false}" x-cloak>
|
|
||||||
<div class="collapse-header clickable" @click="collapsed = !collapsed">
|
|
||||||
<span class="collapse-header-text">
|
|
||||||
{% trans %}Last given gift :{% endtrans %} {{ gifts[0] }}
|
|
||||||
</span>
|
|
||||||
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
|
|
||||||
<i class="fa fa-caret-down"></i>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="collapse-body" x-show="collapsed" x-transition.scale.origin.top>
|
|
||||||
<ul>
|
|
||||||
{% for gift in gifts %}
|
|
||||||
<li>{{ gift }}
|
|
||||||
<a href="{{ url('core:user_gift_delete', user_id=profile.id, gift_id=gift.id) }}">
|
|
||||||
<i class="fa fa-trash"></i>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
{% else %}
|
{% else %}
|
||||||
<em>{% trans %}No gift given yet{% endtrans %}</em>
|
<em>{% trans %}No gift given yet{% endtrans %}</em>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -15,18 +15,17 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from datetime import date, timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import freezegun
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
from django.core.management import call_command
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
|
|
||||||
from club.models import Membership
|
from club.models import Membership
|
||||||
|
from core.models import User, Group, Page, AnonymousUser
|
||||||
from core.markdown import markdown
|
from core.markdown import markdown
|
||||||
from core.models import AnonymousUser, Group, Page, User
|
|
||||||
from core.utils import get_semester_code, get_start_of_semester
|
|
||||||
from sith import settings
|
from sith import settings
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -598,95 +597,15 @@ class UserIsInGroupTest(TestCase):
|
|||||||
Test that when a user is removed from a group,
|
Test that when a user is removed from a group,
|
||||||
the is_in_group_method return False when calling it again
|
the is_in_group_method return False when calling it again
|
||||||
"""
|
"""
|
||||||
# testing with pk
|
|
||||||
self.toto.groups.add(self.com_admin.pk)
|
self.toto.groups.add(self.com_admin.pk)
|
||||||
self.assertTrue(self.toto.is_in_group(pk=self.com_admin.pk))
|
self.assertTrue(self.toto.is_in_group(pk=self.com_admin.pk))
|
||||||
|
|
||||||
self.toto.groups.remove(self.com_admin.pk)
|
self.toto.groups.remove(self.com_admin.pk)
|
||||||
self.assertFalse(self.toto.is_in_group(pk=self.com_admin.pk))
|
self.assertFalse(self.toto.is_in_group(pk=self.com_admin.pk))
|
||||||
|
|
||||||
# testing with name
|
|
||||||
self.toto.groups.add(self.sas_admin.pk)
|
|
||||||
self.assertTrue(self.toto.is_in_group(name="SAS admin"))
|
|
||||||
|
|
||||||
self.toto.groups.remove(self.sas_admin.pk)
|
|
||||||
self.assertFalse(self.toto.is_in_group(name="SAS admin"))
|
|
||||||
|
|
||||||
def test_not_existing_group(self):
|
def test_not_existing_group(self):
|
||||||
"""
|
"""
|
||||||
Test that searching for a not existing group
|
Test that searching for a not existing group
|
||||||
returns False
|
returns False
|
||||||
"""
|
"""
|
||||||
self.assertFalse(self.skia.is_in_group(name="This doesn't exist"))
|
self.assertFalse(self.skia.is_in_group(name="This doesn't exist"))
|
||||||
|
|
||||||
|
|
||||||
class DateUtilsTest(TestCase):
|
|
||||||
@classmethod
|
|
||||||
def setUpTestData(cls):
|
|
||||||
cls.autumn_month = settings.SITH_SEMESTER_START_AUTUMN[0]
|
|
||||||
cls.autumn_day = settings.SITH_SEMESTER_START_AUTUMN[1]
|
|
||||||
cls.spring_month = settings.SITH_SEMESTER_START_SPRING[0]
|
|
||||||
cls.spring_day = settings.SITH_SEMESTER_START_SPRING[1]
|
|
||||||
|
|
||||||
cls.autumn_semester_january = date(2025, 1, 4)
|
|
||||||
cls.autumn_semester_september = date(2024, 9, 4)
|
|
||||||
cls.autumn_first_day = date(2024, cls.autumn_month, cls.autumn_day)
|
|
||||||
|
|
||||||
cls.spring_semester_march = date(2023, 3, 4)
|
|
||||||
cls.spring_first_day = date(2023, cls.spring_month, cls.spring_day)
|
|
||||||
|
|
||||||
def test_get_semester(self):
|
|
||||||
"""
|
|
||||||
Test that the get_semester function returns the correct semester string
|
|
||||||
"""
|
|
||||||
self.assertEqual(get_semester_code(self.autumn_semester_january), "A24")
|
|
||||||
self.assertEqual(get_semester_code(self.autumn_semester_september), "A24")
|
|
||||||
self.assertEqual(get_semester_code(self.autumn_first_day), "A24")
|
|
||||||
|
|
||||||
self.assertEqual(get_semester_code(self.spring_semester_march), "P23")
|
|
||||||
self.assertEqual(get_semester_code(self.spring_first_day), "P23")
|
|
||||||
|
|
||||||
def test_get_start_of_semester_fixed_date(self):
|
|
||||||
"""
|
|
||||||
Test that the get_start_of_semester correctly the starting date of the semester.
|
|
||||||
"""
|
|
||||||
automn_2024 = date(2024, self.autumn_month, self.autumn_day)
|
|
||||||
self.assertEqual(
|
|
||||||
get_start_of_semester(self.autumn_semester_january), automn_2024
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
get_start_of_semester(self.autumn_semester_september), automn_2024
|
|
||||||
)
|
|
||||||
self.assertEqual(get_start_of_semester(self.autumn_first_day), automn_2024)
|
|
||||||
|
|
||||||
spring_2023 = date(2023, self.spring_month, self.spring_day)
|
|
||||||
self.assertEqual(get_start_of_semester(self.spring_semester_march), spring_2023)
|
|
||||||
self.assertEqual(get_start_of_semester(self.spring_first_day), spring_2023)
|
|
||||||
|
|
||||||
def test_get_start_of_semester_today(self):
|
|
||||||
"""
|
|
||||||
Test that the get_start_of_semester returns the start of the current semester
|
|
||||||
when no date is given
|
|
||||||
"""
|
|
||||||
with freezegun.freeze_time(self.autumn_semester_september):
|
|
||||||
self.assertEqual(get_start_of_semester(), self.autumn_first_day)
|
|
||||||
|
|
||||||
with freezegun.freeze_time(self.spring_semester_march):
|
|
||||||
self.assertEqual(get_start_of_semester(), self.spring_first_day)
|
|
||||||
|
|
||||||
def test_get_start_of_semester_changing_date(self):
|
|
||||||
"""
|
|
||||||
Test that the get_start_of_semester correctly gives the starting date of the semester,
|
|
||||||
even when the semester changes while the server isn't restarted.
|
|
||||||
"""
|
|
||||||
spring_2023 = date(2023, self.spring_month, self.spring_day)
|
|
||||||
autumn_2023 = date(2023, self.autumn_month, self.autumn_day)
|
|
||||||
mid_spring = spring_2023 + timedelta(days=45)
|
|
||||||
mid_autumn = autumn_2023 + timedelta(days=45)
|
|
||||||
|
|
||||||
with freezegun.freeze_time(mid_spring) as frozen_time:
|
|
||||||
self.assertEqual(get_start_of_semester(), spring_2023)
|
|
||||||
|
|
||||||
# forward time to the middle of the next semester
|
|
||||||
frozen_time.move_to(mid_autumn)
|
|
||||||
self.assertEqual(get_start_of_semester(), autumn_2023)
|
|
||||||
|
|||||||
@@ -15,19 +15,20 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import subprocess
|
import subprocess
|
||||||
from datetime import date
|
import re
|
||||||
|
|
||||||
# Image utils
|
# Image utils
|
||||||
|
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from typing import Optional
|
from datetime import date
|
||||||
|
|
||||||
|
from PIL import ExifTags
|
||||||
|
|
||||||
import PIL
|
import PIL
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from PIL import ExifTags
|
|
||||||
from django.utils import timezone
|
|
||||||
|
|
||||||
|
|
||||||
def get_git_revision_short_hash() -> str:
|
def get_git_revision_short_hash() -> str:
|
||||||
@@ -43,54 +44,34 @@ def get_git_revision_short_hash() -> str:
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def get_start_of_semester(today: Optional[date] = None) -> date:
|
def get_start_of_semester(d=date.today()):
|
||||||
"""
|
"""
|
||||||
Return the date of the start of the semester of the given date.
|
This function computes the start date of the semester with respect to the given date (default is today),
|
||||||
If no date is given, return the start date of the current semester.
|
and the start date given in settings.SITH_START_DATE.
|
||||||
|
It takes the nearest past start date.
|
||||||
The current semester is computed as follows:
|
Exemples: with SITH_START_DATE = (8, 15)
|
||||||
|
Today -> Start date
|
||||||
- If the date is between 15/08 and 31/12 => Autumn semester.
|
2015-03-17 -> 2015-02-15
|
||||||
- If the date is between 01/01 and 15/02 => Autumn semester of the previous year.
|
2015-01-11 -> 2014-08-15
|
||||||
- If the date is between 15/02 and 15/08 => Spring semester
|
|
||||||
|
|
||||||
:param today: the date to use to compute the semester. If None, use today's date.
|
|
||||||
:return: the date of the start of the semester
|
|
||||||
"""
|
"""
|
||||||
if today is None:
|
today = d
|
||||||
today = timezone.now().date()
|
year = today.year
|
||||||
|
start = date(year, settings.SITH_START_DATE[0], settings.SITH_START_DATE[1])
|
||||||
autumn = date(today.year, *settings.SITH_SEMESTER_START_AUTUMN)
|
start2 = start.replace(month=(start.month + 6) % 12)
|
||||||
spring = date(today.year, *settings.SITH_SEMESTER_START_SPRING)
|
spring, autumn = min(start, start2), max(start, start2)
|
||||||
|
if today > autumn: # autumn semester
|
||||||
if today >= autumn: # between 15/08 (included) and 31/12 -> autumn semester
|
|
||||||
return autumn
|
return autumn
|
||||||
if today >= spring: # between 15/02 (included) and 15/08 -> spring semester
|
if today > spring: # spring semester
|
||||||
return spring
|
return spring
|
||||||
# between 01/01 and 15/02 -> autumn semester of the previous year
|
return autumn.replace(year=year - 1) # autumn semester of last year
|
||||||
return autumn.replace(year=autumn.year - 1)
|
|
||||||
|
|
||||||
|
|
||||||
def get_semester_code(d: Optional[date] = None) -> str:
|
def get_semester(d=date.today()):
|
||||||
"""
|
|
||||||
Return the semester code of the given date.
|
|
||||||
If no date is given, return the semester code of the current semester.
|
|
||||||
|
|
||||||
The semester code is an upper letter (A for autumn, P for spring),
|
|
||||||
followed by the last two digits of the year.
|
|
||||||
For example, the autumn semester of 2018 is "A18".
|
|
||||||
|
|
||||||
:param d: the date to use to compute the semester. If None, use today's date.
|
|
||||||
:return: the semester code corresponding to the given date
|
|
||||||
"""
|
|
||||||
if d is None:
|
|
||||||
d = timezone.now().date()
|
|
||||||
|
|
||||||
start = get_start_of_semester(d)
|
start = get_start_of_semester(d)
|
||||||
|
if start.month <= 6:
|
||||||
if (start.month, start.day) == settings.SITH_SEMESTER_START_AUTUMN:
|
return "P" + str(start.year)[-2:]
|
||||||
|
else:
|
||||||
return "A" + str(start.year)[-2:]
|
return "A" + str(start.year)[-2:]
|
||||||
return "P" + str(start.year)[-2:]
|
|
||||||
|
|
||||||
|
|
||||||
def file_exist(path):
|
def file_exist(path):
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#
|
#
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from typing import Tuple, Optional
|
from typing import Tuple
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import F, Value, Sum, QuerySet, OuterRef, Exists
|
from django.db.models import F, Value, Sum, QuerySet, OuterRef, Exists
|
||||||
@@ -536,7 +536,7 @@ class Counter(models.Model):
|
|||||||
.order_by("-perm_sum")
|
.order_by("-perm_sum")
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_top_customers(self, since: Optional[date] = None) -> QuerySet:
|
def get_top_customers(self, since=get_start_of_semester()) -> QuerySet:
|
||||||
"""
|
"""
|
||||||
Return a QuerySet querying the money spent by customers of this counter
|
Return a QuerySet querying the money spent by customers of this counter
|
||||||
since the specified date, ordered by descending amount of money spent.
|
since the specified date, ordered by descending amount of money spent.
|
||||||
@@ -546,8 +546,6 @@ class Counter(models.Model):
|
|||||||
- the nickname of the customer
|
- the nickname of the customer
|
||||||
- the amount of money spent by the customer
|
- the amount of money spent by the customer
|
||||||
"""
|
"""
|
||||||
if since is None:
|
|
||||||
since = get_start_of_semester()
|
|
||||||
return (
|
return (
|
||||||
self.sellings.filter(date__gte=since)
|
self.sellings.filter(date__gte=since)
|
||||||
.annotate(
|
.annotate(
|
||||||
@@ -559,8 +557,7 @@ class Counter(models.Model):
|
|||||||
)
|
)
|
||||||
.annotate(nickname=F("customer__user__nick_name"))
|
.annotate(nickname=F("customer__user__nick_name"))
|
||||||
.annotate(promo=F("customer__user__promo"))
|
.annotate(promo=F("customer__user__promo"))
|
||||||
.annotate(user=F("customer__user"))
|
.values("customer__user", "name", "nickname")
|
||||||
.values("user", "promo", "name", "nickname")
|
|
||||||
.annotate(
|
.annotate(
|
||||||
selling_sum=Sum(
|
selling_sum=Sum(
|
||||||
F("unit_price") * F("quantity"), output_field=CurrencyField()
|
F("unit_price") * F("quantity"), output_field=CurrencyField()
|
||||||
@@ -570,17 +567,15 @@ class Counter(models.Model):
|
|||||||
.order_by("-selling_sum")
|
.order_by("-selling_sum")
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_total_sales(self, since=None) -> CurrencyField:
|
def get_total_sales(self, since=get_start_of_semester()) -> CurrencyField:
|
||||||
"""
|
"""
|
||||||
Compute and return the total turnover of this counter
|
Compute and return the total turnover of this counter
|
||||||
since the date specified in parameter (by default, since the start of the current
|
since the date specified in parameter (by default, since the start of the current
|
||||||
semester)
|
semester)
|
||||||
:param since: timestamp from which to perform the calculation
|
:param since: timestamp from which to perform the calculation
|
||||||
:type since: datetime | date | None
|
:type since: datetime | date
|
||||||
:return: Total revenue earned at this counter
|
:return: Total revenue earned at this counter
|
||||||
"""
|
"""
|
||||||
if since is None:
|
|
||||||
since = get_start_of_semester()
|
|
||||||
if isinstance(since, date):
|
if isinstance(since, date):
|
||||||
since = datetime.combine(since, datetime.min.time())
|
since = datetime.combine(since, datetime.min.time())
|
||||||
total = self.sellings.filter(date__gte=since).aggregate(
|
total = self.sellings.filter(date__gte=since).aggregate(
|
||||||
|
|||||||
@@ -28,15 +28,15 @@
|
|||||||
<h5>{% trans %}Legend{% endtrans %}</h5>
|
<h5>{% trans %}Legend{% endtrans %}</h5>
|
||||||
<div class="activity-description">
|
<div class="activity-description">
|
||||||
<div>
|
<div>
|
||||||
<i class="fa fa-check" style="color: #2ecc71"></i>
|
<i class="fa-solid fa-check" style="color: #2ecc71"></i>
|
||||||
<span>{% trans %}counter is open, there's at least one barman connected{% endtrans %}</span>
|
<span>{% trans %}counter is open, there's at least one barman connected{% endtrans %}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<i class="fa fa-question" style="color: #f39c12"></i>
|
<i class="fa-solid fa-question" style="color: #f39c12"></i>
|
||||||
<span>{% trans minutes=settings.SITH_COUNTER_MINUTE_INACTIVE %}counter is open but not active, the last sale was done at least {{ minutes }} minutes ago {% endtrans %}</span>
|
<span>{% trans minutes=settings.SITH_COUNTER_MINUTE_INACTIVE %}counter is open but not active, the last sale was done at least {{ minutes }} minutes ago {% endtrans %}</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<i class="fa fa-times" style="color: #eb2f06"></i>
|
<i class="fa-solid fa-xmark" style="color: #eb2f06"></i>
|
||||||
<span>{% trans %}counter is not open : no one is connected{% endtrans %}</span>
|
<span>{% trans %}counter is not open : no one is connected{% endtrans %}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
{{ form }}
|
{{ form }}
|
||||||
<p><input type="submit" value="{% trans %}Show{% endtrans %}" /></p>
|
<p><input type="submit" value="{% trans %}Show{% endtrans %}" /></p>
|
||||||
</form>
|
</form>
|
||||||
<h6>{% trans %}Reloads{% endtrans %}</h6>
|
<h6>{% trans %}Refillings{% endtrans %}</h6>
|
||||||
<p>
|
<p>
|
||||||
{% for b,s in refilling_sums.items() %}
|
{% for b,s in refilling_sums.items() %}
|
||||||
{{ b }}: {{ s }} €<br/>
|
{{ b }}: {{ s }} €<br/>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.is_owner(c) %}
|
{% if user.is_owner(c) %}
|
||||||
<a href="{{ url('counter:prop_admin', counter_id=c.id) }}">{% trans %}Props{% endtrans %}</a> -
|
<a href="{{ url('counter:prop_admin', counter_id=c.id) }}">{% trans %}Props{% endtrans %}</a> -
|
||||||
<a href="{{ url('counter:refilling_list', counter_id=c.id) }}">{% trans %}Reloads list{% endtrans %}</a>
|
<a href="{{ url('counter:refilling_list', counter_id=c.id) }}">{% trans %}Refillings list{% endtrans %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.is_owner(c) %}
|
{% if user.is_owner(c) %}
|
||||||
<a href="{{ url('counter:prop_admin', counter_id=c.id) }}">{% trans %}Props{% endtrans %}</a> -
|
<a href="{{ url('counter:prop_admin', counter_id=c.id) }}">{% trans %}Props{% endtrans %}</a> -
|
||||||
<a href="{{ url('counter:refilling_list', counter_id=c.id) }}">{% trans %}Reloads list{% endtrans %}</a>
|
<a href="{{ url('counter:refilling_list', counter_id=c.id) }}">{% trans %}Refillings list{% endtrans %}</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>{% trans counter_name=counter %}{{ counter_name }} counter{% endtrans %}</h3>
|
<h3>{% trans counter_name=counter %}{{ counter_name }} counter{% endtrans %}</h3>
|
||||||
<div>
|
<div>
|
||||||
<h3>{% trans %}Sales{% endtrans %}</h3>
|
<h3>{% trans %}Sellings{% endtrans %}</h3>
|
||||||
{% if last_basket %}
|
{% if last_basket %}
|
||||||
<h4>{% trans %}Last selling: {% endtrans %}</h4>
|
<h4>{% trans %}Last selling: {% endtrans %}</h4>
|
||||||
<p>{% trans %}Client: {% endtrans %}{{ last_customer }} - {% trans %}New amount: {% endtrans %}{{ new_customer_amount }} €.</p>
|
<p>{% trans %}Client: {% endtrans %}{{ last_customer }} - {% trans %}New amount: {% endtrans %}{{ new_customer_amount }} €.</p>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>{% trans counter_name=counter %}{{ counter_name }} last operations{% endtrans %}</h3>
|
<h3>{% trans counter_name=counter %}{{ counter_name }} last operations{% endtrans %}</h3>
|
||||||
<h4>{% trans %}Reloads{% endtrans %}</h4>
|
<h4>{% trans %}Refillings{% endtrans %}</h4>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h4>{% trans %}Sales{% endtrans %}</h4>
|
<h4>{% trans %}Sellings{% endtrans %}</h4>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
{% from 'core/macros.jinja' import paginate %}
|
{% from 'core/macros.jinja' import paginate %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{%- trans %}Reloads list{% endtrans %} -- {{ counter.name }}
|
{%- trans %}Refillings list{% endtrans %} -- {{ counter.name }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|||||||
@@ -11,9 +11,7 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h3>{% trans counter_name=counter %}{{ counter_name }} stats{% endtrans %}</h3>
|
<h3>{% trans counter_name=counter %}{{ counter_name }} stats{% endtrans %}</h3>
|
||||||
<h4>
|
<h4>{% trans counter_name=counter.name %}Top 100 {{ counter_name }}{% endtrans %}</h4>
|
||||||
{% trans counter_name=counter.name %}Top 100 {{ counter_name }}{% endtrans %} ({{ current_semester }})
|
|
||||||
</h4>
|
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -37,9 +35,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h4>
|
<h4>{% trans counter_name=counter.name %}Top 100 barman {{ counter_name }}{% endtrans %}</h4>
|
||||||
{% trans counter_name=counter.name %}Top 100 barman {{ counter_name }}{% endtrans %} ({{ current_semester }})
|
|
||||||
</h4>
|
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
# OR WITHIN THE LOCAL FILE "LICENSE"
|
# OR WITHIN THE LOCAL FILE "LICENSE"
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
from datetime import date, timedelta
|
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import string
|
import string
|
||||||
@@ -323,49 +322,42 @@ class CounterStatsTest(TestCase):
|
|||||||
Test the result of Counter.get_top_customers() is correct
|
Test the result of Counter.get_top_customers() is correct
|
||||||
"""
|
"""
|
||||||
top = iter(self.counter.get_top_customers())
|
top = iter(self.counter.get_top_customers())
|
||||||
expected_results = [
|
self.assertEqual(
|
||||||
|
next(top),
|
||||||
{
|
{
|
||||||
"user": self.sli.id,
|
"customer__user": self.sli.id,
|
||||||
"name": f"{self.sli.first_name} {self.sli.last_name}",
|
"name": f"{self.sli.first_name} {self.sli.last_name}",
|
||||||
"promo": self.sli.promo,
|
|
||||||
"nickname": self.sli.nick_name,
|
"nickname": self.sli.nick_name,
|
||||||
"selling_sum": 2000,
|
"selling_sum": 2000,
|
||||||
},
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
next(top),
|
||||||
{
|
{
|
||||||
"user": self.skia.id,
|
"customer__user": self.skia.id,
|
||||||
"name": f"{self.skia.first_name} {self.skia.last_name}",
|
"name": f"{self.skia.first_name} {self.skia.last_name}",
|
||||||
"promo": self.skia.promo,
|
|
||||||
"nickname": self.skia.nick_name,
|
"nickname": self.skia.nick_name,
|
||||||
"selling_sum": 1000,
|
"selling_sum": 1000,
|
||||||
},
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
next(top),
|
||||||
{
|
{
|
||||||
"user": self.krophil.id,
|
"customer__user": self.krophil.id,
|
||||||
"name": f"{self.krophil.first_name} {self.krophil.last_name}",
|
"name": f"{self.krophil.first_name} {self.krophil.last_name}",
|
||||||
"promo": self.krophil.promo,
|
|
||||||
"nickname": self.krophil.nick_name,
|
"nickname": self.krophil.nick_name,
|
||||||
"selling_sum": 100,
|
"selling_sum": 100,
|
||||||
},
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
next(top),
|
||||||
{
|
{
|
||||||
"user": self.root.id,
|
"customer__user": self.root.id,
|
||||||
"name": f"{self.root.first_name} {self.root.last_name}",
|
"name": f"{self.root.first_name} {self.root.last_name}",
|
||||||
"promo": self.root.promo,
|
|
||||||
"nickname": self.root.nick_name,
|
"nickname": self.root.nick_name,
|
||||||
"selling_sum": 2,
|
"selling_sum": 2,
|
||||||
},
|
},
|
||||||
]
|
)
|
||||||
|
|
||||||
for result in expected_results:
|
|
||||||
self.assertEqual(
|
|
||||||
next(top),
|
|
||||||
{
|
|
||||||
"user": result["user"],
|
|
||||||
"name": result["name"],
|
|
||||||
"promo": result["promo"],
|
|
||||||
"nickname": result["nickname"],
|
|
||||||
"selling_sum": result["selling_sum"],
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.assertIsNone(next(top, None))
|
self.assertIsNone(next(top, None))
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ import pytz
|
|||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
|
||||||
from core.utils import get_start_of_semester, get_semester_code
|
from core.utils import get_start_of_semester
|
||||||
from core.views import CanViewMixin, TabedViewMixin, CanEditMixin
|
from core.views import CanViewMixin, TabedViewMixin, CanEditMixin
|
||||||
from core.views.forms import LoginForm
|
from core.views.forms import LoginForm
|
||||||
from core.models import User
|
from core.models import User
|
||||||
@@ -1354,14 +1354,13 @@ class CounterStatView(DetailView, CounterAdminMixin):
|
|||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
"""Add stats to the context"""
|
"""Add stats to the context"""
|
||||||
counter: Counter = self.object
|
counter = self.object
|
||||||
semester_start = get_start_of_semester()
|
semester_start = get_start_of_semester()
|
||||||
office_hours = counter.get_top_barmen()
|
office_hours = counter.get_top_barmen()
|
||||||
kwargs = super(CounterStatView, self).get_context_data(**kwargs)
|
kwargs = super(CounterStatView, self).get_context_data(**kwargs)
|
||||||
kwargs.update(
|
kwargs.update(
|
||||||
{
|
{
|
||||||
"counter": counter,
|
"counter": counter,
|
||||||
"current_semester": get_semester_code(),
|
|
||||||
"total_sellings": counter.get_total_sales(since=semester_start),
|
"total_sellings": counter.get_total_sales(since=semester_start),
|
||||||
"top_customers": counter.get_top_customers(since=semester_start)[:100],
|
"top_customers": counter.get_top_customers(since=semester_start)[:100],
|
||||||
"top_barman": office_hours[:100],
|
"top_barman": office_hours[:100],
|
||||||
|
|||||||
@@ -47,9 +47,9 @@
|
|||||||
<template x-for="item in items" :key="item.id">
|
<template x-for="item in items" :key="item.id">
|
||||||
<li class="item-row" x-show="item.quantity > 0">
|
<li class="item-row" x-show="item.quantity > 0">
|
||||||
<div class="item-quantity">
|
<div class="item-quantity">
|
||||||
<i class="fa fa-minus fa-xs" @click="remove(item.id)"></i>
|
<i class="fa-solid fa-minus"></i>
|
||||||
<span x-text="item.quantity"></span>
|
<span x-text="item.quantity"></span>
|
||||||
<i class="fa fa-plus" @click="add(item)"></i>
|
<i class="fa-solid fa-plus"></i>
|
||||||
</div>
|
</div>
|
||||||
<span class="item-name" x-text="item.name"></span>
|
<span class="item-name" x-text="item.name"></span>
|
||||||
<span class="item-price" x-text="(item.unit_price * item.quantity).toFixed(2) + ' €'"></span>
|
<span class="item-price" x-text="(item.unit_price * item.quantity).toFixed(2) + ' €'"></span>
|
||||||
@@ -63,13 +63,13 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<div class="catalog-buttons">
|
<div class="catalog-buttons">
|
||||||
<button @click="clear_basket()" class="clear">
|
<button @click="clear_basket()" class="clear">
|
||||||
<i class="fa fa-trash"></i>
|
<i class="fa-solid fa-trash"></i>
|
||||||
{% trans %}Clear{% endtrans %}
|
{% trans %}Clear{% endtrans %}
|
||||||
</button>
|
</button>
|
||||||
<form method="get" action="{{ url('eboutic:command') }}">
|
<form method="get" action="{{ url('eboutic:command') }}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button class="validate">
|
<button class="validate">
|
||||||
<i class="fa fa-check"></i>
|
<i class="fa-solid fa-check"></i>
|
||||||
<input type="submit" value="{% trans %}Validate{% endtrans %}"/>
|
<input type="submit" value="{% trans %}Validate{% endtrans %}"/>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<span class="clickable" @click="show_alert = false">
|
<span class="clickable" @click="show_alert = false">
|
||||||
<i class="fa fa-close"></i>
|
<i class="fa-solid fa-xmark"></i>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
{% if p.icon %}
|
{% if p.icon %}
|
||||||
<img class="product-image" src="{{ p.icon.url }}" alt="image de {{ p.name }}">
|
<img class="product-image" src="{{ p.icon.url }}" alt="image de {{ p.name }}">
|
||||||
{% else %}
|
{% else %}
|
||||||
<i class="fa fa-2x fa-picture-o product-image" ></i>
|
<i class="fa-solid fa-image product-image"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="product-description">
|
<div class="product-description">
|
||||||
<h4>{{ p.name }}</h4>
|
<h4>{{ p.name }}</h4>
|
||||||
@@ -123,6 +123,19 @@
|
|||||||
{% else %}
|
{% else %}
|
||||||
<p>{% trans %}There are no items available for sale{% endtrans %}</p>
|
<p>{% trans %}There are no items available for sale{% endtrans %}</p>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
<h3>{% trans %}Partnership Eurockéennes 2023{% endtrans %}</h3>
|
||||||
|
{% if user.is_subscribed %}
|
||||||
|
<a title="Logiciel billetterie en ligne"
|
||||||
|
href="https://widget.weezevent.com/ticket/a203b986-73b0-4e63-b18a-b7c8bad986b7?id_evenement=915745&locale=fr-FR&code=71348"
|
||||||
|
class="weezevent-widget-integration" target="_blank"
|
||||||
|
data-src="https://widget.weezevent.com/ticket/a203b986-73b0-4e63-b18a-b7c8bad986b7?id_evenement=915745&locale=fr-FR&code=71348"
|
||||||
|
data-width="650" data-height="600" data-resize="1" data-nopb="0" data-type="neo" data-width_auto="1"
|
||||||
|
data-noscroll="0" data-id="915745">Billetterie Weezevent</a>
|
||||||
|
<script type="text/javascript" src="https://widget.weezevent.com/weez.js" async defer></script>
|
||||||
|
{% else %}
|
||||||
|
<div>{% trans %}You must be a contributor to access the Eurockéennes ticketing service.{% endtrans %}</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
{% trans %}Edit billing information{% endtrans %}
|
{% trans %}Edit billing information{% endtrans %}
|
||||||
</span>
|
</span>
|
||||||
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
|
<span class="collapse-header-icon" :class="{'reverse': collapsed}">
|
||||||
<i class="fa fa-caret-down"></i>
|
<i class="fa-sharp fa-solid fa-caret-down"></i>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<form class="collapse-body" id="billing_info_form" method="post"
|
<form class="collapse-body" id="billing_info_form" method="post"
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div class="clickable" @click="errors = []">
|
<div class="clickable" @click="errors = []">
|
||||||
<i class="fa fa-close"></i>
|
<i class="fa-solid fa-xmark"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div x-show="successful" class="alert alert-green" x-transition>
|
<div x-show="successful" class="alert alert-green" x-transition>
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
Informations de facturation enregistrées
|
Informations de facturation enregistrées
|
||||||
</div>
|
</div>
|
||||||
<div class="clickable" @click="successful = false">
|
<div class="clickable" @click="successful = false">
|
||||||
<i class="fa fa-close"></i>
|
<i class="fa-solid fa-xmark"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" class="btn btn-blue clickable"
|
<input type="submit" class="btn btn-blue clickable"
|
||||||
|
|||||||
@@ -82,18 +82,18 @@
|
|||||||
<a href="{{url('election:update_role', role_id=role.id)}}">✏️</a>
|
<a href="{{url('election:update_role', role_id=role.id)}}">✏️</a>
|
||||||
<a href="{{url('election:delete_role', role_id=role.id)}}">❌</a>
|
<a href="{{url('election:delete_role', role_id=role.id)}}">❌</a>
|
||||||
{%- if role == role_list.last() %}
|
{%- if role == role_list.last() %}
|
||||||
<button disabled><i class="fa fa-arrow-down"></i></button>
|
<button disabled><i class="fa-solid fa-arrow-down"></i></button>
|
||||||
<button disabled><i class="fa fa-caret-down"></i></button>
|
<button disabled><i class="fa-sharp fa-solid fa-caret-down"></i></button>
|
||||||
{%- else %}
|
{%- else %}
|
||||||
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=bottom');"><i class="fa fa-arrow-down"></i></button>
|
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=bottom');"><i class="fa-solid fa-arrow-down"></i></button>
|
||||||
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=down');"><i class="fa fa-caret-down"></i></button>
|
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=down');"><i class="fa-sharp fa-solid fa-caret-down"></i></button>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{% if role == role_list.first() %}
|
{% if role == role_list.first() %}
|
||||||
<button disabled><i class="fa fa-caret-up"></i></button>
|
<button disabled><i class="fa-solid fa-caret-up"></i></i></button>
|
||||||
<button disabled><i class="fa fa-arrow-up"></i></button>
|
<button disabled><i class="fa-sharp fa-solid fa-arrow-up"></i></i></button>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=up');"><i class="fa fa-caret-up"></i></button>
|
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=up');"><i class="fa-solid fa-caret-up"></i></i></button>
|
||||||
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=top');"><i class="fa fa-arrow-up"></i></button>
|
<button type="button" onclick="window.location.replace('?role={{ role.id }}&action=top');"><i class="fa-sharp fa-solid fa-arrow-up"></i></i></button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{%- endif -%}
|
{%- endif -%}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ msgstr "IBAN"
|
|||||||
|
|
||||||
#: accounting/models.py:112
|
#: accounting/models.py:112
|
||||||
msgid "account number"
|
msgid "account number"
|
||||||
msgstr "numéro de compte"
|
msgstr "numero de compte"
|
||||||
|
|
||||||
#: accounting/models.py:116 accounting/models.py:147 club/models.py:275
|
#: accounting/models.py:116 accounting/models.py:147 club/models.py:275
|
||||||
#: com/models.py:75 com/models.py:266 com/models.py:302 counter/models.py:273
|
#: com/models.py:75 com/models.py:266 com/models.py:302 counter/models.py:273
|
||||||
@@ -1173,7 +1173,7 @@ msgstr "Au"
|
|||||||
#: club/templates/club/club_sellings.jinja:5 club/views.py:154
|
#: club/templates/club/club_sellings.jinja:5 club/views.py:154
|
||||||
#: club/views.py:483 counter/templates/counter/counter_main.jinja:24
|
#: club/views.py:483 counter/templates/counter/counter_main.jinja:24
|
||||||
#: counter/templates/counter/last_ops.jinja:41
|
#: counter/templates/counter/last_ops.jinja:41
|
||||||
msgid "Sales"
|
msgid "Sellings"
|
||||||
msgstr "Ventes"
|
msgstr "Ventes"
|
||||||
|
|
||||||
#: club/templates/club/club_sellings.jinja:9 club/templates/club/stats.jinja:19
|
#: club/templates/club/club_sellings.jinja:9 club/templates/club/stats.jinja:19
|
||||||
@@ -1278,7 +1278,7 @@ msgid "Counters:"
|
|||||||
msgstr "Comptoirs : "
|
msgstr "Comptoirs : "
|
||||||
|
|
||||||
#: club/templates/club/club_tools.jinja:33
|
#: club/templates/club/club_tools.jinja:33
|
||||||
msgid "Accounting: "
|
msgid "Accouting: "
|
||||||
msgstr "Comptabilité : "
|
msgstr "Comptabilité : "
|
||||||
|
|
||||||
#: club/templates/club/club_tools.jinja:41
|
#: club/templates/club/club_tools.jinja:41
|
||||||
@@ -1295,8 +1295,8 @@ msgid ""
|
|||||||
"not shown wait until moderation takes action"
|
"not shown wait until moderation takes action"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Rappelez vous : les mailing listes doivent être modérées, si votre liste "
|
"Rappelez vous : les mailing listes doivent être modérées, si votre liste "
|
||||||
"nouvellement créée n'est pas affichée, attendez jusqu'à ce qu'un modérateur "
|
"nouvellement créee n'est pas affichée, attendez jusqu'à qu'un modérateur "
|
||||||
"prenne une décision"
|
"entre en action"
|
||||||
|
|
||||||
#: club/templates/club/mailing.jinja:13
|
#: club/templates/club/mailing.jinja:13
|
||||||
msgid "Mailing lists waiting for moderation"
|
msgid "Mailing lists waiting for moderation"
|
||||||
@@ -1671,8 +1671,8 @@ msgid "Moderator: "
|
|||||||
msgstr "Modérateur : "
|
msgstr "Modérateur : "
|
||||||
|
|
||||||
#: com/templates/com/news_detail.jinja:42
|
#: com/templates/com/news_detail.jinja:42
|
||||||
msgid "Edit (will be moderated again)"
|
msgid "Edit (will be remoderated)"
|
||||||
msgstr "Éditer (sera soumise de nouveau à la modération)"
|
msgstr "Éditer (sera resoumise à modération)"
|
||||||
|
|
||||||
#: com/templates/com/news_edit.jinja:6 com/templates/com/news_edit.jinja:29
|
#: com/templates/com/news_edit.jinja:6 com/templates/com/news_edit.jinja:29
|
||||||
msgid "Edit news"
|
msgid "Edit news"
|
||||||
@@ -1680,7 +1680,7 @@ msgstr "Éditer la nouvelle"
|
|||||||
|
|
||||||
#: com/templates/com/news_edit.jinja:39
|
#: com/templates/com/news_edit.jinja:39
|
||||||
msgid "Notice: Information, election result - no date"
|
msgid "Notice: Information, election result - no date"
|
||||||
msgstr "Information, résultat d'élection - sans date"
|
msgstr "Information, resultat d'élection - sans date"
|
||||||
|
|
||||||
#: com/templates/com/news_edit.jinja:40
|
#: com/templates/com/news_edit.jinja:40
|
||||||
msgid "Event: punctual event, associated with one date"
|
msgid "Event: punctual event, associated with one date"
|
||||||
@@ -1951,7 +1951,7 @@ msgstr "T'es fou? Un événement ne peut pas finir avant même de commencer."
|
|||||||
|
|
||||||
#: com/views.py:466
|
#: com/views.py:466
|
||||||
msgid "Delete and save to regenerate"
|
msgid "Delete and save to regenerate"
|
||||||
msgstr "Supprimer et sauver pour régénérer"
|
msgstr "Supprimer et sauver pour regénérer"
|
||||||
|
|
||||||
#: com/views.py:481
|
#: com/views.py:481
|
||||||
msgid "Weekmail of the "
|
msgid "Weekmail of the "
|
||||||
@@ -2036,7 +2036,7 @@ msgid ""
|
|||||||
"Designates whether this user should be treated as active. Unselect this "
|
"Designates whether this user should be treated as active. Unselect this "
|
||||||
"instead of deleting accounts."
|
"instead of deleting accounts."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Est-ce que l'utilisateur doit être traité comme actif. Désélectionnez au "
|
"Est-ce que l'utilisateur doit être traité comme actif. Déselectionnez au "
|
||||||
"lieu de supprimer les comptes."
|
"lieu de supprimer les comptes."
|
||||||
|
|
||||||
#: core/models.py:185
|
#: core/models.py:185
|
||||||
@@ -2085,7 +2085,7 @@ msgstr "pronoms"
|
|||||||
|
|
||||||
#: core/models.py:234
|
#: core/models.py:234
|
||||||
msgid "tshirt size"
|
msgid "tshirt size"
|
||||||
msgstr "taille de t-shirt"
|
msgstr "taille de tshirt"
|
||||||
|
|
||||||
#: core/models.py:237
|
#: core/models.py:237
|
||||||
msgid "-"
|
msgid "-"
|
||||||
@@ -2426,7 +2426,7 @@ msgstr "Voir plus"
|
|||||||
#: core/templates/core/base.jinja:122
|
#: core/templates/core/base.jinja:122
|
||||||
#: forum/templates/forum/last_unread.jinja:17
|
#: forum/templates/forum/last_unread.jinja:17
|
||||||
msgid "Mark all as read"
|
msgid "Mark all as read"
|
||||||
msgstr "Marquer tout comme lu"
|
msgstr "Marquer tout commme lu"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:132
|
#: core/templates/core/base.jinja:132
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
@@ -2440,17 +2440,33 @@ msgstr "Accueil"
|
|||||||
msgid "Associations & Clubs"
|
msgid "Associations & Clubs"
|
||||||
msgstr "Associations & Clubs"
|
msgstr "Associations & Clubs"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:204
|
#: core/templates/core/base.jinja:173
|
||||||
msgid "AE"
|
msgid "AE"
|
||||||
msgstr "L'AE"
|
msgstr "L'AE"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:205
|
#: core/templates/core/base.jinja:174
|
||||||
msgid "AE's clubs"
|
msgid "AE's clubs"
|
||||||
msgstr "Les clubs de L'AE"
|
msgstr "Les clubs de L'AE"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:206
|
#: core/templates/core/base.jinja:175
|
||||||
msgid "Others UTBM's Associations"
|
msgid "BdF"
|
||||||
msgstr "Les autres associations de l'UTBM"
|
msgstr "Le BdF"
|
||||||
|
|
||||||
|
#: core/templates/core/base.jinja:176
|
||||||
|
msgid "BDS"
|
||||||
|
msgstr "Le BDS"
|
||||||
|
|
||||||
|
#: core/templates/core/base.jinja:177
|
||||||
|
msgid "CETU"
|
||||||
|
msgstr "Le CETU"
|
||||||
|
|
||||||
|
#: core/templates/core/base.jinja:178
|
||||||
|
msgid "Doceo"
|
||||||
|
msgstr "Doceo"
|
||||||
|
|
||||||
|
#: core/templates/core/base.jinja:179
|
||||||
|
msgid "Positions"
|
||||||
|
msgstr "Postes à pourvoir"
|
||||||
|
|
||||||
#: core/templates/core/base.jinja:187 core/templates/core/user_tools.jinja:118
|
#: core/templates/core/base.jinja:187 core/templates/core/user_tools.jinja:118
|
||||||
msgid "Elections"
|
msgid "Elections"
|
||||||
@@ -2764,7 +2780,7 @@ msgstr "Cotisant jusqu'au %(subscription_end)s"
|
|||||||
|
|
||||||
#: core/templates/core/macros.jinja:86 core/templates/core/user_edit.jinja:40
|
#: core/templates/core/macros.jinja:86 core/templates/core/user_edit.jinja:40
|
||||||
msgid "Account number: "
|
msgid "Account number: "
|
||||||
msgstr "Numéro de compte : "
|
msgstr "Numero de compte : "
|
||||||
|
|
||||||
#: core/templates/core/macros.jinja:91 launderette/models.py:217
|
#: core/templates/core/macros.jinja:91 launderette/models.py:217
|
||||||
msgid "Slot"
|
msgid "Slot"
|
||||||
@@ -2988,7 +3004,7 @@ msgstr "Bienvenue, %(user_name)s!"
|
|||||||
|
|
||||||
#: core/templates/core/register.jinja:10
|
#: core/templates/core/register.jinja:10
|
||||||
msgid ""
|
msgid ""
|
||||||
"You successfully registered and you will soon receive a confirmation mail."
|
"You successfully registred and you will soon receive a confirmation mail."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Vous vous êtes correctement enregistré, et vous devriez recevoir rapidement "
|
"Vous vous êtes correctement enregistré, et vous devriez recevoir rapidement "
|
||||||
"un email de confirmation."
|
"un email de confirmation."
|
||||||
@@ -3047,14 +3063,14 @@ msgstr "Compte utilisateur"
|
|||||||
|
|
||||||
#: core/templates/core/user_account.jinja:44
|
#: core/templates/core/user_account.jinja:44
|
||||||
#: core/templates/core/user_account_detail.jinja:13
|
#: core/templates/core/user_account_detail.jinja:13
|
||||||
msgid "Account purchases"
|
msgid "Account buyings"
|
||||||
msgstr "Achats du compte"
|
msgstr "Achat sur compte utilisateur"
|
||||||
|
|
||||||
#: core/templates/core/user_account.jinja:48
|
#: core/templates/core/user_account.jinja:48
|
||||||
#: core/templates/core/user_account_detail.jinja:46
|
#: core/templates/core/user_account_detail.jinja:46
|
||||||
#: counter/templates/counter/cash_summary_list.jinja:17
|
#: counter/templates/counter/cash_summary_list.jinja:17
|
||||||
#: counter/templates/counter/last_ops.jinja:16
|
#: counter/templates/counter/last_ops.jinja:16
|
||||||
msgid "Reloads"
|
msgid "Refillings"
|
||||||
msgstr "Rechargements"
|
msgstr "Rechargements"
|
||||||
|
|
||||||
#: core/templates/core/user_account.jinja:53
|
#: core/templates/core/user_account.jinja:53
|
||||||
@@ -4098,7 +4114,7 @@ msgstr "Nouveau comptoir"
|
|||||||
#: counter/templates/counter/counter_list.jinja:22
|
#: counter/templates/counter/counter_list.jinja:22
|
||||||
#: counter/templates/counter/counter_list.jinja:44
|
#: counter/templates/counter/counter_list.jinja:44
|
||||||
#: counter/templates/counter/refilling_list.jinja:5
|
#: counter/templates/counter/refilling_list.jinja:5
|
||||||
msgid "Reloads list"
|
msgid "Refillings list"
|
||||||
msgstr "Liste de rechargements"
|
msgstr "Liste de rechargements"
|
||||||
|
|
||||||
#: counter/templates/counter/counter_list.jinja:27
|
#: counter/templates/counter/counter_list.jinja:27
|
||||||
@@ -5017,7 +5033,7 @@ msgid ""
|
|||||||
"The code of an UV must only contains uppercase characters without accent and "
|
"The code of an UV must only contains uppercase characters without accent and "
|
||||||
"numbers"
|
"numbers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Le code d'une UV doit seulement contenir des caractères majuscule sans "
|
"Le code d'une UV doit seulement contenire des caractères majuscule sans "
|
||||||
"accents et nombres"
|
"accents et nombres"
|
||||||
|
|
||||||
#: pedagogy/models.py:67
|
#: pedagogy/models.py:67
|
||||||
@@ -5042,7 +5058,7 @@ msgstr "département"
|
|||||||
|
|
||||||
#: pedagogy/models.py:103
|
#: pedagogy/models.py:103
|
||||||
msgid "objectives"
|
msgid "objectives"
|
||||||
msgstr "objectifs"
|
msgstr "objecifs"
|
||||||
|
|
||||||
#: pedagogy/models.py:104
|
#: pedagogy/models.py:104
|
||||||
msgid "program"
|
msgid "program"
|
||||||
@@ -5078,7 +5094,7 @@ msgstr "heures TE"
|
|||||||
|
|
||||||
#: pedagogy/models.py:217 pedagogy/models.py:291
|
#: pedagogy/models.py:217 pedagogy/models.py:291
|
||||||
msgid "uv"
|
msgid "uv"
|
||||||
msgstr "UE"
|
msgstr "uv"
|
||||||
|
|
||||||
#: pedagogy/models.py:221
|
#: pedagogy/models.py:221
|
||||||
msgid "global grade"
|
msgid "global grade"
|
||||||
@@ -5137,7 +5153,7 @@ msgstr "%(credit_type)s"
|
|||||||
#: pedagogy/templates/pedagogy/guide.jinja:59
|
#: pedagogy/templates/pedagogy/guide.jinja:59
|
||||||
#: pedagogy/templates/pedagogy/moderation.jinja:12
|
#: pedagogy/templates/pedagogy/moderation.jinja:12
|
||||||
msgid "UV"
|
msgid "UV"
|
||||||
msgstr "UE"
|
msgstr "UV"
|
||||||
|
|
||||||
#: pedagogy/templates/pedagogy/guide.jinja:61
|
#: pedagogy/templates/pedagogy/guide.jinja:61
|
||||||
msgid "Department"
|
msgid "Department"
|
||||||
@@ -5237,8 +5253,8 @@ msgid "Key concepts"
|
|||||||
msgstr "Concepts clefs"
|
msgstr "Concepts clefs"
|
||||||
|
|
||||||
#: pedagogy/templates/pedagogy/uv_detail.jinja:79
|
#: pedagogy/templates/pedagogy/uv_detail.jinja:79
|
||||||
msgid "UE manager: "
|
msgid "UV manager: "
|
||||||
msgstr "Gestionnaire d'UE : "
|
msgstr "Gestionnaire d'UV : "
|
||||||
|
|
||||||
#: pedagogy/templates/pedagogy/uv_detail.jinja:86 pedagogy/tests.py:453
|
#: pedagogy/templates/pedagogy/uv_detail.jinja:86 pedagogy/tests.py:453
|
||||||
msgid ""
|
msgid ""
|
||||||
@@ -5268,23 +5284,23 @@ msgstr "Signaler ce commentaire"
|
|||||||
|
|
||||||
#: pedagogy/templates/pedagogy/uv_edit.jinja:4
|
#: pedagogy/templates/pedagogy/uv_edit.jinja:4
|
||||||
#: pedagogy/templates/pedagogy/uv_edit.jinja:8
|
#: pedagogy/templates/pedagogy/uv_edit.jinja:8
|
||||||
msgid "Edit UE"
|
msgid "Edit UV"
|
||||||
msgstr "Éditer l'UE"
|
msgstr "Éditer"
|
||||||
|
|
||||||
#: pedagogy/templates/pedagogy/uv_edit.jinja:27
|
#: pedagogy/templates/pedagogy/uv_edit.jinja:27
|
||||||
msgid "Import from UTBM"
|
msgid "Import from UTBM"
|
||||||
msgstr "Importer depuis l'UTBM"
|
msgstr "Importer depuis l'UTBM"
|
||||||
|
|
||||||
#: pedagogy/templates/pedagogy/uv_edit.jinja:62
|
#: pedagogy/templates/pedagogy/uv_edit.jinja:62
|
||||||
msgid "Unknown UE code"
|
msgid "Unknown UV code"
|
||||||
msgstr "Code d'UE inconnu"
|
msgstr "Code d'UV inconnu"
|
||||||
|
|
||||||
#: pedagogy/templates/pedagogy/uv_edit.jinja:77
|
#: pedagogy/templates/pedagogy/uv_edit.jinja:77
|
||||||
msgid "Successful autocomplete"
|
msgid "Successful autocomplete"
|
||||||
msgstr "Autocomplétion réussite"
|
msgstr "Autocomplétion réussite"
|
||||||
|
|
||||||
#: pedagogy/templates/pedagogy/uv_edit.jinja:80
|
#: pedagogy/templates/pedagogy/uv_edit.jinja:80
|
||||||
msgid "An error occurred: "
|
msgid "An error occured: "
|
||||||
msgstr "Une erreur est survenue : "
|
msgstr "Une erreur est survenue : "
|
||||||
|
|
||||||
#: rootplace/templates/rootplace/delete_user_messages.jinja:8
|
#: rootplace/templates/rootplace/delete_user_messages.jinja:8
|
||||||
@@ -5550,7 +5566,7 @@ msgstr "Automne et printemps"
|
|||||||
|
|
||||||
#: sith/settings.py:448
|
#: sith/settings.py:448
|
||||||
msgid "German"
|
msgid "German"
|
||||||
msgstr "Allemand"
|
msgstr "Allemant"
|
||||||
|
|
||||||
#: sith/settings.py:449
|
#: sith/settings.py:449
|
||||||
msgid "Spanish"
|
msgid "Spanish"
|
||||||
@@ -6346,3 +6362,11 @@ msgstr "Vous ne pouvez plus écrire de commentaires, la date est passée."
|
|||||||
#, python-format
|
#, python-format
|
||||||
msgid "Maximum characters: %(max_length)s"
|
msgid "Maximum characters: %(max_length)s"
|
||||||
msgstr "Nombre de caractères max: %(max_length)s"
|
msgstr "Nombre de caractères max: %(max_length)s"
|
||||||
|
|
||||||
|
#: eboutic/templates/eboutic/eboutic_main.jinja:127
|
||||||
|
msgid "Partnership Eurockéennes 2023"
|
||||||
|
msgstr "Partenariat Eurockéennes 2023"
|
||||||
|
|
||||||
|
#: eboutic/templates/eboutic/eboutic_main.jinja:137
|
||||||
|
msgid "You must be a subscriber to access the Eurockéennes ticketing service."
|
||||||
|
msgstr "Vous devez être cotisant pour pouvoir accéder à la billetterie des Eurockéennes."
|
||||||
|
|||||||
@@ -45,8 +45,8 @@
|
|||||||
|
|
||||||
<div class="radio-semester">
|
<div class="radio-semester">
|
||||||
<div class="radio-guide">
|
<div class="radio-guide">
|
||||||
<input type="checkbox" name="semester" id="radioAUTUMN" value="AUTUMN"><label for="radioAUTUMN"><i class="fa fa-leaf"></i></label>
|
<input type="checkbox" name="semester" id="radioAUTUMN" value="AUTUMN"><label for="radioAUTUMN"><i class="fa-solid fa-leaf"></i></label>
|
||||||
<input type="checkbox" name="semester" id="radioSPRING" value="SPRING"><label for="radioSPRING"><i class="fa fa-sun-o"></i></label>
|
<input type="checkbox" name="semester" id="radioSPRING" value="SPRING"><label for="radioSPRING"><i class="fa-solid fa-sun"></i></label>
|
||||||
<span><input type="checkbox" name="semester" id="radioAP" value="AUTUMN_AND_SPRING"><label for="radioAP">AP</label></span>
|
<span><input type="checkbox" name="semester" id="radioAP" value="AUTUMN_AND_SPRING"><label for="radioAP">AP</label></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,8 +60,8 @@
|
|||||||
<td>{% trans %}Title{% endtrans %}</td>
|
<td>{% trans %}Title{% endtrans %}</td>
|
||||||
<td>{% trans %}Department{% endtrans %}</td>
|
<td>{% trans %}Department{% endtrans %}</td>
|
||||||
<td>{% trans %}Credit type{% endtrans %}</td>
|
<td>{% trans %}Credit type{% endtrans %}</td>
|
||||||
<td><i class="fa fa-leaf"></i></td>
|
<td><i class="fa-solid fa-leaf"></i></td>
|
||||||
<td><i class="fa fa-sun-o"></i></td>
|
<td><i class="fa-solid fa-sun"></i></td>
|
||||||
{% if can_create_uv(user) %}
|
{% if can_create_uv(user) %}
|
||||||
<td>{% trans %}Edit{% endtrans %}</td>
|
<td>{% trans %}Edit{% endtrans %}</td>
|
||||||
<td>{% trans %}Delete{% endtrans %}</td>
|
<td>{% trans %}Delete{% endtrans %}</td>
|
||||||
@@ -77,12 +77,12 @@
|
|||||||
<td>{{ uv.credit_type }}</td>
|
<td>{{ uv.credit_type }}</td>
|
||||||
<td>
|
<td>
|
||||||
{% if uv.semester in ["AUTUMN", "AUTUMN_AND_SPRING"] %}
|
{% if uv.semester in ["AUTUMN", "AUTUMN_AND_SPRING"] %}
|
||||||
<i class="fa fa-leaf"></i>
|
<i class="fa-solid fa-leaf"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{% if uv.semester in ["SPRING", "AUTUMN_AND_SPRING"] %}
|
{% if uv.semester in ["SPRING", "AUTUMN_AND_SPRING"] %}
|
||||||
<i class="fa fa-sun-o"></i>
|
<i class="fa-solid fa-sun"></i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
{% if user.is_owner(uv) -%}
|
{% if user.is_owner(uv) -%}
|
||||||
@@ -107,9 +107,9 @@
|
|||||||
var autumn = "";
|
var autumn = "";
|
||||||
var spring = "";
|
var spring = "";
|
||||||
if (uv.semester == "AUTUMN" || uv.semester == "AUTUMN_AND_SPRING")
|
if (uv.semester == "AUTUMN" || uv.semester == "AUTUMN_AND_SPRING")
|
||||||
autumn = "<i class='fa fa-leaf'></i>";
|
autumn = "<i class='fa-solid fa-leaf'></i>";
|
||||||
if (uv.semester == "SPRING" || uv.semester == "AUTUMN_AND_SPRING")
|
if (uv.semester == "SPRING" || uv.semester == "AUTUMN_AND_SPRING")
|
||||||
spring = "<i class='fa fa-sun-o'></i>";
|
spring = "<i class='fa-solid fa-sun'></i>";
|
||||||
|
|
||||||
var html = `
|
var html = `
|
||||||
<tr onclick="window.location.href = '${uv.absolute_url}';">
|
<tr onclick="window.location.href = '${uv.absolute_url}';">
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
{% if grade >= 0 %}
|
{% if grade >= 0 %}
|
||||||
{% for i in range(5) %}
|
{% for i in range(5) %}
|
||||||
{% if i <= grade %}
|
{% if i <= grade %}
|
||||||
<span class="fa fa-star pedagogy star-checked grade-with-star"></span>
|
<span class="fa-solid fa-star pedagogy star-checked grade-with-star"></span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<span class="fa fa-star pedagogy star-not-checked grade-with-star"></span>
|
<span class="fa-solid fa-star pedagogy star-not-checked grade-with-star"></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<span class="pedagogy grade-without-star">{{ grade }}/5</span>
|
<span class="pedagogy grade-without-star">{{ grade }}/5</span>
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
stars[i].setAttribute("class", attrs + " unchecked");
|
stars[i].setAttribute("class", attrs + " unchecked");
|
||||||
}
|
}
|
||||||
' checked>
|
' checked>
|
||||||
<span class="fa fa-times-circle"> {{ translations.do_not_vote }}</span>
|
<span class="fa-solid fa-xmark-circle"> {{ translations.do_not_vote }}</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
{# Star widget #}
|
{# Star widget #}
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
'>
|
'>
|
||||||
<i class="{{ widget.name }} fa fa-star unchecked"></i>
|
<i class="{{ widget.name }} fa-solid fa-star unchecked"></i>
|
||||||
</label>
|
</label>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@
|
|||||||
<p>{{ object.skills|markdown }}</p>
|
<p>{{ object.skills|markdown }}</p>
|
||||||
<p><b>{% trans %}Key concepts{% endtrans %}</b></p>
|
<p><b>{% trans %}Key concepts{% endtrans %}</b></p>
|
||||||
<p>{{ object.key_concepts|markdown }}</p>
|
<p>{{ object.key_concepts|markdown }}</p>
|
||||||
<p><b>{% trans %}UE manager: {% endtrans %}</b>{{ object.manager }}</p>
|
<p><b>{% trans %}UV manager: {% endtrans %}</b>{{ object.manager }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@
|
|||||||
|
|
||||||
<div class="comment">
|
<div class="comment">
|
||||||
<div class="anchor">
|
<div class="anchor">
|
||||||
<a href="{{ url('pedagogy:uv_detail', uv_id=uv.id) }}#{{ comment.id }}"><i class="fa fa-paragraph"></i></a>
|
<a href="{{ url('pedagogy:uv_detail', uv_id=uv.id) }}#{{ comment.id }}"><i class="fa-solid fa-paragraph"></i></a>
|
||||||
</div>
|
</div>
|
||||||
{{ comment.comment|markdown }}
|
{{ comment.comment|markdown }}
|
||||||
</div>
|
</div>
|
||||||
@@ -206,8 +206,8 @@
|
|||||||
$("#return_noscript").hide();
|
$("#return_noscript").hide();
|
||||||
$("#return_js").show();
|
$("#return_js").show();
|
||||||
var icons = {
|
var icons = {
|
||||||
header: "fa fa-toggle-right",
|
header: "fa-solid fa-toggle-on",
|
||||||
activeHeader: "fa fa-toggle-down"
|
activeHeader: "fa-solid fa-toggle-off"
|
||||||
};
|
};
|
||||||
$(function(){
|
$(function(){
|
||||||
$("#leave_comment").accordion({
|
$("#leave_comment").accordion({
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{% extends "core/base.jinja" %}
|
{% extends "core/base.jinja" %}
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{% trans %}Edit UE{% endtrans %}
|
{% trans %}Edit UV{% endtrans %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h2>{% trans %}Edit UE{% endtrans %}</h2>
|
<h2>{% trans %}Edit UV{% endtrans %}</h2>
|
||||||
<form action="" method="post" enctype="multipart/form-data" id="uv_edit">
|
<form action="" method="post" enctype="multipart/form-data" id="uv_edit">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form.non_field_errors() }}
|
{{ form.non_field_errors() }}
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
url: url,
|
url: url,
|
||||||
success: function(data, _, xhr) {
|
success: function(data, _, xhr) {
|
||||||
if (xhr.status != 200) {
|
if (xhr.status != 200) {
|
||||||
createQuickNotif("{% trans %}Unknown UE code{% endtrans %}")
|
createQuickNotif("{% trans %}Unknown UV code{% endtrans %}")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for (let key in data) {
|
for (let key in data) {
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
createQuickNotif('{% trans %}Successful autocomplete{% endtrans %}')
|
createQuickNotif('{% trans %}Successful autocomplete{% endtrans %}')
|
||||||
},
|
},
|
||||||
error: function(_, _, statusMessage) {
|
error: function(_, _, statusMessage) {
|
||||||
createQuickNotif('{% trans %}An error occurred: {% endtrans %}' + statusMessage)
|
createQuickNotif('{% trans %}An error occured: {% endtrans %}' + statusMessage)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
140
poetry.lock
generated
140
poetry.lock
generated
@@ -1,9 +1,10 @@
|
|||||||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
# This file is automatically @generated by Poetry and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "alabaster"
|
name = "alabaster"
|
||||||
version = "0.7.12"
|
version = "0.7.12"
|
||||||
description = "A configurable sidebar-enabled Sphinx theme"
|
description = "A configurable sidebar-enabled Sphinx theme"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -15,6 +16,7 @@ files = [
|
|||||||
name = "appnope"
|
name = "appnope"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
description = "Disable App Nap on macOS >= 10.9"
|
description = "Disable App Nap on macOS >= 10.9"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -26,6 +28,7 @@ files = [
|
|||||||
name = "asgiref"
|
name = "asgiref"
|
||||||
version = "3.6.0"
|
version = "3.6.0"
|
||||||
description = "ASGI specs, helper code, and adapters"
|
description = "ASGI specs, helper code, and adapters"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -40,6 +43,7 @@ tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"]
|
|||||||
name = "babel"
|
name = "babel"
|
||||||
version = "2.11.0"
|
version = "2.11.0"
|
||||||
description = "Internationalization utilities"
|
description = "Internationalization utilities"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -54,6 +58,7 @@ pytz = ">=2015.7"
|
|||||||
name = "backcall"
|
name = "backcall"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
description = "Specifications for callback functions passed in to an API"
|
description = "Specifications for callback functions passed in to an API"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -65,6 +70,7 @@ files = [
|
|||||||
name = "black"
|
name = "black"
|
||||||
version = "23.3.0"
|
version = "23.3.0"
|
||||||
description = "The uncompromising code formatter."
|
description = "The uncompromising code formatter."
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -114,6 +120,7 @@ uvloop = ["uvloop (>=0.15.2)"]
|
|||||||
name = "certifi"
|
name = "certifi"
|
||||||
version = "2022.12.7"
|
version = "2022.12.7"
|
||||||
description = "Python package for providing Mozilla's CA Bundle."
|
description = "Python package for providing Mozilla's CA Bundle."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -125,6 +132,7 @@ files = [
|
|||||||
name = "cffi"
|
name = "cffi"
|
||||||
version = "1.15.1"
|
version = "1.15.1"
|
||||||
description = "Foreign Function Interface for Python calling C code."
|
description = "Foreign Function Interface for Python calling C code."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -201,6 +209,7 @@ pycparser = "*"
|
|||||||
name = "charset-normalizer"
|
name = "charset-normalizer"
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6.0"
|
python-versions = ">=3.6.0"
|
||||||
files = [
|
files = [
|
||||||
@@ -215,6 +224,7 @@ unicode-backport = ["unicodedata2"]
|
|||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.3"
|
version = "8.1.3"
|
||||||
description = "Composable command line interface toolkit"
|
description = "Composable command line interface toolkit"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -229,6 +239,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
|||||||
name = "colorama"
|
name = "colorama"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
description = "Cross-platform colored terminal text."
|
description = "Cross-platform colored terminal text."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -240,6 +251,7 @@ files = [
|
|||||||
name = "coverage"
|
name = "coverage"
|
||||||
version = "5.5"
|
version = "5.5"
|
||||||
description = "Code coverage measurement for Python"
|
description = "Code coverage measurement for Python"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
|
||||||
files = [
|
files = [
|
||||||
@@ -304,6 +316,7 @@ toml = ["toml"]
|
|||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
version = "40.0.1"
|
version = "40.0.1"
|
||||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -345,6 +358,7 @@ tox = ["tox"]
|
|||||||
name = "decorator"
|
name = "decorator"
|
||||||
version = "5.1.1"
|
version = "5.1.1"
|
||||||
description = "Decorators for Humans"
|
description = "Decorators for Humans"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
@@ -356,6 +370,7 @@ files = [
|
|||||||
name = "dict2xml"
|
name = "dict2xml"
|
||||||
version = "1.7.3"
|
version = "1.7.3"
|
||||||
description = "Small utility to convert a python dictionary into an XML string"
|
description = "Small utility to convert a python dictionary into an XML string"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
@@ -370,6 +385,7 @@ tests = ["noseofyeti[black] (==2.4.1)", "pytest (==7.2.1)"]
|
|||||||
name = "django"
|
name = "django"
|
||||||
version = "3.2.18"
|
version = "3.2.18"
|
||||||
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
|
description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -390,6 +406,7 @@ bcrypt = ["bcrypt"]
|
|||||||
name = "django-ajax-selects"
|
name = "django-ajax-selects"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
description = "Edit ForeignKey, ManyToManyField and CharField in Django Admin using jQuery UI AutoComplete."
|
description = "Edit ForeignKey, ManyToManyField and CharField in Django Admin using jQuery UI AutoComplete."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -400,6 +417,7 @@ files = [
|
|||||||
name = "django-countries"
|
name = "django-countries"
|
||||||
version = "7.5.1"
|
version = "7.5.1"
|
||||||
description = "Provides a country field for Django models."
|
description = "Provides a country field for Django models."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -421,6 +439,7 @@ test = ["djangorestframework", "graphene-django", "pytest", "pytest-cov", "pytes
|
|||||||
name = "django-debug-toolbar"
|
name = "django-debug-toolbar"
|
||||||
version = "4.0.0"
|
version = "4.0.0"
|
||||||
description = "A configurable set of panels that display various debug information about the current request/response."
|
description = "A configurable set of panels that display various debug information about the current request/response."
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
@@ -436,6 +455,7 @@ sqlparse = ">=0.2"
|
|||||||
name = "django-haystack"
|
name = "django-haystack"
|
||||||
version = "3.2.1"
|
version = "3.2.1"
|
||||||
description = "Pluggable search for Django."
|
description = "Pluggable search for Django."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -452,6 +472,7 @@ elasticsearch = ["elasticsearch (>=5,<8)"]
|
|||||||
name = "django-jinja"
|
name = "django-jinja"
|
||||||
version = "2.10.2"
|
version = "2.10.2"
|
||||||
description = "Jinja2 templating language integrated in Django."
|
description = "Jinja2 templating language integrated in Django."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -465,19 +486,21 @@ jinja2 = ">=3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-ordered-model"
|
name = "django-ordered-model"
|
||||||
version = "3.7.4"
|
version = "3.6"
|
||||||
description = "Allows Django models to be ordered and provides a simple admin interface for reordering them."
|
description = "Allows Django models to be ordered and provides a simple admin interface for reordering them."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
{file = "django-ordered-model-3.7.4.tar.gz", hash = "sha256:f258b9762525c00a53009e82f8b8bf2a3aa315e8b453e281e8fdbbfe2b8cb3ba"},
|
{file = "django-ordered-model-3.6.tar.gz", hash = "sha256:62161a6bc51d8b402644854b257605d7b5183d01fd349826682a87e9227c05b5"},
|
||||||
{file = "django_ordered_model-3.7.4-py3-none-any.whl", hash = "sha256:dfcd3183fe0749dad1c9971cba1d6240ce7328742a30ddc92feca41107bb241d"},
|
{file = "django_ordered_model-3.6-py3-none-any.whl", hash = "sha256:0006b111f472a2348f75554a4e77bee2b1f379a0f96726af6b1a3ebf3a950789"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django-phonenumber-field"
|
name = "django-phonenumber-field"
|
||||||
version = "6.4.0"
|
version = "6.4.0"
|
||||||
description = "An international phone number field for django models."
|
description = "An international phone number field for django models."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -496,6 +519,7 @@ phonenumberslite = ["phonenumberslite (>=7.0.2)"]
|
|||||||
name = "django-ranged-response"
|
name = "django-ranged-response"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
description = "Modified Django FileResponse that adds Content-Range headers."
|
description = "Modified Django FileResponse that adds Content-Range headers."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -509,6 +533,7 @@ django = "*"
|
|||||||
name = "django-simple-captcha"
|
name = "django-simple-captcha"
|
||||||
version = "0.5.17"
|
version = "0.5.17"
|
||||||
description = "A very simple, yet powerful, Django captcha application"
|
description = "A very simple, yet powerful, Django captcha application"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -528,6 +553,7 @@ test = ["testfixtures"]
|
|||||||
name = "djangorestframework"
|
name = "djangorestframework"
|
||||||
version = "3.14.0"
|
version = "3.14.0"
|
||||||
description = "Web APIs for Django, made easy."
|
description = "Web APIs for Django, made easy."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -543,6 +569,7 @@ pytz = "*"
|
|||||||
name = "docutils"
|
name = "docutils"
|
||||||
version = "0.17.1"
|
version = "0.17.1"
|
||||||
description = "Docutils -- Python Documentation Utilities"
|
description = "Docutils -- Python Documentation Utilities"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
files = [
|
files = [
|
||||||
@@ -550,24 +577,11 @@ files = [
|
|||||||
{file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"},
|
{file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "freezegun"
|
|
||||||
version = "1.2.2"
|
|
||||||
description = "Let your Python tests travel through time"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.6"
|
|
||||||
files = [
|
|
||||||
{file = "freezegun-1.2.2-py3-none-any.whl", hash = "sha256:ea1b963b993cb9ea195adbd893a48d573fda951b0da64f60883d7e988b606c9f"},
|
|
||||||
{file = "freezegun-1.2.2.tar.gz", hash = "sha256:cd22d1ba06941384410cd967d8a99d5ae2442f57dfafeff2fda5de8dc5c05446"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
python-dateutil = ">=2.7"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "3.4"
|
version = "3.4"
|
||||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
@@ -579,6 +593,7 @@ files = [
|
|||||||
name = "imagesize"
|
name = "imagesize"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
description = "Getting image size from png/jpeg/jpeg2000/gif file"
|
description = "Getting image size from png/jpeg/jpeg2000/gif file"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
files = [
|
files = [
|
||||||
@@ -590,6 +605,7 @@ files = [
|
|||||||
name = "importlib-metadata"
|
name = "importlib-metadata"
|
||||||
version = "6.0.0"
|
version = "6.0.0"
|
||||||
description = "Read metadata from Python packages"
|
description = "Read metadata from Python packages"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -609,6 +625,7 @@ testing = ["flake8 (<5)", "flufl.flake8", "importlib-resources (>=1.3)", "packag
|
|||||||
name = "ipython"
|
name = "ipython"
|
||||||
version = "7.34.0"
|
version = "7.34.0"
|
||||||
description = "IPython: Productive Interactive Computing"
|
description = "IPython: Productive Interactive Computing"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -645,6 +662,7 @@ test = ["ipykernel", "nbformat", "nose (>=0.10.1)", "numpy (>=1.17)", "pygments"
|
|||||||
name = "jedi"
|
name = "jedi"
|
||||||
version = "0.18.2"
|
version = "0.18.2"
|
||||||
description = "An autocompletion tool for Python that can be used for text editors."
|
description = "An autocompletion tool for Python that can be used for text editors."
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -664,6 +682,7 @@ testing = ["Django (<3.1)", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
|
|||||||
name = "jinja2"
|
name = "jinja2"
|
||||||
version = "3.1.2"
|
version = "3.1.2"
|
||||||
description = "A very fast and expressive template engine."
|
description = "A very fast and expressive template engine."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -681,6 +700,7 @@ i18n = ["Babel (>=2.7)"]
|
|||||||
name = "libsass"
|
name = "libsass"
|
||||||
version = "0.22.0"
|
version = "0.22.0"
|
||||||
description = "Sass for Python: A straightforward binding of libsass for Python."
|
description = "Sass for Python: A straightforward binding of libsass for Python."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -695,6 +715,7 @@ files = [
|
|||||||
name = "markupsafe"
|
name = "markupsafe"
|
||||||
version = "2.1.1"
|
version = "2.1.1"
|
||||||
description = "Safely add untrusted strings to HTML/XML markup."
|
description = "Safely add untrusted strings to HTML/XML markup."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -744,6 +765,7 @@ files = [
|
|||||||
name = "matplotlib-inline"
|
name = "matplotlib-inline"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
description = "Inline Matplotlib backend for Jupyter"
|
description = "Inline Matplotlib backend for Jupyter"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
@@ -758,6 +780,7 @@ traitlets = "*"
|
|||||||
name = "mistune"
|
name = "mistune"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
description = "The fastest markdown parser in pure Python"
|
description = "The fastest markdown parser in pure Python"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -769,6 +792,7 @@ files = [
|
|||||||
name = "mypy-extensions"
|
name = "mypy-extensions"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -780,6 +804,7 @@ files = [
|
|||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "23.0"
|
version = "23.0"
|
||||||
description = "Core utilities for Python packages"
|
description = "Core utilities for Python packages"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -791,6 +816,7 @@ files = [
|
|||||||
name = "parso"
|
name = "parso"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
description = "A Python Parser"
|
description = "A Python Parser"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -806,6 +832,7 @@ testing = ["docopt", "pytest (<6.0.0)"]
|
|||||||
name = "pathspec"
|
name = "pathspec"
|
||||||
version = "0.10.3"
|
version = "0.10.3"
|
||||||
description = "Utility library for gitignore style pattern matching of file paths."
|
description = "Utility library for gitignore style pattern matching of file paths."
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -817,6 +844,7 @@ files = [
|
|||||||
name = "pexpect"
|
name = "pexpect"
|
||||||
version = "4.8.0"
|
version = "4.8.0"
|
||||||
description = "Pexpect allows easy control of interactive console applications."
|
description = "Pexpect allows easy control of interactive console applications."
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -831,6 +859,7 @@ ptyprocess = ">=0.5"
|
|||||||
name = "phonenumbers"
|
name = "phonenumbers"
|
||||||
version = "8.13.4"
|
version = "8.13.4"
|
||||||
description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers."
|
description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -842,6 +871,7 @@ files = [
|
|||||||
name = "pickleshare"
|
name = "pickleshare"
|
||||||
version = "0.7.5"
|
version = "0.7.5"
|
||||||
description = "Tiny 'shelve'-like database with concurrency support"
|
description = "Tiny 'shelve'-like database with concurrency support"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -853,6 +883,7 @@ files = [
|
|||||||
name = "pillow"
|
name = "pillow"
|
||||||
version = "9.4.0"
|
version = "9.4.0"
|
||||||
description = "Python Imaging Library (Fork)"
|
description = "Python Imaging Library (Fork)"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -943,6 +974,7 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
|
|||||||
name = "platformdirs"
|
name = "platformdirs"
|
||||||
version = "2.6.2"
|
version = "2.6.2"
|
||||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -958,6 +990,7 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-
|
|||||||
name = "prompt-toolkit"
|
name = "prompt-toolkit"
|
||||||
version = "3.0.36"
|
version = "3.0.36"
|
||||||
description = "Library for building powerful interactive command lines in Python"
|
description = "Library for building powerful interactive command lines in Python"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6.2"
|
python-versions = ">=3.6.2"
|
||||||
files = [
|
files = [
|
||||||
@@ -972,6 +1005,7 @@ wcwidth = "*"
|
|||||||
name = "psycopg2-binary"
|
name = "psycopg2-binary"
|
||||||
version = "2.9.3"
|
version = "2.9.3"
|
||||||
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -1040,6 +1074,7 @@ files = [
|
|||||||
name = "ptyprocess"
|
name = "ptyprocess"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
description = "Run a subprocess in a pseudo terminal"
|
description = "Run a subprocess in a pseudo terminal"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -1051,6 +1086,7 @@ files = [
|
|||||||
name = "pycparser"
|
name = "pycparser"
|
||||||
version = "2.21"
|
version = "2.21"
|
||||||
description = "C parser in Python"
|
description = "C parser in Python"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||||
files = [
|
files = [
|
||||||
@@ -1062,6 +1098,7 @@ files = [
|
|||||||
name = "pygments"
|
name = "pygments"
|
||||||
version = "2.14.0"
|
version = "2.14.0"
|
||||||
description = "Pygments is a syntax highlighting package written in Python."
|
description = "Pygments is a syntax highlighting package written in Python."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -1076,6 +1113,7 @@ plugins = ["importlib-metadata"]
|
|||||||
name = "pygraphviz"
|
name = "pygraphviz"
|
||||||
version = "1.10"
|
version = "1.10"
|
||||||
description = "Python interface to Graphviz"
|
description = "Python interface to Graphviz"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
@@ -1086,6 +1124,7 @@ files = [
|
|||||||
name = "pyopenssl"
|
name = "pyopenssl"
|
||||||
version = "23.1.1"
|
version = "23.1.1"
|
||||||
description = "Python wrapper module around the OpenSSL library"
|
description = "Python wrapper module around the OpenSSL library"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -1104,6 +1143,7 @@ test = ["flaky", "pretend", "pytest (>=3.0.1)"]
|
|||||||
name = "python-dateutil"
|
name = "python-dateutil"
|
||||||
version = "2.8.2"
|
version = "2.8.2"
|
||||||
description = "Extensions to the standard Python datetime module"
|
description = "Extensions to the standard Python datetime module"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -1118,6 +1158,7 @@ six = ">=1.5"
|
|||||||
name = "pytz"
|
name = "pytz"
|
||||||
version = "2021.3"
|
version = "2021.3"
|
||||||
description = "World timezone definitions, modern and historical"
|
description = "World timezone definitions, modern and historical"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -1129,6 +1170,7 @@ files = [
|
|||||||
name = "reportlab"
|
name = "reportlab"
|
||||||
version = "3.6.12"
|
version = "3.6.12"
|
||||||
description = "The Reportlab Toolkit"
|
description = "The Reportlab Toolkit"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7,<4"
|
python-versions = ">=3.7,<4"
|
||||||
files = [
|
files = [
|
||||||
@@ -1190,6 +1232,7 @@ rlpycairo = ["rlPyCairo (>=0.1.0)"]
|
|||||||
name = "requests"
|
name = "requests"
|
||||||
version = "2.28.1"
|
version = "2.28.1"
|
||||||
description = "Python HTTP for Humans."
|
description = "Python HTTP for Humans."
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7, <4"
|
python-versions = ">=3.7, <4"
|
||||||
files = [
|
files = [
|
||||||
@@ -1211,6 +1254,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
|||||||
name = "sentry-sdk"
|
name = "sentry-sdk"
|
||||||
version = "1.21.0"
|
version = "1.21.0"
|
||||||
description = "Python client for Sentry (https://sentry.io)"
|
description = "Python client for Sentry (https://sentry.io)"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -1252,6 +1296,7 @@ tornado = ["tornado (>=5)"]
|
|||||||
name = "setuptools"
|
name = "setuptools"
|
||||||
version = "65.6.3"
|
version = "65.6.3"
|
||||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -1268,6 +1313,7 @@ testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (
|
|||||||
name = "six"
|
name = "six"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
description = "Python 2 and 3 compatibility utilities"
|
description = "Python 2 and 3 compatibility utilities"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
files = [
|
files = [
|
||||||
@@ -1279,6 +1325,7 @@ files = [
|
|||||||
name = "snowballstemmer"
|
name = "snowballstemmer"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
|
description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms."
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -1290,6 +1337,7 @@ files = [
|
|||||||
name = "sphinx"
|
name = "sphinx"
|
||||||
version = "4.5.0"
|
version = "4.5.0"
|
||||||
description = "Python documentation generator"
|
description = "Python documentation generator"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -1325,6 +1373,7 @@ test = ["cython", "html5lib", "pytest", "pytest-cov", "typed-ast"]
|
|||||||
name = "sphinx-copybutton"
|
name = "sphinx-copybutton"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
description = "Add a copy button to each of your code cells."
|
description = "Add a copy button to each of your code cells."
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -1343,6 +1392,7 @@ rtd = ["ipython", "sphinx", "sphinx-book-theme"]
|
|||||||
name = "sphinx-rtd-theme"
|
name = "sphinx-rtd-theme"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
description = "Read the Docs theme for Sphinx"
|
description = "Read the Docs theme for Sphinx"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -1361,6 +1411,7 @@ dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"]
|
|||||||
name = "sphinxcontrib-applehelp"
|
name = "sphinxcontrib-applehelp"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
|
description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
@@ -1376,6 +1427,7 @@ test = ["pytest"]
|
|||||||
name = "sphinxcontrib-devhelp"
|
name = "sphinxcontrib-devhelp"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
|
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document."
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
@@ -1391,6 +1443,7 @@ test = ["pytest"]
|
|||||||
name = "sphinxcontrib-htmlhelp"
|
name = "sphinxcontrib-htmlhelp"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
|
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
files = [
|
files = [
|
||||||
@@ -1406,6 +1459,7 @@ test = ["html5lib", "pytest"]
|
|||||||
name = "sphinxcontrib-jsmath"
|
name = "sphinxcontrib-jsmath"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
description = "A sphinx extension which renders display math in HTML via JavaScript"
|
description = "A sphinx extension which renders display math in HTML via JavaScript"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
@@ -1420,6 +1474,7 @@ test = ["flake8", "mypy", "pytest"]
|
|||||||
name = "sphinxcontrib-qthelp"
|
name = "sphinxcontrib-qthelp"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
|
description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document."
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
@@ -1435,6 +1490,7 @@ test = ["pytest"]
|
|||||||
name = "sphinxcontrib-serializinghtml"
|
name = "sphinxcontrib-serializinghtml"
|
||||||
version = "1.1.5"
|
version = "1.1.5"
|
||||||
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
|
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)."
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
@@ -1448,24 +1504,21 @@ test = ["pytest"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sqlparse"
|
name = "sqlparse"
|
||||||
version = "0.4.4"
|
version = "0.4.3"
|
||||||
description = "A non-validating SQL parser."
|
description = "A non-validating SQL parser."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.5"
|
python-versions = ">=3.5"
|
||||||
files = [
|
files = [
|
||||||
{file = "sqlparse-0.4.4-py3-none-any.whl", hash = "sha256:5430a4fe2ac7d0f93e66f1efc6e1338a41884b7ddf2a350cedd20ccc4d9d28f3"},
|
{file = "sqlparse-0.4.3-py3-none-any.whl", hash = "sha256:0323c0ec29cd52bceabc1b4d9d579e311f3e4961b98d174201d5622a23b85e34"},
|
||||||
{file = "sqlparse-0.4.4.tar.gz", hash = "sha256:d446183e84b8349fa3061f0fe7f06ca94ba65b426946ffebe6e3e8295332420c"},
|
{file = "sqlparse-0.4.3.tar.gz", hash = "sha256:69ca804846bb114d2ec380e4360a8a340db83f0ccf3afceeb1404df028f57268"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
dev = ["build", "flake8"]
|
|
||||||
doc = ["sphinx"]
|
|
||||||
test = ["pytest", "pytest-cov"]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tomli"
|
name = "tomli"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
description = "A lil' TOML parser"
|
description = "A lil' TOML parser"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -1477,6 +1530,7 @@ files = [
|
|||||||
name = "traitlets"
|
name = "traitlets"
|
||||||
version = "5.8.1"
|
version = "5.8.1"
|
||||||
description = "Traitlets Python configuration system"
|
description = "Traitlets Python configuration system"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -1492,6 +1546,7 @@ test = ["argcomplete (>=2.0)", "pre-commit", "pytest", "pytest-mock"]
|
|||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.4.0"
|
version = "4.4.0"
|
||||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -1503,6 +1558,7 @@ files = [
|
|||||||
name = "urllib3"
|
name = "urllib3"
|
||||||
version = "1.26.13"
|
version = "1.26.13"
|
||||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||||
|
category = "main"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
|
||||||
files = [
|
files = [
|
||||||
@@ -1519,6 +1575,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
|||||||
name = "wcwidth"
|
name = "wcwidth"
|
||||||
version = "0.2.5"
|
version = "0.2.5"
|
||||||
description = "Measures the displayed width of unicode strings in a terminal"
|
description = "Measures the displayed width of unicode strings in a terminal"
|
||||||
|
category = "dev"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
files = [
|
files = [
|
||||||
@@ -1526,10 +1583,37 @@ files = [
|
|||||||
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
|
{file = "wcwidth-0.2.5.tar.gz", hash = "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xapian-bindings"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Meta-package to build and install xapian-bindings extension."
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "xapian-bindings-0.1.0.tar.gz", hash = "sha256:f2b0396082ebf4f6681ab43d6d8fd1f63b6964b18c32c91236ed067c6f62ad14"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xapian-haystack"
|
||||||
|
version = "3.0.1"
|
||||||
|
description = "A Xapian backend for Haystack"
|
||||||
|
category = "main"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "xapian-haystack-3.0.1.tar.gz", hash = "sha256:a5c0e1262b95008df4dfeb58d093c654acee3f2b27ea3f7d366900895cdc70f9"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
django = ">=2.2"
|
||||||
|
django-haystack = ">=2.8.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zipp"
|
name = "zipp"
|
||||||
version = "3.11.0"
|
version = "3.11.0"
|
||||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||||
|
category = "main"
|
||||||
optional = true
|
optional = true
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
@@ -1542,10 +1626,10 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker
|
|||||||
testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=1.3)", "pytest-flake8", "pytest-mypy (>=0.9.1)"]
|
||||||
|
|
||||||
[extras]
|
[extras]
|
||||||
docs = ["Sphinx", "sphinx-copybutton", "sphinx-rtd-theme"]
|
docs = ["Sphinx", "sphinx-rtd-theme", "sphinx-copybutton"]
|
||||||
testing = ["coverage"]
|
testing = ["coverage"]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.8"
|
python-versions = "^3.8"
|
||||||
content-hash = "32bf0229e7ac812ea278a36587c184cd4ae507f87816f573447e85cd5312e52c"
|
content-hash = "95b9a07660bd8f95a5a90cc273071a675d884424479cd1ed922438dc767d230a"
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ phonenumbers = "^8.12"
|
|||||||
django-ajax-selects = "^2.1.0"
|
django-ajax-selects = "^2.1.0"
|
||||||
reportlab = "^3.6"
|
reportlab = "^3.6"
|
||||||
django-haystack = "^3.2.1"
|
django-haystack = "^3.2.1"
|
||||||
|
xapian-haystack = "^3.0.1"
|
||||||
|
xapian-bindings = "^0.1.0"
|
||||||
libsass = "^0.22"
|
libsass = "^0.22"
|
||||||
django-ordered-model = "^3.7"
|
django-ordered-model = "^3.6"
|
||||||
django-simple-captcha = "^0.5.17"
|
django-simple-captcha = "^0.5.17"
|
||||||
python-dateutil = "^2.8.2"
|
python-dateutil = "^2.8.2"
|
||||||
psycopg2-binary = "2.9.3"
|
psycopg2-binary = "2.9.3"
|
||||||
@@ -57,7 +59,6 @@ testing = ["coverage"]
|
|||||||
docs = ["Sphinx", "sphinx-rtd-theme", "sphinx-copybutton"]
|
docs = ["Sphinx", "sphinx-rtd-theme", "sphinx-copybutton"]
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
freezegun = "^1.2.2" # used to test time-dependent code
|
|
||||||
django-debug-toolbar = "^4.0.0"
|
django-debug-toolbar = "^4.0.0"
|
||||||
ipython = "^7.28.0"
|
ipython = "^7.28.0"
|
||||||
black = "^23.3.0"
|
black = "^23.3.0"
|
||||||
|
|||||||
@@ -191,9 +191,9 @@ TEMPLATES = [
|
|||||||
|
|
||||||
HAYSTACK_CONNECTIONS = {
|
HAYSTACK_CONNECTIONS = {
|
||||||
"default": {
|
"default": {
|
||||||
"ENGINE": "haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine",
|
"ENGINE": "xapian_backend.XapianEngine",
|
||||||
'URL': 'http://localhost:9200/',
|
"PATH": os.path.join(os.path.dirname(__file__), "search_indexes", "xapian"),
|
||||||
'INDEX_NAME': 'haystack',
|
"INCLUDE_SPELLING": True,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,8 +327,7 @@ SITH_CLUB_ROOT_PAGE = "clubs"
|
|||||||
|
|
||||||
# Define the date in the year serving as reference for the subscriptions calendar
|
# Define the date in the year serving as reference for the subscriptions calendar
|
||||||
# (month, day)
|
# (month, day)
|
||||||
SITH_SEMESTER_START_AUTUMN = (8, 15) # 15 August
|
SITH_START_DATE = (8, 15) # 15th August
|
||||||
SITH_SEMESTER_START_SPRING = (2, 15) # 15 February
|
|
||||||
|
|
||||||
# Used to determine the valid promos
|
# Used to determine the valid promos
|
||||||
SITH_SCHOOL_START_YEAR = 1999
|
SITH_SCHOOL_START_YEAR = 1999
|
||||||
@@ -715,7 +714,7 @@ SITH_FRONT_DEP_VERSIONS = {
|
|||||||
"https://github.com/chartjs/Chart.js/": "2.6.0",
|
"https://github.com/chartjs/Chart.js/": "2.6.0",
|
||||||
"https://github.com/xdan/datetimepicker/": "2.5.21",
|
"https://github.com/xdan/datetimepicker/": "2.5.21",
|
||||||
"https://github.com/Ionaru/easy-markdown-editor/": "2.18.0",
|
"https://github.com/Ionaru/easy-markdown-editor/": "2.18.0",
|
||||||
"https://github.com/FortAwesome/Font-Awesome/": "4.7.0",
|
"https://github.com/FortAwesome/Font-Awesome/": "6.4.0",
|
||||||
"https://github.com/jquery/jquery/": "3.6.2",
|
"https://github.com/jquery/jquery/": "3.6.2",
|
||||||
"https://github.com/sethmcl/jquery-ui/": "1.11.1",
|
"https://github.com/sethmcl/jquery-ui/": "1.11.1",
|
||||||
"https://github.com/viralpatel/jquery.shorten/": "",
|
"https://github.com/viralpatel/jquery.shorten/": "",
|
||||||
|
|||||||
@@ -114,12 +114,12 @@ class Subscription(models.Model):
|
|||||||
return "No user - " + str(self.pk)
|
return "No user - " + str(self.pk)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def compute_start(d: date = None, duration: int = 1, user: User = None) -> date:
|
def compute_start(d=None, duration=1, user=None):
|
||||||
"""
|
"""
|
||||||
This function computes the start date of the subscription with respect to the given date (default is today),
|
This function computes the start date of the subscription with respect to the given date (default is today),
|
||||||
and the start date given in settings.SITH_SEMESTER_START_AUTUMN.
|
and the start date given in settings.SITH_START_DATE.
|
||||||
It takes the nearest past start date.
|
It takes the nearest past start date.
|
||||||
Exemples: with SITH_SEMESTER_START_AUTUMN = (8, 15)
|
Exemples: with SITH_START_DATE = (8, 15)
|
||||||
Today -> Start date
|
Today -> Start date
|
||||||
2015-03-17 -> 2015-02-15
|
2015-03-17 -> 2015-02-15
|
||||||
2015-01-11 -> 2014-08-15
|
2015-01-11 -> 2014-08-15
|
||||||
@@ -135,9 +135,9 @@ class Subscription(models.Model):
|
|||||||
return get_start_of_semester(d)
|
return get_start_of_semester(d)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def compute_end(duration: int, start: date = None, user: User = None) -> date:
|
def compute_end(duration, start=None, user=None):
|
||||||
"""
|
"""
|
||||||
This function compute the end date of the subscription given a start date and a duration in number of semester
|
This function compute the end date of the subscription given a start date and a duration in number of semestre
|
||||||
Exemple:
|
Exemple:
|
||||||
Start - Duration -> End date
|
Start - Duration -> End date
|
||||||
2015-09-18 - 1 -> 2016-03-18
|
2015-09-18 - 1 -> 2016-03-18
|
||||||
@@ -153,7 +153,7 @@ class Subscription(models.Model):
|
|||||||
days=math.ceil((6 * duration - round(6 * duration)) * 30),
|
days=math.ceil((6 * duration - round(6 * duration)) * 30),
|
||||||
)
|
)
|
||||||
|
|
||||||
def can_be_edited_by(self, user: User):
|
def can_be_edited_by(self, user):
|
||||||
return user.is_board_member or user.is_root
|
return user.is_board_member or user.is_root
|
||||||
|
|
||||||
def is_valid_now(self):
|
def is_valid_now(self):
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ from django.core.exceptions import ValidationError
|
|||||||
from datetime import timedelta, date
|
from datetime import timedelta, date
|
||||||
|
|
||||||
from core.models import User
|
from core.models import User
|
||||||
from core.utils import get_start_of_semester, get_semester_code
|
from core.utils import get_start_of_semester, get_semester
|
||||||
from club.models import Club
|
from club.models import Club
|
||||||
|
|
||||||
|
|
||||||
@@ -164,14 +164,14 @@ class TrombiUser(models.Model):
|
|||||||
if m.description:
|
if m.description:
|
||||||
role += " (%s)" % m.description
|
role += " (%s)" % m.description
|
||||||
if m.end_date:
|
if m.end_date:
|
||||||
end_date = get_semester_code(m.end_date)
|
end_date = get_semester(m.end_date)
|
||||||
else:
|
else:
|
||||||
end_date = ""
|
end_date = ""
|
||||||
TrombiClubMembership(
|
TrombiClubMembership(
|
||||||
user=self,
|
user=self,
|
||||||
club=str(m.club),
|
club=str(m.club),
|
||||||
role=role[:64],
|
role=role[:64],
|
||||||
start=get_semester_code(m.start_date),
|
start=get_semester(m.start_date),
|
||||||
end=end_date,
|
end=end_date,
|
||||||
).save()
|
).save()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user