From babd802c440e614790b53be04fcca9547b94d9b6 Mon Sep 17 00:00:00 2001 From: cespinosa Date: Tue, 8 Aug 2023 13:18:51 -0500 Subject: [PATCH 1/3] Ht-01 --- .gitignore | 5 + apps/authentication/views.py | 2 +- apps/home/forms.py | 37 ++ apps/home/migrations/0001_initial.py | 26 + .../migrations/0002_auto_20230728_1654.py | 34 ++ .../migrations/0003_alter_inventario_id.py | 18 + .../0004_alter_inventario_estado.py | 18 + .../migrations/0005_auto_20230728_1900.py | 61 ++ apps/home/migrations/0006_eventocaledario.py | 26 + apps/home/models.py | 33 ++ apps/home/templatetags/custom_tags.py | 7 + apps/home/tests.py | 8 - apps/home/urls.py | 16 +- apps/home/views.py | 138 ++++- apps/static/assets/css/material-dashboard.css | 279 +++++---- apps/templates/accounts/login.html | 16 +- apps/templates/home/calendar.html | 119 ++++ apps/templates/home/detalle_inventario.html | 13 + apps/templates/home/index.html | 560 ++++++------------ apps/templates/home/listar_inventario.html | 6 + apps/templates/home/page-rtl-support.html | 500 ---------------- .../home/registrar_inventario_form.html | 50 ++ apps/templates/home/ui-tables.html | 286 --------- apps/templates/home/ui-typography.html | 109 ---- apps/templates/includes/footer.html | 15 +- apps/templates/includes/navigation.html | 21 +- apps/templates/includes/sidebar.html | 82 +-- apps/templates/layouts/base-rtl.html | 83 --- apps/templates/layouts/base.html | 122 +++- apps/templates/layouts/base_list.html | 250 ++++++++ core/settings.py | 26 +- 31 files changed, 1384 insertions(+), 1582 deletions(-) create mode 100644 apps/home/forms.py create mode 100644 apps/home/migrations/0001_initial.py create mode 100644 apps/home/migrations/0002_auto_20230728_1654.py create mode 100644 apps/home/migrations/0003_alter_inventario_id.py create mode 100644 apps/home/migrations/0004_alter_inventario_estado.py create mode 100644 apps/home/migrations/0005_auto_20230728_1900.py create mode 100644 apps/home/migrations/0006_eventocaledario.py create mode 100644 apps/home/templatetags/custom_tags.py delete mode 100644 apps/home/tests.py create mode 100644 apps/templates/home/calendar.html create mode 100644 apps/templates/home/detalle_inventario.html create mode 100644 apps/templates/home/listar_inventario.html delete mode 100644 apps/templates/home/page-rtl-support.html create mode 100644 apps/templates/home/registrar_inventario_form.html delete mode 100644 apps/templates/home/ui-tables.html delete mode 100644 apps/templates/home/ui-typography.html delete mode 100644 apps/templates/layouts/base-rtl.html create mode 100644 apps/templates/layouts/base_list.html diff --git a/.gitignore b/.gitignore index a79e5da..554ae9a 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,11 @@ __pycache__/ # venv env venv +.idea/ +*/migrations/* +!*/migrations/__init__.py +/apps/home/migrations/ + # other .DS_Store diff --git a/apps/authentication/views.py b/apps/authentication/views.py index 88b51eb..560ed9a 100644 --- a/apps/authentication/views.py +++ b/apps/authentication/views.py @@ -22,7 +22,7 @@ def login_view(request): user = authenticate(username=username, password=password) if user is not None: login(request, user) - return redirect("/") + return redirect("/inicio") else: msg = 'Invalid credentials' else: diff --git a/apps/home/forms.py b/apps/home/forms.py new file mode 100644 index 0000000..e25feb7 --- /dev/null +++ b/apps/home/forms.py @@ -0,0 +1,37 @@ +from django import forms +from apps.home.models import Inventario, EventoCaledario + + +#crea formulario para registarr inventario +class RegistrarInventarioForm(forms.ModelForm): + class Meta: + model = Inventario + fields = ('nombre', 'descripcion', 'cantidad', 'precio', 'categoria', 'estado') + widgets = { + 'nombre': forms.TextInput(attrs={'class': 'form-control'}), + 'descripcion': forms.TextInput(attrs={'class': 'form-control'}), + 'cantidad': forms.TextInput(attrs={'class': 'form-control'}), + 'precio': forms.TextInput(attrs={'class': 'form-control'}), + 'categoria': forms.TextInput(attrs={'class': 'form-control'}), + 'estado': forms.Select(attrs={'class': 'form-control'}), # Usamos forms.Select para el campo "estado" + } + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['estado'].widget.attrs.update({'class': 'form-control'}) + +class EventoCalendarioForm(forms.ModelForm): + + class Meta: + model = EventoCaledario + fields = ('titulo', 'descripcion', 'fecha_inicio') + widgets = { + 'titulo': forms.TextInput(attrs={'class': 'form-control'}), + 'descripcion': forms.TextInput(attrs={'class': 'form-control'}), + 'fecha_inicio': forms.DateTimeInput(), + } + + def __init__(self, *args, **kwargs): + super(EventoCalendarioForm, self).__init__(*args, **kwargs) + self.fields['fecha_inicio'].widget.attrs.update({'class': 'form-control'}) + diff --git a/apps/home/migrations/0001_initial.py b/apps/home/migrations/0001_initial.py new file mode 100644 index 0000000..2959ce5 --- /dev/null +++ b/apps/home/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.6 on 2023-07-26 22:37 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Producto', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=50)), + ('descripcion', models.CharField(max_length=50)), + ('precio', models.CharField(max_length=50)), + ('imagen', models.ImageField(blank=True, null=True, upload_to='productos')), + ('created', models.DateTimeField(auto_now_add=True)), + ('updated', models.DateTimeField(auto_now_add=True)), + ], + ), + ] diff --git a/apps/home/migrations/0002_auto_20230728_1654.py b/apps/home/migrations/0002_auto_20230728_1654.py new file mode 100644 index 0000000..c3f3d9f --- /dev/null +++ b/apps/home/migrations/0002_auto_20230728_1654.py @@ -0,0 +1,34 @@ +# Generated by Django 3.2.6 on 2023-07-28 16:54 + +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), + ('home', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Inventario', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('nombre', models.CharField(max_length=100)), + ('descripcion', models.CharField(max_length=100)), + ('cantidad', models.IntegerField()), + ('precio', models.IntegerField()), + ('categoria', models.CharField(max_length=100)), + ('estado', models.CharField(max_length=100)), + ('fecha_creacion', models.DateField()), + ('fecha_actualizacion', models.DateField()), + ('usuario', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.DeleteModel( + name='Producto', + ), + ] diff --git a/apps/home/migrations/0003_alter_inventario_id.py b/apps/home/migrations/0003_alter_inventario_id.py new file mode 100644 index 0000000..547252b --- /dev/null +++ b/apps/home/migrations/0003_alter_inventario_id.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2023-07-28 16:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0002_auto_20230728_1654'), + ] + + operations = [ + migrations.AlterField( + model_name='inventario', + name='id', + field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ] diff --git a/apps/home/migrations/0004_alter_inventario_estado.py b/apps/home/migrations/0004_alter_inventario_estado.py new file mode 100644 index 0000000..a2f0132 --- /dev/null +++ b/apps/home/migrations/0004_alter_inventario_estado.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.6 on 2023-07-28 18:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('home', '0003_alter_inventario_id'), + ] + + operations = [ + migrations.AlterField( + model_name='inventario', + name='estado', + field=models.IntegerField(choices=[(1, 'Activo'), (2, 'Inactivo')], default=1), + ), + ] diff --git a/apps/home/migrations/0005_auto_20230728_1900.py b/apps/home/migrations/0005_auto_20230728_1900.py new file mode 100644 index 0000000..d999ca6 --- /dev/null +++ b/apps/home/migrations/0005_auto_20230728_1900.py @@ -0,0 +1,61 @@ +# Generated by Django 3.2.6 on 2023-07-28 19:00 + +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), + ('home', '0004_alter_inventario_estado'), + ] + + operations = [ + migrations.AlterField( + model_name='inventario', + name='cantidad', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='inventario', + name='categoria', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='inventario', + name='descripcion', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='inventario', + name='estado', + field=models.IntegerField(choices=[(1, 'Activo'), (2, 'Inactivo')]), + ), + migrations.AlterField( + model_name='inventario', + name='fecha_actualizacion', + field=models.DateField(blank=True, null=True), + ), + migrations.AlterField( + model_name='inventario', + name='fecha_creacion', + field=models.DateField(blank=True, null=True), + ), + migrations.AlterField( + model_name='inventario', + name='nombre', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='inventario', + name='precio', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='inventario', + name='usuario', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/apps/home/migrations/0006_eventocaledario.py b/apps/home/migrations/0006_eventocaledario.py new file mode 100644 index 0000000..0550e6d --- /dev/null +++ b/apps/home/migrations/0006_eventocaledario.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.6 on 2023-08-08 16:03 + +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), + ('home', '0005_auto_20230728_1900'), + ] + + operations = [ + migrations.CreateModel( + name='EventoCaledario', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('titulo', models.CharField(blank=True, max_length=100, null=True)), + ('descripcion', models.CharField(blank=True, max_length=100, null=True)), + ('fecha_inicio', models.DateField(blank=True, null=True)), + ('usuario', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + ] diff --git a/apps/home/models.py b/apps/home/models.py index c94fe84..5d3d0f5 100644 --- a/apps/home/models.py +++ b/apps/home/models.py @@ -8,3 +8,36 @@ # Create your models here. + +class Inventario(models.Model): + + ACTIVO = 1 + INACTIVO = 2 + + ESTADO_CHOICES = ( + (ACTIVO, 'Activo'), + (INACTIVO, 'Inactivo'), + ) + + nombre = models.CharField(max_length=100, null=True, blank=True) + descripcion = models.CharField(max_length=100, null=True, blank=True) + cantidad = models.IntegerField(null=True, blank=True) + precio = models.IntegerField(null=True, blank=True) + categoria = models.CharField(max_length=100, null=True, blank=True) + estado = models.IntegerField(choices=ESTADO_CHOICES) + fecha_creacion = models.DateField(null=True, blank=True) + fecha_actualizacion = models.DateField(null=True, blank=True) + usuario = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) + + def __str__(self): + return self.nombre + +class EventoCaledario(models.Model): + + titulo = models.CharField(max_length=100, null=True, blank=True) + descripcion = models.CharField(max_length=100, null=True, blank=True) + fecha_inicio = models.DateField(null=True, blank=True) + usuario = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) + + def __str__(self): + return self.titulo \ No newline at end of file diff --git a/apps/home/templatetags/custom_tags.py b/apps/home/templatetags/custom_tags.py new file mode 100644 index 0000000..703aedb --- /dev/null +++ b/apps/home/templatetags/custom_tags.py @@ -0,0 +1,7 @@ +from django import template + +register = template.Library() + +@register.filter +def get_field_value(obj, field_name): + return getattr(obj, field_name, "") diff --git a/apps/home/tests.py b/apps/home/tests.py deleted file mode 100644 index c77ada2..0000000 --- a/apps/home/tests.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- encoding: utf-8 -*- -""" -Copyright (c) 2019 - present AppSeed.us -""" - -from django.test import TestCase - -# Create your tests here. diff --git a/apps/home/urls.py b/apps/home/urls.py index 5acb444..99c893b 100644 --- a/apps/home/urls.py +++ b/apps/home/urls.py @@ -6,10 +6,22 @@ from django.urls import path, re_path from apps.home import views +app_name = 'home' + urlpatterns = [ - # The home page - path('', views.index, name='home'), + #Pagina de inicio + path('inicio', views.index.as_view(), name='inicio'), + # Inventario + path('registrar-inventario', views.RegistrarInventarioView.as_view(), name='registrar_inventario'), + path('listar-inventario', views.ListarInventarioView.as_view(), name='listar_inventario'), + path('detalle-inventario/', views.DetalleInventarioView.as_view(), name='detalle_inventario'), + + #DASHBOARD + path('inventario-chart', views.inventario_chart, name='inventario_chart'), + + #CALENDARIO + path('calendario', views.Calendarioview.as_view(), name='calendario'), # Matches any html file re_path(r'^.*\.*', views.pages, name='pages'), diff --git a/apps/home/views.py b/apps/home/views.py index 2513b78..9f8c013 100644 --- a/apps/home/views.py +++ b/apps/home/views.py @@ -4,18 +4,33 @@ """ from django import template +from django.contrib import messages from django.contrib.auth.decorators import login_required -from django.http import HttpResponse, HttpResponseRedirect +from django.contrib.auth.mixins import LoginRequiredMixin +from django.http import HttpResponse, HttpResponseRedirect, JsonResponse +from django.shortcuts import render from django.template import loader from django.urls import reverse +from django.views import View +from django.views.generic import FormView, TemplateView, DetailView +#Propios +from apps.home.forms import * +from django.shortcuts import render -@login_required(login_url="/login/") -def index(request): - context = {'segment': 'index'} +from apps.home.models import EventoCaledario + + +class index(LoginRequiredMixin, View): - html_template = loader.get_template('home/index.html') - return HttpResponse(html_template.render(context, request)) + total_inventario = Inventario.objects.all().count() + inventario = Inventario.objects.all() + + context = {'segment': 'index', + 'total_inventario': total_inventario, + 'inventario': inventario,} + def get(self, request, *args, **kwargs): + return render(request, 'home/index.html', self.context) @login_required(login_url="/login/") @@ -42,3 +57,114 @@ def pages(request): except: html_template = loader.get_template('home/page-500.html') return HttpResponse(html_template.render(context, request)) + + +class RegistrarInventarioView(FormView): + + template_name = 'home/registrar_inventario_form.html' + form_class = RegistrarInventarioForm + success_url = '/registrar-inventario' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['activo'] = True + return context + + def form_valid(self, form): + #validar que el estado se activo sino no se guarda + if form.cleaned_data['estado'] == 2: + messages.error(self.request, 'No se puede guardar un inventario inactivo') + return super().form_invalid(form) + form.save() + messages.success(self.request, 'El inventario se ha registrado exitosamente.') + return super().form_valid(form) + + +class ListTableView(TemplateView): + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['models'] = Inventario.objects.all() + context['actions'] = self.actions + context['column_names'] = self.column_names + context['fields'] = self.fields + context['activo_listar'] = True + return context + +class ListarInventarioView(ListTableView): + + template_name = 'home/listar_inventario.html' + column_names = ['Nombre', 'Descripción', 'Cantidad', 'Precio', 'Estado'] + fields = ['nombre', 'descripcion', 'cantidad', 'precio', 'estado'] + model = Inventario + + actions = [ + { + 'url': 'home:detalle_inventario', + 'url_args': 'pk', + 'title': 'Ver', + 'icon': 'eye', + 'color': 'primary', + }, + ] + + +class DetalleInventarioView(DetailView): + + template_name = 'home/detalle_inventario.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['inventario'] = Inventario.objects.get(pk=self.kwargs['pk']) + return context + + def get_queryset(self): + return Inventario.objects.all() + +def inventario_chart(request): + # Obtener los datos del inventario desde la base de datos + inventarios = Inventario.objects.all() + + # Crear diccionario para almacenar la cantidad de inventario por categoría + inventario_por_categoria = {} + + for inventario in inventarios: + categoria = inventario.categoria + cantidad = inventario.cantidad + + if categoria in inventario_por_categoria: + inventario_por_categoria[categoria] += cantidad + else: + inventario_por_categoria[categoria] = cantidad + + # Convertir el diccionario en listas para utilizarlo en el gráfico + categorias = list(inventario_por_categoria.keys()) + cantidades = list(inventario_por_categoria.values()) + + # Retornar los datos en formato JSON + return JsonResponse({'categorias': categorias, 'cantidades': cantidades}) + +class Calendarioview(TemplateView, FormView): + + #crear vista par< mostrar calendario + template_name = 'home/calendar.html' + form_class = EventoCalendarioForm + success_url = '/calendario' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['eventos'] = EventoCaledario.objects.all() + context['activo_calendario'] = True + return context + + def form_valid(self, form): + evento = form.save(commit=False) + evento.save() + return super().form_valid(form) + + def form_invalid(self, form): + errors = form.errors + return super().form_invalid(form) + + + diff --git a/apps/static/assets/css/material-dashboard.css b/apps/static/assets/css/material-dashboard.css index 46414b0..b6293ee 100644 --- a/apps/static/assets/css/material-dashboard.css +++ b/apps/static/assets/css/material-dashboard.css @@ -1,16 +1,16 @@ -/*! - - ========================================================= - * Material Dashboard - v2.1.0 - ========================================================= - - * Product Page: https://www.creative-tim.com/product/material-dashboard - * Copyright 2020 Creative Tim (http://www.creative-tim.com) - - ========================================================= - - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - +/*! + + ========================================================= + * Material Dashboard - v2.1.0 + ========================================================= + + * Product Page: https://www.creative-tim.com/product/material-dashboard + * Copyright 2020 Creative Tim (http://www.creative-tim.com) + + ========================================================= + + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + */ /* brand Colors */ .card { @@ -117,7 +117,7 @@ sup { top: -.5em; } a { - color: #9c27b0; + color: #273746; text-decoration: none; background-color: transparent; -webkit-text-decoration-skip: objects; } @@ -425,7 +425,7 @@ sup { top: -.5em; } a { - color: #9c27b0; + color: #273746; text-decoration: none; background-color: transparent; -webkit-text-decoration-skip: objects; } @@ -2306,7 +2306,7 @@ fieldset:disabled a.btn { .btn-link { font-weight: 400; - color: #9c27b0; + color: #273746; background-color: transparent; } .btn-link:hover { color: #0a6ebd; @@ -6337,24 +6337,24 @@ a.text-dark:hover, a.text-dark:focus { outline: 0; } .btn.btn-primary { color: #fff; - background-color: #9c27b0; - border-color: #9c27b0; - box-shadow: 0 2px 2px 0 rgba(156, 39, 176, 0.14), 0 3px 1px -2px rgba(156, 39, 176, 0.2), 0 1px 5px 0 rgba(156, 39, 176, 0.12); } + background-color: #273746; + border-color: #273746; + box-shadow: 0 2px 2px 0 rgba(52, 73, 94, 0.14), 0 3px 1px -2px rgba(52, 73, 94, 0.2), 0 1px 5px 0 rgba(52, 73, 94, 0.12); } .btn.btn-primary:hover { color: #fff; - background-color: #9124a3; - border-color: #701c7e; } + background-color: #34495E; + border-color: #424949; } .btn.btn-primary:focus, .btn.btn-primary.focus, .btn.btn-primary:hover { color: #fff; - background-color: #9124a3; - border-color: #701c7e; } + background-color: #34495E; + border-color: #424949; } .btn.btn-primary:active, .btn.btn-primary.active, .open > .btn.btn-primary.dropdown-toggle, .show > .btn.btn-primary.dropdown-toggle { color: #fff; - background-color: #9124a3; - border-color: #701c7e; - box-shadow: 0 2px 2px 0 rgba(156, 39, 176, 0.14), 0 3px 1px -2px rgba(156, 39, 176, 0.2), 0 1px 5px 0 rgba(156, 39, 176, 0.12); } + background-color: #34495E; + border-color: #424949; + box-shadow: 0 2px 2px 0 rgba(52, 73, 94, 0.14), 0 3px 1px -2px rgba(52, 73, 94, 0.2), 0 1px 5px 0 rgba(52, 73, 94, 0.12); } .btn.btn-primary:active:hover, .btn.btn-primary:active:focus, .btn.btn-primary:active.focus, .btn.btn-primary.active:hover, .btn.btn-primary.active:focus, .btn.btn-primary.active.focus, .open > .btn.btn-primary.dropdown-toggle:hover, .open > .btn.btn-primary.dropdown-toggle:focus, @@ -6363,28 +6363,28 @@ a.text-dark:hover, a.text-dark:focus { .show > .btn.btn-primary.dropdown-toggle:focus, .show > .btn.btn-primary.dropdown-toggle.focus { color: #fff; - background-color: #9124a3; + background-color: #34495E; border-color: #3f1048; } .open > .btn.btn-primary.dropdown-toggle.bmd-btn-icon { color: inherit; - background-color: #9c27b0; } + background-color: #273746; } .open > .btn.btn-primary.dropdown-toggle.bmd-btn-icon:hover { - background-color: #9124a3; } + background-color: #34495E; } .btn.btn-primary.disabled:focus, .btn.btn-primary.disabled.focus, .btn.btn-primary:disabled:focus, .btn.btn-primary:disabled.focus { - background-color: #9c27b0; - border-color: #9c27b0; } + background-color: #273746; + border-color: #273746; } .btn.btn-primary.disabled:hover, .btn.btn-primary:disabled:hover { - background-color: #9c27b0; - border-color: #9c27b0; } + background-color: #273746; + border-color: #273746; } .btn.btn-primary:focus, .btn.btn-primary:active, .btn.btn-primary:hover { - box-shadow: 0 14px 26px -12px rgba(156, 39, 176, 0.42), 0 4px 23px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(156, 39, 176, 0.2); } + box-shadow: 0 14px 26px -12px rgba(52, 73, 94, 0.42), 0 4px 23px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(52, 73, 94, 0.2); } .btn.btn-primary.btn-link { background-color: transparent; - color: #9c27b0; + color: #273746; box-shadow: none; } .btn.btn-primary.btn-link:hover, .btn.btn-primary.btn-link:focus, .btn.btn-primary.btn-link:active { background-color: transparent; - color: #9c27b0; } + color: #273746; } .btn.btn-secondary { color: #333333; background-color: #fafafa; @@ -6663,7 +6663,7 @@ a.text-dark:hover, a.text-dark:focus { .show > .btn.btn-rose.dropdown-toggle:focus, .show > .btn.btn-rose.dropdown-toggle.focus { color: #fff; - background-color: #ea2c6d; + background-color: #ea2c6d;primary border-color: #7b0c32; } .open > .btn.btn-rose.dropdown-toggle.bmd-btn-icon { color: inherit; @@ -6856,23 +6856,23 @@ a.text-dark:hover, a.text-dark:focus { .btn.btn-outline.btn-link { background-color: transparent; } .btn.btn-outline-primary { - color: #9c27b0; + color: #273746; background-color: transparent; - border-color: #9c27b0; } + border-color: #273746; } .btn.btn-outline-primary:hover { - color: #9c27b0; + color: #273746; background-color: rgba(153, 153, 153, 0.2); - border-color: #9c27b0; } + border-color: #273746; } .btn.btn-outline-primary:focus, .btn.btn-outline-primary.focus, .btn.btn-outline-primary:hover { - color: #9c27b0; + color: #273746; background-color: rgba(153, 153, 153, 0.2); - border-color: #9c27b0; } + border-color: #273746; } .btn.btn-outline-primary:active, .btn.btn-outline-primary.active, .open > .btn.btn-outline-primary.dropdown-toggle, .show > .btn.btn-outline-primary.dropdown-toggle { - color: #9c27b0; + color: #273746; background-color: rgba(153, 153, 153, 0.2); - border-color: #9c27b0; + border-color: #273746; box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } .btn.btn-outline-primary:active:hover, .btn.btn-outline-primary:active:focus, .btn.btn-outline-primary:active.focus, .btn.btn-outline-primary.active:hover, .btn.btn-outline-primary.active:focus, .btn.btn-outline-primary.active.focus, .open > .btn.btn-outline-primary.dropdown-toggle:hover, @@ -6881,9 +6881,9 @@ a.text-dark:hover, a.text-dark:focus { .show > .btn.btn-outline-primary.dropdown-toggle:hover, .show > .btn.btn-outline-primary.dropdown-toggle:focus, .show > .btn.btn-outline-primary.dropdown-toggle.focus { - color: #9c27b0; + color: #273746; background-color: rgba(153, 153, 153, 0.4); - border-color: #9c27b0; } + border-color: #273746; } .open > .btn.btn-outline-primary.dropdown-toggle.bmd-btn-icon { color: inherit; background-color: transparent; } @@ -6891,26 +6891,26 @@ a.text-dark:hover, a.text-dark:focus { background-color: rgba(153, 153, 153, 0.2); } .btn.btn-outline-primary.disabled:focus, .btn.btn-outline-primary.disabled.focus, .btn.btn-outline-primary:disabled:focus, .btn.btn-outline-primary:disabled.focus { background-color: transparent; - border-color: #9c27b0; } + border-color: #273746; } .btn.btn-outline-primary.disabled:hover, .btn.btn-outline-primary:disabled:hover { background-color: transparent; - border-color: #9c27b0; } + border-color: #273746; } .bg-inverse .btn.btn-outline-primary { - color: #9c27b0; + color: #273746; background-color: transparent; - border-color: #9c27b0; } + border-color: #273746; } .bg-inverse .btn.btn-outline-primary:hover { - color: #9c27b0; + color: #273746; background-color: rgba(204, 204, 204, 0.15); border-color: rgba(204, 204, 204, 0.15); } .bg-inverse .btn.btn-outline-primary:focus, .bg-inverse .btn.btn-outline-primary.focus, .bg-inverse .btn.btn-outline-primary:hover { - color: #9c27b0; + color: #273746; background-color: rgba(204, 204, 204, 0.15); border-color: rgba(204, 204, 204, 0.15); } .bg-inverse .btn.btn-outline-primary:active, .bg-inverse .btn.btn-outline-primary.active, .open > .bg-inverse .btn.btn-outline-primary.dropdown-toggle, .show > .bg-inverse .btn.btn-outline-primary.dropdown-toggle { - color: #9c27b0; + color: #273746; background-color: rgba(204, 204, 204, 0.15); border-color: rgba(204, 204, 204, 0.15); box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); } @@ -6921,7 +6921,7 @@ a.text-dark:hover, a.text-dark:focus { .show > .bg-inverse .btn.btn-outline-primary.dropdown-toggle:hover, .show > .bg-inverse .btn.btn-outline-primary.dropdown-toggle:focus, .show > .bg-inverse .btn.btn-outline-primary.dropdown-toggle.focus { - color: #9c27b0; + color: #273746; background-color: rgba(204, 204, 204, 0.25); border-color: rgba(204, 204, 204, 0.25); } .open > .bg-inverse .btn.btn-outline-primary.dropdown-toggle.bmd-btn-icon { @@ -6931,10 +6931,10 @@ a.text-dark:hover, a.text-dark:focus { background-color: rgba(204, 204, 204, 0.15); } .bg-inverse .btn.btn-outline-primary.disabled:focus, .bg-inverse .btn.btn-outline-primary.disabled.focus, .bg-inverse .btn.btn-outline-primary:disabled:focus, .bg-inverse .btn.btn-outline-primary:disabled.focus { background-color: transparent; - border-color: #9c27b0; } + border-color: #273746; } .bg-inverse .btn.btn-outline-primary.disabled:hover, .bg-inverse .btn.btn-outline-primary:disabled:hover { background-color: transparent; - border-color: #9c27b0; } + border-color: #273746; } .btn.btn-outline-primary.btn-link { background-color: transparent; } .btn.btn-outline-secondary { @@ -7533,15 +7533,26 @@ a.text-dark:hover, a.text-dark:focus { width: 0; color: #fff; height: 0; - box-shadow: 0 0 0 0, 0 0 0 0, 0 0 0 0, 0 0 0 0, 0 0 0 0, 0 0 0 0, 0 0 0 0 inset; + box-shadow: 0 0 0 0, + 0 0 0 0, + 0 0 0 0, + 0 0 0 0, + 0 0 0 0, + 0 0 0 0, + 0 0 0 0 inset; animation: checkboxOff 0.3s forwards; } .form-check .form-check-input:focus + .form-check-sign .check:after { opacity: 0.2; } .form-check .form-check-input:checked ~ .form-check-sign .check { - background: #9c27b0; } + background: #273746; } .form-check .form-check-input:checked ~ .form-check-sign .check:before { color: #FFFFFF; - box-shadow: 0 0 0 10px, 10px -10px 0 10px, 32px 0 0 20px, 0px 32px 0 20px, -5px 5px 0 10px, 20px -12px 0 11px; + box-shadow: 0 0 0 10px, + 10px -10px 0 10px, + 32px 0 0 20px, + 0px 32px 0 20px, + -5px 5px 0 10px, + 20px -12px 0 11px; animation: checkboxOn 0.3s forwards; } .form-check .form-check-input:checked ~ .form-check-sign:before { animation: rippleOn 500ms; } @@ -7569,11 +7580,26 @@ a.text-dark:hover, a.text-dark:focus { @keyframes checkboxOn { 0% { - box-shadow: 0 0 0 10px, 10px -10px 0 10px, 32px 0 0 20px, 0px 32px 0 20px, -5px 5px 0 10px, 15px 2px 0 11px; } + box-shadow: 0 0 0 10px, + 10px -10px 0 10px, + 32px 0 0 20px, + 0px 32px 0 20px, + -5px 5px 0 10px, + 15px 2px 0 11px; } 50% { - box-shadow: 0 0 0 10px, 10px -10px 0 10px, 32px 0 0 20px, 0px 32px 0 20px, -5px 5px 0 10px, 20px 2px 0 11px; } + box-shadow: 0 0 0 10px, + 10px -10px 0 10px, + 32px 0 0 20px, + 0px 32px 0 20px, + -5px 5px 0 10px, + 20px 2px 0 11px; } 100% { - box-shadow: 0 0 0 10px, 10px -10px 0 10px, 32px 0 0 20px, 0px 32px 0 20px, -5px 5px 0 10px, 20px -12px 0 11px; } } + box-shadow: 0 0 0 10px, + 10px -10px 0 10px, + 32px 0 0 20px, + 0px 32px 0 20px, + -5px 5px 0 10px, + 20px -12px 0 11px; } } @keyframes rippleOn { 0% { @@ -7617,7 +7643,7 @@ a.text-dark:hover, a.text-dark:focus { height: 15px; width: 15px; border-radius: 100%; - background-color: #9c27b0; + background-color: #273746; transform: scale3d(0,0,0); } .form-check .form-check-input { @@ -7629,9 +7655,9 @@ a.text-dark:hover, a.text-dark:focus { .form-check .form-check-input:checked ~ .circle { opacity: 1; } .form-check .form-check-input:checked ~ .check { - background-color: #9c27b0; } + background-color: #273746; } .form-check .form-check-input:checked ~ .circle { - border-color: #9c27b0; } + border-color: #273746; } .form-check .form-check-input:checked .check:before { animation: checkboxOn .5s forwards; } .form-check .form-check-input:checked ~ .circle .check { @@ -7686,11 +7712,26 @@ a.text-dark:hover, a.text-dark:focus { @keyframes checkboxOn { 0% { - box-shadow: 0 0 0 10px, 10px -10px 0 10px, 32px 0 0 20px, 0px 32px 0 20px, -5px 5px 0 10px, 15px 2px 0 11px; } + box-shadow: 0 0 0 10px, + 10px -10px 0 10px, + 32px 0 0 20px, + 0px 32px 0 20px, + -5px 5px 0 10px, + 15px 2px 0 11px; } 50% { - box-shadow: 0 0 0 10px, 10px -10px 0 10px, 32px 0 0 20px, 0px 32px 0 20px, -5px 5px 0 10px, 20px 2px 0 11px; } + box-shadow: 0 0 0 10px, + 10px -10px 0 10px, + 32px 0 0 20px, + 0px 32px 0 20px, + -5px 5px 0 10px, + 20px 2px 0 11px; } 100% { - box-shadow: 0 0 0 10px, 10px -10px 0 10px, 32px 0 0 20px, 0px 32px 0 20px, -5px 5px 0 10px, 20px -12px 0 11px; } } + box-shadow: 0 0 0 10px, + 10px -10px 0 10px, + 32px 0 0 20px, + 0px 32px 0 20px, + -5px 5px 0 10px, + 20px -12px 0 11px; } } @keyframes rippleOn { 0% { @@ -7941,7 +7982,7 @@ form { .form-control, .is-focused .form-control { - background-image: linear-gradient(to top, #9c27b0 2px, rgba(156, 39, 176, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px); } + background-image: linear-gradient(to top, #273746 2px, rgba(52, 73, 94, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px); } .form-control:invalid { background-image: linear-gradient(to top, #f44336 2px, rgba(244, 67, 54, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px); } @@ -7956,15 +7997,15 @@ fieldset[disabled][disabled] .form-control, .form-control.disabled, .form-contro .form-control.form-control-success, .is-focused .form-control.form-control-success { - background-image: linear-gradient(to top, #9c27b0 2px, rgba(156, 39, 176, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px), "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg=="; } + background-image: linear-gradient(to top, #273746 2px, rgba(52, 73, 94, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px), "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg=="; } .form-control.form-control-warning, .is-focused .form-control.form-control-warning { - background-image: linear-gradient(to top, #9c27b0 2px, rgba(156, 39, 176, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px), "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjZjBhZDRlIiBkPSJNNjAzIDY0MC4ybC0yNzguNS01MDljLTMuOC02LjYtMTAuOC0xMC42LTE4LjUtMTAuNnMtMTQuNyA0LTE4LjUgMTAuNkw5IDY0MC4yYy0zLjcgNi41LTMuNiAxNC40LjIgMjAuOCAzLjggNi41IDEwLjggMTAuNCAxOC4zIDEwLjRoNTU3YzcuNiAwIDE0LjYtNCAxOC40LTEwLjQgMy41LTYuNCAzLjYtMTQuNCAwLTIwLjh6bS0yNjYuNC0zMGgtNjEuMlY1NDloNjEuMnY2MS4yem0wLTEwN2gtNjEuMlYzMDRoNjEuMnYxOTl6Ii8+PC9zdmc+"; } + background-image: linear-gradient(to top, #273746 2px, rgba(52, 73, 94, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px), "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjZjBhZDRlIiBkPSJNNjAzIDY0MC4ybC0yNzguNS01MDljLTMuOC02LjYtMTAuOC0xMC42LTE4LjUtMTAuNnMtMTQuNyA0LTE4LjUgMTAuNkw5IDY0MC4yYy0zLjcgNi41LTMuNiAxNC40LjIgMjAuOCAzLjggNi41IDEwLjggMTAuNCAxOC4zIDEwLjRoNTU3YzcuNiAwIDE0LjYtNCAxOC40LTEwLjQgMy41LTYuNCAzLjYtMTQuNCAwLTIwLjh6bS0yNjYuNC0zMGgtNjEuMlY1NDloNjEuMnY2MS4yem0wLTEwN2gtNjEuMlYzMDRoNjEuMnYxOTl6Ii8+PC9zdmc+"; } .form-control.form-control-danger, .is-focused .form-control.form-control-danger { - background-image: linear-gradient(to top, #9c27b0 2px, rgba(156, 39, 176, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px), "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjZDk1MzRmIiBkPSJNNDQ3IDU0NC40Yy0xNC40IDE0LjQtMzcuNiAxNC40LTUyIDBsLTg5LTkyLjctODkgOTIuN2MtMTQuNSAxNC40LTM3LjcgMTQuNC01MiAwLTE0LjQtMTQuNC0xNC40LTM3LjYgMC01Mmw5Mi40LTk2LjMtOTIuNC05Ni4zYy0xNC40LTE0LjQtMTQuNC0zNy42IDAtNTJzMzcuNi0xNC4zIDUyIDBsODkgOTIuOCA4OS4yLTkyLjdjMTQuNC0xNC40IDM3LjYtMTQuNCA1MiAwIDE0LjMgMTQuNCAxNC4zIDM3LjYgMCA1MkwzNTQuNiAzOTZsOTIuNCA5Ni40YzE0LjQgMTQuNCAxNC40IDM3LjYgMCA1MnoiLz48L3N2Zz4="; } + background-image: linear-gradient(to top, #273746 2px, rgba(52, 73, 94, 0) 2px), linear-gradient(to top, #d2d2d2 1px, rgba(210, 210, 210, 0) 1px), "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjZDk1MzRmIiBkPSJNNDQ3IDU0NC40Yy0xNC40IDE0LjQtMzcuNiAxNC40LTUyIDBsLTg5LTkyLjctODkgOTIuN2MtMTQuNSAxNC40LTM3LjcgMTQuNC01MiAwLTE0LjQtMTQuNC0xNC40LTM3LjYgMC01Mmw5Mi40LTk2LjMtOTIuNC05Ni4zYy0xNC40LTE0LjQtMTQuNC0zNy42IDAtNTJzMzcuNi0xNC4zIDUyIDBsODkgOTIuOCA4OS4yLTkyLjdjMTQuNC0xNC40IDM3LjYtMTQuNCA1MiAwIDE0LjMgMTQuNCAxNC4zIDM3LjYgMCA1MkwzNTQuNiAzOTZsOTIuNCA5Ni40YzE0LjQgMTQuNCAxNC40IDM3LjYgMCA1MnoiLz48L3N2Zz4="; } .is-focused .valid-feedback { display: none; @@ -8045,7 +8086,7 @@ fieldset[disabled][disabled] .form-control, .form-control.disabled, .form-contro .is-focused [class^='bmd-label'], .is-focused [class*=' bmd-label'] { - color: #9c27b0; } + color: #273746; } .is-focused .bmd-label-placeholder { color: #999999; } @@ -9206,12 +9247,12 @@ fieldset[disabled] .form-group .form-control { flex: 1; } .navbar.bg-primary { color: #fff; - background-color: #9c27b0 !important; - box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 12px -5px rgba(156, 39, 176, 0.46); } + background-color: #273746 !important; + box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 12px -5px rgba(52, 73, 94, 0.46); } .navbar.bg-primary .dropdown-item:hover, .navbar.bg-primary .dropdown-item:focus { - box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(156, 39, 176, 0.4); - background-color: #9c27b0; + box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(52, 73, 94, 0.4); + background-color: #273746; color: #fff; } .navbar.bg-primary .navbar-toggler .navbar-toggler-icon { background-color: #fff; } @@ -9421,9 +9462,9 @@ fieldset[disabled] .form-group .form-control { .alert.alert-info i { color: #00bcd4; } .alert.alert-primary { - box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(156, 39, 176, 0.4); } + box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(52, 73, 94, 0.4); } .alert.alert-primary i { - color: #9c27b0; } + color: #273746; } .alert.alert-rose { box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(233, 30, 99, 0.4); } .alert.alert-rose i { @@ -9585,7 +9626,7 @@ h2.title { color: #ff9800 !important; } .text-primary { - color: #9c27b0 !important; } + color: #273746 !important; } .text-danger { color: #f44336 !important; } @@ -9642,9 +9683,9 @@ h2.title { color: #555555; } .nav-tabs .nav-link.active { color: #333333; - border-color: #9c27b0; } + border-color: #273746; } .nav-tabs .nav-link.active:hover, .nav-tabs .nav-link.active:focus { - border-color: #9c27b0; } + border-color: #273746; } .nav-tabs .nav-link.disabled { color: #999999; } .nav-tabs .nav-link.disabled, .nav-tabs .nav-link.disabled:hover, .nav-tabs .nav-link.disabled:focus { @@ -9817,8 +9858,8 @@ h2.title { .dropdown-menu a:hover, .dropdown-menu a:focus, .dropdown-menu a:active { - box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(156, 39, 176, 0.4); - background-color: #9c27b0; + box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(52, 73, 94, 0.4); + background-color: #273746; color: #FFFFFF; } a[data-toggle="collapse"][aria-expanded="true"] .caret, @@ -9937,11 +9978,11 @@ a[aria-expanded="true"] .caret, .togglebutton label input[type=checkbox]:checked + .toggle:after { left: 15px; } .togglebutton label input[type=checkbox]:checked + .toggle { - background-color: rgba(156, 39, 176, 0.7); } + background-color: rgba(52, 73, 94, 0.7); } .togglebutton label input[type=checkbox]:checked + .toggle:after { - border-color: #9c27b0; } + border-color: #273746; } .togglebutton label input[type=checkbox]:checked + .toggle:active:after { - box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.4), 0 0 0 15px rgba(156, 39, 176, 0.1); } + box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.4), 0 0 0 15px rgba(52, 73, 94, 0.1); } .ripple { position: relative; } @@ -10264,8 +10305,8 @@ a[aria-expanded="true"] .caret, .sidebar[data-background-color="black"] .nav li .dropdown-menu .dropdown-item { color: #fff; } .sidebar[data-color="purple"] li.active > a { - background-color: #9c27b0; - box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(156, 39, 176, 0.4); } + background-color: #273746; + box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(52, 73, 94, 0.4); } .sidebar[data-color="azure"] li.active > a { background-color: #00bcd4; box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(0, 188, 212, 0.4); } @@ -10547,24 +10588,24 @@ a[aria-expanded="true"] .caret, will-change: box-shadow, transform; } .fixed-plugin .btn.btn-primary { color: #fff; - background-color: #9c27b0; - border-color: #9c27b0; - box-shadow: 0 2px 2px 0 rgba(156, 39, 176, 0.14), 0 3px 1px -2px rgba(156, 39, 176, 0.2), 0 1px 5px 0 rgba(156, 39, 176, 0.12); } + background-color: #273746; + border-color: #273746; + box-shadow: 0 2px 2px 0 rgba(52, 73, 94, 0.14), 0 3px 1px -2px rgba(52, 73, 94, 0.2), 0 1px 5px 0 rgba(52, 73, 94, 0.12); } .fixed-plugin .btn.btn-primary:hover { color: #fff; - background-color: #9124a3; - border-color: #701c7e; } + background-color: #34495E; + border-color: #424949; } .fixed-plugin .btn.btn-primary:focus, .fixed-plugin .btn.btn-primary.focus, .fixed-plugin .btn.btn-primary:hover { color: #fff; - background-color: #9124a3; - border-color: #701c7e; } + background-color: #34495E; + border-color: #424949; } .fixed-plugin .btn.btn-primary:active, .fixed-plugin .btn.btn-primary.active, .open > .fixed-plugin .btn.btn-primary.dropdown-toggle, .show > .fixed-plugin .btn.btn-primary.dropdown-toggle { color: #fff; - background-color: #9124a3; - border-color: #701c7e; - box-shadow: 0 2px 2px 0 rgba(156, 39, 176, 0.14), 0 3px 1px -2px rgba(156, 39, 176, 0.2), 0 1px 5px 0 rgba(156, 39, 176, 0.12); } + background-color: #34495E; + border-color: #424949; + box-shadow: 0 2px 2px 0 rgba(52, 73, 94, 0.14), 0 3px 1px -2px rgba(52, 73, 94, 0.2), 0 1px 5px 0 rgba(52, 73, 94, 0.12); } .fixed-plugin .btn.btn-primary:active:hover, .fixed-plugin .btn.btn-primary:active:focus, .fixed-plugin .btn.btn-primary:active.focus, .fixed-plugin .btn.btn-primary.active:hover, .fixed-plugin .btn.btn-primary.active:focus, .fixed-plugin .btn.btn-primary.active.focus, .open > .fixed-plugin .btn.btn-primary.dropdown-toggle:hover, .open > .fixed-plugin .btn.btn-primary.dropdown-toggle:focus, @@ -10573,28 +10614,28 @@ a[aria-expanded="true"] .caret, .show > .fixed-plugin .btn.btn-primary.dropdown-toggle:focus, .show > .fixed-plugin .btn.btn-primary.dropdown-toggle.focus { color: #fff; - background-color: #9124a3; + background-color: #34495E; border-color: #3f1048; } .open > .fixed-plugin .btn.btn-primary.dropdown-toggle.bmd-btn-icon { color: inherit; - background-color: #9c27b0; } + background-color: #273746; } .open > .fixed-plugin .btn.btn-primary.dropdown-toggle.bmd-btn-icon:hover { - background-color: #9124a3; } + background-color: #34495E; } .fixed-plugin .btn.btn-primary.disabled:focus, .fixed-plugin .btn.btn-primary.disabled.focus, .fixed-plugin .btn.btn-primary:disabled:focus, .fixed-plugin .btn.btn-primary:disabled.focus { - background-color: #9c27b0; - border-color: #9c27b0; } + background-color: #273746; + border-color: #273746; } .fixed-plugin .btn.btn-primary.disabled:hover, .fixed-plugin .btn.btn-primary:disabled:hover { - background-color: #9c27b0; - border-color: #9c27b0; } + background-color: #273746; + border-color: #273746; } .fixed-plugin .btn.btn-primary:focus, .fixed-plugin .btn.btn-primary:active, .fixed-plugin .btn.btn-primary:hover { - box-shadow: 0 14px 26px -12px rgba(156, 39, 176, 0.42), 0 4px 23px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(156, 39, 176, 0.2); } + box-shadow: 0 14px 26px -12px rgba(52, 73, 94, 0.42), 0 4px 23px 0px rgba(0, 0, 0, 0.12), 0 8px 10px -5px rgba(52, 73, 94, 0.2); } .fixed-plugin .btn.btn-primary.btn-link { background-color: transparent; - color: #9c27b0; + color: #273746; box-shadow: none; } .fixed-plugin .btn.btn-primary.btn-link:hover, .fixed-plugin .btn.btn-primary.btn-link:focus, .fixed-plugin .btn.btn-primary.btn-link:active { background-color: transparent; - color: #9c27b0; } + color: #273746; } .fixed-plugin .btn.btn-secondary { color: #333333; background-color: #fafafa; @@ -11242,7 +11283,7 @@ legend { outline: 0; } a { - color: #9c27b0; } + color: #273746; } a:hover, a:focus { color: #89229b; text-decoration: none; } @@ -11314,7 +11355,7 @@ label { padding: 3px 7px; font-size: 8px; line-height: 9px; - background-color: #9c27b0; } + background-color: #273746; } .bootstrap-datetimepicker-widget .timepicker .table-condesed .btn .ripple-container { width: 40px; @@ -11559,7 +11600,7 @@ html[dir="rtl"] .form-check .form-check-sign .check:before { .card .card-header-primary:not(.card-header-icon):not(.card-header-text), .card.bg-primary, .card.card-rotate.bg-primary .front, .card.card-rotate.bg-primary .back { - background: linear-gradient(60deg, #ab47bc, #8e24aa); } + background: linear-gradient(60deg, #34495E, #2C3E50); } .card .card-header-info .card-icon, .card .card-header-info .card-text, .card .card-header-info:not(.card-header-icon):not(.card-header-text), .card.bg-info, @@ -11593,7 +11634,7 @@ html[dir="rtl"] .form-check .form-check-sign .check:before { .card .card-header-primary .card-icon, .card .card-header-primary:not(.card-header-icon):not(.card-header-text), .card .card-header-primary .card-text { - box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(156, 39, 176, 0.4); } + box-shadow: 0 4px 20px 0px rgba(0, 0, 0, 0.14), 0 7px 10px -5px rgba(52, 73, 94, 0.4); } .card .card-header-danger .card-icon, .card .card-header-danger:not(.card-header-icon):not(.card-header-text), .card .card-header-danger .card-text { @@ -11954,11 +11995,11 @@ html[dir="rtl"] .form-check .form-check-sign .check:before { padding-right: 5px; background-color: transparent; } -/* -Animate.css - http://daneden.me/animate -Licensed under the MIT license - http://opensource.org/licenses/MIT - -Copyright (c) 2015 Daniel Eden +/* +Animate.css - http://daneden.me/animate +Licensed under the MIT license - http://opensource.org/licenses/MIT + +Copyright (c) 2015 Daniel Eden */ .animated { animation-duration: 1s; diff --git a/apps/templates/accounts/login.html b/apps/templates/accounts/login.html index 949a44e..43e8697 100644 --- a/apps/templates/accounts/login.html +++ b/apps/templates/accounts/login.html @@ -1,6 +1,6 @@ {% extends "layouts/base.html" %} -{% block title %} Login {% endblock %} +{% block title %} Iniciar sesion {% endblock %} {% block stylesheets %}{% endblock stylesheets %} @@ -12,7 +12,7 @@

