Browse Source

Primer commit

main
Celestino Rey 10 months ago
commit
f526fd9a71
2405 changed files with 436554 additions and 0 deletions
  1. +49
    -0
      README.md
  2. +1
    -0
      accounts/.gitignore
  3. +0
    -0
      accounts/__init__.py
  4. +3
    -0
      accounts/admin.py
  5. +6
    -0
      accounts/apps.py
  6. +3
    -0
      accounts/models.py
  7. +3
    -0
      accounts/tests.py
  8. +8
    -0
      accounts/urls.py
  9. +1
    -0
      accounts/views.py
  10. +0
    -0
      libros/__init__.py
  11. +8
    -0
      libros/admin.py
  12. +6
    -0
      libros/apps.py
  13. +30
    -0
      libros/forms.py
  14. +38
    -0
      libros/migrations/0001_initial.py
  15. +0
    -0
      libros/migrations/__init__.py
  16. +32
    -0
      libros/models.py
  17. +3
    -0
      libros/tests.py
  18. +21
    -0
      libros/urls.py
  19. +103
    -0
      libros/views.py
  20. +0
    -0
      lyrics/__init__.py
  21. +9
    -0
      lyrics/admin.py
  22. +6
    -0
      lyrics/apps.py
  23. +41
    -0
      lyrics/forms.py
  24. +0
    -0
      lyrics/management/commands/__init__.py
  25. +23
    -0
      lyrics/management/commands/importa_album.py
  26. +23
    -0
      lyrics/management/commands/importa_artista.py
  27. +26
    -0
      lyrics/management/commands/importa_song.py
  28. +52
    -0
      lyrics/migrations/0001_initial.py
  29. +0
    -0
      lyrics/migrations/__init__.py
  30. +42
    -0
      lyrics/models.py
  31. +3
    -0
      lyrics/tests.py
  32. +27
    -0
      lyrics/urls.py
  33. +190
    -0
      lyrics/views.py
  34. +22
    -0
      manage.py
  35. BIN
      mediafiles/profile_images/default.jpg
  36. BIN
      mediafiles/profile_images/gravatar-tino.jpeg
  37. BIN
      mediafiles/profile_images/gravatar-tino_jqB0Vq4.jpeg
  38. BIN
      mediafiles/vehiculos/bmw.jpg
  39. BIN
      mediafiles/vehiculos/bmw.png
  40. BIN
      mediafiles/vehiculos/bmw_PMjCK7Q.png
  41. BIN
      mediafiles/vehiculos/bmw_cSbhRuf.png
  42. BIN
      mediafiles/vehiculos/bmw_x00n9W7.png
  43. BIN
      mediafiles/vehiculos/bmw_yVyuq4g.jpg
  44. +1
    -0
      repostajes/.gitignore
  45. +0
    -0
      repostajes/__init__.py
  46. +9
    -0
      repostajes/admin.py
  47. +6
    -0
      repostajes/apps.py
  48. +41
    -0
      repostajes/forms.py
  49. +27
    -0
      repostajes/models.py
  50. +12
    -0
      repostajes/static/css/portal.css
  51. +21
    -0
      repostajes/static/images/app-logo.svg
  52. BIN
      repostajes/static/images/background/background-1.jpg
  53. BIN
      repostajes/static/images/background/background-2.jpg
  54. BIN
      repostajes/static/images/background/background-3.jpg
  55. BIN
      repostajes/static/images/background/background-palmeras.jpg
  56. BIN
      repostajes/static/images/doc-thumb-1.jpg
  57. BIN
      repostajes/static/images/doc-thumb-2.jpg
  58. BIN
      repostajes/static/images/favicon.ico
  59. BIN
      repostajes/static/images/favicon.png
  60. +21
    -0
      repostajes/static/images/portal-logo.svg
  61. BIN
      repostajes/static/images/profiles/profile-1.png
  62. BIN
      repostajes/static/images/profiles/profile-2.png
  63. BIN
      repostajes/static/images/profiles/profile-3.png
  64. BIN
      repostajes/static/images/profiles/profile-4.png
  65. BIN
      repostajes/static/images/profiles/profile-5.png
  66. BIN
      repostajes/static/images/profiles/profile-6.png
  67. +18
    -0
      repostajes/static/images/reymota-logo.svg
  68. BIN
      repostajes/static/images/user.png
  69. BIN
      repostajes/static/images/users/user-1.jpg
  70. BIN
      repostajes/static/images/users/user-2.jpg
  71. BIN
      repostajes/static/images/users/user-3.jpg
  72. BIN
      repostajes/static/images/users/user-4.jpg
  73. BIN
      repostajes/static/images/users/user-5.jpg
  74. BIN
      repostajes/static/images/users/user-6.jpg
  75. BIN
      repostajes/static/images/users/user-7.jpg
  76. BIN
      repostajes/static/images/users/user-8.jpg
  77. BIN
      repostajes/static/images/users/user-9.jpg
  78. +96
    -0
      repostajes/static/js/app.js
  79. +366
    -0
      repostajes/static/js/charts-demo.js
  80. +224
    -0
      repostajes/static/js/index-charts.js
  81. +4085
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-grid.css
  82. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-grid.css.map
  83. +6
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-grid.min.css
  84. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-grid.min.css.map
  85. +4084
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-grid.rtl.css
  86. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-grid.rtl.css.map
  87. +6
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-grid.rtl.min.css
  88. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-grid.rtl.min.css.map
  89. +593
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-reboot.css
  90. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-reboot.css.map
  91. +6
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-reboot.min.css
  92. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-reboot.min.css.map
  93. +590
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-reboot.rtl.css
  94. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-reboot.rtl.css.map
  95. +6
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-reboot.rtl.min.css
  96. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-reboot.rtl.min.css.map
  97. +5399
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-utilities.css
  98. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-utilities.css.map
  99. +6
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-utilities.min.css
  100. +1
    -0
      repostajes/static/plugins/bootstrap/css/bootstrap-utilities.min.css.map

+ 49
- 0
README.md View File

@ -0,0 +1,49 @@
# Instalación
Desde el directorio K8S ejecutar make (esto hace todo: la imagen, para los pods y los lanza otra vez)
La primera vez, hay que entrar en el pod de vehículos con 'entra.sh' y
python manage.py createsuperuser
python manage.py makemigrations
python manage.py migrate
## Comprobar la base de datos
Con la shell entraPsql.sh:
\l para listar las BD
\c reymota para usar nuestra db
\dt para ver las tablas
# De dónde cogí ideas
https://learndjango.com/tutorials/django-login-and-logout-tutorial
Username: {{ user.username }}
User Full name: {{ user.get_full_name }}
User Group: {{ user.groups.all.0 }}
Email: {{ user.email }}
Session Started at: {{ user.last_login }}
## Para funcionar con gunicorn y nginx
https://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/
## Cambiar la secuencia de lo sid
ALTER SEQUENCE tablename_id_seq RESTART WITH nn;
esto se hace cuando restauro un volcado de la bd sobre una instalación nueva. Si hay índices ya creados, hay que reinciar a partir del último.

+ 1
- 0
accounts/.gitignore View File

@ -0,0 +1 @@
migrations/

+ 0
- 0
accounts/__init__.py View File


+ 3
- 0
accounts/admin.py View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

+ 6
- 0
accounts/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'

+ 3
- 0
accounts/models.py View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

+ 3
- 0
accounts/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 8
- 0
accounts/urls.py View File

@ -0,0 +1,8 @@
# accounts/urls.py
from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('login/', auth_views.LoginView.as_view(), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]

+ 1
- 0
accounts/views.py View File

@ -0,0 +1 @@
from django.shortcuts import render

+ 0
- 0
libros/__init__.py View File


+ 8
- 0
libros/admin.py View File

@ -0,0 +1,8 @@
from django.contrib import admin
# Register your models here.
from .models import Autor, Libro
admin.site.register(Autor)
admin.site.register(Libro)

+ 6
- 0
libros/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class LibrosConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'libros'

+ 30
- 0
libros/forms.py View File

