Switch to Soft-UI admin from Jet
This also adds a bunch of templates and URLS Start to add routes for user-facing bills pages Add an Index page that may start to display some great work
3
.vscode/settings.json
vendored
@ -16,7 +16,8 @@
|
|||||||
"titleBar.activeBackground": "#f9e64f",
|
"titleBar.activeBackground": "#f9e64f",
|
||||||
"titleBar.activeForeground": "#15202b",
|
"titleBar.activeForeground": "#15202b",
|
||||||
"titleBar.inactiveBackground": "#f9e64f99",
|
"titleBar.inactiveBackground": "#f9e64f99",
|
||||||
"titleBar.inactiveForeground": "#15202b99"
|
"titleBar.inactiveForeground": "#15202b99",
|
||||||
|
"commandCenter.border": "#15202b99"
|
||||||
},
|
},
|
||||||
"peacock.color": "#f9e64f"
|
"peacock.color": "#f9e64f"
|
||||||
}
|
}
|
@ -12,6 +12,8 @@ https://docs.djangoproject.com/en/3.2/ref/settings/
|
|||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import environ
|
import environ
|
||||||
|
import os
|
||||||
|
import environ
|
||||||
|
|
||||||
env = environ.Env()
|
env = environ.Env()
|
||||||
environ.Env.read_env()
|
environ.Env.read_env()
|
||||||
@ -24,20 +26,22 @@ BASE_DIR = Path(__file__).resolve().parent.parent
|
|||||||
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
|
||||||
|
|
||||||
# SECURITY WARNING: keep the secret key used in production secret!
|
# SECURITY WARNING: keep the secret key used in production secret!
|
||||||
SECRET_KEY = env("SECRET_KEY", default='django-insecure-7uajhmbt^@)mklk1ur=slkmn3*+9_cnfhww6wi8jg*h@qqd%6u')
|
SECRET_KEY = env(
|
||||||
|
"SECRET_KEY", default='django-insecure-7uajhmbt^@)mklk1ur=slkmn3*+9_cnfhww6wi8jg*h@qqd%6u')
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = env("DEBUG")
|
DEBUG = env("DEBUG")
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "192.168.1.187", "192.168.1.23", "192.168.1.125", "0.0.0.0"]
|
ALLOWED_HOSTS = ["localhost", "127.0.0.1", "192.168.1.187",
|
||||||
|
"192.168.1.23", "192.168.1.125", "0.0.0.0"]
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'jet.dashboard',
|
'bills',
|
||||||
'jet',
|
# 'bills.apps.BillsConfig',
|
||||||
'bills.apps.BillsConfig',
|
'admin_soft.apps.AdminSoftDashboardConfig',
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
@ -47,6 +51,7 @@ INSTALLED_APPS = [
|
|||||||
'rest_framework',
|
'rest_framework',
|
||||||
'rest_framework.authtoken',
|
'rest_framework.authtoken',
|
||||||
'django_filters',
|
'django_filters',
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
@ -64,7 +69,7 @@ ROOT_URLCONF = 'api.urls'
|
|||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [],
|
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'api/templates')],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
@ -129,7 +134,7 @@ USE_TZ = True
|
|||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/3.2/howto/static-files/
|
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
@ -140,9 +145,9 @@ DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|||||||
|
|
||||||
JET_THEMES = [
|
JET_THEMES = [
|
||||||
{
|
{
|
||||||
'theme': 'default', # theme folder name
|
'theme': 'default', # theme folder name
|
||||||
'color': '#47bac1', # color of the theme's button in user menu
|
'color': '#47bac1', # color of the theme's button in user menu
|
||||||
'title': 'Default' # theme title
|
'title': 'Default' # theme title
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'theme': 'green',
|
'theme': 'green',
|
||||||
@ -174,3 +179,10 @@ JET_THEMES = [
|
|||||||
# JET_INDEX_DASHBOARD = 'jet.dashboard.dashboard.DefaultIndexDashboard'
|
# JET_INDEX_DASHBOARD = 'jet.dashboard.dashboard.DefaultIndexDashboard'
|
||||||
# JET_APP_INDEX_DASHBOARD = 'dashboard.CustomIndexDashboard'
|
# JET_APP_INDEX_DASHBOARD = 'dashboard.CustomIndexDashboard'
|
||||||
JET_INDEX_DASHBOARD = 'dashboard.CustomIndexDashboard'
|
JET_INDEX_DASHBOARD = 'dashboard.CustomIndexDashboard'
|
||||||
|
|
||||||
|
|
||||||
|
STATICFILES_DIRS = [
|
||||||
|
BASE_DIR / "api/static",
|
||||||
|
("assets", BASE_DIR / "assets"),
|
||||||
|
"[os.path.join(BASE_DIR, 'static')",
|
||||||
|
]
|
||||||
|
BIN
api/api/static/assets/favicon.ico
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
api/api/static/assets/img/bg-masthead.jpg
Normal file
After Width: | Height: | Size: 939 KiB |
BIN
api/api/static/assets/img/bg-showcase-1.jpg
Normal file
After Width: | Height: | Size: 298 KiB |
BIN
api/api/static/assets/img/bg-showcase-2.jpg
Normal file
After Width: | Height: | Size: 193 KiB |
BIN
api/api/static/assets/img/bg-showcase-3.jpg
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
api/api/static/assets/img/testimonials-1.jpg
Normal file
After Width: | Height: | Size: 133 KiB |
BIN
api/api/static/assets/img/testimonials-2.jpg
Normal file
After Width: | Height: | Size: 189 KiB |
BIN
api/api/static/assets/img/testimonials-3.jpg
Normal file
After Width: | Height: | Size: 244 KiB |
10919
api/api/static/css/styles.css
Normal file
7
api/api/static/js/scripts.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
/*!
|
||||||
|
* Start Bootstrap - Landing Page v6.0.6 (https://startbootstrap.com/theme/landing-page)
|
||||||
|
* Copyright 2013-2023 Start Bootstrap
|
||||||
|
* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-landing-page/blob/master/LICENSE)
|
||||||
|
*/
|
||||||
|
// This file is intentionally blank
|
||||||
|
// Use this file to add JavaScript to your project
|
14
api/api/templates/bills/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<b>Bills!</b>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{% url 'bills:create' %}">Create Bill</a></li>
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
|
{% if bills_list %}
|
||||||
|
<ul>
|
||||||
|
{% for bill in bills_list %}
|
||||||
|
<li><a href="{% url 'bills:detail' bill.id %}"> {{ bill.name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p>No bills are available.</p>
|
||||||
|
{% endif %}
|
248
api/api/templates/index.html
Normal file
@ -0,0 +1,248 @@
|
|||||||
|
{% load static %}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
|
||||||
|
<meta name="description" content="" />
|
||||||
|
<meta name="author" content="" />
|
||||||
|
<title>Manage My Bills</title>
|
||||||
|
<!-- Favicon-->
|
||||||
|
<link rel="icon" type="image/x-icon" href="{% static 'assets/favicon.ico' %}" />
|
||||||
|
<!-- Bootstrap icons-->
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- Google fonts-->
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Lato:300,400,700,300italic,400italic,700italic" rel="stylesheet" type="text/css" />
|
||||||
|
<!-- Core theme CSS (includes Bootstrap)-->
|
||||||
|
<link href="{% static 'css/styles.css' %}" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Navigation-->
|
||||||
|
<nav class="navbar navbar-light bg-light static-top">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="#!">Manage My Bills!</a>
|
||||||
|
<a class="btn btn-primary" href="#signup">Sign Up</a>
|
||||||
|
</div>
|
||||||
|
<div><a class="btn btn-secondary" href="{% url 'bills:create' %}">Log In</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</nav>
|
||||||
|
<!-- Masthead-->
|
||||||
|
<header class="masthead">
|
||||||
|
<div class="container position-relative">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-xl-6">
|
||||||
|
<div class="text-center text-white">
|
||||||
|
<!-- Page heading-->
|
||||||
|
<h1 class="mb-5">Generate more leads with a professional landing page!</h1>
|
||||||
|
<!-- Signup form-->
|
||||||
|
<!-- * * * * * * * * * * * * * * *-->
|
||||||
|
<!-- * * SB Forms Contact Form * *-->
|
||||||
|
<!-- * * * * * * * * * * * * * * *-->
|
||||||
|
<!-- This form is pre-integrated with SB Forms.-->
|
||||||
|
<!-- To make this form functional, sign up at-->
|
||||||
|
<!-- https://startbootstrap.com/solution/contact-forms-->
|
||||||
|
<!-- to get an API token!-->
|
||||||
|
<form class="form-subscribe" id="contactForm" data-sb-form-api-token="API_TOKEN">
|
||||||
|
<!-- Email address input-->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<input class="form-control form-control-lg" id="emailAddress" type="email" placeholder="Email Address" data-sb-validations="required,email" />
|
||||||
|
<div class="invalid-feedback text-white" data-sb-feedback="emailAddress:required">Email Address is required.</div>
|
||||||
|
<div class="invalid-feedback text-white" data-sb-feedback="emailAddress:email">Email Address Email is not valid.</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto"><button class="btn btn-primary btn-lg disabled" id="submitButton" type="submit">Submit</button></div>
|
||||||
|
</div>
|
||||||
|
<!-- Submit success message-->
|
||||||
|
<!---->
|
||||||
|
<!-- This is what your users will see when the form-->
|
||||||
|
<!-- has successfully submitted-->
|
||||||
|
<div class="d-none" id="submitSuccessMessage">
|
||||||
|
<div class="text-center mb-3">
|
||||||
|
<div class="fw-bolder">Form submission successful!</div>
|
||||||
|
<p>To activate this form, sign up at</p>
|
||||||
|
<a class="text-white" href="https://startbootstrap.com/solution/contact-forms">https://startbootstrap.com/solution/contact-forms</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Submit error message-->
|
||||||
|
<!---->
|
||||||
|
<!-- This is what your users will see when there is-->
|
||||||
|
<!-- an error submitting the form-->
|
||||||
|
<div class="d-none" id="submitErrorMessage"><div class="text-center text-danger mb-3">Error sending message!</div></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<!-- Icons Grid-->
|
||||||
|
<section class="features-icons bg-light text-center">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="features-icons-item mx-auto mb-5 mb-lg-0 mb-lg-3">
|
||||||
|
<div class="features-icons-icon d-flex"><i class="bi-window m-auto text-primary"></i></div>
|
||||||
|
<h3>Fully Responsive</h3>
|
||||||
|
<p class="lead mb-0">This theme will look great on any device, no matter the size!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="features-icons-item mx-auto mb-5 mb-lg-0 mb-lg-3">
|
||||||
|
<div class="features-icons-icon d-flex"><i class="bi-layers m-auto text-primary"></i></div>
|
||||||
|
<h3>Bootstrap 5 Ready</h3>
|
||||||
|
<p class="lead mb-0">Featuring the latest build of the new Bootstrap 5 framework!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="features-icons-item mx-auto mb-0 mb-lg-3">
|
||||||
|
<div class="features-icons-icon d-flex"><i class="bi-terminal m-auto text-primary"></i></div>
|
||||||
|
<h3>Easy to Use</h3>
|
||||||
|
<p class="lead mb-0">Ready to use with your own content, or customize the source files!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Image Showcases-->
|
||||||
|
<section class="showcase">
|
||||||
|
<div class="container-fluid p-0">
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="col-lg-6 order-lg-2 text-white showcase-img" style="background-image: url('{% static "assets/img/bg-showcase-1.jpg" %}')"></div>
|
||||||
|
<div class="col-lg-6 order-lg-1 my-auto showcase-text">
|
||||||
|
<h2>Fully Responsive Design</h2>
|
||||||
|
<p class="lead mb-0">When you use a theme created by Start Bootstrap, you know that the theme will look great on any device, whether it's a phone, tablet, or desktop the page will behave responsively!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="col-lg-6 text-white showcase-img" style="background-image: url('{% static "assets/img/bg-showcase-2.jpg" %}')"></div>
|
||||||
|
<div class="col-lg-6 my-auto showcase-text">
|
||||||
|
<h2>Updated For Bootstrap 5</h2>
|
||||||
|
<p class="lead mb-0">Newly improved, and full of great utility classes, Bootstrap 5 is leading the way in mobile responsive web development! All of the themes on Start Bootstrap are now using Bootstrap 5!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row g-0">
|
||||||
|
<div class="col-lg-6 order-lg-2 text-white showcase-img" style="background-image: url('{% static "assets/img/bg-showcase-3.jpg" %}')"></div>
|
||||||
|
<div class="col-lg-6 order-lg-1 my-auto showcase-text">
|
||||||
|
<h2>Easy to Use & Customize</h2>
|
||||||
|
<p class="lead mb-0">Landing Page is just HTML and CSS with a splash of SCSS for users who demand some deeper customization options. Out of the box, just add your content and images, and your new landing page will be ready to go!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Testimonials-->
|
||||||
|
<section class="testimonials text-center bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="mb-5">What people are saying...</h2>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="testimonial-item mx-auto mb-5 mb-lg-0">
|
||||||
|
<img class="img-fluid rounded-circle mb-3" src="{% static 'assets/img/testimonials-1.jpg' %}" alt="..." />
|
||||||
|
<h5>Margaret E.</h5>
|
||||||
|
<p class="font-weight-light mb-0">"This is fantastic! Thanks so much guys!"</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="testimonial-item mx-auto mb-5 mb-lg-0">
|
||||||
|
<img class="img-fluid rounded-circle mb-3" src="{% static 'assets/img/testimonials-2.jpg' %}" alt="..." />
|
||||||
|
<h5>Fred S.</h5>
|
||||||
|
<p class="font-weight-light mb-0">"Bootstrap is amazing. I've been using it to create lots of super nice landing pages."</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<div class="testimonial-item mx-auto mb-5 mb-lg-0">
|
||||||
|
<img class="img-fluid rounded-circle mb-3" src="{% static 'assets/img/testimonials-3.jpg' %}" alt="..." />
|
||||||
|
<h5>Sarah W.</h5>
|
||||||
|
<p class="font-weight-light mb-0">"Thanks so much for making these free resources available to us!"</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Call to Action-->
|
||||||
|
<section class="call-to-action text-white text-center" id="signup">
|
||||||
|
<div class="container position-relative">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-xl-6">
|
||||||
|
<h2 class="mb-4">Ready to get started? Sign up now!</h2>
|
||||||
|
<!-- Signup form-->
|
||||||
|
<!-- * * * * * * * * * * * * * * *-->
|
||||||
|
<!-- * * SB Forms Contact Form * *-->
|
||||||
|
<!-- * * * * * * * * * * * * * * *-->
|
||||||
|
<!-- This form is pre-integrated with SB Forms.-->
|
||||||
|
<!-- To make this form functional, sign up at-->
|
||||||
|
<!-- https://startbootstrap.com/solution/contact-forms-->
|
||||||
|
<!-- to get an API token!-->
|
||||||
|
<form class="form-subscribe" id="contactFormFooter" data-sb-form-api-token="API_TOKEN">
|
||||||
|
<!-- Email address input-->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<input class="form-control form-control-lg" id="emailAddressBelow" type="email" placeholder="Email Address" data-sb-validations="required,email" />
|
||||||
|
<div class="invalid-feedback text-white" data-sb-feedback="emailAddressBelow:required">Email Address is required.</div>
|
||||||
|
<div class="invalid-feedback text-white" data-sb-feedback="emailAddressBelow:email">Email Address Email is not valid.</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto"><button class="btn btn-primary btn-lg disabled" id="submitButton" type="submit">Submit</button></div>
|
||||||
|
</div>
|
||||||
|
<!-- Submit success message-->
|
||||||
|
<!---->
|
||||||
|
<!-- This is what your users will see when the form-->
|
||||||
|
<!-- has successfully submitted-->
|
||||||
|
<div class="d-none" id="submitSuccessMessage">
|
||||||
|
<div class="text-center mb-3">
|
||||||
|
<div class="fw-bolder">Form submission successful!</div>
|
||||||
|
<p>To activate this form, sign up at</p>
|
||||||
|
<a class="text-white" href="https://startbootstrap.com/solution/contact-forms">https://startbootstrap.com/solution/contact-forms</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Submit error message-->
|
||||||
|
<!---->
|
||||||
|
<!-- This is what your users will see when there is-->
|
||||||
|
<!-- an error submitting the form-->
|
||||||
|
<div class="d-none" id="submitErrorMessage"><div class="text-center text-danger mb-3">Error sending message!</div></div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<!-- Footer-->
|
||||||
|
<footer class="footer bg-light">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 h-100 text-center text-lg-start my-auto">
|
||||||
|
<ul class="list-inline mb-2">
|
||||||
|
<li class="list-inline-item"><a href="#!">About</a></li>
|
||||||
|
<li class="list-inline-item">⋅</li>
|
||||||
|
<li class="list-inline-item"><a href="#!">Contact</a></li>
|
||||||
|
<li class="list-inline-item">⋅</li>
|
||||||
|
<li class="list-inline-item"><a href="#!">Terms of Use</a></li>
|
||||||
|
<li class="list-inline-item">⋅</li>
|
||||||
|
<li class="list-inline-item"><a href="#!">Privacy Policy</a></li>
|
||||||
|
</ul>
|
||||||
|
<p class="text-muted small mb-4 mb-lg-0">© Your Website 2023. All Rights Reserved.</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-6 h-100 text-center text-lg-end my-auto">
|
||||||
|
<ul class="list-inline mb-0">
|
||||||
|
<li class="list-inline-item me-4">
|
||||||
|
<a href="#!"><i class="bi-facebook fs-3"></i></a>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item me-4">
|
||||||
|
<a href="#!"><i class="bi-twitter fs-3"></i></a>
|
||||||
|
</li>
|
||||||
|
<li class="list-inline-item">
|
||||||
|
<a href="#!"><i class="bi-instagram fs-3"></i></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
<!-- Bootstrap core JS-->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<!-- Core theme JS-->
|
||||||
|
<script src="{% static 'js/scripts.js' %}"></script>
|
||||||
|
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *-->
|
||||||
|
<!-- * * SB Forms JS * *-->
|
||||||
|
<!-- * * Activate your form at https://startbootstrap.com/solution/contact-forms * *-->
|
||||||
|
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *-->
|
||||||
|
<script src="https://cdn.startbootstrap.com/sb-forms-latest.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -24,10 +24,6 @@ urlpatterns = [
|
|||||||
# url(r'^$', view=TemplateView.as_view(template_name='bills/home.html')),
|
# url(r'^$', view=TemplateView.as_view(template_name='bills/home.html')),
|
||||||
# url(r'^$', view=TemplateView.as_view(template_name='main_api/home.html')),
|
# url(r'^$', view=TemplateView.as_view(template_name='main_api/home.html')),
|
||||||
path('', views.index, name='index'),
|
path('', views.index, name='index'),
|
||||||
# url(r'^jet/', include('jet.urls', 'jet')), # Django JET URLS
|
|
||||||
# url(r'^jet/dashboard/', include('jet.dashboard.urls', 'jet-dashboard')),
|
|
||||||
path('jet/', include('jet.urls', 'jet')),
|
|
||||||
path('jet/dashboard', include('jet.dashboard.urls', 'jet-dashboard')),
|
|
||||||
path('bills/', include('bills.urls')),
|
path('bills/', include('bills.urls')),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
]
|
]
|
||||||
|
@ -1,4 +1,9 @@
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
from django.template import loader
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
return HttpResponse("Hi there! This is the API index")
|
# return HttpResponse("Hi there! This is the API index")
|
||||||
|
template = loader.get_template('index.html')
|
||||||
|
context = {}
|
||||||
|
return HttpResponse(template.render(context, request))
|
||||||
|
@ -1,9 +1,21 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
|
||||||
from .models import Bill
|
from .models import Bill, Organization
|
||||||
|
|
||||||
|
|
||||||
@admin.register(Bill)
|
@admin.register(Bill)
|
||||||
class BillAdmin(admin.ModelAdmin):
|
class BillAdmin(admin.ModelAdmin):
|
||||||
list_display = ['name', 'due', 'amount']
|
list_display = ['name', 'due', 'amount']
|
||||||
list_filter = ('name', 'type', 'is_paid', 'is_overdue', 'is_missed')
|
list_filter = ('name', 'type', 'is_paid', 'is_overdue', 'is_missed')
|
||||||
search_fields = ['name', 'type', 'amount']
|
search_fields = ['name', 'type', 'amount']
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Organization)
|
||||||
|
class Organization(admin.ModelAdmin):
|
||||||
|
list_display = ['name']
|
||||||
|
search_fields = ['name']
|
||||||
|
list_filter = ('name',)
|
||||||
|
ordering = ['name']
|
||||||
|
# prepopulated_fields = {'slug': ('name',)}
|
||||||
|
# raw_id_fields = ('members',)
|
||||||
|
# readonly_fields = ('members',)
|
||||||
|
24
api/bills/migrations/0005_organization.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 4.1.7 on 2023-04-08 15:19
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bills', '0004_auto_20211203_1549'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Organization',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=64, verbose_name='Name')),
|
||||||
|
('address', models.CharField(max_length=64, verbose_name='Address')),
|
||||||
|
('phone', models.CharField(max_length=64, verbose_name='Phone')),
|
||||||
|
('email', models.CharField(max_length=64, verbose_name='Email')),
|
||||||
|
('website', models.CharField(max_length=64, verbose_name='Website')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
19
api/bills/migrations/0006_bill_organization.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Generated by Django 4.1.7 on 2023-04-08 15:51
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('bills', '0005_organization'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='bill',
|
||||||
|
name='organization',
|
||||||
|
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='bills.organization', verbose_name='Organization'),
|
||||||
|
),
|
||||||
|
]
|
@ -1,18 +1,36 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
|
|
||||||
class Bill(models.Model):
|
class Bill(models.Model):
|
||||||
name = models.CharField(max_length=64, verbose_name='Name')
|
name = models.CharField(max_length=64, verbose_name='Name')
|
||||||
type = models.CharField(max_length=64, verbose_name="Type")
|
type = models.CharField(max_length=64, verbose_name="Type")
|
||||||
due = models.DateField(verbose_name="Due Date")
|
due = models.DateField(verbose_name="Due Date")
|
||||||
amount = models.FloatField(default='00.00')
|
amount = models.FloatField(default='00.00')
|
||||||
is_paid = models.BooleanField(default=False, verbose_name="Paid")
|
is_paid = models.BooleanField(default=False, verbose_name="Paid")
|
||||||
paid_date = models.DateField('Paid Date',null=True, blank=True)
|
paid_date = models.DateField('Paid Date', null=True, blank=True)
|
||||||
is_overdue = models.BooleanField(default=False, verbose_name="Overdue")
|
is_overdue = models.BooleanField(default=False, verbose_name="Overdue")
|
||||||
is_missed = models.BooleanField(default=False, verbose_name='Missed Payment')
|
is_missed = models.BooleanField(
|
||||||
|
default=False, verbose_name='Missed Payment')
|
||||||
|
organization = models.ForeignKey(
|
||||||
|
'Organization', on_delete=models.CASCADE, verbose_name='Organization', null=True, blank=True)
|
||||||
|
|
||||||
def overdue(self):
|
def overdue(self):
|
||||||
return self.is_overdue
|
return self.is_overdue
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ("%s - %s" % (self.name, self.due))
|
return ("%s - %s" % (self.name, self.due))
|
||||||
|
|
||||||
|
# Create organization model
|
||||||
|
|
||||||
|
|
||||||
|
class Organization(models.Model):
|
||||||
|
name = models.CharField(max_length=64, verbose_name='Name')
|
||||||
|
address = models.CharField(max_length=64, verbose_name='Address')
|
||||||
|
phone = models.CharField(max_length=64, verbose_name='Phone')
|
||||||
|
email = models.CharField(max_length=64, verbose_name='Email')
|
||||||
|
website = models.CharField(max_length=64, verbose_name='Website')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return ("%s - %s" % (self.name, self.phone))
|
||||||
|
10
api/bills/templates/bills/create.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<form action="{% url 'bills:create' %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<fieldset>
|
||||||
|
<legend><h1>Create a New Bill</h1></legend>
|
||||||
|
<label for="name">Bill Name:</label>
|
||||||
|
<input type="text" name="name" id="name" value="">
|
||||||
|
<br>
|
||||||
|
</fieldset>
|
||||||
|
<input type="submit" value="Create Bill">
|
||||||
|
</form>
|
17
api/bills/templates/bills/detail.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<h1> {{bill.name }}</h1>
|
||||||
|
|
||||||
|
{{ bill.due}}
|
||||||
|
<br>
|
||||||
|
{{ bill.type }}
|
||||||
|
<br>
|
||||||
|
{{ bill.amount}}
|
||||||
|
<br>
|
||||||
|
{{ bill.is_paid}}
|
||||||
|
<br>
|
||||||
|
{{ bill.paid_date}}
|
||||||
|
<br>
|
||||||
|
{{ bill.is_overdue}}
|
||||||
|
<br>
|
||||||
|
{{ bill.is_missed}}
|
||||||
|
<br>
|
||||||
|
{{ bill.organization.name}}
|
14
api/bills/templates/bills/index.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<b>Bills!</b>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{% url 'bills:create' %}">Create Bill</a></li>
|
||||||
|
</ul>
|
||||||
|
<hr>
|
||||||
|
{% if bills_list %}
|
||||||
|
<ul>
|
||||||
|
{% for bill in bills_list %}
|
||||||
|
<li><a href="{% url 'bills:detail' bill.id %}"> {{ bill.name }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% else %}
|
||||||
|
<p>No bills are available.</p>
|
||||||
|
{% endif %}
|
@ -1,3 +1,9 @@
|
|||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
from .models import Bill, Organization
|
||||||
|
|
||||||
|
|
||||||
|
class BillModelTests(TestCase):
|
||||||
|
def test_has_due_date_no_amount(self):
|
||||||
|
pass
|
||||||
|
@ -5,9 +5,11 @@ from django.urls import include, path
|
|||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
|
|
||||||
|
app_name = 'bills'
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
|
||||||
path('', views.index, name='index'),
|
path('', views.index, name='index'),
|
||||||
path('<int:bill_id>/', views.detail, name='detail')
|
path('<int:bill_id>/', views.detail, name='detail'),
|
||||||
|
path('create', views.create, name='create')
|
||||||
# path('admin/', admin.site.urls),
|
# path('admin/', admin.site.urls),
|
||||||
]
|
]
|
||||||
|
@ -1,8 +1,27 @@
|
|||||||
from django.shortcuts import render
|
# from django.shortcuts import render
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse, Http404
|
||||||
|
from django.template import loader
|
||||||
|
from django.shortcuts import render, get_object_or_404, get_list_or_404
|
||||||
|
|
||||||
|
from .models import Bill
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
return HttpResponse("Let there be bills!")
|
bills_list = Bill.objects.order_by('-due')
|
||||||
|
# bills_list = get_list_or_404(Bill)
|
||||||
|
template = loader.get_template('bills/index.html')
|
||||||
|
context = {'bills_list': bills_list, }
|
||||||
|
print(bills_list)
|
||||||
|
return HttpResponse(template.render(context, request))
|
||||||
|
# return render(request, 'bills/index.html', context)
|
||||||
|
|
||||||
|
|
||||||
def detail(request, bill_id):
|
def detail(request, bill_id):
|
||||||
return HttpResponse("You're looking at Bill %s." % bill_id)
|
bill = get_object_or_404(Bill, pk=bill_id)
|
||||||
|
return render(request, 'bills/detail.html', {'bill': bill})
|
||||||
|
|
||||||
|
# view to retriev a users bills
|
||||||
|
|
||||||
|
|
||||||
|
def create(request):
|
||||||
|
return render(request, 'bills/create.html')
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
asgiref==3.6.0
|
ansible-core==2.14.4
|
||||||
Django==4.1.7
|
cffi==1.15.1
|
||||||
django-3-jet==1.0.8
|
cryptography==40.0.1
|
||||||
django-4-jet==1.0.9
|
django-admin-soft-dashboard==1.0.12
|
||||||
django-environ==0.10.0
|
django-environ==0.10.0
|
||||||
django-filter==22.1
|
docutils==0.19
|
||||||
djangorestframework==3.14.0
|
Jinja2==3.1.2
|
||||||
pendulum==2.1.2
|
MarkupSafe==2.1.2
|
||||||
psycopg2-binary==2.9.5
|
packaging==23.0
|
||||||
python-dateutil==2.8.2
|
protobuf==4.21.12
|
||||||
pytz==2021.3
|
pycairo==1.23.0
|
||||||
pytzdata==2020.1
|
pycparser==2.21
|
||||||
six==1.16.0
|
Pygments==2.13.0
|
||||||
sqlparse==0.4.2
|
PyGObject==3.44.1
|
||||||
|
PyYAML==6.0
|
||||||
|
resolvelib==0.8.1
|
||||||
|