- Login + INICIAR SESIÓN

@@ -21,20 +21,20 @@
{% if msg %} {{ msg | safe }} {% else %} - Add your credentials + Inicia sesión {% endif %}

- - {% csrf_token %} + + {% csrf_token %}
- + {{ form.username }}
@@ -45,7 +45,7 @@
- + {{ form.password }}
@@ -57,7 +57,7 @@
    - Don't have an account? Create + No tienes cuenta? Crear
diff --git a/apps/templates/home/calendar.html b/apps/templates/home/calendar.html new file mode 100644 index 0000000..db715d6 --- /dev/null +++ b/apps/templates/home/calendar.html @@ -0,0 +1,119 @@ +{% extends "layouts/base.html" %} + +{% block title %} Calendario {% endblock %} + + +{% block stylesheets %} + + + +{% endblock stylesheets %} + +{% block content %} +
+
+
+

Calendario

+

+
+
+
+
+
+
+
+
+ + + +{% endblock content %} + +{% block javascripts %} + + + + + + + + +{% endblock javascripts %} \ No newline at end of file diff --git a/apps/templates/home/detalle_inventario.html b/apps/templates/home/detalle_inventario.html new file mode 100644 index 0000000..7e18db1 --- /dev/null +++ b/apps/templates/home/detalle_inventario.html @@ -0,0 +1,13 @@ +{% extends "layouts/base.html" %} + +{% block title %}detalles inventario{% endblock %} +{% block title_detail %} Detalle{% endblock %} + +{% block content%} + +
+
+ +
+
+{% endblock content%} \ No newline at end of file diff --git a/apps/templates/home/index.html b/apps/templates/home/index.html index 7ad7465..f759f8e 100644 --- a/apps/templates/home/index.html +++ b/apps/templates/home/index.html @@ -3,31 +3,33 @@ {% block title %} Dashboard {% endblock %} -{% block stylesheets %}{% endblock stylesheets %} +{% block stylesheets %} + + +{% endblock stylesheets %} {% block content %} - +
-
+
- content_copy +
-

