Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions net_maestro/core/admin/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from .component_model import ComponentModelAdmin
from .event_file import EventFileAdmin
from .event_record import EventRecordAdmin
from .model_file import ModelFileAdmin
Expand All @@ -12,6 +13,7 @@
from .simulation_pe_record import SimulationPeRecordAdmin

__all__ = [
"ComponentModelAdmin",
"EventFileAdmin",
"EventRecordAdmin",
"ModelFileAdmin",
Expand Down
14 changes: 14 additions & 0 deletions net_maestro/core/admin/component_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from __future__ import annotations

from django.contrib import admin

from net_maestro.core.models import ComponentModel


@admin.register(ComponentModel)
class ComponentModelAdmin(admin.ModelAdmin):
list_display = ["id", "name", "component_type", "description", "engine", "parameters"]
list_filter = [
"component_type",
"engine",
]
37 changes: 37 additions & 0 deletions net_maestro/core/migrations/0010_add_component_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Generated by Django 6.0.6 on 2026-08-05 21:34
from __future__ import annotations

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("core", "0009_pholdsimulationlprecord"),
]

operations = [
migrations.CreateModel(
name="ComponentModel",
fields=[
(
"id",
models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("name", models.CharField(max_length=255)),
(
"component_type",
models.CharField(
choices=[("host", "Host"), ("router", "Router"), ("switch", "Switch")],
max_length=100,
),
),
("description", models.TextField(blank=True, null=True)),
("engine", models.CharField(max_length=100)),
("parameters", models.JSONField(blank=True, null=True)),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
],
),
]
2 changes: 2 additions & 0 deletions net_maestro/core/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

from .component_model import ComponentModel
from .event_file import EventFile
from .event_record import EventRecord
from .model_file import ModelFile
Expand All @@ -12,6 +13,7 @@
from .simulation_pe_record import SimulationPeRecord

__all__ = [
"ComponentModel",
"EventFile",
"EventRecord",
"ModelFile",
Expand Down
25 changes: 25 additions & 0 deletions net_maestro/core/models/component_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from __future__ import annotations

from django.db import models


class ComponentType(models.TextChoices):
HOST = "host", "Host"
ROUTER = "router", "Router"
SWITCH = "switch", "Switch"


class ComponentModel(models.Model):
# TODO: Verify that these fields are correct.
# Would we want to extend for specific types? ie. Host/ Router
# TODO: Revisit when we have a User model: created_by, updated_by
name = models.CharField(max_length=255)
component_type = models.CharField(max_length=100, choices=ComponentType.choices)
description = models.TextField(blank=True)
engine = models.CharField(max_length=100)
parameters = models.JSONField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self) -> str:
return f"ComponentModel {self.name}"
95 changes: 95 additions & 0 deletions net_maestro/core/templates/net_maestro/partials/model_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<div class="bg-base-300 overflow-y-auto" style="height: calc(100vh - 64px);">
<div class="p-8 max-w-5xl">
{% comment %}
This page is a demonstration-only create form for `/models-list/new-model`.
The fields are read-only and are populated by model_create() via
_model_form_context(). Depending on further specs the fields and details here might change.
Save and Cancel intentionally navigate back to the
custom component list without persisting anything.

TODO: Replace the read-only display with a real Django form when models
are backed properly by django models.
TODO: Convert the save action to POST and persist the new model before returning
to `/models/`.
{% endcomment %}
<div class="flex flex-row items-start justify-between gap-4">
<div>
<div class="flex flex-row items-center gap-2 text-sm text-base-content/60">
<a
href="{% url 'models-list-partial' %}"
hx-get="{% url 'models-list-partial' %}"
hx-target="#main-content"
hx-swap="innerHTML"
hx-push-url="true"
class="link link-hover"
>
Models
</a>
<i class="ri-arrow-right-s-line" aria-hidden="true"></i>
<span>New Model</span>
</div>
<h1 class="text-3xl font-semibold mt-2">
Model
</h1>
</div>
<div class="flex flex-row gap-2">
<a
href="{% url 'models-list-partial' %}"
hx-get="{% url 'models-list-partial' %}"
hx-target="#main-content"
hx-swap="innerHTML"
hx-push-url="true"
class="btn btn-ghost"
>
Cancel
</a>
<a
href="{% url 'models-list-partial' %}"
hx-get="{% url 'models-list-partial' %}"
hx-target="#main-content"
hx-swap="innerHTML"
hx-push-url="true"
class="btn btn-primary"
>
Save
</a>
</div>
</div>

<div class="grid grid-cols-1 gap-6 mt-8">
<div class="card bg-base-100 shadow-sm">
<div class="card-body">
<div class="flex flex-row items-center justify-between gap-4">
<div class="flex flex-row items-center gap-3">
<i class="ri-server-line text-2xl text-primary" aria-hidden="true"></i>
<div>
<h2 class="card-title">New Model</h2>
</div>
</div>
</div>

{% for section in form_sections %}
<div class="mt-6">
<h3 class="font-semibold mb-3">{{ section.title }}</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
{% for field in section.fields %}
<label class="form-control w-full">
<div class="label">
<span class="label-text">{{ field.label }}</span>
</div>
<input
type="text"
value="{{ field.value }}"
class="input input-bordered w-full"
readonly
>
</label>
{% endfor %}
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
51 changes: 51 additions & 0 deletions net_maestro/core/templates/net_maestro/partials/models_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<div class="bg-base-300 overflow-y-auto" style="height: calc(100vh - 64px);">
<div class="p-8">
<div class="flex flex-row items-start justify-between gap-4">
<div>
<h1 class="text-3xl font-semibold">Available Component Models</h1>
</div>
<a
href="{% url 'model-create' %}"
hx-get="{% url 'model-create' %}"
hx-target="#main-content"
hx-swap="innerHTML"
hx-push-url="true"
class="btn btn-primary"
>
<i class="ri-add-line" aria-hidden="true"></i>
New Component Model
</a>
</div>

<div class="grid grid-cols-1 xl:grid-cols-2 gap-6 mt-8">
{% for model in models %}
<div class="card bg-base-100 shadow-sm">
<div class="card-body">
<div class="flex flex-row items-start justify-between gap-4">
<div class="flex flex-row items-center gap-3">
<i class="{{ model.icon_class }} text-xl" aria-hidden="true"></i>
<h2 class="card-title">{{ model.name }}</h2>
</div>
<div class="flex flex-row gap-2">
<div class="badge badge-outline">{{ model.type }}</div>
</div>
</div>
<p class="text-[12.5px] leading-relaxed" style="color:var(--text-dim);"> {{model.description}}</p>
<div class="flex flex-row gap-2">
{% for param in model.parameters %}
<div class="badge badge-outline">{{ param }}</div>
{% endfor %}
</div>
</div>
</div>
{% empty %}
<div class="card bg-base-100 shadow-sm border border-dashed border-base-content/20 xl:col-span-2">
<div class="card-body items-center justify-center text-center min-h-72">
<i class="ri-stack-line text-4xl text-base-content/50" aria-hidden="true"></i>
<h2 class="card-title mt-4">No models available</h2>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
15 changes: 15 additions & 0 deletions net_maestro/core/templates/net_maestro/shared/sidebar.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
<div class="menu menu-lg bg-neutral h-[calc(100vh-64px)] w-16 flex flex-col">
<!-- Navigation menu items -->
<ul class="grid h-screen gap-6 content-baseline">
<!-- Models List Section -->
<li>
<a
href="{% url 'models-list-partial' %}"
hx-get="{% url 'models-list-partial' %}"
hx-target="#main-content"
hx-swap="innerHTML"
hx-push-url="true"
class="flex items-center justify-center"
:class="{ 'menu-active': activeItem === 'modelsList' }"
@click="activeItem = 'modelsList'"
>
<i class="ri-layout-grid-2-fill" aria-hidden="true"></i>
</a>
</li>
<!-- Base Models section -->
<li>
<a
Expand Down
Loading
Loading