@ -0,0 +1,30 @@
from django import forms
from .models import Autor, Libro
class AutorForm(forms.ModelForm):
class Meta:
model = Autor
fields = ['nombre', 'biografia', 'foto']
nombre = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
biografia = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
class LibroForm(forms.ModelForm):
class Meta:
model = Libro
fields = ['titulo', 'autor', 'fecha_publicacion', 'descripcion',
'archivo', 'portada']
titulo = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
descripcion = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
autor = forms.ModelChoiceField(
queryset=Autor.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'}))

+ 38
- 0
libros/migrations/0001_initial.py View File

@ -0,0 +1,38 @@
# Generated by Django 4.2 on 2024-09-09 14:52
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import libros.models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Autor',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nombre', models.CharField(max_length=200)),
('biografia', models.TextField(blank=True, null=True)),
('foto', models.ImageField(blank=True, null=True, upload_to='autores/')),
],
),
migrations.CreateModel(
name='Libro',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('titulo', models.CharField(max_length=200)),
('fecha_publicacion', models.PositiveBigIntegerField(default=2024, validators=[django.core.validators.MinValueValidator(1984), libros.models.max_value_current_year])),
('descripcion', models.TextField(blank=True, null=True)),
('archivo', models.FileField(upload_to='libros/')),
('portada', models.ImageField(blank=True, null=True, upload_to='portadas/')),
('autor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='libros.autor')),
],
),
]

+ 0
- 0
libros/migrations/__init__.py View File


+ 32
- 0
libros/models.py View File

@ -0,0 +1,32 @@
from django.db import models
import datetime
from django.core.validators import MaxValueValidator, MinValueValidator
def current_year():
return datetime.date.today().year
def max_value_current_year(value):
return MaxValueValidator(current_year())(value)
class Autor(models.Model):
nombre = models.CharField(max_length=200)
biografia = models.TextField(blank=True, null=True)
foto = models.ImageField(upload_to='autores/', blank=True, null=True) # Nuevo campo
def __str__(self):
return self.nombre
class Libro(models.Model):
titulo = models.CharField(max_length=200)
autor = models.ForeignKey(Autor, on_delete=models.CASCADE)
fecha_publicacion = models.PositiveBigIntegerField(default=current_year(), validators=[MinValueValidator(1984), max_value_current_year])
descripcion = models.TextField(blank=True, null=True)
archivo = models.FileField(upload_to='libros/')
portada = models.ImageField(upload_to='portadas/', blank=True, null=True) # Nuevo campo
def __str__(self):
return self.titulo

+ 3
- 0
libros/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 21
- 0
libros/urls.py View File

@ -0,0 +1,21 @@
from django.urls import path
from . import views
app_name = 'libros'
urlpatterns = [
path('', views.principal, name='principal'),
path('autores/', views.lista_autores, name='lista_autores'),
path('autores/nuevo/', views.nuevo_autor, name='nuevo_autor'),
path('autores/<int:autor_id>/', views.detalle_autor, name='detalle_autor'),
path('autores/<int:autor_id>/editar/', views.editar_autor, name='editar_autor'),
path('autores/<int:autor_id>/eliminar/', views.eliminar_autor, name='eliminar_autor'),
path('libros/', views.lista_libros, name='lista_libros'),
path('libros/nuevo/', views.nuevo_libro, name='nuevo_libro'),
path('libros/<int:libro_id>/', views.detalle_libro, name='detalle_libro'),
path('libros/<int:libro_id>/editar/', views.editar_libro, name='editar_libro'),
path('libros/<int:libro_id>/eliminar/', views.eliminar_libro, name='eliminar_libro'),
]

+ 103
- 0
libros/views.py View File

@ -0,0 +1,103 @@
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from .models import Autor, Libro
from .forms import AutorForm, LibroForm
@login_required
def principal(request):
return render(request, 'libros/index.html')
# Vistas para los autores
@login_required
def lista_autores(request):
autores = Autor.objects.all()
return render(request, 'libros/lista_autores.html', {'autores': autores})
@login_required
def detalle_autor(request, autor_id):
autor = get_object_or_404(Autor, pk=autor_id)
libros = Libro.objects.filter(autor=autor_id)
return render(request, 'libros/detalle_autor.html', {'autor': autor, 'libros': libros})
@login_required
def nuevo_autor(request):
if request.method == 'POST':
form = AutorForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('libros:lista_autores')
else:
form = AutorForm()
return render(request, 'libros/form_autor.html', {'form': form})
@login_required
def editar_autor(request, autor_id):
autor = get_object_or_404(Autor, pk=autor_id)
if request.method == 'POST':
form = AutorForm(request.POST, request.FILES, instance=autor)
if form.is_valid():
form.save()
return redirect('libros:lista_autores')
else:
form = AutorForm(instance=autor)
return render(request, 'libros/form_autor.html', {'form': form})
@login_required
def eliminar_autor(request, autor_id):
autor = get_object_or_404(Autor, pk=autor_id)
autor.delete()
return redirect('libros:lista_autores')
# Vistas para los libros
@login_required
def lista_libros(request):
libros = Libro.objects.all()
return render(request, 'libros/lista_libros.html', {'libros': libros})
@login_required
def detalle_libro(request, libro_id):
libro = get_object_or_404(Libro, pk=libro_id)
return render(request, 'libros/detalle_libro.html', {'libro': libro})
@login_required
def nuevo_libro(request):
if request.method == 'POST':
form = LibroForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('libros:lista_libros')
else:
form = LibroForm()
return render(request, 'libros/form_libro.html', {'form': form})
@login_required
def editar_libro(request, libro_id):
libro = get_object_or_404(Libro, pk=libro_id)
if request.method == 'POST':
form = LibroForm(request.POST, request.FILES, instance=libro)
if form.is_valid():
form.save()
return redirect('libros:lista_libros')
else:
form = LibroForm(instance=libro)
return render(request, 'libros/form_libro.html', {'form': form})
@login_required
def eliminar_libro(request, libro_id):
libro = get_object_or_404(Libro, pk=libro_id)
libro.delete()
return redirect('libros:lista_libros')

+ 0
- 0
lyrics/__init__.py View File


+ 9
- 0
lyrics/admin.py View File

@ -0,0 +1,9 @@
from django.contrib import admin
# Register your models here.
from .models import Artista, Album, Song
admin.site.register(Artista)
admin.site.register(Album)
admin.site.register(Song)

+ 6
- 0
lyrics/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class LyricsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'lyrics'

+ 41
- 0
lyrics/forms.py View File

@ -0,0 +1,41 @@
from django import forms
from .models import Artista, Album, Song
class ArtistaForm(forms.ModelForm):
class Meta:
model = Artista
fields = ['nombre', 'biografia', 'foto']
nombre = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
biografia = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
class AlbumForm(forms.ModelForm):
class Meta:
model = Album
fields = ['name', 'artist', 'year', 'cover_image']
# year = forms.DateField(
# widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}))
artist = forms.ModelChoiceField(
queryset=Artista.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'}))
class SongForm(forms.ModelForm):
class Meta:
model = Song
fields = ['title', 'artist', 'album', 'year', 'lyrics']
artist = forms.ModelChoiceField(
queryset=Artista.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'}))
album = forms.ModelChoiceField(
queryset=Album.objects.all(), # habría que seleccionar los álbumes del artista
widget=forms.Select(attrs={'class': 'form-control'}))

+ 0
- 0
lyrics/management/commands/__init__.py View File


+ 23
- 0
lyrics/management/commands/importa_album.py View File

@ -0,0 +1,23 @@
from django.core.management.base import BaseCommand, CommandError
from lyrics.models import Album, Artista, Song
import csv
import argparse
from datetime import datetime
class Command(BaseCommand):
help = "Importa la lista de letras"
def add_arguments(self, parser):
parser.add_argument("fichero_csv", type=str, help='Ruta al fichero csv')
def handle(self, *args, **options):
fichero = options["fichero_csv"]
with open(fichero, 'r') as file:
reader = csv.DictReader(file)
for row in reader:
name = row['name'],
artist = row['artist'],
year = row['year'],
cover_image = row['cover_image']
print(name, ",", artist, ",", year, ",", cover_image)

+ 23
- 0
lyrics/management/commands/importa_artista.py View File

@ -0,0 +1,23 @@
from django.core.management.base import BaseCommand, CommandError
from lyrics.models import Album, Artista, Song
import csv
import argparse
from datetime import datetime
class Command(BaseCommand):
help = "Importa la lista de letras"
def add_arguments(self, parser):
parser.add_argument("fichero_csv", type=str, help='Ruta al fichero csv')
def handle(self, *args, **options):
fichero = options["fichero_csv"]
with open(fichero, 'r') as file:
reader = csv.DictReader(file)
for row in reader:
name = row['name'],
artist = row['artist'],
year = row['year'],
cover_image = row['cover_image']
print(name, ",", artist, ",", year, ",", cover_image)

+ 26
- 0
lyrics/management/commands/importa_song.py View File

@ -0,0 +1,26 @@
from django.core.management.base import BaseCommand, CommandError
from lyrics.models import Album, Artista, Song
import csv
import argparse
from datetime import datetime
import pandas as pd
class Command(BaseCommand):
help = "Importa la lista de letras"
def add_arguments(self, parser):
parser.add_argument("fichero_csv", type=str, help='Ruta al fichero csv')
def handle(self, *args, **options):
fichero = options["fichero_csv"]
contenido = pd.read_csv(fichero)
for fila in contenido.iterrows():
print(fila[1].title, ", ", fila[1].artist, ", ", fila[1].album)
artista = Artista.objects.get(nombre=fila[1].artist)
album = Album.objects.get(pk=fila[1].album)
cancion = Song(title=fila[1].title, artist=artista, album=album, pista=fila[1].pista, lyrics=fila[1].lyrics)
cancion.save()

+ 52
- 0
lyrics/migrations/0001_initial.py View File

@ -0,0 +1,52 @@
# Generated by Django 4.2 on 2024-09-10 13:23
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion
import lyrics.models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Album',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('year', models.PositiveBigIntegerField(default=2024, validators=[django.core.validators.MinValueValidator(1984), lyrics.models.max_value_current_year])),
('cover_image', models.ImageField(blank=True, null=True, upload_to='cover_image/')),
],
),
migrations.CreateModel(
name='Artista',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nombre', models.CharField(max_length=200)),
('biografia', models.TextField(blank=True, null=True)),
('foto', models.ImageField(blank=True, null=True, upload_to='artistas/')),
],
),
migrations.CreateModel(
name='Song',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=200)),
('year', models.PositiveBigIntegerField(default=2024, validators=[django.core.validators.MinValueValidator(1984), lyrics.models.max_value_current_year])),
('lyrics', models.CharField(max_length=1000)),
('pista', models.DecimalField(blank=True, decimal_places=0, max_digits=5, null=True)),
('album', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lyrics.album')),
('artist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lyrics.artista')),
],
),
migrations.AddField(
model_name='album',
name='artist',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='lyrics.artista'),
),
]

+ 0
- 0
lyrics/migrations/__init__.py View File


+ 42
- 0
lyrics/models.py View File

@ -0,0 +1,42 @@
from django.db import models
import datetime
from django.core.validators import MaxValueValidator, MinValueValidator
def current_year():
return datetime.date.today().year
def max_value_current_year(value):
return MaxValueValidator(current_year())(value)
class Artista(models.Model):
nombre = models.CharField(max_length=200)
biografia = models.TextField(blank=True, null=True)
foto = models.ImageField(upload_to='artistas/', blank=True, null=True) # Nuevo campo
def __str__(self):
return self.nombre
class Album(models.Model):
name = models.CharField(max_length=200)
artist = models.ForeignKey(Artista, on_delete=models.CASCADE)
year = models.PositiveBigIntegerField(default=current_year(), validators=[MinValueValidator(1945), max_value_current_year])
cover_image = models.ImageField(upload_to='cover_image/', blank=True, null=True) # Nuevo campo
def __str__(self):
return self.name
class Song(models.Model):
title = models.CharField(max_length=200)
artist = models.ForeignKey(Artista, on_delete=models.CASCADE)
album = models.ForeignKey(Album, on_delete=models.CASCADE, related_name='song')
year = models.DecimalField(max_digits=4, decimal_places=0, blank=False, null=False)
lyrics = models.TextField()
pista = models.DecimalField(max_digits=5, decimal_places=0, blank=True, null=True)
def __str__(self):
return self.title

+ 3
- 0
lyrics/tests.py View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

+ 27
- 0
lyrics/urls.py View File

@ -0,0 +1,27 @@
from django.urls import path
from . import views
app_name = 'lyrics'
urlpatterns = [
path('', views.principal, name='principal'),
path('artistas/', views.lista_artistas, name='lista_artistas'),
path('artistas/nuevo/', views.nuevo_artista, name='nuevo_artista'),
path('artistas/<int:artista_id>/', views.detalle_artista, name='detalle_artista'),
path('artistas/<int:artista_id>/editar/', views.editar_artista, name='editar_artista'),
path('artistas/<int:artista_id>/eliminar/', views.eliminar_artista, name='eliminar_artista'),
path('album/', views.lista_albumes, name='lista_albumes'),
path('album/nuevo/', views.nuevo_album, name='nuevo_album'),
path('album/<int:album_id>/', views.detalle_album, name='detalle_album'),
path('album/<int:album_id>/editar/', views.editar_album, name='editar_album'),
path('album/<int:album_id>/eliminar/', views.eliminar_album, name='eliminar_album'),
path('song/', views.lista_songs, name='lista_songs'),
path('song/nuevo/', views.nuevo_song, name='nuevo_song'),
path('song/<int:song_id>/', views.detalle_song, name='detalle_song'),
path('song/<int:song_id>/editar/', views.editar_song, name='editar_song'),
path('song/<int:song_id>/eliminar/', views.eliminar_song, name='eliminar_song'),
]

+ 190
- 0
lyrics/views.py View File