Used Space

-

49/50 - GB +

Total en inventario

+

{{ total_inventario }} + Unidades

-
+
@@ -37,381 +39,62 @@

49/50

$34,245

-
-
-
-
-
-
- info_outline -
-

Fixed Issues

-

75

-
- -
-
-
-
-
-
- -
-

Followers

-

+245

-
-
-
-
-
-
-
-
-
-

Daily Sales

-

- 55% increase in today sales.

-
- -
-
-
-
-
-
-
-
-

Email Subscriptions

-

Last Campaign Performance

-
- + + +
+
Graficos
+

-
-
-
-
-
-
-
-

Completed Tasks

-

Last Campaign Performance

-
-
+ +
-
+
- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
Sign contract for "What are conference organizers afraid of?" - - -
-
- -
-
Lines From Great Russian Literature? Or E-mails From My Boss? - - -
-
- -
-
Flooded: One year later, assessing what was lost and what was found when a ravaging rain swept through metro Detroit - - - -
-
- -
-
Create 4 Invisible User Experiences you Never Knew About - - -
-
-
- - - - - - - - - - - - - -
-
- -
-
Flooded: One year later, assessing what was lost and what was found when a ravaging rain swept through metro Detroit - - - -
-
- -
-
Sign contract for "What are conference organizers afraid of?" - - -
-
-
- - - - - - - - - - - - - - - - - - -
-
- -
-
Lines From Great Russian Literature? Or E-mails From My Boss? - - -
-
- -
-
Flooded: One year later, assessing what was lost and what was found when a ravaging rain swept through metro Detroit - - - -
-
- -
-
Sign contract for "What are conference organizers afraid of?" - - -
-
-
-
-
-
-
-
-
-

