Compare commits
4 Commits
main
...
6-simple-s
Author | SHA1 | Date | |
---|---|---|---|
cef423c3d1 | |||
f9af3cfefe | |||
20096010b4 | |||
7b2f789724 |
@ -1 +0,0 @@
|
|||||||
3.9.0
|
|
20
.vscode/launch.json
vendored
@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
// Use IntelliSense to learn about possible attributes.
|
|
||||||
// Hover to view descriptions of existing attributes.
|
|
||||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
||||||
"version": "0.2.0",
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Python: Django",
|
|
||||||
"type": "python",
|
|
||||||
"request": "launch",
|
|
||||||
"program": "${workspaceFolder}/api/manage.py",
|
|
||||||
"args": [
|
|
||||||
"runserver",
|
|
||||||
"0.0.0.0:9000"
|
|
||||||
],
|
|
||||||
"django": true,
|
|
||||||
"justMyCode": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
3
.vscode/settings.json
vendored
@ -16,8 +16,7 @@
|
|||||||
"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"
|
||||||
}
|
}
|
28
README.md
@ -5,36 +5,14 @@ The AHosking.com API
|
|||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
1. `sudo apt install libpq-dev python-dev python3-psycopg2`
|
1. `sudo apt install libpq-dev python-dev python3-psycopg2`
|
||||||
1. `pip install virtualenv`
|
1. `pip install virtualenv`
|
||||||
1. `python3 -m virtualenv .env`
|
1. `python3 -m virtualenv .env`
|
||||||
1. Activate environment
|
1. Activate environment
|
||||||
`.\.env\Scripts\activate`
|
`.\.env\Scripts\activate`
|
||||||
1. `export DEBUG=false`
|
1.
|
||||||
1. `docker run --name api-postgres -e POSTGRES_PASSWORD=mysecretpassword -e POSTGRES_USER=api -e POSTGRES_DB=api -p 5432:5432 -d postgres`
|
|
||||||
1. ```
|
|
||||||
export DATABASE_HOST=localhost
|
|
||||||
export DATABASE_PORT=5432
|
|
||||||
export DATABASE_USER=api
|
|
||||||
export DATABASE_PASSWORD=mysecretpassword
|
|
||||||
export DATABASE_NAME=api
|
|
||||||
```
|
|
||||||
1. `python3 manage.py makemigrations`
|
|
||||||
1. `python3 manage.py migrate`
|
|
||||||
1. `python3 manage.py createsuperuser`
|
|
||||||
1. `python manage.py runserver 0.0.0.0:9000`
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
`pip3 install --upgrade --force-reinstall -r requirements.txt` will re-install requirements and upgrade based on requirements.txt
|
|
||||||
|
|
||||||
### Third-party
|
### Third-party
|
||||||
|
|
||||||
- https://pypi.org/project/django-4-jet/
|
* https://pypi.org/project/django-3-jet/
|
||||||
|
|
||||||
## Themes and Templates
|
|
||||||
|
|
||||||
- https://startbootstrap.com/theme/landing-page
|
|
||||||
- https://startbootstrap.com/previews/new-age
|
|
||||||
- https://startbootstrap.com/theme/new-age
|
|
@ -1,3 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
# Register your models here.
|
|
@ -1,6 +0,0 @@
|
|||||||
from django.apps import AppConfig
|
|
||||||
|
|
||||||
|
|
||||||
class AccountsConfig(AppConfig):
|
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
|
||||||
name = 'accounts'
|
|
@ -1,3 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
|
|
||||||
# Create your models here.
|
|
@ -1,3 +0,0 @@
|
|||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
|
@ -1,3 +0,0 @@
|
|||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
# Create your views here.
|
|
@ -0,0 +1,5 @@
|
|||||||
|
# This will make sure the app is always imported when
|
||||||
|
# Django starts so that shared_task will use this app.
|
||||||
|
from .celery import app as celery_app
|
||||||
|
|
||||||
|
__all__ = ('celery_app',)
|
23
api/api/celery.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
# Set the default Django settings module for the 'celery' program.
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'api.settings')
|
||||||
|
|
||||||
|
app = Celery('api')
|
||||||
|
|
||||||
|
|
||||||
|
# Using a string here means the worker doesn't have to serialize
|
||||||
|
# the configuration object to child processes.
|
||||||
|
# - namespace='CELERY' means all celery-related configuration keys
|
||||||
|
# should have a `CELERY_` prefix.
|
||||||
|
app.config_from_object('django.conf:settings', namespace='CELERY')
|
||||||
|
|
||||||
|
# Load task modules from all registered Django apps.
|
||||||
|
app.autodiscover_tasks()
|
||||||
|
|
||||||
|
|
||||||
|
@app.task(bind=True)
|
||||||
|
def debug_task(self):
|
||||||
|
print(f'Request: {self.request!r}')
|
@ -12,8 +12,6 @@ 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()
|
||||||
@ -26,22 +24,20 @@ 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 = env("SECRET_KEY", default='django-insecure-7uajhmbt^@)mklk1ur=slkmn3*+9_cnfhww6wi8jg*h@qqd%6u')
|
||||||
"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",
|
ALLOWED_HOSTS = ["127.0.0.1", "192.168.1.187", "192.168.1.23"]
|
||||||
"192.168.1.23", "192.168.1.125", "0.0.0.0"]
|
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'bills',
|
'jet.dashboard',
|
||||||
# 'bills.apps.BillsConfig',
|
'jet',
|
||||||
'admin_soft.apps.AdminSoftDashboardConfig',
|
'bills.apps.BillsConfig',
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
@ -51,7 +47,6 @@ INSTALLED_APPS = [
|
|||||||
'rest_framework',
|
'rest_framework',
|
||||||
'rest_framework.authtoken',
|
'rest_framework.authtoken',
|
||||||
'django_filters',
|
'django_filters',
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
@ -69,7 +64,7 @@ ROOT_URLCONF = 'api.urls'
|
|||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [os.path.join(BASE_DIR, 'templates'), os.path.join(BASE_DIR, 'api/templates')],
|
'DIRS': [],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
'context_processors': [
|
'context_processors': [
|
||||||
@ -134,7 +129,7 @@ USE_TZ = True
|
|||||||
|
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/4.2/howto/static-files/
|
# https://docs.djangoproject.com/en/3.2/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
|
|
||||||
@ -145,9 +140,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',
|
||||||
@ -176,12 +171,6 @@ 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 = 'bills.dashboard.CustomIndexDashboard'
|
||||||
JET_INDEX_DASHBOARD = 'dashboard.CustomIndexDashboard'
|
# JET_INDEX_DASHBOARD = 'bills.dashboard.CustomIndexDashboard'
|
||||||
|
|
||||||
|
|
||||||
STATICFILES_DIRS = [
|
|
||||||
BASE_DIR / "api/static",
|
|
||||||
("assets", BASE_DIR / "api/static/assets"),
|
|
||||||
]
|
|
Before Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 939 KiB |
Before Width: | Height: | Size: 298 KiB |
Before Width: | Height: | Size: 193 KiB |
Before Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 133 KiB |
Before Width: | Height: | Size: 189 KiB |
Before Width: | Height: | Size: 244 KiB |
4124
api/api/static/css/bootstrap-grid.css
vendored
7
api/api/static/css/bootstrap-grid.min.css
vendored
4123
api/api/static/css/bootstrap-grid.rtl.css
vendored
488
api/api/static/css/bootstrap-reboot.css
vendored
@ -1,488 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap Reboot v5.2.3 (https://getbootstrap.com/)
|
|
||||||
* Copyright 2011-2022 The Bootstrap Authors
|
|
||||||
* Copyright 2011-2022 Twitter, Inc.
|
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
||||||
*/
|
|
||||||
:root {
|
|
||||||
--bs-blue: #0d6efd;
|
|
||||||
--bs-indigo: #6610f2;
|
|
||||||
--bs-purple: #6f42c1;
|
|
||||||
--bs-pink: #d63384;
|
|
||||||
--bs-red: #dc3545;
|
|
||||||
--bs-orange: #fd7e14;
|
|
||||||
--bs-yellow: #ffc107;
|
|
||||||
--bs-green: #198754;
|
|
||||||
--bs-teal: #20c997;
|
|
||||||
--bs-cyan: #0dcaf0;
|
|
||||||
--bs-black: #000;
|
|
||||||
--bs-white: #fff;
|
|
||||||
--bs-gray: #6c757d;
|
|
||||||
--bs-gray-dark: #343a40;
|
|
||||||
--bs-gray-100: #f8f9fa;
|
|
||||||
--bs-gray-200: #e9ecef;
|
|
||||||
--bs-gray-300: #dee2e6;
|
|
||||||
--bs-gray-400: #ced4da;
|
|
||||||
--bs-gray-500: #adb5bd;
|
|
||||||
--bs-gray-600: #6c757d;
|
|
||||||
--bs-gray-700: #495057;
|
|
||||||
--bs-gray-800: #343a40;
|
|
||||||
--bs-gray-900: #212529;
|
|
||||||
--bs-primary: #0d6efd;
|
|
||||||
--bs-secondary: #6c757d;
|
|
||||||
--bs-success: #198754;
|
|
||||||
--bs-info: #0dcaf0;
|
|
||||||
--bs-warning: #ffc107;
|
|
||||||
--bs-danger: #dc3545;
|
|
||||||
--bs-light: #f8f9fa;
|
|
||||||
--bs-dark: #212529;
|
|
||||||
--bs-primary-rgb: 13, 110, 253;
|
|
||||||
--bs-secondary-rgb: 108, 117, 125;
|
|
||||||
--bs-success-rgb: 25, 135, 84;
|
|
||||||
--bs-info-rgb: 13, 202, 240;
|
|
||||||
--bs-warning-rgb: 255, 193, 7;
|
|
||||||
--bs-danger-rgb: 220, 53, 69;
|
|
||||||
--bs-light-rgb: 248, 249, 250;
|
|
||||||
--bs-dark-rgb: 33, 37, 41;
|
|
||||||
--bs-white-rgb: 255, 255, 255;
|
|
||||||
--bs-black-rgb: 0, 0, 0;
|
|
||||||
--bs-body-color-rgb: 33, 37, 41;
|
|
||||||
--bs-body-bg-rgb: 255, 255, 255;
|
|
||||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
||||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
||||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
|
||||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
|
||||||
--bs-body-font-size: 1rem;
|
|
||||||
--bs-body-font-weight: 400;
|
|
||||||
--bs-body-line-height: 1.5;
|
|
||||||
--bs-body-color: #212529;
|
|
||||||
--bs-body-bg: #fff;
|
|
||||||
--bs-border-width: 1px;
|
|
||||||
--bs-border-style: solid;
|
|
||||||
--bs-border-color: #dee2e6;
|
|
||||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
|
||||||
--bs-border-radius: 0.375rem;
|
|
||||||
--bs-border-radius-sm: 0.25rem;
|
|
||||||
--bs-border-radius-lg: 0.5rem;
|
|
||||||
--bs-border-radius-xl: 1rem;
|
|
||||||
--bs-border-radius-2xl: 2rem;
|
|
||||||
--bs-border-radius-pill: 50rem;
|
|
||||||
--bs-link-color: #0d6efd;
|
|
||||||
--bs-link-hover-color: #0a58ca;
|
|
||||||
--bs-code-color: #d63384;
|
|
||||||
--bs-highlight-bg: #fff3cd;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
:root {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: var(--bs-body-font-family);
|
|
||||||
font-size: var(--bs-body-font-size);
|
|
||||||
font-weight: var(--bs-body-font-weight);
|
|
||||||
line-height: var(--bs-body-line-height);
|
|
||||||
color: var(--bs-body-color);
|
|
||||||
text-align: var(--bs-body-text-align);
|
|
||||||
background-color: var(--bs-body-bg);
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
color: inherit;
|
|
||||||
border: 0;
|
|
||||||
border-top: 1px solid;
|
|
||||||
opacity: 0.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
h6, h5, h4, h3, h2, h1 {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: calc(1.375rem + 1.5vw);
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h1 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: calc(1.325rem + 0.9vw);
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h2 {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: calc(1.3rem + 0.6vw);
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h3 {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: calc(1.275rem + 0.3vw);
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h4 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h6 {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
abbr[title] {
|
|
||||||
-webkit-text-decoration: underline dotted;
|
|
||||||
text-decoration: underline dotted;
|
|
||||||
cursor: help;
|
|
||||||
-webkit-text-decoration-skip-ink: none;
|
|
||||||
text-decoration-skip-ink: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
address {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
font-style: normal;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul {
|
|
||||||
padding-left: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul,
|
|
||||||
dl {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol ol,
|
|
||||||
ul ul,
|
|
||||||
ol ul,
|
|
||||||
ul ol {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
b,
|
|
||||||
strong {
|
|
||||||
font-weight: bolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark {
|
|
||||||
padding: 0.1875em;
|
|
||||||
background-color: var(--bs-highlight-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub,
|
|
||||||
sup {
|
|
||||||
position: relative;
|
|
||||||
font-size: 0.75em;
|
|
||||||
line-height: 0;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub {
|
|
||||||
bottom: -0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
sup {
|
|
||||||
top: -0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--bs-link-color);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: var(--bs-link-hover-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre,
|
|
||||||
code,
|
|
||||||
kbd,
|
|
||||||
samp {
|
|
||||||
font-family: var(--bs-font-monospace);
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
display: block;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
overflow: auto;
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
pre code {
|
|
||||||
font-size: inherit;
|
|
||||||
color: inherit;
|
|
||||||
word-break: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 0.875em;
|
|
||||||
color: var(--bs-code-color);
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
a > code {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
kbd {
|
|
||||||
padding: 0.1875rem 0.375rem;
|
|
||||||
font-size: 0.875em;
|
|
||||||
color: var(--bs-body-bg);
|
|
||||||
background-color: var(--bs-body-color);
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
}
|
|
||||||
kbd kbd {
|
|
||||||
padding: 0;
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
img,
|
|
||||||
svg {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
caption-side: bottom;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
caption {
|
|
||||||
padding-top: 0.5rem;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
color: #6c757d;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
text-align: inherit;
|
|
||||||
text-align: -webkit-match-parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead,
|
|
||||||
tbody,
|
|
||||||
tfoot,
|
|
||||||
tr,
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
border-color: inherit;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus:not(:focus-visible) {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
button,
|
|
||||||
select,
|
|
||||||
optgroup,
|
|
||||||
textarea {
|
|
||||||
margin: 0;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
select {
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
[role=button] {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
word-wrap: normal;
|
|
||||||
}
|
|
||||||
select:disabled {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
[type=button],
|
|
||||||
[type=reset],
|
|
||||||
[type=submit] {
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
button:not(:disabled),
|
|
||||||
[type=button]:not(:disabled),
|
|
||||||
[type=reset]:not(:disabled),
|
|
||||||
[type=submit]:not(:disabled) {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-moz-focus-inner {
|
|
||||||
padding: 0;
|
|
||||||
border-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset {
|
|
||||||
min-width: 0;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
legend {
|
|
||||||
float: left;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-size: calc(1.275rem + 0.3vw);
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
legend {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
legend + * {
|
|
||||||
clear: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-datetime-edit-fields-wrapper,
|
|
||||||
::-webkit-datetime-edit-text,
|
|
||||||
::-webkit-datetime-edit-minute,
|
|
||||||
::-webkit-datetime-edit-hour-field,
|
|
||||||
::-webkit-datetime-edit-day-field,
|
|
||||||
::-webkit-datetime-edit-month-field,
|
|
||||||
::-webkit-datetime-edit-year-field {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-inner-spin-button {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
[type=search] {
|
|
||||||
outline-offset: -2px;
|
|
||||||
-webkit-appearance: textfield;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* rtl:raw:
|
|
||||||
[type="tel"],
|
|
||||||
[type="url"],
|
|
||||||
[type="email"],
|
|
||||||
[type="number"] {
|
|
||||||
direction: ltr;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
::-webkit-search-decoration {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-color-swatch-wrapper {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-file-upload-button {
|
|
||||||
font: inherit;
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
::file-selector-button {
|
|
||||||
font: inherit;
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
output {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
summary {
|
|
||||||
display: list-item;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
progress {
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
[hidden] {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
|
7
api/api/static/css/bootstrap-reboot.min.css
vendored
485
api/api/static/css/bootstrap-reboot.rtl.css
vendored
@ -1,485 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap Reboot v5.2.3 (https://getbootstrap.com/)
|
|
||||||
* Copyright 2011-2022 The Bootstrap Authors
|
|
||||||
* Copyright 2011-2022 Twitter, Inc.
|
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
|
||||||
*/
|
|
||||||
:root {
|
|
||||||
--bs-blue: #0d6efd;
|
|
||||||
--bs-indigo: #6610f2;
|
|
||||||
--bs-purple: #6f42c1;
|
|
||||||
--bs-pink: #d63384;
|
|
||||||
--bs-red: #dc3545;
|
|
||||||
--bs-orange: #fd7e14;
|
|
||||||
--bs-yellow: #ffc107;
|
|
||||||
--bs-green: #198754;
|
|
||||||
--bs-teal: #20c997;
|
|
||||||
--bs-cyan: #0dcaf0;
|
|
||||||
--bs-black: #000;
|
|
||||||
--bs-white: #fff;
|
|
||||||
--bs-gray: #6c757d;
|
|
||||||
--bs-gray-dark: #343a40;
|
|
||||||
--bs-gray-100: #f8f9fa;
|
|
||||||
--bs-gray-200: #e9ecef;
|
|
||||||
--bs-gray-300: #dee2e6;
|
|
||||||
--bs-gray-400: #ced4da;
|
|
||||||
--bs-gray-500: #adb5bd;
|
|
||||||
--bs-gray-600: #6c757d;
|
|
||||||
--bs-gray-700: #495057;
|
|
||||||
--bs-gray-800: #343a40;
|
|
||||||
--bs-gray-900: #212529;
|
|
||||||
--bs-primary: #0d6efd;
|
|
||||||
--bs-secondary: #6c757d;
|
|
||||||
--bs-success: #198754;
|
|
||||||
--bs-info: #0dcaf0;
|
|
||||||
--bs-warning: #ffc107;
|
|
||||||
--bs-danger: #dc3545;
|
|
||||||
--bs-light: #f8f9fa;
|
|
||||||
--bs-dark: #212529;
|
|
||||||
--bs-primary-rgb: 13, 110, 253;
|
|
||||||
--bs-secondary-rgb: 108, 117, 125;
|
|
||||||
--bs-success-rgb: 25, 135, 84;
|
|
||||||
--bs-info-rgb: 13, 202, 240;
|
|
||||||
--bs-warning-rgb: 255, 193, 7;
|
|
||||||
--bs-danger-rgb: 220, 53, 69;
|
|
||||||
--bs-light-rgb: 248, 249, 250;
|
|
||||||
--bs-dark-rgb: 33, 37, 41;
|
|
||||||
--bs-white-rgb: 255, 255, 255;
|
|
||||||
--bs-black-rgb: 0, 0, 0;
|
|
||||||
--bs-body-color-rgb: 33, 37, 41;
|
|
||||||
--bs-body-bg-rgb: 255, 255, 255;
|
|
||||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
||||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
||||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
|
||||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
|
||||||
--bs-body-font-size: 1rem;
|
|
||||||
--bs-body-font-weight: 400;
|
|
||||||
--bs-body-line-height: 1.5;
|
|
||||||
--bs-body-color: #212529;
|
|
||||||
--bs-body-bg: #fff;
|
|
||||||
--bs-border-width: 1px;
|
|
||||||
--bs-border-style: solid;
|
|
||||||
--bs-border-color: #dee2e6;
|
|
||||||
--bs-border-color-translucent: rgba(0, 0, 0, 0.175);
|
|
||||||
--bs-border-radius: 0.375rem;
|
|
||||||
--bs-border-radius-sm: 0.25rem;
|
|
||||||
--bs-border-radius-lg: 0.5rem;
|
|
||||||
--bs-border-radius-xl: 1rem;
|
|
||||||
--bs-border-radius-2xl: 2rem;
|
|
||||||
--bs-border-radius-pill: 50rem;
|
|
||||||
--bs-link-color: #0d6efd;
|
|
||||||
--bs-link-hover-color: #0a58ca;
|
|
||||||
--bs-code-color: #d63384;
|
|
||||||
--bs-highlight-bg: #fff3cd;
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
|
||||||
:root {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: var(--bs-body-font-family);
|
|
||||||
font-size: var(--bs-body-font-size);
|
|
||||||
font-weight: var(--bs-body-font-weight);
|
|
||||||
line-height: var(--bs-body-line-height);
|
|
||||||
color: var(--bs-body-color);
|
|
||||||
text-align: var(--bs-body-text-align);
|
|
||||||
background-color: var(--bs-body-bg);
|
|
||||||
-webkit-text-size-adjust: 100%;
|
|
||||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
margin: 1rem 0;
|
|
||||||
color: inherit;
|
|
||||||
border: 0;
|
|
||||||
border-top: 1px solid;
|
|
||||||
opacity: 0.25;
|
|
||||||
}
|
|
||||||
|
|
||||||
h6, h5, h4, h3, h2, h1 {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: calc(1.375rem + 1.5vw);
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h1 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: calc(1.325rem + 0.9vw);
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h2 {
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
font-size: calc(1.3rem + 0.6vw);
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h3 {
|
|
||||||
font-size: 1.75rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h4 {
|
|
||||||
font-size: calc(1.275rem + 0.3vw);
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
h4 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
font-size: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
h6 {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
abbr[title] {
|
|
||||||
-webkit-text-decoration: underline dotted;
|
|
||||||
text-decoration: underline dotted;
|
|
||||||
cursor: help;
|
|
||||||
-webkit-text-decoration-skip-ink: none;
|
|
||||||
text-decoration-skip-ink: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
address {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
font-style: normal;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul {
|
|
||||||
padding-right: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul,
|
|
||||||
dl {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol ol,
|
|
||||||
ul ul,
|
|
||||||
ol ul,
|
|
||||||
ul ol {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
blockquote {
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
b,
|
|
||||||
strong {
|
|
||||||
font-weight: bolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
small {
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
|
|
||||||
mark {
|
|
||||||
padding: 0.1875em;
|
|
||||||
background-color: var(--bs-highlight-bg);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub,
|
|
||||||
sup {
|
|
||||||
position: relative;
|
|
||||||
font-size: 0.75em;
|
|
||||||
line-height: 0;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub {
|
|
||||||
bottom: -0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
sup {
|
|
||||||
top: -0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: var(--bs-link-color);
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
a:hover {
|
|
||||||
color: var(--bs-link-hover-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre,
|
|
||||||
code,
|
|
||||||
kbd,
|
|
||||||
samp {
|
|
||||||
font-family: var(--bs-font-monospace);
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
display: block;
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
overflow: auto;
|
|
||||||
font-size: 0.875em;
|
|
||||||
}
|
|
||||||
pre code {
|
|
||||||
font-size: inherit;
|
|
||||||
color: inherit;
|
|
||||||
word-break: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
font-size: 0.875em;
|
|
||||||
color: var(--bs-code-color);
|
|
||||||
word-wrap: break-word;
|
|
||||||
}
|
|
||||||
a > code {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
kbd {
|
|
||||||
padding: 0.1875rem 0.375rem;
|
|
||||||
font-size: 0.875em;
|
|
||||||
color: var(--bs-body-bg);
|
|
||||||
background-color: var(--bs-body-color);
|
|
||||||
border-radius: 0.25rem;
|
|
||||||
}
|
|
||||||
kbd kbd {
|
|
||||||
padding: 0;
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
figure {
|
|
||||||
margin: 0 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
img,
|
|
||||||
svg {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
caption-side: bottom;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
caption {
|
|
||||||
padding-top: 0.5rem;
|
|
||||||
padding-bottom: 0.5rem;
|
|
||||||
color: #6c757d;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
text-align: inherit;
|
|
||||||
text-align: -webkit-match-parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
thead,
|
|
||||||
tbody,
|
|
||||||
tfoot,
|
|
||||||
tr,
|
|
||||||
td,
|
|
||||||
th {
|
|
||||||
border-color: inherit;
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
button:focus:not(:focus-visible) {
|
|
||||||
outline: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
input,
|
|
||||||
button,
|
|
||||||
select,
|
|
||||||
optgroup,
|
|
||||||
textarea {
|
|
||||||
margin: 0;
|
|
||||||
font-family: inherit;
|
|
||||||
font-size: inherit;
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
select {
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
[role=button] {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
word-wrap: normal;
|
|
||||||
}
|
|
||||||
select:disabled {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
[list]:not([type=date]):not([type=datetime-local]):not([type=month]):not([type=week]):not([type=time])::-webkit-calendar-picker-indicator {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
button,
|
|
||||||
[type=button],
|
|
||||||
[type=reset],
|
|
||||||
[type=submit] {
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
button:not(:disabled),
|
|
||||||
[type=button]:not(:disabled),
|
|
||||||
[type=reset]:not(:disabled),
|
|
||||||
[type=submit]:not(:disabled) {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-moz-focus-inner {
|
|
||||||
padding: 0;
|
|
||||||
border-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset {
|
|
||||||
min-width: 0;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
legend {
|
|
||||||
float: right;
|
|
||||||
width: 100%;
|
|
||||||
padding: 0;
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
font-size: calc(1.275rem + 0.3vw);
|
|
||||||
line-height: inherit;
|
|
||||||
}
|
|
||||||
@media (min-width: 1200px) {
|
|
||||||
legend {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
legend + * {
|
|
||||||
clear: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-datetime-edit-fields-wrapper,
|
|
||||||
::-webkit-datetime-edit-text,
|
|
||||||
::-webkit-datetime-edit-minute,
|
|
||||||
::-webkit-datetime-edit-hour-field,
|
|
||||||
::-webkit-datetime-edit-day-field,
|
|
||||||
::-webkit-datetime-edit-month-field,
|
|
||||||
::-webkit-datetime-edit-year-field {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-inner-spin-button {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
[type=search] {
|
|
||||||
outline-offset: -2px;
|
|
||||||
-webkit-appearance: textfield;
|
|
||||||
}
|
|
||||||
|
|
||||||
[type="tel"],
|
|
||||||
[type="url"],
|
|
||||||
[type="email"],
|
|
||||||
[type="number"] {
|
|
||||||
direction: ltr;
|
|
||||||
}
|
|
||||||
::-webkit-search-decoration {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-color-swatch-wrapper {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-file-upload-button {
|
|
||||||
font: inherit;
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
::file-selector-button {
|
|
||||||
font: inherit;
|
|
||||||
-webkit-appearance: button;
|
|
||||||
}
|
|
||||||
|
|
||||||
output {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
iframe {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
summary {
|
|
||||||
display: list-item;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
progress {
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
[hidden] {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
|
4266
api/api/static/css/bootstrap-utilities.css
vendored
4257
api/api/static/css/bootstrap-utilities.rtl.css
vendored
10878
api/api/static/css/bootstrap.css
vendored
7
api/api/static/css/bootstrap.min.css
vendored
10842
api/api/static/css/bootstrap.rtl.css
vendored
7
api/api/static/css/bootstrap.rtl.min.css
vendored
7075
api/api/static/js/bootstrap.bundle.js
vendored
7
api/api/static/js/bootstrap.bundle.min.js
vendored
5202
api/api/static/js/bootstrap.esm.js
vendored
7
api/api/static/js/bootstrap.esm.min.js
vendored
5249
api/api/static/js/bootstrap.js
vendored
7
api/api/static/js/bootstrap.min.js
vendored
@ -1,7 +0,0 @@
|
|||||||
/*!
|
|
||||||
* 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
|
|
@ -1,14 +0,0 @@
|
|||||||
<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,100 +0,0 @@
|
|||||||
{% load static %}
|
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<title>Bootstrap demo</title>
|
|
||||||
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<header class="p-3 text-bg-dark">
|
|
||||||
<div class="container">
|
|
||||||
<div class="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
|
|
||||||
<a href="/" class="d-flex align-items-center mb-2 mb-lg-0 text-white text-decoration-none">
|
|
||||||
<svg class="bi me-2" width="40" height="32" role="img" aria-label="Bootstrap"><use xlink:href="#bootstrap"></use></svg>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-center mb-md-0">
|
|
||||||
<li><a href="#" class="nav-link px-2 text-secondary">Home</a></li>
|
|
||||||
<li><a href="#" class="nav-link px-2 text-white">Features</a></li>
|
|
||||||
<li><a href="#" class="nav-link px-2 text-white">Pricing</a></li>
|
|
||||||
<li><a href="#" class="nav-link px-2 text-white">FAQs</a></li>
|
|
||||||
<li><a href="#" class="nav-link px-2 text-white">About</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<form class="col-12 col-lg-auto mb-3 mb-lg-0 me-lg-3" role="search">
|
|
||||||
<input type="search" class="form-control form-control-dark text-bg-dark" placeholder="Search..." aria-label="Search">
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div class="text-end">
|
|
||||||
<button type="button" class="btn btn-outline-light me-2">Login</button>
|
|
||||||
<button type="button" class="btn btn-warning">Sign-up</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
<script src="{% static 'js/bootstrap.bundle.min.js' %}" crossorigin="anonymous"></script>
|
|
||||||
<!-- end header -->
|
|
||||||
<div class="col-lg-8 mx-auto p-4 py-md-5">
|
|
||||||
<!-- main -->
|
|
||||||
<main>
|
|
||||||
<h1>Bills</h1>
|
|
||||||
<p class="fs-5 col-md-8">Quickly and easily start adding your bills and service costs to get a better understanding of your operational expenses.</p>
|
|
||||||
|
|
||||||
<div class="mb-5">
|
|
||||||
<a href="#" class="btn btn-primary btn-lg px-4">Sign-up!</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr class="col-3 col-md-2 mb-5">
|
|
||||||
|
|
||||||
<div class="row g-5">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h2>Starter projects</h2>
|
|
||||||
<p>Ready to beyond the starter template? Check out these open source projects that you can quickly duplicate to a new GitHub repository.</p>
|
|
||||||
<ul class="icon-list ps-0">
|
|
||||||
<li class="d-flex align-items-start mb-1"><a href="https://github.com/twbs/bootstrap-npm-starter" rel="noopener" target="_blank">Bootstrap npm starter</a></li>
|
|
||||||
<li class="text-muted d-flex align-items-start mb-1">Bootstrap Parcel starter (coming soon!)</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h2>Guides</h2>
|
|
||||||
<p>Read more detailed instructions and documentation on using or contributing to Bootstrap.</p>
|
|
||||||
<ul class="icon-list ps-0">
|
|
||||||
<li class="d-flex align-items-start mb-1"><a href="../getting-started/introduction/">Bootstrap quick start guide</a></li>
|
|
||||||
<li class="d-flex align-items-start mb-1"><a href="../getting-started/webpack/">Bootstrap Webpack guide</a></li>
|
|
||||||
<li class="d-flex align-items-start mb-1"><a href="../getting-started/parcel/">Bootstrap Parcel guide</a></li>
|
|
||||||
<li class="d-flex align-items-start mb-1"><a href="../getting-started/vite/">Bootstrap Vite guide</a></li>
|
|
||||||
<li class="d-flex align-items-start mb-1"><a href="../getting-started/contribute/">Contributing to Bootstrap</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<!-- end main -->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- footer -->
|
|
||||||
<div class="container">
|
|
||||||
<footer class="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
|
|
||||||
<p class="col-md-4 mb-0 text-muted">© 2022 Automated Bytes Inc.</p>
|
|
||||||
|
|
||||||
<a href="/" class="col-md-4 d-flex align-items-center justify-content-center mb-3 mb-md-0 me-md-auto link-dark text-decoration-none">
|
|
||||||
<svg class="bi me-2" width="40" height="32"><use xlink:href="#bootstrap"></use></svg>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul class="nav col-md-4 justify-content-end">
|
|
||||||
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">Home</a></li>
|
|
||||||
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">Features</a></li>
|
|
||||||
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">Pricing</a></li>
|
|
||||||
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">FAQs</a></li>
|
|
||||||
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">About</a></li>
|
|
||||||
</ul>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
@ -13,7 +13,7 @@ Including another URLconf
|
|||||||
1. Import the include() function: from django.urls import include, path
|
1. Import the include() function: from django.urls import include, path
|
||||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||||
"""
|
"""
|
||||||
from django.urls import path
|
from django.conf.urls import url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.urls import include, path
|
from django.urls import include, path
|
||||||
@ -24,6 +24,10 @@ 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,16 +1,4 @@
|
|||||||
from django.contrib.auth import logout
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.template import loader
|
|
||||||
from django.shortcuts import redirect
|
|
||||||
|
|
||||||
|
|
||||||
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))
|
|
||||||
|
|
||||||
|
|
||||||
def logout(request):
|
|
||||||
logout(request)
|
|
||||||
redirect(index)
|
|
@ -1,21 +1,32 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
import pendulum
|
||||||
|
|
||||||
from .models import Bill, Organization
|
from .models import Bill
|
||||||
|
from.tasks import get_overdue_bills, get_upcoming_bills
|
||||||
|
|
||||||
|
@admin.action(description='Duplicate Bill')
|
||||||
|
def duplicate(modeladmin, request, queryset):
|
||||||
|
for object in queryset:
|
||||||
|
object.id = None
|
||||||
|
# object.name = object.name+'-duplicate' ## This was temporary while I figured out how to massage the date
|
||||||
|
# print(object.due)
|
||||||
|
new_date = (pendulum.parse(str(object.due), exact=True)).add(months=1)
|
||||||
|
# print(new_date)
|
||||||
|
object.due = new_date
|
||||||
|
object.save()
|
||||||
|
|
||||||
|
@admin.action(description='Duplicate Older Bill')
|
||||||
|
def duplicate_old(modeladmin, request, queryset):
|
||||||
|
for object in queryset:
|
||||||
|
object.id = None
|
||||||
|
new_date = (pendulum.parse(str(object.due), exact=True)).subtract(months=1)
|
||||||
|
object.due = new_date
|
||||||
|
object.save()
|
||||||
|
|
||||||
@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'
|
||||||
|
]
|
||||||
|
actions = [duplicate, duplicate_old, get_overdue_bills, get_upcoming_bills]
|
||||||
@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',)
|
|
@ -2,10 +2,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from jet.dashboard import modules
|
from jet.dashboard import modules
|
||||||
from jet.dashboard.dashboard import Dashboard, AppIndexDashboard
|
from jet.dashboard.dashboard import Dashboard, AppIndexDashboard
|
||||||
|
|
||||||
|
|
||||||
class CustomIndexDashboard(Dashboard):
|
class CustomIndexDashboard(Dashboard):
|
||||||
# app_label = "api"
|
|
||||||
|
|
||||||
columns = 3
|
columns = 3
|
||||||
|
|
||||||
def init_with_context(self, context):
|
def init_with_context(self, context):
|
||||||
@ -28,7 +25,19 @@ class CustomIndexDashboard(Dashboard):
|
|||||||
'url': 'irc://irc.freenode.net/django',
|
'url': 'irc://irc.freenode.net/django',
|
||||||
'external': True,
|
'external': True,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'title': _('COME ON'),
|
||||||
|
'url': 'irc://irc.freenode.net/django',
|
||||||
|
'external': True,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
column=0,
|
column=0,
|
||||||
order=0
|
order=0
|
||||||
))
|
))
|
||||||
|
|
||||||
|
self.children.append(modules.ModelList(
|
||||||
|
_('Models'),
|
||||||
|
exclude=('auth.*',),
|
||||||
|
column=0,
|
||||||
|
order=0
|
||||||
|
))
|
@ -1,24 +0,0 @@
|
|||||||
# 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')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,19 +0,0 @@
|
|||||||
# 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,36 +1,18 @@
|
|||||||
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(
|
is_missed = models.BooleanField(default=False, verbose_name='Missed Payment')
|
||||||
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))
|
|
||||||
|
35
api/bills/tasks.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
### Celery Tasks!
|
||||||
|
|
||||||
|
from django.core.checks import messages
|
||||||
|
import pendulum
|
||||||
|
from .models import Bill
|
||||||
|
|
||||||
|
from celery import shared_task
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def get_overdue_bills(modeladmin, request, queryset):
|
||||||
|
|
||||||
|
try:
|
||||||
|
bills_list = []
|
||||||
|
bill_request = Bill.objects.filter(is_overdue=True)
|
||||||
|
print(bill_request)
|
||||||
|
for bill in bill_request:
|
||||||
|
# print(bill.id)
|
||||||
|
bills_list.append(bill.id)
|
||||||
|
except Bill.DoesNotExist:
|
||||||
|
bills_list = "There are no bills that are overdue!"
|
||||||
|
print("function complete")
|
||||||
|
print(bills_list)
|
||||||
|
return('This is a test')
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def get_upcoming_bills(modeladmin, request, queryset):
|
||||||
|
today = pendulum.today().add(days=7)
|
||||||
|
print(today)
|
||||||
|
try:
|
||||||
|
bill_request = Bill.objects.filter(is_paid=False)
|
||||||
|
print(bill_request)
|
||||||
|
except Bill.DoesNotExist:
|
||||||
|
message = 'There are no bill coming due soon that are unpaid.'
|
||||||
|
print(message)
|
||||||
|
return(message)
|
@ -1,10 +0,0 @@
|
|||||||
<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>
|
|
@ -1,17 +0,0 @@
|
|||||||
<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}}
|
|
@ -1,14 +0,0 @@
|
|||||||
<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,9 +1,3 @@
|
|||||||
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
|
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
from django.urls import path
|
from django.conf.urls import url
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
from django.urls import include, path
|
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('admin/', admin.site.urls),
|
||||||
path('create', views.create, name='create')
|
|
||||||
# path('admin/', admin.site.urls),
|
|
||||||
]
|
]
|
||||||
|
@ -1,32 +1,6 @@
|
|||||||
# from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.contrib.auth import authenticate, login
|
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, redirect
|
|
||||||
|
|
||||||
from .models import Bill
|
|
||||||
|
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
if request.user.is_authenticated:
|
return HttpResponse("Let there be bills!")
|
||||||
bills_list = Bill.objects.order_by('-due')
|
# Create your views here.
|
||||||
# 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))
|
|
||||||
else:
|
|
||||||
# return redirect(api.index)
|
|
||||||
return render(request, "index.html")
|
|
||||||
# return render(request, 'bills/index.html', context)
|
|
||||||
|
|
||||||
|
|
||||||
def detail(request, 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')
|
|
||||||
|