@ -0,0 +1,190 @@
# Create your views here.
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from .models import Artista, Album, Song
from .forms import ArtistaForm, AlbumForm, SongForm
import logging
logger = logging.getLogger(__name__)
@login_required
def principal(request):
artistas = Artista.objects.all()
albumes = Album.objects.all()
return render(request, 'lyrics/index.html', {'artistas': artistas, 'albumes': albumes})
#########################
# Vistas para los artistas
@login_required
def lista_artistas(request):
artistas = Artista.objects.all()
return render(request, 'lyrics/lista_artistas.html', {'artistas': artistas})
@login_required
def detalle_artista(request, artista_id):
artista = get_object_or_404(Artista, pk=artista_id)
albumes = Album.objects.filter(artist=artista_id)
return render(request, 'lyrics/detalle_artista.html', {'artista': artista, 'albumes': albumes})
@login_required
def nuevo_artista(request):
if request.method == 'POST':
form = ArtistaForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('lyrics:lista_artistas')
else:
form = ArtistaForm()
return render(request, 'lyrics/form_artista.html', {'form': form})
@login_required
def editar_artista(request, artista_id):
artista = get_object_or_404(Artista, pk=artista_id)
if request.method == 'POST':
form = ArtistaForm(request.POST, request.FILES, instance=artista)
if form.is_valid():
form.save()
return redirect('lyrics:lista_artistas')
else:
form = ArtistaForm(instance=artista)
return render(request, 'lyrics/form_artista.html', {'form': form})
@login_required
def eliminar_artista(request, artista_id):
artista = get_object_or_404(Artista, pk=artista_id)
artista.delete()
return redirect('lyrics:lista_artistas')
#########################
# Vistas para los albumes
@login_required
def lista_albumes(request):
albumes = Album.objects.all()
return render(request, 'lyrics/lista_albumes.html', {'albumes': albumes})
@login_required
def detalle_album(request, album_id):
album = get_object_or_404(Album, pk=album_id)
songs = Song.objects.filter(album_id=album_id)
return render(request, 'lyrics/detalle_album.html', {'album': album, 'songs': songs})
@login_required
def nuevo_album(request):
artistas = Artista.objects.all() # vamos a ver si hay vehículos dados de alta
if artistas:
if request.method == 'POST':
form = AlbumForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('lyrics:lista_albumes')
else:
form = AlbumForm()
return render(request, 'lyrics/form_album.html', {'form': form})
else:
return render(request, 'lyrics/index.html')
@login_required
def editar_album(request, album_id):
album = get_object_or_404(Album, pk=album_id)
if request.method == 'POST':
form = AlbumForm(request.POST, request.FILES, instance=album)
if form.is_valid():
form.save()
return redirect('lyrics:lista_albumes')
else:
form = AlbumForm(instance=album)
return render(request, 'lyrics/form_album.html', {'form': form})
@login_required
def eliminar_album(request, album_id):
album = Album.objects.get(pk=album_id)
album.delete()
return redirect('lyrics:lista_albumes')
#########################
# Vistas para los songs
@login_required
def lista_songs(request):
songs = Song.objects.all()
return render(request, 'lyrics/lista_songs.html', {'songs': songs})
@login_required
def detalle_song(request, song_id):
song = get_object_or_404(Song, pk=song_id)
albumes = Album.objects.filter(song=song_id)
return render(request, 'lyrics/detalle_song.html', {'song': song, 'albumes': albumes})
@login_required
def nuevo_song(request):
album_id = request.GET.get('album_id') # Obtener el album_id de los parámetros de la URL
if request.method == 'POST':
form = SongForm(request.POST, request.FILES)
if form.is_valid():
album = form.cleaned_data['album']
song_count = album.song.count()
nueva_cancion = form.save(commit=False)
nueva_cancion.pista = song_count + 1
nueva_cancion.save()
logger.info("Canción creada %s", nueva_cancion.title)
return redirect('lyrics:lista_songs')
else:
if album_id:
# Si tenemos un album_id, preseleccionamos ese álbum en el formulario
album = get_object_or_404(Album, id=album_id)
form = SongForm(initial={'album': album, 'artist': album.artist, 'year': album.year})
else:
form = SongForm()
return render(request, 'lyrics/form_song.html', {'form': form})
@login_required
def editar_song(request, song_id):
song = get_object_or_404(Song, pk=song_id)
if request.method == 'POST':
form = SongForm(request.POST, request.FILES, instance=song)
if form.is_valid():
form.save()
return redirect('lyrics:lista_songs')
else:
form = SongForm(instance=song)
return render(request, 'lyrics/form_song.html', {'form': form})
@login_required
def eliminar_song(request, song_id):
song = get_object_or_404(Song, pk=song_id)
song.delete()
return redirect('lyrics:lista_songs')

+ 22
- 0
manage.py View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'reymota.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()

BIN
mediafiles/profile_images/default.jpg View File

Before After
Width: 826  |  Height: 826  |  Size: 20 KiB

BIN
mediafiles/profile_images/gravatar-tino.jpeg View File

Before After
Width: 256  |  Height: 256  |  Size: 29 KiB

BIN
mediafiles/profile_images/gravatar-tino_jqB0Vq4.jpeg View File

Before After
Width: 256  |  Height: 256  |  Size: 29 KiB

BIN
mediafiles/vehiculos/bmw.jpg View File

Before After
Width: 500  |  Height: 500  |  Size: 18 KiB

BIN
mediafiles/vehiculos/bmw.png View File

Before After
Width: 360  |  Height: 225  |  Size: 9.5 KiB

BIN
mediafiles/vehiculos/bmw_PMjCK7Q.png View File

Before After
Width: 360  |  Height: 225  |  Size: 9.5 KiB

BIN
mediafiles/vehiculos/bmw_cSbhRuf.png View File

Before After
Width: 360  |  Height: 225  |  Size: 9.5 KiB

BIN
mediafiles/vehiculos/bmw_x00n9W7.png View File

Before After
Width: 360  |  Height: 225  |  Size: 9.5 KiB

BIN
mediafiles/vehiculos/bmw_yVyuq4g.jpg View File

Before After
Width: 500  |  Height: 500  |  Size: 18 KiB

+ 1
- 0
repostajes/.gitignore View File

@ -0,0 +1 @@
migrations/

+ 0
- 0
repostajes/__init__.py View File


+ 9
- 0
repostajes/admin.py View File

@ -0,0 +1,9 @@
from django.contrib import admin
# Register your models here.
from .models import Vehiculo, Repostaje
admin.site.register(Vehiculo)
admin.site.register(Repostaje)

+ 6
- 0
repostajes/apps.py View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class RepostajesConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'repostajes'

+ 41
- 0
repostajes/forms.py View File

@ -0,0 +1,41 @@
from django import forms
from .models import Vehiculo, Repostaje
class VehiculoForm(forms.ModelForm):
class Meta:
model = Vehiculo
fields = ['marca', 'modelo', 'matricula', 'foto']
marca = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
modelo = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
matricula = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
class RepostajeForm(forms.ModelForm):
class Meta:
model = Repostaje
fields = ['fecha', 'vehiculo', 'kms', 'litros', 'importe']
exclude = ['descuento', 'precioxlitro']
fecha = forms.DateField(
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}))
vehiculo = forms.ModelChoiceField(
queryset=Vehiculo.objects.all(),
widget=forms.Select(attrs={'class': 'form-control'}))
kms = forms.DecimalField(
widget=forms.TextInput(attrs={'class': 'form-control'}))
litros = forms.DecimalField(
widget=forms.NumberInput(attrs={'class': 'form-control'}))
importe = forms.DecimalField(
widget=forms.NumberInput(attrs={'class': 'form-control'}))
aplica_descuento = forms.BooleanField(initial=False, required=False)

+ 27
- 0
repostajes/models.py View File

@ -0,0 +1,27 @@
from django.db import models
from django.core.validators import MaxValueValidator
class Vehiculo(models.Model):
marca = models.CharField(max_length=200)
modelo = models.CharField(max_length=200)
matricula = models.CharField(max_length=200)
foto = models.ImageField(upload_to='vehiculos/', blank=True, null=True) # Nuevo campo
def __str__(self):
return self.marca
class Repostaje(models.Model):
vehiculo = models.ForeignKey(Vehiculo, on_delete=models.CASCADE)
fecha = models.DateField()
kms = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)
litros = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
descuento = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
importe = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
precioxlitro = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
kmsrecorridos = models.DecimalField(max_digits=10, decimal_places=0, blank=True, null=True)
consumo = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True)
def __str__(self):
return str(self.fecha)

+ 12
- 0
repostajes/static/css/portal.css
File diff suppressed because it is too large
View File


+ 21
- 0
repostajes/static/images/app-logo.svg View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="215px" height="215px" viewBox="0 0 215 215" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<title>portal-logo</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M51.165,8.742 C54.505,12.619 56.876,17.365 57.892,22.588 C60.148,17.225 65.452,13.46 71.636,13.46 C79.867,13.46 86.541,20.134 86.541,28.365 C86.541,36.597 79.867,43.269 71.636,43.269 C63.404,43.269 56.728,36.597 56.728,28.365 C56.728,12.7 44.03,0 28.365,0 C12.7,0 0,12.7 0,28.365 C0,44.031 12.7,56.731 28.365,56.731 C36.419,56.731 43.695,53.393 48.858,48.003 C45.501,44.117 43.128,39.383 42.108,34.14 C39.852,39.504 34.548,43.269 28.365,43.269 C20.133,43.269 13.46,36.597 13.46,28.365 C13.46,20.134 20.133,13.46 28.365,13.46 C36.966,13.46 43.27,20.577 43.27,28.365 C43.27,44.031 55.97,56.731 71.636,56.731 C87.3,56.731 100,44.031 100,28.365 C100,12.7 87.3,0 71.636,0 C63.589,0 56.327,3.358 51.165,8.742 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="portal-logo">
<circle id="Oval" fill="#51B37F" fill-rule="nonzero" cx="107.5" cy="107.5" r="107.5"></circle>
<g id="logo" transform="translate(58.000000, 79.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<polygon id="Fill-1" fill="#FFFFFE" mask="url(#mask-2)" points="-5 61.73 105 61.73 105 -5 -5 -5"></polygon>
</g>
</g>
</g>
</svg>

BIN
repostajes/static/images/background/background-1.jpg View File

Before After
Width: 1000  |  Height: 1139  |  Size: 150 KiB

BIN
repostajes/static/images/background/background-2.jpg View File

Before After
Width: 1200  |  Height: 781  |  Size: 232 KiB

BIN
repostajes/static/images/background/background-3.jpg View File

Before After
Width: 1200  |  Height: 789  |  Size: 256 KiB

BIN
repostajes/static/images/background/background-palmeras.jpg View File

Before After
Width: 1000  |  Height: 1139  |  Size: 360 KiB

BIN
repostajes/static/images/doc-thumb-1.jpg View File

Before After
Width: 600  |  Height: 432  |  Size: 75 KiB

BIN
repostajes/static/images/doc-thumb-2.jpg View File

Before After
Width: 600  |  Height: 472  |  Size: 75 KiB

BIN
repostajes/static/images/favicon.ico View File

Before After

BIN
repostajes/static/images/favicon.png View File

Before After
Width: 32  |  Height: 32  |  Size: 1.7 KiB

+ 21
- 0
repostajes/static/images/portal-logo.svg View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="215px" height="215px" viewBox="0 0 215 215" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.6 (67491) - http://www.bohemiancoding.com/sketch -->
<title>portal-logo</title>
<desc>Created with Sketch.</desc>
<defs>
<path d="M51.165,8.742 C54.505,12.619 56.876,17.365 57.892,22.588 C60.148,17.225 65.452,13.46 71.636,13.46 C79.867,13.46 86.541,20.134 86.541,28.365 C86.541,36.597 79.867,43.269 71.636,43.269 C63.404,43.269 56.728,36.597 56.728,28.365 C56.728,12.7 44.03,0 28.365,0 C12.7,0 0,12.7 0,28.365 C0,44.031 12.7,56.731 28.365,56.731 C36.419,56.731 43.695,53.393 48.858,48.003 C45.501,44.117 43.128,39.383 42.108,34.14 C39.852,39.504 34.548,43.269 28.365,43.269 C20.133,43.269 13.46,36.597 13.46,28.365 C13.46,20.134 20.133,13.46 28.365,13.46 C36.966,13.46 43.27,20.577 43.27,28.365 C43.27,44.031 55.97,56.731 71.636,56.731 C87.3,56.731 100,44.031 100,28.365 C100,12.7 87.3,0 71.636,0 C63.589,0 56.327,3.358 51.165,8.742 Z" id="path-1"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="portal-logo">
<circle id="Oval" fill="#09B6CA" fill-rule="nonzero" cx="107.5" cy="107.5" r="107.5"></circle>
<g id="logo" transform="translate(58.000000, 79.000000)">
<mask id="mask-2" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="Clip-2"></g>
<polygon id="Fill-1" fill="#FFFFFE" mask="url(#mask-2)" points="-5 61.73 105 61.73 105 -5 -5 -5"></polygon>
</g>
</g>
</g>
</svg>

BIN
repostajes/static/images/profiles/profile-1.png View File

Before After
Width: 120  |  Height: 120  |  Size: 34 KiB

BIN
repostajes/static/images/profiles/profile-2.png View File

Before After
Width: 120  |  Height: 120  |  Size: 35 KiB

BIN
repostajes/static/images/profiles/profile-3.png View File

Before After
Width: 120  |  Height: 120  |  Size: 37 KiB

BIN
repostajes/static/images/profiles/profile-4.png View File

Before After
Width: 120  |  Height: 120  |  Size: 22 KiB

BIN
repostajes/static/images/profiles/profile-5.png View File

Before After
Width: 120  |  Height: 120  |  Size: 36 KiB

BIN
repostajes/static/images/profiles/profile-6.png View File

Before After
Width: 120  |  Height: 120  |  Size: 29 KiB

+ 18
- 0
repostajes/static/images/reymota-logo.svg View File

@ -0,0 +1,18 @@
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<!-- Fondo -->
<rect width="400" height="400" fill="#ffffff" />
<!-- Corona -->
<g transform="translate(100, 100) scale(2)">
<polygon points="50,150 75,50 100,150" fill="#FFD700" />
<polygon points="0,150 50,0 100,150" fill="#FFD700" />
<polygon points="100,150 125,50 150,150" fill="#FFD700" />
</g>
<!-- Letra R -->
<!--
<text x="100" y="360" font-family="Arial, sans-serif" font-size="400" fill="#000000" font-weight="bold">R</text>
-->
<text x="100" y="360" font-family="Open Sans" font-size="400" fill="#000000" font-weight="bold">R</text>
</svg>

BIN
repostajes/static/images/user.png View File

Before After
Width: 120  |  Height: 120  |  Size: 38 KiB

BIN
repostajes/static/images/users/user-1.jpg View File

Before After
Width: 200  |  Height: 200  |  Size: 48 KiB

BIN
repostajes/static/images/users/user-2.jpg View File

Before After
Width: 350  |  Height: 350  |  Size: 28 KiB

BIN
repostajes/static/images/users/user-3.jpg View File

Before After
Width: 200  |  Height: 200  |  Size: 40 KiB

BIN
repostajes/static/images/users/user-4.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 7.2 KiB

BIN
repostajes/static/images/users/user-5.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 22 KiB

BIN
repostajes/static/images/users/user-6.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 9.1 KiB

BIN
repostajes/static/images/users/user-7.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 22 KiB

BIN
repostajes/static/images/users/user-8.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 12 KiB

BIN
repostajes/static/images/users/user-9.jpg View File

Before After
Width: 240  |  Height: 240  |  Size: 32 KiB

+ 96
- 0
repostajes/static/js/app.js View File

@ -0,0 +1,96 @@
'use strict';
/* ===== Enable Bootstrap Popover (on element ====== */
const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]')
const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
/* ==== Enable Bootstrap Alert ====== */
//var alertList = document.querySelectorAll('.alert')
//alertList.forEach(function (alert) {
// new bootstrap.Alert(alert)
//});
const alertList = document.querySelectorAll('.alert')
const alerts = [...alertList].map(element => new bootstrap.Alert(element))
/* ===== Responsive Sidepanel ====== */
const sidePanelToggler = document.getElementById('sidepanel-toggler');
const sidePanel = document.getElementById('app-sidepanel');
const sidePanelDrop = document.getElementById('sidepanel-drop');
const sidePanelClose = document.getElementById('sidepanel-close');
window.addEventListener('load', function(){
responsiveSidePanel();
});
window.addEventListener('resize', function(){
responsiveSidePanel();
});
function responsiveSidePanel() {
let w = window.innerWidth;
if(w >= 1200) {
// if larger
//console.log('larger');
sidePanel.classList.remove('sidepanel-hidden');
sidePanel.classList.add('sidepanel-visible');
} else {
// if smaller
//console.log('smaller');
sidePanel.classList.remove('sidepanel-visible');
sidePanel.classList.add('sidepanel-hidden');
}
};
sidePanelToggler.addEventListener('click', () => {
if (sidePanel.classList.contains('sidepanel-visible')) {
console.log('visible');
sidePanel.classList.remove('sidepanel-visible');
sidePanel.classList.add('sidepanel-hidden');
} else {
console.log('hidden');
sidePanel.classList.remove('sidepanel-hidden');
sidePanel.classList.add('sidepanel-visible');
}
});
sidePanelClose.addEventListener('click', (e) => {
e.preventDefault();
sidePanelToggler.click();
});
sidePanelDrop.addEventListener('click', (e) => {
sidePanelToggler.click();
});
/* ====== Mobile search ======= */
const searchMobileTrigger = document.querySelector('.search-mobile-trigger');
const searchBox = document.querySelector('.app-search-box');
searchMobileTrigger.addEventListener('click', () => {
searchBox.classList.toggle('is-visible');
let searchMobileTriggerIcon = document.querySelector('.search-mobile-trigger-icon');
if(searchMobileTriggerIcon.classList.contains('fa-magnifying-glass')) {
searchMobileTriggerIcon.classList.remove('fa-magnifying-glass');
searchMobileTriggerIcon.classList.add('fa-xmark');
} else {
searchMobileTriggerIcon.classList.remove('fa-xmark');
searchMobileTriggerIcon.classList.add('fa-magnifying-glass');
}
});

+ 366
- 0
repostajes/static/js/charts-demo.js View File

@ -0,0 +1,366 @@
'use strict';
/* Chart.js docs: https://www.chartjs.org/ */
window.chartColors = {
green: '#75c181', // rgba(117,193,129, 1)
blue: '#5b99ea', // rgba(91,153,234, 1)
gray: '#a9b5c9',
text: '#252930',
border: '#e7e9ed'
};
/* Random number generator for demo purpose */
var randomDataPoint = function(){ return Math.round(Math.random()*100)};
//Area line Chart Demo
var lineChartConfig = {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
datasets: [{
label: 'Dataset',
backgroundColor: "rgba(117,193,129,0.2)",
borderColor: "rgba(117,193,129, 0.8)",
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
],
}]
},
options: {
responsive: true,
legend: {
display: true,
position: 'bottom',
align: 'end',
},
tooltips: {
mode: 'index',
intersect: false,
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
callbacks: {
label: function(tooltipItem, data) {
return tooltipItem.value + '%';
}
},
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
scaleLabel: {
display: false,
}
}],
yAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
scaleLabel: {
display: false,
},
ticks: {
beginAtZero: true,
userCallback: function(value, index, values) {
return value.toLocaleString() + '%';
}
},
}]
}
}
};
//Bar Chart Demo
var barChartConfig = {
type: 'bar',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul'],
datasets: [{
label: 'Dataset 1',
backgroundColor: "rgba(117,193,129,0.8)",
hoverBackgroundColor: "rgba(117,193,129,1)",
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
]
},
{
label: 'Dataset 2',
backgroundColor: "rgba(91,153,234,0.8)",
hoverBackgroundColor: "rgba(91,153,234,1)",
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
]
}
]
},
options: {
responsive: true,
legend: {
position: 'bottom',
align: 'end',
},
tooltips: {
mode: 'index',
intersect: false,
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
callbacks: {
label: function(tooltipItem, data) {
return tooltipItem.value + '%';
}
},
},
scales: {
xAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
}],
yAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.borders,
},
ticks: {
beginAtZero: true,
userCallback: function(value, index, values) {
return value + '%';
}
},
}]
}
}
}
// Pie Chart Demo
var pieChartConfig = {
type: 'pie',
data: {
datasets: [{
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
],
backgroundColor: [
window.chartColors.green,
window.chartColors.blue,
window.chartColors.gray,
],
label: 'Dataset 1'
}],
labels: [
'Green',
'Blue',
'Gray',
]
},
options: {
responsive: true,
legend: {
display: true,
position: 'bottom',
align: 'center',
},
tooltips: {
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
/* Display % in tooltip - https://stackoverflow.com/questions/37257034/chart-js-2-0-doughnut-tooltip-percentages */
callbacks: {
label: function(tooltipItem, data) {
//get the concerned dataset
var dataset = data.datasets[tooltipItem.datasetIndex];
//calculate the total of this data set
var total = dataset.data.reduce(function(previousValue, currentValue, currentIndex, array) {
return previousValue + currentValue;
});
//get the current items value
var currentValue = dataset.data[tooltipItem.index];
//calculate the precentage based on the total and current item, also this does a rough rounding to give a whole number
var percentage = Math.floor(((currentValue/total) * 100)+0.5);
return percentage + "%";
},
},
},
}
};
// Doughnut Chart Demo
var doughnutChartConfig = {
type: 'doughnut',
data: {
datasets: [{
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
],
backgroundColor: [
window.chartColors.green,
window.chartColors.blue,
window.chartColors.gray,
],
label: 'Dataset 1'
}],
labels: [
'Green',
'Blue',
'Gray',
]
},
options: {
responsive: true,
legend: {
display: true,
position: 'bottom',
align: 'center',
},
tooltips: {
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
animation: {
animateScale: true,
animateRotate: true
},
/* Display % in tooltip - https://stackoverflow.com/questions/37257034/chart-js-2-0-doughnut-tooltip-percentages */
callbacks: {
label: function(tooltipItem, data) {
//get the concerned dataset
var dataset = data.datasets[tooltipItem.datasetIndex];
//calculate the total of this data set
var total = dataset.data.reduce(function(previousValue, currentValue, currentIndex, array) {
return previousValue + currentValue;
});
//get the current items value
var currentValue = dataset.data[tooltipItem.index];
//calculate the precentage based on the total and current item, also this does a rough rounding to give a whole number
var percentage = Math.floor(((currentValue/total) * 100)+0.5);
return percentage + "%";
},
},
},
}
};
// Generate charts on load
window.addEventListener('load', function(){
var lineChart = document.getElementById('chart-line').getContext('2d');
window.myLine = new Chart(lineChart, lineChartConfig);
var barChart = document.getElementById('chart-bar').getContext('2d');
window.myBar = new Chart(barChart, barChartConfig);
var pieChart = document.getElementById('chart-pie').getContext('2d');
window.myPie = new Chart(pieChart, pieChartConfig);
var doughnutChart = document.getElementById('chart-doughnut').getContext('2d');
window.myDoughnut = new Chart(doughnutChart, doughnutChartConfig);
});

+ 224
- 0
repostajes/static/js/index-charts.js View File

@ -0,0 +1,224 @@
'use strict';
/* Chart.js docs: https://www.chartjs.org/ */
window.chartColors = {
green: '#75c181',
gray: '#a9b5c9',
text: '#252930',
border: '#e7e9ed'
};
/* Random number generator for demo purpose */
var randomDataPoint = function(){ return Math.round(Math.random()*10000)};
//Chart.js Line Chart Example
var lineChartConfig = {
type: 'line',
data: {
labels: ['Day 1', 'Day 2', 'Day 3', 'Day 4', 'Day 5', 'Day 6', 'Day 7'],
datasets: [{
label: 'Current week',
fill: false,
backgroundColor: window.chartColors.green,
borderColor: window.chartColors.green,
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
],
}, {
label: 'Previous week',
borderDash: [3, 5],
backgroundColor: window.chartColors.gray,
borderColor: window.chartColors.gray,
data: [
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint(),
randomDataPoint()
],
fill: false,
}]
},
options: {
responsive: true,
aspectRatio: 1.5,
legend: {
display: true,
position: 'bottom',
align: 'end',
},
title: {
display: true,
text: 'Chart.js Line Chart Example',
},
tooltips: {
mode: 'index',
intersect: false,
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
callbacks: {
//Ref: https://stackoverflow.com/questions/38800226/chart-js-add-commas-to-tooltip-and-y-axis
label: function(tooltipItem, data) {
if (parseInt(tooltipItem.value) >= 1000) {
return "$" + tooltipItem.value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
} else {
return '$' + tooltipItem.value;
}
}
},
},
hover: {
mode: 'nearest',
intersect: true
},
scales: {
xAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
scaleLabel: {
display: false,
}
}],
yAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
scaleLabel: {
display: false,
},
ticks: {
beginAtZero: true,
userCallback: function(value, index, values) {
return '$' + value.toLocaleString(); //Ref: https://stackoverflow.com/questions/38800226/chart-js-add-commas-to-tooltip-and-y-axis
}
},
}]
}
}
};
// Chart.js Bar Chart Example
var barChartConfig = {
type: 'bar',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [{
label: 'Orders',
backgroundColor: window.chartColors.green,
borderColor: window.chartColors.green,
borderWidth: 1,
maxBarThickness: 16,
data: [
23,
45,
76,
75,
62,
37,
83
]
}]
},
options: {
responsive: true,
aspectRatio: 1.5,
legend: {
position: 'bottom',
align: 'end',
},
title: {
display: true,
text: 'Chart.js Bar Chart Example'
},
tooltips: {
mode: 'index',
intersect: false,
titleMarginBottom: 10,
bodySpacing: 10,
xPadding: 16,
yPadding: 16,
borderColor: window.chartColors.border,
borderWidth: 1,
backgroundColor: '#fff',
bodyFontColor: window.chartColors.text,
titleFontColor: window.chartColors.text,
},
scales: {
xAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.border,
},
}],
yAxes: [{
display: true,
gridLines: {
drawBorder: false,
color: window.chartColors.borders,
},
}]
}
}
}
// Generate charts on load
window.addEventListener('load', function(){
var lineChart = document.getElementById('canvas-linechart').getContext('2d');
window.myLine = new Chart(lineChart, lineChartConfig);
var barChart = document.getElementById('canvas-barchart').getContext('2d');
window.myBar = new Chart(barChart, barChartConfig);
});