Employees Stats

-

New employees on 15th September, 2016

+
+

Inventario

+

- - +
+ - - - + + + + + {% for inv in inventario %} - - - - - - - - - - - - - - - - - - - - - - + + + + + + {% endfor %}
IDNameSalaryCountryNombreDescripcionCantidadprecio
1Dakota Rice$36,738Niger
2Minerva Hooper$23,789Curaçao
3Sage Rodriguez$56,142Netherlands
4Philip Chaney$38,735Korea, South{{ inv.id }}{{ inv.nombre }}{{ inv.descripcion }}{{ inv.cantidad }}{{ inv.precio }}
@@ -421,15 +104,144 @@

Employees Stats

{% endblock content %} - {% block javascripts %} - + + + +// ------------Grafico de Linea---------------- +fetch("{% url 'home:inventario_chart' %}") + .then(response => response.json()) + .then(data => { + const ctx = document.getElementById('graficoInventarioLinea').getContext('2d'); + const cantidades = data.cantidades; + + // Generar una lista de colores aleatorios con la misma longitud que las cantidades + const coloresAleatorios = cantidades.map(generarColorAleatorio); + + const chart = new Chart(ctx, { + type: 'line', // Cambiar el tipo de gráfico a line chart (línea) + data: { + labels: data.categorias, // Etiquetas para el eje X (categorías) + datasets: [{ + label: 'Cantidad de inventario', + data: cantidades, // Datos de las cantidades + fill: false, // No rellenar el área bajo la línea + backgroundColor: coloresAleatorios[0], // Color de fondo de la línea + borderColor: coloresAleatorios[1], // Color de la línea + borderWidth: 1 // Ancho de la línea + }] + }, + options: { + responsive: true, // Habilitar la responsividad + maintainAspectRatio: false, // Desactivar la relación de aspecto fijo + scales: { + x: { + display: true // Mostrar el eje X + }, + y: { + beginAtZero: true // Comenzar el eje Y desde el valor 0 + } + } + } + }); + }); + + {% endblock javascripts %} diff --git a/apps/templates/home/listar_inventario.html b/apps/templates/home/listar_inventario.html new file mode 100644 index 0000000..6fcb6a9 --- /dev/null +++ b/apps/templates/home/listar_inventario.html @@ -0,0 +1,6 @@ +{% extends "layouts/base_list.html" %} + +{% block title %}Listar Inventario{% endblock %} + +{% block title_module %}VISAGGE INVENTARIO{% endblock %} +{% block title_table %}Inventario{% endblock %} \ No newline at end of file diff --git a/apps/templates/home/page-rtl-support.html b/apps/templates/home/page-rtl-support.html deleted file mode 100644 index bd6e122..0000000 --- a/apps/templates/home/page-rtl-support.html +++ /dev/null @@ -1,500 +0,0 @@ -{% extends "layouts/base-rtl.html" %} - -{% block title %} داشبورد متریال توسط تیم خلاق {% endblock %} - - -{% block stylesheets %} - - - - -{% endblock stylesheets %} - -{% block content %} - -
- -
-
-
-
- content_copy -
-

فضا مصرف شده

-

49/50 - GB -

-
- -
-
-
-
-
-
- store -
-

سود

-

$34,245

-
- -
-
-
-
-
-
- info_outline -
-

مشکلات حل شده

-

75

-
- -
-
-
-
-
-
- -
-

دنبال‌کننده

-

+245

-
- -
-
-
-
-
-
-
-
-
-
-

فروش روزانه

-

- - 55% رشد در فروش امروز.

-
- -
-
-
-
-
-
-
-
-

دنبال کننده‌های ایمیلی

-

کارایی آخرین کمپین

-
- -
-
-
-
-
-
-
-
-

وظایف انجام شده

-

کارایی آخرین کمپین

-
- -
-
-
-
-
-
- -
-
-
- - - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
طراح گرافیک از این متن به عنوان عنصری از ترکیب بندی برای پر کردن؟ - - -
-
- -
-
نخست از متن‌های آزمایشی و بی‌معنی استفاده می‌کنند تا صرفا به مشتری یا صاحب کار خود نشان دهند؟ - - -
-
- -
-
همان حال کار آنها به نوعی وابسته به متن می‌باشد - - - -
-
- -
-
آنها با استفاده از محتویات ساختگی، صفحه گرافیکی خود را صفحه‌آرایی می‌کنند - - -
-
-
- - - - - - - - - - - - - -
-
- -
-
بعد از اینکه متن در آن قرار گیرد چگونه به نظر می‌رسد و قلم‌ها و اندازه‌بندی‌ها چگونه در نظر گرفته - - - -
-
- -
-
اولیه شکل ظاهری و کلی طرح سفارش گرفته شده استفاده می نماید؟ - - -
-
-
- - - - - - - - - - - - - - - - - - -
-
- -
-
گرافیکی نشانگر چگونگی نوع و اندازه فونت و ظاهر متن باشد. معمولا طراحان گرافیک برای صفحه‌آرایی، نخست از متن‌های آزمایشی؟ - - -
-
- -
-
از این متن به عنوان عنصری از ترکیب بندی برای پر کردن صفحه و ارایه اولیه شکل ظاهری و کلی طرح سفارش گرفته شده استفاده می نماید، تا از نظر گرافیکی نشانگر چگونگی نوع و اندازه فونت و ظاهر متن باشد. معمولا طراحان گرافیک برای صفحه‌آرایی، نخست از متن‌های آزمایشی ؟ - - - -
-
- -
-
از متن‌های آزمایشی و بی‌معنی استفاده می‌کنند تا صرفا به مشتری یا صاحب کار خود نشان دهند؟ - - -
-
-
-
-
-
-
-
-
-

آمار کارکنان

-

کارکنان جدید از ۱۵ آبان ۱۳۹۶

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
کدنامحقوقاستان
1احمد حسینی$36,738مازندران
2مینا رضایی$23,789گلستان
3مبینا احمدپور$56,142تهران
4جلال آقایی$38,735شهرکرد
-
-
-
-
-
-
-
-
-

اعلان ها

-

ایجاد شده توسط دوست ما - Robert McIntosh. لطفا - مستندات کامل را مشاهده بکنید. -

-
-
-
- - - این یک اعلان است که با کلاس "alert-warning" ایجاد شده است. -
-
- - - این یک اعلان است که با کلاس "alert-primary" ایجاد شده است. -
-
- add_alert - - این یک اعلان با دکمه بستن و آیکن است -
-
-
-
-
-
-
- - - -
-
-
مدیرعامل / مدیرفنی
-

خداداد عزیزی

-

- طراح گرافیک از این متن به عنوان عنصری از ترکیب بندی برای پر کردن صفحه و ارایه اولیه شکل ظاهری و کلی طرح سفارش گرفته شده استفاده می نماید، تا از نظر گرافیکی نشانگر چگونگی نوع و اندازه فونت و ظاهر متن باشد. معمولا طراحان گرافیک برای صفحه‌آرایی، نخست از متن‌های آزمایشی و بی‌معنی استفاده می‌کنند ... -

- دنبال‌کردن -
-
- -
-
- -{% endblock content %} - - -{% block javascripts %}{% endblock javascripts %} diff --git a/apps/templates/home/registrar_inventario_form.html b/apps/templates/home/registrar_inventario_form.html new file mode 100644 index 0000000..dc49ff3 --- /dev/null +++ b/apps/templates/home/registrar_inventario_form.html @@ -0,0 +1,50 @@ +{% extends "layouts/base.html" %} + +{% block title %} Registrar inventario {% endblock %} + + +{% block stylesheets %}{% endblock stylesheets %} +{% block titulo_form %}Registrar Invetario{% endblock %} + +{% block title_module %}VISAGGE INVENTARIO{% endblock %} + +{% block content_form %} + +
+ {% csrf_token %} +
+
+ {{ form.nombre.label_tag }} + {{ form.nombre }} +
+
+ {{ form.descripcion.label_tag }} + {{ form.descripcion }} +
+
+
+
+ {{ form.precio.label_tag }} + {{ form.precio }} +
+
+ {{ form.estado.label_tag }} + {{ form.estado }} +
+
+
+
+ {{ form.categoria.label_tag }} + {{ form.categoria }} +
+
+ {{ form.cantidad.label_tag }} + {{ form.cantidad }} +
+
+ +
+ +{% endblock %} + +{% block javascripts %}{% endblock javascripts %} diff --git a/apps/templates/home/ui-tables.html b/apps/templates/home/ui-tables.html deleted file mode 100644 index 400ca3b..0000000 --- a/apps/templates/home/ui-tables.html +++ /dev/null @@ -1,286 +0,0 @@ -{% extends "layouts/base.html" %} - -{% block title %} UI Tables {% endblock %} - - -{% block stylesheets %}{% endblock stylesheets %} - -{% block content %} - -
-
-
-
-

Simple Table

-

Here is a subtitle for this table

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ID - - Name - - Country - - City - - Salary -
- 1 - - Dakota Rice - - Niger - - Oud-Turnhout - - $36,738 -
- 2 - - Minerva Hooper - - Curaçao - - Sinaai-Waas - - $23,789 -
- 3 - - Sage Rodriguez - - Netherlands - - Baileux - - $56,142 -
- 4 - - Philip Chaney - - Korea, South - - Overland Park - - $38,735 -
- 5 - - Doris Greene - - Malawi - - Feldkirchen in Kärnten - - $63,542 -
- 6 - - Mason Porter - - Chile - - Gloucester - - $78,615 -
-
-
-
-
-
-
-
-

Table on Plain Background

-

Here is a subtitle for this table

-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ID - - Name - - Country - - City - - Salary -
- 1 - - Dakota Rice - - Niger - - Oud-Turnhout - - $36,738 -
- 2 - - Minerva Hooper - - Curaçao - - Sinaai-Waas - - $23,789 -
- 3 - - Sage Rodriguez - - Netherlands - - Baileux - - $56,142 -
- 4 - - Philip Chaney - - Korea, South - - Overland Park - - $38,735 -
- 5 - - Doris Greene - - Malawi - - Feldkirchen in Kärnten - - $63,542 -
- 6 - - Mason Porter - - Chile - - Gloucester - - $78,615 -
-
-
-
-
-
- -{% endblock content %} - - -{% block javascripts %}{% endblock javascripts %} diff --git a/apps/templates/home/ui-typography.html b/apps/templates/home/ui-typography.html deleted file mode 100644 index 3d957ed..0000000 --- a/apps/templates/home/ui-typography.html +++ /dev/null @@ -1,109 +0,0 @@ -{% extends "layouts/base.html" %} - -{% block title %} UI Typography {% endblock %} - - -{% block stylesheets %}{% endblock stylesheets %} - -{% block content %} - -
-
-

Material Dashboard Heading

-

Created using Roboto Font Family

-
-
-
-
-

Typography

-
-
-
-

- Header 1The Life of Material Dashboard

-
-
-

- Header 2The Life of Material Dashboard

-
-
-

- Header 3The Life of Material Dashboard

-
-
-

- Header 4The Life of Material Dashboard

-
-
-
- Header 5The Life of Material Dashboard
-
-
-
- Header 6The Life of Material Dashboard
-
-
-

- Paragraph - I will be the leader of a company that ends up being worth billions of dollars, because I got the answers. I understand culture. I am the nucleus. I think that’s a responsibility that I have, to push possibilities, to show people, this is the level that things could be at.

-
-
- Quote -
-

- I will be the leader of a company that ends up being worth billions of dollars, because I got the answers. I understand culture. I am the nucleus. I think that’s a responsibility that I have, to push possibilities, to show people, this is the level that things could be at. -

- - Kanye West, Musician - -
-
-
- Muted Text -

- I will be the leader of a company that ends up being worth billions of dollars, because I got the answers... -

-
-
- Primary Text -

- I will be the leader of a company that ends up being worth billions of dollars, because I got the answers...

-
-
- Info Text -

- I will be the leader of a company that ends up being worth billions of dollars, because I got the answers...

-
-
- Success Text -

- I will be the leader of a company that ends up being worth billions of dollars, because I got the answers...

-
-
- Warning Text -

- I will be the leader of a company that ends up being worth billions of dollars, because I got the answers... -

-
-
- Danger Text -

- I will be the leader of a company that ends up being worth billions of dollars, because I got the answers...

-
-
-

- Small Tag - Header with small subtitle -
- Use "small" tag for the headers -

-
-
-
-
-
- -{% endblock content %} - - -{% block javascripts %}{% endblock javascripts %} diff --git a/apps/templates/includes/footer.html b/apps/templates/includes/footer.html index c215041..f62f739 100644 --- a/apps/templates/includes/footer.html +++ b/apps/templates/includes/footer.html @@ -6,18 +6,21 @@
+ + diff --git a/apps/templates/includes/navigation.html b/apps/templates/includes/navigation.html index 15faff6..65944cf 100644 --- a/apps/templates/includes/navigation.html +++ b/apps/templates/includes/navigation.html @@ -2,19 +2,10 @@ + diff --git a/apps/templates/includes/sidebar.html b/apps/templates/includes/sidebar.html index cc5d0d5..c1cc642 100644 --- a/apps/templates/includes/sidebar.html +++ b/apps/templates/includes/sidebar.html @@ -1,8 +1,7 @@
- {% include 'includes/fixed-plugin.html' %} +
+
+
+
+
+ + {% include 'includes/scripts.html' %} @@ -73,6 +163,26 @@ {% block javascripts %}{% endblock javascripts %} - + + + + + diff --git a/apps/templates/layouts/base_list.html b/apps/templates/layouts/base_list.html new file mode 100644 index 0000000..7f37922 --- /dev/null +++ b/apps/templates/layouts/base_list.html @@ -0,0 +1,250 @@ +{% extends "layouts/base.html" %} +{% load custom_tags %} + + +{% block title %}{% endblock %} + + +{% block stylesheets %} + + + +{% endblock stylesheets %} + +{% block content %} + +
+
+

{% block title_module %}{% endblock %}

+
+
+

{% block title_table %}{% endblock %}

