working on tickets implementation

This commit is contained in:
2024-01-04 21:58:11 +00:00
parent 2b1531a31d
commit d9ecd692ef
48 changed files with 1190 additions and 253 deletions

34
.gitignore vendored Normal file
View File

@ -0,0 +1,34 @@
# byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# env vars
.env
# tests and coverage
*.pytest_cache
.coverage
# database & logs
*.db
*.sqlite3
*.log
# venv
env
venv
# other
.DS_Store
# javascript
package-lock.json
staticfiles/*
!staticfiles/.gitkeep
.vscode/symbols.json
apps/static/assets/node_modules
apps/static/assets/yarn.lock
apps/static/assets/.temp

206
README.md
View File

@ -1,204 +1,20 @@
# [Adminator Django](https://appseed.us/product/adminator/django/) # Contributing
Open-source **[Django Dashboard](https://appseed.us/admin-dashboards/django/)** generated by `AppSeed` op top of an iconic design. For newcomers, **Adminator** is one of the best open-source admin dashboard & control panel theme. Built on top of Bootstrap, `Adminator` provides a range of responsive, reusable, and commonly used components. ## Migrations
- 👉 [Adminator Django](https://appseed.us/product/adminator/django/) - `Product page` If facing migration errors, delete folders in all apps called `migrations` and delete the `db.sqlite3` database file. Note you will lose all data.
- 👉 [Adminator Django](https://django-adminator.appseed-srv1.com) - `LIVE deployment`
<br /> To get started:
> 🚀 Built with [App Generator](https://appseed.us/generator/), Timestamp: `2022-05-31 07:49` 1. `python manage.py makemigrations authentication`
2. `python manage.py makemigrations home`
3. `python manage.py migrate`
- ✅ Database: `sqlite` ## Run the server
- ✅ UI-Ready app, Django Native ORM
-`Session-Based authentication`, Forms validation
- ✅ Design: [Adminator](https://github.com/app-generator/adminator) **v2.0.3**
- Gulp-generated version
<br /> `python manage.py runserver 0.0.0.0:8000`
![Adminator Dashboard - Starter generated by AppSeed.](https://user-images.githubusercontent.com/51070104/173175611-63faf177-33d8-4238-ad0b-271a16465bd0.png) ## Access the website
<br /> `http://localhost:8000`
## ✨ Start the app in Docker
> **Step 1** - Download the code from the GH repository (using `GIT`)
```bash
$ # Get the code
$ git clone https://github.com/app-generator/django-adminator.git
$ cd django-adminator
```
<br />
> **Step 2** - Start the APP in `Docker`
```bash
$ docker-compose up --build
```
Visit `http://localhost:5085` in your browser. The app should be up & running.
<br />
## ✨ How to use it
> Download the code
```bash
$ # Get the code
$ git clone https://github.com/app-generator/django-adminator.git
$ cd django-adminator
```
<br />
### 👉 Set Up for `Unix`, `MacOS`
> Install modules via `VENV`
```bash
$ virtualenv env
$ source env/bin/activate
$ pip3 install -r requirements.txt
```
<br />
> Set Up Database
```bash
$ python manage.py makemigrations
$ python manage.py migrate
```
<br />
> Start the app
```bash
$ python manage.py runserver
```
At this point, the app runs at `http://127.0.0.1:8000/`.
<br />
### 👉 Set Up for `Windows`
> Install modules via `VENV` (windows)
```
$ virtualenv env
$ .\env\Scripts\activate
$ pip3 install -r requirements.txt
```
<br />
> Set Up Database
```bash
$ python manage.py makemigrations
$ python manage.py migrate
```
<br />
> Start the app
```bash
$ python manage.py runserver
```
At this point, the app runs at `http://127.0.0.1:8000/`.
<br />
### 👉 Create Users
By default, the app redirects guest users to authenticate. In order to access the private pages, follow this set up:
- Start the app via `flask run`
- Access the `registration` page and create a new user:
- `http://127.0.0.1:8000/register/`
- Access the `sign in` page and authenticate
- `http://127.0.0.1:8000/login/`
<br />
## ✨ Code-base structure
The project is coded using a simple and intuitive structure presented below:
```bash
< PROJECT ROOT >
|
|-- core/ # Implements app configuration
| |-- settings.py # Defines Global Settings
| |-- wsgi.py # Start the app in production
| |-- urls.py # Define URLs served by all apps/nodes
|
|-- apps/
| |
| |-- home/ # A simple app that serve HTML files
| | |-- views.py # Serve HTML pages for authenticated users
| | |-- urls.py # Define some super simple routes
| |
| |-- authentication/ # Handles auth routes (login and register)
| | |-- urls.py # Define authentication routes
| | |-- views.py # Handles login and registration
| | |-- forms.py # Define auth forms (login and register)
| |
| |-- static/
| | |-- <css, JS, images> # CSS files, Javascripts files
| |
| |-- templates/ # Templates used to render pages
| |-- includes/ # HTML chunks and components
| | |-- navigation.html # Top menu component
| | |-- sidebar.html # Sidebar component
| | |-- footer.html # App Footer
| | |-- scripts.html # Scripts common to all pages
| |
| |-- layouts/ # Master pages
| | |-- base-fullscreen.html # Used by Authentication pages
| | |-- base.html # Used by common pages
| |
| |-- accounts/ # Authentication pages
| | |-- login.html # Login page
| | |-- register.html # Register page
| |
| |-- home/ # UI Kit Pages
| |-- index.html # Index page
| |-- 404-page.html # 404 page
| |-- *.html # All other pages
|
|-- requirements.txt # Development modules - SQLite storage
|
|-- .env # Inject Configuration via Environment
|-- manage.py # Start the app - Django default start script
|
|-- ************************************************************************
```
<br />
## ✨ PRO Version
> For more components, pages and priority on support, feel free to take a look at this amazing starter:
Soft UI Dashboard is a premium Bootstrap 5 Design now available for download in Django. Made of hundred of elements, designed blocks, and fully coded pages, Soft UI Dashboard PRO is ready to help you create stunning websites and web apps.
- 👉 [Soft UI Dashboard PRO Django](https://appseed.us/product/soft-ui-dashboard-pro/django/) - Product Page
- 👉 [Soft UI Dashboard PRO Django](https://django-soft-ui-dashboard-pro.appseed-srv1.com/) - LIVE Demo
<br >
![Soft UI Dashboard PRO - Starter generated by AppSeed.](https://user-images.githubusercontent.com/51070104/170829870-8acde5af-849a-4878-b833-3be7e67cff2d.png)
<br />
---
[Adminator Django](https://appseed.us/product/adminator/django/) - Open-source starter generated by **[AppSeed Generator](https://appseed.us/generator/)**.

View File

@ -1,8 +1,8 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
# Register your models here. from .models import User
admin.site.register(User, UserAdmin)

View File

@ -0,0 +1,45 @@
# Generated by Django 3.2.16 on 2024-01-04 14:05
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.utils.timezone
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name='User',
fields=[
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.16 on 2024-01-04 14:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='user',
name='icon',
field=models.ImageField(default='users/default.webp', upload_to='users'),
),
]

View File

@ -0,0 +1,24 @@
# Generated by Django 3.2.16 on 2024-01-04 14:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0002_user_icon'),
]
operations = [
migrations.AddField(
model_name='user',
name='name',
field=models.CharField(default='Corban-Lee Jones', max_length=150),
preserve_default=False,
),
migrations.AlterField(
model_name='user',
name='email',
field=models.EmailField(max_length=254, unique=True),
),
]

View File

@ -1,4 +0,0 @@
# -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""

View File

@ -1,8 +1,23 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us import uuid
"""
from django.db import models from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
# default user profile image
# https://st3.depositphotos.com/9998432/13335/v/450/depositphotos_133352156-stock-illustration-default-placeholder-profile-icon.jpg
class User(AbstractUser):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
icon = models.ImageField(upload_to="users", default="users/default.webp")
name = models.CharField(max_length=150)
email = models.EmailField(unique=True)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["id", "icon", "name"]
def __str__(self):
return self.name

View File

@ -4,11 +4,12 @@ Copyright (c) 2019 - present AppSeed.us
""" """
from django.urls import path from django.urls import path
from .views import login_view, register_user from .views import login_view, register_user, profile_view
from django.contrib.auth.views import LogoutView from django.contrib.auth.views import LogoutView
urlpatterns = [ urlpatterns = [
path('login/', login_view, name="login"), path('login/', login_view, name="login"),
path('register/', register_user, name="register"), path('register/', register_user, name="register"),
path("logout/", LogoutView.as_view(), name="logout") path("logout/", LogoutView.as_view(), name="logout"),
path("profile/", profile_view, name="profile"),
] ]

View File

@ -1,11 +1,9 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""
# Create your views here.
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
from django.contrib.auth.decorators import login_required
from .forms import LoginForm, SignUpForm from .forms import LoginForm, SignUpForm
@ -54,3 +52,7 @@ def register_user(request):
form = SignUpForm() form = SignUpForm()
return render(request, "accounts/register.html", {"form": form, "msg": msg, "success": success}) return render(request, "accounts/register.html", {"form": form, "msg": msg, "success": success})
@login_required()
def profile_view(request):
return render(request, "accounts/profile.html")

View File

@ -1,8 +1,7 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""
from django.contrib import admin from django.contrib import admin
# Register your models here. from .models import Ticket
admin.site.register(Ticket)

View File

@ -0,0 +1,45 @@
# Generated by Django 3.2.16 on 2024-01-04 14:05
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='TicketPriority',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=32)),
('colour', models.CharField(max_length=7)),
],
),
migrations.CreateModel(
name='TicketTag',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=32)),
('colour', models.CharField(max_length=7)),
],
),
migrations.CreateModel(
name='Ticket',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=60)),
('description', models.TextField(max_length=650)),
('create_timestamp', models.DateTimeField(default=django.utils.timezone.now)),
('edit_timestamp', models.DateTimeField(default=django.utils.timezone.now)),
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
]

View File

@ -1,4 +0,0 @@
# -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""

View File

@ -1,10 +1,67 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us from datetime import timedelta, datetime
"""
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.conf import settings
from django.utils import timezone
# Create your models here.
class TicketPriority(models.Model):
title = models.CharField(max_length=32)
colour = models.CharField(max_length=7)
class TicketTag(models.Model):
title = models.CharField(max_length=32)
colour = models.CharField(max_length=7)
class Ticket(models.Model):
title = models.CharField(max_length=60)
description = models.TextField(max_length=650)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
create_timestamp = models.DateTimeField(editable=True, default=timezone.now)
edit_timestamp = models.DateTimeField(editable=True, default=timezone.now)
def __str__(self):
return f"#{self.id}{self.title}{self.author}"
@property
def is_edited(self) -> bool:
"""Returns boolean if the ticket is believed to have been edited.
We assume a ticket is edited if the edit_timestamp doesn't match the create_timestamp.
Returns
-------
bool
True if `self.edit_timestamp` doesn't match `self.create_timestamp`, False otherwise.
"""
return self.create_timestamp != self.edit_timestamp
@property
def is_older_than_day(self) -> bool:
"""Returns boolean dependent on if `self.timestamp` is older than 24 hours.
Returns
-------
bool
True if `self.timestamp` is older than 24 hours, False otherwise.
"""
dayago = timezone.now() - timedelta(hours=24)
return self.timestamp <= dayago
@property
def timestamp(self) -> datetime:
"""Returns `self.edit_timestamp` if `self.is_edited` is True, otherwise
returns `self.create_timestamp`.
Returns
-------
datetime
Either `self.edit_timestamp` or `self.create_timestamp`.
"""
return self.edit_timestamp if self.is_edited else self.create_timestamp

View File

@ -3,7 +3,7 @@
Copyright (c) 2019 - present AppSeed.us Copyright (c) 2019 - present AppSeed.us
""" """
from django.urls import path, re_path from django.urls import path, re_path, include
from apps.home import views from apps.home import views
urlpatterns = [ urlpatterns = [
@ -11,6 +11,13 @@ urlpatterns = [
# The home page # The home page
path('', views.index, name='home'), path('', views.index, name='home'),
# Custom Dashboard
path('dashboard/', views.dashboard, name="dashboard"),
path('tickets/', include([
path('', views.tickets, name="tickets"),
path('new/', views.new_ticket, name="ticket-new"),
])),
# Matches any html file # Matches any html file
re_path(r'^.*\.*', views.pages, name='pages'), re_path(r'^.*\.*', views.pages, name='pages'),

View File

@ -1,16 +1,44 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us from datetime import timedelta, datetime
"""
from django import template from django import template
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.template import loader from django.template import loader
from django.shortcuts import render
from django.urls import reverse from django.urls import reverse
from .models import Ticket
@login_required(login_url="/login/")
@login_required()
def dashboard(request):
return render(request, "home/dashboard.html")
@login_required()
def tickets(request):
tickets = Ticket.objects.all().order_by("-create_timestamp")
context = {
"tickets": tickets,
"dayago": datetime.now() - timedelta(hours=24)
}
return render(request, "home/tickets.html", context)
def get_ticket(request, ticket_id: int):
ticket = Ticket.objects.get(id=ticket_id)
@login_required()
def new_ticket(request):
return render(request, "home/newticket.html")
@login_required()
def index(request): def index(request):
context = {'segment': 'index'} context = {'segment': 'index'}
@ -18,7 +46,7 @@ def index(request):
return HttpResponse(html_template.render(context, request)) return HttpResponse(html_template.render(context, request))
@login_required(login_url="/login/") @login_required()
def pages(request): def pages(request):
context = {} context = {}
# All resource paths end in .html. # All resource paths end in .html.

View File

@ -69077,3 +69077,4 @@ table.dataTable.no-footer {
ADD Custom code bellow this block ADD Custom code bellow this block
*/ */
/*# sourceMappingURL=index.css.map */ /*# sourceMappingURL=index.css.map */

