First commit
This commit is contained in:
commit
a1ae3e9134
|
@ -0,0 +1,26 @@
|
|||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
steps:
|
||||
- name: build
|
||||
image: python:3.9-slim
|
||||
commands:
|
||||
- pip install -r requirements/ci.txt
|
||||
- pylint ultron --errors-only
|
||||
- name: discord notification
|
||||
image: appleboy/drone-discord
|
||||
settings:
|
||||
webhook_id:
|
||||
from_secret: discord_webhook_id
|
||||
webhook_token:
|
||||
from_secret: discord_webhook_token
|
||||
message: >
|
||||
{{#success build.status}}
|
||||
Ultron build {{build.number}} succeeded. Good job.
|
||||
{{else}}
|
||||
Ultron build {{build.number}} failed. Fix me please. More info : https://drone.grimbox.be/Sulley/Ultron/{{build.number}}
|
||||
{{/success}}
|
||||
when:
|
||||
status:
|
||||
- failure
|
||||
- success
|
|
@ -0,0 +1,43 @@
|
|||
# Django #
|
||||
*.log
|
||||
*.pot
|
||||
*.pyc
|
||||
__pycache__
|
||||
db.sqlite3
|
||||
*.sql
|
||||
media
|
||||
*.yaml
|
||||
*.json
|
||||
|
||||
# Python #
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
data/
|
||||
|
||||
# Visual Studio Code #
|
||||
.vscode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history
|
||||
|
||||
# Mac OS
|
||||
.DS_Store
|
||||
|
||||
# Project Specific
|
||||
static/js/plugins/fullcalendar/locales/*
|
||||
static/js/plugins/fullcalendar/locales-all.js
|
||||
static/js/plugins/fullcalendar/locales-all.min.js
|
||||
|
||||
*.db
|
|
@ -0,0 +1,575 @@
|
|||
[MASTER]
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code.
|
||||
extension-pkg-allow-list=
|
||||
|
||||
# A comma-separated list of package or module names from where C extensions may
|
||||
# be loaded. Extensions are loading into the active Python interpreter and may
|
||||
# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
|
||||
# for backward compatibility.)
|
||||
extension-pkg-whitelist=
|
||||
|
||||
# Return non-zero exit code if any of these messages/categories are detected,
|
||||
# even if score is above --fail-under value. Syntax same as enable. Messages
|
||||
# specified are enabled, while categories only check already-enabled messages.
|
||||
fail-on=
|
||||
|
||||
# Specify a score threshold to be exceeded before program exits with error.
|
||||
fail-under=10.0
|
||||
|
||||
# Files or directories to be skipped. They should be base names, not paths.
|
||||
ignore=CVS
|
||||
|
||||
# Add files or directories matching the regex patterns to the ignore-list. The
|
||||
# regex matches against paths and can be in Posix or Windows format.
|
||||
ignore-paths=
|
||||
|
||||
# Files or directories matching the regex patterns are skipped. The regex
|
||||
# matches against base names, not paths.
|
||||
ignore-patterns=
|
||||
|
||||
# Python code to execute, usually for sys.path manipulation such as
|
||||
# pygtk.require().
|
||||
init-hook=sys.path.append(".")
|
||||
|
||||
# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
|
||||
# number of processors available to use.
|
||||
jobs=1
|
||||
|
||||
# Control the amount of potential inferred values when inferring a single
|
||||
# object. This can help the performance when dealing with large functions or
|
||||
# complex, nested conditions.
|
||||
limit-inference-results=100
|
||||
|
||||
# List of plugins (as comma separated values of python module names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=pylint_django
|
||||
|
||||
django-settings-module=config.settings
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# Minimum Python version to use for version dependent checks. Will default to
|
||||
# the version used to run pylint.
|
||||
py-version=3.9
|
||||
|
||||
# When enabled, pylint would attempt to guess common misconfiguration and emit
|
||||
# user-friendly hints instead of false-positive error messages.
|
||||
suggestion-mode=yes
|
||||
|
||||
# Allow loading of arbitrary C extensions. Extensions are imported into the
|
||||
# active Python interpreter and may run arbitrary code.
|
||||
unsafe-load-any-extension=no
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Only show warnings with the listed confidence levels. Leave empty to show
|
||||
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
|
||||
confidence=
|
||||
|
||||
# Disable the message, report, category or checker with the given id(s). You
|
||||
# can either give multiple identifiers separated by comma (,) or put this
|
||||
# option multiple times (only on the command line, not in the configuration
|
||||
# file where it should appear only once). You can also use "--disable=all" to
|
||||
# disable everything first and then reenable specific checks. For example, if
|
||||
# you want to run only the similarities checker, you can use "--disable=all
|
||||
# --enable=similarities". If you want to run only the classes checker, but have
|
||||
# no Warning level messages displayed, use "--disable=all --enable=classes
|
||||
# --disable=W".
|
||||
disable=raw-checker-failed,
|
||||
bad-inline-option,
|
||||
locally-disabled,
|
||||
file-ignored,
|
||||
suppressed-message,
|
||||
useless-suppression,
|
||||
deprecated-pragma,
|
||||
use-symbolic-message-instead,
|
||||
empty-docstring,
|
||||
missing-class-docstring,
|
||||
missing-module-docstring,
|
||||
missing-function-docstring,
|
||||
consider-using-f-string,
|
||||
duplicate-code,
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
# multiple time (only on the command line, not in the configuration file where
|
||||
# it should appear only once). See also the "--disable" option for examples.
|
||||
enable=c-extension-no-member
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# Python expression which should return a score less than or equal to 10. You
|
||||
# have access to the variables 'error', 'warning', 'refactor', and 'convention'
|
||||
# which contain the number of messages in each category, as well as 'statement'
|
||||
# which is the total number of statements analyzed. This score is used by the
|
||||
# global evaluation report (RP0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Template used to display messages. This is a python new-style format string
|
||||
# used to format the message information. See doc for all details.
|
||||
#msg-template=
|
||||
|
||||
# Set the output format. Available formats are text, parseable, colorized, json
|
||||
# and msvs (visual studio). You can also give a reporter class, e.g.
|
||||
# mypackage.mymodule.MyReporterClass.
|
||||
output-format=text
|
||||
|
||||
# Tells whether to display a full report or only the messages.
|
||||
reports=no
|
||||
|
||||
# Activate the evaluation score.
|
||||
score=yes
|
||||
|
||||
|
||||
[REFACTORING]
|
||||
|
||||
# Maximum number of nested blocks for function / method body
|
||||
max-nested-blocks=5
|
||||
|
||||
# Complete name of functions that never returns. When checking for
|
||||
# inconsistent-return-statements if a never returning function is called then
|
||||
# it will be considered as an explicit return statement and no message will be
|
||||
# printed.
|
||||
never-returning-functions=sys.exit,argparse.parse_error
|
||||
|
||||
|
||||
[FORMAT]
|
||||
|
||||
# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
|
||||
expected-line-ending-format=
|
||||
|
||||
# Regexp for a line that is allowed to be longer than the limit.
|
||||
ignore-long-lines=^\s*(# )?<?https?://\S+>?$
|
||||
|
||||
# Number of spaces of indent required inside a hanging or continued line.
|
||||
indent-after-paren=4
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=100
|
||||
|
||||
# Maximum number of lines in a module.
|
||||
max-module-lines=1000
|
||||
|
||||
# Allow the body of a class to be on the same line as the declaration if body
|
||||
# contains single statement.
|
||||
single-line-class-stmt=no
|
||||
|
||||
# Allow the body of an if to be on the same line as the test if there is no
|
||||
# else.
|
||||
single-line-if-stmt=no
|
||||
|
||||
|
||||
[VARIABLES]
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid defining new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
# Tells whether unused global variables should be treated as a violation.
|
||||
allow-global-unused-variables=yes
|
||||
|
||||
# List of names allowed to shadow builtins
|
||||
allowed-redefined-builtins=
|
||||
|
||||
# List of strings which can identify a callback function by name. A callback
|
||||
# name must start or end with one of those strings.
|
||||
callbacks=cb_,
|
||||
_cb
|
||||
|
||||
# A regular expression matching the name of dummy variables (i.e. expected to
|
||||
# not be used).
|
||||
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
|
||||
|
||||
# Argument names that match this expression will be ignored. Default to name
|
||||
# with leading underscore.
|
||||
ignored-argument-names=_.*|^ignored_|^unused_
|
||||
|
||||
# Tells whether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# List of qualified module names which can have objects that can redefine
|
||||
# builtins.
|
||||
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
|
||||
|
||||
|
||||
[SIMILARITIES]
|
||||
|
||||
# Comments are removed from the similarity computation
|
||||
ignore-comments=yes
|
||||
|
||||
# Docstrings are removed from the similarity computation
|
||||
ignore-docstrings=yes
|
||||
|
||||
# Imports are removed from the similarity computation
|
||||
ignore-imports=no
|
||||
|
||||
# Signatures are removed from the similarity computation
|
||||
ignore-signatures=no
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=4
|
||||
|
||||
|
||||
[BASIC]
|
||||
|
||||
# Naming style matching correct argument names.
|
||||
argument-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct argument names. Overrides argument-
|
||||
# naming-style.
|
||||
#argument-rgx=
|
||||
|
||||
# Naming style matching correct attribute names.
|
||||
attr-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct attribute names. Overrides attr-naming-
|
||||
# style.
|
||||
#attr-rgx=
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma.
|
||||
bad-names=foo,
|
||||
bar,
|
||||
baz,
|
||||
toto,
|
||||
tutu,
|
||||
tata
|
||||
|
||||
# Bad variable names regexes, separated by a comma. If names match any regex,
|
||||
# they will always be refused
|
||||
bad-names-rgxs=
|
||||
|
||||
# Naming style matching correct class attribute names.
|
||||
class-attribute-naming-style=any
|
||||
|
||||
# Regular expression matching correct class attribute names. Overrides class-
|
||||
# attribute-naming-style.
|
||||
#class-attribute-rgx=
|
||||
|
||||
# Naming style matching correct class constant names.
|
||||
class-const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct class constant names. Overrides class-
|
||||
# const-naming-style.
|
||||
#class-const-rgx=
|
||||
|
||||
# Naming style matching correct class names.
|
||||
class-naming-style=PascalCase
|
||||
|
||||
# Regular expression matching correct class names. Overrides class-naming-
|
||||
# style.
|
||||
#class-rgx=
|
||||
|
||||
# Naming style matching correct constant names.
|
||||
const-naming-style=UPPER_CASE
|
||||
|
||||
# Regular expression matching correct constant names. Overrides const-naming-
|
||||
# style.
|
||||
#const-rgx=
|
||||
|
||||
# Minimum line length for functions/classes that require docstrings, shorter
|
||||
# ones are exempt.
|
||||
docstring-min-length=-1
|
||||
|
||||
# Naming style matching correct function names.
|
||||
function-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct function names. Overrides function-
|
||||
# naming-style.
|
||||
#function-rgx=
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma.
|
||||
good-names=i,
|
||||
j,
|
||||
k,
|
||||
ex,
|
||||
Run,
|
||||
_
|
||||
|
||||
# Good variable names regexes, separated by a comma. If names match any regex,
|
||||
# they will always be accepted
|
||||
good-names-rgxs=
|
||||
|
||||
# Include a hint for the correct naming format with invalid-name.
|
||||
include-naming-hint=no
|
||||
|
||||
# Naming style matching correct inline iteration names.
|
||||
inlinevar-naming-style=any
|
||||
|
||||
# Regular expression matching correct inline iteration names. Overrides
|
||||
# inlinevar-naming-style.
|
||||
#inlinevar-rgx=
|
||||
|
||||
# Naming style matching correct method names.
|
||||
method-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct method names. Overrides method-naming-
|
||||
# style.
|
||||
#method-rgx=
|
||||
|
||||
# Naming style matching correct module names.
|
||||
module-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct module names. Overrides module-naming-
|
||||
# style.
|
||||
#module-rgx=
|
||||
|
||||
# Colon-delimited sets of names that determine each other's naming style when
|
||||
# the name regexes allow several styles.
|
||||
name-group=
|
||||
|
||||
# Regular expression which should only match function or class names that do
|
||||
# not require a docstring.
|
||||
no-docstring-rgx=^_
|
||||
|
||||
# List of decorators that produce properties, such as abc.abstractproperty. Add
|
||||
# to this list to register other decorators that produce valid properties.
|
||||
# These decorators are taken in consideration only for invalid-name.
|
||||
property-classes=abc.abstractproperty
|
||||
|
||||
# Naming style matching correct variable names.
|
||||
variable-naming-style=snake_case
|
||||
|
||||
# Regular expression matching correct variable names. Overrides variable-
|
||||
# naming-style.
|
||||
#variable-rgx=
|
||||
|
||||
|
||||
[SPELLING]
|
||||
|
||||
# Limits count of emitted suggestions for spelling mistakes.
|
||||
max-spelling-suggestions=4
|
||||
|
||||
# Spelling dictionary name. Available dictionaries: none. To make it work,
|
||||
# install the 'python-enchant' package.
|
||||
spelling-dict=
|
||||
|
||||
# List of comma separated words that should be considered directives if they
|
||||
# appear and the beginning of a comment and should not be checked.
|
||||
spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
|
||||
|
||||
# List of comma separated words that should not be checked.
|
||||
spelling-ignore-words=
|
||||
|
||||
# A path to a file that contains the private dictionary; one word per line.
|
||||
spelling-private-dict-file=
|
||||
|
||||
# Tells whether to store unknown words to the private dictionary (see the
|
||||
# --spelling-private-dict-file option) instead of raising a message.
|
||||
spelling-store-unknown-words=no
|
||||
|
||||
|
||||
[LOGGING]
|
||||
|
||||
# The type of string formatting that logging methods do. `old` means using %
|
||||
# formatting, `new` is for `{}` formatting.
|
||||
logging-format-style=old
|
||||
|
||||
# Logging modules to check that the string format arguments are in logging
|
||||
# function parameter format.
|
||||
logging-modules=logging
|
||||
|
||||
|
||||
[TYPECHECK]
|
||||
|
||||
# List of decorators that produce context managers, such as
|
||||
# contextlib.contextmanager. Add to this list to register other decorators that
|
||||
# produce valid context managers.
|
||||
contextmanager-decorators=contextlib.contextmanager
|
||||
|
||||
# List of members which are set dynamically and missed by pylint inference
|
||||
# system, and so shouldn't trigger E1101 when accessed. Python regular
|
||||
# expressions are accepted.
|
||||
generated-members=
|
||||
|
||||
# Tells whether missing members accessed in mixin class should be ignored. A
|
||||
# class is considered mixin if its name matches the mixin-class-rgx option.
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# Tells whether to warn about missing members when the owner of the attribute
|
||||
# is inferred to be None.
|
||||
ignore-none=yes
|
||||
|
||||
# This flag controls whether pylint should warn about no-member and similar
|
||||
# checks whenever an opaque object is returned when inferring. The inference
|
||||
# can return multiple potential results while evaluating a Python object, but
|
||||
# some branches might not be evaluated, which results in partial inference. In
|
||||
# that case, it might be useful to still emit no-member and other checks for
|
||||
# the rest of the inferred objects.
|
||||
ignore-on-opaque-inference=yes
|
||||
|
||||
# List of class names for which member attributes should not be checked (useful
|
||||
# for classes with dynamically set attributes). This supports the use of
|
||||
# qualified names.
|
||||
ignored-classes=optparse.Values,thread._local,_thread._local
|
||||
|
||||
# List of module names for which member attributes should not be checked
|
||||
# (useful for modules/projects where namespaces are manipulated during runtime
|
||||
# and thus existing member attributes cannot be deduced by static analysis). It
|
||||
# supports qualified module names, as well as Unix pattern matching.
|
||||
ignored-modules=
|
||||
|
||||
# Show a hint with possible names when a member name was not found. The aspect
|
||||
# of finding the hint is based on edit distance.
|
||||
missing-member-hint=yes
|
||||
|
||||
# The minimum edit distance a name should have in order to be considered a
|
||||
# similar match for a missing member name.
|
||||
missing-member-hint-distance=1
|
||||
|
||||
# The total number of similar names that should be taken in consideration when
|
||||
# showing a hint for a missing member.
|
||||
missing-member-max-choices=1
|
||||
|
||||
# Regex pattern to define which classes are considered mixins ignore-mixin-
|
||||
# members is set to 'yes'
|
||||
mixin-class-rgx=.*[Mm]ixin
|
||||
|
||||
# List of decorators that change the signature of a decorated function.
|
||||
signature-mutators=
|
||||
|
||||
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,
|
||||
XXX,
|
||||
TODO
|
||||
|
||||
# Regular expression of note tags to take in consideration.
|
||||
#notes-rgx=
|
||||
|
||||
|
||||
[STRING]
|
||||
|
||||
# This flag controls whether inconsistent-quotes generates a warning when the
|
||||
# character used as a quote delimiter is used inconsistently within a module.
|
||||
check-quote-consistency=no
|
||||
|
||||
# This flag controls whether the implicit-str-concat should generate a warning
|
||||
# on implicit string concatenation in sequences defined over several lines.
|
||||
check-str-concat-over-line-jumps=no
|
||||
|
||||
|
||||
[DESIGN]
|
||||
|
||||
# List of regular expressions of class ancestor names to ignore when counting
|
||||
# public methods (see R0903)
|
||||
exclude-too-few-public-methods=
|
||||
|
||||
# List of qualified class names to ignore when counting class parents (see
|
||||
# R0901)
|
||||
ignored-parents=
|
||||
|
||||
# Maximum number of arguments for function / method.
|
||||
max-args=5
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=7
|
||||
|
||||
# Maximum number of boolean expressions in an if statement (see R0916).
|
||||
max-bool-expr=5
|
||||
|
||||
# Maximum number of branch for function / method body.
|
||||
max-branches=12
|
||||
|
||||
# Maximum number of locals for function / method body.
|
||||
max-locals=15
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
# Maximum number of return / yield for function / method body.
|
||||
max-returns=6
|
||||
|
||||
# Maximum number of statements in function / method body.
|
||||
max-statements=50
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=2
|
||||
|
||||
|
||||
[CLASSES]
|
||||
|
||||
# Warn about protected attribute access inside special methods
|
||||
check-protected-access-in-special-methods=no
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,
|
||||
__new__,
|
||||
setUp,
|
||||
__post_init__
|
||||
|
||||
# List of member names, which should be excluded from the protected access
|
||||
# warning.
|
||||
exclude-protected=_asdict,
|
||||
_fields,
|
||||
_replace,
|
||||
_source,
|
||||
_make
|
||||
|
||||
# List of valid names for the first argument in a class method.
|
||||
valid-classmethod-first-arg=cls
|
||||
|
||||
# List of valid names for the first argument in a metaclass class method.
|
||||
valid-metaclass-classmethod-first-arg=cls
|
||||
|
||||
|
||||
[IMPORTS]
|
||||
|
||||
# List of modules that can be imported at any level, not just the top level
|
||||
# one.
|
||||
allow-any-import-level=
|
||||
|
||||
# Allow wildcard imports from modules that define __all__.
|
||||
allow-wildcard-with-all=no
|
||||
|
||||
# Analyse import fallback blocks. This can be used to support both Python 2 and
|
||||
# 3 compatible code, which means that the block might have code that exists
|
||||
# only in one or another interpreter, leading to false positives when analysed.
|
||||
analyse-fallback-blocks=no
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma.
|
||||
deprecated-modules=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of external dependencies
|
||||
# to the given file (report RP0402 must not be disabled).
|
||||
ext-import-graph=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of all (i.e. internal and
|
||||
# external) dependencies to the given file (report RP0402 must not be
|
||||
# disabled).
|
||||
import-graph=
|
||||
|
||||
# Output a graph (.gv or any supported image format) of internal dependencies
|
||||
# to the given file (report RP0402 must not be disabled).
|
||||
int-import-graph=
|
||||
|
||||
# Force import order to recognize a module as part of the standard
|
||||
# compatibility libraries.
|
||||
known-standard-library=
|
||||
|
||||
# Force import order to recognize a module as part of a third party library.
|
||||
known-third-party=enchant
|
||||
|
||||
# Couples of modules and preferred modules, separated by a comma.
|
||||
preferred-modules=
|
||||
|
||||
|
||||
[EXCEPTIONS]
|
||||
|
||||
# Exceptions that will emit a warning when being caught. Defaults to
|
||||
# "BaseException, Exception".
|
||||
overgeneral-exceptions=BaseException,
|
||||
Exception
|
|
@ -0,0 +1,2 @@
|
|||
release: python manage.py migrate
|
||||
web: gunicorn config.wsgi
|
|
@ -0,0 +1,121 @@
|
|||
# Ultron
|
||||
|
||||
[![Build Status](https://drone.grimbox.be/api/badges/Sulley/Ultron/status.svg)](https://drone.grimbox.be/Sulley/Ultron)
|
||||
|
||||
## Déploiement en local (Docker)
|
||||
|
||||
- installer Docker (+ drivers PGSQL)
|
||||
- créer un fichier `docker-compose.yml` :
|
||||
```
|
||||
version: "3"
|
||||
services:
|
||||
db:
|
||||
image: "postgres:14"
|
||||
restart: always
|
||||
container_name: "jarvis_container"
|
||||
environment:
|
||||
POSTGRES_DB: "jarvis_db"
|
||||
POSTGRES_USER: "Iamironman"
|
||||
POSTGRES_PASSWORD: "J4rV1s"
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- ./data:/var/lib/postgresql/data
|
||||
```
|
||||
- tapez la commande `docker-compose up -d`
|
||||
|
||||
- pip install -r requirements.txt
|
||||
### Installation de weasyprint
|
||||
En plus du `pip install weasyprint` et `pip install django-weasyprint`, il faut installer weasyprint (via homebrew, …)
|
||||
puis, **pour les mac M1** exécuter les commandes :
|
||||
```
|
||||
sudo ln -s /opt/homebrew/opt/glib/lib/libgobject-2.0.0.dylib /usr/local/lib/gobject-2.0
|
||||
sudo ln -s /opt/homebrew/opt/pango/lib/libpango-1.0.dylib /usr/local/lib/pango-1.0
|
||||
sudo ln -s /opt/homebrew/opt/harfbuzz/lib/libharfbuzz.dylib /usr/local/lib/harfbuzz
|
||||
sudo ln -s /opt/homebrew/opt/fontconfig/lib/libfontconfig.1.dylib /usr/local/lib/fontconfig-1
|
||||
sudo ln -s /opt/homebrew/opt/pango/lib/libpangoft2-1.0.dylib /usr/local/lib/pangoft2-1.0
|
||||
````
|
||||
|
||||
## Déploiement sur Heroku
|
||||
|
||||
- Créer l'application sur Heroku
|
||||
|
||||
- Créer les variables d'environnement :
|
||||
- ALLOWED_HOSTS : avengers-jarvis.herokuapp.com
|
||||
- DATABASE_NAME : ultron
|
||||
- DISABLE_COLLECTSTATIC : 1
|
||||
- SECRET_KEY : django-insecure-g_eoy6z%xshku4o5#k%o%i_%nb%_pz80config_#+t%f
|
||||
- DATABASE_URL : créé automatiquement lorsqu'on ajoute l' `element` PostgreSQL
|
||||
|
||||
Exemple :
|
||||
|
||||
```
|
||||
heroku config:set DISABLE_COLLECTSTATIC="1"
|
||||
heroku config:set ALLOWED_HOSTS="avengers-jarvis.herokuapp.com"
|
||||
heroku config:set SECRET_KEY="django-insecure-g_eoy6z%xshku4o5#k%o%i_%nb%_pz80config_#+t%f"
|
||||
heroku config:set DATABASE_NAME="ultron"
|
||||
```
|
||||
|
||||
- Push de l'application : `git push heroku master`
|
||||
|
||||
- Se connecter à Héroku (via l'invite de commande) : `heroku login`
|
||||
|
||||
- Création du super user : `heroku run python manage.py createsuperuser`
|
||||
|
||||
|
||||
## Récupération des données :
|
||||
Pour transferer des données d'un site à un autre, le plus simple est d'utiliser la commande
|
||||
`./manage.py dumpdata > db.json`.
|
||||
|
||||
Pour ne pas récupérer les user, les authorisation et les content-type, utilisez la commande :
|
||||
|
||||
```
|
||||
python manage.py dumpdata --natural-foreign --exclude contenttypes --exclude auth.permission --exclude admin.logentry --exclude sessions.session --indent 4 > save.json
|
||||
```
|
||||
|
||||
Pour charger les données, tapez ensuite :
|
||||
```
|
||||
python manage.py loaddata save.json
|
||||
```
|
||||
## Applications
|
||||
|
||||
### Right
|
||||
|
||||
Il y a 3 types pe de droits :
|
||||
|
||||
- Administrateur
|
||||
- Entraineur (groupe `Trainer`)
|
||||
- Gymnaste (groupe `Gymnast`)
|
||||
|
||||
##### Administrateur
|
||||
|
||||
Il peut tout faire.
|
||||
|
||||
##### Entraîneur
|
||||
|
||||
Peut tout faire sauf :
|
||||
|
||||
- Gérer les skill
|
||||
- Gérer les Pays
|
||||
- Gérer les lieux
|
||||
|
||||
##### Gymnaste
|
||||
|
||||
Un gymnaste peut tout faire pour *lui-même* :
|
||||
|
||||
- Ajouter un chrono
|
||||
- Ajouter un score
|
||||
- Ajouter un height/weight
|
||||
- …
|
||||
|
||||
|
||||
|
||||
### Skill
|
||||
|
||||
### Learned Skill
|
||||
Il y a quatre niveau de connaissance d'un skill :
|
||||
|
||||
- non connu
|
||||
- connu avec aide (tapis, élastiques, fosse, …)
|
||||
- connu sans aucune aide
|
||||
- connu et enchainé
|
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
ASGI config for Ultron project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
||||
|
||||
application = get_asgi_application()
|
|
@ -0,0 +1,192 @@
|
|||
"""
|
||||
Django settings for Ultron project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 3.2.8.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/3.2/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/3.2/ref/settings/
|
||||
"""
|
||||
|
||||
import os
|
||||
import environ
|
||||
from pathlib import Path
|
||||
|
||||
# Initialise environment variables
|
||||
env = environ.Env()
|
||||
environ.Env.read_env()
|
||||
|
||||
# Sentry
|
||||
SENTRY_DSN = env("SENTRY_DSN", default=None)
|
||||
if SENTRY_DSN is not None:
|
||||
import sentry_sdk
|
||||
from sentry_sdk.integrations.django import DjangoIntegration
|
||||
|
||||
sentry_sdk.init(
|
||||
dsn=SENTRY_DSN,
|
||||
integrations=[DjangoIntegration()],
|
||||
traces_sample_rate=env("SENTRY_TRACES_SAMPLE_RATE", default=1.0),
|
||||
send_default_pii=True,
|
||||
debug=env("SENTRY_DEBUG", default=True),
|
||||
)
|
||||
|
||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = env("SECRET_KEY", default="Super Little Poney 2000")
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = env("ALLOWED_HOSTS", default="localhost").split()
|
||||
|
||||
# Application definition
|
||||
INSTALLED_APPS = [
|
||||
"django.contrib.admin",
|
||||
"django.contrib.auth",
|
||||
"django.contrib.contenttypes",
|
||||
"django.contrib.sessions",
|
||||
"django.contrib.messages",
|
||||
"django.contrib.staticfiles",
|
||||
"django_admin_listfilter_dropdown",
|
||||
"django_extensions",
|
||||
"jarvis.core",
|
||||
"jarvis.location",
|
||||
"jarvis.people",
|
||||
"jarvis.followup",
|
||||
"jarvis.tools",
|
||||
"jarvis.profiles",
|
||||
"jarvis.planning",
|
||||
"jarvis.objective",
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
"django.middleware.security.SecurityMiddleware",
|
||||
"django.contrib.sessions.middleware.SessionMiddleware",
|
||||
"django.middleware.common.CommonMiddleware",
|
||||
"django.middleware.csrf.CsrfViewMiddleware",
|
||||
"django.contrib.auth.middleware.AuthenticationMiddleware",
|
||||
"django.contrib.messages.middleware.MessageMiddleware",
|
||||
"django.middleware.clickjacking.XFrameOptionsMiddleware",
|
||||
"whitenoise.middleware.WhiteNoiseMiddleware",
|
||||
]
|
||||
|
||||
ROOT_URLCONF = "config.urls"
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||
"DIRS": [
|
||||
os.path.join(BASE_DIR, "templates"),
|
||||
],
|
||||
"APP_DIRS": True,
|
||||
"OPTIONS": {
|
||||
"context_processors": [
|
||||
"django.template.context_processors.debug",
|
||||
"django.template.context_processors.request",
|
||||
"django.contrib.auth.context_processors.auth",
|
||||
"django.contrib.messages.context_processors.messages",
|
||||
"jarvis.core.context_processors.git_describe",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = "config.wsgi.application"
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
|
||||
DATABASES = {"default": env.db_url("DATABASE_URL", default="sqlite:///jarvis.db")}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
|
||||
},
|
||||
{
|
||||
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/3.2/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = "en-us"
|
||||
|
||||
TIME_ZONE = "UTC"
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
LOGIN_URL = "/login/"
|
||||
|
||||
LOGOUT_URL = "/logout/"
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/3.2/howto/static-files/
|
||||
|
||||
STATIC_URL = "/static/"
|
||||
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
|
||||
STATIC_ROOT = BASE_DIR / "staticfiles"
|
||||
|
||||
# Default primary key field type
|
||||
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||
|
||||
|
||||
# Simplified static file serving.
|
||||
# https://warehouse.python.org/project/whitenoise/
|
||||
|
||||
STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage"
|
||||
|
||||
|
||||
# CLUB Settings
|
||||
ZIP = env("ZIP", default=None)
|
||||
CITY = env("CITY", default=None)
|
||||
ADDRESS = env("ADDRESS", default=None)
|
||||
CLUB_NAME = env("CLUB_NAME", default=None)
|
||||
HEAD_COACH = env("HEAD_COACH", default=None)
|
||||
SITE_TITLE = env("SITE_TITLE", default=None)
|
||||
MOBILE_PHONE = env("MOBILE_PHONE", default=None)
|
||||
HEAD_COACH_EMAIL = env("HEAD_COACH_EMAIL", default=None)
|
||||
|
||||
|
||||
# EMAIL Settings
|
||||
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
|
||||
|
||||
# EMAIL_HOST = env("EMAIL_HOST", default=None)
|
||||
# EMAIL_PORT = env("EMAIL_PORT", default=None)
|
||||
# EMAIL_SOURCE = env("EMAIL_SOURCE", default=None)
|
||||
# EMAIL_USE_TLS = env("EMAIL_USE_TLS", default=None)
|
||||
# EMAIL_HOST_USER = env("EMAIL_HOST_USER", default=None)
|
||||
# EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD", default=None)
|
||||
# SENDGRID_WebAPI_KEY = env("SENDGRID_WebAPI_KEY", default=None)
|
||||
|
||||
EMAIL_HOST = env("EMAIL_HOST", default=None)
|
||||
EMAIL_PORT = env("EMAIL_PORT", default=None)
|
||||
EMAIL_USE_TLS = env("EMAIL_USE_TLS", default=None)
|
||||
EMAIL_HOST_USER = env("EMAIL_HOST_USER", default=None)
|
||||
EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD", default=None)
|
|
@ -0,0 +1,42 @@
|
|||
"""Ultron URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/3.2/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
|
||||
import jarvis.followup.urls
|
||||
import jarvis.location.urls
|
||||
import jarvis.people.urls
|
||||
import jarvis.profiles.urls
|
||||
import jarvis.planning.urls
|
||||
import jarvis.objective.urls
|
||||
|
||||
urlpatterns = [
|
||||
# Profile list
|
||||
path(r"profile/", include(jarvis.profiles.urls.profile_urlpatterns)),
|
||||
# Gymnast management
|
||||
path(r"gymnast/", include(jarvis.people.urls.gymnast_urlpatterns)),
|
||||
# Location management
|
||||
path(r"location/", include(jarvis.location.urls.urlpatterns)),
|
||||
# Follow-up management
|
||||
path(r"follow-up/", include(jarvis.followup.urls.urlpatterns)),
|
||||
# Objective management
|
||||
path(r"objective/", include(jarvis.objective.urls.urlpatterns)),
|
||||
# Planning management
|
||||
path(r"event/", include(jarvis.planning.urls.event_urlpatterns)),
|
||||
path("", include("jarvis.core.urls")),
|
||||
# Administration
|
||||
path("admin/", admin.site.urls),
|
||||
]
|
|
@ -0,0 +1,16 @@
|
|||
"""
|
||||
WSGI config for Ultron project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
|
||||
|
||||
application = get_wsgi_application()
|
|
@ -0,0 +1,14 @@
|
|||
version: "3"
|
||||
services:
|
||||
db:
|
||||
image: "postgres:14"
|
||||
restart: always
|
||||
container_name: "jarvis_container"
|
||||
environment:
|
||||
POSTGRES_DB: "jarvis_db"
|
||||
POSTGRES_USER: "Iamironman"
|
||||
POSTGRES_PASSWORD: "J4rV1s"
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- ./data:/var/lib/postgresql/data
|
|
@ -0,0 +1,18 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from django_admin_listfilter_dropdown.filters import (
|
||||
DropdownFilter,
|
||||
ChoiceDropdownFilter,
|
||||
RelatedDropdownFilter,
|
||||
)
|
||||
|
||||
from .models import Citation
|
||||
|
||||
|
||||
class CitationAdmin(admin.ModelAdmin):
|
||||
model = Citation
|
||||
|
||||
list_display = ("author", "quote")
|
||||
|
||||
|
||||
admin.site.register(Citation, CitationAdmin)
|
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class CoreConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "jarvis.core"
|
|
@ -0,0 +1,24 @@
|
|||
import subprocess
|
||||
|
||||
|
||||
def git_describe(request) -> str:
|
||||
try:
|
||||
git_describe = subprocess.check_output(
|
||||
["git", "describe", "--always"], stderr=subprocess.STDOUT
|
||||
).decode()
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("Exception on process, rc=", e.returncode, "output=", e.output)
|
||||
git_describe = ""
|
||||
|
||||
try:
|
||||
git_date = subprocess.check_output(
|
||||
["git", "show", "-s", r"--format=%cd", r"--date=format:%d-%m-%Y"], stderr=subprocess.STDOUT
|
||||
).decode()
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("Exception on process, rc=", e.returncode, "output=", e.output)
|
||||
git_date = ""
|
||||
|
||||
return {
|
||||
"git_describe": git_describe,
|
||||
"git_date": git_date
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 4.1.1 on 2023-01-29 11:38
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Citation",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("quote", models.TextField()),
|
||||
("author", models.CharField(blank=True, max_length=50, null=True)),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.1.1 on 2023-01-29 13:19
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("core", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="citation",
|
||||
name="quote",
|
||||
field=models.TextField(help_text="Only MarkDown is authorized"),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,21 @@
|
|||
from django.db import models
|
||||
import markdown
|
||||
|
||||
|
||||
class Citation(models.Model):
|
||||
"""
|
||||
Représente les citations.
|
||||
"""
|
||||
|
||||
quote = models.TextField(
|
||||
help_text="Only MarkDown is authorized",
|
||||
)
|
||||
author = models.CharField(max_length=50, null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.quote} - {self.author}"
|
||||
|
||||
def to_markdown(self):
|
||||
"""Convertit le champ `informations` en (Github-flavored) Markdown."""
|
||||
|
||||
return markdown.markdown(self.quote)
|
|
@ -0,0 +1,349 @@
|
|||
{% load static %}
|
||||
{% load menuitems %}
|
||||
{% load has_group %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="Gregory Trullemans">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="{% static "img/apple-icon.png" %}">
|
||||
<link rel="icon" type="image/png" href="{% static "img/favicon.png" %}">
|
||||
|
||||
<title>• {% block page_title %}Jarvis{% endblock %} •</title>
|
||||
|
||||
<!-- Fonts and icons -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Poppins:200,300,400,600,700,800" rel="stylesheet" />
|
||||
<!-- Font Awesome Pro -->
|
||||
<link href="{% static "css/font_awesome_all_5.15.3.css" %}" rel="stylesheet" />
|
||||
|
||||
<!-- Full Calendar Plugin, full documentation here: https://github.com/fullcalendar/fullcalendar -->
|
||||
<link href="{% static "js/plugins/fullcalendar/main.min.css" %}" rel="stylesheet" />
|
||||
|
||||
<!-- JQuery UI CSS -->
|
||||
<link href="{% static "js/plugins/jqueryui/jquery-ui.theme.min.css" %}" rel="stylesheet" />
|
||||
<link href="{% static "js/plugins/jqueryui/jquery-ui.min.css" %}" rel="stylesheet" />
|
||||
|
||||
<!-- Nucleo Icons -->
|
||||
<link href="{% static "css/nucleo-icons.css" %}" rel="stylesheet" />
|
||||
|
||||
<!-- CSS Files -->
|
||||
<link href="{% static "css/black-dashboard.css" %}" rel="stylesheet" />
|
||||
|
||||
<!-- Maps by mapbox -->
|
||||
<script src='https://api.mapbox.com/mapbox.js/v3.2.0/mapbox.js'></script>
|
||||
<link href='https://api.mapbox.com/mapbox.js/v3.2.0/mapbox.css' rel='stylesheet' />
|
||||
|
||||
<!-- Core JS Files -->
|
||||
<script src="{% static "js/core/jquery-3.6.0.min.js" %}"></script>
|
||||
<script src="{% static "js/core/popper.min.js" %}"></script>
|
||||
<script src="{% static "js/core/bootstrap.min.js" %}"></script>
|
||||
|
||||
<!-- Chart JS -->
|
||||
<script src="{% static "js/plugins/momentjs/moment_2.29.1.min.js" %}"></script>
|
||||
<script src="{% static "js/plugins/momentjs/moment_locale_en-gb.js" %}"></script>
|
||||
<script src="{% static "js/plugins/chartjs/chartjs_3.9.1.min.js" %}"></script>
|
||||
<script src="{% static "js/plugins/chartjs/chartjs-adapter-moment_1.0.0.js" %}"></script>
|
||||
|
||||
<!-- FullCalendar CSS -->
|
||||
<!-- <link href="{% static "js/plugins/fullcalendar/main.css" %}" rel="stylesheet" /> -->
|
||||
|
||||
{% block header %}{% endblock %}
|
||||
</head>
|
||||
|
||||
<body class="sidebar-mini {% if request.session.template == 1 %}white-content{% endif %}">
|
||||
<div class="wrapper">
|
||||
<div class="navbar-minimize-fixed">
|
||||
<button class="minimize-sidebar btn btn-link btn-just-icon">
|
||||
<i class="tim-icons icon-align-center visible-on-sidebar-regular text-muted"></i>
|
||||
<i class="tim-icons icon-bullet-list-67 visible-on-sidebar-mini text-muted"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-wrapper">
|
||||
<div class="logo">
|
||||
<a href="javascript:void(0)" class="simple-text logo-mini">TRA</a>
|
||||
<a href="javascript:void(0)" class="simple-text logo-normal">Trampoline</a>
|
||||
</div>
|
||||
<ul class="nav">
|
||||
{% menuitem 'home' 'fal fa-chart-pie' 'Dashboard' %}
|
||||
{% menuitem 'gymnast_list' 'tim-icons icon-badge' 'Gymnasts' %}
|
||||
{% menuitem 'skill_list' 'tim-icons icon-molecule-40' 'Skills' %}
|
||||
{% menuitem 'routine_list' 'tim-icons icon-components' 'Routines' %}
|
||||
{% menuitem 'event_list' 'fal fa-calendar-alt' 'Events' %}
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
{% menuitem 'accident_list' 'fal fa-comment-alt-medical' 'Accidents' %}
|
||||
{% endif %}
|
||||
{% menuitem 'place_list' 'fal fa-map-marked-alt' 'Places' %}
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
{% menuitem 'chrono_list' 'fal fa-stopwatch' 'Chronos' %}
|
||||
{% endif %}
|
||||
{% if request.user.is_staff %}
|
||||
<li>
|
||||
<a href="/admin/" target="_blank">
|
||||
<!-- <i class="tim-icons icon-settings"></i> -->
|
||||
<i class="fal fa-tools"></i>
|
||||
<p>Administration</p>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="main-panel">
|
||||
<!-- Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-absolute navbar-transparent">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-wrapper">
|
||||
<div class="navbar-minimize d-inline">
|
||||
<button class="minimize-sidebar btn btn-link btn-just-icon" rel="tooltip" data-original-title="Sidebar toggle" data-placement="right">
|
||||
<i class="tim-icons icon-align-center visible-on-sidebar-regular"></i>
|
||||
<i class="tim-icons icon-bullet-list-67 visible-on-sidebar-mini"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="navbar-toggle d-inline">
|
||||
<button type="button" class="navbar-toggler">
|
||||
<span class="navbar-toggler-bar bar1"></span>
|
||||
<span class="navbar-toggler-bar bar2"></span>
|
||||
<span class="navbar-toggler-bar bar3"></span>
|
||||
</button>
|
||||
</div>
|
||||
<a class="navbar-brand" href="/">Jarvis</a>
|
||||
</div>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navigation" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-bar navbar-kebab"></span>
|
||||
<span class="navbar-toggler-bar navbar-kebab"></span>
|
||||
<span class="navbar-toggler-bar navbar-kebab"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navigation">
|
||||
<ul class="navbar-nav ml-auto">
|
||||
<li class="search-bar input-group">
|
||||
<button class="btn btn-link" id="search-button" data-toggle="modal" data-target="#searchModal">
|
||||
<i class="tim-icons icon-zoom-split"></i>
|
||||
<span class="d-lg-none d-md-block">Search</span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="dropdown nav-item">
|
||||
<a href="#" class="dropdown-toggle nav-link" data-toggle="dropdown">
|
||||
<div class="photo">
|
||||
<img src="{% static '/img/default-avatar.png' %}" alt="Profile Photo">
|
||||
</div>
|
||||
<b class="caret d-none d-lg-block d-xl-block"></b>
|
||||
<p class="d-lg-none">Log out</p>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-navbar">
|
||||
<li class="nav-link">
|
||||
<a href="{% url 'profile_update' %}" class="nav-item dropdown-item"><i class="fal fa-id-card-alt"></i> {{ request.user }}</a>
|
||||
</li>
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
<li class="nav-link">
|
||||
<a href="{% url 'notification_update' %}" class="nav-item dropdown-item"><i class="fal fa-envelope"></i> Notifications</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="dropdown-divider"></li>
|
||||
<li class="nav-link">
|
||||
<a href="{% url 'logout' %}" class="nav-item dropdown-item"><i class="fal fa-sign-out-alt"></i> Log out</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="separator d-lg-none"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="modal modal-search" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModal" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<form action="{% url 'global_search' %}" method="GET" class="sidebar-form">
|
||||
<input type="text" class="form-control" name="pattern" id="inlineFormInputGroup" placeholder="Global Search..." autofocus>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Navbar -->
|
||||
|
||||
|
||||
<div class="content">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="{% static "js/plugins/perfect-scrollbar.jquery_1.4.0.min.js" %}"></script>
|
||||
|
||||
<!-- Plugin for Switches, full documentation here: http://www.jque.re/plugins/version3/bootstrap.switch/ -->
|
||||
<script src="{% static "js/plugins/bootstrap-switch_3.3.4.js" %}"></script>
|
||||
<!-- Plugin for Sweet Alert -->
|
||||
<script src="{% static "js/plugins/sweetalert2.min.js" %}"></script>
|
||||
<!-- Plugin for Sorting Tables -->
|
||||
<script src="{% static "js/plugins/jquery.tablesorter_2.0.5b.js" %}"></script>
|
||||
<!-- Forms Validations Plugin -->
|
||||
<script src="{% static "js/plugins/jquery.validate_1.17.0.min.js" %}"></script>
|
||||
<!-- Plugin for the Wizard, full documentation here: https://github.com/VinceG/twitter-bootstrap-wizard -->
|
||||
<script src="{% static "js/plugins/jquery.bootstrap-wizard_1.4.2.js" %}"></script>
|
||||
<!-- Plugin for Select, full documentation here: http://silviomoreto.github.io/bootstrap-select -->
|
||||
<script src="{% static "js/plugins/bootstrap-selectpicker_1.12.4.js" %}"></script>
|
||||
<!-- Plugin for the DateTimePicker, full documentation here: https://eonasdan.github.io/bootstrap-datetimepicker/ -->
|
||||
<script src="{% static "js/plugins/bootstrap-datetimepicker_4.17.47.js" %}"></script>
|
||||
<!-- DataTables.net Plugin, full documentation here: https://datatables.net/ -->
|
||||
<script src="{% static "js/plugins/datatables/datatables_1.12.1.min.js" %}"></script>
|
||||
<!-- Plugin for Tags, full documentation here: https://github.com/bootstrap-tagsinput/bootstrap-tagsinputs -->
|
||||
<script src="{% static "js/plugins/bootstrap-tagsinput_0.8.0.js" %}"></script>
|
||||
<!-- Plugin for Fileupload, full documentation here: http://www.jasny.net/bootstrap/javascript/#fileinput -->
|
||||
<script src="{% static "js/plugins/jasny-bootstrap_3.1.3.min.js" %}"></script>
|
||||
<!-- Full Calendar Plugin, full documentation here: https://github.com/fullcalendar/fullcalendar -->
|
||||
<script src="{% static "js/plugins/fullcalendar/main.js" %}"></script>
|
||||
<!-- Vector Map plugin, full documentation here: http://jvectormap.com/documentation/ -->
|
||||
<script src="{% static "js/plugins/jquery-jvectormap_2.0.4.js" %}"></script>
|
||||
<!-- Plugin for the Sliders, full documentation here: http://refreshless.com/nouislider/ -->
|
||||
<script src="{% static "js/plugins/nouislider_11.1.0.min.js" %}"></script>
|
||||
<!-- Notifications Plugin -->
|
||||
<script src="{% static "js/plugins/bootstrap-notify_3.1.5.js" %}"></script>
|
||||
<!-- Control Center for Black Dashboard: parallax effects, scripts for the example pages etc -->
|
||||
<script src="{% static "js/black-dashboard.js" %}"></script>
|
||||
<!-- Jquery UI for autocomplete, etc. -->
|
||||
<script src="{% static "js/plugins/jqueryui/jquery-ui.min.js" %}"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$().ready(function() {
|
||||
$sidebar = $('.sidebar');
|
||||
$navbar = $('.navbar');
|
||||
$main_panel = $('.main-panel');
|
||||
$full_page = $('.full-page');
|
||||
$sidebar_responsive = $('body > .navbar-collapse');
|
||||
|
||||
{% if request.session.is_sidebar_minified %}sidebar_mini_active = true;
|
||||
{% else %}sidebar_mini_active = false;
|
||||
{% endif %}
|
||||
|
||||
{% if request.session.template == 0 %}white_color = false;
|
||||
{% else %}white_color = true;
|
||||
{% endif %}
|
||||
|
||||
window_width = $(window).width();
|
||||
fixed_plugin_open = $('.sidebar .sidebar-wrapper .nav li.active a p').html();
|
||||
|
||||
{% if request.session.sidebar == 1 %}color = 'blue';
|
||||
{% elif request.session.sidebar == 2 %}color = 'green';
|
||||
{% elif request.session.sidebar == 3 %}color = 'orange';
|
||||
{% elif request.session.sidebar == 4 %}color = 'red';
|
||||
{% else %}color = 'purple'
|
||||
{% endif %}
|
||||
$sidebar.attr('data', color);
|
||||
$main_panel.attr('data', color);
|
||||
$full_page.attr('filter-color', color);
|
||||
$sidebar_responsive.attr('data', color);
|
||||
|
||||
// $('.fixed-plugin a').click(function(event) {
|
||||
// if ($(this).hasClass('switch-trigger')) {
|
||||
// if (event.stopPropagation) {
|
||||
// event.stopPropagation();
|
||||
// } else if (window.event) {
|
||||
// window.event.cancelBubble = true;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// $('.fixed-plugin .background-color span').click(function() {
|
||||
// $(this).siblings().removeClass('active');
|
||||
// $(this).addClass('active');
|
||||
|
||||
// var new_color = $(this).data('color');
|
||||
|
||||
// if ($sidebar.length != 0)
|
||||
// $sidebar.attr('data', new_color);
|
||||
|
||||
// if ($main_panel.length != 0)
|
||||
// $main_panel.attr('data', new_color);
|
||||
|
||||
// if ($full_page.length != 0)
|
||||
// $full_page.attr('filter-color', new_color);
|
||||
|
||||
// if ($sidebar_responsive.length != 0)
|
||||
// $sidebar_responsive.attr('data', new_color);
|
||||
// });
|
||||
|
||||
// $('.switch-sidebar-mini input').on("switchChange.bootstrapSwitch", function() {
|
||||
// var $btn = $(this);
|
||||
|
||||
// if (sidebar_mini_active == true) {
|
||||
// $('body').removeClass('sidebar-mini');
|
||||
// sidebar_mini_active = false;
|
||||
// blackDashboard.showSidebarMessage('Sidebar mini deactivated...');
|
||||
// } else {
|
||||
// $('body').addClass('sidebar-mini');
|
||||
// sidebar_mini_active = true;
|
||||
// blackDashboard.showSidebarMessage('Sidebar mini activated...');
|
||||
// }
|
||||
|
||||
// // we simulate the window Resize so the charts will get updated in realtime.
|
||||
// var simulateWindowResize = setInterval(function() {
|
||||
// window.dispatchEvent(new Event('resize'));
|
||||
// }, 180);
|
||||
|
||||
// // we stop the simulation of Window Resize after the animations are completed
|
||||
// setTimeout(function() {
|
||||
// clearInterval(simulateWindowResize);
|
||||
// }, 1000);
|
||||
// });
|
||||
|
||||
// $('.switch-change-color input').on("switchChange.bootstrapSwitch", function() {
|
||||
// var $btn = $(this);
|
||||
|
||||
// if (white_color == true) {
|
||||
// $('body').addClass('change-background');
|
||||
// setTimeout(function() {
|
||||
// $('body').removeClass('change-background');
|
||||
// $('body').removeClass('white-content');
|
||||
// }, 900);
|
||||
// white_color = true; // false
|
||||
// } else {
|
||||
// $('body').addClass('change-background');
|
||||
// setTimeout(function() {
|
||||
// $('body').removeClass('change-background');
|
||||
// $('body').addClass('white-content');
|
||||
// }, 900);
|
||||
// white_color = true;
|
||||
// }
|
||||
// });
|
||||
|
||||
$('.light-badge').click(function() {
|
||||
$('body').addClass('white-content');
|
||||
});
|
||||
|
||||
$('.dark-badge').click(function() {
|
||||
$('body').removeClass('white-content');
|
||||
});
|
||||
|
||||
// $('#searchModal').on('shown.bs.modal', function() {
|
||||
// $('#inlineFormInputGroup').trigger('focus')
|
||||
// });
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% block footerscript %}{% endblock %}
|
||||
|
||||
<!-- CSS Files -->
|
||||
<link href="{% static "css/jarvis.css" %}" rel="stylesheet" />
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,180 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
|
||||
{% block page_title %}Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4><i class="fal fa-quote-left text-danger"></i> Quote</h4>
|
||||
</div>
|
||||
<div class="card-body text-justify">
|
||||
{{ quote.to_markdown | safe }}
|
||||
</div>
|
||||
{% if quote.author %}
|
||||
<div class="card-footer text-right text-muted">
|
||||
<i>{{ quote.author }}</i>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class=""><i class="text-primary fal fa-laugh-wink"></i> Hi {{ user.username }} !</h4>
|
||||
</div>
|
||||
<div class="card-body text-justify">
|
||||
<p>Welcome to Jarvi v0.80 <span class="text-muted">(last update : 29-01-2023)</span></p>
|
||||
<p>This application is here to help coaches to manage the gymnasts (evolution, evaluation, routines, scores, …). This tool is not perfect so feel free to make improvement proposals, bug reports, … by sending me an <a href="mailto:gregory@flyingacrobaticstrampoline.be">email</a>.</p>
|
||||
<p>You can find the user manuel <a href="{% static "files/Manuel_Utilisateur.pdf" %}" download>here (in french)</a>.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4><i class="fal fa-chart-area text-warning"></i> Statistics</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="w-lg m-x-auto">
|
||||
<div class="progress-container progress-primary">
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="60"
|
||||
aria-valuemin="0" aria-valuemax="100" style="width: {{ percentage_week }}%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
{% if nb_active_gymnast or nb_event or nb_skill or nb_routine or nb_score or nb_club %}
|
||||
<div class="row">
|
||||
<div class="col-md-7">
|
||||
<ul class="list-unstyled mb-0">
|
||||
{% if nb_active_gymnast %}<li>{{ nb_active_gymnast }} active gymnasts</li>{% endif %}
|
||||
{% if nb_event %}<li>{{ nb_event }} events</li>{% endif %}
|
||||
{% if nb_score %}<li>{{ nb_score }} scores</li>{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<ul class="list-unstyled mb-0">
|
||||
{% if nb_skill %}<li>{{ nb_skill }} skills</li>{% endif %}
|
||||
{% if nb_routine %}<li>{{ nb_routine }} routines</li>{% endif %}
|
||||
{% if nb_club %}<li>{{ nb_club }} clubs</li>{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<br />
|
||||
No statistics to display.
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4><i class="fal fa-calendar-alt text-warning"></i> Next Events</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if event_list %}
|
||||
<table class="table tablesorter table-striped table-condensed" data-sort="table" id="event_table">
|
||||
{% for event in event_list %}
|
||||
<tr>
|
||||
<td class="text-left"><a href="{% url 'event_details' event.id %}">{{ event.name }}</a></td>
|
||||
<td>
|
||||
{% if event.number_of_week_from_today < 0 %}
|
||||
{{event.number_of_week_from_today}}
|
||||
{% else %}
|
||||
<span class="text-{% if event.number_of_week_from_today > 12 %}success{% elif event.number_of_week_from_today > 9 %}info{% elif event.number_of_week_from_today > 6 %}warning{% else %}danger{% endif %}">
|
||||
<b>{{event.number_of_week_from_today}}</b></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
No future event defined
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4><i class="fal fa-exclamation-triangle text-danger"></i> Updated needed</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if waiting_update_gymnast %}
|
||||
<table class="table tablesorter table-striped table-condensed" data-sort="table" id="gymnast_table">
|
||||
{% for gymnast in waiting_update_gymnast %}
|
||||
<tr>
|
||||
<td class="text-left"><a href="{% url 'gymnast_details' gymnast.id %}">{{ gymnast }}</a></td>
|
||||
<td class="text-right">{{ gymnast.club.acronym }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
No update needed.
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4><i class="fal fa-highlighter text-success"></i> Last updated gymnasts</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if last_updated_gymnast %}
|
||||
<table class="table tablesorter table-striped table-condensed" data-sort="table" id="gymnast_table">
|
||||
{% for gymnast in last_updated_gymnast %}
|
||||
<tr>
|
||||
<td class="text-left"><a href="{% url 'gymnast_details' gymnast.id %}">{{ gymnast }}</a></td>
|
||||
<td class="text-right">{{ gymnast.club.acronym }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
No update since your last visit
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4><i class="fal fa-birthday-cake text-info"></i> Next birthday</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if birthday_list %}
|
||||
<table class="table tablesorter table-striped table-condensed" data-sort="table" id="gymnast_table">
|
||||
{% for gymnast in birthday_list %}
|
||||
<tr>
|
||||
<td class="text-left"><a href="{% url 'gymnast_details' gymnast.id %}">{{ gymnast.first_name }}</a></td>
|
||||
<td class="">{{ gymnast.birthdate | date:"j M"}}</td>
|
||||
<td class="text-right">{{ gymnast.next_age }} years</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% else %}
|
||||
No next birtday (it's a bug).
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
|
||||
{% endblock%}
|
|
@ -0,0 +1,41 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<!-- <div class="flextable table-actions">
|
||||
<div class="flextable-item flextable-primary">
|
||||
<form action="/{% block searchurl %}{% endblock %}/search/" method="GET">
|
||||
<div class="btn-toolbar-item input-with-icon">
|
||||
<input type="text" class="form-control input-block" name="pattern" placeholder="Search {% block search %}{% endblock %}">
|
||||
<span class="icon icon-magnifying-glass"></span>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="flextable-item">
|
||||
<div class="btn-group">
|
||||
<a href="/{% block addurl %}{% endblock %}/add">
|
||||
<button type="button" class="btn btn-primary-outline">
|
||||
<span class="icon icon-plus"></span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<!-- <div class="table-full">
|
||||
<div class="table-responsive">
|
||||
{% block upper %}{% endblock %}
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
{% block datacontent %}{% endblock %}
|
||||
|
||||
<!-- <div class="flextable table-actions">
|
||||
{% block under %}{% endblock %}
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- {% block pagination %}{% endblock %} -->
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,132 @@
|
|||
{% load static %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="Gregory Trullemans">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="{% static "img/apple-icon.png" %}">
|
||||
<link rel="icon" type="image/png" href="{% static "img/favicon.png" %}">
|
||||
|
||||
<!-- <title>{% block page_title %}{% endblock %}</title> -->
|
||||
<title>• JARVIS •</title>
|
||||
|
||||
<!-- Fonts and icons -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Poppins:200,300,400,600,700,800" rel="stylesheet" />
|
||||
<link href="https://use.fontawesome.com/releases/v5.0.6/css/all.css" rel="stylesheet" />
|
||||
<!-- Nucleo Icons -->
|
||||
<link href="{% static "css/nucleo-icons.css" %}" rel="stylesheet" />
|
||||
<!-- CSS Files -->
|
||||
<link href="{% static "css/black-dashboard.css" %}" rel="stylesheet" />
|
||||
<!-- CSS Just for demo purpose, don't include it in your project -->
|
||||
<!-- <link href="../assets/demo/demo.css" rel="stylesheet" /> -->
|
||||
<!-- <link rel="stylesheet" href="{% static "css/application.css" %}"> -->
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="wrapper wrapper-full-page ">
|
||||
<div class="full-page login-page " data-color="red">
|
||||
<!-- you can change the color of the filter page using: data-color="blue | purple | green | orange | red | rose " -->
|
||||
<div class="content">
|
||||
<div class="container">
|
||||
<div class="col-lg-4 col-md-6 ml-auto mr-auto">
|
||||
<form class="form" action="/login/" method="post" if="formulaire">
|
||||
{% csrf_token %}
|
||||
<div class="card card-login card-white">
|
||||
<div class="card-header">
|
||||
<img src="{% static "img/card-danger.png" %}" alt="">
|
||||
<h1 class="card-title"> Log in</h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<i class="tim-icons icon-single-02"></i>
|
||||
</div>
|
||||
</div>
|
||||
<input type="login" name="login" class="form-control" id="login" placeholder="Login">
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text">
|
||||
<i class="tim-icons icon-lock-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<input type="password" name="password" class="form-control" id="password" placeholder="Password">
|
||||
</div>
|
||||
{% if message %}
|
||||
<p class="text-danger"><b>{{message}}</b></p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-danger btn-lg btn-block mb-3">Log me in</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<div class="footer-content"></div>
|
||||
</footer>
|
||||
|
||||
<script src="{% static "js/core/jquery.min.js" %}"></script>
|
||||
<script src="{% static "js/core/popper.min.js" %}"></script>
|
||||
<script src="{% static "js/core/bootstrap.min.js" %}"></script>
|
||||
<script src="{% static "js/plugins/perfect-scrollbar.jquery.min.js" %}"></script>
|
||||
<script src="{% static "js/plugins/moment.min.js" %}"></script>
|
||||
<!-- Plugin for Switches, full documentation here: http://www.jque.re/plugins/version3/bootstrap.switch/ -->
|
||||
<script src="{% static "js/plugins/bootstrap-switch.js" %}"></script>
|
||||
<!-- Plugin for Sweet Alert -->
|
||||
<script src="{% static "js/plugins/sweetalert2.min.js" %}"></script>
|
||||
<!-- Plugin for Sorting Tables -->
|
||||
<script src="{% static "js/plugins/jquery.tablesorter.js" %}"></script>
|
||||
<!-- Forms Validations Plugin -->
|
||||
<script src="{% static "js/plugins/jquery.validate.min.js" %}"></script>
|
||||
<!-- Plugin for the Wizard, full documentation here: https://github.com/VinceG/twitter-bootstrap-wizard -->
|
||||
<script src="{% static "js/plugins/jquery.bootstrap-wizard.js" %}"></script>
|
||||
<!-- Plugin for Select, full documentation here: http://silviomoreto.github.io/bootstrap-select -->
|
||||
<script src="{% static "js/plugins/bootstrap-selectpicker.js" %}"></script>
|
||||
<!-- Plugin for the DateTimePicker, full documentation here: https://eonasdan.github.io/bootstrap-datetimepicker/ -->
|
||||
<script src="{% static "js/plugins/bootstrap-datetimepicker.js" %}"></script>
|
||||
<!-- DataTables.net Plugin, full documentation here: https://datatables.net/ -->
|
||||
<script src="{% static "js/plugins/jquery.dataTables.min.js" %}"></script>
|
||||
<!-- Plugin for Tags, full documentation here: https://github.com/bootstrap-tagsinput/bootstrap-tagsinputs -->
|
||||
<script src="{% static "js/plugins/bootstrap-tagsinput.js" %}"></script>
|
||||
<!-- Plugin for Fileupload, full documentation here: http://www.jasny.net/bootstrap/javascript/#fileinput -->
|
||||
<script src="{% static "js/plugins/jasny-bootstrap.min.js" %}"></script>
|
||||
<!-- Full Calendar Plugin, full documentation here: https://github.com/fullcalendar/fullcalendar -->
|
||||
<script src="{% static "js/plugins/fullcalendar.min.js" %}"></script>
|
||||
<!-- Vector Map plugin, full documentation here: http://jvectormap.com/documentation/ -->
|
||||
<script src="{% static "js/plugins/jquery-jvectormap.js" %}"></script>
|
||||
<!-- Plugin for the Sliders, full documentation here: http://refreshless.com/nouislider/ -->
|
||||
<script src="{% static "js/plugins/nouislider.min.js" %}"></script>
|
||||
<!-- Google Maps Plugin -->
|
||||
<!-- Place this tag in your head or just before your close body tag. -->
|
||||
<!-- <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY_HERE"></script> -->
|
||||
<!-- Chart JS -->
|
||||
<script src="{% static "js/plugins/chartjs.min.js" %}"></script>
|
||||
<!-- Notifications Plugin -->
|
||||
<script src="{% static "js/plugins/bootstrap-notify.js" %}"></script>
|
||||
<!-- Control Center for Black Dashboard: parallax effects, scripts for the example pages etc -->
|
||||
<script src="{% static "js/black-dashboard.min.js" %}"></script>
|
||||
|
||||
<script type="text/javascript" >
|
||||
$(function(){
|
||||
$('#login').focus();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,70 @@
|
|||
{% load static %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="keywords" content="">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="Gregory Trullemans">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="{% static "img/apple-icon.png" %}">
|
||||
<link rel="icon" type="image/png" href="{% static "img/favicon.png" %}">
|
||||
|
||||
<title>List of records</title>
|
||||
|
||||
<!-- Fonts and icons -->
|
||||
<link href="https://fonts.googleapis.com/css?family=Poppins:200,300,400,600,700,800" rel="stylesheet" />
|
||||
<!-- Font Awesome Pro -->
|
||||
<link href="{% static "css/gymnast_report.css" %}" rel="stylesheet" />
|
||||
<link href="{% static "css/font_awesome_all_5.15.3.css" %}" rel="stylesheet" />
|
||||
<link href="{% static "css/black-dashboard_report.css" %}" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<header class="white-content">
|
||||
<div class="row">
|
||||
<div id="header-left" class="col-7 text-12">
|
||||
{{ SITE_TITLE }} - {{ CLUB_NAME }}<br />
|
||||
{{ ADDRESS }} - {{ ZIP }} {{ CITY }}<br />
|
||||
Season {{ season }} - week {{ week_number }}
|
||||
</div>
|
||||
<div id="header-right" class="col-5 text-right text-12">
|
||||
Head Coach : {{ HEAD_COACH }}<br />
|
||||
{{ HEAD_COACH_EMAIL }}<br />
|
||||
{{ today | date:"j F Y" }}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<br />
|
||||
</header>
|
||||
<body class="white-content">
|
||||
<div class="row">
|
||||
<div class="col-12 text-center">
|
||||
<h1>Top 10| chrono scores</h1>
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
<div class="col-6 pl-0">
|
||||
{% for record in records_list %}
|
||||
<h3 class="ml-3">{{ record.score }} - {{ record.gymnast__first_name }} {{ record.gymnast__last_name }}</h3>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="col-6 pl-0">
|
||||
<!-- (seconde partie de la liste) -->
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="row">
|
||||
<div class="col-12">
|
||||
Confirmé par
|
||||
</div>
|
||||
<div class="col-12 text-center">
|
||||
<img src="{% static '/img/chatons_hebdo.png' %}" alt="Chaton hebdo" width="350">
|
||||
</div>
|
||||
</div> -->
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,264 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
<!-- {% block page_title %}.: Search results :.{% endblock %} -->
|
||||
|
||||
{% block title %}Search results{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card mb-0">
|
||||
{% if gymnast_list or skill_list or event_list or place_list or club_list %}
|
||||
{% if gymnast_list %}
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0"> Gymnasts results</h4>
|
||||
</div>
|
||||
<div class="card-body pt-0 pb-1">
|
||||
<div class="table-responsive pb-0">
|
||||
<table class="table tablesorter table-striped" data-sort="table" id="gymnast_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="header text-left" style="width: 20%">Firstname</th>
|
||||
<th class="header text-left" style="width: 20%">Lastname</th>
|
||||
<th class="header text-left" style="width: 15%">Gender</th>
|
||||
<th class="header text-left" style="width: 15%">Age</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for gymnast in gymnast_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td class="text-left">
|
||||
<a href="{% url 'gymnast_details' gymnast.id %}">{{ gymnast.first_name }}</a>
|
||||
</td>
|
||||
<td class="text-left">
|
||||
<a href="{% url 'gymnast_details' gymnast.id %}">{{ gymnast.last_name }}</a>
|
||||
</td>
|
||||
<td class="text-left">{{ gymnast.get_gender_display }}</td>
|
||||
<td class="text-left">{{ gymnast.age }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if skill_list %}
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0"> Skills results</h4>
|
||||
</div>
|
||||
<div class="card-body pt-0 pb-1">
|
||||
<div class="table-responsive pb-0">
|
||||
<table class="table tablesorter table-striped" data-sort="table" id="skill_table">
|
||||
<thead class="text-primary">
|
||||
<tr>
|
||||
<th class="text-left"> Long Label</th>
|
||||
<th class="text-left"> Short Label</th>
|
||||
<th class="text-center"> Age Girl</th>
|
||||
<th class="text-center"> Age Boy</th>
|
||||
<th class="text-center">Notation</th>
|
||||
<th class="header text-center">Diff.</th>
|
||||
<th class="header text-center">Level</th>
|
||||
<th class="header text-center">Rank</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for skill in skill_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td class="text-left"> <a href="{% url 'skill_details' skill.id %}">{{ skill.long_label }}</a></td>
|
||||
<td class="text-left"><a href="{% url 'skill_details' skill.id %}">{{ skill.short_label }}</a></td>
|
||||
<td class="text-right">{{ skill.age_girl_masterised }}</td>
|
||||
<td class="text-right">{{ skill.age_boy_masterised }}</td>
|
||||
<td class="text-center">{{ skill.notation }}</td>
|
||||
<td class="text-center">{{ skill.difficulty }}</td>
|
||||
<td class="text-center">{{ skill.level }}</td>
|
||||
<td class="text-center">{{ skill.rank }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if event_list %}
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0"> Events results</h4>
|
||||
</div>
|
||||
<div class="card-body pt-0 pb-1">
|
||||
<div class="table-responsive pb-0">
|
||||
<table class="table tablesorter table-striped" data-sort="table" id="event_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left">Event</th>
|
||||
<th class="text-left">Type</th>
|
||||
<th class="text-center">Date</th>
|
||||
<th class="text-center"># week</th>
|
||||
<th class="text-left">Place</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for event in event_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td class="text-left"><a href="{% url 'event_details' event.id %}">{{ event.name }}</a></td>
|
||||
<td class="text-left">{{ event.event_type.name }}</td>
|
||||
<td class="text-center">{{ event.date_begin | date:"d-m-Y"}}</td>
|
||||
<td class="text-center">{% if event.number_of_week_from_today < 0 %}{{event.number_of_week_from_today}}{% else %}<span class="text-{% if event.number_of_week_from_today > 12 %}success{% elif event.number_of_week_from_today > 9 %}info{% elif event.number_of_week_from_today > 6 %}warning{% else %}danger{% endif %}"><b>{{event.number_of_week_from_today}}</b></span>{% endif %}</td>
|
||||
<td class="text-left">{{ event.place }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if place_list %}
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0"> Places results</h4>
|
||||
</div>
|
||||
<div class="card-body pt-0 pb-1">
|
||||
<div class="table-responsive pb-0">
|
||||
<table class="table tablesorter table-striped" data-sort="table" id="place_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="header text-left" style="width: 27%">Name</th>
|
||||
<th class="header text-left" style="width: 35%">Address</th>
|
||||
<th class="header text-center" style="width: 10%">Zip</th>
|
||||
<th class="header text-left" style="width: 15%">City</th>
|
||||
<!-- <th class="header text-left" style="width: 4%">#km</th>
|
||||
<th class="header text-left" style="width: 4%">#min</th> -->
|
||||
<!-- <th class="header text-center">Active ?</th> -->
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for place in place_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td class="text-left"><a href="{% url 'place_details' place.id %}">{{ place.name }}</a></td>
|
||||
<td class="text-left">{{ place.address }}</td>
|
||||
<td class="text-left">{{ place.postal}}</td>
|
||||
<td class="text-left">{{ place.city }}</td>
|
||||
<!-- <td class="text-center">{% if place.nbkm %}{{ place.nbkm }}{% else %}0{% endif %}</td>
|
||||
<td class="text-center">{% if place.timing %}{{ place.timing }}{% else %}0{% endif %}</td> -->
|
||||
<!-- <td class="text-center">{{ place.active }}</td> -->
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if club_list %}
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0"> Clubs results</h4>
|
||||
</div>
|
||||
<div class="card-body pt-0 pb-1">
|
||||
<div class="table-responsive pb-0">
|
||||
<table class="table tablesorter table-striped" data-sort="table" id="club_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="header text-left" style="width: 35%">Name</th>
|
||||
<th class="header text-left" style="width: 10%">Acronym</th>
|
||||
<th class="header text-left" style="width: 35%">City</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for club in club_list %}
|
||||
<tr>
|
||||
<td class="text-left"> {{ club.name }}</td>
|
||||
<td class="text-left">{{ club.acronym }}</td>
|
||||
<td class="text-left">{{ club.place.city }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% else %}
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0"> Search results</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>There are no items corresponding to your criterias : "{{ pattern }}"</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('#gymnast_table').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false }, // disable first column
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[1,0], [2,0]]
|
||||
})
|
||||
|
||||
$('#gymnast_table').DataTable({
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
"bInfo" : false,
|
||||
});
|
||||
|
||||
$('#skill_table').tablesorter({
|
||||
headers: {
|
||||
4: { sorter: false },
|
||||
},
|
||||
sortList: [[0,0], [1,0]]
|
||||
})
|
||||
|
||||
$('#skill_table').DataTable({
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
"bInfo" : false,
|
||||
});
|
||||
|
||||
$('#event_table').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false }, // disable first column
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[3,1], [1,0]]
|
||||
});
|
||||
|
||||
$('#event_table').DataTable({
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
"bInfo" : false,
|
||||
});
|
||||
|
||||
$('#place_table').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false }, // disable first column
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[3,0], [1,0]]
|
||||
});
|
||||
|
||||
$('#place_table').DataTable({
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
"bInfo" : false,
|
||||
});
|
||||
|
||||
$('#club_table').tablesorter({
|
||||
sortList: [[0,0], [2,0]]
|
||||
});
|
||||
|
||||
$('#club_table').DataTable({
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
"bInfo" : false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,29 @@
|
|||
from django.contrib.auth import get_user_model
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
|
||||
USER = get_user_model()
|
||||
|
||||
|
||||
class HomeTests(TestCase):
|
||||
def setUp(self):
|
||||
self.user = USER.objects.create(
|
||||
username="jbond", email="james@hms.co.uk", password="007"
|
||||
)
|
||||
|
||||
def test_home_view_anonymous_redirected_statuts_code(self):
|
||||
url = reverse("home")
|
||||
response = self.client.get(url)
|
||||
self.assertEqual(response.status_code, 302)
|
||||
|
||||
def test_home_view_status_code_with_user_connected(self):
|
||||
"""Note: This test will switch to green once we will get rid of whitenoise
|
||||
|
||||
See https://stackoverflow.com/questions/50658241/django-doesnt-load-static-files-valueerrormissing-staticfiles-manifest-entry # pylint: disable=line-too-long
|
||||
"""
|
||||
self.client.login(username="jbond", password="007")
|
||||
|
||||
url = reverse("home")
|
||||
response = self.client.get(url, follow=True)
|
||||
self.assertEqual(response.status_code, 200)
|
|
@ -0,0 +1,16 @@
|
|||
from django.urls import path
|
||||
|
||||
from .views import login, logout, home, search, generate_best_straightjump_listing
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
r"core/record_straightjump/",
|
||||
generate_best_straightjump_listing,
|
||||
name="generate_best_straightjump_listing",
|
||||
),
|
||||
path(r"search/", search, name="global_search"),
|
||||
path(r"login/", login, name="login"),
|
||||
path(r"logout/", logout, name="logout"),
|
||||
path(r"", home, name="home"),
|
||||
]
|
|
@ -0,0 +1,6 @@
|
|||
|
||||
def user_has_group_trainer(user):
|
||||
return user.groups.filter(name='Trainer').exists()
|
||||
|
||||
def user_has_group_gymnast(user):
|
||||
return user.groups.filter(name='Gymnast').exists()
|
|
@ -0,0 +1,252 @@
|
|||
from datetime import timedelta
|
||||
|
||||
from django.db.models import Q
|
||||
from django.shortcuts import render
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
|
||||
from jarvis.objective.models import Routine
|
||||
from jarvis.profiles.models import Profile
|
||||
from jarvis.followup.models import Skill, Point, Chrono
|
||||
from jarvis.location.models import Place, Club
|
||||
from jarvis.people.models import Gymnast
|
||||
from jarvis.people.views import gymnast_details
|
||||
from jarvis.planning.models import Event
|
||||
from django.db.models import Max
|
||||
from django.conf import settings
|
||||
from .models import Citation
|
||||
from jarvis.tools.models import from_date_to_week_number
|
||||
|
||||
from weasyprint import HTML, CSS
|
||||
import pendulum
|
||||
|
||||
|
||||
def login(request):
|
||||
"""
|
||||
Formulaire d'authentifictation.
|
||||
"""
|
||||
|
||||
if request.method == "POST":
|
||||
username = request.POST["login"]
|
||||
password = request.POST["password"]
|
||||
|
||||
user = authenticate(username=username, password=password)
|
||||
|
||||
if user is not None: # Pq pas "if user:" ??
|
||||
if user.is_active:
|
||||
auth_login(request, user)
|
||||
try:
|
||||
profile = Profile.objects.get(user=user)
|
||||
request.session["profileid"] = profile.id
|
||||
request.session["template"] = profile.template_color
|
||||
request.session["sidebar"] = profile.sidebar_color
|
||||
request.session["is_sidebar_minified"] = profile.is_sidebar_minified
|
||||
except Exception:
|
||||
pass
|
||||
# request.session["clubid"] = request.POST.get("clubid", None)
|
||||
return HttpResponseRedirect(reverse("home"))
|
||||
|
||||
context = {"message": "Account disabled."}
|
||||
else:
|
||||
context = {"message": "Wrong login/password."}
|
||||
else:
|
||||
context = {}
|
||||
|
||||
return render(request, "login.html", context)
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET"])
|
||||
def logout(request):
|
||||
"""
|
||||
Fonction de déconnexion
|
||||
"""
|
||||
auth_logout(request)
|
||||
return HttpResponseRedirect(reverse("login"))
|
||||
|
||||
|
||||
def next_birthdays(request, number_of_birthday):
|
||||
"""
|
||||
Renvoie la liste des `number_of_birthday` prochains anniversaires.
|
||||
"""
|
||||
birthday_list = sorted(
|
||||
Gymnast.objects.all(), key=lambda t: t.next_birthday_in_days
|
||||
)[:number_of_birthday]
|
||||
return birthday_list
|
||||
|
||||
|
||||
# @lru_cache()
|
||||
# def get_last_updated_gymnasts(expiration_date):
|
||||
# ...
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET"])
|
||||
def home(request):
|
||||
"""
|
||||
Génère la page d'accueil du site basée sur la saison (si celle-ci est connue)
|
||||
"""
|
||||
event_list = Event.objects.filter(date_begin__gte=timezone.now()).order_by(
|
||||
"date_begin"
|
||||
)[:10]
|
||||
|
||||
quote = Citation.objects.order_by("?").first()
|
||||
# print(quote)
|
||||
|
||||
# mettre tout ca en cache.
|
||||
last_updated_gymnast = Gymnast.objects.filter(
|
||||
Q(mindstate__created_at__gt=request.user.last_login)
|
||||
| Q(points__created_at__gt=request.user.last_login)
|
||||
| Q(chronos__created_at__gt=request.user.last_login)
|
||||
| Q(accident__created_at__gt=request.user.last_login)
|
||||
| Q(known_skills__created_at__gt=request.user.last_login)
|
||||
).distinct()
|
||||
|
||||
limit_date = timezone.now() - timedelta(days=14)
|
||||
waiting_update_gymnast = Gymnast.objects.exclude(
|
||||
Q(is_active=False)
|
||||
| Q(mindstate__created_at__gte=limit_date)
|
||||
| Q(points__created_at__gte=limit_date)
|
||||
| Q(chronos__created_at__gte=limit_date)
|
||||
| Q(accident__created_at__gte=limit_date)
|
||||
| Q(known_skills__created_at__gte=limit_date)
|
||||
).distinct()
|
||||
|
||||
nb_active_gymnast = Gymnast.objects.filter(is_active=True).count()
|
||||
nb_event = Event.objects.all().count()
|
||||
nb_skill = Skill.objects.all().count()
|
||||
nb_routine = Routine.objects.all().count()
|
||||
nb_score = Point.objects.all().count()
|
||||
nb_club = Club.objects.all().count()
|
||||
# percentage_week = int(
|
||||
# (get_number_of_weeks_between(datetime(2021, 9, 1), datetime.now()) / 52) * 100
|
||||
# )
|
||||
|
||||
date_begin = pendulum.now().date()
|
||||
season, week_number = from_date_to_week_number(date_begin)
|
||||
percentage_week = (week_number / 52) * 100
|
||||
|
||||
birthday_list = next_birthdays(request, 10)
|
||||
|
||||
# check if gymnast have point
|
||||
# ---------------------------
|
||||
# 1. récupérer tous les évènements passés
|
||||
# 2. pour chaque event, vérifier que tous les gymnastes renseignés
|
||||
# dans les participants ont des points associés.
|
||||
# S'il n'y a pas de point, faire une alerte à l'utilisateur qui se connecte.
|
||||
|
||||
# Check if gymnast have update
|
||||
# -----------------------------
|
||||
# lister tous les gymnastes qui n'ont pas eu d'update depuis... 2 semaines ?
|
||||
# peut-être le paramètre (en jour) devrait être stocké en DB.
|
||||
# S'il n'y a pas d'update, faire une alerte à l'utilisateur qui se connecte.
|
||||
|
||||
context = {
|
||||
"quote": quote,
|
||||
"event_list": event_list,
|
||||
"last_updated_gymnast": last_updated_gymnast,
|
||||
"waiting_update_gymnast": waiting_update_gymnast,
|
||||
"nb_active_gymnast": nb_active_gymnast,
|
||||
"nb_event": nb_event,
|
||||
"nb_skill": nb_skill,
|
||||
"nb_routine": nb_routine,
|
||||
"nb_score": nb_score,
|
||||
"nb_club": nb_club,
|
||||
"percentage_week": percentage_week,
|
||||
"birthday_list": birthday_list,
|
||||
}
|
||||
return render(request, "dashboard/dashboard.html", context)
|
||||
|
||||
|
||||
@login_required
|
||||
@require_http_methods(["GET"])
|
||||
def search(request):
|
||||
"""
|
||||
Recherche globale au travers de toutes les applications.
|
||||
"""
|
||||
pattern = request.GET.get("pattern", None)
|
||||
|
||||
if pattern:
|
||||
gymnast_list = Gymnast.objects.filter(
|
||||
Q(last_name__icontains=pattern) | Q(first_name__icontains=pattern)
|
||||
)
|
||||
|
||||
if gymnast_list.count() == 1:
|
||||
gymnast = gymnast_list.first()
|
||||
return gymnast_details(request, gymnast.id)
|
||||
else:
|
||||
skill_list = Skill.objects.filter(
|
||||
Q(long_label__icontains=pattern) | Q(short_label__icontains=pattern)
|
||||
)
|
||||
event_list = Event.objects.filter(
|
||||
Q(name__icontains=pattern) | Q(place__name__icontains=pattern)
|
||||
)
|
||||
place_list = Place.objects.filter(
|
||||
Q(name__icontains=pattern) | Q(city__icontains=pattern)
|
||||
)
|
||||
club_list = Club.objects.filter(
|
||||
Q(name__icontains=pattern)
|
||||
| Q(place__name__icontains=pattern)
|
||||
| Q(place__city__icontains=pattern)
|
||||
)
|
||||
|
||||
context = {
|
||||
"gymnast_list": gymnast_list,
|
||||
"skill_list": skill_list,
|
||||
"event_list": event_list,
|
||||
"place_list": place_list,
|
||||
"club_list": club_list,
|
||||
"pattern": pattern,
|
||||
}
|
||||
else:
|
||||
context = {}
|
||||
|
||||
return render(request, "search/results.html", context)
|
||||
|
||||
|
||||
def generate_best_straightjump_listing(request):
|
||||
""" """
|
||||
|
||||
date_begin = pendulum.now().date()
|
||||
season, week_number = from_date_to_week_number(date_begin)
|
||||
|
||||
records_list = (
|
||||
Chrono.objects.values("gymnast__last_name", "gymnast__first_name")
|
||||
.annotate(score=Max("score"))
|
||||
.order_by("-score") # [:16]
|
||||
)
|
||||
|
||||
context = {
|
||||
"SITE_TITLE": settings.SITE_TITLE,
|
||||
"CLUB_NAME": settings.CLUB_NAME,
|
||||
"ADDRESS": settings.ADDRESS,
|
||||
"CITY": settings.CITY,
|
||||
"ZIP": settings.ZIP,
|
||||
"HEAD_COACH": settings.HEAD_COACH,
|
||||
"MOBILE_PHONE": settings.MOBILE_PHONE,
|
||||
"HEAD_COACH_EMAIL": settings.HEAD_COACH_EMAIL,
|
||||
"week_number": week_number,
|
||||
"today": date_begin,
|
||||
"records_list": records_list,
|
||||
}
|
||||
# return render(request, "core/records_10.html", context)
|
||||
response = HttpResponse(content_type="application/pdf")
|
||||
response["Content-Disposition"] = "attachment; filename=report-top_straightjump.pdf"
|
||||
|
||||
html = render_to_string("jarvis/core/records_10.html", context)
|
||||
|
||||
# font_config = FontConfiguration()
|
||||
HTML(string=html, base_url=request.build_absolute_uri()).write_pdf(
|
||||
response,
|
||||
stylesheets=[
|
||||
CSS(settings.STATICFILES_DIRS[0] + "/css/gymnast_report.css"),
|
||||
CSS(settings.STATICFILES_DIRS[0] + "/css/black-dashboard_report.css"),
|
||||
CSS(settings.STATICFILES_DIRS[0] + "/css/font_awesome_all_5.15.3.css"),
|
||||
],
|
||||
) # , font_config=font_config)
|
||||
return response
|
|
@ -0,0 +1,269 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from django_admin_listfilter_dropdown.filters import (
|
||||
DropdownFilter,
|
||||
ChoiceDropdownFilter,
|
||||
RelatedDropdownFilter,
|
||||
)
|
||||
|
||||
from .models import (
|
||||
Plan,
|
||||
Note,
|
||||
Point,
|
||||
Chrono,
|
||||
Accident,
|
||||
MindState,
|
||||
Intensity,
|
||||
HeightWeight,
|
||||
LearnedSkill,
|
||||
ChronoDetails,
|
||||
GymnastHasRoutine,
|
||||
SeasonInformation,
|
||||
NumberOfRoutineDone,
|
||||
CompetitivePointsStats,
|
||||
)
|
||||
|
||||
|
||||
class ChronoAdmin(admin.ModelAdmin):
|
||||
model = Chrono
|
||||
|
||||
list_display = ("date", "gymnast", "tof", "chrono_type")
|
||||
readonly_fields = ("season", "week_number", "created_at", "updated_at")
|
||||
list_filter = ("chrono_type", ("gymnast", RelatedDropdownFilter))
|
||||
# list_filter = (("gymnast", RelatedDropdownFilter),)
|
||||
autocomplete_fields = ("gymnast",)
|
||||
date_hierarchy = "date"
|
||||
related_search_fields = {"gymnast": ("last_name", "first_name")}
|
||||
|
||||
|
||||
class ChronoDetailsAdmin(admin.ModelAdmin):
|
||||
model = ChronoDetails
|
||||
|
||||
list_display = ("chrono", "order", "value") # "chrono__gymnast",
|
||||
list_filter = (
|
||||
("chrono", RelatedDropdownFilter),
|
||||
# ('chrono__gymnast', RelatedDropdownFilter),
|
||||
)
|
||||
related_search_fields = {
|
||||
"chrono": ("date", "chrono__gymnast__last_name", "chrono__gymnast__first_name")
|
||||
}
|
||||
|
||||
|
||||
class LearnedSkillAdmin(admin.ModelAdmin):
|
||||
model = LearnedSkill
|
||||
|
||||
list_display = ("gymnast", "skill", "learning_step", "date")
|
||||
readonly_fields = ("season", "week_number", "created_at", "updated_at")
|
||||
list_filter = (
|
||||
("gymnast", RelatedDropdownFilter),
|
||||
("skill", RelatedDropdownFilter),
|
||||
"learning_step",
|
||||
)
|
||||
search_fields = ("gymnast", "skill")
|
||||
autocomplete_fields = ("gymnast", "skill")
|
||||
date_hierarchy = "date"
|
||||
|
||||
|
||||
class PointAdmin(admin.ModelAdmin):
|
||||
model = Point
|
||||
|
||||
list_display = (
|
||||
"gymnast",
|
||||
"point_execution",
|
||||
"point_difficulty",
|
||||
"point_time_of_flight",
|
||||
"total",
|
||||
)
|
||||
readonly_fields = ("created_at", "updated_at")
|
||||
ordering = ("gymnast",)
|
||||
list_filter = (
|
||||
("gymnast", RelatedDropdownFilter),
|
||||
("event", RelatedDropdownFilter),
|
||||
("routine_type", DropdownFilter),
|
||||
)
|
||||
search_fields = (
|
||||
"gymnast__first_name",
|
||||
"gymnast__last_name",
|
||||
"event__place_name",
|
||||
"event__place_city",
|
||||
"event__place__country_name",
|
||||
)
|
||||
autocomplete_fields = ("gymnast", "event")
|
||||
|
||||
|
||||
class AccidentAdmin(admin.ModelAdmin):
|
||||
model = Accident
|
||||
|
||||
fields = ("date", "gymnast", "skill", "informations") # educative
|
||||
readonly_fields = ("season", "week_number", "created_at", "updated_at")
|
||||
list_display = ("date", "gymnast", "skill") # educative
|
||||
list_filter = ("date",)
|
||||
date_hierarchy = "date"
|
||||
search_fields = ("date", "gymnast") # educative
|
||||
autocomplete_fields = ("gymnast", "skill")
|
||||
|
||||
|
||||
class MindStateAdmin(admin.ModelAdmin):
|
||||
model = MindState
|
||||
|
||||
fields = ("gymnast", "date", "score", "informations")
|
||||
readonly_fields = ("season", "week_number", "created_at", "updated_at")
|
||||
list_display = ("date", "gymnast", "score")
|
||||
list_filter = (
|
||||
"date",
|
||||
("gymnast", RelatedDropdownFilter),
|
||||
)
|
||||
autocomplete_fields = ("gymnast",)
|
||||
date_hierarchy = "date"
|
||||
|
||||
|
||||
class GymnastHasRoutineAdmin(admin.ModelAdmin):
|
||||
model = GymnastHasRoutine
|
||||
|
||||
list_display = ("gymnast", "routine", "routine_type", "date_begin", "date_end")
|
||||
list_filter = (
|
||||
("gymnast", RelatedDropdownFilter),
|
||||
("routine_type", DropdownFilter), # A supprimer ?
|
||||
)
|
||||
search_fields = ("gymnast", "routine")
|
||||
autocomplete_fields = ("gymnast", "routine")
|
||||
|
||||
|
||||
class NumberOfRoutineDoneAdmin(admin.ModelAdmin):
|
||||
model = NumberOfRoutineDone
|
||||
|
||||
list_display = (
|
||||
"gymnast",
|
||||
"routine_type",
|
||||
"date",
|
||||
"number_of_successes",
|
||||
"number_of_try",
|
||||
)
|
||||
list_filter = (
|
||||
("gymnast", RelatedDropdownFilter),
|
||||
("routine_type", DropdownFilter), # A supprimer ?
|
||||
)
|
||||
autocomplete_fields = ("gymnast", "routine")
|
||||
date_hierarchy = "date"
|
||||
|
||||
|
||||
class HeightWeightAdmin(admin.ModelAdmin):
|
||||
model = HeightWeight
|
||||
|
||||
list_display = ("gymnast", "height", "hips_height", "weight", "date")
|
||||
readonly_fields = ("season", "week_number")
|
||||
list_filter = (("gymnast", RelatedDropdownFilter),)
|
||||
date_hierarchy = "date"
|
||||
autocomplete_fields = ("gymnast",)
|
||||
|
||||
|
||||
class PlanAdmin(admin.ModelAdmin):
|
||||
model = Plan
|
||||
|
||||
list_display = ("gymnast", "date", "educative")
|
||||
readonly_fields = ("season", "week_number", "created_at", "updated_at")
|
||||
list_filter = (
|
||||
("gymnast", RelatedDropdownFilter),
|
||||
("educative", RelatedDropdownFilter),
|
||||
)
|
||||
search_fields = (
|
||||
"gymnast__firstname",
|
||||
"gymnast__lastname",
|
||||
"educative__long_label",
|
||||
"educative__short_label",
|
||||
)
|
||||
date_hierarchy = "date"
|
||||
autocomplete_fields = ("gymnast",)
|
||||
|
||||
|
||||
class NoteAdmin(admin.ModelAdmin):
|
||||
model = Note
|
||||
|
||||
list_display = ("gymnast", "coach", "date", "created_at")
|
||||
readonly_fields = ("season", "week_number", "created_at", "updated_at")
|
||||
list_filter = (
|
||||
("gymnast", RelatedDropdownFilter),
|
||||
("coach", RelatedDropdownFilter),
|
||||
"status",
|
||||
)
|
||||
search_fields = (
|
||||
"gymnast__firstname",
|
||||
"gymnast__lastname",
|
||||
"coach__last_name",
|
||||
"coach__first_name",
|
||||
)
|
||||
date_hierarchy = "created_at"
|
||||
autocomplete_fields = ("gymnast",)
|
||||
|
||||
|
||||
class IntensityAdmin(admin.ModelAdmin):
|
||||
model = Intensity
|
||||
|
||||
list_display = (
|
||||
"gymnast",
|
||||
"time",
|
||||
"difficulty",
|
||||
"quantity_of_skill",
|
||||
"number_of_passes",
|
||||
)
|
||||
readonly_fields = ("season", "week_number")
|
||||
list_filter = (("gymnast", RelatedDropdownFilter),)
|
||||
search_fields = (
|
||||
"gymnast__firstname",
|
||||
"gymnast__lastname",
|
||||
)
|
||||
autocomplete_fields = ("gymnast",)
|
||||
|
||||
|
||||
class SeasonInformationAdmin(admin.ModelAdmin):
|
||||
model = SeasonInformation
|
||||
|
||||
list_display = (
|
||||
"gymnast",
|
||||
"season",
|
||||
"category",
|
||||
"number_of_training_sessions_per_week",
|
||||
"number_of_hours_per_week",
|
||||
"number_of_s_and_c_sessions_per_week",
|
||||
"number_of_s_and_c_hours_per_week",
|
||||
# "club",
|
||||
)
|
||||
list_filter = (("gymnast", RelatedDropdownFilter),)
|
||||
search_fields = (
|
||||
"gymnast__firstname",
|
||||
"gymnast__lastname",
|
||||
)
|
||||
autocomplete_fields = ("gymnast",)
|
||||
|
||||
|
||||
class CompetitivePointsStatsAdmin(admin.ModelAdmin):
|
||||
model = CompetitivePointsStats
|
||||
|
||||
list_display = (
|
||||
"label",
|
||||
"age_category",
|
||||
"gender",
|
||||
"statistic_type",
|
||||
"total",
|
||||
"routine_type",
|
||||
)
|
||||
list_filter = (
|
||||
("statistic_type", ChoiceDropdownFilter),
|
||||
("routine_type", ChoiceDropdownFilter), # A supprimer ?
|
||||
)
|
||||
|
||||
|
||||
admin.site.register(Plan, PlanAdmin)
|
||||
admin.site.register(Note, NoteAdmin)
|
||||
admin.site.register(Point, PointAdmin)
|
||||
admin.site.register(Chrono, ChronoAdmin)
|
||||
admin.site.register(Accident, AccidentAdmin)
|
||||
admin.site.register(MindState, MindStateAdmin)
|
||||
admin.site.register(Intensity, IntensityAdmin)
|
||||
admin.site.register(LearnedSkill, LearnedSkillAdmin)
|
||||
admin.site.register(HeightWeight, HeightWeightAdmin)
|
||||
admin.site.register(ChronoDetails, ChronoDetailsAdmin)
|
||||
admin.site.register(SeasonInformation, SeasonInformationAdmin)
|
||||
admin.site.register(GymnastHasRoutine, GymnastHasRoutineAdmin)
|
||||
admin.site.register(NumberOfRoutineDone, NumberOfRoutineDoneAdmin)
|
||||
admin.site.register(CompetitivePointsStats, CompetitivePointsStatsAdmin)
|
|
@ -0,0 +1,6 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class FollowupConfig(AppConfig):
|
||||
default_auto_field = "django.db.models.BigAutoField"
|
||||
name = "jarvis.followup"
|
|
@ -0,0 +1,657 @@
|
|||
from datetime import date
|
||||
|
||||
from django import forms
|
||||
|
||||
from .models import (
|
||||
Plan,
|
||||
Note,
|
||||
Point,
|
||||
Chrono,
|
||||
Accident,
|
||||
MindState,
|
||||
Intensity,
|
||||
HeightWeight,
|
||||
LearnedSkill,
|
||||
GymnastHasRoutine,
|
||||
SeasonInformation,
|
||||
NumberOfRoutineDone,
|
||||
)
|
||||
|
||||
|
||||
class ChronoForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Chrono
|
||||
fields = ("gymnast", "date", "chrono_type", "score_type", "score", "tof")
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"date": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
"placeholder": date.today().strftime("%Y-%m-%d"),
|
||||
"value": date.today().strftime("%Y-%m-%d"),
|
||||
}
|
||||
),
|
||||
"chrono_type": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
"score_type": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
"score": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xx,xxx",
|
||||
"min": "0.01",
|
||||
"step": "0.01",
|
||||
}
|
||||
),
|
||||
"tof": forms.HiddenInput(),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class LearnedSkillForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = LearnedSkill
|
||||
fields = ("gymnast", "skill", "learning_step", "date")
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"skill": forms.HiddenInput(),
|
||||
"date": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
"placeholder": date.today().strftime("%Y-%m-%d"),
|
||||
"value": date.today().strftime("%Y-%m-%d"),
|
||||
}
|
||||
),
|
||||
"learning_step": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
skill_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching skill…",
|
||||
"data-ref": "#id_skill",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class ScoreForm(forms.ModelForm):
|
||||
class Meta:
|
||||
ROUTINETYPE_CHOICE = (
|
||||
(0, "Routine 1"),
|
||||
(1, "Routine 2"),
|
||||
(2, "Final's routine"),
|
||||
)
|
||||
|
||||
model = Point
|
||||
fields = (
|
||||
"gymnast",
|
||||
"event",
|
||||
"routine_type",
|
||||
"point_difficulty",
|
||||
"point_time_of_flight",
|
||||
"point_execution",
|
||||
"point_horizontal_displacement",
|
||||
"penality",
|
||||
"total",
|
||||
)
|
||||
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"event": forms.HiddenInput(),
|
||||
"routine_type": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
"point_execution": forms.NumberInput(
|
||||
attrs={"class": "form-control", "placeholder": "xx,xx", "min": "0"}
|
||||
),
|
||||
"point_difficulty": forms.NumberInput(
|
||||
attrs={"class": "form-control", "placeholder": "xx,xx", "min": "0"}
|
||||
),
|
||||
"point_time_of_flight": forms.NumberInput(
|
||||
attrs={"class": "form-control", "placeholder": "xx,xx", "min": "0"}
|
||||
),
|
||||
"point_horizontal_displacement": forms.NumberInput(
|
||||
attrs={"class": "form-control", "placeholder": "x,xx", "min": "0"}
|
||||
),
|
||||
"penality": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xx,xx",
|
||||
"value": "0",
|
||||
"min": "0",
|
||||
}
|
||||
),
|
||||
"total": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "000,000",
|
||||
"readonly": "readonly",
|
||||
"maxlength": "6",
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
event_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching…",
|
||||
"data-ref": "#id_event",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
add_to_chrono = forms.NullBooleanField(
|
||||
required=False,
|
||||
widget=forms.CheckboxInput(
|
||||
attrs={"class": "form-control form-check-input ml-0 mt-0"}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class AccidentForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Accident
|
||||
fields = ("gymnast", "date", "nb_week_off", "informations")
|
||||
widgets = {
|
||||
"date": forms.DateInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
"placeholder": date.today().strftime("%Y-%m-%d"),
|
||||
"value": date.today().strftime("%Y-%m-%d"),
|
||||
}
|
||||
),
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"skill": forms.HiddenInput(),
|
||||
"nb_week_off": forms.NumberInput(
|
||||
attrs={"class": "form-control", "placeholder": "xx"}
|
||||
),
|
||||
"informations": forms.Textarea(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Informations about accident: context (why, where, …), consequencies, re-education exercices, …", # pylint: disable=line-too-long
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
skill_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching skill…",
|
||||
"data-ref": "#id_skill",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class MindStateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = MindState
|
||||
fields = ("gymnast", "date", "score", "informations")
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"date": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
"placeholder": date.today().strftime("%Y-%m-%d"),
|
||||
"value": date.today().strftime("%Y-%m-%d"),
|
||||
}
|
||||
),
|
||||
"event": forms.HiddenInput(),
|
||||
"score": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "x",
|
||||
"min": "0",
|
||||
"max": "10",
|
||||
}
|
||||
),
|
||||
"informations": forms.Textarea(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Informations about the psychological state of mind : context (why, where, …), possible consequencies, …", # pylint: disable=line-too-long
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
event_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching event…",
|
||||
"data-ref": "#id_event",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class GymnastHasRoutineForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = GymnastHasRoutine
|
||||
fields = ("gymnast", "routine", "routine_type", "date_begin", "date_end")
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"routine": forms.HiddenInput(),
|
||||
"routine_type": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
"date_begin": forms.DateInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
}
|
||||
),
|
||||
"date_end": forms.DateInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
routine_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching routine…",
|
||||
"data-ref": "#id_routine",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class HeightWeightForm(forms.ModelForm):
|
||||
"""
|
||||
Formulaire d'enregistrement d'un couple taille/poids
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = HeightWeight
|
||||
fields = ("gymnast", "date", "height", "hips_height", "weight")
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"date": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
"placeholder": date.today().strftime("%Y-%m-%d"),
|
||||
"value": date.today().strftime("%Y-%m-%d"),
|
||||
}
|
||||
),
|
||||
"height": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xxx,x",
|
||||
"min": "100",
|
||||
"max": "220",
|
||||
}
|
||||
),
|
||||
"hips_height": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xxx,x",
|
||||
"min": "50",
|
||||
"max": "110",
|
||||
}
|
||||
),
|
||||
"weight": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xxx,x",
|
||||
"min": "20",
|
||||
"max": "110",
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class NumberOfRoutineDoneForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = NumberOfRoutineDone
|
||||
fields = (
|
||||
"gymnast",
|
||||
"routine",
|
||||
"routine_type",
|
||||
"date",
|
||||
"number_of_try",
|
||||
"number_of_successes",
|
||||
)
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"routine": forms.HiddenInput(),
|
||||
"routine_type": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
"date": forms.DateInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
}
|
||||
),
|
||||
"number_of_try": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "x",
|
||||
"min": "0",
|
||||
"max": "50",
|
||||
}
|
||||
),
|
||||
"number_of_successes": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "x",
|
||||
"min": "0",
|
||||
"max": "50",
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
routine_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching routine…",
|
||||
"data-ref": "#id_routine",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class PlanForm(forms.ModelForm):
|
||||
"""
|
||||
Formulaire d'enregistrement d'un plan (gymnast qui doit faire un eductative pour une date X)
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
model = Plan
|
||||
fields = (
|
||||
"date",
|
||||
"gymnast",
|
||||
"educative",
|
||||
"learning_step",
|
||||
"is_done",
|
||||
"informations",
|
||||
)
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"educative": forms.HiddenInput(),
|
||||
"date": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
"placeholder": date.today().strftime("%Y-%m-%d"),
|
||||
"value": date.today().strftime("%Y-%m-%d"),
|
||||
}
|
||||
),
|
||||
"learning_step": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
"is_done": forms.CheckboxInput(
|
||||
attrs={"class": "form-control form-check-input ml-0 mt-0"}
|
||||
),
|
||||
"informations": forms.Textarea(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Informations about gymnast for this particular skill: usual mistake, fear, …", # pylint: disable=line-too-long
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
educative_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching skill…",
|
||||
"data-ref": "#id_skill",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class NoteForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Note
|
||||
fields = ("gymnast", "coach", "status", "informations", "date")
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"coach": forms.HiddenInput(),
|
||||
"status": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
"date": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
"placeholder": date.today().strftime("%Y-%m-%d"),
|
||||
"value": date.today().strftime("%Y-%m-%d"),
|
||||
}
|
||||
),
|
||||
"informations": forms.Textarea(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Informations about gymnast: fear, lost skill syndrom, …", # pylint: disable=line-too-long
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class IntensityForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Intensity
|
||||
fields = (
|
||||
"gymnast",
|
||||
"time",
|
||||
"difficulty",
|
||||
"quantity_of_skill",
|
||||
"number_of_passes",
|
||||
"informations",
|
||||
"date",
|
||||
)
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"time": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xxx",
|
||||
}
|
||||
),
|
||||
"difficulty": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xxx",
|
||||
}
|
||||
),
|
||||
"quantity_of_skill": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xxx",
|
||||
}
|
||||
),
|
||||
"number_of_passes": forms.NumberInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "xxx",
|
||||
}
|
||||
),
|
||||
"date": forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control datepicker",
|
||||
"placeholder": date.today().strftime("%Y-%m-%d"),
|
||||
"value": date.today().strftime("%Y-%m-%d"),
|
||||
}
|
||||
),
|
||||
"informations": forms.Textarea(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Informations about intensity: did you do your full program, did you stop before the end, why did you stop before the end, …", # pylint: disable=line-too-long
|
||||
}
|
||||
),
|
||||
}
|
||||
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class SeasonInformationForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = SeasonInformation
|
||||
fields = (
|
||||
"gymnast",
|
||||
"season",
|
||||
"number_of_training_sessions_per_week",
|
||||
"number_of_hours_per_week",
|
||||
"number_of_s_and_c_sessions_per_week",
|
||||
"number_of_s_and_c_hours_per_week",
|
||||
"category",
|
||||
"club",
|
||||
)
|
||||
widgets = {
|
||||
"gymnast": forms.HiddenInput(),
|
||||
"season": forms.TextInput(
|
||||
attrs={"class": "form-control", "placeholder": "202x-202y"}
|
||||
),
|
||||
"number_of_training_sessions_per_week": forms.TextInput(
|
||||
attrs={"class": "form-control", "placeholder": "5"}
|
||||
),
|
||||
"number_of_hours_per_week": forms.TextInput(
|
||||
attrs={"class": "form-control", "placeholder": "11.5"}
|
||||
),
|
||||
"number_of_s_and_c_sessions_per_week": forms.TextInput(
|
||||
attrs={"class": "form-control", "placeholder": "5"}
|
||||
),
|
||||
"number_of_s_and_c_hours_per_week": forms.TextInput(
|
||||
attrs={"class": "form-control", "placeholder": "11.5"}
|
||||
),
|
||||
"category": forms.Select(attrs={"class": "form-control selectpicker"}),
|
||||
"club": forms.HiddenInput(),
|
||||
}
|
||||
|
||||
club_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching club…",
|
||||
"data-ref": "#id_club",
|
||||
}
|
||||
),
|
||||
)
|
||||
gymnast_related = forms.CharField(
|
||||
required=False,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"placeholder": "Searching gymnast…",
|
||||
"data-ref": "#id_gymnast",
|
||||
}
|
||||
),
|
||||
)
|
|
@ -0,0 +1,369 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-02 06:43
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
("planning", "0001_initial"),
|
||||
("people", "0001_initial"),
|
||||
("objective", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Point",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"routine_type",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[(0, "Routine 1"), (1, "Routine 2"), (2, "Final")]
|
||||
),
|
||||
),
|
||||
(
|
||||
"point_execution",
|
||||
models.DecimalField(decimal_places=3, max_digits=5),
|
||||
),
|
||||
(
|
||||
"point_difficulty",
|
||||
models.DecimalField(decimal_places=1, max_digits=3),
|
||||
),
|
||||
(
|
||||
"point_time_of_flight",
|
||||
models.DecimalField(decimal_places=3, max_digits=5),
|
||||
),
|
||||
(
|
||||
"point_horizontal_displacement",
|
||||
models.DecimalField(decimal_places=3, max_digits=4),
|
||||
),
|
||||
("penality", models.DecimalField(decimal_places=1, max_digits=3)),
|
||||
("total", models.DecimalField(decimal_places=3, max_digits=6)),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"event",
|
||||
models.ForeignKey(
|
||||
default=None,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="planning.event",
|
||||
),
|
||||
),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
default=None,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="points",
|
||||
to="people.gymnast",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="MindState",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"informations",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="Only MarkDown is authorized",
|
||||
null=True,
|
||||
verbose_name="Comments",
|
||||
),
|
||||
),
|
||||
(
|
||||
"date",
|
||||
models.DateField(default=datetime.date.today, verbose_name="Date"),
|
||||
),
|
||||
("score", models.PositiveSmallIntegerField(verbose_name="Score")),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"event",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
default=None,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="mindstate",
|
||||
to="planning.event",
|
||||
),
|
||||
),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
default=None,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="mindstate",
|
||||
to="people.gymnast",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="GymnastHasRoutine",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"routine_type",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(1, "L1"),
|
||||
(2, "L2"),
|
||||
(3, "L3"),
|
||||
(4, "L4"),
|
||||
(5, "L1S"),
|
||||
(6, "L2S"),
|
||||
(7, "L3S"),
|
||||
(8, "L4S"),
|
||||
],
|
||||
default="1",
|
||||
verbose_name="Type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"datebegin",
|
||||
models.DateField(
|
||||
default=datetime.date.today, verbose_name="Date begin"
|
||||
),
|
||||
),
|
||||
(
|
||||
"dateend",
|
||||
models.DateField(
|
||||
blank=True,
|
||||
default=datetime.date.today,
|
||||
null=True,
|
||||
verbose_name="Date end",
|
||||
),
|
||||
),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="routines",
|
||||
to="people.gymnast",
|
||||
verbose_name="Gymnast",
|
||||
),
|
||||
),
|
||||
(
|
||||
"routine",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="done_by",
|
||||
to="objective.routine",
|
||||
verbose_name="Routine",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Gymnast Has Routine",
|
||||
"verbose_name_plural": "Gymnast Has Routines",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Chrono",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"type",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "10 |"),
|
||||
(1, "L1"),
|
||||
(2, "L2"),
|
||||
(3, "L3"),
|
||||
(4, "L4"),
|
||||
(99, "Other"),
|
||||
],
|
||||
verbose_name="Routine type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"score_type",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[(0, "Chrono"), (1, "ToF")], verbose_name="Score type"
|
||||
),
|
||||
),
|
||||
("score", models.DecimalField(decimal_places=3, max_digits=5)),
|
||||
(
|
||||
"tof",
|
||||
models.DecimalField(
|
||||
blank=True, decimal_places=3, max_digits=5, null=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"date",
|
||||
models.DateField(default=datetime.date.today, verbose_name="Date"),
|
||||
),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="chronos",
|
||||
to="people.gymnast",
|
||||
verbose_name="gymnast",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Chrono",
|
||||
"verbose_name_plural": "Chronos",
|
||||
"ordering": ["date", "gymnast"],
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Accident",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"informations",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="Only MarkDown is authorized",
|
||||
null=True,
|
||||
verbose_name="Comments",
|
||||
),
|
||||
),
|
||||
("date", models.DateField(verbose_name="Date")),
|
||||
(
|
||||
"nb_week_off",
|
||||
models.SmallIntegerField(
|
||||
blank=True, null=True, verbose_name="# week off"
|
||||
),
|
||||
),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="accident",
|
||||
to="people.gymnast",
|
||||
verbose_name="Gymnast",
|
||||
),
|
||||
),
|
||||
(
|
||||
"skill",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="accident",
|
||||
to="objective.skill",
|
||||
verbose_name="Skill",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Accident",
|
||||
"verbose_name_plural": "Accidents",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="LearnedSkill",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"cando",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "No"),
|
||||
(1, "With help"),
|
||||
(2, "Without help"),
|
||||
(3, "Chained"),
|
||||
],
|
||||
verbose_name="Can do type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"date",
|
||||
models.DateField(default=datetime.date.today, verbose_name="Date"),
|
||||
),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="can_do_skill",
|
||||
to="people.gymnast",
|
||||
verbose_name="gymnast",
|
||||
),
|
||||
),
|
||||
(
|
||||
"skill",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="done_by_gymnasts",
|
||||
to="objective.skill",
|
||||
verbose_name="Skill",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Learned Skill",
|
||||
"verbose_name_plural": "Learned Skills",
|
||||
"unique_together": {("gymnast", "skill", "date")},
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-02 17:02
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("people", "0001_initial"),
|
||||
("followup", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="learnedskill",
|
||||
name="gymnast",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="known_skills",
|
||||
to="people.gymnast",
|
||||
verbose_name="gymnast",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-02 17:20
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("objective", "0001_initial"),
|
||||
("followup", "0002_alter_learnedskill_gymnast"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="learnedskill",
|
||||
name="skill",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="known_by_gymnasts",
|
||||
to="objective.skill",
|
||||
verbose_name="Skill",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-04 16:53
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("objective", "0001_initial"),
|
||||
("followup", "0003_alter_learnedskill_skill"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="learnedskill",
|
||||
name="skill",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="known_by",
|
||||
to="objective.skill",
|
||||
verbose_name="Skill",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,55 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-05 14:12
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("objective", "0003_delete_gymnasthasroutine"),
|
||||
("people", "0001_initial"),
|
||||
("followup", "0004_alter_learnedskill_skill"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="gymnasthasroutine",
|
||||
name="gymnast",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="has_routine",
|
||||
to="people.gymnast",
|
||||
verbose_name="Gymnast",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="gymnasthasroutine",
|
||||
name="routine",
|
||||
field=models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="done_by_gymnast",
|
||||
to="objective.routine",
|
||||
verbose_name="Routine",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="gymnasthasroutine",
|
||||
name="routine_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "L1"),
|
||||
(2, "L2"),
|
||||
(3, "L3"),
|
||||
(4, "L4"),
|
||||
(5, "L1S"),
|
||||
(6, "L2S"),
|
||||
(7, "L3S"),
|
||||
(8, "L4S"),
|
||||
],
|
||||
default="1",
|
||||
verbose_name="Type",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,130 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-13 07:46
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("people", "0001_initial"),
|
||||
("objective", "0003_delete_gymnasthasroutine"),
|
||||
("followup", "0005_auto_20211205_1412"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="NumberOfRoutineDone",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"routine_type",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "L1"),
|
||||
(2, "L2"),
|
||||
(3, "L3"),
|
||||
(4, "L4"),
|
||||
(5, "L1S"),
|
||||
(6, "L2S"),
|
||||
(7, "L3S"),
|
||||
(8, "L4S"),
|
||||
],
|
||||
default="1",
|
||||
verbose_name="Type",
|
||||
),
|
||||
),
|
||||
(
|
||||
"number_of_try",
|
||||
models.PositiveSmallIntegerField(verbose_name="Number of try"),
|
||||
),
|
||||
(
|
||||
"number_of_successes",
|
||||
models.PositiveSmallIntegerField(
|
||||
verbose_name="number of successes"
|
||||
),
|
||||
),
|
||||
(
|
||||
"date",
|
||||
models.DateField(default=datetime.date.today, verbose_name="Date"),
|
||||
),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="number_of_routine_done",
|
||||
to="people.gymnast",
|
||||
verbose_name="Gymnast",
|
||||
),
|
||||
),
|
||||
(
|
||||
"routine",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="number_of_try",
|
||||
to="objective.routine",
|
||||
verbose_name="Routine",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Number of routine done",
|
||||
"verbose_name_plural": "Number of routines done",
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="HeightWeight",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"height",
|
||||
models.DecimalField(
|
||||
decimal_places=1, max_digits=4, verbose_name="Height"
|
||||
),
|
||||
),
|
||||
(
|
||||
"weight",
|
||||
models.DecimalField(
|
||||
decimal_places=1, max_digits=4, verbose_name="Weight"
|
||||
),
|
||||
),
|
||||
(
|
||||
"date",
|
||||
models.DateField(default=datetime.date.today, verbose_name="Date"),
|
||||
),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="height_weight",
|
||||
to="people.gymnast",
|
||||
verbose_name="Gymnast",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Height & weight",
|
||||
"verbose_name_plural": "Heights & weights",
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,41 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-13 14:45
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("objective", "0003_delete_gymnasthasroutine"),
|
||||
("planning", "0001_initial"),
|
||||
("followup", "0006_heightweight_numberofroutinedone"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="accident",
|
||||
name="skill",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
default=None,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="accident",
|
||||
to="objective.skill",
|
||||
verbose_name="Skill",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="mindstate",
|
||||
name="event",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
default=None,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="mindstate",
|
||||
to="planning.event",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-17 08:16
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("people", "0001_initial"),
|
||||
("objective", "0003_delete_gymnasthasroutine"),
|
||||
("followup", "0007_auto_20211213_1445"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name="learnedskill",
|
||||
unique_together={("gymnast", "skill", "date", "cando")},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,24 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-22 13:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('people', '0001_initial'),
|
||||
('followup', '0008_alter_learnedskill_unique_together'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='heightweight',
|
||||
name='hips_height',
|
||||
field=models.DecimalField(decimal_places=1, default=100, max_digits=4, verbose_name='Hips height'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='heightweight',
|
||||
unique_together={('gymnast', 'date')},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 3.2.8 on 2021-12-24 06:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0009_auto_20211222_1318'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='chrono',
|
||||
old_name='type',
|
||||
new_name='chrono_type',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='gymnasthasroutine',
|
||||
name='routine_type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'L1'), (2, 'L2'), (3, 'L3'), (4, 'L4'), (5, 'L1S'), (6, 'L2S'), (7, 'L3S'), (8, 'L4S'), (9, 'Other')], default='1', verbose_name='Type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='numberofroutinedone',
|
||||
name='routine_type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'L1'), (2, 'L2'), (3, 'L3'), (4, 'L4'), (5, 'L1S'), (6, 'L2S'), (7, 'L3S'), (8, 'L4S'), (9, 'Other')], default='1', verbose_name='Type'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 3.2.8 on 2022-01-05 10:00
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0010_auto_20211224_0627'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='learnedskill',
|
||||
name='cando',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'No'), (1, 'With help'), (2, 'Without help'), (3, 'Chained'), (4, 'Masterised')], verbose_name='Can do type'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,36 @@
|
|||
# Generated by Django 3.2.8 on 2022-01-05 15:31
|
||||
|
||||
import datetime
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('objective', '0006_delete_plan'),
|
||||
('people', '0001_initial'),
|
||||
('followup', '0011_alter_learnedskill_cando'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Plan',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('date', models.DateField(default=datetime.date.today, verbose_name='Date')),
|
||||
('cando', models.PositiveSmallIntegerField(choices=[(0, 'No'), (1, 'With help'), (2, 'Without help'), (3, 'Chained'), (4, 'Masterised')], default=3, verbose_name='Can do type')),
|
||||
('is_done', models.BooleanField(default=0)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('updated_at', models.DateTimeField(auto_now=True)),
|
||||
('educative', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='plan', to='objective.educative', verbose_name='Educative')),
|
||||
('gymnast', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='todo', to='people.gymnast', verbose_name='Gymnast')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Plan',
|
||||
'verbose_name_plural': 'Plans',
|
||||
'ordering': ['date', 'educative', 'gymnast'],
|
||||
'unique_together': {('gymnast', 'educative')},
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 3.2.8 on 2022-01-20 17:20
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0012_plan'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ChronoDetails',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('order', models.SmallIntegerField()),
|
||||
('value', models.DecimalField(decimal_places=3, max_digits=5)),
|
||||
('chrono', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='followup.chrono')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Chronos Details',
|
||||
'verbose_name_plural': 'Chronos Details',
|
||||
'ordering': ['chrono', 'order'],
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.2.8 on 2022-01-25 17:51
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0013_chronodetails'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='chronodetails',
|
||||
name='chrono',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='details', to='followup.chrono'),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='chronodetails',
|
||||
unique_together={('chrono', 'order')},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
# Generated by Django 3.2.8 on 2022-02-01 16:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0014_auto_20220125_1751'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='chrono',
|
||||
name='chrono_type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, '10 |'), (1, 'Routine 1'), (2, 'Routine 2'), (3, 'Routine 3'), (4, 'Routine 4'), (9, 'Other')], verbose_name='Routine type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='gymnasthasroutine',
|
||||
name='routine_type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'R1'), (2, 'R2'), (3, 'R3'), (4, 'R4'), (5, 'R1S'), (6, 'R2S'), (7, 'R3S'), (8, 'R4S'), (9, 'Other')], default='1', verbose_name='Type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='numberofroutinedone',
|
||||
name='routine_type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'R1'), (2, 'R2'), (3, 'R3'), (4, 'R4'), (5, 'R1S'), (6, 'R2S'), (7, 'R3S'), (8, 'R4S'), (9, 'Other')], default='1', verbose_name='Type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='point',
|
||||
name='routine_type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(1, 'Routine 1'), (2, 'Routine 2'), (3, 'Final')]),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
# Generated by Django 3.2.8 on 2022-02-03 10:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0015_auto_20220201_1633'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='point',
|
||||
name='point_difficulty',
|
||||
field=models.DecimalField(decimal_places=1, max_digits=3, verbose_name='Difficulty'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='point',
|
||||
name='point_execution',
|
||||
field=models.DecimalField(decimal_places=3, max_digits=5, verbose_name='Execution'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='point',
|
||||
name='point_horizontal_displacement',
|
||||
field=models.DecimalField(decimal_places=3, max_digits=4, verbose_name='HD'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='point',
|
||||
name='point_time_of_flight',
|
||||
field=models.DecimalField(decimal_places=3, max_digits=5, verbose_name='ToF'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.2.8 on 2022-02-03 10:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0016_auto_20220203_1035'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='point',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='Created'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='point',
|
||||
name='updated_at',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='Updated'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 3.2.8 on 2022-02-08 16:48
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0017_auto_20220203_1037'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='gymnasthasroutine',
|
||||
name='dateend',
|
||||
field=models.DateField(blank=True, null=True, verbose_name='Date end'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='numberofroutinedone',
|
||||
name='number_of_successes',
|
||||
field=models.PositiveSmallIntegerField(default=0, verbose_name='number of successes'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='numberofroutinedone',
|
||||
name='number_of_try',
|
||||
field=models.PositiveSmallIntegerField(default=0, verbose_name='Number of try'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.2.8 on 2022-02-13 14:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('followup', '0018_auto_20220208_1648'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='gymnasthasroutine',
|
||||
name='routine_type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'R1'), (2, 'R2'), (3, 'R3'), (4, 'R4'), (5, 'R1S'), (6, 'R2S'), (7, 'R3S'), (8, 'R4S')], default='1', verbose_name='Type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='numberofroutinedone',
|
||||
name='routine_type',
|
||||
field=models.PositiveSmallIntegerField(choices=[(0, 'Other'), (1, 'R1'), (2, 'R2'), (3, 'R3'), (4, 'R4'), (5, 'R1S'), (6, 'R2S'), (7, 'R3S'), (8, 'R4S')], default='1', verbose_name='Type'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.1.1 on 2022-09-23 07:42
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0019_auto_20220213_1441"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name="gymnasthasroutine",
|
||||
old_name="datebegin",
|
||||
new_name="date_begin",
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="gymnasthasroutine",
|
||||
old_name="dateend",
|
||||
new_name="date_end",
|
||||
),
|
||||
]
|
|
@ -0,0 +1,63 @@
|
|||
# Generated by Django 4.1.1 on 2022-09-26 10:18
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("people", "0004_gymnast_email_trainer"),
|
||||
("followup", "0020_rename_datebegin_gymnasthasroutine_date_begin_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Notes",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"informations",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="Only MarkDown is authorized",
|
||||
null=True,
|
||||
verbose_name="Comments",
|
||||
),
|
||||
),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
("updated_at", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"coach",
|
||||
models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="notes",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="remarks",
|
||||
to="people.gymnast",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 4.1.1 on 2022-09-26 10:24
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("people", "0004_gymnast_email_trainer"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("followup", "0021_notes"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name="Notes",
|
||||
new_name="Note",
|
||||
),
|
||||
]
|
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-06 12:33
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0022_rename_notes_note"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="note",
|
||||
name="note_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[(0, "Draft"), (1, "Published")],
|
||||
default=0,
|
||||
verbose_name="Routine type",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,18 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-06 12:36
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0023_note_note_type"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name="note",
|
||||
old_name="note_type",
|
||||
new_name="status",
|
||||
),
|
||||
]
|
|
@ -0,0 +1,33 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-12 08:37
|
||||
|
||||
from django.db import migrations, models
|
||||
import jarvis.tools.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0024_rename_note_type_note_status"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="note",
|
||||
name="date",
|
||||
field=models.DateField(
|
||||
default=jarvis.tools.models.get_default_date, verbose_name="Date"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="note",
|
||||
name="season",
|
||||
field=models.CharField(default="2022-2023", max_length=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="note",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(default=1),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-12 08:58
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0025_note_date_note_season_note_week_number"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="note",
|
||||
name="season",
|
||||
field=models.CharField(editable=False, max_length=9),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="note",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(editable=False),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,147 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-12 09:03
|
||||
|
||||
from django.db import migrations, models
|
||||
import jarvis.tools.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0026_alter_note_season_alter_note_week_number"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="accident",
|
||||
name="season",
|
||||
field=models.CharField(default="2022-2023", editable=False, max_length=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="accident",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(default=1, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="chrono",
|
||||
name="season",
|
||||
field=models.CharField(default="2022-2023", editable=False, max_length=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="chrono",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(default=1, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="heightweight",
|
||||
name="season",
|
||||
field=models.CharField(default="2022-2023", editable=False, max_length=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="heightweight",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(default=1, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="learnedskill",
|
||||
name="season",
|
||||
field=models.CharField(default="2022-2023", editable=False, max_length=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="learnedskill",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(default=1, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="mindstate",
|
||||
name="season",
|
||||
field=models.CharField(default="2022-2023", editable=False, max_length=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="mindstate",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(default=1, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="numberofroutinedone",
|
||||
name="season",
|
||||
field=models.CharField(default="2022-2023", editable=False, max_length=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="numberofroutinedone",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(default=1, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="plan",
|
||||
name="season",
|
||||
field=models.CharField(default="2022-2023", editable=False, max_length=9),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="plan",
|
||||
name="week_number",
|
||||
field=models.PositiveSmallIntegerField(default=1, editable=False),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="accident",
|
||||
name="date",
|
||||
field=models.DateField(
|
||||
default=jarvis.tools.models.get_default_date, verbose_name="Date"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="chrono",
|
||||
name="date",
|
||||
field=models.DateField(
|
||||
default=jarvis.tools.models.get_default_date, verbose_name="Date"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="heightweight",
|
||||
name="date",
|
||||
field=models.DateField(
|
||||
default=jarvis.tools.models.get_default_date, verbose_name="Date"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="learnedskill",
|
||||
name="date",
|
||||
field=models.DateField(
|
||||
default=jarvis.tools.models.get_default_date, verbose_name="Date"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="mindstate",
|
||||
name="date",
|
||||
field=models.DateField(
|
||||
default=jarvis.tools.models.get_default_date, verbose_name="Date"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="numberofroutinedone",
|
||||
name="date",
|
||||
field=models.DateField(
|
||||
default=jarvis.tools.models.get_default_date, verbose_name="Date"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="plan",
|
||||
name="date",
|
||||
field=models.DateField(
|
||||
default=jarvis.tools.models.get_default_date, verbose_name="Date"
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,32 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-12 15:12
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("objective", "0013_alter_skill_position"),
|
||||
("people", "0004_gymnast_email_trainer"),
|
||||
(
|
||||
"followup",
|
||||
"0027_accident_season_accident_week_number_chrono_season_and_more",
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name="learnedskill",
|
||||
old_name="cando",
|
||||
new_name="learning_step",
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="plan",
|
||||
old_name="cando",
|
||||
new_name="learning_step",
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name="learnedskill",
|
||||
unique_together={("gymnast", "skill", "date", "learning_step")},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-16 06:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0028_rename_cando_learnedskill_learning_step_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="plan",
|
||||
name="informations",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Only MarkDown is authorized",
|
||||
null=True,
|
||||
verbose_name="Comments",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,24 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-18 03:43
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0029_plan_informations"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="heightweight",
|
||||
name="hips_height",
|
||||
field=models.DecimalField(
|
||||
blank=True,
|
||||
decimal_places=1,
|
||||
max_digits=4,
|
||||
null=True,
|
||||
verbose_name="Hips height",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,22 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-21 13:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0030_alter_heightweight_hips_height"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="note",
|
||||
name="status",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[(0, "Draft"), (1, "Published")],
|
||||
default=0,
|
||||
verbose_name="Status",
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,66 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-25 14:21
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import jarvis.tools.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("people", "0004_gymnast_email_trainer"),
|
||||
("followup", "0031_alter_note_status"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Intensity",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"date",
|
||||
models.DateField(
|
||||
default=jarvis.tools.models.get_default_date,
|
||||
verbose_name="Date",
|
||||
),
|
||||
),
|
||||
("season", models.CharField(editable=False, max_length=9)),
|
||||
("week_number", models.PositiveSmallIntegerField(editable=False)),
|
||||
(
|
||||
"informations",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="Only MarkDown is authorized",
|
||||
null=True,
|
||||
verbose_name="Comments",
|
||||
),
|
||||
),
|
||||
(
|
||||
"time",
|
||||
models.PositiveSmallIntegerField(verbose_name="Time (in minutes)"),
|
||||
),
|
||||
("difficulty", models.PositiveSmallIntegerField()),
|
||||
("quantity_of_skill", models.PositiveSmallIntegerField()),
|
||||
("number_of_passes", models.PositiveSmallIntegerField()),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="intensities",
|
||||
to="people.gymnast",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,29 @@
|
|||
# Generated by Django 4.1.1 on 2022-10-25 15:41
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("people", "0004_gymnast_email_trainer"),
|
||||
("followup", "0032_intensity"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name="intensity",
|
||||
options={"verbose_name": "Intensity", "verbose_name_plural": "Intensities"},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="intensity",
|
||||
name="difficulty",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
verbose_name="Difficulty (in tenths)"
|
||||
),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name="intensity",
|
||||
unique_together={("gymnast", "date")},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,85 @@
|
|||
# Generated by Django 4.1.1 on 2022-11-01 14:31
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("location", "0003_auto_20220109_1001"),
|
||||
("people", "0006_gymnast_created_at"),
|
||||
(
|
||||
"followup",
|
||||
"0033_alter_intensity_options_alter_intensity_difficulty_and_more",
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="SeasonInformation",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("season", models.CharField(editable=False, max_length=9)),
|
||||
(
|
||||
"trainings_by_week",
|
||||
models.PositiveSmallIntegerField(verbose_name="# Training by week"),
|
||||
),
|
||||
(
|
||||
"hours_by_week",
|
||||
models.PositiveSmallIntegerField(verbose_name="# Hours by week"),
|
||||
),
|
||||
(
|
||||
"category",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(9, "I9"),
|
||||
(10, "I10"),
|
||||
(11, "A11"),
|
||||
(12, "A12"),
|
||||
(13, "A13-14"),
|
||||
(15, "A Junior"),
|
||||
(18, "A Senior"),
|
||||
(21, "B11"),
|
||||
(22, "B12"),
|
||||
(23, "B13-14"),
|
||||
(24, "B Junior"),
|
||||
(25, "B Senior"),
|
||||
],
|
||||
verbose_name="Category",
|
||||
),
|
||||
),
|
||||
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||
(
|
||||
"club",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
related_name="season_informations",
|
||||
to="location.club",
|
||||
),
|
||||
),
|
||||
(
|
||||
"gymnast",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="season_informations",
|
||||
to="people.gymnast",
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Season Information",
|
||||
"verbose_name_plural": "Season Informations",
|
||||
"unique_together": {("gymnast", "season")},
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 4.1.1 on 2022-11-02 12:53
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0034_seasoninformation"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name="seasoninformation",
|
||||
old_name="hours_by_week",
|
||||
new_name="number_of_hours_per_week",
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name="seasoninformation",
|
||||
old_name="trainings_by_week",
|
||||
new_name="number_of_training_sessions_per_week",
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="seasoninformation",
|
||||
name="season",
|
||||
field=models.CharField(max_length=9),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,21 @@
|
|||
# Generated by Django 4.1.1 on 2022-11-04 09:56
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("people", "0008_alter_gymnast_orientation"),
|
||||
(
|
||||
"followup",
|
||||
"0035_rename_hours_by_week_seasoninformation_number_of_hours_per_week_and_more",
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name="numberofroutinedone",
|
||||
unique_together={("gymnast", "date", "routine_type")},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,90 @@
|
|||
# Generated by Django 4.1.1 on 2022-11-07 21:40
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0036_alter_numberofroutinedone_unique_together"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="chrono",
|
||||
name="chrono_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "10 |"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(9, "Other"),
|
||||
],
|
||||
verbose_name="Routine type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="gymnasthasroutine",
|
||||
name="routine_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(6, "Q1R1S"),
|
||||
(7, "Q1R2S"),
|
||||
(8, "Q2R1S"),
|
||||
(9, "SFS"),
|
||||
(9, "FS"),
|
||||
],
|
||||
default="1",
|
||||
verbose_name="Type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="numberofroutinedone",
|
||||
name="routine_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(6, "Q1R1S"),
|
||||
(7, "Q1R2S"),
|
||||
(8, "Q2R1S"),
|
||||
(9, "SFS"),
|
||||
(9, "FS"),
|
||||
],
|
||||
default="1",
|
||||
verbose_name="Type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="point",
|
||||
name="routine_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(6, "Q1R1S"),
|
||||
(7, "Q1R2S"),
|
||||
(8, "Q2R1S"),
|
||||
(9, "SFS"),
|
||||
(9, "FS"),
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,93 @@
|
|||
# Generated by Django 4.1.1 on 2022-12-07 11:27
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0037_alter_chrono_chrono_type_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="chrono",
|
||||
name="chrono_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "10 |"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(99, "Other"),
|
||||
],
|
||||
verbose_name="Routine type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="gymnasthasroutine",
|
||||
name="routine_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(6, "Q1R1S"),
|
||||
(7, "Q1R2S"),
|
||||
(8, "Q2R1S"),
|
||||
(9, "SFS"),
|
||||
(9, "FS"),
|
||||
(99, "Other"),
|
||||
],
|
||||
default="1",
|
||||
verbose_name="Type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="numberofroutinedone",
|
||||
name="routine_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(6, "Q1R1S"),
|
||||
(7, "Q1R2S"),
|
||||
(8, "Q2R1S"),
|
||||
(9, "SFS"),
|
||||
(9, "FS"),
|
||||
(99, "Other"),
|
||||
],
|
||||
default="1",
|
||||
verbose_name="Type",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="point",
|
||||
name="routine_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(6, "Q1R1S"),
|
||||
(7, "Q1R2S"),
|
||||
(8, "Q2R1S"),
|
||||
(9, "SFS"),
|
||||
(9, "FS"),
|
||||
(99, "Other"),
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,112 @@
|
|||
# Generated by Django 4.1.1 on 2022-12-28 13:28
|
||||
|
||||
from django.db import migrations, models
|
||||
import jarvis.tools.models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0038_alter_chrono_chrono_type_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="CompetitivePointsStats",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
(
|
||||
"date",
|
||||
models.DateField(
|
||||
default=jarvis.tools.models.get_default_date,
|
||||
verbose_name="Date",
|
||||
),
|
||||
),
|
||||
("season", models.CharField(editable=False, max_length=9)),
|
||||
("week_number", models.PositiveSmallIntegerField(editable=False)),
|
||||
(
|
||||
"informations",
|
||||
models.TextField(
|
||||
blank=True,
|
||||
help_text="Only MarkDown is authorized",
|
||||
null=True,
|
||||
verbose_name="Comments",
|
||||
),
|
||||
),
|
||||
(
|
||||
"gender",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[(0, "Male"), (1, "Female")], verbose_name="Gender"
|
||||
),
|
||||
),
|
||||
(
|
||||
"age_category",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(11, "11-12"),
|
||||
(13, "13-14"),
|
||||
(15, "15-16"),
|
||||
(17, "17-21"),
|
||||
(22, "Senior"),
|
||||
],
|
||||
verbose_name="Age category",
|
||||
),
|
||||
),
|
||||
(
|
||||
"point_execution",
|
||||
models.DecimalField(
|
||||
decimal_places=3, max_digits=5, verbose_name="Execution"
|
||||
),
|
||||
),
|
||||
(
|
||||
"point_difficulty",
|
||||
models.DecimalField(
|
||||
decimal_places=1, max_digits=3, verbose_name="Difficulty"
|
||||
),
|
||||
),
|
||||
(
|
||||
"point_time_of_flight",
|
||||
models.DecimalField(
|
||||
decimal_places=3, max_digits=5, verbose_name="ToF"
|
||||
),
|
||||
),
|
||||
(
|
||||
"point_horizontal_displacement",
|
||||
models.DecimalField(
|
||||
decimal_places=3, max_digits=4, verbose_name="HD"
|
||||
),
|
||||
),
|
||||
("total", models.DecimalField(decimal_places=3, max_digits=6)),
|
||||
(
|
||||
"routine_type",
|
||||
models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "Other"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(6, "Q1R1S"),
|
||||
(7, "Q1R2S"),
|
||||
(8, "Q2R1S"),
|
||||
(9, "SFS"),
|
||||
(9, "FS"),
|
||||
(99, "Other"),
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.1.1 on 2022-12-28 13:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0039_competitivepointsstats"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="competitivepointsstats",
|
||||
name="place",
|
||||
field=models.PositiveSmallIntegerField(default=1, verbose_name="place"),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 4.1.1 on 2022-12-28 17:22
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0040_competitivepointsstats_place"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="competitivepointsstats",
|
||||
name="label",
|
||||
field=models.CharField(default="blah", max_length=40),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
|
@ -0,0 +1,63 @@
|
|||
# Generated by Django 4.1.1 on 2023-02-01 07:25
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("planning", "0009_alter_event_date_begin_alter_event_date_end"),
|
||||
("followup", "0041_competitivepointsstats_label"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="competitivepointsstats",
|
||||
name="event",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
default=None,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="planning.event",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="competitivepointsstats",
|
||||
name="statistic_type",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
choices=[
|
||||
(0, "precise"),
|
||||
(1, "mean + 4 * standard deviation"),
|
||||
(2, "mean + 2 * standard deviation"),
|
||||
(3, "mean + standard deviation"),
|
||||
(4, "mean + ½ standard deviation"),
|
||||
(5, "mean + ¼ standard deviation"),
|
||||
(6, "mean"),
|
||||
(7, "mean - ¼ standard deviation"),
|
||||
(8, "mean - ½ standard deviation"),
|
||||
(9, "mean - standard deviation"),
|
||||
(10, "mean - 2 * standard deviation"),
|
||||
(11, "mean - 4 * standard deviation"),
|
||||
],
|
||||
default=1,
|
||||
verbose_name="Type of statistic",
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="competitivepointsstats",
|
||||
name="informations",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Information about even or statistics (mean, standard deviation, …).",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="competitivepointsstats",
|
||||
name="place",
|
||||
field=models.PositiveSmallIntegerField(verbose_name="Place"),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,27 @@
|
|||
# Generated by Django 4.1.1 on 2023-02-09 12:26
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("followup", "0042_competitivepointsstats_event_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="seasoninformation",
|
||||
name="number_of_s_and_c_hours_per_week",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
blank=True, null=True, verbose_name="# S&C hours by week"
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="seasoninformation",
|
||||
name="number_of_s_and_c_sessions_per_week",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
blank=True, null=True, verbose_name="# S&C training by week"
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,40 @@
|
|||
# Generated by Django 4.2 on 2023-04-23 06:42
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
(
|
||||
"followup",
|
||||
"0043_seasoninformation_number_of_s_and_c_hours_per_week_and_more",
|
||||
),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="seasoninformation",
|
||||
name="number_of_hours_per_week",
|
||||
field=models.PositiveSmallIntegerField(verbose_name="# Hours/w"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="seasoninformation",
|
||||
name="number_of_s_and_c_hours_per_week",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
blank=True, null=True, verbose_name="# S&C hours/w"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="seasoninformation",
|
||||
name="number_of_s_and_c_sessions_per_week",
|
||||
field=models.PositiveSmallIntegerField(
|
||||
blank=True, null=True, verbose_name="# S&C training/w"
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name="seasoninformation",
|
||||
name="number_of_training_sessions_per_week",
|
||||
field=models.PositiveSmallIntegerField(verbose_name="# Training/w"),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,612 @@
|
|||
from django.db import models
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from datetime import date
|
||||
|
||||
from jarvis.tools.models import Markdownizable, Seasonisable
|
||||
from jarvis.people.models import Gymnast, GENDER_CHOICES
|
||||
from jarvis.planning.models import Event
|
||||
from jarvis.objective.models import Educative, Skill, Routine
|
||||
from jarvis.location.models import Club
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
ROUTINE_TYPE_CHOICE = (
|
||||
(0, "Other"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(6, "Q1R1S"),
|
||||
(7, "Q1R2S"),
|
||||
(8, "Q2R1S"),
|
||||
(9, "SFS"),
|
||||
(9, "FS"),
|
||||
(99, "Other"),
|
||||
)
|
||||
|
||||
LEARNING_STEP_CHOICES = (
|
||||
(0, "No"),
|
||||
(1, "With help"),
|
||||
(2, "Without help"),
|
||||
(3, "Chained"),
|
||||
(4, "Masterised"),
|
||||
)
|
||||
|
||||
CHRONO_TYPE_CHOICE = (
|
||||
(0, "10 |"),
|
||||
(1, "Q1R1"),
|
||||
(2, "Q1R2"),
|
||||
(3, "Q2R1"),
|
||||
(4, "SF"),
|
||||
(5, "F"),
|
||||
(99, "Other"),
|
||||
)
|
||||
|
||||
SCORE_TYPE_CHOICE = (
|
||||
(0, "Chrono"),
|
||||
(1, "ToF"),
|
||||
)
|
||||
|
||||
CATEGORY_CHOICES = {
|
||||
9: "I9",
|
||||
10: "I10",
|
||||
11: "A11",
|
||||
12: "A12",
|
||||
13: "A13-14",
|
||||
15: "A Junior",
|
||||
18: "A Senior",
|
||||
21: "B11",
|
||||
22: "B12",
|
||||
23: "B13-14",
|
||||
24: "B Junior",
|
||||
25: "B Senior",
|
||||
}
|
||||
|
||||
AGE_CATOGORY_CHOICES = (
|
||||
(11, "11-12"),
|
||||
(13, "13-14"),
|
||||
(15, "15-16"),
|
||||
(17, "17-21"),
|
||||
(22, "Senior"),
|
||||
)
|
||||
|
||||
|
||||
class Chrono(Seasonisable):
|
||||
"""
|
||||
Représente les chronos (de chandelles ou de série) enregistrés pour un(e) gymnaste.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Chrono"
|
||||
verbose_name_plural = "Chronos"
|
||||
ordering = ["date", "gymnast"]
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast,
|
||||
verbose_name="gymnast",
|
||||
related_name="chronos",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
chrono_type = models.PositiveSmallIntegerField(
|
||||
choices=CHRONO_TYPE_CHOICE, verbose_name="Routine type"
|
||||
)
|
||||
score_type = models.PositiveSmallIntegerField(
|
||||
choices=SCORE_TYPE_CHOICE, verbose_name="Score type"
|
||||
)
|
||||
score = models.DecimalField(max_digits=5, decimal_places=3)
|
||||
tof = models.DecimalField(max_digits=5, decimal_places=3, blank=True, null=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s (%s - %s)" % (
|
||||
self.gymnast,
|
||||
self.score,
|
||||
self.date,
|
||||
self.chrono_type,
|
||||
)
|
||||
|
||||
def timeline_representation(self):
|
||||
return f"<li>{self.date:%d %b %Y} - New personel best {CHRONO_TYPE_CHOICE[self.chrono_type][1]}: {self.score}' ({self.tof}')</li>"
|
||||
|
||||
@staticmethod
|
||||
def compute_tof(value):
|
||||
tof = round((value * 13) / 15, 3) * 1000
|
||||
tof = tof - (tof % 5)
|
||||
return tof / 1000
|
||||
|
||||
|
||||
class ChronoDetails(models.Model):
|
||||
"""
|
||||
Class permettant d'enregistrer des détails d'un chrono : le temps de chaque saut.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Chronos Details"
|
||||
verbose_name_plural = "Chronos Details"
|
||||
ordering = ["chrono", "order"]
|
||||
unique_together = ["chrono", "order"]
|
||||
|
||||
chrono = models.ForeignKey(Chrono, on_delete=models.CASCADE, related_name="details")
|
||||
order = models.SmallIntegerField()
|
||||
value = models.DecimalField(max_digits=5, decimal_places=3)
|
||||
|
||||
|
||||
class Accident(Markdownizable, Seasonisable):
|
||||
"""
|
||||
La classe `Accident` permet d'indiquer qu'un gymnaste a eu un accident, en liaison avec un
|
||||
skill ou non.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Accident"
|
||||
verbose_name_plural = "Accidents"
|
||||
# unique_together = ("gymnast", "skill", "date")
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast,
|
||||
verbose_name="Gymnast",
|
||||
related_name="accident",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
skill = models.ForeignKey(
|
||||
"objective.Skill",
|
||||
verbose_name="Skill",
|
||||
related_name="accident",
|
||||
on_delete=models.SET_NULL,
|
||||
default=None,
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
nb_week_off = models.SmallIntegerField(
|
||||
blank=True, null=True, verbose_name="# week off"
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s (%s)" % (
|
||||
self.gymnast,
|
||||
self.date,
|
||||
)
|
||||
|
||||
def timeline_representation(self):
|
||||
return f"<li>{self.date:%d %b %Y} - Accident ({self.skill}): {self.nb_week_off} (weeks off)</li>"
|
||||
|
||||
|
||||
class LearnedSkill(Seasonisable):
|
||||
"""
|
||||
Représente la capacité d'un gymnaste à savori faire un skill de la ligne d'apprentissage.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Learned Skill"
|
||||
verbose_name_plural = "Learned Skills"
|
||||
unique_together = ("gymnast", "skill", "date", "learning_step")
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast,
|
||||
verbose_name="gymnast",
|
||||
related_name="known_skills",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
skill = models.ForeignKey(
|
||||
Skill,
|
||||
verbose_name="Skill",
|
||||
related_name="known_by",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
learning_step = models.PositiveSmallIntegerField(
|
||||
choices=LEARNING_STEP_CHOICES, verbose_name="Can do type"
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s - %s - %s" % (
|
||||
self.gymnast,
|
||||
self.date,
|
||||
self.learning_step,
|
||||
self.skill,
|
||||
)
|
||||
|
||||
def timeline_representation(self):
|
||||
return f"<li>{self.date:%d %b %Y} - learning of {self.skill.long_label} ({self.skill.short_label}): {LEARNING_STEP_CHOICES[self.learning_step][1]}</li>"
|
||||
|
||||
|
||||
class Plan(Seasonisable, Markdownizable):
|
||||
"""
|
||||
Classe représentant les objectifs qu'un gymnaste devra savoir faire pour une date donnée.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Plan"
|
||||
verbose_name_plural = "Plans"
|
||||
ordering = ["date", "educative", "gymnast"]
|
||||
unique_together = ("gymnast", "educative")
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
"people.Gymnast",
|
||||
verbose_name="Gymnast",
|
||||
related_name="todo",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
educative = models.ForeignKey(
|
||||
Educative,
|
||||
verbose_name="Educative",
|
||||
related_name="plan",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
learning_step = models.PositiveSmallIntegerField(
|
||||
choices=LEARNING_STEP_CHOICES, verbose_name="Can do type", default=3
|
||||
)
|
||||
is_done = models.BooleanField(default=0)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s - %s" % (
|
||||
self.gymnast,
|
||||
self.educative.short_label,
|
||||
self.date,
|
||||
)
|
||||
|
||||
|
||||
class Point(models.Model):
|
||||
"""
|
||||
Représente les points obtenus lors d'une compétition.
|
||||
"""
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast, on_delete=models.CASCADE, default=None, related_name="points"
|
||||
)
|
||||
event = models.ForeignKey(Event, on_delete=models.CASCADE, default=None)
|
||||
routine_type = models.PositiveSmallIntegerField(choices=ROUTINE_TYPE_CHOICE)
|
||||
point_execution = models.DecimalField(
|
||||
max_digits=5, decimal_places=3, verbose_name="Execution"
|
||||
)
|
||||
point_difficulty = models.DecimalField(
|
||||
max_digits=3, decimal_places=1, verbose_name="Difficulty"
|
||||
)
|
||||
point_time_of_flight = models.DecimalField(
|
||||
max_digits=5, decimal_places=3, verbose_name="ToF"
|
||||
)
|
||||
point_horizontal_displacement = models.DecimalField(
|
||||
max_digits=4, decimal_places=3, verbose_name="HD"
|
||||
)
|
||||
penality = models.DecimalField(max_digits=3, decimal_places=1)
|
||||
total = models.DecimalField(max_digits=6, decimal_places=3)
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name="Created")
|
||||
updated_at = models.DateTimeField(auto_now=True, verbose_name="Updated")
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s" % (
|
||||
self.gymnast,
|
||||
self.total,
|
||||
)
|
||||
|
||||
|
||||
class MindState(Markdownizable, Seasonisable):
|
||||
"""
|
||||
Représente l'état d'esprit psychologique d'un gymnaste
|
||||
"""
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast, on_delete=models.CASCADE, default=None, related_name="mindstate"
|
||||
)
|
||||
event = models.ForeignKey(
|
||||
Event,
|
||||
on_delete=models.SET_NULL,
|
||||
default=None,
|
||||
blank=True,
|
||||
null=True,
|
||||
related_name="mindstate",
|
||||
)
|
||||
score = models.PositiveSmallIntegerField(verbose_name="Score")
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s : %s" % (self.gymnast, self.date, self.score)
|
||||
|
||||
|
||||
class GymnastHasRoutine(models.Model):
|
||||
"""
|
||||
Classe représentant le lien entre les gymnastes et leurs séries.
|
||||
|
||||
TODO: il y a un champ "date_begin" et un champ "date_end" --> peut hérité de Temporizable
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Gymnast Has Routine"
|
||||
verbose_name_plural = "Gymnast Has Routines"
|
||||
# unique_together()
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast,
|
||||
verbose_name="Gymnast",
|
||||
related_name="has_routine",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
routine = models.ForeignKey(
|
||||
Routine,
|
||||
verbose_name="Routine",
|
||||
related_name="done_by_gymnast",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
routine_type = models.PositiveSmallIntegerField(
|
||||
choices=ROUTINE_TYPE_CHOICE, verbose_name="Type", default="1"
|
||||
)
|
||||
date_begin = models.DateField(default=date.today, verbose_name="Date begin")
|
||||
date_end = models.DateField(verbose_name="Date end", null=True, blank=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s : %s" % (self.gymnast, self.routine_type, self.routine)
|
||||
|
||||
|
||||
class NumberOfRoutineDone(Seasonisable):
|
||||
"""
|
||||
Classe permettant de suivre le nombre de séries faites par le gymnaste.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Number of routine done"
|
||||
verbose_name_plural = "Number of routines done"
|
||||
unique_together = ("gymnast", "date", "routine_type")
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast,
|
||||
verbose_name="Gymnast",
|
||||
related_name="number_of_routine_done",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
routine = models.ForeignKey(
|
||||
Routine,
|
||||
verbose_name="Routine",
|
||||
related_name="number_of_try",
|
||||
on_delete=models.SET_NULL,
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
routine_type = models.PositiveSmallIntegerField(
|
||||
choices=ROUTINE_TYPE_CHOICE, verbose_name="Type", default="1"
|
||||
)
|
||||
number_of_try = models.PositiveSmallIntegerField(
|
||||
verbose_name="Number of try", default=0
|
||||
)
|
||||
number_of_successes = models.PositiveSmallIntegerField(
|
||||
verbose_name="number of successes", default=0
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s (%s) : %s | %s" % (
|
||||
self.gymnast,
|
||||
self.routine_type,
|
||||
self.routine,
|
||||
self.number_of_try,
|
||||
self.number_of_successes,
|
||||
)
|
||||
|
||||
|
||||
class HeightWeight(Seasonisable):
|
||||
"""
|
||||
Classe permettant de suivre le poids et la taille d'un gymnaste
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Height & weight"
|
||||
verbose_name_plural = "Heights & weights"
|
||||
unique_together = ("gymnast", "date")
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast,
|
||||
verbose_name="Gymnast",
|
||||
related_name="height_weight",
|
||||
on_delete=models.CASCADE,
|
||||
)
|
||||
height = models.DecimalField(max_digits=4, decimal_places=1, verbose_name="Height")
|
||||
hips_height = models.DecimalField(
|
||||
max_digits=4,
|
||||
decimal_places=1,
|
||||
verbose_name="Hips height",
|
||||
null=True,
|
||||
blank=True,
|
||||
)
|
||||
weight = models.DecimalField(max_digits=4, decimal_places=1, verbose_name="Weight")
|
||||
|
||||
def __str__(self):
|
||||
return "%s : %s/%s - %s" % (
|
||||
self.gymnast,
|
||||
self.height,
|
||||
self.hips_height,
|
||||
self.weight,
|
||||
)
|
||||
|
||||
|
||||
class Note(Markdownizable, Seasonisable):
|
||||
"""
|
||||
Notes relatives à un gymnaste
|
||||
"""
|
||||
|
||||
STATUS_CHOICES = (
|
||||
(0, "Draft"),
|
||||
(1, "Published"),
|
||||
)
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast, on_delete=models.CASCADE, related_name="remarks"
|
||||
)
|
||||
coach = models.ForeignKey(
|
||||
User, on_delete=models.SET_NULL, blank=True, null=True, related_name="notes"
|
||||
)
|
||||
status = models.PositiveSmallIntegerField(
|
||||
choices=STATUS_CHOICES, verbose_name="Status", default=0
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s : %s" % (self.gymnast, self.created_at, self.coach)
|
||||
|
||||
|
||||
class Intensity(Markdownizable, Seasonisable):
|
||||
"""Classe représentant l'intensité d'un entraînement
|
||||
L'intensité va prendre 4 valeurs :
|
||||
- la temps (en minute),
|
||||
- la difficulté (en 10 ème),
|
||||
- la quantité de figure et
|
||||
- le nombre de passafe.
|
||||
|
||||
Avec ces 4 informations, la classe va en calculer 4 autres :
|
||||
- la difficulté moyenne par passage
|
||||
- la difficulté moyenne par figure
|
||||
- la quantité moyene de figures par passage
|
||||
- la quantité moyenne de figure par minute
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Intensity"
|
||||
verbose_name_plural = "Intensities"
|
||||
unique_together = ("gymnast", "date")
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast, on_delete=models.CASCADE, related_name="intensities"
|
||||
)
|
||||
time = models.PositiveSmallIntegerField(verbose_name="Time (in minutes)")
|
||||
difficulty = models.PositiveSmallIntegerField(verbose_name="Difficulty (in tenths)")
|
||||
quantity_of_skill = models.PositiveSmallIntegerField()
|
||||
number_of_passes = models.PositiveSmallIntegerField()
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s : %s - %s - %s - %s" % (
|
||||
self.gymnast,
|
||||
self.date,
|
||||
self.time,
|
||||
self.difficulty,
|
||||
self.quantity_of_skill,
|
||||
self.number_of_passes,
|
||||
)
|
||||
|
||||
@property
|
||||
def mean_difficulty_by_passe(self):
|
||||
return self.difficulty / self.number_of_passes
|
||||
|
||||
@property
|
||||
def mean_quantity_of_skill(self):
|
||||
return self.quantity_of_skill / self.time
|
||||
|
||||
@property
|
||||
def quantity_of_skill_by_passe(self):
|
||||
return self.quantity_of_skill / self.number_of_passes
|
||||
|
||||
@property
|
||||
def mean_difficulty_by_skill(self):
|
||||
return self.difficulty / self.quantity_of_skill
|
||||
|
||||
|
||||
class SeasonInformation(models.Model):
|
||||
"""Classe représentant l'intensité d'un entraînement"""
|
||||
|
||||
class Meta:
|
||||
verbose_name = "Season Information"
|
||||
verbose_name_plural = "Season Informations"
|
||||
unique_together = ("gymnast", "season")
|
||||
|
||||
CATEGORY_CHOICES_ARRAY = [(key, value) for key, value in CATEGORY_CHOICES.items()]
|
||||
|
||||
gymnast = models.ForeignKey(
|
||||
Gymnast, on_delete=models.CASCADE, related_name="season_informations"
|
||||
)
|
||||
season = models.CharField(max_length=9)
|
||||
number_of_training_sessions_per_week = models.PositiveSmallIntegerField(
|
||||
verbose_name="# Training/w"
|
||||
)
|
||||
number_of_hours_per_week = models.PositiveSmallIntegerField(
|
||||
verbose_name="# Hours/w"
|
||||
)
|
||||
number_of_s_and_c_sessions_per_week = models.PositiveSmallIntegerField(
|
||||
verbose_name="# S&C training/w",
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
number_of_s_and_c_hours_per_week = models.PositiveSmallIntegerField(
|
||||
verbose_name="# S&C hours/w",
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
category = models.PositiveSmallIntegerField(
|
||||
choices=CATEGORY_CHOICES_ARRAY,
|
||||
verbose_name="Category",
|
||||
)
|
||||
club = models.ForeignKey(
|
||||
Club, null=True, on_delete=models.SET_NULL, related_name="season_informations"
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
def __str__(self):
|
||||
return "%s - %s : %s - %s - %s - %s" % (
|
||||
self.gymnast,
|
||||
self.season,
|
||||
self.number_of_training_sessions_per_week,
|
||||
self.number_of_hours_per_week,
|
||||
self.category,
|
||||
self.club,
|
||||
)
|
||||
|
||||
|
||||
class CompetitivePointsStats(Markdownizable, Seasonisable):
|
||||
"""Class représentant des points de références de compétitions"""
|
||||
|
||||
TYPE_OF_STAT = (
|
||||
(0, "precise"),
|
||||
(1, "mean + 4 * standard deviation"),
|
||||
(2, "mean + 2 * standard deviation"),
|
||||
(3, "mean + standard deviation"),
|
||||
(4, "mean + ½ standard deviation"),
|
||||
(5, "mean + ¼ standard deviation"),
|
||||
(6, "mean"),
|
||||
(7, "mean - ¼ standard deviation"),
|
||||
(8, "mean - ½ standard deviation"),
|
||||
(9, "mean - standard deviation"),
|
||||
(10, "mean - 2 * standard deviation"),
|
||||
(11, "mean - 4 * standard deviation"),
|
||||
)
|
||||
|
||||
label = models.CharField(max_length=40, null=False, blank=False)
|
||||
gender = models.PositiveSmallIntegerField(
|
||||
choices=GENDER_CHOICES, verbose_name="Gender"
|
||||
)
|
||||
age_category = models.PositiveSmallIntegerField(
|
||||
choices=AGE_CATOGORY_CHOICES, verbose_name="Age category"
|
||||
)
|
||||
statistic_type = models.PositiveSmallIntegerField(
|
||||
choices=TYPE_OF_STAT, verbose_name="Type of statistic"
|
||||
)
|
||||
point_execution = models.DecimalField(
|
||||
max_digits=5, decimal_places=3, verbose_name="Execution"
|
||||
)
|
||||
point_difficulty = models.DecimalField(
|
||||
max_digits=3, decimal_places=1, verbose_name="Difficulty"
|
||||
)
|
||||
point_time_of_flight = models.DecimalField(
|
||||
max_digits=5, decimal_places=3, verbose_name="ToF"
|
||||
)
|
||||
point_horizontal_displacement = models.DecimalField(
|
||||
max_digits=4, decimal_places=3, verbose_name="HD"
|
||||
)
|
||||
total = models.DecimalField(max_digits=6, decimal_places=3)
|
||||
place = models.PositiveSmallIntegerField(verbose_name="Place")
|
||||
event = models.ForeignKey(
|
||||
Event, on_delete=models.SET_NULL, default=None, blank=True, null=True
|
||||
)
|
||||
routine_type = models.PositiveSmallIntegerField(choices=ROUTINE_TYPE_CHOICE)
|
||||
informations = models.TextField(
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Information about even or statistics (mean, standard deviation, …).",
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.age_category} - {self.gender} - {self.routine_type} : {self.total} ({self.statistic_type})"
|
|
@ -0,0 +1,84 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-8 col-lg-8 col-xl-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="">{% if accident_id %}Edit{% else %}Add{% endif %} accident</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{% if accident_id %}{% url 'accident_update' accident_id %}{% else %}{% url 'accident_create' %}{% endif %}" method="post" class="form-horizontal" id="formulaire" name="formulaire">
|
||||
{% csrf_token %}
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Gymnast <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-sm-9 col-md-9 col-lg-6 col-lg-4 col-xl-4 {% if form.jumper.errors %}has-danger{% endif %}">
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
{{ form.gymnast }}
|
||||
{{ form.gymnast_related }}
|
||||
{% if form.gymnast.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.gymnast.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
{% else %}
|
||||
<input type="text" class="form-control" value="{{ request.user.first_name }} {{ request.user.last_name }}" readonly="readonly" />
|
||||
<input type="hidden" name="gymnast" id="gymnast" value="{{ request.user.gymnast.id }}" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Date <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-sm-3 col-md-4 col-lg-4 col-xl-4 {% if form.date.errors %}has-danger{% endif %}">
|
||||
{{ form.date }}
|
||||
{% if form.date.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.date.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_skill" class="col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Skill</label>
|
||||
<div class="col-sm-8 col-md-6 col-lg-6 col-xl-6 {% if form.skill.errors %}has-danger{% endif %}">
|
||||
{{ form.skill }}
|
||||
{{ form.skill_related }}
|
||||
{% if form.skill.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.skill.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_nb_week_off" class="col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label"># Week off</label>
|
||||
<div class="col-sm-3 col-md-4 col-lg-2 {% if form.nb_week_off.errors %}has-danger{% endif %}">
|
||||
{{ form.nb_week_off }}
|
||||
{% if form.nb_week_off.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.nb_week_off.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_information" class="col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Informations</label>
|
||||
<div class="col-sm-9 col-md-9 col-lg-9 col-xl-9 {% if form.id_informations.errors %}has-danger{% endif %}">
|
||||
{{ form.informations }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" value="{% if accident_id %}Save{% else %}Add{% endif %}" class="btn btn-warning" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript" >
|
||||
$(function(){
|
||||
blackDashboard.initDateTimePicker();
|
||||
});
|
||||
|
||||
const csrf_token = "{{ csrf_token|escapejs }}";
|
||||
const gymnast_lookup = "{% url 'gymnast_lookup' %}";
|
||||
const skill_lookup = "{% url 'skill_lookup' %}";
|
||||
</script>
|
||||
<script src="{% static "js/template_users/datepicker_maxdate_today.js" %}"></script>
|
||||
{% if request.session.template == 0 %}
|
||||
<script src="{% static "js/template_users/gymnast_autocomplete_black.js" %}"></script>
|
||||
<script src="{% static "js/template_users/skill_autocomplete_black.js" %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static "js/template_users/gymnast_autocomplete.js" %}"></script>
|
||||
<script src="{% static "js/template_users/skill_autocomplete.js" %}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,32 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-8 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="mb-0">Accident : {{ accident.date | date:"d-m-Y" }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<a href="{% url 'gymnast_details' accident.gymnast.id %}">{{ accident.gymnast }}</a><br />
|
||||
{% if accident.nb_week_off %}
|
||||
{{ accident.nb_week_off }} week(s) off.<br />
|
||||
{% endif %}
|
||||
<br />
|
||||
|
||||
{{ accident.to_markdown | safe }}
|
||||
|
||||
<div class="card-footer pl-0 pb-0">
|
||||
<a href="{% url 'accident_list' %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="tim-icons icon-double-left"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,90 @@
|
|||
{% extends "listing.html" %}
|
||||
|
||||
{% block datacontent %}
|
||||
<div class="card mb-0">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<h4 class=""> Accidents Listing</h4>
|
||||
</div>
|
||||
<div class="col-1 ml-auto">
|
||||
<div class="text-right">
|
||||
<a href="{% url 'accident_create' %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
{% if accident_list %}
|
||||
<table class="table tablesorter table-striped" data-sort="table" id="accident_table">
|
||||
<thead class="text-primary">
|
||||
<tr>
|
||||
<th style="width: 3%"></th>
|
||||
<th class="header text-left" style="width: 10%">Date</th>
|
||||
<th class="header text-left" style="width: 30%">Gymnast</th>
|
||||
<th style="width: 30%">Skill</th>
|
||||
<th style="width: 25%"># Week off</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for accident in accident_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td>
|
||||
<a href="{% url 'accident_update' accident.id %}">
|
||||
<span class="tim-icons icon-pencil text-warning"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-left"><a href="{% url 'accident_details' accident.id %}">{{ accident.date | date:"d-m-Y" }}</a></td>
|
||||
<td class="text-left"><a href="{% url 'gymnast_details_tab' accident.gymnast.id 'physiological' %}">{{ accident.gymnast }}</a></td>
|
||||
<td class="text-left">
|
||||
{% if accident.skill %}
|
||||
<a href="{% url 'skill_details' accident.skill.id %}">{{ accident.skill }}</a>
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right">
|
||||
{% if accident.nb_week_off %}
|
||||
{{ accident.nb_week_off }}
|
||||
{% else %}
|
||||
-
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="muted-text">There are no accident corresponding to your criterias.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('#accident_table').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false }, // disable first column
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[1, 1]]
|
||||
});
|
||||
|
||||
$('#accident_table').DataTable({
|
||||
scrollY: 500,
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
"bInfo": false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,123 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-8 col-lg-8 col-xl-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Add chrono details : {{ chrono.score }} - {{ chrono.routine.short_label }} on the {{ chrono.date | date:"d N Y" }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<ol>
|
||||
{% for jump in jump_list %}
|
||||
<li>
|
||||
<div class="form-group row pb-0 mb-0">
|
||||
<label class="col-1 col-sm-1 col-md-1 col-lg-1 col-xl-1 col-form-label text-right mb-0 pb-0"> </label>
|
||||
<div class="col-11 col-sm-11 col-md-11 col-lg-11 col-xl-11 pt-2 text-danger pb-0">
|
||||
{{ jump.value }}
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
<li id="li_add_score">
|
||||
<div class="form-group row mb-0">
|
||||
<label class="col-1 col-sm-1 col-md-1 col-lg-1 col-xl-1 col-form-label text-right"> </label>
|
||||
<div class="col-3 col-sm-3 col-md-3 col-lg-3 col-xl-3">
|
||||
<input type="number" min="1" max="{% if score_type %}2500{% else %}250{% endif %}" step="1" name="jump_score" placeholder="{% if score_type %}xxxx{% else %}xxx{% endif %}" class="form-control" id="jump_score">
|
||||
</div>
|
||||
<div class="col-1 col-sm-1 col-md-1 col-lg-1 col-xl-1"><button type="button" class="btn btn-warning btn-sm" id="plus_button">+</button></div>
|
||||
</div>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
<div class="card-footer pt-0">
|
||||
<a href="{% url 'jump_chrono_details' chrono.id %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="fal fa-chart-line"></i>
|
||||
</button>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'chrono_list_for_gymnast' chrono.gymnast.id %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning mr-2">
|
||||
<i class="fal fa-stopwatch"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript" >
|
||||
$(document).ready(function() {
|
||||
var number_of_jump = {{ number_of_jump }};
|
||||
var score_type = {{ score_type }};
|
||||
$('#jump_score').focus();
|
||||
|
||||
function send_score_to_database(score)
|
||||
{
|
||||
var jump_value = score / 100;
|
||||
if(score_type && score.length >= 4) // tof
|
||||
var jump_value = jump_value / 10;
|
||||
|
||||
$.ajax({
|
||||
url: "{% url 'add_jump_chrono_value' %}",
|
||||
method: "POST",
|
||||
data: {
|
||||
chrono_id: {{ chrono.id }},
|
||||
order: number_of_jump + 1,
|
||||
value: jump_value,
|
||||
csrfmiddlewaretoken: '{{ csrf_token }}'
|
||||
},
|
||||
}).done(function() {
|
||||
insert_entered_value(jump_value);
|
||||
number_of_jump = number_of_jump + 1;
|
||||
});
|
||||
}
|
||||
|
||||
function check_number_of_jump()
|
||||
{
|
||||
if(number_of_jump >= 10)
|
||||
$('#li_add_score').hide();
|
||||
else
|
||||
$('#li_add_score').show();
|
||||
}
|
||||
|
||||
function insert_entered_value(jump_score)
|
||||
{
|
||||
$('#minusButton').remove();
|
||||
$('ol li:last-child').before('<li><div class="form-group row mb-0"><label class="col-1 col-sm-1 col-md-1 col-lg-1 col-xl-1 col-form-label text-right mb-0"> </label><div class="col-3 col-sm-3 col-md-3 col-lg-3 col-xl-3 pt-2">' + jump_score + '</div><div class="col-1 col-sm-1 col-md-1 col-lg-1 col-xl-1"><button type="button" class="btn btn-warning btn-sm" id="minus_button">-</button></div></div></li>');
|
||||
$('#jump_score').val('').focus();
|
||||
check_number_of_jump();
|
||||
}
|
||||
|
||||
$('#jump_score').keyup(function(){
|
||||
var score = $('#jump_score').val();
|
||||
if((score_type && score.length >= 4) || (!score_type && score.length >= 3))
|
||||
send_score_to_database(score);
|
||||
});
|
||||
|
||||
$('body').on('click', '#minus_button', function(event){
|
||||
$.ajax({
|
||||
url: "{% url 'remove_jump_chrono_value' %}",
|
||||
method: "POST",
|
||||
data: {
|
||||
chrono_id: {{ chrono.id }},
|
||||
order: number_of_jump,
|
||||
csrfmiddlewaretoken: '{{ csrf_token }}'
|
||||
},
|
||||
}).done(function() {
|
||||
$('ol li:last-child').prev().remove();
|
||||
number_of_jump = number_of_jump - 1;
|
||||
});
|
||||
});
|
||||
|
||||
$('#plus_button').click(function(){
|
||||
send_score_to_database($('#jump_score').val());
|
||||
});
|
||||
|
||||
check_number_of_jump();
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,90 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-8 col-lg-6 col-xl-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="">{% if chrono_id %}Edit{% else %}Add{% endif %} chrono</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{% if chrono_id %}{% url 'chrono_update' chrono_id %}{% else %}{% url 'chrono_create' %}{% endif %}" method="post" class="form-horizontal" id="formulaire" name="formulaire">
|
||||
{% csrf_token %}
|
||||
<div class="form-group row ">
|
||||
<label for="id_gymnast" class="col-4 col-sm-3 col-form-label">Gymnast <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-8 col-sm-9 col-md-9 col-lg-6 col-lg-4 col-xl-4 {% if form.jumper.errors %}has-danger{% endif %}">
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
{{ form.gymnast }}
|
||||
{{ form.gymnast_related }}
|
||||
{% if form.gymnast.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.gymnast.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
{% else %}
|
||||
<input type="text" class="form-control" value="{{ request.user.first_name }} {{ request.user.last_name }}" readonly="readonly" />
|
||||
<input type="hidden" name="gymnast" id="gymnast" value="{{ request.user.gymnast.id }}" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_gymnast" class="col-4 col-sm-3 col-form-label">Date <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-6 col-sm-3 col-md-4 col-lg-4 col-xl-4 {% if form.date.errors %}has-danger{% endif %}">
|
||||
{{ form.date }}
|
||||
{% if form.date.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.date.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_chrono_type" class="col-4 col-sm-3 col-form-label">Chrono Type <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-5 col-sm-3 col-md-4 col-lg-4 col-xl-4 {% if form.chrono_type.errors %}has-danger{% endif %}">
|
||||
{{ form.chrono_type }}
|
||||
{% if form.chrono_type.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.chrono_type.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_score_type" class="col-4 col-sm-3 col-form-label">Score Type <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-5 col-sm-3 col-md-4 col-lg-4 col-xl-4 {% if form.score_type.errors %}has-danger{% endif %}">
|
||||
{{ form.score_type }}
|
||||
{% if form.score_type.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.score_type.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_score" class="col-4 col-sm-3 col-form-label">Score <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-4 col-sm-3 col-md-4 col-lg-3 {% if form.score.errors %}has-danger{% endif %}">
|
||||
{{ form.score }}
|
||||
{% if form.score.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.score.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{{ form.tof }}
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" value="{% if chrono_id %}Save{% else %}Add{% endif %}" class="btn btn-warning" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript" >
|
||||
$(function(){
|
||||
blackDashboard.initDateTimePicker();
|
||||
});
|
||||
|
||||
// Ne fonctionne pas avec un "forms.NumberInput" dans le form.
|
||||
$('#id_score').keyup(function(){
|
||||
if($(this).val().length == 2 && $(this).val().indexOf(',') == -1) {
|
||||
var res = $(this).val().toString() + '.'
|
||||
$(this).val(res);
|
||||
}
|
||||
});
|
||||
|
||||
const csrf_token = "{{ csrf_token|escapejs }}";
|
||||
const gymnast_lookup = "{% url 'gymnast_lookup' %}";
|
||||
</script>
|
||||
<script src="{% static "js/template_users/datepicker_maxdate_today.js" %}"></script>
|
||||
{% if request.session.template == 0 %}
|
||||
<script src="{% static "js/template_users/gymnast_autocomplete_black.js" %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static "js/template_users/gymnast_autocomplete.js" %}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,88 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card mb-0">
|
||||
<div class="card-header">
|
||||
<h3 class="mb-0"><a href="{% url 'gymnast_details_tab' chrono.gymnast.id 'scores' %}">{{ chrono.gymnast }}</a></h3>
|
||||
<h4 class="card-title"> Chrono of {{ chrono.date | date:'d N Y' }}</h4>
|
||||
</div>
|
||||
<div class="card-body pb-0 mb-0">
|
||||
<div class="row mr-1 ml-1 pb-0 mb-0">
|
||||
<div class="col-md-2 offset-md-1">
|
||||
<table class="table tablesorter table-striped" data-sort="table" id="chrono_values_table">
|
||||
{% for detail in chrono.details.all %}
|
||||
<tr>
|
||||
<td>{{ detail.order }}</td>
|
||||
<td class="text-right">{{ detail.value }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td class="text-right"><b>{{ chrono.score }}</b></td>
|
||||
</tr>
|
||||
</table>
|
||||
<a href="{% url 'chrono_list_for_gymnast' chrono.gymnast.id %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning mr-2">
|
||||
<i class="fal fa-stopwatch"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-md-8 offset-md-1 alert {% if request.session.template == 0 %}skill-info{% else %}alert-secondary{% endif %} mr-0 pb-0 pl-1 pr-1">
|
||||
<canvas id="chartjs_chrono_details" class="chartjs" width="800" height="400"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
var ctx = document.getElementById("chartjs_chrono_details").getContext("2d");
|
||||
var gradient_stroke_1 = ctx.createLinearGradient(0, 450, 0, 0);
|
||||
|
||||
gradient_stroke_1.addColorStop(1, 'rgba(255, 99, 132, 0.4)');
|
||||
gradient_stroke_1.addColorStop(0.75, 'rgba(255, 99, 132, 0.3)');
|
||||
gradient_stroke_1.addColorStop(0.5, 'rgba(255, 99, 132, 0.2)');
|
||||
gradient_stroke_1.addColorStop(0.25, 'rgba(255, 99, 132, 0)');
|
||||
|
||||
new Chart(document.getElementById("chartjs_chrono_details"), {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [
|
||||
{% for detail in chrono.details.all %}
|
||||
{{ detail.order }},
|
||||
{% endfor %}
|
||||
],
|
||||
datasets: [{
|
||||
fill: true,
|
||||
borderColor: 'rgb(255, 99, 132)',
|
||||
cubicInterpolationMode: 'monotone',
|
||||
backgroundColor: gradient_stroke_1,
|
||||
pointBackgroundColor: 'rgb(255, 99, 132)',
|
||||
|
||||
data: [
|
||||
{% for detail in chrono.details.all %}
|
||||
{{ detail.value }},
|
||||
{% endfor %}
|
||||
],
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
yAxes: [{
|
||||
ticks: {
|
||||
suggestedMin: {{ chart_min_value }},
|
||||
suggestedMax: {{ chart_max_value }},
|
||||
}
|
||||
}]
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,99 @@
|
|||
{% extends "listing.html" %}
|
||||
|
||||
{% block datacontent %}
|
||||
<div class="card mb-0">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<h4 class=""> Chronos listing {% if gymnast %}for <i><a href="{% url 'gymnast_details_tab' gymnast.id 'scores' %}">{{ gymnast }}</a></i>{% endif %}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="col-1 ml-auto">
|
||||
<div class="text-right">
|
||||
<a
|
||||
href="{% if gymnast %}{% url 'chrono_create_for_gymnast' gymnast.id %}{% else %}{% url 'chrono_create' %}{% endif %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
{% if chrono_list %}
|
||||
<table class="table table-striped tablesorter" id="chrono_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 5%"> </th>
|
||||
<th style="width: 10%" class="header">Date</th>
|
||||
<th style="width: 25%" class="header text-left">Gymnast</th>
|
||||
<th style="width: 25%" class="header text-left">Routine</th>
|
||||
<th style="width: 15%" class="header">Type</th>
|
||||
<th style="width: 10%" class="header text-center">Score</th>
|
||||
<th style="width: 10%" class="header text-center">TOF</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for chrono in chrono_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td>
|
||||
<a href="{% url 'chrono_update' chrono.id %}">
|
||||
<span class="tim-icons icon-pencil text-warning"></span>
|
||||
</a>
|
||||
|
||||
<a href="{% url 'jump_chrono_values_create_or_update' chrono.id %}">
|
||||
<span class="far fa-search-plus text-warning"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td>{% if chrono.details.all %}<a href="{% url 'jump_chrono_details' chrono.id %}">{% endif %}{{ chrono.date | date:"d-m-Y" }}{% if chrono.details.all %}</a>{% endif %}</td>
|
||||
<td class="text-left">
|
||||
<a href="{% url 'gymnast_details_tab' chrono.gymnast.id 'scores' %}">
|
||||
{{ chrono.gymnast }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-left">
|
||||
{% if chrono.routine %}
|
||||
{{ chrono.routine.long_label }}
|
||||
{% else %}
|
||||
{{ chrono.get_chrono_type_display }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ chrono.get_score_type_display }}</td>
|
||||
<td class="text-center">{{ chrono.score }}</td>
|
||||
<td class="text-center">{{ chrono.tof }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="text-muted">There are no chronos corresponding to your criterias.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('#chrono_table').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false },
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[1, 1], [2, 1]]
|
||||
});
|
||||
|
||||
$('#chrono_table').DataTable({
|
||||
scrollY: 475,
|
||||
scrollCollapse: true,
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
// "bInfo" : false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,256 @@
|
|||
{% extends "base.html" %}
|
||||
{% load get_value_at_index %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card mb-0">
|
||||
<div class="card-header">
|
||||
<h3 class="mb-0"><a href="{% url 'gymnast_details_tab' gymnast.id 'scores' %}">{{ gymnast }}</a></h3>
|
||||
Chrono for
|
||||
<select id="routine_type">
|
||||
{% for type in distinct_routine_type_list %}
|
||||
<option value="{{ type }}" {% if type == selected_routine_type %}selected{% endif %}>{{ type }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
from {{ current_season }}
|
||||
{% if date_begin %}
|
||||
<i>{{ date_begin | date:'j M Y' }}</i> to <i>{{ date_end | date:'j M Y' }}</i>
|
||||
{% else %}
|
||||
<select id="select_season">
|
||||
{% for season in distinct_season_list %}
|
||||
<option value="{{ season }}" {% if selected_season|stringformat:"s" == season %}selected{% endif %}>{{ season }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<span id="week_1_management"> week
|
||||
<select id="select_week_number">
|
||||
{% for week_number in distinct_week_number_list %}
|
||||
<option value="{{ week_number }}" {% if selected_week_number == week_number %}selected{% endif %}>{{ week_number }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</span>
|
||||
{% endif %}
|
||||
<br />
|
||||
{% if chrono_list %}
|
||||
<input type="checkbox" id="comparison" name="comparison" /> Compare with: chrono for
|
||||
<select id="routine_type_2">
|
||||
{% for type in distinct_routine_type_list %}
|
||||
<option value="{{ type }}" {% if type == selected_routine_type %}selected{% endif %}>{{ type }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
from {{ current_season }}
|
||||
{% if date_begin %}
|
||||
<i>{{ date_begin | date:'j M Y' }}</i> to <i>{{ date_end | date:'j M Y' }}</i>
|
||||
{% else %}
|
||||
<select id="select_season_2">
|
||||
{% for season in distinct_season_list %}
|
||||
<option value="{{ season }}" {% if selected_season|stringformat:"s" == season %}selected{% endif %}>{{ season }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<span id="week_2_management"> week
|
||||
<select id="select_week_number_2">
|
||||
{% for week_number in distinct_week_number_list %}
|
||||
<option value="{{ week_number }}" {% if selected_week_number == week_number %}selected{% endif %}>{{ week_number }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body pb-0 mb-0">
|
||||
<div class="row pb-0 mb-0">
|
||||
{% if chrono_list %}
|
||||
<div class="col-md-5">
|
||||
<table class="table table-condensed" id="chrono_values_table">
|
||||
{% for chrono in chrono_list %}
|
||||
{% if chrono.details.all %}
|
||||
<tr>
|
||||
{% for detail in chrono.details.all %}
|
||||
{% with stat_value=stat_values|get_value_at_index:forloop.counter0 %}
|
||||
<td class="{% if stat_value.max_score == detail.value %}cell-success{% endif %}{% if stat_value.min_score == detail.value %}cell-danger{% endif %}">{{ detail.value | floatformat:2 }}</td>
|
||||
{% endwith %}
|
||||
{% endfor %}
|
||||
<td class="text-right"><b>{{ chrono.score | floatformat:2 }}</b></td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<tr>
|
||||
{% for value in stat_values %}
|
||||
<td><b>{{ value.avg_score | floatformat:2 }}</b></td>
|
||||
{% endfor %}
|
||||
<td class="text-right"><b></b></td>
|
||||
</tr>
|
||||
<!-- <tr>
|
||||
{% for value in stat_values %}
|
||||
<td><b>{{ value.min_score | floatformat:2 }}</b></td>
|
||||
{% endfor %}
|
||||
<td class="text-right"><b></b></td>
|
||||
</tr><tr>
|
||||
{% for value in stat_values %}
|
||||
<td><b>{{ value.max_score | floatformat:2 }}</b></td>
|
||||
{% endfor %}
|
||||
<td class="text-right"><b></b></td> -->
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-7 alert {% if request.session.template == 0 %}skill-info{% else %}alert-secondary{% endif %}">
|
||||
<canvas id="chartjs_chrono" class="chartjs"></canvas>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="col-md-12">
|
||||
No chrono details with the selected criteria (routine type, season and week).
|
||||
<br />
|
||||
<br />
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
|
||||
var ctx = document.getElementById("chartjs_chrono").getContext("2d");
|
||||
var gradient_stroke_1 = ctx.createLinearGradient(0, 450, 0, 0);
|
||||
var gradient_stroke_2 = ctx.createLinearGradient(0, 230, 0, 50);
|
||||
|
||||
gradient_stroke_1.addColorStop(1, 'rgba(255, 99, 132, 0.4)');
|
||||
gradient_stroke_1.addColorStop(0.75, 'rgba(255, 99, 132, 0.3)');
|
||||
gradient_stroke_1.addColorStop(0.5, 'rgba(255, 99, 132, 0.2)');
|
||||
gradient_stroke_1.addColorStop(0.25, 'rgba(255, 99, 132, 0)');
|
||||
|
||||
gradient_stroke_2.addColorStop(1, 'rgba(255, 159, 64, 0.4)');
|
||||
gradient_stroke_2.addColorStop(0.75, 'rgba(255, 159, 64, 0.3)');
|
||||
gradient_stroke_2.addColorStop(0.5, 'rgba(255, 159, 64, 0.2)');
|
||||
gradient_stroke_2.addColorStop(0.25, 'rgba(255, 159, 64, 0)');
|
||||
|
||||
var chrono_chart = new Chart(document.getElementById("chartjs_chrono"), {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
datasets: [{
|
||||
data: [
|
||||
{% for value in stat_values %}{{ value.avg_score | floatformat:3 }}, {% endfor %}
|
||||
],
|
||||
pointBackgroundColor: 'rgb(255, 99, 132)',
|
||||
borderColor: 'rgb(255, 99, 132)',
|
||||
backgroundColor: gradient_stroke_1,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
// min/max value ?
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
$('#select_season').change(function(){
|
||||
var tmp_url = "{% url 'get_chrono_detail_distinct_weeknumber_for_season' gymnast.id '_season_label_' %}";
|
||||
var season_label = $(this).children("option:selected").val();
|
||||
target_url = tmp_url.replace('_season_label_', season_label);
|
||||
|
||||
$.getJSON(target_url, function(data) {
|
||||
if (!$.trim(data))
|
||||
$('#week_1_management').hide();
|
||||
else
|
||||
$('#week_1_management').show();
|
||||
|
||||
$("#select_week_number option").remove(); // Remove all <option> child tags.
|
||||
$.each(data, function(key, value) { // Iterates through a collection
|
||||
$("#select_week_number").append( // Append an object to the inside of the select box
|
||||
$("<option></option>").text(value).val(value)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('#select_week_number').change(function(){
|
||||
var tmp_url = "{% url 'average_jump_chrono_details_for_gymnast_routinetype_season_and_week' gymnast.id '8888' '_season_label_' '9999' %}";
|
||||
var routine_type = $('#routine_type').children("option:selected").val();
|
||||
var season_label = $('#select_season').children("option:selected").val();
|
||||
var week_number = $(this).children("option:selected").val();
|
||||
|
||||
target_url = tmp_url.replace('8888', routine_type).replace('_season_label_', season_label).replace('9999', week_number);
|
||||
|
||||
$(location).attr('href', target_url);
|
||||
});
|
||||
|
||||
$('#select_season_2').change(function(){
|
||||
var tmp_url = "{% url 'get_chrono_detail_distinct_weeknumber_for_season' gymnast.id '_season_label_' %}";
|
||||
var season_label = $(this).children("option:selected").val();
|
||||
target_url = tmp_url.replace('_season_label_', season_label);
|
||||
|
||||
$.getJSON(target_url, function(data) {
|
||||
if (!$.trim(data))
|
||||
$('#week_2_management').hide();
|
||||
else
|
||||
$('#week_2_management').show();
|
||||
|
||||
$("#select_week_number_2 option").remove();
|
||||
$.each(data, function(key, value) {
|
||||
$("#select_week_number_2").append($("<option></option>").text(value).val(value));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function remove_comparison_data() {
|
||||
if ((Object.keys(chrono_chart.data.datasets).length) > 1) {
|
||||
chrono_chart.data.datasets.pop();
|
||||
chrono_chart.update();
|
||||
}
|
||||
}
|
||||
|
||||
function load_comparison_data() {
|
||||
var tmp_url = "{% url 'get_average_jump_chrono_details_for_season_and_week' gymnast.id '8888' '_season_label_' '9999' %}";
|
||||
var routine_type = $('#routine_type_2').children("option:selected").val();
|
||||
var season_label = $('#select_season_2').children("option:selected").val();
|
||||
var week_number = $('#select_week_number_2').children("option:selected").val();
|
||||
|
||||
target_url = tmp_url.replace('8888', routine_type).replace('_season_label_', season_label).replace('9999', week_number);
|
||||
|
||||
$.getJSON(target_url, function(data) {
|
||||
if (!$.trim(data))
|
||||
// $('#week_2_management').hide();
|
||||
alert('No data for comparison.');
|
||||
else {
|
||||
var new_values = []
|
||||
$.each(data, function(key, value) {
|
||||
item = JSON.stringify(value);
|
||||
new_values.push(parseFloat(value['avg_score']).toFixed(3));
|
||||
});
|
||||
var new_dataset = {
|
||||
pointBackgroundColor: 'rgb(255, 159, 64)',
|
||||
borderColor: 'rgb(255, 159, 64)',
|
||||
backgroundColor: gradient_stroke_2,
|
||||
cubicInterpolationMode: 'monotone',
|
||||
fill: true,
|
||||
data: new_values,
|
||||
}
|
||||
chrono_chart.data.datasets.push(new_dataset);
|
||||
chrono_chart.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$('#select_week_number_2').change(function(){
|
||||
if ($('#comparison').is(':checked')) {
|
||||
remove_comparison_data();
|
||||
load_comparison_data();
|
||||
}
|
||||
});
|
||||
|
||||
$('#comparison').change(function(){
|
||||
if (this.checked) {
|
||||
if (($('#select_week_number_2').val() != $('#select_week_number').val()) || ($('#select_season_2').val() != $('#select_season').val()))
|
||||
load_comparison_data();
|
||||
} else {
|
||||
remove_comparison_data();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,97 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-8 col-lg-6 col-xl-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="">{% if heightweight_id %}Edit{% else %}Add{% endif %} height/weight couple</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger">
|
||||
{{ form.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
<form
|
||||
action="{% if heightweight_id %}{% url 'heightweight_update' heightweight_id %}{% else %}{% url 'heightweight_create' %}{% endif %}"
|
||||
method="post" class="form-horizontal" id="formulaire" name="formulaire">
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-group row ">
|
||||
<label for="id_gymnast" class="col-3 col-sm-2 col-form-label">Gymnast <span class="text-danger"><b>*</b></span></label>
|
||||
<div
|
||||
class="col-9 col-sm-9 col-md-9 col-lg-6 col-lg-8 col-xl-8 {% if form.jumper.errors %}has-danger{% endif %}">
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
{{ form.gymnast }}
|
||||
{{ form.gymnast_related }}
|
||||
{% if form.gymnast.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.gymnast.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
{% else %}
|
||||
<input type="text" class="form-control" value="{{ request.user.first_name }} {{ request.user.last_name }}" readonly="readonly" />
|
||||
<input type="hidden" name="gymnast" id="gymnast" value="{{ request.user.gymnast.id }}" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-3 col-sm-2 col-form-label">Date <span
|
||||
class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-6 col-sm-3 col-md-5 col-lg-4 col-xl-3 {% if form.date.errors %}has-danger{% endif %}">
|
||||
{{ form.date }}
|
||||
{% if form.date.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.date.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row ">
|
||||
<label for="id_height" class="col-3 col-sm-2 col-form-label">Height <span
|
||||
class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-6 col-sm-3 col-md-3 col-lg-3 {% if form.height.errors %}has-danger{% endif %}">
|
||||
{{ form.height }}
|
||||
{% if form.height.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.height.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_hips_height" class="col-3 col-sm-2 col-form-label">Hips Height</label>
|
||||
<div
|
||||
class="col-6 col-sm-3 col-md-3 col-lg-3 {% if form.hips_height.errors %}has-danger{% endif %}">
|
||||
{{ form.hips_height }}
|
||||
{% if form.hips_height.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.hips_height.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_weight" class="col-3 col-sm-2 col-form-label">Weight <span
|
||||
class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-6 col-sm-3 col-md-3 col-lg-3 {% if form.weight.errors %}has-danger{% endif %}">
|
||||
{{ form.weight }}
|
||||
{% if form.weight.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.weight.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" value="Save" class="btn btn-fill btn-warning" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
blackDashboard.initDateTimePicker();
|
||||
});
|
||||
|
||||
const csrf_token = "{{ csrf_token|escapejs }}";
|
||||
const gymnast_lookup = "{% url 'gymnast_lookup' %}";
|
||||
</script>
|
||||
<script src="{% static " js/template_users/datepicker_maxdate_today.js" %}"></script>
|
||||
{% if request.session.template == 0 %}
|
||||
<script src="{% static " js/template_users/gymnast_autocomplete_black.js" %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static " js/template_users/gymnast_autocomplete.js" %}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,84 @@
|
|||
{% extends "listing.html" %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block datacontent %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-12 col-xl-12">
|
||||
<div class="card">
|
||||
<div class="card-header row">
|
||||
<div class="col-8">
|
||||
<h4 class="">Height/Weight list {% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'physiological' %}"><i>{{ gymnast }}</i></a>{% endif %}</h4>
|
||||
</div>
|
||||
<div class="col-1 ml-auto">
|
||||
<div class="text-right">
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
<a href="{% if gymnast %}{% url 'heightweight_create_for_gymnast' gymnast.id %}{% else %}{% url 'heightweight_create' %}{% endif %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if heightweight_list %}
|
||||
<table class="table tablesorter table-striped mb-0" data-sort="table" id="heightweight_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="header text-left">Date</th>
|
||||
<th class="header text-left">Gymnast</th>
|
||||
<th class="header text-left">Height</th>
|
||||
<th class="header text-left">Hips height</th>
|
||||
<th class="header text-left">Weight</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for heightweight in heightweight_list %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'heightweight_update' heightweight.id %}">
|
||||
<span class="tim-icons icon-pencil text-warning"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-left">{{ heightweight.date | date:"d-m-Y" }}</td>
|
||||
<td class="text-left"><a href="{% url 'gymnast_details' heightweight.gymnast.id %}">{{ heightweight.gymnast }}</a></td>
|
||||
<td>{{ heightweight.height }}</td>
|
||||
<td>{{ heightweight.hips_height }}</td>
|
||||
<td>{{ heightweight.weight }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="text-muted">There are no scores corresponding to your criterias</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('[data-sort="table"]').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false },
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[1, 1]]
|
||||
});
|
||||
|
||||
$('#heightweight_table').DataTable({
|
||||
scrollY: 500,
|
||||
scrollCollapse: true,
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
// "bInfo" : false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,137 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-8 col-lg-6 col-xl-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="">{% if intensity_id %}Edit{% else %}Add{% endif %} intensity</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form
|
||||
action="{% if intensity_id %}{% url 'intensity_update' intensity_id %}{% else %}{% url 'intensity_create' %}{% endif %}"
|
||||
method="post" class="form-horizontal" id="formulaire" name="formulaire">
|
||||
{% csrf_token %}
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Gymnast <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-8 col-sm-9 col-md-9 col-lg-6 col-lg-4 col-xl-4 {% if form.jumper.errors %}has-danger{% endif %}">
|
||||
{{ form.gymnast }}
|
||||
{{ form.gymnast_related }}
|
||||
{% if form.gymnast.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.gymnast.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Date <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-5 col-sm-3 col-md-4 col-lg-4 col-xl-4 {% if form.date.errors %}has-danger{% endif %}">
|
||||
{{ form.date }}
|
||||
{% if form.date.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.date.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_time" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Time <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-5 col-sm-3 col-md-3 col-lg-2 {% if form.time.errors %}has-danger{% endif %}">
|
||||
{{ form.time }}
|
||||
{% if form.time.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.time.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_difficulty" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Difficulty <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-5 col-sm-3 col-md-3 col-lg-2 {% if form.difficulty.errors %}has-danger{% endif %}">
|
||||
{{ form.difficulty }}
|
||||
{% if form.difficulty.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.difficulty.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_quantity_of_skill" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label"># of skill <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-5 col-sm-3 col-md-3 col-lg-2 {% if form.quantity_of_skill.errors %}has-danger{% endif %}">
|
||||
{{ form.quantity_of_skill }}
|
||||
{% if form.quantity_of_skill.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.quantity_of_skill.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_number_of_passes" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label"># of passes <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-5 col-sm-3 col-md-3 col-lg-2 {% if form.number_of_passes.errors %}has-danger{% endif %}">
|
||||
{{ form.number_of_passes }}
|
||||
{% if form.number_of_passes.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.number_of_passes.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_information" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Informations</label>
|
||||
<div class="col-5 col-sm-10 col-md-10 col-lg-10 col-xl-10 {% if form.id_informations.errors %}has-danger{% endif %}">
|
||||
{{ form.informations }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" value="{% if note_id %}Save{% else %}Add{% endif %}"
|
||||
class="btn btn-warning" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
blackDashboard.initDateTimePicker();
|
||||
});
|
||||
|
||||
const csrf_token = "{{ csrf_token|escapejs }}";
|
||||
const gymnast_lookup = "{% url 'gymnast_lookup' %}";
|
||||
|
||||
$('#id_club_related').autocomplete({
|
||||
source: function(request, response) {
|
||||
$.ajax({
|
||||
url: club_lookup,
|
||||
method: "POST",
|
||||
data: {
|
||||
pattern: $('#id_club_related').val(),
|
||||
csrfmiddlewaretoken: csrf_token
|
||||
},
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
if(data.length != 0) {
|
||||
response($.map(data, function(item) {
|
||||
return {
|
||||
label: item.Name,
|
||||
value: item.Name,
|
||||
clubid: item.ID
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
response([{ label: 'No result found.', value: '' }]);
|
||||
};
|
||||
},
|
||||
|
||||
error: function (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
});
|
||||
},
|
||||
minLength: 3,
|
||||
select: function (event, ui) {
|
||||
$($(this).data('ref')).val(ui.item.clubid);
|
||||
},
|
||||
{% if request.session.template == 0 %}
|
||||
classes: {
|
||||
"ui-widget-content": "custom_autocomplete_ul",
|
||||
"ui-autocomplete": "custom_autocomplete_ul",
|
||||
"ui-menu-item-wrapper": "custom_autocomplete_li",
|
||||
"ui-menu-item": "custom_autocomplete_li",
|
||||
},
|
||||
{% endif %}
|
||||
});
|
||||
</script>
|
||||
<script src="{% static " js/template_users/datepicker_maxdate_today.js" %}"></script>
|
||||
{% if request.session.template == 0 %}
|
||||
<script src="{% static " js/template_users/gymnast_autocomplete_black.js" %}"></script>
|
||||
<script src="{% static " js/template_users/skill_autocomplete_black.js" %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static " js/template_users/gymnast_autocomplete.js" %}"></script>
|
||||
<script src="{% static " js/template_users/skill_autocomplete.js" %}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,96 @@
|
|||
{% extends "listing.html" %}
|
||||
|
||||
{% block datacontent %}
|
||||
<div class="card mb-0">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<h4 class=""> Intensity listing {% if gymnast %}for <i><a href="{% url 'gymnast_details_tab' gymnast.id 'routine' %}">{{ gymnast }}</a></i>{% endif %}
|
||||
</h4>
|
||||
</div>
|
||||
<div class="col-1 ml-auto">
|
||||
<div class="text-right">
|
||||
<a href="{% if gymnast %}{% url 'intensity_create_for_gymnast' gymnast.id %}{% else %}{% url 'intensity_create' %}{% endif %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
{% if intensity_list %}
|
||||
<table class="table table-striped tablesorter" id="intensity_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 3%"> </th>
|
||||
<th style="width: 7%" class="header">Date</th>
|
||||
<th style="width: 25%" class="header text-left">Gymnast</th>
|
||||
<th style="width: 7%" class="header text-left">Time</th>
|
||||
<th style="width: 7%" class="header">Diff</th>
|
||||
<th style="width: 7%" class="header text-center"># skill</th>
|
||||
<th style="width: 7%" class="header text-center"># passes</th>
|
||||
<th style="width: 7%" class="header text-left">mean diff/passe</th>
|
||||
<th style="width: 7%" class="header">mean # skill</th>
|
||||
<th style="width: 7%" class="header text-center"># skill/passe</th>
|
||||
<th style="width: 7%" class="header text-center">mean diff/skill</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for intensity in intensity_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td>
|
||||
<a href="{% url 'intensity_update' intensity.id %}">
|
||||
<span class="tim-icons icon-pencil text-warning"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td>{{ intensity.date | date:"d-m-Y" }}</td>
|
||||
<td class="text-left">
|
||||
<a href="{% url 'gymnast_details_tab' intensity.gymnast.id 'routine' %}">
|
||||
{{ intensity.gymnast }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-left">{{ intensity.time }}</td>
|
||||
<td>{{ intensity.difficulty }}</td>
|
||||
<td class="text-center">{{ intensity.quantity_of_skill }}</td>
|
||||
<td class="text-center">{{ intensity.number_of_passes }}</td>
|
||||
<td class="text-left">{{ intensity.mean_difficulty_by_passe | floatformat:2 }}</td>
|
||||
<td>{{ intensity.mean_quantity_of_skill | floatformat:2 }}</td>
|
||||
<td class="text-center">{{ intensity.quantity_of_skill_by_passe | floatformat:2 }}</td>
|
||||
<td class="text-center">{{ intensity.mean_difficulty_by_skill | floatformat:2 }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="text-muted">There are no intensity corresponding to your criterias.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('#intensity_table').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false },
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[1, 1], [2, 1]]
|
||||
});
|
||||
|
||||
$('#intensity_table').DataTable({
|
||||
scrollY: 475,
|
||||
scrollCollapse: true,
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
// "bInfo" : false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,90 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-8 col-xl-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Add Jumper/Skill link</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{% url 'learnedskill_create' %}" method="post" class="form-horizontal" id="formulaire" name="formulaire">
|
||||
{% csrf_token %}
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-4 col-sm-3 col-form-label">Date</label>
|
||||
<div class="col-sm-6 col-md-5 col-lg-4 col-xl-3 {% if form.date.errors %}has-danger{% endif %}">
|
||||
{{ form.date }}
|
||||
{% if form.date.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.date.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_gymnast" class="col-4 col-sm-3 col-form-label">Gymnast <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-8 col-md-9 col-lg-6 col-lg-4 col-xl-4 {% if form.jumper.errors %}has-danger{% endif %}">
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
{{ form.gymnast }}
|
||||
{{ form.gymnast_related }}
|
||||
{% if form.gymnast.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.gymnast.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
{% else %}
|
||||
<input type="text" class="form-control" value="{{ request.user.first_name }} {{ request.user.last_name }}" readonly="readonly" />
|
||||
<input type="hidden" name="gymnast" id="gymnast" value="{{ request.user.gymnast.id }}" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group row ">
|
||||
<label for="id_skill" class="col-4 col-sm-3 col-form-label">Skill</label>
|
||||
<div class="col-8 col-md-9 col-lg-6 {% if form.skill.errors %}has-danger{% endif %}">
|
||||
{{ form.skill }}
|
||||
{{ form.skill_related }}
|
||||
{% if form.skill.errors %} <skilln class="btn btn-sm btn-danger-outline">{% for error in form.skill.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_learning_step" class="col-4 col-sm-3 col-form-label">Learning step</label>
|
||||
<div class="col-8 col-sm-4 col-md-3 {% if form.learning_step.errors %}has-danger{% endif %}">
|
||||
{{ form.learning_step }}
|
||||
{% if form.learning_step.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.learning_step.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if plan_id %}
|
||||
<div class="form-group row {% if form.is_done.errors %}has-error has-feedback{% endif %}">
|
||||
<label for="id_is_done" class="col-4 col-sm-2 col-md-3 col-lg-3 col-xl-3 col-form-label">Is Done</label>
|
||||
<div class="col-8 col-sm-2 col-md-2 col-lg-2 col-xl-2">
|
||||
{{ form.is_done }}
|
||||
{% if form.is_done.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.is_done.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" value="Save" class="btn btn-fill btn-warning" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" >
|
||||
$(function(){
|
||||
|
||||
$('#id_birthdate').datetimepicker({
|
||||
format: 'YYYY-MM-DD'
|
||||
});
|
||||
blackDashboard.initDateTimePicker();
|
||||
|
||||
});
|
||||
|
||||
const csrf_token = "{{ csrf_token|escapejs }}";
|
||||
const gymnast_lookup = "{% url 'gymnast_lookup' %}";
|
||||
const skill_lookup = "{% url 'skill_lookup' %}";
|
||||
</script>
|
||||
{% if request.session.template == 0 %}
|
||||
<script src="{% static "js/template_users/gymnast_autocomplete_black.js" %}"></script>
|
||||
<script src="{% static "js/template_users/skill_autocomplete_black.js" %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static "js/template_users/gymnast_autocomplete.js" %}"></script>
|
||||
<script src="{% static "js/template_users/skill_autocomplete.js" %}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,92 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-8 col-lg-6 col-xl-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="">{% if mindstate_id %}Edit{% else %}Add{% endif %} mind state score</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="{% if mindstate_id %}{% url 'mindstate_update' mindstate_id %}{% else %}{% url 'mindstate_create' %}{% endif %}" method="post" class="form-horizontal" id="formulaire" name="formulaire">
|
||||
{% csrf_token %}
|
||||
<div class="form-group row ">
|
||||
<label for="id_gymnast" class="col-3 col-sm-2 col-md-3 col-lg-3 col-xl-2 col-form-label">Gymnast <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-8 col-sm-9 col-md-9 col-lg-6 col-lg-8 col-xl-8 {% if form.jumper.errors %}has-danger{% endif %}">
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
{{ form.gymnast }}
|
||||
{{ form.gymnast_related }}
|
||||
{% if form.gymnast.errors %}
|
||||
<label class="text-danger" for="id_gymnast" id="gymnast-error">
|
||||
{% for error in form.gymnast.errors %}{{ error }}{% endfor %}
|
||||
</label>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<input type="text" class="form-control" value="{{ request.user.first_name }} {{ request.user.last_name }}" readonly="readonly" />
|
||||
<input type="hidden" name="gymnast" id="gymnast" value="{{ request.user.gymnast.id }}" />
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-3 col-sm-2 col-md-3 col-lg-3 col-xl-2 col-form-label">Date <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-5 col-sm-3 col-md-3 col-lg-4 col-xl-3 {% if form.date.errors %}has-danger{% endif %}">
|
||||
{{ form.date }}
|
||||
{% if form.date.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.date.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_event" class="col-3 col-sm-2 col-md-3 col-lg-3 col-xl-2 col-form-label">Event</label>
|
||||
<div class="col-8 col-sm-9 col-md-9 col-lg-9 col-xl-10 {% if form.date.errors %}has-danger{% endif %}">
|
||||
{{ form.event }}
|
||||
{{ form.event_related }}
|
||||
{% if form.eventt.errors %}
|
||||
<label class="text-danger" for="id_eventt" id="event-error">
|
||||
{% for error in form.event.errors %}{{ error }}{% endfor %}
|
||||
</label>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_score" class="col-3 col-sm-2 col-md-3 col-lg-3 col-xl-2 col-form-label">Score <span class="text-danger"><b>*</b></span></label>
|
||||
<div class="col-4 col-sm-3 col-md-3 col-lg-3 {% if form.score.errors %}has-danger{% endif %}">
|
||||
{{ form.score }}
|
||||
{% if form.score.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.score.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_information" class="col-3 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Informations</label>
|
||||
<div class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10 {% if form.id_information.errors %}has-danger{% endif %}">
|
||||
{{ form.informations }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" value="{% if mindstate_id %}Save{% else %}Add{% endif %}" class="btn btn-warning" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript" >
|
||||
$(function(){
|
||||
blackDashboard.initDateTimePicker();
|
||||
});
|
||||
|
||||
const csrf_token = "{{ csrf_token|escapejs }}";
|
||||
const gymnast_lookup = "{% url 'gymnast_lookup' %}";
|
||||
const event_lookup = "{% url 'event_lookup' %}";
|
||||
</script>
|
||||
<script src="{% static "js/template_users/datepicker_maxdate_today.js" %}"></script>
|
||||
{% if request.session.template == 0 %}
|
||||
<script src="{% static "js/template_users/gymnast_autocomplete_black.js" %}"></script>
|
||||
<script src="{% static "js/template_users/event_autocomplete_black.js" %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static "js/template_users/gymnast_autocomplete.js" %}"></script>
|
||||
<script src="{% static "js/template_users/event_autocomplete.js" %}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,30 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-8 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title mb-0">Mind State {{ mindstate.date | date:"d N Y" }}</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<a href="{% url 'gymnast_details_tab' mindstate.gymnast.id 'physiological' %}">{{ mindstate.gymnast }}</a> : {{ mindstate.score }}
|
||||
<br />
|
||||
<br />
|
||||
|
||||
{{ mindstate.to_markdown | safe }}
|
||||
|
||||
<div class="card-footer pl-0 pb-0">
|
||||
<a href="{% url 'mindstate_list' %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="tim-icons icon-double-left"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,80 @@
|
|||
{% extends "listing.html" %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block datacontent %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-12 col-xl-12">
|
||||
<div class="card">
|
||||
<div class="card-header row">
|
||||
<div class="col-8">
|
||||
<h4 class="">Mind State list {% if gymnast %}for <a href="{% url 'gymnast_details_tab' gymnast.id 'physiological' %}"><i>{{ gymnast }}</i></a>{% endif %}</h4>
|
||||
</div>
|
||||
<div class="col-1 ml-auto">
|
||||
<div class="text-right">
|
||||
{% if request.user|has_group:"trainer" %}
|
||||
<a href="{% if gymnast %}{% url 'mindstate_create_for_gymnast' gymnast.id %}{% else %}{% url 'mindstate_create' %}{% endif %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
{% if mindstate_list %}
|
||||
<table class="table tablesorter table-striped mb-0" data-sort="table" id="mindstate_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th class="header text-left">Date</th>
|
||||
<th class="header text-left">Gymnast</th>
|
||||
<th class="header text-left">Score</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for state in mindstate_list %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{% url 'mindstate_update' state.id %}">
|
||||
<span class="tim-icons icon-pencil text-warning"></span>
|
||||
</a>
|
||||
</td>
|
||||
<td class="text-left">{{ state.date | date:"d-m-Y" }}</td>
|
||||
<td class="text-left"><a href="{% url 'gymnast_details_tab' state.gymnast.id 'physiological' %}">{{ state.gymnast }}</a></td>
|
||||
<td>{{ state.score }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="text-muted">There are no mindstates corresponding to your criterias</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('[data-sort="table"]').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false },
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[1, 1]]
|
||||
});
|
||||
|
||||
$('#mindstate_table').DataTable({
|
||||
scrollY: 500,
|
||||
scrollCollapse: true,
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
// "bInfo" : false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,84 @@
|
|||
{% extends "base.html" %}
|
||||
{% load static %}
|
||||
{% load has_group %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-10 col-xl-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="">{% if note_id %}Edit{% else %}Add{% endif %} notes</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form
|
||||
action="{% if note_id %}{% url 'note_update' note_id %}{% else %}{% url 'note_create' %}{% endif %}"
|
||||
method="post" class="form-horizontal" id="formulaire" name="formulaire">
|
||||
{% csrf_token %}
|
||||
{{ form.coach }}
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Gymnast
|
||||
<span class="text-danger"><b>*</b></span></label>
|
||||
<div
|
||||
class="col-8 col-md-9 col-lg-6 col-lg-4 col-xl-4 {% if form.jumper.errors %}has-danger{% endif %}">
|
||||
{{ form.gymnast }}
|
||||
{{ form.gymnast_related }}
|
||||
{% if form.gymnast.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.gymnast.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_date" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Date <span
|
||||
class="text-danger"><b>*</b></span></label>
|
||||
<div
|
||||
class="col-8 col-sm-6 col-md-4 col-lg-4 col-xl-4 {% if form.date.errors %}has-danger{% endif %}">
|
||||
{{ form.date }}
|
||||
{% if form.date.errors %}<span class="btn btn-sm btn-danger-outline">{% for error in form.date.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_information"
|
||||
class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Informations <span
|
||||
class="text-danger"><b>*</b></span></label>
|
||||
<div
|
||||
class="col-8 col-sm-10 col-md-10 col-lg-10 col-xl-10 {% if form.id_informations.errors %}has-danger{% endif %}">
|
||||
{{ form.informations }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row ">
|
||||
<label for="id_status" class="col-4 col-sm-2 col-md-2 col-lg-2 col-xl-2 col-form-label">Status
|
||||
<span class="text-danger"><b>*</b></span></label>
|
||||
<div
|
||||
class="col-8 col-sm-5 col-md-4 col-lg-4 col-xl-4 {% if form.status.errors %}has-danger{% endif %}">
|
||||
{{ form.status }}
|
||||
{% if form.status.errors %} <span class="btn btn-sm btn-danger-outline">{% for error in form.status.errors %}{{ error }}{% endfor %}</span>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group text-center">
|
||||
<input type="submit" value="{% if note_id %}Save{% else %}Add{% endif %}"
|
||||
class="btn btn-warning" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
blackDashboard.initDateTimePicker();
|
||||
});
|
||||
|
||||
const csrf_token = "{{ csrf_token|escapejs }}";
|
||||
const gymnast_lookup = "{% url 'gymnast_lookup' %}";
|
||||
const skill_lookup = "{% url 'skill_lookup' %}";
|
||||
</script>
|
||||
<script src="{% static " js/template_users/datepicker_maxdate_today.js" %}"></script>
|
||||
{% if request.session.template == 0 %}
|
||||
<script src="{% static " js/template_users/gymnast_autocomplete_black.js" %}"></script>
|
||||
<script src="{% static " js/template_users/skill_autocomplete_black.js" %}"></script>
|
||||
{% else %}
|
||||
<script src="{% static " js/template_users/gymnast_autocomplete.js" %}"></script>
|
||||
<script src="{% static " js/template_users/skill_autocomplete.js" %}"></script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
|
@ -0,0 +1,19 @@
|
|||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="card mb-0">
|
||||
<div class="card-header">
|
||||
<h3 class="mb-0"><a href="{% url 'gymnast_details_tab' note.gymnast.id 'scores' %}">{{ note.gymnast }}</a></h3>
|
||||
<h4 class="card-title"> Note of {{ note.created_at | date:'d-m-Y' }}</h4>
|
||||
</div>
|
||||
<div class="card-body pb-0 mb-0">
|
||||
<div class="row mr-1 ml-1 pb-0 mb-0">
|
||||
<div class="col-md-12">
|
||||
<p>{{ note.to_markdown | safe }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<a href="{% url 'note_update' note.id %}"><span class="tim-icons icon-pencil text-warning"></span></a><br /><br />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,77 @@
|
|||
{% extends "listing.html" %}
|
||||
|
||||
{% block datacontent %}
|
||||
<div class="card mb-0">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<h4 class=""> Notes listing {% if gymnast %}for <i>{{ gymnast }}</i>{% endif %}</h4>
|
||||
</div>
|
||||
<div class="col-1 ml-auto">
|
||||
<div class="text-right">
|
||||
<a href="{% if gymnast %}{% url 'note_create_for_gymnast' gymnast.id %}{% else %}{% url 'note_create' %}{% endif %}">
|
||||
<button type="submit" value="add" class="btn btn-icon btn-warning ">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
{% if note_list %}
|
||||
<table class="table table-striped tablesorter" id="chrono_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 5%"> </th>
|
||||
<th style="width: 10%" class="header">Date</th>
|
||||
<th style="width: 25%" class="header text-left">Gymnast</th>
|
||||
<th style="width: 25%" class="header text-left">Coach</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for note in note_list %}
|
||||
<tr role="row" class="{% cycle 'odd' 'even' %}">
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url 'note_details' note.id %}">{{ note.created_at | date:"d-m-Y" }}</a>
|
||||
</td>
|
||||
<td class="text-left"><a href="{% url 'gymnast_details' note.gymnast.id %}">{{ note.gymnast
|
||||
}}</a></td>
|
||||
<td class="text-left">{{ note.coach }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<p class="text-muted">There are no chronos corresponding to your criterias.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block footerscript %}
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function () {
|
||||
$('#chrono_table').tablesorter({
|
||||
headers: {
|
||||
0: { sorter: false },
|
||||
},
|
||||
dateFormat: "uk",
|
||||
sortList: [[1, 1], [2, 1]]
|
||||
});
|
||||
|
||||
$('#chrono_table').DataTable({
|
||||
scrollY: 475,
|
||||
scrollCollapse: true,
|
||||
paging: false,
|
||||
searching: false,
|
||||
ordering: false,
|
||||
// "bInfo" : false,
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue