Waste management dashboar
Some checks reported errors
continuous-integration/drone/push Build was killed

This commit is contained in:
Ekaropolus 2025-05-18 02:25:46 -06:00
parent 3160d86e53
commit 96fed7c45e
32 changed files with 1485 additions and 653 deletions

View File

@ -15,8 +15,12 @@ sys.path.append(str(BASE_DIR))
# Core security settings # Core security settings
SECRET_KEY = os.getenv("SECRET_KEY") SECRET_KEY = os.getenv("SECRET_KEY")
DEBUG = os.getenv("DEBUG", "False") == "True" DEBUG = os.getenv("DEBUG", "False") == "True"
ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "").split(",") #ALLOWED_HOSTS = os.getenv("ALLOWED_HOSTS", "").split(",")
ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
'.ngrok-free.app',
]
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
# Django built-in apps # Django built-in apps
@ -60,7 +64,7 @@ INSTALLED_APPS = [
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5" CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap5"
CRISPY_TEMPLATE_PACK = "bootstrap5" CRISPY_TEMPLATE_PACK = "bootstrap5"
SITE_ID = 2 SITE_ID = 1
AUTHENTICATION_BACKENDS = [ AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend", # default "django.contrib.auth.backends.ModelBackend", # default

View File

@ -75,3 +75,46 @@ def generate_osm_city_data(lat, lon, dist=400, scale=1.0):
buildings = [] buildings = []
return {"buildings": buildings} return {"buildings": buildings}
def generate_osm_road_midpoints_only(lat, lon, dist=400, scale=1.0):
import osmnx as ox
import networkx as nx
from shapely.geometry import LineString
import geopandas as gpd
import random
print(f"🛣️ Fetching road midpoints only at ({lat}, {lon})")
# Obtener grafo y convertir a GeoDataFrame con geometría
G = ox.graph_from_point((lat, lon), dist=dist, network_type='drive').to_undirected()
edge_gdf = ox.graph_to_gdfs(G, nodes=False, edges=True)
# Proyectar a metros (3857)
edge_gdf = edge_gdf.to_crs(epsg=3857)
midpoints_raw = []
for _, row in edge_gdf.iterrows():
geom = row.get('geometry', None)
if isinstance(geom, LineString) and geom.length > 0:
midpoint = geom.interpolate(0.5, normalized=True)
midpoints_raw.append((midpoint.x, midpoint.y))
if not midpoints_raw:
return {"roads": []}
avg_x = sum(x for x, _ in midpoints_raw) / len(midpoints_raw)
avg_z = sum(z for _, z in midpoints_raw) / len(midpoints_raw)
midpoints = [{
"id": f"RD-{i}",
"position_x": (x - avg_x) * scale,
"position_z": (z - avg_z) * scale,
"status": random.choice(["OK", "Warning", "Critical", "Offline"])
} for i, (x, z) in enumerate(midpoints_raw)]
# DEBUG
for i in range(min(5, len(midpoints))):
print(f"🧭 Road {i}: x={midpoints[i]['position_x']:.2f}, z={midpoints[i]['position_z']:.2f}")
return {"roads": midpoints}

View File

@ -0,0 +1,38 @@
<a-entity
class="status-gauge-augmented"
gauge-click-toggle
position="{{ pos_x|default:'0' }} {{ pos_y|default:'1.5' }} {{ pos_z|default:'0' }}"
scale="{{ scale|default:'0.3 0.3 0.3' }}">
<!-- Glass core -->
<a-circle
radius="0.6"
class="glass-core"
color="{{ ring_color|default:'#00FFFF' }}"
material="shader: standard; transparent: true; opacity: 0.3; metalness: 0.8; roughness: 0.1; side: double"
rotation="0 0 0">
</a-circle>
<!-- Animated outer ring -->
<a-ring
class="gauge-ring"
radius-inner="0.7"
radius-outer="0.9"
color="{{ ring_color|default:'#00FFFF' }}"
material="shader: flat; opacity: 0.8; side: double"
rotation="0 0 0"
animation="property: rotation; to: 0 90 0; loop: true; dur: 2000; easing: linear">
</a-ring>
<!-- Text label -->
<a-text
class="gauge-label"
value="{{ label|default:'Status\nOK' }}"
align="center"
color="#FFFFFF"
width="2"
side="double"
position="0 0 0.02"
rotation="0 0 0">
</a-text>
</a-entity>

View File

@ -0,0 +1,65 @@
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Digital Twin City - AR</title>
<!-- A-Frame & AR.js -->
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://raw.githack.com/AR-js-org/AR.js/3.4.5/aframe/build/aframe-ar.js"></script>
<!-- Billboard: make objects face the camera -->
<script>
AFRAME.registerComponent('billboard', {
schema: {type: 'selector'},
tick: function () {
if (!this.data) return;
this.el.object3D.lookAt(this.data.object3D.position);
}
});
</script>
<!-- Toggle gauge color/status -->
<script>
AFRAME.registerComponent('gauge-click-toggle', {
init: function () {
const colors = ["#00FF00", "#FFFF00", "#FF0000", "#00FFFF"];
const statuses = ["OK", "Warning", "Critical", "Offline"];
let i = 0;
const ring = this.el.querySelector('.gauge-ring');
const label = this.el.querySelector('.gauge-label');
this.el.addEventListener('click', () => {
i = (i + 1) % colors.length;
if (ring) ring.setAttribute('color', colors[i]);
if (label) {
const current = label.getAttribute('value');
const idLine = current.split("\n")[0];
label.setAttribute('value', `${idLine}\n${statuses[i]}`);
}
});
}
});
</script>
</head>
<body>
<a-scene embedded arjs="sourceType: webcam; debugUIEnabled: false" vr-mode-ui="enabled: false">
<!-- Cámara y controles -->
<a-entity id="mainCamera" camera look-controls wasd-controls position="0 2 5">
<a-cursor color="#FF0000"></a-cursor>
</a-entity>
<!-- Solo los gauges -->
{% for road in city_data.roads %}
<a-entity id="{{ road.id }}" status="{{ road.status }}">
<a-entity
position="{{ road.position_x }} 1.5 {{ road.position_z }}">
{% include "pxy_city_digital_twins/_status_gauge.html" with ring_color="#FF6600" offset_y="0" status=road.status id=road.id %}
</a-entity>
</a-entity>
{% endfor %}
</a-scene>
</body>
</html>

View File

@ -0,0 +1,59 @@
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Gauge Ahead</title>
<!-- A-Frame & AR.js -->
<script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
<script src="https://raw.githack.com/AR-js-org/AR.js/3.4.5/aframe/build/aframe-ar.js"></script>
<!-- Billboard & click toggle (ya los usas en tu sistema) -->
<script>
AFRAME.registerComponent('billboard', {
schema: {type: 'selector'},
tick: function () {
if (!this.data) return;
this.el.object3D.lookAt(this.data.object3D.position);
}
});
AFRAME.registerComponent('gauge-click-toggle', {
init: function () {
const colors = ["#00FF00", "#FFFF00", "#FF0000", "#00FFFF"];
const statuses = ["OK", "Warning", "Critical", "Offline"];
let i = 0;
const ring = this.el.querySelector('.gauge-ring');
const label = this.el.querySelector('.gauge-label');
this.el.addEventListener('click', () => {
i = (i + 1) % colors.length;
if (ring) ring.setAttribute('color', colors[i]);
if (label) {
const current = label.getAttribute('value');
const idLine = current.split("\n")[0];
label.setAttribute('value', `${idLine}\n${statuses[i]}`);
}
});
}
});
</script>
</head>
<body>
<a-scene embedded arjs="sourceType: webcam; debugUIEnabled: false" vr-mode-ui="enabled: false">
<!-- Cámara -->
<a-entity id="mainCamera" camera look-controls wasd-controls position="0 2 5">
<a-cursor color="#FF0000"></a-cursor>
</a-entity>
<!-- Gauge fijo visible a 3 unidades frente a cámara -->
<a-entity position="0 1.5 -3">
{% include "pxy_city_digital_twins/_status_gauge_augmented.html" with pos_x="0" pos_y="1.6" pos_z="-3" scale="2.7 2.7 2.7" ring_color="#00FF00" label="WELCOME\nUSER" %}
</a-entity>
</a-scene>
</body>
</html>

View File

@ -2,10 +2,11 @@ from django.urls import path
from . import views from . import views
urlpatterns = [ urlpatterns = [
# Pattern to accept UUIDs # Digital Twin (normal)
path('city/digital/twin/<uuid:city_id>/', views.city_digital_twin, name='city_digital_twin_uuid'), path('city/digital/twin/<uuid:city_id>/', views.city_digital_twin, name='city_digital_twin_uuid'),
# Pattern to accept string words
path('city/digital/twin/<str:city_id>/', views.city_digital_twin, name='city_digital_twin_str'), path('city/digital/twin/<str:city_id>/', views.city_digital_twin, name='city_digital_twin_str'),
# Augmented Digital Twin
path('city/augmented/digital/twin/<uuid:city_id>/', views.city_augmented_digital_twin, name='city_augmented_digital_twin_uuid'),
path('city/augmented/digital/twin/<str:city_id>/', views.city_augmented_digital_twin, name='city_augmented_digital_twin_str'),
] ]

View File

@ -12,7 +12,7 @@ from .services.layouts import (
) )
from .services.random_city import generate_random_city_data from .services.random_city import generate_random_city_data
from .services.com_con_city import generate_com_con_city_data from .services.com_con_city import generate_com_con_city_data
from .services.osm_city import generate_osm_city_data from .services.osm_city import generate_osm_city_data, generate_osm_road_midpoints_only
@ -135,3 +135,33 @@ def get_example_data():
} }
] ]
} }
def city_augmented_digital_twin(request, city_id):
try:
lat = float(request.GET.get('lat', 0))
long = float(request.GET.get('long', 0))
scale = float(request.GET.get('scale', 1.0)) # default to 1.0
if city_id == "osm_city":
city_data = generate_osm_road_midpoints_only(lat, long, scale=scale)
elif city_id == "random_city":
city_data = generate_random_city_data()
elif city_id == "gauge_ahead":
# No city data needed, just render the special AR scene
return render(request, 'pxy_city_digital_twins/spawn_gauge_ahead.html')
else:
raise Http404("Unsupported city_id for AR view")
preset = get_environment_preset(lat, long)
context = {
'city_data': city_data,
'environment_preset': preset,
'lat': lat,
'long': long,
}
return render(request, 'pxy_city_digital_twins/city_augmented_digital_twin.html', context)
except (ValueError, TypeError):
raise Http404("Invalid parameters provided.")

View File

@ -1,5 +1,6 @@
from django.urls import path from django.urls import path
from pxy_dashboard.apps.views import ( from pxy_dashboard.apps.views import (
# Existing
apps_calendar_view, apps_calendar_view,
apps_chat_view, apps_chat_view,
apps_email_inbox_view, apps_email_inbox_view,
@ -8,24 +9,70 @@ from pxy_dashboard.apps.views import (
apps_tasks_details, apps_tasks_details,
apps_kanban_board, apps_kanban_board,
apps_file_manager, apps_file_manager,
# New Waste Collection (Pre-Operation)
apps_zone_definition,
apps_route_optimization,
apps_dispatch_plan,
# New Operation
apps_urban_digital_twin,
apps_whatsapp_bot,
apps_telegram_bot,
apps_facebook_pages_bot,
apps_feedback_loop,
# New Post-Operation
apps_route_analytics,
apps_feedback_review,
apps_twin_refinement,
# New System Control
apps_sync_monitor,
apps_logs_webhooks,
apps_logs_parsing,
apps_logs_limits,
apps_config_api,
apps_config_map,
apps_config_collection,
) )
app_name = "apps" app_name = "apps"
urlpatterns = [ urlpatterns = [
# Calaendar # Existing
path("calendar", view=apps_calendar_view, name="calendar"), path("calendar", apps_calendar_view, name="calendar"),
# Chat path("chat", apps_chat_view, name="chat"),
path("chat", view=apps_chat_view, name="chat"), path("email-inbox", apps_email_inbox_view, name="email-inbox"),
# Email path("email-read", apps_email_read, name="email-read"),
path("email-inbox", view=apps_email_inbox_view, name="email-inbox"), path("tasks", apps_tasks, name="tasks"),
path("email-read", view=apps_email_read, name="email-read"), path("tasks-details", apps_tasks_details, name="tasks-details"),
# Tasks path("kanban-board", apps_kanban_board, name="kanban"),
path("tasks", view=apps_tasks, name="tasks"), path("file-manager", apps_file_manager, name="file-manager"),
path("tasks-details", view=apps_tasks_details, name="tasks-details"),
# Kanban
path("kanban-board", view=apps_kanban_board, name="kanban"),
# File Manager
path("file-manager", view=apps_file_manager, name="file-manager"),
# Pre-Operation
path("zone-definition", apps_zone_definition, name="zone-definition"),
path("route-optimization", apps_route_optimization, name="route-optimization"),
path("dispatch-plan", apps_dispatch_plan, name="dispatch-plan"),
# Operation
path("urban-digital-twin", apps_urban_digital_twin, name="urban-digital-twin"),
path("bot-whatsapp", apps_whatsapp_bot, name="bot-whatsapp"),
path("bot-telegram", apps_telegram_bot, name="bot-telegram"),
path("bot-facebook", apps_facebook_pages_bot, name="bot-facebook"),
path("feedback-loop", apps_feedback_loop, name="feedback-loop"),
# Post-Operation
path("route-analytics", apps_route_analytics, name="route-analytics"),
path("feedback-review", apps_feedback_review, name="feedback-review"),
path("twin-refinement", apps_twin_refinement, name="twin-refinement"),
# System Control
path("sync-monitor", apps_sync_monitor, name="sync-monitor"),
path("logs-webhooks", apps_logs_webhooks, name="logs-webhooks"),
path("logs-parsing", apps_logs_parsing, name="logs-parsing"),
path("logs-limits", apps_logs_limits, name="logs-limits"),
path("config-api", apps_config_api, name="config-api"),
path("config-map", apps_config_map, name="config-map"),
path("config-collection", apps_config_collection, name="config-collection"),
] ]

View File

@ -5,12 +5,13 @@ from django.contrib.auth.mixins import LoginRequiredMixin
class AppsView(LoginRequiredMixin, TemplateView): class AppsView(LoginRequiredMixin, TemplateView):
pass pass
# ───── Existing ──────────────────────────────────────────────────────────────
# Calendar # Calendar
apps_calendar_view = AppsView.as_view(template_name="pxy_dashboard/apps/apps-calendar.html") apps_calendar_view = AppsView.as_view(template_name="pxy_dashboard/apps/apps-calendar.html")
# Chat # Chat
apps_chat_view = AppsView.as_view(template_name="pxy_dashboard/apps/apps-chat.html") apps_chat_view = AppsView.as_view(template_name="pxy_dashboard/apps/apps-chat.html")
# Mail Box # Email
apps_email_inbox_view = AppsView.as_view(template_name="pxy_dashboard/apps/apps-email-inbox.html") apps_email_inbox_view = AppsView.as_view(template_name="pxy_dashboard/apps/apps-email-inbox.html")
apps_email_read = AppsView.as_view(template_name="pxy_dashboard/apps/apps-email-read.html") apps_email_read = AppsView.as_view(template_name="pxy_dashboard/apps/apps-email-read.html")
# Tasks # Tasks
@ -20,3 +21,31 @@ apps_tasks_details = AppsView.as_view(template_name="pxy_dashboard/apps/apps-tas
apps_kanban_board = AppsView.as_view(template_name="pxy_dashboard/apps/apps-kanban.html") apps_kanban_board = AppsView.as_view(template_name="pxy_dashboard/apps/apps-kanban.html")
# File Manager # File Manager
apps_file_manager = AppsView.as_view(template_name="pxy_dashboard/apps/apps-file-manager.html") apps_file_manager = AppsView.as_view(template_name="pxy_dashboard/apps/apps-file-manager.html")
# ───── Waste Collection Intelligence ─────────────────────────────────────────
# Pre-Operation
apps_zone_definition = AppsView.as_view(template_name="pxy_dashboard/apps/apps-zone-definition.html")
apps_route_optimization = AppsView.as_view(template_name="pxy_dashboard/apps/apps-route-optimization.html")
apps_dispatch_plan = AppsView.as_view(template_name="pxy_dashboard/apps/apps-dispatch-plan.html")
# Operation Physical & Social Digital Twin
apps_urban_digital_twin = AppsView.as_view(template_name="pxy_dashboard/apps/apps-urban-digital-twin.html")
apps_whatsapp_bot = AppsView.as_view(template_name="pxy_dashboard/apps/apps-whatsapp-bot.html")
apps_telegram_bot = AppsView.as_view(template_name="pxy_dashboard/apps/apps-telegram-bot.html")
apps_facebook_pages_bot = AppsView.as_view(template_name="pxy_dashboard/apps/apps-facebook-pages-bot.html")
apps_feedback_loop = AppsView.as_view(template_name="pxy_dashboard/apps/apps-feedback-loop.html")
# Post-Operation
apps_route_analytics = AppsView.as_view(template_name="pxy_dashboard/apps/apps-route-analytics.html")
apps_feedback_review = AppsView.as_view(template_name="pxy_dashboard/apps/apps-feedback-review.html")
apps_twin_refinement = AppsView.as_view(template_name="pxy_dashboard/apps/apps-twin-refinement.html")
# System Control
apps_sync_monitor = AppsView.as_view(template_name="pxy_dashboard/apps/apps-sync-monitor.html")
apps_logs_webhooks = AppsView.as_view(template_name="pxy_dashboard/apps/apps-logs-webhooks.html")
apps_logs_parsing = AppsView.as_view(template_name="pxy_dashboard/apps/apps-logs-parsing.html")
apps_logs_limits = AppsView.as_view(template_name="pxy_dashboard/apps/apps-logs-limits.html")
apps_config_api = AppsView.as_view(template_name="pxy_dashboard/apps/apps-config-api.html")
apps_config_map = AppsView.as_view(template_name="pxy_dashboard/apps/apps-config-map.html")
apps_config_collection = AppsView.as_view(template_name="pxy_dashboard/apps/apps-config-collection.html")

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Config Api</h2>
<p>This is a placeholder page for <code>apps-config-api.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Config Collection</h2>
<p>This is a placeholder page for <code>apps-config-collection.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Config Map</h2>
<p>This is a placeholder page for <code>apps-config-map.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Dispatch Plan</h2>
<p>This is a placeholder page for <code>apps-dispatch-plan.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Facebook Pages Bot</h2>
<p>This is a placeholder page for <code>apps-facebook-pages-bot.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Feedback Loop</h2>
<p>This is a placeholder page for <code>apps-feedback-loop.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Feedback Review</h2>
<p>This is a placeholder page for <code>apps-feedback-review.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Logs Limits</h2>
<p>This is a placeholder page for <code>apps-logs-limits.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Logs Parsing</h2>
<p>This is a placeholder page for <code>apps-logs-parsing.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Logs Webhooks</h2>
<p>This is a placeholder page for <code>apps-logs-webhooks.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Route Analytics</h2>
<p>This is a placeholder page for <code>apps-route-analytics.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Route Optimization</h2>
<p>This is a placeholder page for <code>apps-route-optimization.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Sync Monitor</h2>
<p>This is a placeholder page for <code>apps-sync-monitor.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Telegram Bot</h2>
<p>This is a placeholder page for <code>apps-telegram-bot.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Twin Refinement</h2>
<p>This is a placeholder page for <code>apps-twin-refinement.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Urban Digital Twin</h2>
<p>This is a placeholder page for <code>apps-urban-digital-twin.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Whatsapp Bot</h2>
<p>This is a placeholder page for <code>apps-whatsapp-bot.html</code></p>
{% endblock %}

View File

@ -0,0 +1,5 @@
{% extends "pxy_dashboard/partials/base.html" %}
{% block content %}
<h2>Zone Definition</h2>
<p>This is a placeholder page for <code>apps-zone-definition.html</code></p>
{% endblock %}

View File

@ -0,0 +1,666 @@
{% load static %}
<!-- ========== Left Sidebar Start ========== -->
<div class="leftside-menu">
<!-- Brand Logo Light -->
<a href="/" class="logo logo-light">
<span class="logo-lg">
<img src="{% static 'dashboard/images/logo.png' %}" alt="logo">
</span>
<span class="logo-sm">
<img src="{% static 'dashboard/images/logo-sm.png' %}" alt="small logo">
</span>
</a>
<!-- Brand Logo Dark -->
<a href="/" class="logo logo-dark">
<span class="logo-lg">
<img src="{% static 'dashboard/images/logo-dark.png' %}" alt="dark logo">
</span>
<span class="logo-sm">
<img src="{% static 'dashboard/images/logo-sm.png' %}" alt="small logo">
</span>
</a>
<!-- Sidebar Hover Menu Toggle Button -->
<div class="button-sm-hover" data-bs-toggle="tooltip" data-bs-placement="right" title="Show Full Sidebar">
<i class="ri-checkbox-blank-circle-line align-middle"></i>
</div>
<!-- Full Sidebar Menu Close Button -->
<div class="button-close-fullsidebar">
<i class="ri-close-fill align-middle"></i>
</div>
<!-- Sidebar -left -->
<div class="h-100" id="leftside-menu-container" data-simplebar>
<!-- Leftbar User -->
<div class="leftbar-user p-3 text-white">
<a href="{% url 'custom:profile' %}" class="d-flex align-items-center text-reset">
<div class="flex-shrink-0">
<img src="{% static 'dashboard/images/users/avatar-1.jpg' %}" alt="user-image" height="42" class="rounded-circle shadow">
</div>
<div class="flex-grow-1 ms-2">
<span class="fw-semibold fs-15 d-block">Doris Larson</span>
<span class="fs-13">Founder</span>
</div>
<div class="ms-auto">
<i class="ri-arrow-right-s-fill fs-20"></i>
</div>
</a>
</div>
{% load sidebar_menu %}
<ul class="side-nav">
{% render_sidebar_menu sidebar_menu %}
</ul>
<!--- Sidemenu -->
<ul class="side-nav">
<li class="side-nav-title mt-1"> Main</li>
<li class="side-nav-item">
<a href="{% url 'index' %}" class="side-nav-link">
<i class="ri-dashboard-2-fill"></i>
<span class="badge bg-success float-end">9+</span>
<span> Dashboard </span>
</a>
</li>
<li class="side-nav-item">
<a href="{% url 'apps:calendar' %}" class="side-nav-link">
<i class="ri-calendar-2-fill"></i>
<span> Calendar </span>
</a>
</li>
<li class="side-nav-item">
<a href="{% url 'apps:chat' %}" class="side-nav-link">
<i class="ri-chat-voice-fill"></i>
<span> Chat </span>
</a>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarEmail" aria-expanded="false" aria-controls="sidebarEmail"
class="side-nav-link">
<i class="ri-mail-fill"></i>
<span> Email </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarEmail">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'apps:email-inbox' %}">Inbox</a>
</li>
<li>
<a href="{% url 'apps:email-read' %}">Read Email</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarTasks" aria-expanded="false" aria-controls="sidebarTasks"
class="side-nav-link">
<i class="ri-list-check-3"></i>
<span> Tasks </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarTasks">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'apps:tasks' %}">List</a>
</li>
<li>
<a href="{% url 'apps:tasks-details' %}">Details</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a href="{% url 'apps:kanban' %}" class="side-nav-link">
<i class="ri-clipboard-fill"></i>
<span> Kanban Board </span>
</a>
</li>
<li class="side-nav-item">
<a href="{% url 'apps:file-manager' %}" class="side-nav-link">
<i class="ri-folder-4-fill"></i>
<span class="badge bg-purple float-end">1 File</span>
<span> File Manager </span>
</a>
</li>
<li class="side-nav-title">Custom</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarPages" aria-expanded="false" aria-controls="sidebarPages"
class="side-nav-link">
<i class="ri-pages-fill"></i>
<span> Pages </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarPages">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'custom:profile' %}">Profile</a>
</li>
<li>
<a href="{% url 'custom:invoice' %}">Invoice</a>
</li>
<li>
<a href="{% url 'custom:faq' %}">FAQ</a>
</li>
<li>
<a href="{% url 'custom:pricing' %}">Pricing</a>
</li>
<li>
<a href="{% url 'custom:maintenance' %}">Maintenance</a>
</li>
<li>
<a href="{% url 'custom:starter' %}">Starter Page</a>
</li>
<li>
<a href="{% url 'custom:preloader' %}">With Preloader</a>
</li>
<li>
<a href="{% url 'custom:timeline' %}">Timeline</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarPagesAuth" aria-expanded="false" aria-controls="sidebarPagesAuth"
class="side-nav-link">
<i class="ri-group-2-fill"></i>
<span> Auth Pages </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarPagesAuth">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'custom:login' %}">Login</a>
</li>
<li>
<a href="{% url 'custom:login-2' %}">Login 2</a>
</li>
<li>
<a href="{% url 'custom:register' %}">Register</a>
</li>
<li>
<a href="{% url 'custom:register-2' %}">Register 2</a>
</li>
<li>
<a href="{% url 'custom:logout' %}">Logout</a>
</li>
<li>
<a href="{% url 'custom:logout-2' %}">Logout 2</a>
</li>
<li>
<a href="{% url 'custom:recoverpw' %}">Recover Password</a>
</li>
<li>
<a href="{% url 'custom:recoverpw-2' %}">Recover Password 2</a>
</li>
<li>
<a href="{% url 'custom:lock-screen' %}">Lock Screen</a>
</li>
<li>
<a href="{% url 'custom:lock-screen-2' %}">Lock Screen 2</a>
</li>
<li>
<a href="{% url 'custom:confirm-mail' %}">Confirm Mail</a>
</li>
<li>
<a href="{% url 'custom:confirm-mail-2' %}">Confirm Mail 2</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarPagesError" aria-expanded="false" aria-controls="sidebarPagesError"
class="side-nav-link">
<i class="ri-error-warning-fill"></i>
<span> Error Pages </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarPagesError">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'custom:error-404' %}">Error 404</a>
</li>
<li>
<a href="{% url 'custom:error-404-alt' %}">Error 404-alt</a>
</li>
<li>
<a href="{% url 'custom:error-500' %}">Error 500</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarLayouts" aria-expanded="false" aria-controls="sidebarLayouts"
class="side-nav-link">
<i class="ri-layout-3-fill"></i>
<span> Layouts </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarLayouts">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'layouts:horizontal' %}" target="_blank">Horizontal</a>
</li>
<li>
<a href="{% url 'layouts:detached' %}" target="_blank">Detached</a>
</li>
<li>
<a href="{% url 'layouts:full' %}" target="_blank">Full View</a>
</li>
<li>
<a href="{% url 'layouts:fullscreen' %}" target="_blank">Fullscreen View</a>
</li>
<li>
<a href="{% url 'layouts:hover' %}" target="_blank">Hover Menu</a>
</li>
<li>
<a href="{% url 'layouts:compact' %}" target="_blank">Compact</a>
</li>
<li>
<a href="{% url 'layouts:icon-view' %}" target="_blank">Icon View</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-title">Components</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarBaseUI" aria-expanded="false" aria-controls="sidebarBaseUI"
class="side-nav-link">
<i class="ri-suitcase-fill"></i>
<span> Base UI </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarBaseUI">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:accordions' %}">Accordions</a>
</li>
<li>
<a href="{% url 'components:alerts' %}">Alerts</a>
</li>
<li>
<a href="{% url 'components:avatars' %}">Avatars</a>
</li>
<li>
<a href="{% url 'components:badges' %}">Badges</a>
</li>
<li>
<a href="{% url 'components:breadcrumb' %}">Breadcrumb</a>
</li>
<li>
<a href="{% url 'components:buttons' %}">Buttons</a>
</li>
<li>
<a href="{% url 'components:cards' %}">Cards</a>
</li>
<li>
<a href="{% url 'components:carousel' %}">Carousel</a>
</li>
<li>
<a href="{% url 'components:collapse' %}">Collapse</a>
</li>
<li>
<a href="{% url 'components:dropdowns' %}">Dropdowns</a>
</li>
<li>
<a href="{% url 'components:embed-video' %}">Embed Video</a>
</li>
<li>
<a href="{% url 'components:grid' %}">Grid</a>
</li>
<li>
<a href="{% url 'components:links' %}">Links</a>
</li>
<li>
<a href="{% url 'components:list-group' %}">List Group</a>
</li>
<li>
<a href="{% url 'components:modals' %}">Modals</a>
</li>
<li>
<a href="{% url 'components:notifications' %}">Notifications</a>
</li>
<li>
<a href="{% url 'components:offcanvas' %}">Offcanvas</a>
</li>
<li>
<a href="{% url 'components:placeholders' %}">Placeholders</a>
</li>
<li>
<a href="{% url 'components:pagination' %}">Pagination</a>
</li>
<li>
<a href="{% url 'components:popovers' %}">Popovers</a>
</li>
<li>
<a href="{% url 'components:progress' %}">Progress</a>
</li>
<li>
<a href="{% url 'components:spinners' %}">Spinners</a>
</li>
<li>
<a href="{% url 'components:tabs' %}">Tabs</a>
</li>
<li>
<a href="{% url 'components:tooltips' %}">Tooltips</a>
</li>
<li>
<a href="{% url 'components:typography' %}">Typography</a>
</li>
<li>
<a href="{% url 'components:utilities' %}">Utilities</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarExtendedUI" aria-expanded="false" aria-controls="sidebarExtendedUI"
class="side-nav-link">
<i class="ri-paint-brush-fill"></i>
<span> Extended UI </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarExtendedUI">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:extended-dragula' %}">Dragula</a>
</li>
<li>
<a href="{% url 'components:extended-range-slider' %}">Range Slider</a>
</li>
<li>
<a href="{% url 'components:extended-ratings' %}">Ratings</a>
</li>
<li>
<a href="{% url 'components:extended-scrollbar' %}">Scrollbar</a>
</li>
<li>
<a href="{% url 'components:extended-scrollspy' %}">Scrollspy</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a href="{% url 'components:widgets' %}" class="side-nav-link">
<i class="ri-cup-fill"></i>
<span> Widgets </span>
</a>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarIcons" aria-expanded="false" aria-controls="sidebarIcons"
class="side-nav-link">
<i class="ri-copper-diamond-fill"></i>
<span> Icons </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarIcons">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:icons-remixicons' %}">Remix Icons</a>
</li>
<li>
<a href="{% url 'components:icons-bootstrap' %}">Bootstrap Icons</a>
</li>
<li>
<a href="{% url 'components:icons-material' %}">Material Symbol Icons</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarCharts" aria-expanded="false" aria-controls="sidebarCharts"
class="side-nav-link">
<i class="ri-bubble-chart-fill"></i>
<span> Charts </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarCharts">
<ul class="side-nav-second-level">
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarApexCharts" aria-expanded="false"
aria-controls="sidebarApexCharts">
<span> Apex Charts </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarApexCharts">
<ul class="side-nav-third-level">
<li>
<a href="{% url 'components:apex-area' %}">Area</a>
</li>
<li>
<a href="{% url 'components:apex-bar' %}">Bar</a>
</li>
<li>
<a href="{% url 'components:apex-bubble' %}">Bubble</a>
</li>
<li>
<a href="{% url 'components:apex-candlestick' %}">Candlestick</a>
</li>
<li>
<a href="{% url 'components:apex-column' %}">Column</a>
</li>
<li>
<a href="{% url 'components:apex-heatmap' %}">Heatmap</a>
</li>
<li>
<a href="{% url 'components:apex-line' %}">Line</a>
</li>
<li>
<a href="{% url 'components:apex-mixed' %}">Mixed</a>
</li>
<li>
<a href="{% url 'components:apex-timeline' %}">Timeline</a>
</li>
<li>
<a href="{% url 'components:apex-boxplot' %}">Boxplot</a>
</li>
<li>
<a href="{% url 'components:apex-treemap' %}">Treemap</a>
</li>
<li>
<a href="{% url 'components:apex-pie' %}">Pie</a>
</li>
<li>
<a href="{% url 'components:apex-radar' %}">Radar</a>
</li>
<li>
<a href="{% url 'components:apex-radialbar' %}">RadialBar</a>
</li>
<li>
<a href="{% url 'components:apex-scatter' %}">Scatter</a>
</li>
<li>
<a href="{% url 'components:apex-polar-area' %}">Polar Area</a>
</li>
<li>
<a href="{% url 'components:apex-sparklines' %}">Sparklines</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarChartJSCharts" aria-expanded="false"
aria-controls="sidebarChartJSCharts">
<span> ChartJS </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarChartJSCharts">
<ul class="side-nav-third-level">
<li>
<a href="{% url 'components:chartjs-area' %}">Area</a>
</li>
<li>
<a href="{% url 'components:chartjs-bar' %}">Bar</a>
</li>
<li>
<a href="{% url 'components:chartjs-line' %}">Line</a>
</li>
<li>
<a href="{% url 'components:chartjs-other' %}">Other</a>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarForms" aria-expanded="false" aria-controls="sidebarForms"
class="side-nav-link">
<i class="ri-survey-fill"></i>
<span> Forms </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarForms">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:form-elements' %}">Basic Elements</a>
</li>
<li>
<a href="{% url 'components:form-advanced' %}">Form Advanced</a>
</li>
<li>
<a href="{% url 'components:form-validation' %}">Validation</a>
</li>
<li>
<a href="{% url 'components:form-wizard' %}">Wizard</a>
</li>
<li>
<a href="{% url 'components:form-fileuploads' %}">File Uploads</a>
</li>
<li>
<a href="{% url 'components:form-editors' %}">Editors</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarTables" aria-expanded="false" aria-controls="sidebarTables"
class="side-nav-link">
<i class="ri-table-fill"></i>
<span> Tables </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarTables">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:tables-basic' %}">Basic Tables</a>
</li>
<li>
<a href="{% url 'components:tables-datatable' %}">Data Tables</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarMaps" aria-expanded="false" aria-controls="sidebarMaps"
class="side-nav-link">
<i class="ri-map-2-fill"></i>
<span> Maps </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarMaps">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:google-map' %}">Google Maps</a>
</li>
<li>
<a href="{% url 'components:vector-map' %}">Vector Maps</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarMultiLevel" aria-expanded="false" aria-controls="sidebarMultiLevel"
class="side-nav-link">
<i class="ri-share-fill"></i>
<span> Multi Level </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarMultiLevel">
<ul class="side-nav-second-level">
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarSecondLevel" aria-expanded="false"
aria-controls="sidebarSecondLevel">
<span> Second Level </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarSecondLevel">
<ul class="side-nav-third-level">
<li>
<a href="javascript: void(0);">Item 1</a>
</li>
<li>
<a href="javascript: void(0);">Item 2</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarThirdLevel" aria-expanded="false"
aria-controls="sidebarThirdLevel">
<span> Third Level </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarThirdLevel">
<ul class="side-nav-third-level">
<li>
<a href="javascript: void(0);">Item 1</a>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarFourthLevel" aria-expanded="false"
aria-controls="sidebarFourthLevel">
<span> Item 2 </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarFourthLevel">
<ul class="side-nav-forth-level">
<li>
<a href="javascript: void(0);">Item 2.1</a>
</li>
<li>
<a href="javascript: void(0);">Item 2.2</a>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
<!--- End Sidemenu -->
<div class="clearfix"></div>
</div>
</div>
<!-- ========== Left Sidebar End ========== -->

View File

@ -0,0 +1,176 @@
<!-- Theme Settings -->
<div class="offcanvas offcanvas-end" tabindex="-1" id="theme-settings-offcanvas">
<div class="d-flex align-items-center bg-primary p-3 offcanvas-header">
<h5 class="text-white m-0">Theme Settings</h5>
<button type="button" class="btn-close btn-close-white ms-auto" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body p-0">
<div data-simplebar class="h-100">
<div class="card mb-0 p-3">
<div class="alert alert-warning" role="alert">
<strong>Customize </strong> the overall color scheme, sidebar menu, etc.
</div>
<h5 class="mt-0 fs-16 fw-bold mb-3">Choose Layout</h5>
<div class="d-flex flex-column gap-2">
<div class="form-check form-switch">
<input id="customizer-layout01" name="data-layout" type="checkbox" value="vertical" class="form-check-input" >
<label class="form-check-label" for="customizer-layout01">Vertical</label>
</div>
<div class="form-check form-switch">
<input id="customizer-layout02" name="data-layout" type="checkbox" value="horizontal" class="form-check-input">
<label class="form-check-label" for="customizer-layout02">Horizontal</label>
</div>
</div>
<h5 class="my-3 fs-16 fw-bold">Color Scheme</h5>
<div class="d-flex flex-column gap-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-bs-theme" id="layout-color-light" value="light">
<label class="form-check-label" for="layout-color-light">Light</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-bs-theme" id="layout-color-dark" value="dark">
<label class="form-check-label" for="layout-color-dark">Dark</label>
</div>
</div>
<div id="layout-width">
<h5 class="my-3 fs-16 fw-bold">Layout Mode</h5>
<div class="d-flex flex-column gap-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-layout-mode" id="layout-mode-fluid" value="fluid">
<label class="form-check-label" for="layout-mode-fluid">Fluid</label>
</div>
<div id="layout-boxed">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-layout-mode" id="layout-mode-boxed" value="boxed">
<label class="form-check-label" for="layout-mode-boxed">Boxed</label>
</div>
</div>
<div id="layout-detached">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-layout-mode" id="data-layout-detached" value="detached">
<label class="form-check-label" for="data-layout-detached">Detached</label>
</div>
</div>
</div>
</div>
<h5 class="my-3 fs-16 fw-bold">Topbar Color</h5>
<div class="d-flex flex-column gap-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-topbar-color" id="topbar-color-light" value="light">
<label class="form-check-label" for="topbar-color-light">Light</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-topbar-color" id="topbar-color-dark" value="dark">
<label class="form-check-label" for="topbar-color-dark">Dark</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-topbar-color" id="topbar-color-brand" value="brand">
<label class="form-check-label" for="topbar-color-brand">Brand</label>
</div>
</div>
<div>
<h5 class="my-3 fs-16 fw-bold">Menu Color</h5>
<div class="d-flex flex-column gap-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-menu-color" id="leftbar-color-light" value="light">
<label class="form-check-label" for="leftbar-color-light">Light</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-menu-color" id="leftbar-color-dark" value="dark">
<label class="form-check-label" for="leftbar-color-dark">Dark</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-menu-color" id="leftbar-color-brand" value="brand">
<label class="form-check-label" for="leftbar-color-brand">Brand</label>
</div>
</div>
</div>
<div id="sidebar-size">
<h5 class="my-3 fs-16 fw-bold">Sidebar Size</h5>
<div class="d-flex flex-column gap-2">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-sidenav-size" id="leftbar-size-default" value="default">
<label class="form-check-label" for="leftbar-size-default">Default</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-sidenav-size" id="leftbar-size-compact" value="compact">
<label class="form-check-label" for="leftbar-size-compact">Compact</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-sidenav-size" id="leftbar-size-small" value="condensed">
<label class="form-check-label" for="leftbar-size-small">Condensed</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-sidenav-size" id="leftbar-size-small-hover" value="sm-hover">
<label class="form-check-label" for="leftbar-size-small-hover">Hover View</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-sidenav-size" id="leftbar-size-full" value="full">
<label class="form-check-label" for="leftbar-size-full">Full Layout</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" name="data-sidenav-size" id="leftbar-size-fullscreen" value="fullscreen">
<label class="form-check-label" for="leftbar-size-fullscreen">Fullscreen Layout</label>
</div>
</div>
</div>
<div id="layout-position">
<h5 class="my-3 fs-16 fw-bold">Layout Position</h5>
<div class="btn-group checkbox" role="group">
<input type="radio" class="btn-check" name="data-layout-position" id="layout-position-fixed" value="fixed">
<label class="btn btn-soft-primary w-sm" for="layout-position-fixed">Fixed</label>
<input type="radio" class="btn-check" name="data-layout-position" id="layout-position-scrollable" value="scrollable">
<label class="btn btn-soft-primary w-sm ms-0" for="layout-position-scrollable">Scrollable</label>
</div>
</div>
<div id="sidebar-user">
<div class="d-flex justify-content-between align-items-center mt-3">
<label class="fs-16 fw-bold m-0" for="sidebaruser-check">Sidebar User Info</label>
<div class="form-check form-switch">
<input type="checkbox" class="form-check-input" name="sidebar-user" id="sidebaruser-check">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="offcanvas-footer border-top p-3 text-center">
<div class="row">
<div class="col-6">
<button type="button" class="btn btn-light w-100" id="reset-layout">Reset</button>
</div>
<div class="col-6">
<a href="#" role="button" class="btn btn-primary w-100">Buy Now</a>
</div>
</div>
</div>
</div>

View File

@ -50,615 +50,14 @@
</a> </a>
</div> </div>
<!--- Sidemenu -->
{% load sidebar_menu %} {% load sidebar_menu %}
<ul class="side-nav"> <ul class="side-nav">
{% render_sidebar_menu sidebar_menu %} {% render_sidebar_menu sidebar_menu %}
</ul> </ul>
<!--- Sidemenu --> <!--- End Sidemenu -->
<ul class="side-nav">
<li class="side-nav-title mt-1"> Main</li>
<li class="side-nav-item">
<a href="{% url 'index' %}" class="side-nav-link">
<i class="ri-dashboard-2-fill"></i>
<span class="badge bg-success float-end">9+</span>
<span> Dashboard </span>
</a>
</li>
<li class="side-nav-item">
<a href="{% url 'apps:calendar' %}" class="side-nav-link">
<i class="ri-calendar-2-fill"></i>
<span> Calendar </span>
</a>
</li>
<li class="side-nav-item">
<a href="{% url 'apps:chat' %}" class="side-nav-link">
<i class="ri-chat-voice-fill"></i>
<span> Chat </span>
</a>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarEmail" aria-expanded="false" aria-controls="sidebarEmail"
class="side-nav-link">
<i class="ri-mail-fill"></i>
<span> Email </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarEmail">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'apps:email-inbox' %}">Inbox</a>
</li>
<li>
<a href="{% url 'apps:email-read' %}">Read Email</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarTasks" aria-expanded="false" aria-controls="sidebarTasks"
class="side-nav-link">
<i class="ri-list-check-3"></i>
<span> Tasks </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarTasks">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'apps:tasks' %}">List</a>
</li>
<li>
<a href="{% url 'apps:tasks-details' %}">Details</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a href="{% url 'apps:kanban' %}" class="side-nav-link">
<i class="ri-clipboard-fill"></i>
<span> Kanban Board </span>
</a>
</li>
<li class="side-nav-item">
<a href="{% url 'apps:file-manager' %}" class="side-nav-link">
<i class="ri-folder-4-fill"></i>
<span class="badge bg-purple float-end">1 File</span>
<span> File Manager </span>
</a>
</li>
<li class="side-nav-title">Custom</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarPages" aria-expanded="false" aria-controls="sidebarPages"
class="side-nav-link">
<i class="ri-pages-fill"></i>
<span> Pages </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarPages">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'custom:profile' %}">Profile</a>
</li>
<li>
<a href="{% url 'custom:invoice' %}">Invoice</a>
</li>
<li>
<a href="{% url 'custom:faq' %}">FAQ</a>
</li>
<li>
<a href="{% url 'custom:pricing' %}">Pricing</a>
</li>
<li>
<a href="{% url 'custom:maintenance' %}">Maintenance</a>
</li>
<li>
<a href="{% url 'custom:starter' %}">Starter Page</a>
</li>
<li>
<a href="{% url 'custom:preloader' %}">With Preloader</a>
</li>
<li>
<a href="{% url 'custom:timeline' %}">Timeline</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarPagesAuth" aria-expanded="false" aria-controls="sidebarPagesAuth"
class="side-nav-link">
<i class="ri-group-2-fill"></i>
<span> Auth Pages </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarPagesAuth">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'custom:login' %}">Login</a>
</li>
<li>
<a href="{% url 'custom:login-2' %}">Login 2</a>
</li>
<li>
<a href="{% url 'custom:register' %}">Register</a>
</li>
<li>
<a href="{% url 'custom:register-2' %}">Register 2</a>
</li>
<li>
<a href="{% url 'custom:logout' %}">Logout</a>
</li>
<li>
<a href="{% url 'custom:logout-2' %}">Logout 2</a>
</li>
<li>
<a href="{% url 'custom:recoverpw' %}">Recover Password</a>
</li>
<li>
<a href="{% url 'custom:recoverpw-2' %}">Recover Password 2</a>
</li>
<li>
<a href="{% url 'custom:lock-screen' %}">Lock Screen</a>
</li>
<li>
<a href="{% url 'custom:lock-screen-2' %}">Lock Screen 2</a>
</li>
<li>
<a href="{% url 'custom:confirm-mail' %}">Confirm Mail</a>
</li>
<li>
<a href="{% url 'custom:confirm-mail-2' %}">Confirm Mail 2</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarPagesError" aria-expanded="false" aria-controls="sidebarPagesError"
class="side-nav-link">
<i class="ri-error-warning-fill"></i>
<span> Error Pages </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarPagesError">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'custom:error-404' %}">Error 404</a>
</li>
<li>
<a href="{% url 'custom:error-404-alt' %}">Error 404-alt</a>
</li>
<li>
<a href="{% url 'custom:error-500' %}">Error 500</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarLayouts" aria-expanded="false" aria-controls="sidebarLayouts"
class="side-nav-link">
<i class="ri-layout-3-fill"></i>
<span> Layouts </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarLayouts">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'layouts:horizontal' %}" target="_blank">Horizontal</a>
</li>
<li>
<a href="{% url 'layouts:detached' %}" target="_blank">Detached</a>
</li>
<li>
<a href="{% url 'layouts:full' %}" target="_blank">Full View</a>
</li>
<li>
<a href="{% url 'layouts:fullscreen' %}" target="_blank">Fullscreen View</a>
</li>
<li>
<a href="{% url 'layouts:hover' %}" target="_blank">Hover Menu</a>
</li>
<li>
<a href="{% url 'layouts:compact' %}" target="_blank">Compact</a>
</li>
<li>
<a href="{% url 'layouts:icon-view' %}" target="_blank">Icon View</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-title">Components</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarBaseUI" aria-expanded="false" aria-controls="sidebarBaseUI"
class="side-nav-link">
<i class="ri-suitcase-fill"></i>
<span> Base UI </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarBaseUI">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:accordions' %}">Accordions</a>
</li>
<li>
<a href="{% url 'components:alerts' %}">Alerts</a>
</li>
<li>
<a href="{% url 'components:avatars' %}">Avatars</a>
</li>
<li>
<a href="{% url 'components:badges' %}">Badges</a>
</li>
<li>
<a href="{% url 'components:breadcrumb' %}">Breadcrumb</a>
</li>
<li>
<a href="{% url 'components:buttons' %}">Buttons</a>
</li>
<li>
<a href="{% url 'components:cards' %}">Cards</a>
</li>
<li>
<a href="{% url 'components:carousel' %}">Carousel</a>
</li>
<li>
<a href="{% url 'components:collapse' %}">Collapse</a>
</li>
<li>
<a href="{% url 'components:dropdowns' %}">Dropdowns</a>
</li>
<li>
<a href="{% url 'components:embed-video' %}">Embed Video</a>
</li>
<li>
<a href="{% url 'components:grid' %}">Grid</a>
</li>
<li>
<a href="{% url 'components:links' %}">Links</a>
</li>
<li>
<a href="{% url 'components:list-group' %}">List Group</a>
</li>
<li>
<a href="{% url 'components:modals' %}">Modals</a>
</li>
<li>
<a href="{% url 'components:notifications' %}">Notifications</a>
</li>
<li>
<a href="{% url 'components:offcanvas' %}">Offcanvas</a>
</li>
<li>
<a href="{% url 'components:placeholders' %}">Placeholders</a>
</li>
<li>
<a href="{% url 'components:pagination' %}">Pagination</a>
</li>
<li>
<a href="{% url 'components:popovers' %}">Popovers</a>
</li>
<li>
<a href="{% url 'components:progress' %}">Progress</a>
</li>
<li>
<a href="{% url 'components:spinners' %}">Spinners</a>
</li>
<li>
<a href="{% url 'components:tabs' %}">Tabs</a>
</li>
<li>
<a href="{% url 'components:tooltips' %}">Tooltips</a>
</li>
<li>
<a href="{% url 'components:typography' %}">Typography</a>
</li>
<li>
<a href="{% url 'components:utilities' %}">Utilities</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarExtendedUI" aria-expanded="false" aria-controls="sidebarExtendedUI"
class="side-nav-link">
<i class="ri-paint-brush-fill"></i>
<span> Extended UI </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarExtendedUI">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:extended-dragula' %}">Dragula</a>
</li>
<li>
<a href="{% url 'components:extended-range-slider' %}">Range Slider</a>
</li>
<li>
<a href="{% url 'components:extended-ratings' %}">Ratings</a>
</li>
<li>
<a href="{% url 'components:extended-scrollbar' %}">Scrollbar</a>
</li>
<li>
<a href="{% url 'components:extended-scrollspy' %}">Scrollspy</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a href="{% url 'components:widgets' %}" class="side-nav-link">
<i class="ri-cup-fill"></i>
<span> Widgets </span>
</a>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarIcons" aria-expanded="false" aria-controls="sidebarIcons"
class="side-nav-link">
<i class="ri-copper-diamond-fill"></i>
<span> Icons </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarIcons">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:icons-remixicons' %}">Remix Icons</a>
</li>
<li>
<a href="{% url 'components:icons-bootstrap' %}">Bootstrap Icons</a>
</li>
<li>
<a href="{% url 'components:icons-material' %}">Material Symbol Icons</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarCharts" aria-expanded="false" aria-controls="sidebarCharts"
class="side-nav-link">
<i class="ri-bubble-chart-fill"></i>
<span> Charts </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarCharts">
<ul class="side-nav-second-level">
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarApexCharts" aria-expanded="false"
aria-controls="sidebarApexCharts">
<span> Apex Charts </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarApexCharts">
<ul class="side-nav-third-level">
<li>
<a href="{% url 'components:apex-area' %}">Area</a>
</li>
<li>
<a href="{% url 'components:apex-bar' %}">Bar</a>
</li>
<li>
<a href="{% url 'components:apex-bubble' %}">Bubble</a>
</li>
<li>
<a href="{% url 'components:apex-candlestick' %}">Candlestick</a>
</li>
<li>
<a href="{% url 'components:apex-column' %}">Column</a>
</li>
<li>
<a href="{% url 'components:apex-heatmap' %}">Heatmap</a>
</li>
<li>
<a href="{% url 'components:apex-line' %}">Line</a>
</li>
<li>
<a href="{% url 'components:apex-mixed' %}">Mixed</a>
</li>
<li>
<a href="{% url 'components:apex-timeline' %}">Timeline</a>
</li>
<li>
<a href="{% url 'components:apex-boxplot' %}">Boxplot</a>
</li>
<li>
<a href="{% url 'components:apex-treemap' %}">Treemap</a>
</li>
<li>
<a href="{% url 'components:apex-pie' %}">Pie</a>
</li>
<li>
<a href="{% url 'components:apex-radar' %}">Radar</a>
</li>
<li>
<a href="{% url 'components:apex-radialbar' %}">RadialBar</a>
</li>
<li>
<a href="{% url 'components:apex-scatter' %}">Scatter</a>
</li>
<li>
<a href="{% url 'components:apex-polar-area' %}">Polar Area</a>
</li>
<li>
<a href="{% url 'components:apex-sparklines' %}">Sparklines</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarChartJSCharts" aria-expanded="false"
aria-controls="sidebarChartJSCharts">
<span> ChartJS </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarChartJSCharts">
<ul class="side-nav-third-level">
<li>
<a href="{% url 'components:chartjs-area' %}">Area</a>
</li>
<li>
<a href="{% url 'components:chartjs-bar' %}">Bar</a>
</li>
<li>
<a href="{% url 'components:chartjs-line' %}">Line</a>
</li>
<li>
<a href="{% url 'components:chartjs-other' %}">Other</a>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarForms" aria-expanded="false" aria-controls="sidebarForms"
class="side-nav-link">
<i class="ri-survey-fill"></i>
<span> Forms </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarForms">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:form-elements' %}">Basic Elements</a>
</li>
<li>
<a href="{% url 'components:form-advanced' %}">Form Advanced</a>
</li>
<li>
<a href="{% url 'components:form-validation' %}">Validation</a>
</li>
<li>
<a href="{% url 'components:form-wizard' %}">Wizard</a>
</li>
<li>
<a href="{% url 'components:form-fileuploads' %}">File Uploads</a>
</li>
<li>
<a href="{% url 'components:form-editors' %}">Editors</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarTables" aria-expanded="false" aria-controls="sidebarTables"
class="side-nav-link">
<i class="ri-table-fill"></i>
<span> Tables </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarTables">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:tables-basic' %}">Basic Tables</a>
</li>
<li>
<a href="{% url 'components:tables-datatable' %}">Data Tables</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarMaps" aria-expanded="false" aria-controls="sidebarMaps"
class="side-nav-link">
<i class="ri-map-2-fill"></i>
<span> Maps </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarMaps">
<ul class="side-nav-second-level">
<li>
<a href="{% url 'components:google-map' %}">Google Maps</a>
</li>
<li>
<a href="{% url 'components:vector-map' %}">Vector Maps</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarMultiLevel" aria-expanded="false" aria-controls="sidebarMultiLevel"
class="side-nav-link">
<i class="ri-share-fill"></i>
<span> Multi Level </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarMultiLevel">
<ul class="side-nav-second-level">
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarSecondLevel" aria-expanded="false"
aria-controls="sidebarSecondLevel">
<span> Second Level </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarSecondLevel">
<ul class="side-nav-third-level">
<li>
<a href="javascript: void(0);">Item 1</a>
</li>
<li>
<a href="javascript: void(0);">Item 2</a>
</li>
</ul>
</div>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarThirdLevel" aria-expanded="false"
aria-controls="sidebarThirdLevel">
<span> Third Level </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarThirdLevel">
<ul class="side-nav-third-level">
<li>
<a href="javascript: void(0);">Item 1</a>
</li>
<li class="side-nav-item">
<a data-bs-toggle="collapse" href="#sidebarFourthLevel" aria-expanded="false"
aria-controls="sidebarFourthLevel">
<span> Item 2 </span>
<span class="menu-arrow"></span>
</a>
<div class="collapse" id="sidebarFourthLevel">
<ul class="side-nav-forth-level">
<li>
<a href="javascript: void(0);">Item 2.1</a>
</li>
<li>
<a href="javascript: void(0);">Item 2.2</a>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
<!--- End Sidemenu -->
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>

View File

@ -4,8 +4,8 @@
{% elif item.children %} {% elif item.children %}
<li class="side-nav-item"> <li class="side-nav-item">
<a data-bs-toggle="collapse" href="#menu-{{ item.label|slugify }}-{{ level }}" class="side-nav-link"> <a class="side-nav-link" data-bs-toggle="collapse" href="#menu-{{ item.label|slugify }}-{{ level }}" aria-expanded="false" aria-controls="menu-{{ item.label|slugify }}-{{ level }}">
<i class="{{ item.icon }}"></i> <i class="{{ item.icon|default:'ri-folder-4-fill' }}"></i>
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
<span class="menu-arrow"></span> <span class="menu-arrow"></span>
</a> </a>
@ -17,7 +17,8 @@
{% else %} {% else %}
<li> <li>
<a href="{% url child.url %}"> <a href="{% url child.url %}">
{{ child.label }} <i class="{{ child.icon|default:'ri-arrow-right-s-line' }}"></i>
<span>{{ child.label }}</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
@ -26,15 +27,15 @@
</div> </div>
</li> </li>
{% else %} {% else %}
<li class="side-nav-item"> <li class="side-nav-item">
<a href="{% url item.url %}" class="side-nav-link" {% if item.open_in_new_tab %}target="_blank"{% endif %}> <a href="{% url item.url %}" class="side-nav-link" {% if item.open_in_new_tab %}target="_blank"{% endif %}>
<i class="{{ item.icon }}"></i> <i class="{{ item.icon|default:'ri-circle-line' }}"></i>
{% if item.badge %} {% if item.badge %}
<span class="badge bg-success float-end">{{ item.badge }}</span> <span class="badge bg-success float-end">{{ item.badge }}</span>
{% endif %} {% endif %}
<span>{{ item.label }}</span> <span>{{ item.label }}</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View File

@ -1,17 +1,201 @@
[ [
{ {
"type": "group", "type": "title",
"label": "Layouts", "label": "Waste Collection Intelligence",
"icon": "ri-layout-3-fill", "order": 1
"order": 140, },
{
"type": "submenu",
"label": "Pre-Operation",
"icon": "ri-settings-3-fill",
"order": 2,
"children": [ "children": [
{ "type": "link", "label": "Horizontal", "url": "layouts:horizontal", "order": 10 }, {
{ "type": "link", "label": "Detached", "url": "layouts:detached", "order": 20 }, "type": "link",
{ "type": "link", "label": "Full View", "url": "layouts:full", "order": 30 }, "label": "Zone Definition & Depot Upload",
{ "type": "link", "label": "Fullscreen View", "url": "layouts:fullscreen", "order": 40 }, "url": "apps:zone-definition",
{ "type": "link", "label": "Hover Menu", "url": "layouts:hover", "order": 50 }, "icon": "ri-map-pin-2-fill",
{ "type": "link", "label": "Compact", "url": "layouts:compact", "order": 60 }, "order": 1
{ "type": "link", "label": "Icon View", "url": "layouts:icon-view", "order": 70 } },
{
"type": "link",
"label": "Route Optimization",
"url": "apps:route-optimization",
"icon": "ri-shuffle-fill",
"order": 2
},
{
"type": "link",
"label": "Download Dispatch Plan",
"url": "apps:dispatch-plan",
"icon": "ri-download-2-fill",
"order": 3
}
]
},
{
"type": "submenu",
"label": "Operation",
"icon": "ri-road-map-fill",
"order": 3,
"children": [
{
"type": "link",
"label": "Urban Digital Twin",
"url": "apps:urban-digital-twin",
"icon": "ri-building-2-fill",
"order": 1
},
{
"type": "submenu",
"label": "Social Digital Twin",
"icon": "ri-group-fill",
"order": 2,
"children": [
{
"type": "link",
"label": "WhatsApp Bot",
"url": "apps:bot-whatsapp",
"icon": "ri-whatsapp-fill",
"order": 1
},
{
"type": "link",
"label": "Telegram Bot",
"url": "apps:bot-telegram",
"icon": "ri-telegram-fill",
"order": 2
},
{
"type": "link",
"label": "Facebook Pages Bot",
"url": "apps:bot-facebook",
"icon": "ri-facebook-fill",
"order": 3
}
]
},
{
"type": "link",
"label": "Data Feedback Loop",
"url": "apps:feedback-loop",
"icon": "ri-loop-left-line",
"order": 3
}
]
},
{
"type": "submenu",
"label": "Post-Operation",
"icon": "ri-bar-chart-box-fill",
"order": 4,
"children": [
{
"type": "link",
"label": "Route Analytics",
"url": "apps:route-analytics",
"icon": "ri-line-chart-fill",
"order": 1
},
{
"type": "link",
"label": "Citizen Feedback Review",
"url": "apps:feedback-review",
"icon": "ri-message-3-fill",
"order": 2
},
{
"type": "link",
"label": "Twin Refinement",
"url": "apps:twin-refinement",
"icon": "ri-slideshow-2-fill",
"order": 3
}
]
},
{
"type": "title",
"label": "System Control",
"order": 5
},
{
"type": "submenu",
"label": "Digital Twin Sync Monitor",
"icon": "ri-refresh-fill",
"order": 6,
"children": [
{
"type": "link",
"label": "Sync Status",
"url": "apps:sync-monitor",
"icon": "ri-check-double-fill",
"order": 1
},
{
"type": "link",
"label": "Force Refresh",
"url": "apps:sync-monitor",
"icon": "ri-restart-fill",
"order": 2
}
]
},
{
"type": "submenu",
"label": "Logs & Failures",
"icon": "ri-error-warning-fill",
"order": 7,
"children": [
{
"type": "link",
"label": "Webhook Logs",
"url": "apps:logs-webhooks",
"icon": "ri-file-list-2-fill",
"order": 1
},
{
"type": "link",
"label": "Parsing Errors",
"url": "apps:logs-parsing",
"icon": "ri-bug-fill",
"order": 2
},
{
"type": "link",
"label": "API Limits",
"url": "apps:logs-limits",
"icon": "ri-cpu-fill",
"order": 3
}
]
},
{
"type": "submenu",
"label": "Configuration",
"icon": "ri-settings-5-fill",
"order": 8,
"children": [
{
"type": "link",
"label": "API Keys & Tokens",
"url": "apps:config-api",
"icon": "ri-key-2-fill",
"order": 1
},
{
"type": "link",
"label": "Map Rendering",
"url": "apps:config-map",
"icon": "ri-map-pin-user-fill",
"order": 2
},
{
"type": "link",
"label": "Collection Logic",
"url": "apps:config-collection",
"icon": "ri-truck-fill",
"order": 3
}
] ]
} }
] ]