View File

@ -0,0 +1,49 @@
{% extends "layouts/base.html" %}
{% block title %} Profile {% endblock title %}
<!-- Specific CSS goes HERE -->
{% block stylesheets %}{% endblock stylesheets %}
{% block content %}
<!-- ### $App Screen Content ### -->
<main class='main-content bgc-grey-100'>
<div id='mainContent'>
<div class="row gap-20 masonry pos-r">
<div class="masonry-sizer col-md-6"></div>
<div class="masonry-item col-md-6">
<div class="bgc-white p-20 bd">
<h6 class="c-grey-900">Basic Form</h6>
<div class="mT-30">
<form>
<div class="mb-3">
<label class="form-label" for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email">
<small id="emailHelp" class="text-muted">We'll never share your email with anyone else.</small>
</div>
<button type="submit" class="btn btn-primary btn-color">Submit</button>
</form>
</div>
</div>
</div>
<div class="masonry-item col-md-6">
<div class="bgc-white p-20 bd">
<div class="row pos-r justify-content-center justify-content-md-start">
<div class="col-md-4 col-8">
<img src="{{ request.user.icon.url }}" alt="" class="bdrs-50p w-100">
</div>
<div class="col-md-6">
<h3>{{ request.user.name }}</h3>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock content %}
<!-- Specific Page JS goes HERE -->
{% block javascripts %}{% endblock javascripts %}

View File

@ -0,0 +1,287 @@
{% extends "layouts/base.html" %}
{% block title %} Dashboard {% endblock title %}
<!-- Specific CSS goes HERE -->
{% block stylesheets %}{% endblock stylesheets %}
{% block content %}
<!-- ### $App Screen Content ### -->
<main class='main-content bgc-grey-100'>
<div id='mainContent'>
<div class="row gap-20 masonry pos-r">
<div class="masonry-sizer col-md-6"></div>
<div class="masonry-item w-100">
<div class="row gap-20">
<!-- #Toatl Tickets ==================== -->
<div class='col-md-3'>
<div class="layers bd bgc-white p-20">
<div class="layer w-100 mB-10">
<h6 class="lh-1">Total Tickets</h6>
</div>
<div class="layer w-100">
<div class="peers ai-sb fxw-nw">
<div class="peer peer-greed">
<span id="sparklinedash"></span>
</div>
<div class="peer">
<span class="d-ib lh-0 va-m fw-600 bdrs-10em pX-15 pY-15 bgc-green-50 c-green-500">+10%</span>
</div>
</div>
</div>
</div>
</div>
<!-- #Open Tickets ==================== -->
<div class='col-md-3'>
<div class="layers bd bgc-white p-20">
<div class="layer w-100 mB-10">
<h6 class="lh-1">Open Tickets</h6>
</div>
<div class="layer w-100">
<div class="peers ai-sb fxw-nw">
<div class="peer peer-greed">
<span id="sparklinedash2"></span>
</div>
<div class="peer">
<span class="d-ib lh-0 va-m fw-600 bdrs-10em pX-15 pY-15 bgc-red-50 c-red-500">-7%</span>
</div>
</div>
</div>
</div>
</div>
<!-- #Pending Tickets ==================== -->
<div class='col-md-3'>
<div class="layers bd bgc-white p-20">
<div class="layer w-100 mB-10">
<h6 class="lh-1">Pending Tickets</h6>
</div>
<div class="layer w-100">
<div class="peers ai-sb fxw-nw">
<div class="peer peer-greed">
<span id="sparklinedash3"></span>
</div>
<div class="peer">
<span class="d-ib lh-0 va-m fw-600 bdrs-10em pX-15 pY-15 bgc-purple-50 c-purple-500">~12%</span>
</div>
</div>
</div>
</div>
</div>
<!-- #Closed Tickets ==================== -->
<div class='col-md-3'>
<div class="layers bd bgc-white p-20">
<div class="layer w-100 mB-10">
<h6 class="lh-1">Closed Tickets</h6>
</div>
<div class="layer w-100">
<div class="peers ai-sb fxw-nw">
<div class="peer peer-greed">
<span id="sparklinedash4"></span>
</div>
<div class="peer">
<span class="d-ib lh-0 va-m fw-600 bdrs-10em pX-15 pY-15 bgc-blue-50 c-blue-500">33%</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="masonry-item col-12">
<div class="bd bgc-white">
<div class="peers fxw-nw@lg+ ai-s">
<div class="peer peer-greed w-70p@lg- p-20">
<div class="layers">
<div class="layer w-100 pX-20 pT-20">
<h6 class="lh-1">Monthly Stats</h6>
</div>
<div class="layer w-100 p-20 pos-r">
<canvas id="line-chart" class="mw-100p" height="220"></canvas>
</div>
<div class="layer bdT p-20 w-100">
<div class="peers ai-c jc-c gapX-20">
<div class="peer fw-600">
<span class="fsz-def fw-600 mR-10 c-grey-800">2% <i class="fa fa-level-down c-red-500"></i></span>
<small class="c-grey-500 fw-600">Open Tickets</small>
</div>
<div class="peer fw-600">
<span class="fsz-def fw-600 mR-10 c-grey-800">15% <i class="fa fa-level-up c-green-500"></i></span>
<small class="c-grey-500 fw-600">Pending Tickets</small>
</div>
<div class="peer fw-600">
<span class="fsz-def fw-600 mR-10 c-grey-800">8% <i class="fa fa-level-down c-red-500"></i></span>
<small class="c-grey-500 fw-600">Closed Tickets</small>
</div>
</div>
</div>
</div>
</div>
<div class="peer bdL p-20 w-30p@lg+ w-100p@lg-">
<div class="layers">
<div class="layer w-100">
<!-- Progress Bars -->
<div class="layers">
<div class="layer w-100">
<h5 class="mB-5">14</h5>
<small class="fw-600 c-grey-700">Open Tickets</small>
<span class="pull-right c-grey-600 fsz-sm">35%</span>
<div class="progress mT-10">
<div class="progress-bar bgc-deep-purple-500" role="progressbar" aria-valuenow="35" aria-valuemin="0" aria-valuemax="100" style="width:35%;">
<span class="visually-hidden">35% Complete</span>
</div>
<div class="progress-bar bgc-grey-300" role="progressbar" style="width: 65%;"></div>
</div>
</div>
<div class="layer w-100 mT-15">
<h5 class="mB-5">10</h5>
<small class="fw-600 c-grey-700">Pending Tickets</small>
<span class="pull-right c-grey-600 fsz-sm">25%</span>
<div class="progress mT-10">
<div class="progress-bar bgc-grey-300" role="progressbar" style="width: 35%;"></div>
<div class="progress-bar bgc-blue-500" role="progressbar" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" style="width:25%;">
<span class="visually-hidden">25% Complete</span>
</div>
<div class="progress-bar bgc-grey-300" role="progressbar" style="width: 40%;"></div>
</div>
</div>
<div class="layer w-100 mT-15">
<h5 class="mB-5">16</h5>
<small class="fw-600 c-grey-700">Closed Tickets</small>
<span class="pull-right c-grey-600 fsz-sm">40%</span>
<div class="progress mT-10">
<div class="progress-bar bgc-grey-300" role="progressbar" style="width: 60%;"></div>
<div class="progress-bar bgc-red-500" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width:40%;">
<span class="visually-hidden">40% Complete</span>
</div>
</div>
</div>
</div>
<!-- Pie Charts -->
<div class="peers pT-20 mT-20 bdT fxw-nw@lg+ jc-sb ta-c gap-10">
<div class="peer">
<div class="easy-pie-chart" data-size='80' data-percent="75" data-bar-color='#f44336'>
<span></span>
</div>
<h6 class="fsz-sm">Low Priority</h6>
</div>
<div class="peer">
<div class="easy-pie-chart" data-size='80' data-percent="50" data-bar-color='#2196f3'>
<span></span>
</div>
<h6 class="fsz-sm">Medium Priority</h6>
</div>
<div class="peer">
<div class="easy-pie-chart" data-size='80' data-percent="90" data-bar-color='#ff9800'>
<span></span>
</div>
<h6 class="fsz-sm">High Priority</h6>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="masonry-item col-md-6">
<!-- #Sales Report ==================== -->
<div class="bd bgc-white">
<div class="layers">
<div class="layer w-100 p-20">
<h6 class="lh-1">Tickets Report</h6>
</div>
<div class="layer w-100">
<div class="bgc-light-blue-500 c-white p-20">
<div class="peers ai-c jc-sb gap-40">
<div class="peer peer-greed">
<h5>January 2024</h5>
<p class="mB-0">Tickets Report</p>
</div>
<div class="peer">
<h3 class="text-end">17 Solved</h3>
</div>
</div>
</div>
<div class="table-responsive p-20">
<table class="table">
<thead>
<tr>
<th class=" bdwT-0">Name</th>
<th class=" bdwT-0">Status</th>
<th class=" bdwT-0">Date</th>
<th class=" bdwT-0">Department</th>
</tr>
</thead>
<tbody>
<tr>
<td class="fw-600">Ticket #01</td>
<td><span class="badge bgc-red-50 c-red-700 p-10 lh-0 tt-c rounded-pill">Closed</span> </td>
<td>Jan 18</td>
<td><span class="">Sales</span></td>
</tr>
<tr>
<td class="fw-600">Ticket #02</td>
<td><span class="badge bgc-deep-purple-50 c-deep-purple-700 p-10 lh-0 tt-c rounded-pill">Open</span></td>
<td>Jan 19</td>
<td><span class="">Sales</span></td>
</tr>
<tr>
<td class="fw-600">Ticket #03</td>
<td><span class="badge bgc-red-50 c-red-700 p-10 lh-0 tt-c rounded-pill">Closed</span></td>
<td>Jan 20</td>
<td><span class="">Sales</span></td>
</tr>
<tr>
<td class="fw-600">Ticket #04</td>
<td><span class="badge bgc-blue-50 c-blue-700 p-10 lh-0 tt-c rounded-pill">Pending</span></td>
<td>Jan 21</td>
<td><span class="">Sales</span></td>
</tr>
<tr>
<td class="fw-600">Ticket #05</td>
<td><span class="badge bgc-deep-purple-50 c-deep-purple-700 p-10 lh-0 tt-c rounded-pill">Open</span></td>
<td>Jan 22</td>
<td><span class="">Sales</span></td>
</tr>
<tr>
<td class="fw-600">Ticket #06</td>
<td><span class="badge bgc-deep-purple-50 c-deep-purple-700 p-10 lh-0 tt-c rounded-pill">Open</span> </td>
<td>Jan 23</td>
<td><span class="">Sales</span></td>
</tr>
<tr>
<td class="fw-600">Ticket #07</td>
<td><span class="badge bgc-blue-50 c-blue-700 p-10 lh-0 tt-c rounded-pill">Pending</span></td>
<td>Jan 22</td>
<td><span class="">Sales</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="ta-c bdT w-100 p-20">
<a href="#">Check all the tickets</a>
</div>
</div>
</div>
<div class="masonry-item col-md-6">
<div class="bgc-white p-20 bd">
<h6 class="c-grey-900">Bar Chart</h6>
<div class="mT-30">
<canvas id="bar-chart" height="220"></canvas>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock content %}
<!-- Specific Page JS goes HERE -->
{% block javascripts %}{% endblock javascripts %}

