Many updates
@@ -1,6 +1,6 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import Aulario, ComedorMenu, ComedorMenuType, StudentAttachment
|
from .models import Aulario, ComedorMenu, ComedorMenuType, Cuaderno, StudentAttachment
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Aulario)
|
@admin.register(Aulario)
|
||||||
@@ -30,4 +30,11 @@ class ComedorMenuTypeAdmin(admin.ModelAdmin):
|
|||||||
list_display = ("org_id", "source_aulario_id", "type_id", "label", "color", "created_by")
|
list_display = ("org_id", "source_aulario_id", "type_id", "label", "color", "created_by")
|
||||||
search_fields = ("org_id", "source_aulario_id", "type_id", "label", "created_by")
|
search_fields = ("org_id", "source_aulario_id", "type_id", "label", "created_by")
|
||||||
list_filter = ("org_id", "source_aulario_id", "created_at")
|
list_filter = ("org_id", "source_aulario_id", "created_at")
|
||||||
filter_horizontal = ("shared_aularios",)
|
filter_horizontal = ("shared_aularios",)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Cuaderno)
|
||||||
|
class CuadernoAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ("org_id", "aulario_id", "alumno", "titulo", "created_by", "updated_at")
|
||||||
|
search_fields = ("org_id", "aulario_id", "alumno", "titulo", "created_by", "updated_by")
|
||||||
|
list_filter = ("org_id", "aulario_id", "created_at", "updated_at")
|
||||||
30
django_app/aulatek/migrations/0006_cuaderno.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("aulatek", "0005_comedormenutype"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Cuaderno",
|
||||||
|
fields=[
|
||||||
|
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||||
|
("org_id", models.TextField()),
|
||||||
|
("aulario_id", models.TextField()),
|
||||||
|
("alumno", models.TextField(default="")),
|
||||||
|
("titulo", models.TextField(default="")),
|
||||||
|
("contenido_encriptado", models.TextField(default="")),
|
||||||
|
("pin_hash", models.TextField(default="")),
|
||||||
|
("pin_salt", models.TextField(default="")),
|
||||||
|
("created_by", models.TextField(default="")),
|
||||||
|
("updated_by", models.TextField(default="")),
|
||||||
|
("created_at", models.DateTimeField(auto_now_add=True)),
|
||||||
|
("updated_at", models.DateTimeField(auto_now=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"db_table": "aulatek_cuadernos",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -104,6 +104,28 @@ class ComedorMenuType(models.Model):
|
|||||||
return f"{self.org_id}/{self.source_aulario_id}/{self.type_id}"
|
return f"{self.org_id}/{self.source_aulario_id}/{self.type_id}"
|
||||||
|
|
||||||
|
|
||||||
|
class Cuaderno(models.Model):
|
||||||
|
org_id = models.TextField()
|
||||||
|
aulario_id = models.TextField()
|
||||||
|
alumno = models.TextField(default="")
|
||||||
|
titulo = models.TextField(default="")
|
||||||
|
contenido_encriptado = models.TextField(default="")
|
||||||
|
pin_hash = models.TextField(default="")
|
||||||
|
pin_salt = models.TextField(default="")
|
||||||
|
created_by = models.TextField(default="")
|
||||||
|
updated_by = models.TextField(default="")
|
||||||
|
created_at = models.DateTimeField(auto_now_add=True)
|
||||||
|
updated_at = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
db_table = "aulatek_cuadernos"
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
alumno = self.alumno or "sin-alumno"
|
||||||
|
titulo = self.titulo or "sin-titulo"
|
||||||
|
return f"{self.org_id}/{self.aulario_id}/{alumno}/{titulo}"
|
||||||
|
|
||||||
|
|
||||||
class Aulario(CoreAulario):
|
class Aulario(CoreAulario):
|
||||||
class Meta:
|
class Meta:
|
||||||
proxy = True
|
proxy = True
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ urlpatterns = [
|
|||||||
path("aulario/", views.aulatek_aulario, name="aulatek_aulario"),
|
path("aulario/", views.aulatek_aulario, name="aulatek_aulario"),
|
||||||
path("paneldiario/", views.paneldiario, name="paneldiario"),
|
path("paneldiario/", views.paneldiario, name="paneldiario"),
|
||||||
path("alumnos/", views.alumnos, name="alumnos"),
|
path("alumnos/", views.alumnos, name="alumnos"),
|
||||||
|
path("cuadernos/", views.cuadernos, name="cuadernos"),
|
||||||
|
path("cuadernos/new/", views.cuaderno_new, name="cuaderno_new"),
|
||||||
|
path("cuadernos/<int:cuaderno_id>/", views.cuaderno_edit, name="cuaderno_edit"),
|
||||||
path("alumnos/new/", views.alumno_new, name="alumno_new"),
|
path("alumnos/new/", views.alumno_new, name="alumno_new"),
|
||||||
path("alumnos/edit/<int:student_id>/", views.alumno_edit, name="alumno_edit"),
|
path("alumnos/edit/<int:student_id>/", views.alumno_edit, name="alumno_edit"),
|
||||||
path("alumnos/delete/<int:student_id>/", views.alumno_delete, name="alumno_delete"),
|
path("alumnos/delete/<int:student_id>/", views.alumno_delete, name="alumno_delete"),
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from django.shortcuts import redirect, render
|
|||||||
from core.models import Aulario
|
from core.models import Aulario
|
||||||
from core.shell import require_axia_login, shell_context
|
from core.shell import require_axia_login, shell_context
|
||||||
|
|
||||||
from .models import ComedorMenu, ComedorMenuType, StudentAttachment
|
from .models import ComedorMenu, ComedorMenuType, Cuaderno, StudentAttachment
|
||||||
|
|
||||||
|
|
||||||
def _safe_organization_id(value: str) -> str:
|
def _safe_organization_id(value: str) -> str:
|
||||||
@@ -48,6 +48,13 @@ def _alumnos_permission(request: HttpRequest) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _cuadernos_permission(request: HttpRequest) -> bool:
|
||||||
|
return (
|
||||||
|
request.axia_user.has_permission("aulatek:docente")
|
||||||
|
or request.axia_user.has_permission("entreaulas:docente")
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _alumnos_access(request: HttpRequest):
|
def _alumnos_access(request: HttpRequest):
|
||||||
gate = require_axia_login(request)
|
gate = require_axia_login(request)
|
||||||
if gate:
|
if gate:
|
||||||
@@ -60,6 +67,15 @@ def _alumnos_access(request: HttpRequest):
|
|||||||
return None, request.axia_user, org_id
|
return None, request.axia_user, org_id
|
||||||
|
|
||||||
|
|
||||||
|
def _cuadernos_access(request: HttpRequest):
|
||||||
|
gate, user, org_id = _alumnos_access(request)
|
||||||
|
if gate:
|
||||||
|
return gate, None, None
|
||||||
|
if not _cuadernos_permission(request):
|
||||||
|
return HttpResponseForbidden("No tienes permiso para ver cuadernos."), None, None
|
||||||
|
return None, user, org_id
|
||||||
|
|
||||||
|
|
||||||
def _comedor_access(request: HttpRequest):
|
def _comedor_access(request: HttpRequest):
|
||||||
gate, user, org_id = _alumnos_access(request)
|
gate, user, org_id = _alumnos_access(request)
|
||||||
if gate:
|
if gate:
|
||||||
@@ -83,6 +99,16 @@ def _parse_menu_date(value: str):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _safe_titulo(value: str) -> str:
|
||||||
|
value = (value or "").strip()
|
||||||
|
value = re.sub(r"[\x00-\x1F\x7F]", "", value)
|
||||||
|
return value[:140]
|
||||||
|
|
||||||
|
|
||||||
|
def _signature_verified(request: HttpRequest) -> bool:
|
||||||
|
return (request.POST.get("_firma_signed") or "") == "1"
|
||||||
|
|
||||||
|
|
||||||
def aulatek_home(request: HttpRequest):
|
def aulatek_home(request: HttpRequest):
|
||||||
gate = require_axia_login(request)
|
gate = require_axia_login(request)
|
||||||
if gate:
|
if gate:
|
||||||
@@ -139,6 +165,13 @@ def aulatek_aulario(request: HttpRequest):
|
|||||||
"variant": "info",
|
"variant": "info",
|
||||||
"visible": _alumnos_permission(request),
|
"visible": _alumnos_permission(request),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"href": f"/aulatek/cuadernos/?aulario={aulario_id}",
|
||||||
|
"label": "Cuadernos",
|
||||||
|
"icon": "/static/iconexperience/contract.png",
|
||||||
|
"variant": "dark",
|
||||||
|
"visible": _cuadernos_permission(request),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"href": f"/sysadmin/aularios/?aulario={aulario_id}",
|
"href": f"/sysadmin/aularios/?aulario={aulario_id}",
|
||||||
"label": "Cambiar Ajustes",
|
"label": "Cambiar Ajustes",
|
||||||
@@ -198,6 +231,7 @@ def alumnos(request: HttpRequest):
|
|||||||
"module_title": "Gestion de Alumnos",
|
"module_title": "Gestion de Alumnos",
|
||||||
"aulario_id": aulario_id,
|
"aulario_id": aulario_id,
|
||||||
"students": students,
|
"students": students,
|
||||||
|
"can_view_cuadernos": _cuadernos_permission(request),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return render(request, "aulatek/alumnos.html", context)
|
return render(request, "aulatek/alumnos.html", context)
|
||||||
@@ -283,6 +317,8 @@ def alumno_delete(request: HttpRequest, student_id: int):
|
|||||||
return gate
|
return gate
|
||||||
if request.method != "POST":
|
if request.method != "POST":
|
||||||
return HttpResponseForbidden("Metodo no permitido.")
|
return HttpResponseForbidden("Metodo no permitido.")
|
||||||
|
if not _signature_verified(request):
|
||||||
|
return HttpResponseForbidden("Firma requerida para eliminar.")
|
||||||
|
|
||||||
student = StudentAttachment.objects.filter(id=student_id, org_id=org_id).first()
|
student = StudentAttachment.objects.filter(id=student_id, org_id=org_id).first()
|
||||||
if not student:
|
if not student:
|
||||||
@@ -313,6 +349,148 @@ def alumno_photo(request: HttpRequest, student_id: int):
|
|||||||
return FileResponse(student.photo.open("rb"), content_type=mime_type or "application/octet-stream")
|
return FileResponse(student.photo.open("rb"), content_type=mime_type or "application/octet-stream")
|
||||||
|
|
||||||
|
|
||||||
|
def cuadernos(request: HttpRequest):
|
||||||
|
gate, _, org_id = _cuadernos_access(request)
|
||||||
|
if gate:
|
||||||
|
return gate
|
||||||
|
|
||||||
|
aulario_id = _safe_aulario_id(request.GET.get("aulario", ""))
|
||||||
|
context = shell_context(request, "aulatek", "Cuadernos")
|
||||||
|
if not aulario_id or not org_id:
|
||||||
|
context.update(
|
||||||
|
{
|
||||||
|
"module_title": "Cuadernos",
|
||||||
|
"aulario_id": "",
|
||||||
|
"cuadernos": [],
|
||||||
|
"alumnos": [],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return render(request, "aulatek/cuadernos.html", context)
|
||||||
|
|
||||||
|
if not Aulario.objects.filter(org_id=org_id, aulario_id=aulario_id).exists():
|
||||||
|
raise Http404("Aulario no encontrado")
|
||||||
|
|
||||||
|
cuadernos_rows = Cuaderno.objects.filter(org_id=org_id, aulario_id=aulario_id).order_by("-updated_at", "-created_at")
|
||||||
|
context.update(
|
||||||
|
{
|
||||||
|
"module_title": "Cuadernos",
|
||||||
|
"aulario_id": aulario_id,
|
||||||
|
"cuadernos": cuadernos_rows,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return render(request, "aulatek/cuadernos.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def cuaderno_new(request: HttpRequest):
|
||||||
|
gate, user, org_id = _cuadernos_access(request)
|
||||||
|
if gate:
|
||||||
|
return gate
|
||||||
|
|
||||||
|
aulario_id = _safe_aulario_id(request.GET.get("aulario", ""))
|
||||||
|
if not aulario_id or not org_id:
|
||||||
|
messages.error(request, "No se ha indicado un aulario valido.")
|
||||||
|
return redirect("/aulatek/")
|
||||||
|
|
||||||
|
if not Aulario.objects.filter(org_id=org_id, aulario_id=aulario_id).exists():
|
||||||
|
raise Http404("Aulario no encontrado")
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
titulo = _safe_titulo(request.POST.get("titulo", ""))
|
||||||
|
alumno = _safe_alumno_name(request.POST.get("alumno", ""))
|
||||||
|
contenido = (request.POST.get("contenido") or "").strip()
|
||||||
|
|
||||||
|
if not titulo:
|
||||||
|
messages.error(request, "El titulo es obligatorio.")
|
||||||
|
return redirect(f"/aulatek/cuadernos/new/?aulario={aulario_id}")
|
||||||
|
if not contenido:
|
||||||
|
messages.error(request, "El contenido no puede estar vacio.")
|
||||||
|
return redirect(f"/aulatek/cuadernos/new/?aulario={aulario_id}")
|
||||||
|
Cuaderno.objects.create(
|
||||||
|
org_id=org_id,
|
||||||
|
aulario_id=aulario_id,
|
||||||
|
alumno=alumno,
|
||||||
|
titulo=titulo,
|
||||||
|
contenido_encriptado=contenido,
|
||||||
|
pin_hash="",
|
||||||
|
pin_salt="",
|
||||||
|
created_by=user.username if user else "",
|
||||||
|
updated_by=user.username if user else "",
|
||||||
|
)
|
||||||
|
messages.success(request, "Cuaderno creado correctamente.")
|
||||||
|
return redirect(f"/aulatek/cuadernos/?aulario={aulario_id}")
|
||||||
|
|
||||||
|
alumnos_rows = StudentAttachment.objects.filter(org_id=org_id, aulario_id=aulario_id).order_by("alumno")
|
||||||
|
context = shell_context(request, "aulatek", "Nuevo Cuaderno")
|
||||||
|
context.update(
|
||||||
|
{
|
||||||
|
"module_title": "Nuevo Cuaderno",
|
||||||
|
"aulario_id": aulario_id,
|
||||||
|
"alumnos": [row.alumno for row in alumnos_rows],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return render(request, "aulatek/cuaderno_new.html", context)
|
||||||
|
|
||||||
|
|
||||||
|
def cuaderno_edit(request: HttpRequest, cuaderno_id: int):
|
||||||
|
gate, user, org_id = _cuadernos_access(request)
|
||||||
|
if gate:
|
||||||
|
return gate
|
||||||
|
|
||||||
|
cuaderno = Cuaderno.objects.filter(id=cuaderno_id, org_id=org_id).first()
|
||||||
|
if not cuaderno:
|
||||||
|
raise Http404("Cuaderno no encontrado")
|
||||||
|
|
||||||
|
aulario_id = cuaderno.aulario_id
|
||||||
|
decrypted_content = cuaderno.contenido_encriptado or ""
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
action = (request.POST.get("action") or "unlock").strip().lower()
|
||||||
|
|
||||||
|
if action == "unlock":
|
||||||
|
return redirect(f"/aulatek/cuadernos/{cuaderno.id}/")
|
||||||
|
|
||||||
|
if action == "update":
|
||||||
|
titulo = _safe_titulo(request.POST.get("titulo", ""))
|
||||||
|
alumno = _safe_alumno_name(request.POST.get("alumno", ""))
|
||||||
|
contenido = (request.POST.get("contenido") or "").strip()
|
||||||
|
|
||||||
|
if not titulo:
|
||||||
|
messages.error(request, "El titulo es obligatorio.")
|
||||||
|
return redirect(f"/aulatek/cuadernos/{cuaderno.id}/")
|
||||||
|
if not contenido:
|
||||||
|
messages.error(request, "El contenido no puede estar vacio.")
|
||||||
|
return redirect(f"/aulatek/cuadernos/{cuaderno.id}/")
|
||||||
|
|
||||||
|
cuaderno.titulo = titulo
|
||||||
|
cuaderno.alumno = alumno
|
||||||
|
cuaderno.pin_salt = ""
|
||||||
|
cuaderno.pin_hash = ""
|
||||||
|
cuaderno.contenido_encriptado = contenido
|
||||||
|
cuaderno.updated_by = user.username if user else ""
|
||||||
|
cuaderno.save(update_fields=["titulo", "alumno", "pin_hash", "pin_salt", "contenido_encriptado", "updated_by", "updated_at"])
|
||||||
|
messages.success(request, "Cuaderno actualizado correctamente.")
|
||||||
|
return redirect(f"/aulatek/cuadernos/{cuaderno.id}/")
|
||||||
|
|
||||||
|
if action == "delete":
|
||||||
|
if not _signature_verified(request):
|
||||||
|
messages.error(request, "Firma requerida para eliminar el cuaderno.")
|
||||||
|
return redirect(f"/aulatek/cuadernos/{cuaderno.id}/")
|
||||||
|
cuaderno.delete()
|
||||||
|
messages.success(request, "Cuaderno eliminado.")
|
||||||
|
return redirect(f"/aulatek/cuadernos/?aulario={aulario_id}")
|
||||||
|
|
||||||
|
context = shell_context(request, "aulatek", f"Cuaderno: {cuaderno.titulo}")
|
||||||
|
context.update(
|
||||||
|
{
|
||||||
|
"module_title": "Editar Cuaderno",
|
||||||
|
"cuaderno": cuaderno,
|
||||||
|
"aulario_id": aulario_id,
|
||||||
|
"decrypted_content": decrypted_content,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return render(request, "aulatek/cuaderno_edit.html", context)
|
||||||
|
|
||||||
|
|
||||||
def comedor(request: HttpRequest):
|
def comedor(request: HttpRequest):
|
||||||
gate, user, org_id, aulario_row = _comedor_access(request)
|
gate, user, org_id, aulario_row = _comedor_access(request)
|
||||||
if gate:
|
if gate:
|
||||||
@@ -400,6 +578,8 @@ def comedor(request: HttpRequest):
|
|||||||
return redirect(comedor_url(selected_date, row.type_id))
|
return redirect(comedor_url(selected_date, row.type_id))
|
||||||
|
|
||||||
if action == "delete_type":
|
if action == "delete_type":
|
||||||
|
if not _signature_verified(request):
|
||||||
|
return HttpResponseForbidden("Firma requerida para eliminar tipo.")
|
||||||
delete_id = (request.POST.get("delete_type_id") or "").strip()
|
delete_id = (request.POST.get("delete_type_id") or "").strip()
|
||||||
row = ComedorMenuType.objects.filter(org_id=org_id, source_aulario_id=aulario_row.aulario_id, type_id=delete_id).first()
|
row = ComedorMenuType.objects.filter(org_id=org_id, source_aulario_id=aulario_row.aulario_id, type_id=delete_id).first()
|
||||||
if row:
|
if row:
|
||||||
@@ -475,6 +655,8 @@ def comedor(request: HttpRequest):
|
|||||||
if action == "delete":
|
if action == "delete":
|
||||||
if not selected_type_row or not can_edit_selected_type:
|
if not selected_type_row or not can_edit_selected_type:
|
||||||
return HttpResponseForbidden("No puedes eliminar menu de un tipo compartido.")
|
return HttpResponseForbidden("No puedes eliminar menu de un tipo compartido.")
|
||||||
|
if not _signature_verified(request):
|
||||||
|
return HttpResponseForbidden("Firma requerida para eliminar menu.")
|
||||||
menu_id = int(request.POST.get("menu_id") or 0)
|
menu_id = int(request.POST.get("menu_id") or 0)
|
||||||
menu = ComedorMenu.objects.filter(
|
menu = ComedorMenu.objects.filter(
|
||||||
id=menu_id,
|
id=menu_id,
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ USE_I18N = True
|
|||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
STATIC_URL = "/static/"
|
STATIC_URL = "/static/"
|
||||||
STATICFILES_DIRS = [REPO_ROOT / "public_html" / "static"]
|
STATICFILES_DIRS = [BASE_DIR / "static"]
|
||||||
MEDIA_URL = "/media/"
|
MEDIA_URL = "/media/"
|
||||||
MEDIA_ROOT = DATA_ROOT / "attachments"
|
MEDIA_ROOT = DATA_ROOT / "attachments"
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 411 B After Width: | Height: | Size: 411 B |
|
Before Width: | Height: | Size: 353 B After Width: | Height: | Size: 353 B |
|
Before Width: | Height: | Size: 172 B After Width: | Height: | Size: 172 B |
|
Before Width: | Height: | Size: 194 B After Width: | Height: | Size: 194 B |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
BIN
django_app/static/iconexperience/key.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
BIN
django_app/static/iconexperience/lock_open.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
django_app/static/iconexperience/lock_warning.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
BIN
django_app/static/lock_open.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 347 KiB After Width: | Height: | Size: 347 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.7 KiB After Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |