feat: bootstrap dashboard templates and dashboard homepage view
ci/woodpecker/push/woodpecker Pipeline was successful Details

wip-payments
Aravinth Manivannan 2022-06-17 16:03:13 +05:30
parent 1a0ca0117a
commit 64b4437acd
Signed by: realaravinth
GPG Key ID: AD9F0F08E855ED88
13 changed files with 278 additions and 0 deletions

0
dash/__init__.py Normal file
View File

3
dash/admin.py Normal file
View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

6
dash/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class DashConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'dash'

View File

3
dash/models.py Normal file
View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="{% static 'css/main.css' %}" />
<title>{{ title }}| Hostea Dashbaord</title>
{% include "common/components/meta.html" %}
</head>
<body>
<header>
{% include "dash/common/components/primary-nav.html" %}
</header>
<div class="panel__container">
{% include "dash/common/components/secondary-nav.html" %}
<main class="dash__main">
{% block dash %} {% endblock %}
{% include "common/components/footer.html" %}
</main>
</div>
</body>
</html>

View File

@ -0,0 +1,36 @@
{% load static %}
<nav class="nav__container">
<input type="checkbox" class="nav__toggle" id="nav__toggle" />
<div class="nav__header">
<a class="nav__logo-container" href="/">
<img
src="{% static 'img/android-icon-48x48.png' %}"
alt="Hostea temporary logo"
/>
<p class="nav__home-btn">ostea</p>
</a>
<label class="nav__hamburger-menu" for="nav__toggle">
<span class="nav__hamburger-inner"></span>
</label>
</div>
<div class="nav__spacer"></div>
<div class="nav__link-group">
<div class="nav__link-container">
<a class="nav__link" rel="noreferrer" href="{% url 'accounts.login' %}"
>Add Instance</a
>
</div>
<div class="nav__link-container">
<a class="nav__link" rel="noreferrer" href="{% url 'accounts.login' %}"
>Support</a
>
</div>
<div class="nav__link-container">
<a class="nav__link" rel="noreferrer" href="{% url 'accounts.logout' %}"
>Logout</a
>
</div>
</div>
</nav>

View File

@ -0,0 +1,15 @@
<aside class="secondary-nav__container">
<nav class="secondary-nav">
<div class="secondary-nav__options">
<p class="secondary-nav__option-link">realaravinth</p>
</div>
<div class="secondary-nav__options">
<a href="/foo" class="secondary-nav__option-link">Instances</a>
<a href="/foo" class="secondary-nav__option-link">Support</a>
<a href="/foo" class="secondary-nav__option-link">Billing</a>
</div>
<div class="secondary-nav__options">
<a href="/foo" class="secondary-nav__option-link">Manage Account</a>
</div>
</nav>
</aside>

View File

@ -0,0 +1,6 @@
{% extends 'dash/common/base.html' %}
{% block dash %}
{% include "common/components/error.html" %}
<h2>{{ title }}</h2>
{% include "common/components/error.html" %}
{% endblock %}

71
dash/tests.py Normal file
View File

@ -0,0 +1,71 @@
# Copyright © 2022 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.contrib.auth import get_user_model
from django.utils.http import urlencode
from django.urls import reverse
from django.test import TestCase, Client, override_settings
from django.contrib.auth import authenticate
from django.conf import settings
class DashHome(TestCase):
"""
Tests create new app view
"""
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()
def test_dash_is_protected(self):
"""
Tests if dashboard template renders
"""
resp = self.client.get(reverse("dash.home"))
self.assertEqual(resp.status_code, 302)
# default LOGIN redirect URI that is used by @login_required decorator is
# /accounts/login. There's a redirection endpoint at /accounts/login/ that
# will redirect user to /login. Hence the /accounts prefix
redirect_login_uri = f"/accounts{reverse('accounts.login')}?next={reverse('dash.home')}"
self.assertEqual(resp.headers["location"], redirect_login_uri)
def test_dash_home_renders(self):
"""
Tests if login template renders
"""
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"))
# email login works
resp = c.get(reverse('dash.home'))
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)

24
dash/urls.py Normal file
View File

@ -0,0 +1,24 @@
# Copyright © 2022 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.contrib import admin
from django.urls import path, include
from .views import (
home
)
urlpatterns = [
path("", home, name="dash.home"),
]

36
dash/views.py Normal file
View File

@ -0,0 +1,36 @@
# Copyright © 2022 Aravinth Manivannan <realaravinth@batsense.net>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.shortcuts import render, redirect, get_object_or_404
from django.utils.http import urlencode
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_protect
from django.urls import reverse
def default_ctx(title: str):
return {
"title": title,
}
@login_required
def home(request):
PAGE_TITLE = "Home"
ctx = default_ctx(title=PAGE_TITLE)
return render(request, "dash/home/index.html", context=ctx)

View File

@ -34,9 +34,11 @@ h2 {
body {
width: 100%;
min-height: 100vh;
/*
display: flex;
flex-direction: column;
justify-content: space-between;
*/
}
a:hover {
@ -99,6 +101,7 @@ header {
width: 100%;
padding-top: 5px;
border-bottom: 1px solid rgb(211, 211, 211);
height: 63px;
}
.nav__home-btn {
@ -469,3 +472,56 @@ footer {
}
/* footer ends */
/* dashbaord starts */
.panel__container {
/* background-color: green; */
}
/* secondary nav starts */
.secondary-nav__container {
box-sizing: border-box;
overflow-x: auto;
flex: 1;
position: fixed;
top: 63px;
bottom: 0;
z-index: 1000;
width: 260px;
border-right: 1px solid rgb(217, 217, 217);
}
.secondary-nav {
width: 100%;
height: 100%;
position: relative;
box-sizing: border-box;
}
.secondary-nav__options {
display: flex;
flex-direction: column;
border-bottom: 1px solid rgb(217, 217, 217);
}
.secondary-nav__option-link {
padding: 20px 0 20px 20px;
}
.secondary-nav__option-link:hover {
background-color: lightslategray;
}
/* secondary nav ends */
.dash__main {
flex: 2;
display: flex;
flex-direction: column;
justify-content: space-between;
min-height: calc(-63px + 100vh);
}
/* dashbaord ends */