View File

@ -0,0 +1,35 @@
{% extends "layouts/base.html" %}
{% block title %} New Ticket {% endblock title %}
<!-- Specific CSS goes HERE -->
{% block stylesheets %}{% endblock stylesheets %}
{% block content %}
<!-- ### $App Screen Content ### -->
<main class='main-content bgc-grey-100'>
<div id='mainContent'>
<div class="row gap-20 masonry pos-r">
<div class="masonry-sizer col-md-6"></div>
<div class="masonry-item col-md-6">
<div class="bgc-white p-20 bd">
<h6 class="c-grey-900">Basic Form</h6>
<div class="mT-30">
<form>
<div class="mb-3">
<label for="input1" class="form-label">Input 1</label>
<input type="text" id="input1" class="form-control" placeholder="Enter Input 1">
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</main>
{% endblock content %}
<!-- Specific Page JS goes HERE -->
{% block javascripts %}{% endblock javascripts %}

View File

@ -0,0 +1,422 @@
{% extends "layouts/base.html" %}
{% block title %} Tickets {% endblock title %}
<!-- Specific CSS goes HERE -->
{% block stylesheets %}{% endblock stylesheets %}
{% block content %}
<!-- ### $App Screen Content ### -->
<main class='main-content bgc-grey-100'>
<div id='mainContent'>
<div class="full-container">
<div class="email-app">
<div class="email-side-nav remain-height ov-h">
<div class="h-100 layers">
<div class="p-20 bgc-grey-100 layer w-100">
<button type="button" class="btn btn-danger c-white w-100" data-bs-toggle="modal" data-bs-target="#ticketModal">New Ticket</button>
</div>
<div class="scrollable pos-r bdT layer w-100 fxg-1">
<ul class="p-20 nav flex-column">
<li class="nav-item">
<h6>Filters</h6>
</li>
<li class="nav-item ps-3 mT-15">
<h6 class="small">Priority</h6>
<div class="form-check">
<input type="checkbox" id="priority1" class="form-check-input">
<label for="priority1" class="form-check-label">High</label>
</div>
<div class="form-check">
<input type="checkbox" id="priority2" class="form-check-input">
<label for="priority2" class="form-check-label">Medium</label>
</div>
<div class="form-check">
<input type="checkbox" id="priority3" class="form-check-input">
<label for="priority3" class="form-check-label">Low</label>
</div>
</li>
<li class="nav-item ps-3 mT-15">
<h6 class="small">Department</h6>
<div class="form-check">
<input type="checkbox" id="sales" class="form-check-input">
<label for="sales" class="form-check-label">Sales</label>
</div>
<div class="form-check">
<input type="checkbox" id="strategy" class="form-check-input">
<label for="strategy" class="form-check-label">Strategy</label>
</div>
<div class="form-check">
<input type="checkbox" id="marketing" class="form-check-input">
<label for="marketing" class="form-check-label">Marketing</label>
</div>
</li>
<li class="nav-item ps-3 mT-15">
<h6 class="small">Tags</h6>
</li>
<!-- <li class="nav-item mt-5">
<a href="javascript:void(0)" class="nav-link c-grey-800 cH-blue-500 actived">
<div class="peers ai-c jc-sb">
<div class="peer peer-greed">
<i class="mR-10 ti-email"></i>
<span>Inbox</span>
</div>
<div class="peer">
<span class="badge rounded-pill bgc-deep-purple-50 c-deep-purple-700">+99</span>
</div>
</div>
</a>
</li>
<li class="nav-item">
<a href="" class="nav-link c-grey-800 cH-blue-500">
<div class="peers ai-c jc-sb">
<div class="peer peer-greed">
<i class="mR-10 ti-share"></i>
<span>Sent</span>
</div>
<div class="peer">
<span class="badge rounded-pill bgc-green-50 c-green-700">12</span>
</div>
</div>
</a>
</li>
<li class="nav-item">
<a href="" class="nav-link c-grey-800 cH-blue-500">
<div class="peers ai-c jc-sb">
<div class="peer peer-greed">
<i class="mR-10 ti-star"></i>
<span>Important</span>
</div>
<div class="peer">
<span class="badge rounded-pill bgc-blue-50 c-blue-700">3</span>
</div>
</div>
</a>
</li>
<li class="nav-item">
<a href="" class="nav-link c-grey-800 cH-blue-500">
<div class="peers ai-c jc-sb">
<div class="peer peer-greed">
<i class="mR-10 ti-file"></i>
<span>Drafts</span>
</div>
<div class="peer">
<span class="badge rounded-pill bgc-amber-50 c-amber-700">5</span>
</div>
</div>
</a>
</li>
<li class="nav-item">
<a href="" class="nav-link c-grey-800 cH-blue-500">
<div class="peers ai-c jc-sb">
<div class="peer peer-greed">
<i class="mR-10 ti-alert"></i>
<span>Spam</span>
</div>
<div class="peer">
<span class="badge rounded-pill bgc-red-50 c-red-700">1</span>
</div>
</div>
</a>
</li>
<li class="nav-item">
<a href="" class="nav-link c-grey-800 cH-blue-500">
<div class="peers ai-c jc-sb">
<div class="peer peer-greed">
<i class="mR-10 ti-trash"></i>
<span>Trash</span>
</div>
<div class="peer">
<span class="badge rounded-pill bgc-red-50 c-red-700">+99</span>
</div>
</div>
</a>
</li> -->
</ul>
</div>
</div>
</div>
<div class="email-wrapper row remain-height bgc-white ov-h">
<div class="email-list h-100 layers">
<div class="layer w-100">
<div class="bgc-grey-100 peers ai-c p-20 fxw-nw">
<div class="peer me-auto">
<div class="btn-group" role="group">
<button type="button" class="email-side-toggle d-n@md+ btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-menu"></i>
</button>
<button type="button" class="btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-folder"></i>
</button>
<button type="button" class="btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-tag"></i>
</button>
<div class="btn-group" role="group">
<button id="btnGroupDrop1" type="button" class="btn cur-p bgc-white no-after dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="ti-more-alt"></i>
</button>
<ul class="dropdown-menu fsz-sm" aria-labelledby="btnGroupDrop1">
<li>
<a href="" class="d-b td-n pY-5 pX-10 bgcH-grey-100 c-grey-700">
<i class="ti-trash mR-10"></i>
<span>Delete</span>
</a>
</li>
<li>
<a href="" class="d-b td-n pY-5 pX-10 bgcH-grey-100 c-grey-700">
<i class="ti-alert mR-10"></i>
<span>Mark as Spam</span>
</a>
</li>
<li>
<a href="" class="d-b td-n pY-5 pX-10 bgcH-grey-100 c-grey-700">
<i class="ti-star mR-10"></i>
<span>Star</span>
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="peer">
<div class="btn-group" role="group">
<button type="button" class="fsz-xs btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-angle-left"></i>
</button>
<button type="button" class="fsz-xs btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-angle-right"></i>
</button>
</div>
</div>
</div>
</div>
<div class="layer w-100">
<div class="bdT bdB">
<input type="text" class="form-control m-0 bdw-0 pY-15 pX-20 bdrs-0" placeholder="Search...">
</div>
</div>
<div class="layer w-100 fxg-1 scrollable pos-r">
{% for ticket in tickets %}
<div class="email-list-item peers fxw-nw p-20 bdB bgcH-grey-100 cur-p" data-ticket-id="{{ ticket.id }}" data-author-icon="{{ ticket.author.icon.url }}">
<div class="peer mR-10">
<img src="{{ ticket.author.icon.url }}" alt="" class="w-2r bdrs-50p me-2">
<!-- <div class="checkbox checkbox-circle checkbox-info peers ai-c">
<input type="checkbox" id="inputCall1" name="inputCheckboxesCall" class="peer">
<label for="inputCall1" class="form-label peers peer-greed js-sb ai-c"></label>
</div> -->
</div>
<div class="peer peer-greed ov-h">
<div class="peers ai-c">
<div class="peer peer-greed">
<h6 class="ticket-author mb-0">{{ ticket.author }}</h6>
</div>
<div class="peer">
<small class="ticket-timestamp">
{% if ticket.is_older_than_day %}
{{ ticket.timestamp|date:"w M, Y" }}
{% else %}
{{ ticket.timestamp|date:"H:i" }}
{% endif %}
</small>
{% if ticket.is_edited %}
<small>&bull; edited</small>
{% endif %}
</div>
</div>
<h5 class="fsz-def tt-c c-grey-900 ticket-title">{{ ticket.title }}</h5>
<span class="whs-nw w-100 ov-h tov-e d-b ticket-desc">{{ ticket.description }}</span>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="email-content h-100">
<div class="h-100 scrollable pos-r">
<div class="bgc-grey-100 peers ai-c jc-sb p-20 fxw-nw d-n@md+">
<div class="peer">
<div class="btn-group" role="group">
<button type="button" class="back-to-mailbox btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-angle-left"></i>
</button>
<button type="button" class="btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-folder"></i>
</button>
<button type="button" class="btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-tag"></i>
</button>
<div class="btn-group" role="group">
<button id="btnGroupDrop1" type="button" class="btn cur-p bgc-white no-after dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="ti-more-alt"></i>
</button>
<ul class="dropdown-menu fsz-sm" aria-labelledby="btnGroupDrop1">
<li>
<a href="" class="d-b td-n pY-5 pX-10 bgcH-grey-100 c-grey-700">
<i class="ti-trash mR-10"></i>
<span>Delete</span>
</a>
</li>
<li>
<a href="" class="d-b td-n pY-5 pX-10 bgcH-grey-100 c-grey-700">
<i class="ti-alert mR-10"></i>
<span>Mark as Spam</span>
</a>
</li>
<li>
<a href="" class="d-b td-n pY-5 pX-10 bgcH-grey-100 c-grey-700">
<i class="ti-star mR-10"></i>
<span>Star</span>
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="peer">
<div class="btn-group" role="group">
<button type="button" class="fsz-xs btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-angle-left"></i>
</button>
<button type="button" class="fsz-xs btn bgc-white bdrs-2 mR-3 cur-p">
<i class="ti-angle-right"></i>
</button>
</div>
</div>
</div>
<div class="email-content-wrapper">
<!-- Header -->
<div class="peers ai-c jc-sb pX-40 pY-30">
<div class="peers peer-greed">
<div class="peer mR-20">
<img id="ticketAuthorImg" class="bdrs-50p w-3r h-3r" alt="" src="" style="display: none;">
</div>
<div class="peer">
<small id="ticketTimestamp"></small>
<h5 id="ticketAuthor" class="c-grey-900 mB-5"></h5>
<div id="ticketBadges" style="display: none;">
<div class="badge bgc-pink-300">Urgent</div>
<div class="badge bgc-deep-purple-400">IT</div>
<div class="badge bgc-green-300">Open</div>
</div>
</div>
</div>
<div class="peer">
<div class="btn-group" role="group">
<button id="btnGroupDrop2" class="btn btn-danger c-white bdrs-50p p-15 lh-0" style="display: none;" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<i class="ti-menu"></i>
</button>
<ul class="dropdown-menu fsz-sm" aria-labelledby="btnGroupDrop2">
test
</ul>
</div>
</div>
</div>
<!-- Content -->
<div class="bdT pX-40 pY-30">
<h4 id="ticketTitle"></h4>
<p id="ticketDesc"></p>
<!-- <h4>Title of this email goes here</h4>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam
</p> -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<div id="ticketModal" class="modal fade" aria-hidden="true">
<div class="modal-dialog modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title fs-5">Modal</h3>
<button type="button" class="btn-close" data-bs-toggle="modal"></button>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
{% endblock content %}
<!-- Specific Page JS goes HERE -->
{% block javascripts %}
<script>
var displayedTicketID = -1;
$(document).ready(function() {
$(".email-list-item").on("click", function() {
displayTicket(this);
});
});
function displayTicket(ticketElement) {
ticket = $(ticketElement);
ticketID = ticket.data("ticket-id");
$(".back-to-mailbox").off("click").on("click", function(event) {
event.preventDefault();
$('.email-content').toggleClass('open');
displayTicket(ticketElement);
});
if (displayedTicketID === ticketID) {
$("#ticketTitle").text("")
$("#ticketDesc").text("");
$("#ticketAuthor").text("");
$("#ticketAuthorImg").hide();
$("#ticketAuthorImg").prop("src", "");
$("#ticketTimestamp").text("");
$("#btnGroupDrop2").hide();
$("#ticketBadges").hide();
displayedTicketID = -1;
return;
}
displayedTicketID = ticketID;
title = ticket.find(".ticket-title").text();
desc = ticket.find(".ticket-desc").text();
author = ticket.find(".ticket-author").text();
authorIcon = ticket.data("author-icon");
timestamp = ticket.find(".ticket-timestamp").text();
$("#ticketTitle").text(title)
$("#ticketDesc").text(desc);
$("#ticketAuthor").text(author);
$("#ticketAuthorImg").show();
$("#ticketAuthorImg").prop("src", authorIcon);
$("#ticketTimestamp").text(timestamp);
$("#btnGroupDrop2").show();
$("#ticketBadges").show();
}
</script>
{% endblock javascripts %}

View File

@ -1,5 +1,5 @@
<footer class="bdT ta-c p-30 lh-0 fsz-sm c-grey-600"> <footer class="bdT ta-c p-30 lh-0 fsz-sm c-grey-600">
<span> <span>
&copy; Designed by Colorlib - Supported By <a href="https://appseed.us/" target="_blank">AppSeed</a>. &copy; Designed by Colorlib.
</span> </span>
</footer> </footer>

View File

@ -181,10 +181,10 @@
<li class="dropdown"> <li class="dropdown">
<a href="" class="dropdown-toggle no-after peers fxw-nw ai-c lh-1" data-bs-toggle="dropdown"> <a href="" class="dropdown-toggle no-after peers fxw-nw ai-c lh-1" data-bs-toggle="dropdown">
<div class="peer mR-10"> <div class="peer mR-10">
<img class="w-2r bdrs-50p" src="https://randomuser.me/api/portraits/men/10.jpg" alt=""> <img class="w-2r bdrs-50p" src="{{ request.user.icon.url }}" alt="">
</div> </div>
<div class="peer"> <div class="peer">
<span class="fsz-sm c-grey-900">John Doe</span> <span class="fsz-sm c-grey-900">{{ request.user }}</span>
</div> </div>
</a> </a>
<ul class="dropdown-menu fsz-sm"> <ul class="dropdown-menu fsz-sm">
@ -195,7 +195,7 @@
</a> </a>
</li> </li>
<li> <li>
<a href="" class="d-b td-n pY-5 bgcH-grey-100 c-grey-700"> <a href="{% url 'profile' %}" class="d-b td-n pY-5 bgcH-grey-100 c-grey-700">
<i class="ti-user mR-10"></i> <i class="ti-user mR-10"></i>
<span>Profile</span> <span>Profile</span>
</a> </a>

View File

@ -31,11 +31,31 @@
<!-- ### $Sidebar Menu ### --> <!-- ### $Sidebar Menu ### -->
<ul class="sidebar-menu scrollable pos-r"> <ul class="sidebar-menu scrollable pos-r">
<li class="nav-item mT-30 actived"> <li class="nav-item mT-30 actived">
<a class="sidebar-link" href="{% url 'dashboard' %}">
<span class="icon-holder">
<i class="c-blue-500 ti-home"></i>
</span>
<span class="title">New Dashboard</span>
<!-- ti-comment-alt -->
</a>
</li>
<li class="nav-item">
<a class="sidebar-link" href="{% url 'tickets' %}">
<span class="icon-holder">
<i class="c-green-500 ti-ticket"></i>
</span>
<span class="title">Tickets</span>
</a>
</li>
<li class="nav-item">
<hr class="bgc-grey-500">
</li>
<li class="nav-item">
<a class="sidebar-link" href="/index.html"> <a class="sidebar-link" href="/index.html">
<span class="icon-holder"> <span class="icon-holder">
<i class="c-blue-500 ti-home"></i> <i class="c-blue-500 ti-home"></i>
</span> </span>
<span class="title">Dashboard</span> <span class="title">Template Dashboard</span>
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">

View File

