diff --git a/dash/templates/dash/instances/new/index.html b/dash/templates/dash/instances/new/index.html
new file mode 100644
index 0000000..796a24f
--- /dev/null
+++ b/dash/templates/dash/instances/new/index.html
@@ -0,0 +1,53 @@
+{% extends 'dash/common/base.html' %} {% block dash %}
+
{{ title }}
+
+
+{% endblock %}
diff --git a/dash/tests.py b/dash/tests.py
index 7af6025..b9d36ee 100644
--- a/dash/tests.py
+++ b/dash/tests.py
@@ -19,7 +19,45 @@ from django.test import TestCase, Client, override_settings
from django.conf import settings
from django.db.utils import IntegrityError
-from .models import InstanceConfiguration
+from .models import InstanceConfiguration, Instance
+
+
+def register_util(t: TestCase, username: str):
+ t.password = "password121231"
+ t.username = username
+ t.email = f"{t.username}@example.org"
+ t.user = get_user_model().objects.create(
+ username=t.username,
+ email=t.email,
+ )
+ t.user.set_password(t.password)
+ t.user.save()
+
+
+def create_configurations(t: TestCase):
+ t.instance_config = [
+ InstanceConfiguration(name="Personal", ram=0.5, cpu=1, storage=25),
+ InstanceConfiguration(name="Enthusiast", ram=2, cpu=2, storage=50),
+ InstanceConfiguration(name="Small Business", ram=8, cpu=4, storage=64),
+ InstanceConfiguration(name="Enterprise", ram=64, cpu=24, storage=1024),
+ ]
+
+ for instance in t.instance_config:
+ instance.save()
+ print(f"[*][init] Instance {instance.name} is saved")
+ t.assertEqual(
+ InstanceConfiguration.objects.filter(name=instance.name).exists(), True
+ )
+
+
+def login_util(t: TestCase, c: Client, redirect_to: str):
+ payload = {
+ "login": t.username,
+ "password": t.password,
+ }
+ resp = c.post(reverse("accounts.login"), payload)
+ t.assertEqual(resp.status_code, 302)
+ t.assertEqual(resp.headers["location"], reverse(redirect_to))
class DashHome(TestCase):
@@ -28,15 +66,7 @@ class DashHome(TestCase):
"""
def setUp(self):
- self.password = "password121231"
- self.username = "dashboard_home_user"
- self.email = f"{self.username}@example.org"
- self.user = get_user_model().objects.create(
- username=self.username,
- email=self.email,
- )
- self.user.set_password(self.password)
- self.user.save()
+ register_util(t=self, username="dashboard_home_user")
def test_dash_is_protected(self):
"""
@@ -60,13 +90,7 @@ class DashHome(TestCase):
c = Client()
# username login works
- payload = {
- "login": self.username,
- "password": self.password,
- }
- resp = c.post(reverse("accounts.login"), payload)
- self.assertEqual(resp.status_code, 302)
- self.assertEqual(resp.headers["location"], reverse("accounts.home"))
+ login_util(t=self, c=c, redirect_to="accounts.home")
# email login works
resp = c.get(reverse("dash.home"))
@@ -98,3 +122,54 @@ class InstancesConfig(TestCase):
name="test config 3", ram=0.5, cpu=1, storage=0.5
)
config3.save()
+
+
+class CreateInstance(TestCase):
+ def setUp(self):
+ register_util(t=self, username="createinstance_user")
+ create_configurations(t=self)
+
+ def test_create_instance_renders(self):
+ c = Client()
+ login_util(self, c, "accounts.home")
+ urls = [(reverse("dash.instances.new"), "Instance Configuration")]
+ for (url, test) in urls:
+ print(f"[*] Testing URI: {url}")
+ resp = c.get(url)
+ self.assertEqual(resp.status_code, 200)
+ self.assertEqual(b"Billing" in resp.content, True)
+ self.assertEqual(b"Support" in resp.content, True)
+ self.assertEqual(b"Logout" in resp.content, True)
+ self.assertEqual(str.encode(test) in resp.content, True)
+
+ payload = {
+ "name": "test_create_instance_renders",
+ "configuration": self.instance_config[0].name,
+ }
+
+ self.assertEqual(Instance.objects.filter(name=payload["name"]).exists(), False)
+
+ resp = c.post(reverse("dash.instances.new"), payload)
+ self.assertEqual(resp.status_code, 302)
+ self.assertEqual(resp.headers["location"], reverse("dash.home"))
+
+ self.assertEqual(
+ Instance.objects.filter(
+ name=payload["name"],
+ owned_by=self.user,
+ configuration_id=self.instance_config[0],
+ ).exists(),
+ True,
+ )
+
+ resp = c.post(reverse("dash.instances.new"), payload)
+ self.assertEqual(resp.status_code, 400)
+ self.assertEqual(b"Instance name exists" in resp.content, True)
+
+ payload = {
+ "name": f"2{payload['name']}",
+ "configuration": f"2{payload['name']}",
+ }
+ resp = c.post(reverse("dash.instances.new"), payload)
+ self.assertEqual(resp.status_code, 400)
+ self.assertEqual(b"Configuration doesn" in resp.content, True)
diff --git a/dash/urls.py b/dash/urls.py
index 437c358..a9d857a 100644
--- a/dash/urls.py
+++ b/dash/urls.py
@@ -15,8 +15,9 @@
from django.contrib import admin
from django.urls import path, include
-from .views import home
+from .views import home, create_instance
urlpatterns = [
+ path("instance/new/", create_instance, name="dash.instances.new"),
path("", home, name="dash.home"),
]
diff --git a/dash/views.py b/dash/views.py
index a5e17c6..41bd15e 100644
--- a/dash/views.py
+++ b/dash/views.py
@@ -21,6 +21,8 @@ from django.http import HttpResponse
from django.views.decorators.csrf import csrf_protect
from django.urls import reverse
+from .models import Instance, InstanceConfiguration
+
def default_ctx(title: str, username: str):
"""
@@ -38,7 +40,58 @@ def home(request):
Dashboard homepage view
"""
PAGE_TITLE = "Home"
- username = request.user
- ctx = default_ctx(title=PAGE_TITLE, username=username.username)
+ user = request.user
+ ctx = default_ctx(title=PAGE_TITLE, username=user.username)
+
+ instances = Instance.objects.filter(owned_by=user)
+ if instances:
+ ctx["instances"] = instances
return render(request, "dash/home/index.html", context=ctx)
+
+
+@login_required
+@csrf_protect
+def create_instance(request):
+ """
+ Create instance view
+ """
+ PAGE_TITLE = "Create Instance"
+ user = request.user
+
+ def get_ctx():
+ ctx = default_ctx(title=PAGE_TITLE, username=user.username)
+ configurations = InstanceConfiguration.objects.all()
+ ctx["configurations"] = InstanceConfiguration.objects.all()
+ return ctx
+
+ if request.method == "GET":
+ ctx = get_ctx()
+ return render(request, "dash/instances/new/index.html", context=ctx)
+
+ name = request.POST["name"]
+ if Instance.objects.filter(name=name).exists():
+ ctx = get_ctx()
+ ctx["error"] = {
+ "title": "Can't create instance",
+ "reason": "Instance name exists, please try again with a different name",
+ }
+ print(ctx["error"]["reason"])
+ return render(request, "dash/instances/new/index.html", status=400, context=ctx)
+
+ configuration = request.POST["configuration"]
+ if not InstanceConfiguration.objects.filter(name=configuration).exists():
+ ctx = get_ctx()
+ ctx["error"] = {
+ "title": "Can't create instance",
+ "reason": "Configuration doesn't exist, please try again.",
+ }
+ print(ctx["error"]["reason"])
+ return render(request, "dash/instances/new/index.html", status=400, context=ctx)
+
+ configuration = get_object_or_404(InstanceConfiguration, name=configuration)
+ instance = Instance(
+ name=name, configuration_id=configuration, owned_by=request.user
+ )
+ instance.save()
+ return redirect(reverse("dash.home"))
diff --git a/static/css/main.css b/static/css/main.css
index 338f6ac..816fda1 100644
--- a/static/css/main.css
+++ b/static/css/main.css
@@ -522,7 +522,6 @@ footer {
content: " ►";
}
-
.secondary-nav__options-group[open] > summary::after {
margin-left: 30px;
content: " ▼";
@@ -531,11 +530,72 @@ footer {
/* secondary nav ends */
.dash__main {
- flex: 2;
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: calc(-63px + 100vh);
+ flex:2;
}
+/* dash forms starts */
+.dash__form {
+ display: flex;
+ flex-direction: column;
+ width: 50%;
+ margin: auto;
+ background-color: ping;
+ padding: 0 10px;
+}
+
+fieldset {
+ border: none;
+}
+
+.configuration__container {
+ padding: 20px;
+ padding-left: 0;
+ margin: 10px 20px;
+ margin-left: 0;
+ border: 1px solid rgb(211, 211, 211);
+ display: inline-flex;
+ flex-direction: column;
+}
+
+.configuration__name {
+ margin-left: 20px;
+}
+
+.configuration__spec {
+ margin-left: 40px;
+}
+
+/*
+.form__label {
+ margin: 5px 0;
+}
+
+.form__input {
+ display: block;
+ width: 100%;
+ margin: 10px 0;
+ padding: 5px 0;
+ height: 25px;
+}
+
+.form__submit {
+ width: 100%;
+ display: block;
+ margin: 10px 0;
+ color: #fff;
+ border: none;
+ font-weight: 400;
+ padding: 15px;
+ cursor: pointer;
+ background-color: rgb(0, 128, 0);
+}
+
+*/
+
+/* dash forms ends */
+
/* dashbaord ends */