+
+
+ {% if actions %} + + {% endif %} + + + + {% for column_name in column_names %} + + {% endfor %} + + + {% for _ in column_names %} + + {% endfor %} + + + + {% for atr in models %} + + {% for field in fields %} + + {% endfor %} + + {% endfor %} + +
{{ column_name }}
{{ atr|get_field_value:field }}
+
+
+
+
+ + + + +{% endblock content %} + + +{% block javascripts %} + + + + + + + + + + +{% endblock javascripts %} diff --git a/core/settings.py b/core/settings.py index a03adb5..d23d613 100644 --- a/core/settings.py +++ b/core/settings.py @@ -1,4 +1,4 @@ -# -*- encoding: utf-8 -*- +# -*- encoding: utf-8 -*-🥰 """ Copyright (c) 2019 - present AppSeed.us """ @@ -6,6 +6,7 @@ import os from decouple import config from unipath import Path +from django.urls import reverse_lazy # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = Path(__file__).parent @@ -15,10 +16,12 @@ SECRET_KEY = config('SECRET_KEY', default='S#perS3crEt_1122') # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = config('DEBUG', default=True, cast=bool) +DEBUG = config('false', default=True, cast=bool) # load production server from .env -ALLOWED_HOSTS = ['localhost', '127.0.0.1', config('SERVER', default='127.0.0.1')] +ALLOWED_HOSTS = ['*'] + +DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' # Application definition @@ -29,7 +32,8 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'apps.home' # Enable the inner home (home) + 'apps.home', + 'schedule', ] MIDDLEWARE = [ @@ -43,9 +47,10 @@ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] + ROOT_URLCONF = 'core.urls' -LOGIN_REDIRECT_URL = "home" # Route defined in home/urls.py -LOGOUT_REDIRECT_URL = "home" # Route defined in home/urls.py +LOGIN_REDIRECT_URL = reverse_lazy('inicio') +LOGOUT_REDIRECT_URL = reverse_lazy('login') TEMPLATE_DIR = os.path.join(CORE_DIR, "apps/templates") # ROOT dir for templates TEMPLATES = [ @@ -71,11 +76,16 @@ DATABASES = { 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': 'db.sqlite3', + 'ENGINE': 'django.db.backends.postgresql', + 'NAME': 'plantilla', + 'USER': 'postgres', + 'PASSWORD': 'postgres', + 'HOST': 'localhost', + 'PORT': '', } } + # Password validation # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators From 56fa5eb6e0208dfe29f450eb772df2f0af0ebe3b Mon Sep 17 00:00:00 2001 From: espinosa98 Date: Tue, 8 Aug 2023 16:47:39 -0500 Subject: [PATCH 2/3] HT-01 Ajuset en calendario --- apps/home/forms.py | 4 +- apps/home/models.py | 3 +- apps/home/urls.py | 1 + apps/home/views.py | 26 ++++- apps/templates/home/calendar.html | 98 ++++++++++++++++--- apps/templates/layouts/base.html | 23 +++-- .../templates/{home => layouts}/page-403.html | 0 .../templates/{home => layouts}/page-404.html | 0 .../templates/{home => layouts}/page-500.html | 0 .../{home => layouts}/page-blank.html | 0 core/settings.py | 1 - 11 files changed, 124 insertions(+), 32 deletions(-) rename apps/templates/{home => layouts}/page-403.html (100%) rename apps/templates/{home => layouts}/page-404.html (100%) rename apps/templates/{home => layouts}/page-500.html (100%) rename apps/templates/{home => layouts}/page-blank.html (100%) diff --git a/apps/home/forms.py b/apps/home/forms.py index e25feb7..48490be 100644 --- a/apps/home/forms.py +++ b/apps/home/forms.py @@ -24,14 +24,16 @@ class EventoCalendarioForm(forms.ModelForm): class Meta: model = EventoCaledario - fields = ('titulo', 'descripcion', 'fecha_inicio') + fields = ('titulo', 'descripcion', 'fecha_inicio' , 'fecha_fin') widgets = { 'titulo': forms.TextInput(attrs={'class': 'form-control'}), 'descripcion': forms.TextInput(attrs={'class': 'form-control'}), 'fecha_inicio': forms.DateTimeInput(), + 'fecha_fin': forms.DateTimeInput(), } def __init__(self, *args, **kwargs): super(EventoCalendarioForm, self).__init__(*args, **kwargs) self.fields['fecha_inicio'].widget.attrs.update({'class': 'form-control'}) + self.fields['fecha_fin'].widget.attrs.update({'class': 'form-control'}) diff --git a/apps/home/models.py b/apps/home/models.py index 5d3d0f5..0baa317 100644 --- a/apps/home/models.py +++ b/apps/home/models.py @@ -36,7 +36,8 @@ class EventoCaledario(models.Model): titulo = models.CharField(max_length=100, null=True, blank=True) descripcion = models.CharField(max_length=100, null=True, blank=True) - fecha_inicio = models.DateField(null=True, blank=True) + fecha_inicio = models.DateTimeField(null=True, blank=True) + fecha_fin = models.DateTimeField(null=True, blank=True) usuario = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True) def __str__(self): diff --git a/apps/home/urls.py b/apps/home/urls.py index 99c893b..00f48e0 100644 --- a/apps/home/urls.py +++ b/apps/home/urls.py @@ -22,6 +22,7 @@ #CALENDARIO path('calendario', views.Calendarioview.as_view(), name='calendario'), + path('actualizar-evento', views.UpdateCalendarioView.as_view(), name='actualizar_evento'), # Matches any html file re_path(r'^.*\.*', views.pages, name='pages'), diff --git a/apps/home/views.py b/apps/home/views.py index 9f8c013..2ae4f72 100644 --- a/apps/home/views.py +++ b/apps/home/views.py @@ -12,7 +12,7 @@ from django.template import loader from django.urls import reverse from django.views import View -from django.views.generic import FormView, TemplateView, DetailView +from django.views.generic import FormView, TemplateView, DetailView, UpdateView #Propios from apps.home.forms import * @@ -51,11 +51,11 @@ def pages(request): except template.TemplateDoesNotExist: - html_template = loader.get_template('home/page-404.html') + html_template = loader.get_template('layouts/page-404.html') return HttpResponse(html_template.render(context, request)) except: - html_template = loader.get_template('home/page-500.html') + html_template = loader.get_template('layouts/page-500.html') return HttpResponse(html_template.render(context, request)) @@ -141,12 +141,11 @@ def inventario_chart(request): categorias = list(inventario_por_categoria.keys()) cantidades = list(inventario_por_categoria.values()) - # Retornar los datos en formato JSON return JsonResponse({'categorias': categorias, 'cantidades': cantidades}) + class Calendarioview(TemplateView, FormView): - #crear vista par< mostrar calendario template_name = 'home/calendar.html' form_class = EventoCalendarioForm success_url = '/calendario' @@ -160,11 +159,28 @@ def get_context_data(self, **kwargs): def form_valid(self, form): evento = form.save(commit=False) evento.save() + messages.success(self.request, 'El evento se ha registrado exitosamente.') return super().form_valid(form) def form_invalid(self, form): errors = form.errors + for error in errors: + messages.error(self.request, 'Se ha producido un error en el formulario.') return super().form_invalid(form) +class UpdateCalendarioView(View): + + def post(self, request, *args, **kwargs): + + if request.is_ajax(): + try: + id = request.POST.get('id') + fecha_inicio = request.POST.get('start') + evento = EventoCaledario.objects.get(pk=id) + evento.fecha_inicio = fecha_inicio + evento.save() + return JsonResponse({'status': 'success'}) + except: + return JsonResponse({'status': 'error'}) diff --git a/apps/templates/home/calendar.html b/apps/templates/home/calendar.html index db715d6..05310d3 100644 --- a/apps/templates/home/calendar.html +++ b/apps/templates/home/calendar.html @@ -17,6 +17,10 @@

Calendario

+
@@ -48,6 +52,10 @@ {{ form.fecha_inicio.label_tag }} {{ form.fecha_inicio }}
+
+ {{ form.fecha_fin.label_tag }} + {{ form.fecha_fin }} +
+ + + + {% endblock content %} {% block javascripts %} + + diff --git a/apps/templates/layouts/base.html b/apps/templates/layouts/base.html index eaf10f6..b868c20 100644 --- a/apps/templates/layouts/base.html +++ b/apps/templates/layouts/base.html @@ -107,17 +107,18 @@

{% block title_detail %} {% endblock %}

- {% block content %} - - -
- {% if messages %} + {% if messages %} {% for message in messages %} {% endfor %} {% endif %} + + {% block content %} + + +

{% block title_module %}{% endblock %}

@@ -166,7 +167,7 @@