@ -4,7 +4,7 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title> <title>
Django Adminator - {% block title %}{% endblock %} | AppSeed Django Adminator - {% block title %}{% endblock %}
</title> </title>
<link <link
@ -72,7 +72,38 @@
{% include 'includes/scripts.html' %} {% include 'includes/scripts.html' %}
<!-- Specific Page JS goes HERE --> <!-- Specific Page JS goes HERE -->
{% block javascripts %}{% endblock javascripts %} {% block javascripts %}{% endblock javascripts %}
<script>
// $(document).ready(function() {
// (function(){
// var nativeAddClass = jQuery.fn.addClass;
// var nativeRemoveClass = jQuery.fn.removeClass;
// jQuery.fn.addClass = function(){
// var result = nativeAddClass.apply( this, arguments );
// jQuery(this).trigger('cssClassChanged');
// return result;
// }
// jQuery.fn.removeClass = function(){
// var result = nativeRemoveClass.apply( this, arguments );
// jQuery(this).trigger('cssClassChanged');
// return result;
// }
// })();
// $(function() {
// $("body").bind("cssClassChanged", function() {
// alert("trigger");
// localStorage.setItem("collapsed", $(this).hasClass("is-collapsed"));
// });
// });
// if (localStorage.getItem("collapsed") === "true") {
// $("body").addClass("is-collapsed");
// }
// });
</script>
</body> </body>
</html> </html>