+ 4085
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-grid.css
File diff suppressed because it is too large
View File


+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-grid.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-grid.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-grid.min.css.map
File diff suppressed because it is too large
View File


+ 4084
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-grid.rtl.css
File diff suppressed because it is too large
View File


+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-grid.rtl.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-grid.rtl.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-grid.rtl.min.css.map
File diff suppressed because it is too large
View File


+ 593
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-reboot.css View File

@ -0,0 +1,593 @@
/*!
* Bootstrap Reboot v5.3.0 (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #adb5bd;
--bs-body-color-rgb: 173, 181, 189;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(173, 181, 189, 0.75);
--bs-secondary-color-rgb: 173, 181, 189;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(173, 181, 189, 0.5);
--bs-tertiary-color-rgb: 173, 181, 189;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-left: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-left: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: left;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: left;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: left;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.css.map */

+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-reboot.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-reboot.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-reboot.min.css.map
File diff suppressed because it is too large
View File


+ 590
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-reboot.rtl.css View File

@ -0,0 +1,590 @@
/*!
* Bootstrap Reboot v5.3.0 (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
:root,
[data-bs-theme=light] {
--bs-blue: #0d6efd;
--bs-indigo: #6610f2;
--bs-purple: #6f42c1;
--bs-pink: #d63384;
--bs-red: #dc3545;
--bs-orange: #fd7e14;
--bs-yellow: #ffc107;
--bs-green: #198754;
--bs-teal: #20c997;
--bs-cyan: #0dcaf0;
--bs-black: #000;
--bs-white: #fff;
--bs-gray: #6c757d;
--bs-gray-dark: #343a40;
--bs-gray-100: #f8f9fa;
--bs-gray-200: #e9ecef;
--bs-gray-300: #dee2e6;
--bs-gray-400: #ced4da;
--bs-gray-500: #adb5bd;
--bs-gray-600: #6c757d;
--bs-gray-700: #495057;
--bs-gray-800: #343a40;
--bs-gray-900: #212529;
--bs-primary: #0d6efd;
--bs-secondary: #6c757d;
--bs-success: #198754;
--bs-info: #0dcaf0;
--bs-warning: #ffc107;
--bs-danger: #dc3545;
--bs-light: #f8f9fa;
--bs-dark: #212529;
--bs-primary-rgb: 13, 110, 253;
--bs-secondary-rgb: 108, 117, 125;
--bs-success-rgb: 25, 135, 84;
--bs-info-rgb: 13, 202, 240;
--bs-warning-rgb: 255, 193, 7;
--bs-danger-rgb: 220, 53, 69;
--bs-light-rgb: 248, 249, 250;
--bs-dark-rgb: 33, 37, 41;
--bs-primary-text-emphasis: #052c65;
--bs-secondary-text-emphasis: #2b2f32;
--bs-success-text-emphasis: #0a3622;
--bs-info-text-emphasis: #055160;
--bs-warning-text-emphasis: #664d03;
--bs-danger-text-emphasis: #58151c;
--bs-light-text-emphasis: #495057;
--bs-dark-text-emphasis: #495057;
--bs-primary-bg-subtle: #cfe2ff;
--bs-secondary-bg-subtle: #e2e3e5;
--bs-success-bg-subtle: #d1e7dd;
--bs-info-bg-subtle: #cff4fc;
--bs-warning-bg-subtle: #fff3cd;
--bs-danger-bg-subtle: #f8d7da;
--bs-light-bg-subtle: #fcfcfd;
--bs-dark-bg-subtle: #ced4da;
--bs-primary-border-subtle: #9ec5fe;
--bs-secondary-border-subtle: #c4c8cb;
--bs-success-border-subtle: #a3cfbb;
--bs-info-border-subtle: #9eeaf9;
--bs-warning-border-subtle: #ffe69c;
--bs-danger-border-subtle: #f1aeb5;
--bs-light-border-subtle: #e9ecef;
--bs-dark-border-subtle: #adb5bd;
--bs-white-rgb: 255, 255, 255;
--bs-black-rgb: 0, 0, 0;
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
--bs-body-font-family: var(--bs-font-sans-serif);
--bs-body-font-size: 1rem;
--bs-body-font-weight: 400;
--bs-body-line-height: 1.5;
--bs-body-color: #212529;
--bs-body-color-rgb: 33, 37, 41;
--bs-body-bg: #fff;
--bs-body-bg-rgb: 255, 255, 255;
--bs-emphasis-color: #000;
--bs-emphasis-color-rgb: 0, 0, 0;
--bs-secondary-color: rgba(33, 37, 41, 0.75);
--bs-secondary-color-rgb: 33, 37, 41;
--bs-secondary-bg: #e9ecef;
--bs-secondary-bg-rgb: 233, 236, 239;
--bs-tertiary-color: rgba(33, 37, 41, 0.5);
--bs-tertiary-color-rgb: 33, 37, 41;
--bs-tertiary-bg: #f8f9fa;
--bs-tertiary-bg-rgb: 248, 249, 250;
--bs-heading-color: inherit;
--bs-link-color: #0d6efd;
--bs-link-color-rgb: 13, 110, 253;
--bs-link-decoration: underline;
--bs-link-hover-color: #0a58ca;
--bs-link-hover-color-rgb: 10, 88, 202;
--bs-code-color: #d63384;
--bs-highlight-bg: #fff3cd;
--bs-border-width: 1px;
--bs-border-style: solid;
--bs-border-color: #dee2e6;
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
--bs-border-radius: 0.375rem;
--bs-border-radius-sm: 0.25rem;
--bs-border-radius-lg: 0.5rem;
--bs-border-radius-xl: 1rem;
--bs-border-radius-xxl: 2rem;
--bs-border-radius-2xl: var(--bs-border-radius-xxl);
--bs-border-radius-pill: 50rem;
--bs-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
--bs-box-shadow-sm: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
--bs-box-shadow-lg: 0 1rem 3rem rgba(0, 0, 0, 0.175);
--bs-box-shadow-inset: inset 0 1px 2px rgba(0, 0, 0, 0.075);
--bs-focus-ring-width: 0.25rem;
--bs-focus-ring-opacity: 0.25;
--bs-focus-ring-color: rgba(13, 110, 253, 0.25);
--bs-form-valid-color: #198754;
--bs-form-valid-border-color: #198754;
--bs-form-invalid-color: #dc3545;
--bs-form-invalid-border-color: #dc3545;
}
[data-bs-theme=dark] {
color-scheme: dark;
--bs-body-color: #adb5bd;
--bs-body-color-rgb: 173, 181, 189;
--bs-body-bg: #212529;
--bs-body-bg-rgb: 33, 37, 41;
--bs-emphasis-color: #fff;
--bs-emphasis-color-rgb: 255, 255, 255;
--bs-secondary-color: rgba(173, 181, 189, 0.75);
--bs-secondary-color-rgb: 173, 181, 189;
--bs-secondary-bg: #343a40;
--bs-secondary-bg-rgb: 52, 58, 64;
--bs-tertiary-color: rgba(173, 181, 189, 0.5);
--bs-tertiary-color-rgb: 173, 181, 189;
--bs-tertiary-bg: #2b3035;
--bs-tertiary-bg-rgb: 43, 48, 53;
--bs-primary-text-emphasis: #6ea8fe;
--bs-secondary-text-emphasis: #a7acb1;
--bs-success-text-emphasis: #75b798;
--bs-info-text-emphasis: #6edff6;
--bs-warning-text-emphasis: #ffda6a;
--bs-danger-text-emphasis: #ea868f;
--bs-light-text-emphasis: #f8f9fa;
--bs-dark-text-emphasis: #dee2e6;
--bs-primary-bg-subtle: #031633;
--bs-secondary-bg-subtle: #161719;
--bs-success-bg-subtle: #051b11;
--bs-info-bg-subtle: #032830;
--bs-warning-bg-subtle: #332701;
--bs-danger-bg-subtle: #2c0b0e;
--bs-light-bg-subtle: #343a40;
--bs-dark-bg-subtle: #1a1d20;
--bs-primary-border-subtle: #084298;
--bs-secondary-border-subtle: #41464b;
--bs-success-border-subtle: #0f5132;
--bs-info-border-subtle: #087990;
--bs-warning-border-subtle: #997404;
--bs-danger-border-subtle: #842029;
--bs-light-border-subtle: #495057;
--bs-dark-border-subtle: #343a40;
--bs-heading-color: inherit;
--bs-link-color: #6ea8fe;
--bs-link-hover-color: #8bb9fe;
--bs-link-color-rgb: 110, 168, 254;
--bs-link-hover-color-rgb: 139, 185, 254;
--bs-code-color: #e685b5;
--bs-border-color: #495057;
--bs-border-color-translucent: rgba(255, 255, 255, 0.15);
--bs-form-valid-color: #75b798;
--bs-form-valid-border-color: #75b798;
--bs-form-invalid-color: #ea868f;
--bs-form-invalid-border-color: #ea868f;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
@media (prefers-reduced-motion: no-preference) {
:root {
scroll-behavior: smooth;
}
}
body {
margin: 0;
font-family: var(--bs-body-font-family);
font-size: var(--bs-body-font-size);
font-weight: var(--bs-body-font-weight);
line-height: var(--bs-body-line-height);
color: var(--bs-body-color);
text-align: var(--bs-body-text-align);
background-color: var(--bs-body-bg);
-webkit-text-size-adjust: 100%;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
hr {
margin: 1rem 0;
color: inherit;
border: 0;
border-top: var(--bs-border-width) solid;
opacity: 0.25;
}
h6, h5, h4, h3, h2, h1 {
margin-top: 0;
margin-bottom: 0.5rem;
font-weight: 500;
line-height: 1.2;
color: var(--bs-heading-color);
}
h1 {
font-size: calc(1.375rem + 1.5vw);
}
@media (min-width: 1200px) {
h1 {
font-size: 2.5rem;
}
}
h2 {
font-size: calc(1.325rem + 0.9vw);
}
@media (min-width: 1200px) {
h2 {
font-size: 2rem;
}
}
h3 {
font-size: calc(1.3rem + 0.6vw);
}
@media (min-width: 1200px) {
h3 {
font-size: 1.75rem;
}
}
h4 {
font-size: calc(1.275rem + 0.3vw);
}
@media (min-width: 1200px) {
h4 {
font-size: 1.5rem;
}
}
h5 {
font-size: 1.25rem;
}
h6 {
font-size: 1rem;
}
p {
margin-top: 0;
margin-bottom: 1rem;
}
abbr[title] {
-webkit-text-decoration: underline dotted;
text-decoration: underline dotted;
cursor: help;
-webkit-text-decoration-skip-ink: none;
text-decoration-skip-ink: none;
}
address {
margin-bottom: 1rem;
font-style: normal;
line-height: inherit;
}
ol,
ul {
padding-right: 2rem;
}
ol,
ul,
dl {
margin-top: 0;
margin-bottom: 1rem;
}
ol ol,
ul ul,
ol ul,
ul ol {
margin-bottom: 0;
}
dt {
font-weight: 700;
}
dd {
margin-bottom: 0.5rem;
margin-right: 0;
}
blockquote {
margin: 0 0 1rem;
}
b,
strong {
font-weight: bolder;
}
small {
font-size: 0.875em;
}
mark {
padding: 0.1875em;
background-color: var(--bs-highlight-bg);
}
sub,
sup {
position: relative;
font-size: 0.75em;
line-height: 0;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
a {
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
text-decoration: underline;
}
a:hover {
--bs-link-color-rgb: var(--bs-link-hover-color-rgb);
}
a:not([href]):not([class]), a:not([href]):not([class]):hover {
color: inherit;
text-decoration: none;
}
pre,
code,
kbd,
samp {
font-family: var(--bs-font-monospace);
font-size: 1em;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
overflow: auto;
font-size: 0.875em;
}
pre code {
font-size: inherit;
color: inherit;
word-break: normal;
}
code {
font-size: 0.875em;
color: var(--bs-code-color);
word-wrap: break-word;
}
a > code {
color: inherit;
}
kbd {
padding: 0.1875rem 0.375rem;
font-size: 0.875em;
color: var(--bs-body-bg);
background-color: var(--bs-body-color);
border-radius: 0.25rem;
}
kbd kbd {
padding: 0;
font-size: 1em;
}
figure {
margin: 0 0 1rem;
}
img,
svg {
vertical-align: middle;
}
table {
caption-side: bottom;
border-collapse: collapse;
}
caption {
padding-top: 0.5rem;
padding-bottom: 0.5rem;
color: var(--bs-secondary-color);
text-align: right;
}
th {
text-align: inherit;
text-align: -webkit-match-parent;
}
thead,
tbody,
tfoot,
tr,
td,
th {
border-color: inherit;
border-style: solid;
border-width: 0;
}
label {
display: inline-block;
}
button {
border-radius: 0;
}
button:focus:not(:focus-visible) {
outline: 0;
}
input,
button,
select,
optgroup,
textarea {
margin: 0;
font-family: inherit;
font-size: inherit;
line-height: inherit;
}
button,
select {
text-transform: none;
}
[role=button] {
cursor: pointer;
}
select {
word-wrap: normal;
}
select:disabled {
opacity: 1;
}
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
display: none !important;
}
button,
[type=button],
[type=reset],
[type=submit] {
-webkit-appearance: button;
}
button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {
cursor: pointer;
}
::-moz-focus-inner {
padding: 0;
border-style: none;
}
textarea {
resize: vertical;
}
fieldset {
min-width: 0;
padding: 0;
margin: 0;
border: 0;
}
legend {
float: right;
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
font-size: calc(1.275rem + 0.3vw);
line-height: inherit;
}
@media (min-width: 1200px) {
legend {
font-size: 1.5rem;
}
}
legend + * {
clear: right;
}
::-webkit-datetime-edit-fields-wrapper,
::-webkit-datetime-edit-text,
::-webkit-datetime-edit-minute,
::-webkit-datetime-edit-hour-field,
::-webkit-datetime-edit-day-field,
::-webkit-datetime-edit-month-field,
::-webkit-datetime-edit-year-field {
padding: 0;
}
::-webkit-inner-spin-button {
height: auto;
}
[type=search] {
outline-offset: -2px;
-webkit-appearance: textfield;
}
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-color-swatch-wrapper {
padding: 0;
}
::-webkit-file-upload-button {
font: inherit;
-webkit-appearance: button;
}
::file-selector-button {
font: inherit;
-webkit-appearance: button;
}
output {
display: inline-block;
}
iframe {
border: 0;
}
summary {
display: list-item;
cursor: pointer;
}
progress {
vertical-align: baseline;
}
[hidden] {
display: none !important;
}
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */

+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-reboot.rtl.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-reboot.rtl.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-reboot.rtl.min.css.map
File diff suppressed because it is too large
View File


+ 5399
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-utilities.css
File diff suppressed because it is too large
View File


+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-utilities.css.map
File diff suppressed because it is too large
View File


+ 6
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-utilities.min.css
File diff suppressed because it is too large
View File


+ 1
- 0
repostajes/static/plugins/bootstrap/css/bootstrap-utilities.min.css.map
File diff suppressed because it is too large
View File


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save