{% block titulo_form %}{% endblo - diff --git a/apps/templates/home/page-403.html b/apps/templates/layouts/page-403.html similarity index 100% rename from apps/templates/home/page-403.html rename to apps/templates/layouts/page-403.html diff --git a/apps/templates/home/page-404.html b/apps/templates/layouts/page-404.html similarity index 100% rename from apps/templates/home/page-404.html rename to apps/templates/layouts/page-404.html diff --git a/apps/templates/home/page-500.html b/apps/templates/layouts/page-500.html similarity index 100% rename from apps/templates/home/page-500.html rename to apps/templates/layouts/page-500.html diff --git a/apps/templates/home/page-blank.html b/apps/templates/layouts/page-blank.html similarity index 100% rename from apps/templates/home/page-blank.html rename to apps/templates/layouts/page-blank.html diff --git a/core/settings.py b/core/settings.py index d23d613..dd1f299 100644 --- a/core/settings.py +++ b/core/settings.py @@ -33,7 +33,6 @@ 'django.contrib.messages', 'django.contrib.staticfiles', 'apps.home', - 'schedule', ] MIDDLEWARE = [ From 5a68a4614e3acebbb8edffce3624a4ac4d4f6267 Mon Sep 17 00:00:00 2001 From: espinosa98 Date: Tue, 15 Aug 2023 16:49:30 -0500 Subject: [PATCH 3/3] HT-01 Se agrega pagina de inicio --- apps/authentication/urls.py | 1 + apps/home/urls.py | 1 + apps/home/views.py | 4 + .../static/assets/js/ResizeObserver.global.js | 1034 +++++++++++++++++ apps/templates/accounts/login.html | 2 +- apps/templates/includes/navigation.html | 2 +- apps/templates/includes/sidebar.html | 8 +- apps/templates/static_page/static_page.html | 125 ++ core/settings.py | 6 +- 9 files changed, 1177 insertions(+), 6 deletions(-) create mode 100644 apps/static/assets/js/ResizeObserver.global.js create mode 100644 apps/templates/static_page/static_page.html diff --git a/apps/authentication/urls.py b/apps/authentication/urls.py index 1b5c270..dff0329 100644 --- a/apps/authentication/urls.py +++ b/apps/authentication/urls.py @@ -6,6 +6,7 @@ from django.urls import path from .views import login_view, register_user from django.contrib.auth.views import LogoutView +app_name = 'authentication' urlpatterns = [ path('login/', login_view, name="login"), diff --git a/apps/home/urls.py b/apps/home/urls.py index 00f48e0..b9130de 100644 --- a/apps/home/urls.py +++ b/apps/home/urls.py @@ -11,6 +11,7 @@ urlpatterns = [ #Pagina de inicio + path('', views.StaticPageView.as_view(), name='static_page'), path('inicio', views.index.as_view(), name='inicio'), # Inventario path('registrar-inventario', views.RegistrarInventarioView.as_view(), name='registrar_inventario'), diff --git a/apps/home/views.py b/apps/home/views.py index 2ae4f72..e13eeeb 100644 --- a/apps/home/views.py +++ b/apps/home/views.py @@ -183,4 +183,8 @@ def post(self, request, *args, **kwargs): except: return JsonResponse({'status': 'error'}) +class StaticPageView(TemplateView): + + template_name = 'static_page/static_page.html' + diff --git a/apps/static/assets/js/ResizeObserver.global.js b/apps/static/assets/js/ResizeObserver.global.js new file mode 100644 index 0000000..11618f1 --- /dev/null +++ b/apps/static/assets/js/ResizeObserver.global.js @@ -0,0 +1,1034 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global.ResizeObserver = factory()); +}(this, (function () { 'use strict'; + +/** + * A collection of shims that provide minimal functionality of the ES6 collections. + * + * These implementations are not meant to be used outside of the ResizeObserver + * modules as they cover only a limited range of use cases. + */ +/* eslint-disable require-jsdoc, valid-jsdoc */ +var MapShim = (function () { + if (typeof Map !== 'undefined') { + return Map; + } + + /** + * Returns index in provided array that matches the specified key. + * + * @param {Array} arr + * @param {*} key + * @returns {number} + */ + function getIndex(arr, key) { + var result = -1; + + arr.some(function (entry, index) { + if (entry[0] === key) { + result = index; + + return true; + } + + return false; + }); + + return result; + } + + return (function () { + function anonymous() { + this.__entries__ = []; + } + + var prototypeAccessors = { size: { configurable: true } }; + + /** + * @returns {boolean} + */ + prototypeAccessors.size.get = function () { + return this.__entries__.length; + }; + + /** + * @param {*} key + * @returns {*} + */ + anonymous.prototype.get = function (key) { + var index = getIndex(this.__entries__, key); + var entry = this.__entries__[index]; + + return entry && entry[1]; + }; + + /** + * @param {*} key + * @param {*} value + * @returns {void} + */ + anonymous.prototype.set = function (key, value) { + var index = getIndex(this.__entries__, key); + + if (~index) { + this.__entries__[index][1] = value; + } else { + this.__entries__.push([key, value]); + } + }; + + /** + * @param {*} key + * @returns {void} + */ + anonymous.prototype.delete = function (key) { + var entries = this.__entries__; + var index = getIndex(entries, key); + + if (~index) { + entries.splice(index, 1); + } + }; + + /** + * @param {*} key + * @returns {void} + */ + anonymous.prototype.has = function (key) { + return !!~getIndex(this.__entries__, key); + }; + + /** + * @returns {void} + */ + anonymous.prototype.clear = function () { + this.__entries__.splice(0); + }; + + /** + * @param {Function} callback + * @param {*} [ctx=null] + * @returns {void} + */ + anonymous.prototype.forEach = function (callback, ctx) { + var this$1 = this; + if ( ctx === void 0 ) ctx = null; + + for (var i = 0, list = this$1.__entries__; i < list.length; i += 1) { + var entry = list[i]; + + callback.call(ctx, entry[1], entry[0]); + } + }; + + Object.defineProperties( anonymous.prototype, prototypeAccessors ); + + return anonymous; + }()); +})(); + +/** + * Detects whether window and document objects are available in current environment. + */ +var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined' && window.document === document; + +// Returns global object of a current environment. +var global$1 = (function () { + if (typeof global !== 'undefined' && global.Math === Math) { + return global; + } + + if (typeof self !== 'undefined' && self.Math === Math) { + return self; + } + + if (typeof window !== 'undefined' && window.Math === Math) { + return window; + } + + // eslint-disable-next-line no-new-func + return Function('return this')(); +})(); + +/** + * A shim for the requestAnimationFrame which falls back to the setTimeout if + * first one is not supported. + * + * @returns {number} Requests' identifier. + */ +var requestAnimationFrame$1 = (function () { + if (typeof requestAnimationFrame === 'function') { + // It's required to use a bounded function because IE sometimes throws + // an "Invalid calling object" error if rAF is invoked without the global + // object on the left hand side. + return requestAnimationFrame.bind(global$1); + } + + return function (callback) { return setTimeout(function () { return callback(Date.now()); }, 1000 / 60); }; +})(); + +// Defines minimum timeout before adding a trailing call. +var trailingTimeout = 2; + +/** + * Creates a wrapper function which ensures that provided callback will be + * invoked only once during the specified delay period. + * + * @param {Function} callback - Function to be invoked after the delay period. + * @param {number} delay - Delay after which to invoke callback. + * @returns {Function} + */ +var throttle = function (callback, delay) { + var leadingCall = false, + trailingCall = false, + lastCallTime = 0; + + /** + * Invokes the original callback function and schedules new invocation if + * the "proxy" was called during current request. + * + * @returns {void} + */ + function resolvePending() { + if (leadingCall) { + leadingCall = false; + + callback(); + } + + if (trailingCall) { + proxy(); + } + } + + /** + * Callback invoked after the specified delay. It will further postpone + * invocation of the original function delegating it to the + * requestAnimationFrame. + * + * @returns {void} + */ + function timeoutCallback() { + requestAnimationFrame$1(resolvePending); + } + + /** + * Schedules invocation of the original function. + * + * @returns {void} + */ + function proxy() { + var timeStamp = Date.now(); + + if (leadingCall) { + // Reject immediately following calls. + if (timeStamp - lastCallTime < trailingTimeout) { + return; + } + + // Schedule new call to be in invoked when the pending one is resolved. + // This is important for "transitions" which never actually start + // immediately so there is a chance that we might miss one if change + // happens amids the pending invocation. + trailingCall = true; + } else { + leadingCall = true; + trailingCall = false; + + setTimeout(timeoutCallback, delay); + } + + lastCallTime = timeStamp; + } + + return proxy; +}; + +// Minimum delay before invoking the update of observers. +var REFRESH_DELAY = 20; + +// A list of substrings of CSS properties used to find transition events that +// might affect dimensions of observed elements. +var transitionKeys = ['top', 'right', 'bottom', 'left', 'width', 'height', 'size', 'weight']; + +// Check if MutationObserver is available. +var mutationObserverSupported = typeof MutationObserver !== 'undefined'; + +/** + * Singleton controller class which handles updates of ResizeObserver instances. + */ +var ResizeObserverController = function() { + this.connected_ = false; + this.mutationEventsAdded_ = false; + this.mutationsObserver_ = null; + this.observers_ = []; + + this.onTransitionEnd_ = this.onTransitionEnd_.bind(this); + this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY); +}; + +/** + * Adds observer to observers list. + * + * @param {ResizeObserverSPI} observer - Observer to be added. + * @returns {void} + */ + + +/** + * Holds reference to the controller's instance. + * + * @private {ResizeObserverController} + */ + + +/** + * Keeps reference to the instance of MutationObserver. + * + * @private {MutationObserver} + */ + +/** + * Indicates whether DOM listeners have been added. + * + * @private {boolean} + */ +ResizeObserverController.prototype.addObserver = function (observer) { + if (!~this.observers_.indexOf(observer)) { + this.observers_.push(observer); + } + + // Add listeners if they haven't been added yet. + if (!this.connected_) { + this.connect_(); + } +}; + +/** + * Removes observer from observers list. + * + * @param {ResizeObserverSPI} observer - Observer to be removed. + * @returns {void} + */ +ResizeObserverController.prototype.removeObserver = function (observer) { + var observers = this.observers_; + var index = observers.indexOf(observer); + + // Remove observer if it's present in registry. + if (~index) { + observers.splice(index, 1); + } + + // Remove listeners if controller has no connected observers. + if (!observers.length && this.connected_) { + this.disconnect_(); + } +}; + +/** + * Invokes the update of observers. It will continue running updates insofar + * it detects changes. + * + * @returns {void} + */ +ResizeObserverController.prototype.refresh = function () { + var changesDetected = this.updateObservers_(); + + // Continue running updates if changes have been detected as there might + // be future ones caused by CSS transitions. + if (changesDetected) { + this.refresh(); + } +}; + +/** + * Updates every observer from observers list and notifies them of queued + * entries. + * + * @private + * @returns {boolean} Returns "true" if any observer has detected changes in + * dimensions of it's elements. + */ +ResizeObserverController.prototype.updateObservers_ = function () { + // Collect observers that have active observations. + var activeObservers = this.observers_.filter(function (observer) { + return observer.gatherActive(), observer.hasActive(); + }); + + // Deliver notifications in a separate cycle in order to avoid any + // collisions between observers, e.g. when multiple instances of + // ResizeObserver are tracking the same element and the callback of one + // of them changes content dimensions of the observed target. Sometimes + // this may result in notifications being blocked for the rest of observers. + activeObservers.forEach(function (observer) { return observer.broadcastActive(); }); + + return activeObservers.length > 0; +}; + +/** + * Initializes DOM listeners. + * + * @private + * @returns {void} + */ +ResizeObserverController.prototype.connect_ = function () { + // Do nothing if running in a non-browser environment or if listeners + // have been already added. + if (!isBrowser || this.connected_) { + return; + } + + // Subscription to the "Transitionend" event is used as a workaround for + // delayed transitions. This way it's possible to capture at least the + // final state of an element. + document.addEventListener('transitionend', this.onTransitionEnd_); + + window.addEventListener('resize', this.refresh); + + if (mutationObserverSupported) { + this.mutationsObserver_ = new MutationObserver(this.refresh); + + this.mutationsObserver_.observe(document, { + attributes: true, + childList: true, + characterData: true, + subtree: true + }); + } else { + document.addEventListener('DOMSubtreeModified', this.refresh); + + this.mutationEventsAdded_ = true; + } + + this.connected_ = true; +}; + +/** + * Removes DOM listeners. + * + * @private + * @returns {void} + */ +ResizeObserverController.prototype.disconnect_ = function () { + // Do nothing if running in a non-browser environment or if listeners + // have been already removed. + if (!isBrowser || !this.connected_) { + return; + } + + document.removeEventListener('transitionend', this.onTransitionEnd_); + window.removeEventListener('resize', this.refresh); + + if (this.mutationsObserver_) { + this.mutationsObserver_.disconnect(); + } + + if (this.mutationEventsAdded_) { + document.removeEventListener('DOMSubtreeModified', this.refresh); + } + + this.mutationsObserver_ = null; + this.mutationEventsAdded_ = false; + this.connected_ = false; +}; + +/** + * "Transitionend" event handler. + * + * @private + * @param {TransitionEvent} event + * @returns {void} + */ +ResizeObserverController.prototype.onTransitionEnd_ = function (ref) { + var propertyName = ref.propertyName; if ( propertyName === void 0 ) propertyName = ''; + + // Detect whether transition may affect dimensions of an element. + var isReflowProperty = transitionKeys.some(function (key) { + return !!~propertyName.indexOf(key); + }); + + if (isReflowProperty) { + this.refresh(); + } +}; + +/** + * Returns instance of the ResizeObserverController. + * + * @returns {ResizeObserverController} + */ +ResizeObserverController.getInstance = function () { + if (!this.instance_) { + this.instance_ = new ResizeObserverController(); + } + + return this.instance_; +}; + +ResizeObserverController.instance_ = null; + +/** + * Defines non-writable/enumerable properties of the provided target object. + * + * @param {Object} target - Object for which to define properties. + * @param {Object} props - Properties to be defined. + * @returns {Object} Target object. + */ +var defineConfigurable = (function (target, props) { + for (var i = 0, list = Object.keys(props); i < list.length; i += 1) { + var key = list[i]; + + Object.defineProperty(target, key, { + value: props[key], + enumerable: false, + writable: false, + configurable: true + }); + } + + return target; +}); + +/** + * Returns the global object associated with provided element. + * + * @param {Object} target + * @returns {Object} + */ +var getWindowOf = (function (target) { + // Assume that the element is an instance of Node, which means that it + // has the "ownerDocument" property from which we can retrieve a + // corresponding global object. + var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView; + + // Return the local global object if it's not possible extract one from + // provided element. + return ownerGlobal || global$1; +}); + +// Placeholder of an empty content rectangle. +var emptyRect = createRectInit(0, 0, 0, 0); + +/** + * Converts provided string to a number. + * + * @param {number|string} value + * @returns {number} + */ +function toFloat(value) { + return parseFloat(value) || 0; +} + +/** + * Extracts borders size from provided styles. + * + * @param {CSSStyleDeclaration} styles + * @param {...string} positions - Borders positions (top, right, ...) + * @returns {number} + */ +function getBordersSize(styles) { + var positions = [], len = arguments.length - 1; + while ( len-- > 0 ) positions[ len ] = arguments[ len + 1 ]; + + return positions.reduce(function (size, position) { + var value = styles['border-' + position + '-width']; + + return size + toFloat(value); + }, 0); +} + +/** + * Extracts paddings sizes from provided styles. + * + * @param {CSSStyleDeclaration} styles + * @returns {Object} Paddings box. + */ +function getPaddings(styles) { + var positions = ['top', 'right', 'bottom', 'left']; + var paddings = {}; + + for (var i = 0, list = positions; i < list.length; i += 1) { + var position = list[i]; + + var value = styles['padding-' + position]; + + paddings[position] = toFloat(value); + } + + return paddings; +} + +/** + * Calculates content rectangle of provided SVG element. + * + * @param {SVGGraphicsElement} target - Element content rectangle of which needs + * to be calculated. + * @returns {DOMRectInit} + */ +function getSVGContentRect(target) { + var bbox = target.getBBox(); + + return createRectInit(0, 0, bbox.width, bbox.height); +} + +/** + * Calculates content rectangle of provided HTMLElement. + * + * @param {HTMLElement} target - Element for which to calculate the content rectangle. + * @returns {DOMRectInit} + */ +function getHTMLElementContentRect(target) { + // Client width & height properties can't be + // used exclusively as they provide rounded values. + var clientWidth = target.clientWidth; + var clientHeight = target.clientHeight; + + // By this condition we can catch all non-replaced inline, hidden and + // detached elements. Though elements with width & height properties less + // than 0.5 will be discarded as well. + // + // Without it we would need to implement separate methods for each of + // those cases and it's not possible to perform a precise and performance + // effective test for hidden elements. E.g. even jQuery's ':visible' filter + // gives wrong results for elements with width & height less than 0.5. + if (!clientWidth && !clientHeight) { + return emptyRect; + } + + var styles = getWindowOf(target).getComputedStyle(target); + var paddings = getPaddings(styles); + var horizPad = paddings.left + paddings.right; + var vertPad = paddings.top + paddings.bottom; + + // Computed styles of width & height are being used because they are the + // only dimensions available to JS that contain non-rounded values. It could + // be possible to utilize the getBoundingClientRect if only it's data wasn't + // affected by CSS transformations let alone paddings, borders and scroll bars. + var width = toFloat(styles.width), + height = toFloat(styles.height); + + // Width & height include paddings and borders when the 'border-box' box + // model is applied (except for IE). + if (styles.boxSizing === 'border-box') { + // Following conditions are required to handle Internet Explorer which + // doesn't include paddings and borders to computed CSS dimensions. + // + // We can say that if CSS dimensions + paddings are equal to the "client" + // properties then it's either IE, and thus we don't need to subtract + // anything, or an element merely doesn't have paddings/borders styles. + if (Math.round(width + horizPad) !== clientWidth) { + width -= getBordersSize(styles, 'left', 'right') + horizPad; + } + + if (Math.round(height + vertPad) !== clientHeight) { + height -= getBordersSize(styles, 'top', 'bottom') + vertPad; + } + } + + // Following steps can't be applied to the document's root element as its + // client[Width/Height] properties represent viewport area of the window. + // Besides, it's as well not necessary as the itself neither has + // rendered scroll bars nor it can be clipped. + if (!isDocumentElement(target)) { + // In some browsers (only in Firefox, actually) CSS width & height + // include scroll bars size which can be removed at this step as scroll + // bars are the only difference between rounded dimensions + paddings + // and "client" properties, though that is not always true in Chrome. + var vertScrollbar = Math.round(width + horizPad) - clientWidth; + var horizScrollbar = Math.round(height + vertPad) - clientHeight; + + // Chrome has a rather weird rounding of "client" properties. + // E.g. for an element with content width of 314.2px it sometimes gives + // the client width of 315px and for the width of 314.7px it may give + // 314px. And it doesn't happen all the time. So just ignore this delta + // as a non-relevant. + if (Math.abs(vertScrollbar) !== 1) { + width -= vertScrollbar; + } + + if (Math.abs(horizScrollbar) !== 1) { + height -= horizScrollbar; + } + } + + return createRectInit(paddings.left, paddings.top, width, height); +} + +/** + * Checks whether provided element is an instance of the SVGGraphicsElement. + * + * @param {Element} target - Element to be checked. + * @returns {boolean} + */ +var isSVGGraphicsElement = (function () { + // Some browsers, namely IE and Edge, don't have the SVGGraphicsElement + // interface. + if (typeof SVGGraphicsElement !== 'undefined') { + return function (target) { return target instanceof getWindowOf(target).SVGGraphicsElement; }; + } + + // If it's so, then check that element is at least an instance of the + // SVGElement and that it has the "getBBox" method. + // eslint-disable-next-line no-extra-parens + return function (target) { return target instanceof getWindowOf(target).SVGElement && typeof target.getBBox === 'function'; }; +})(); + +/** + * Checks whether provided element is a document element (). + * + * @param {Element} target - Element to be checked. + * @returns {boolean} + */ +function isDocumentElement(target) { + return target === getWindowOf(target).document.documentElement; +} + +/** + * Calculates an appropriate content rectangle for provided html or svg element. + * + * @param {Element} target - Element content rectangle of which needs to be calculated. + * @returns {DOMRectInit} + */ +function getContentRect(target) { + if (!isBrowser) { + return emptyRect; + } + + if (isSVGGraphicsElement(target)) { + return getSVGContentRect(target); + } + + return getHTMLElementContentRect(target); +} + +/** + * Creates rectangle with an interface of the DOMRectReadOnly. + * Spec: https://drafts.fxtf.org/geometry/#domrectreadonly + * + * @param {DOMRectInit} rectInit - Object with rectangle's x/y coordinates and dimensions. + * @returns {DOMRectReadOnly} + */ +function createReadOnlyRect(ref) { + var x = ref.x; + var y = ref.y; + var width = ref.width; + var height = ref.height; + + // If DOMRectReadOnly is available use it as a prototype for the rectangle. + var Constr = typeof DOMRectReadOnly !== 'undefined' ? DOMRectReadOnly : Object; + var rect = Object.create(Constr.prototype); + + // Rectangle's properties are not writable and non-enumerable. + defineConfigurable(rect, { + x: x, y: y, width: width, height: height, + top: y, + right: x + width, + bottom: height + y, + left: x + }); + + return rect; +} + +/** + * Creates DOMRectInit object based on the provided dimensions and the x/y coordinates. + * Spec: https://drafts.fxtf.org/geometry/#dictdef-domrectinit + * + * @param {number} x - X coordinate. + * @param {number} y - Y coordinate. + * @param {number} width - Rectangle's width. + * @param {number} height - Rectangle's height. + * @returns {DOMRectInit} + */ +function createRectInit(x, y, width, height) { + return { x: x, y: y, width: width, height: height }; +} + +/** + * Class that is responsible for computations of the content rectangle of + * provided DOM element and for keeping track of it's changes. + */ +var ResizeObservation = function(target) { + this.broadcastWidth = 0; + this.broadcastHeight = 0; + this.contentRect_ = createRectInit(0, 0, 0, 0); + + this.target = target; +}; + +/** + * Updates content rectangle and tells whether it's width or height properties + * have changed since the last broadcast. + * + * @returns {boolean} + */ + + +/** + * Reference to the last observed content rectangle. + * + * @private {DOMRectInit} + */ + + +/** + * Broadcasted width of content rectangle. + * + * @type {number} + */ +ResizeObservation.prototype.isActive = function () { + var rect = getContentRect(this.target); + + this.contentRect_ = rect; + + return rect.width !== this.broadcastWidth || rect.height !== this.broadcastHeight; +}; + +/** + * Updates 'broadcastWidth' and 'broadcastHeight' properties with a data + * from the corresponding properties of the last observed content rectangle. + * + * @returns {DOMRectInit} Last observed content rectangle. + */ +ResizeObservation.prototype.broadcastRect = function () { + var rect = this.contentRect_; + + this.broadcastWidth = rect.width; + this.broadcastHeight = rect.height; + + return rect; +}; + +var ResizeObserverEntry = function(target, rectInit) { + var contentRect = createReadOnlyRect(rectInit); + + // According to the specification following properties are not writable + // and are also not enumerable in the native implementation. + // + // Property accessors are not being used as they'd require to define a + // private WeakMap storage which may cause memory leaks in browsers that + // don't support this type of collections. + defineConfigurable(this, { target: target, contentRect: contentRect }); +}; + +var ResizeObserverSPI = function(callback, controller, callbackCtx) { + this.activeObservations_ = []; + this.observations_ = new MapShim(); + + if (typeof callback !== 'function') { + throw new TypeError('The callback provided as parameter 1 is not a function.'); + } + + this.callback_ = callback; + this.controller_ = controller; + this.callbackCtx_ = callbackCtx; +}; + +/** + * Starts observing provided element. + * + * @param {Element} target - Element to be observed. + * @returns {void} + */ + + +/** + * Registry of the ResizeObservation instances. + * + * @private {Map} + */ + + +/** + * Public ResizeObserver instance which will be passed to the callback + * function and used as a value of it's "this" binding. + * + * @private {ResizeObserver} + */ + +/** + * Collection of resize observations that have detected changes in dimensions + * of elements. + * + * @private {Array} + */ +ResizeObserverSPI.prototype.observe = function (target) { + if (!arguments.length) { + throw new TypeError('1 argument required, but only 0 present.'); + } + + // Do nothing if current environment doesn't have the Element interface. + if (typeof Element === 'undefined' || !(Element instanceof Object)) { + return; + } + + if (!(target instanceof getWindowOf(target).Element)) { + throw new TypeError('parameter 1 is not of type "Element".'); + } + + var observations = this.observations_; + + // Do nothing if element is already being observed. + if (observations.has(target)) { + return; + } + + observations.set(target, new ResizeObservation(target)); + + this.controller_.addObserver(this); + + // Force the update of observations. + this.controller_.refresh(); +}; + +/** + * Stops observing provided element. + * + * @param {Element} target - Element to stop observing. + * @returns {void} + */ +ResizeObserverSPI.prototype.unobserve = function (target) { + if (!arguments.length) { + throw new TypeError('1 argument required, but only 0 present.'); + } + + // Do nothing if current environment doesn't have the Element interface. + if (typeof Element === 'undefined' || !(Element instanceof Object)) { + return; + } + + if (!(target instanceof getWindowOf(target).Element)) { + throw new TypeError('parameter 1 is not of type "Element".'); + } + + var observations = this.observations_; + + // Do nothing if element is not being observed. + if (!observations.has(target)) { + return; + } + + observations.delete(target); + + if (!observations.size) { + this.controller_.removeObserver(this); + } +}; + +/** + * Stops observing all elements. + * + * @returns {void} + */ +ResizeObserverSPI.prototype.disconnect = function () { + this.clearActive(); + this.observations_.clear(); + this.controller_.removeObserver(this); +}; + +/** + * Collects observation instances the associated element of which has changed + * it's content rectangle. + * + * @returns {void} + */ +ResizeObserverSPI.prototype.gatherActive = function () { + var this$1 = this; + + this.clearActive(); + + this.observations_.forEach(function (observation) { + if (observation.isActive()) { + this$1.activeObservations_.push(observation); + } + }); +}; + +/** + * Invokes initial callback function with a list of ResizeObserverEntry + * instances collected from active resize observations. + * + * @returns {void} + */ +ResizeObserverSPI.prototype.broadcastActive = function () { + // Do nothing if observer doesn't have active observations. + if (!this.hasActive()) { + return; + } + + var ctx = this.callbackCtx_; + + // Create ResizeObserverEntry instance for every active observation. + var entries = this.activeObservations_.map(function (observation) { + return new ResizeObserverEntry(observation.target, observation.broadcastRect()); + }); + + this.callback_.call(ctx, entries, ctx); + this.clearActive(); +}; + +/** + * Clears the collection of active observations. + * + * @returns {void} + */ +ResizeObserverSPI.prototype.clearActive = function () { + this.activeObservations_.splice(0); +}; + +/** + * Tells whether observer has active observations. + * + * @returns {boolean} + */ +ResizeObserverSPI.prototype.hasActive = function () { + return this.activeObservations_.length > 0; +}; + +// Registry of internal observers. If WeakMap is not available use current shim +// for the Map collection as it has all required methods and because WeakMap +// can't be fully polyfilled anyway. +var observers = typeof WeakMap !== 'undefined' ? new WeakMap() : new MapShim(); + +/** + * ResizeObserver API. Encapsulates the ResizeObserver SPI implementation + * exposing only those methods and properties that are defined in the spec. + */ +var ResizeObserver = function(callback) { + if (!(this instanceof ResizeObserver)) { + throw new TypeError('Cannot call a class as a function.'); + } + if (!arguments.length) { + throw new TypeError('1 argument required, but only 0 present.'); + } + + var controller = ResizeObserverController.getInstance(); + var observer = new ResizeObserverSPI(callback, controller, this); + + observers.set(this, observer); +}; + +// Expose public methods of ResizeObserver. +['observe', 'unobserve', 'disconnect'].forEach(function (method) { + ResizeObserver.prototype[method] = function () { + return (ref = observers.get(this))[method].apply(ref, arguments); + var ref; + }; +}); + +var index = (function () { + // Export existing implementation if available. + if (typeof global$1.ResizeObserver !== 'undefined') { + return global$1.ResizeObserver; + } + + global$1.ResizeObserver = ResizeObserver; + + return ResizeObserver; +})(); + +return index; + +}))); diff --git a/apps/templates/accounts/login.html b/apps/templates/accounts/login.html index 43e8697..12ce4cb 100644 --- a/apps/templates/accounts/login.html +++ b/apps/templates/accounts/login.html @@ -57,7 +57,7 @@
    - No tienes cuenta? Crear + No tienes cuenta? Crear
diff --git a/apps/templates/includes/navigation.html b/apps/templates/includes/navigation.html index 65944cf..fecd0eb 100644 --- a/apps/templates/includes/navigation.html +++ b/apps/templates/includes/navigation.html @@ -53,7 +53,7 @@ diff --git a/apps/templates/includes/sidebar.html b/apps/templates/includes/sidebar.html index c1cc642..3c4c45b 100644 --- a/apps/templates/includes/sidebar.html +++ b/apps/templates/includes/sidebar.html @@ -55,13 +55,19 @@ {% else %} + {% endif %}

diff --git a/apps/templates/static_page/static_page.html b/apps/templates/static_page/static_page.html new file mode 100644 index 0000000..55316e9 --- /dev/null +++ b/apps/templates/static_page/static_page.html @@ -0,0 +1,125 @@ + + + + + + Gestión de Inventario + + + + + + + +
+
+
+

Bienvenido a la página de gestión de inventario

+

Aquí podrás controlar y administrar tu inventario de productos de manera eficiente.

+
+
+
+ + +
+

Últimas novedades

+
+
+
+ ... +
+
Título de la noticia 1
+

Descripción breve de la noticia 1.

+ Leer más +
+
+
+
+
+ ... +
+
Título de la noticia 1
+

Descripción breve de la noticia 1.

+ Leer más +
+
+
+
+
+ ... +
+
Título de la noticia 1
+

Descripción breve de la noticia 1.

+ Leer más +
+
+
+ +
+
+ + +
+
+
+
+
+ + + + + diff --git a/core/settings.py b/core/settings.py index dd1f299..0d67fcc 100644 --- a/core/settings.py +++ b/core/settings.py @@ -49,7 +49,7 @@ ROOT_URLCONF = 'core.urls' LOGIN_REDIRECT_URL = reverse_lazy('inicio') -LOGOUT_REDIRECT_URL = reverse_lazy('login') +LOGOUT_REDIRECT_URL = reverse_lazy('authentication:login') TEMPLATE_DIR = os.path.join(CORE_DIR, "apps/templates") # ROOT dir for templates TEMPLATES = [ @@ -106,9 +106,9 @@ # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = 'es-CO' -TIME_ZONE = 'UTC' +TIME_ZONE = 'America/Bogota' USE_I18N = True