View File

@ -1,7 +1,4 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""
import os, environ import os, environ
@ -27,7 +24,7 @@ DEBUG = env('DEBUG')
ASSETS_ROOT = os.getenv('ASSETS_ROOT', '/static/assets') ASSETS_ROOT = os.getenv('ASSETS_ROOT', '/static/assets')
# load production server from .env # load production server from .env
ALLOWED_HOSTS = ['localhost', 'localhost:85', '127.0.0.1', 'code.corbz.dev', env('SERVER', default='127.0.0.1') ] ALLOWED_HOSTS = ['localhost', 'localhost:85', '127.0.0.1', '192.168.0.19', env('SERVER', default='127.0.0.1') ]
CSRF_TRUSTED_ORIGINS = ['http://localhost:85', 'http://127.0.0.1', 'https://' + env('SERVER', default='127.0.0.1') ] CSRF_TRUSTED_ORIGINS = ['http://localhost:85', 'http://127.0.0.1', 'https://' + env('SERVER', default='127.0.0.1') ]
# Application definition # Application definition
@ -39,7 +36,8 @@ INSTALLED_APPS = [
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'apps.home' # Enable the inner home (home) 'apps.home', # Enable the inner home (home)
'apps.authentication'
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -120,9 +118,9 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/ # https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us' LANGUAGE_CODE = 'en-gb'
TIME_ZONE = 'UTC' TIME_ZONE = 'Europe/London'
USE_I18N = True USE_I18N = True
@ -143,6 +141,16 @@ STATICFILES_DIRS = (
os.path.join(CORE_DIR, 'apps/static'), os.path.join(CORE_DIR, 'apps/static'),
) )
# Media Files
MEDIA_ROOT = os.path.join(CORE_DIR, 'media')
MEDIA_URL = '/media/'
############################################################# #############################################################
############################################################# #############################################################
# If route isnt found, try again with appended slash
APPEND_SLASH = True
AUTH_USER_MODEL = "authentication.User"
LOGIN_URL = "/login/"

View File

@ -1,17 +1,17 @@
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
"""
Copyright (c) 2019 - present AppSeed.us
"""
from django.contrib import admin from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from django.urls import path, include # add this from django.urls import path, include # add this
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), # Django admin route path('admin/', admin.site.urls), # Django admin route
path("", include("apps.authentication.urls")), # Auth routes - login / register
# ADD NEW Routes HERE # ADD NEW Routes HERE
*static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT),
path("", include("apps.authentication.urls")), # Auth routes - login / register
# Leave `Home.Urls` as last the last line # Leave `Home.Urls` as last the last line
path("", include("apps.home.urls")) path("", include("apps.home.urls"))
] ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 664 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

BIN
media/users/default.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,11 +1,12 @@
Django==3.2.16
asgiref==3.4.1 asgiref==3.4.1
autopep8==1.6.0 autopep8==1.6.0
dj-database-url==0.5.0 dj-database-url==0.5.0
Django==3.2.16
django-environ==0.8.1
gunicorn==20.1.0 gunicorn==20.1.0
pillow==10.2.0
pycodestyle==2.8.0 pycodestyle==2.8.0
pytz==2021.3 pytz==2021.3
sqlparse==0.4.2 sqlparse==0.4.2
toml==0.10.2 toml==0.10.2
whitenoise==5.3.0 whitenoise==5.3.0
django-environ==0.8.1